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