Passed
Push — dev ( 837c0e...fdbfdd )
by Nico
26:17
created

ShipWrapper::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 10
dl 0
loc 14
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Ship\Lib;
6
7
use Doctrine\Common\Collections\ArrayCollection;
8
use Doctrine\Common\Collections\Collection;
9
use Override;
0 ignored issues
show
Bug introduced by
The type Override was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use RuntimeException;
11
use Stu\Component\Ship\Repair\RepairUtilInterface;
12
use Stu\Component\Ship\ShipAlertStateEnum;
13
use Stu\Component\Ship\ShipStateEnum;
14
use Stu\Component\Ship\System\Data\AbstractSystemData;
15
use Stu\Component\Ship\System\Data\AstroLaboratorySystemData;
16
use Stu\Component\Ship\System\Data\AggregationSystemSystemData;
17
use Stu\Component\Ship\System\Data\BussardCollectorSystemData;
18
use Stu\Component\Ship\System\Data\EpsSystemData;
19
use Stu\Component\Ship\System\Data\FusionCoreSystemData;
20
use Stu\Component\Ship\System\Data\HullSystemData;
21
use Stu\Component\Ship\System\Data\ProjectileLauncherSystemData;
22
use Stu\Component\Ship\System\Data\ShieldSystemData;
23
use Stu\Component\Ship\System\Data\SingularityCoreSystemData;
24
use Stu\Component\Ship\System\Data\TrackerSystemData;
25
use Stu\Component\Ship\System\Data\WarpCoreSystemData;
26
use Stu\Component\Ship\System\Data\WarpDriveSystemData;
27
use Stu\Component\Ship\System\Data\WebEmitterSystemData;
28
use Stu\Component\Ship\System\Exception\SystemNotFoundException;
29
use Stu\Component\Ship\System\ShipSystemManagerInterface;
30
use Stu\Component\Ship\System\ShipSystemTypeEnum;
31
use Stu\Component\Ship\System\SystemDataDeserializerInterface;
32
use Stu\Module\Colony\Lib\ColonyLibFactoryInterface;
33
use Stu\Module\Commodity\CommodityTypeEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Module\Commodity\CommodityTypeEnum was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34
use Stu\Module\Control\GameControllerInterface;
35
use Stu\Module\Ship\Lib\Interaction\ShipTakeoverManagerInterface;
36
use Stu\Module\Ship\Lib\Ui\StateIconAndTitle;
37
use Stu\Orm\Entity\ShipInterface;
38
use Stu\Orm\Entity\ShipSystemInterface;
39
use Stu\Orm\Entity\ShipTakeoverInterface;
40
use Stu\Orm\Repository\TorpedoTypeRepositoryInterface;
41
42
//TODO increase coverage
43
final class ShipWrapper implements ShipWrapperInterface
44
{
45
    /**
46
     * @var Collection<int, AbstractSystemData>
47
     */
48
    private Collection $shipSystemDataCache;
49
50
    private ?ReactorWrapperInterface $reactorWrapper = null;
51
52
    private ?int $epsUsage = null;
53
54 8
    public function __construct(
55
        private ShipInterface $ship,
56
        private ShipSystemManagerInterface $shipSystemManager,
57
        private SystemDataDeserializerInterface $systemDataDeserializer,
58
        private ColonyLibFactoryInterface $colonyLibFactory,
59
        private TorpedoTypeRepositoryInterface $torpedoTypeRepository,
60
        private GameControllerInterface $game,
61
        private ShipWrapperFactoryInterface $shipWrapperFactory,
62
        private ShipStateChangerInterface $shipStateChanger,
63
        private RepairUtilInterface $repairUtil,
64
        private StateIconAndTitle $stateIconAndTitle,
65
    ) {
66
67 8
        $this->shipSystemDataCache = new ArrayCollection();
68
    }
69
70 3
    #[Override]
71
    public function get(): ShipInterface
72
    {
73 3
        return $this->ship;
74
    }
75
76
    #[Override]
77
    public function getShipWrapperFactory(): ShipWrapperFactoryInterface
78
    {
79
        return $this->shipWrapperFactory;
80
    }
81
82
    #[Override]
83
    public function getShipSystemManager(): ShipSystemManagerInterface
84
    {
85
        return $this->shipSystemManager;
86
    }
87
88
    #[Override]
89
    public function getFleetWrapper(): ?FleetWrapperInterface
90
    {
91
        if ($this->ship->getFleet() === null) {
92
            return null;
93
        }
94
95
        return $this->shipWrapperFactory->wrapFleet($this->ship->getFleet());
96
    }
97
98
    #[Override]
99
    public function getEpsUsage(): int
100
    {
101
        if ($this->epsUsage === null) {
102
            $this->epsUsage = $this->reloadEpsUsage();
103
        }
104
        return $this->epsUsage;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->epsUsage could return the type null which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
105
    }
106
107
    #[Override]
108
    public function lowerEpsUsage(int $value): void
109
    {
110
        $this->epsUsage -= $value;
111
    }
112
113
    private function reloadEpsUsage(): int
114
    {
115
        $result = 0;
116
117
        foreach ($this->shipSystemManager->getActiveSystems($this->ship) as $shipSystem) {
118
            $result += $this->shipSystemManager->getEnergyConsumption($shipSystem->getSystemType());
119
        }
120
121
        if ($this->ship->getAlertState() == ShipAlertStateEnum::ALERT_YELLOW) {
122
            $result += ShipStateChangerInterface::ALERT_YELLOW_EPS_USAGE;
123
        }
124
        if ($this->ship->getAlertState() == ShipAlertStateEnum::ALERT_RED) {
125
            $result += ShipStateChangerInterface::ALERT_RED_EPS_USAGE;
126
        }
127
128
        return $result;
129
    }
130
131
    public function getReactorUsage(): int
132
    {
133
        $reactor = $this->reactorWrapper;
134
        if ($reactor === null) {
135
            throw new RuntimeException('this should not happen');
136
        }
137
138
        return $this->getEpsUsage() + $reactor->getUsage();
139
    }
140
141
    #[Override]
142
    public function getReactorWrapper(): ?ReactorWrapperInterface
143
    {
144
        if ($this->reactorWrapper === null) {
145
            $ship = $this->ship;
146
            $reactorSystemData = null;
147
148
149
            if ($ship->hasShipSystem(ShipSystemTypeEnum::SYSTEM_WARPCORE)) {
150
                $reactorSystemData = $this->getSpecificShipSystem(
151
                    ShipSystemTypeEnum::SYSTEM_WARPCORE,
152
                    WarpCoreSystemData::class
153
                );
154
            }
155
            if ($ship->hasShipSystem(ShipSystemTypeEnum::SYSTEM_SINGULARITY_REACTOR)) {
156
                $reactorSystemData = $this->getSpecificShipSystem(
157
                    ShipSystemTypeEnum::SYSTEM_SINGULARITY_REACTOR,
158
                    SingularityCoreSystemData::class
159
                );
160
            }
161
            if ($ship->hasShipSystem(ShipSystemTypeEnum::SYSTEM_FUSION_REACTOR)) {
162
                $reactorSystemData = $this->getSpecificShipSystem(
163
                    ShipSystemTypeEnum::SYSTEM_FUSION_REACTOR,
164
                    FusionCoreSystemData::class
165
                );
166
            }
167
168
            if ($reactorSystemData === null) {
169
                return null;
170
            }
171
172
            $this->reactorWrapper = new ReactorWrapper($this, $reactorSystemData);
173
        }
174
175
        return $this->reactorWrapper;
176
    }
177
178
    #[Override]
179
    public function setAlertState(ShipAlertStateEnum $alertState): ?string
180
    {
181
        $msg = $this->shipStateChanger->changeAlertState($this, $alertState);
182
        $this->epsUsage = $this->reloadEpsUsage();
183
184
        return $msg;
185
    }
186
187
    /**
188
     * highest damage first, then prio
189
     *
190
     * @return ShipSystemInterface[]
191
     */
192
    #[Override]
193
    public function getDamagedSystems(): array
194
    {
195
        $damagedSystems = [];
196
        $prioArray = [];
197
        foreach ($this->ship->getSystems() as $system) {
198
            if ($system->getStatus() < 100) {
199
                $damagedSystems[] = $system;
200
                $prioArray[$system->getSystemType()->value] = $this->shipSystemManager->lookupSystem($system->getSystemType())->getPriority();
201
            }
202
        }
203
204
        // sort by damage and priority
205
        usort(
206
            $damagedSystems,
207
            function (ShipSystemInterface $a, ShipSystemInterface $b) use ($prioArray): int {
208
                if ($a->getStatus() === $b->getStatus()) {
209
                    return $prioArray[$b->getSystemType()->value] <=> $prioArray[$a->getSystemType()->value];
210
                }
211
                return ($a->getStatus() < $b->getStatus()) ? -1 : 1;
212
            }
213
        );
214
215
        return $damagedSystems;
216
    }
217
218
    #[Override]
219
    public function isOwnedByCurrentUser(): bool
220
    {
221
        return $this->game->getUser() === $this->ship->getUser();
222
    }
223
224
    #[Override]
225
    public function canLandOnCurrentColony(): bool
226
    {
227
        if ($this->ship->getRump()->getCommodity() === null) {
228
            return false;
229
        }
230
        if ($this->ship->isShuttle()) {
231
            return false;
232
        }
233
234
        $currentColony = $this->ship->getStarsystemMap() !== null ? $this->ship->getStarsystemMap()->getColony() : null;
235
236
        if ($currentColony === null) {
237
            return false;
238
        }
239
        if ($currentColony->getUser() !== $this->ship->getUser()) {
240
            return false;
241
        }
242
243
        return $this->colonyLibFactory
244
            ->createColonySurface($currentColony)
245
            ->hasAirfield();
246
    }
247
248
    #[Override]
249
    public function canBeRepaired(): bool
250
    {
251
        if ($this->ship->getAlertState() !== ShipAlertStateEnum::ALERT_GREEN) {
252
            return false;
253
        }
254
255
        if ($this->ship->getShieldState()) {
256
            return false;
257
        }
258
259
        if ($this->ship->getCloakState()) {
260
            return false;
261
        }
262
263
        if ($this->getDamagedSystems() !== []) {
264
            return true;
265
        }
266
267
        return $this->ship->getHull() < $this->ship->getMaxHull();
268
    }
269
270
    #[Override]
271
    public function canBeRetrofitted(): bool
272
    {
273
        if ($this->ship->getAlertState() !== ShipAlertStateEnum::ALERT_GREEN) {
274
            return false;
275
        }
276
277
        if ($this->ship->getShieldState()) {
278
            return false;
279
        }
280
281
        if ($this->ship->getCloakState()) {
282
            return false;
283
        }
284
285
        if ($this->ship->getBuildplan()->getUser() != $this->game->getUser()) {
286
            return false;
287
        }
288
289
        return true;
290
    }
291
292 4
    #[Override]
293
    public function canFire(): bool
294
    {
295 4
        $ship = $this->ship;
296 4
        if (!$ship->getNbs()) {
297 1
            return false;
298
        }
299 3
        if (!$ship->hasActiveWeapon()) {
300 1
            return false;
301
        }
302
303 2
        $epsSystem = $this->getEpsSystemData();
304 2
        return $epsSystem !== null && $epsSystem->getEps() !== 0;
305
    }
306
307
    #[Override]
308
    public function getRepairDuration(): int
309
    {
310
        return $this->repairUtil->getRepairDuration($this);
311
    }
312
313
    #[Override]
314
    public function getRepairDurationPreview(): int
315
    {
316
        return $this->repairUtil->getRepairDurationPreview($this);
317
    }
318
319
    #[Override]
320
    public function getRepairCosts(): array
321
    {
322
        $neededParts = $this->repairUtil->determineSpareParts($this, false);
323
324
        $neededSpareParts = $neededParts[CommodityTypeEnum::COMMODITY_SPARE_PART];
325
        $neededSystemComponents = $neededParts[CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT];
326
327
        return [
328
            new ShipRepairCost($neededSpareParts, CommodityTypeEnum::COMMODITY_SPARE_PART, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SPARE_PART)),
329
            new ShipRepairCost($neededSystemComponents, CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT))
330
        ];
