Passed
Pull Request — master (#1948)
by Nico
21:26 queued 10:43
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 20
    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 20
        $this->shipSystemDataCache = new ArrayCollection();
68
    }
69
70 15
    #[Override]
71
    public function get(): ShipInterface
72
    {
73 15
        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 2
    #[Override]
99
    public function getEpsUsage(): int
100
    {
101 2
        if ($this->epsUsage === null) {
102 2
            $this->epsUsage = $this->reloadEpsUsage();
103
        }
104 2
        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 2
    private function reloadEpsUsage(): int
114
    {
115 2
        $result = 0;
116
117 2
        foreach ($this->shipSystemManager->getActiveSystems($this->ship) as $shipSystem) {
118 2
            $result += $this->shipSystemManager->getEnergyConsumption($shipSystem->getSystemType());
119
        }
120
121 2
        if ($this->ship->getAlertState() == ShipAlertStateEnum::ALERT_YELLOW) {
122
            $result += ShipStateChangerInterface::ALERT_YELLOW_EPS_USAGE;
123
        }
124 2
        if ($this->ship->getAlertState() == ShipAlertStateEnum::ALERT_RED) {
125
            $result += ShipStateChangerInterface::ALERT_RED_EPS_USAGE;
126
        }
127
128 2
        return $result;
129
    }
130
131 1
    public function getReactorUsage(): int
132
    {
133 1
        $reactor = $this->reactorWrapper;
134 1
        if ($reactor === null) {
135
            throw new RuntimeException('this should not happen');
136
        }
137
138 1
        return $this->getEpsUsage() + $reactor->getUsage();
139
    }
140
141 3
    #[Override]
142
    public function getReactorWrapper(): ?ReactorWrapperInterface
143
    {
144 3
        if ($this->reactorWrapper === null) {
145 3
            $ship = $this->ship;
146 3
            $reactorSystemData = null;
147
148
149 3
            if ($ship->hasShipSystem(ShipSystemTypeEnum::SYSTEM_WARPCORE)) {
150 3
                $reactorSystemData = $this->getSpecificShipSystem(
151 3
                    ShipSystemTypeEnum::SYSTEM_WARPCORE,
152 3
                    WarpCoreSystemData::class
153 3
                );
154
            }
155 3
            if ($ship->hasShipSystem(ShipSystemTypeEnum::SYSTEM_SINGULARITY_REACTOR)) {
156
                $reactorSystemData = $this->getSpecificShipSystem(
157
                    ShipSystemTypeEnum::SYSTEM_SINGULARITY_REACTOR,
158
                    SingularityCoreSystemData::class
159
                );
160
            }
161 3
            if ($ship->hasShipSystem(ShipSystemTypeEnum::SYSTEM_FUSION_REACTOR)) {
162
                $reactorSystemData = $this->getSpecificShipSystem(
163
                    ShipSystemTypeEnum::SYSTEM_FUSION_REACTOR,
164
                    FusionCoreSystemData::class
165
                );
166
            }
167
168 3
            if ($reactorSystemData === null) {
169
                return null;
170
            }
171
172 3
            $this->reactorWrapper = new ReactorWrapper($this, $reactorSystemData);
173
        }
174
175 3
        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 2
    #[Override]
193
    public function getDamagedSystems(): array
194
    {
195 2
        $damagedSystems = [];
196 2
        $prioArray = [];
197 2
        foreach ($this->ship->getSystems() as $system) {
198 2
            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 2
        usort(
206 2
            $damagedSystems,
207 2
            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 2
            }
213 2
        );
214
215 2
        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 1
    #[Override]
249
    public function canBeRepaired(): bool
250
    {
251 1
        if ($this->ship->getAlertState() !== ShipAlertStateEnum::ALERT_GREEN) {
252
            return false;
253
        }
254
255 1
        if ($this->ship->getShieldState()) {
256
            return false;
257
        }
258
259 1
        if ($this->ship->getCloakState()) {
260
            return false;
261
        }
262
263 1
        if ($this->getDamagedSystems() !== []) {
264
            return true;
265
        }
266
267 1
        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->getFleet()) {
278
            return false;
279
        }
280
281
        if ($this->ship->getShieldState()) {
282
            return false;
283
        }
284
285
        if ($this->ship->getCloakState()) {
286
            return false;
287
        }
288
289
        if ($this->ship->getUser() != $this->game->getUser()) {
290
            return false;
291
        }
292
293
        if (
294
            $this->ship->getBuildplan() != null
295
            && $this->ship->getBuildplan()->getUser() != $this->game->getUser()
296
        ) {
297
            return false;
298
        }
299
300
        return true;
301
    }
302
303 4
    #[Override]
304
    public function canFire(): bool
305
    {
306 4
        $ship = $this->ship;
307 4
        if (!$ship->getNbs()) {
308 1
            return false;
309
        }
310 3
        if (!$ship->hasActiveWeapon()) {
311 1
            return false;
312
        }
313
314 2
        $epsSystem = $this->getEpsSystemData();
315 2
        return $epsSystem !== null && $epsSystem->getEps() !== 0;
316
    }
317
318
    #[Override]
319
    public function getRepairDuration(): int
320
    {
321
        return $this->repairUtil->getRepairDuration($this);
322
    }
323
324
    #[Override]
325
    public function getRepairDurationPreview(): int
326
    {
327
        return $this->repairUtil->getRepairDurationPreview($this);
328
    }
329
330
    #[Override]
331
    public function getRepairCosts(): array
332
    {
333
        $neededParts = $this->repairUtil->determineSpareParts($this, false);
334
335
        $neededSpareParts = $neededParts[CommodityTypeEnum::COMMODITY_SPARE_PART];
336
        $neededSystemComponents = $neededParts[CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT];
337
338
        return [
339
            new ShipRepairCost($neededSpareParts, CommodityTypeEnum::COMMODITY_SPARE_PART, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SPARE_PART)),
340
            new ShipRepairCost($neededSystemComponents, CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT))
341
        ];
342
    }
343
344
    #[Override]
345
    public function getPossibleTorpedoTypes(): array
346
    {
347
        if ($this->ship->hasShipSystem(ShipSystemTypeEnum::SYSTEM_TORPEDO_STORAGE)) {
348
            return $this->torpedoTypeRepository->getAll();
349
        }
350
351
        return $this->torpedoTypeRepository->getByLevel($this->ship->getRump()->getTorpedoLevel());
352
    }
353
354
    #[Override]
355
    public function getTractoredShipWrapper(): ?ShipWrapperInterface
356
    {
357
        $tractoredShip = $this->ship->getTractoredShip();
358
        if ($tractoredShip === null) {
359
            return null;
360
        }
361
362
        return $this->shipWrapperFactory->wrapShip($tractoredShip);
363
    }
364
365
    #[Override]
366
    public function getTractoringShipWrapper(): ?ShipWrapperInterface
367
    {
368
        $tractoringShip = $this->ship->getTractoringShip();
369
        if ($tractoringShip === null) {
370
            return null;
371
        }
372
373
        return $this->shipWrapperFactory->wrapShip($tractoringShip);
374
    }
375
376
    #[Override]
377
    public function getDockedToShipWrapper(): ?ShipWrapperInterface
378
    {
379
        $dockedTo = $this->ship->getDockedTo();
380
        if ($dockedTo === null) {
381
            return null;
382
        }
383
384
        return $this->shipWrapperFactory->wrapShip($dockedTo);
385
    }
386
387 1
    #[Override]
388
    public function getStateIconAndTitle(): ?array
389
    {
390 1
        return $this->stateIconAndTitle->getStateIconAndTitle($this);
391
    }
392
393
    #[Override]
394
    public function getTakeoverTicksLeft(?ShipTakeoverInterface $takeover = null): int
395
    {
396
        $takeover ??= $this->ship->getTakeoverActive();
397
        if ($takeover === null) {
398
            throw new RuntimeException('should not call when active takeover is null');
399
        }
400
401
        $currentTurn = $this->game->getCurrentRound()->getTurn();
402
403
        return $takeover->getStartTurn() + ShipTakeoverManagerInterface::TURNS_TO_TAKEOVER - $currentTurn;
404
    }
405
406 1
    #[Override]
407
    public function canBeScrapped(): bool
408
    {
409 1
        $ship = $this->ship;
410
411 1
        return $ship->isBase() && $ship->getState() !== ShipStateEnum::SHIP_STATE_UNDER_SCRAPPING;
412
    }
413
414 2
    #[Override]
415
    public function getCrewStyle(): string
416
    {
417 2
        $ship = $this->ship;
418 2
        $excessCrew = $ship->getExcessCrewCount();
419
420 2
        if ($excessCrew === 0) {
421 2
            return "";
422
        }
423
424
        return $excessCrew > 0 ? "color: green;" : "color: red;";
425
    }
426
427 3
    #[Override]
428
    public function getHullSystemData(): HullSystemData
429
    {
430 3
        $hullSystemData = $this->getSpecificShipSystem(
431 3
            ShipSystemTypeEnum::SYSTEM_HULL,
432 3
            HullSystemData::class
433 3
        );
434
435 3
        if ($hullSystemData === null) {
436
            throw new SystemNotFoundException('no hull installed?');
437
        }
438
439 3
        return $hullSystemData;
440
    }
441
442 2
    #[Override]
443
    public function getShieldSystemData(): ?ShieldSystemData
444
    {
445 2
        return $this->getSpecificShipSystem(
446 2
            ShipSystemTypeEnum::SYSTEM_SHIELDS,
447 2
            ShieldSystemData::class
448 2
        );
449
    }
450
451 6
    #[Override]
452
    public function getEpsSystemData(): ?EpsSystemData
453
    {
454 6
        return $this->getSpecificShipSystem(
455 6
            ShipSystemTypeEnum::SYSTEM_EPS,
456 6
            EpsSystemData::class
457 6
        );
458
    }
459
460 2
    #[Override]
461
    public function getWarpDriveSystemData(): ?WarpDriveSystemData
462
    {
463 2
        return $this->getSpecificShipSystem(
464 2
            ShipSystemTypeEnum::SYSTEM_WARPDRIVE,
465 2
            WarpDriveSystemData::class
466 2
        );
467
    }
468
469 1
    #[Override]
470
    public function getTrackerSystemData(): ?TrackerSystemData
471
    {
472 1
        return $this->getSpecificShipSystem(
473 1
            ShipSystemTypeEnum::SYSTEM_TRACKER,
474 1
            TrackerSystemData::class
475 1
        );
476
    }
477
478
    #[Override]
479
    public function getAggregationSystemSystemData(): ?AggregationSystemSystemData
480
    {
481
        return $this->getSpecificShipSystem(
482
            ShipSystemTypeEnum::SYSTEM_AGGREGATION_SYSTEM,
483
            AggregationSystemSystemData::class
484
        );
485
    }
486
487
    #[Override]
488
    public function getBussardCollectorSystemData(): ?BussardCollectorSystemData
489
    {
490
        return $this->getSpecificShipSystem(
491
            ShipSystemTypeEnum::SYSTEM_BUSSARD_COLLECTOR,
492
            BussardCollectorSystemData::class
493
        );
494
    }
495
496
    #[Override]
497
    public function getWebEmitterSystemData(): ?WebEmitterSystemData
498
    {
499
        return $this->getSpecificShipSystem(
500
            ShipSystemTypeEnum::SYSTEM_THOLIAN_WEB,
501
            WebEmitterSystemData::class
502
        );
503
    }
504
505 1
    #[Override]
506
    public function getAstroLaboratorySystemData(): ?AstroLaboratorySystemData
507
    {
508 1
        return $this->getSpecificShipSystem(
509 1
            ShipSystemTypeEnum::SYSTEM_ASTRO_LABORATORY,
510 1
            AstroLaboratorySystemData::class
511 1
        );
512
    }
513
514 1
    #[Override]
515
    public function getProjectileLauncherSystemData(): ?ProjectileLauncherSystemData
516
    {
517 1
        return $this->getSpecificShipSystem(
518 1
            ShipSystemTypeEnum::SYSTEM_TORPEDO,
519 1
            ProjectileLauncherSystemData::class
520 1
        );
521
    }
522
523
    /**
524
     * @template T
525
     * @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...
526
     *
527
     * @return T|null
528
     */
529 7
    private function getSpecificShipSystem(ShipSystemTypeEnum $systemType, string $className)
530
    {
531 7
        return $this->systemDataDeserializer->getSpecificShipSystem(
532 7
            $this->ship,
533 7
            $systemType,
534 7
            $className,
535 7
            $this->shipSystemDataCache,
536 7
            $this->shipWrapperFactory
537 7
        );
538
    }
539
}
540