Passed
Pull Request — master (#1948)
by Nico
21:26 queued 10:43
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 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