331
    }
332
333
    #[Override]
334
    public function getPossibleTorpedoTypes(): array
335
    {
336
        if ($this->ship->hasShipSystem(ShipSystemTypeEnum::SYSTEM_TORPEDO_STORAGE)) {
337
            return $this->torpedoTypeRepository->getAll();
338
        }
339
340
        return $this->torpedoTypeRepository->getByLevel($this->ship->getRump()->getTorpedoLevel());
341
    }
342
343
    #[Override]
344
    public function getTractoredShipWrapper(): ?ShipWrapperInterface
345
    {
346
        $tractoredShip = $this->ship->getTractoredShip();
347
        if ($tractoredShip === null) {
348
            return null;
349
        }
350
351
        return $this->shipWrapperFactory->wrapShip($tractoredShip);
352
    }
353
354
    #[Override]
355
    public function getTractoringShipWrapper(): ?ShipWrapperInterface
356
    {
357
        $tractoringShip = $this->ship->getTractoringShip();
358
        if ($tractoringShip === null) {
359
            return null;
360
        }
361
362
        return $this->shipWrapperFactory->wrapShip($tractoringShip);
363
    }
364
365
    #[Override]
366
    public function getDockedToShipWrapper(): ?ShipWrapperInterface
367
    {
368
        $dockedTo = $this->ship->getDockedTo();
369
        if ($dockedTo === null) {
370
            return null;
371
        }
372
373
        return $this->shipWrapperFactory->wrapShip($dockedTo);
374
    }
