Passed
Push — master ( 92a2e9...9d73f4 )
by Nico
41:55
created

ShipWrapper::getWebEmitterSystemData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 6
ccs 0
cts 4
cp 0
crap 2
rs 10
c 0
b 0
f 0
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