Passed
Push — master ( 77a570...adeb98 )
by Nico
26: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 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() != null) {
286
            if ($this->ship->getBuildplan()->getUser() != $this->game->getUser()) {
287
                return false;
288
            }
289
        }
290
291
        return true;
292
    }
293
294 4
    #[Override]
295
    public function canFire(): bool
296
    {
297 4
        $ship = $this->ship;
298 4
        if (!$ship->getNbs()) {
299 1
            return false;
300
        }
301 3
        if (!$ship->hasActiveWeapon()) {
302 1
            return false;
303
        }
304
305 2
        $epsSystem = $this->getEpsSystemData();
306 2
        return $epsSystem !== null && $epsSystem->getEps() !== 0;
307
    }
308
309
    #[Override]
310
    public function getRepairDuration(): int
311
    {
312
        return $this->repairUtil->getRepairDuration($this);
313
    }
314
315
    #[Override]
316
    public function getRepairDurationPreview(): int
317
    {
318
        return $this->repairUtil->getRepairDurationPreview($this);
319
    }
320
321
    #[Override]
322
    public function getRepairCosts(): array
323
    {
324
        $neededParts = $this->repairUtil->determineSpareParts($this, false);
325
326
        $neededSpareParts = $neededParts[CommodityTypeEnum::COMMODITY_SPARE_PART];
327
        $neededSystemComponents = $neededParts[CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT];
328
329
        return [
330
            new ShipRepairCost($neededSpareParts, CommodityTypeEnum::COMMODITY_SPARE_PART, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SPARE_PART)),
331
            new ShipRepairCost($neededSystemComponents, CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT))
332
        ];
333
    }
334
335
    #[Override]
336
    public function getPossibleTorpedoTypes(): array
337
    {
338
        if ($this->ship->hasShipSystem(ShipSystemTypeEnum::SYSTEM_TORPEDO_STORAGE)) {
339
            return $this->torpedoTypeRepository->getAll();
340
        }
341
342
        return $this->torpedoTypeRepository->getByLevel($this->ship->getRump()->getTorpedoLevel());
343
    }
344
345
    #[Override]
346
    public function getTractoredShipWrapper(): ?ShipWrapperInterface
347
    {
348
        $tractoredShip = $this->ship->getTractoredShip();
349
        if ($tractoredShip === null) {
350
            return null;
351
        }
352
353
        return $this->shipWrapperFactory->wrapShip($tractoredShip);
354
    }
355
356
    #[Override]
357
    public function getTractoringShipWrapper(): ?ShipWrapperInterface
358
    {
359
        $tractoringShip = $this->ship->getTractoringShip();
360
        if ($tractoringShip === null) {
361
            return null;
362
        }
363
364
        return $this->shipWrapperFactory->wrapShip($tractoringShip);
365
    }
366
367
    #[Override]
368
    public function getDockedToShipWrapper(): ?ShipWrapperInterface
369
    {
370
        $dockedTo = $this->ship->getDockedTo();
371
        if ($dockedTo === null) {
372
            return null;
373
        }
374
375
        return $this->shipWrapperFactory->wrapShip($dockedTo);
376
    }
377
378
    #[Override]
379
    public function getStateIconAndTitle(): ?array
380
    {
381
        return $this->stateIconAndTitle->getStateIconAndTitle($this);
382
    }
383
384
    #[Override]
385
    public function getTakeoverTicksLeft(?ShipTakeoverInterface $takeover = null): int
386
    {
387
        $takeover ??= $this->ship->getTakeoverActive();
388
        if ($takeover === null) {
389
            throw new RuntimeException('should not call when active takeover is null');
390
        }
391
392
        $currentTurn = $this->game->getCurrentRound()->getTurn();
393
394
        return $takeover->getStartTurn() + ShipTakeoverManagerInterface::TURNS_TO_TAKEOVER - $currentTurn;
395
    }
396
397
    #[Override]
398
    public function canBeScrapped(): bool
399
    {
400
        $ship = $this->ship;
401
402
        return $ship->isBase() && $ship->getState() !== ShipStateEnum::SHIP_STATE_UNDER_SCRAPPING;
403
    }
404
405
    #[Override]