375
376
    #[Override]
377
    public function getStateIconAndTitle(): ?array
378
    {
379
        return $this->stateIconAndTitle->getStateIconAndTitle($this);
380
    }
381
382
    #[Override]
383
    public function getTakeoverTicksLeft(?ShipTakeoverInterface $takeover = null): int
384
    {
385
        $takeover ??= $this->ship->getTakeoverActive();
386
        if ($takeover === null) {
387
            throw new RuntimeException('should not call when active takeover is null');
388
        }
389
390
        $currentTurn = $this->game->getCurrentRound()->getTurn();
391
392
        return $takeover->getStartTurn() + ShipTakeoverManagerInterface::TURNS_TO_TAKEOVER - $currentTurn;
393
    }
394
395
    #[Override]
396
    public function canBeScrapped(): bool
397
    {
398
        $ship = $this->ship;
399
400
        return $ship->isBase() && $ship->getState() !== ShipStateEnum::SHIP_STATE_UNDER_SCRAPPING;
401
    }
402
403
    #[Override]
404
    public function getCrewStyle(): string
405
    {
406
        $ship = $this->ship;
407
        $excessCrew = $ship->getExcessCrewCount();
408
409
        if ($excessCrew === 0) {
410
            return "";
411
        }
412
413
        return $excessCrew > 0 ? "color: green;" : "color: red;";
414
    }
