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