406
    public function getCrewStyle(): string
407
    {
408
        $ship = $this->ship;
409
        $excessCrew = $ship->getExcessCrewCount();
410
411
        if ($excessCrew === 0) {
412
            return "";
413
        }
414
415
        return $excessCrew > 0 ? "color: green;" : "color: red;";
416
    }
417
418 1
    #[Override]
419
    public function getHullSystemData(): HullSystemData
420
    {
421 1
        $hullSystemData = $this->getSpecificShipSystem(
422 1
            ShipSystemTypeEnum::SYSTEM_HULL,
423 1
            HullSystemData::class
424 1
        );
425
426 1
        if ($hullSystemData === null) {
427
            throw new SystemNotFoundException('no hull installed?');
428
        }
429
430 1
        return $hullSystemData;
431
    }
432
433
    #[Override]
434
    public function getShieldSystemData(): ?ShieldSystemData
435
    {
436
        return $this->getSpecificShipSystem(
437
            ShipSystemTypeEnum::SYSTEM_SHIELDS,
438
            ShieldSystemData::class
439
        );
440
    }
441
442 2
    #[Override]
443
    public function getEpsSystemData(): ?EpsSystemData
444
    {
445 2
        return $this->getSpecificShipSystem(
446 2
            ShipSystemTypeEnum::SYSTEM_EPS,
447 2
            EpsSystemData::class
448 2
        );
449
    }
450
451
    #[Override]
452
    public function getWarpDriveSystemData(): ?WarpDriveSystemData
453
    {
454
        return $this->getSpecificShipSystem(
455
            ShipSystemTypeEnum::SYSTEM_WARPDRIVE,
456
            WarpDriveSystemData::class
457
        );
458
    }
459
460
    #[Override]
461
    public function getTrackerSystemData(): ?TrackerSystemData
462
    {
463
        return $this->getSpecificShipSystem(
464
            ShipSystemTypeEnum::SYSTEM_TRACKER,
465
            TrackerSystemData::class
466
        );
467
    }
468
469
    #[Override]
470
    public function getAggregationSystemSystemData(): ?AggregationSystemSystemData
471
    {
472
        return $this->getSpecificShipSystem(
473
            ShipSystemTypeEnum::SYSTEM_AGGREGATION_SYSTEM,
474
            AggregationSystemSystemData::class
475
        );
476
    }
477
478
    #[Override]
479
    public function getBussardCollectorSystemData(): ?BussardCollectorSystemData
480
    {
481
        return $this->getSpecificShipSystem(
482
            ShipSystemTypeEnum::SYSTEM_BUSSARD_COLLECTOR,
483
            BussardCollectorSystemData::class
484
        );
485
    }
486
487
    #[Override]
488
    public function getWebEmitterSystemData(): ?WebEmitterSystemData
489
    {
490
        return $this->getSpecificShipSystem(
491
            ShipSystemTypeEnum::SYSTEM_THOLIAN_WEB,
492
            WebEmitterSystemData::class
493
        );
494
    }
495
496
    #[Override]
497
    public function getAstroLaboratorySystemData(): ?AstroLaboratorySystemData
498
    {
499
        return $this->getSpecificShipSystem(
500
            ShipSystemTypeEnum::SYSTEM_ASTRO_LABORATORY,
501
            AstroLaboratorySystemData::class
502
        );
503
    }
504
505
    #[Override]
506
    public function getProjectileLauncherSystemData(): ?ProjectileLauncherSystemData
507
    {
508
        return $this->getSpecificShipSystem(
509
            ShipSystemTypeEnum::SYSTEM_TORPEDO,
510
            ProjectileLauncherSystemData::class
511
        );
512
    }
513
514
    /**
515
     * @template T
516
     * @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...
517
     *
518
     * @return T|null
519
     */
520 3
    private function getSpecificShipSystem(ShipSystemTypeEnum $systemType, string $className)
521
    {
522 3
        return $this->systemDataDeserializer->getSpecificShipSystem(
523 3
            $this->ship,
524 3
            $systemType,
525 3
            $className,
526 3
            $this->shipSystemDataCache,
527 3
            $this->shipWrapperFactory
528 3
        );
529
    }
530
}