415
416 1
    #[Override]
417
    public function getHullSystemData(): HullSystemData
418
    {
419 1
        $hullSystemData = $this->getSpecificShipSystem(
420 1
            ShipSystemTypeEnum::SYSTEM_HULL,
421 1
            HullSystemData::class
422 1
        );
423
424 1
        if ($hullSystemData === null) {
425
            throw new SystemNotFoundException('no hull installed?');
426
        }
427
428 1
        return $hullSystemData;
429
    }
430
431
    #[Override]
432
    public function getShieldSystemData(): ?ShieldSystemData
433
    {
434
        return $this->getSpecificShipSystem(
435
            ShipSystemTypeEnum::SYSTEM_SHIELDS,
436
            ShieldSystemData::class
437
        );
438
    }
439
440 2
    #[Override]
441
    public function getEpsSystemData(): ?EpsSystemData
442
    {
443 2
        return $this->getSpecificShipSystem(
444 2
            ShipSystemTypeEnum::SYSTEM_EPS,
445 2
            EpsSystemData::class
446 2
        );
447
    }
448
449
    #[Override]
450
    public function getWarpDriveSystemData(): ?WarpDriveSystemData
451
    {
452
        return $this->getSpecificShipSystem(
453
            ShipSystemTypeEnum::SYSTEM_WARPDRIVE,
454
            WarpDriveSystemData::class
455
        );
456
    }
457
458
    #[Override]
459
    public function getTrackerSystemData(): ?TrackerSystemData
460
    {
461
        return $this->getSpecificShipSystem(
462
            ShipSystemTypeEnum::SYSTEM_TRACKER,
463
            TrackerSystemData::class
464
        );
465
    }
466
467
    #[Override]
468
    public function getAggregationSystemSystemData(): ?AggregationSystemSystemData
469
    {
470
        return $this->getSpecificShipSystem(
471
            ShipSystemTypeEnum::SYSTEM_AGGREGATION_SYSTEM,
472
            AggregationSystemSystemData::class
473
        );
474
    }
475
476
    #[Override]
477
    public function getBussardCollectorSystemData(): ?BussardCollectorSystemData
478
    {
479
        return $this->getSpecificShipSystem(
480
            ShipSystemTypeEnum::SYSTEM_BUSSARD_COLLECTOR,
481
            BussardCollectorSystemData::class
482
        );
483
    }
484
485
    #[Override]
486
    public function getWebEmitterSystemData(): ?WebEmitterSystemData
487
    {
488
        return $this->getSpecificShipSystem(
489
            ShipSystemTypeEnum::SYSTEM_THOLIAN_WEB,
490
            WebEmitterSystemData::class
491
        );
492
    }
493
494
    #[Override]
495
    public function getAstroLaboratorySystemData(): ?AstroLaboratorySystemData
496
    {
497
        return $this->getSpecificShipSystem(
498
            ShipSystemTypeEnum::SYSTEM_ASTRO_LABORATORY,
499
            AstroLaboratorySystemData::class
500
        );
501
    }
502
503
    #[Override]
504
    public function getProjectileLauncherSystemData(): ?ProjectileLauncherSystemData
505
    {
506
        return $this->getSpecificShipSystem(
507
            ShipSystemTypeEnum::SYSTEM_TORPEDO,
508
            ProjectileLauncherSystemData::class
509
        );
510
    }
511
512
    /**
513
     * @template T
514
     * @param class-string<T> $className
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
515
     *
516
     * @return T|null
517
     */
518 3
    private function getSpecificShipSystem(ShipSystemTypeEnum $systemType, string $className)
519
    {
520 3
        return $this->systemDataDeserializer->getSpecificShipSystem(
521 3
            $this->ship,
522 3
            $systemType,
523 3
            $className,
524 3
            $this->shipSystemDataCache,
525 3
            $this->shipWrapperFactory
526 3
        );
527
    }
528
}