Test Failed
Push — dev ( cc891d...2da33f )
by Janko
09:11
created

SpacecraftWrapper::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 9
dl 0
loc 13
ccs 1
cts 1
cp 1
crap 1
rs 10

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\Spacecraft\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\Spacecraft\Repair\RepairUtilInterface;
12
use Stu\Component\Spacecraft\SpacecraftAlertStateEnum;
13
use Stu\Component\Spacecraft\System\Data\AbstractSystemData;
14
use Stu\Component\Spacecraft\System\Data\EpsSystemData;
15
use Stu\Component\Spacecraft\System\Data\FusionCoreSystemData;
16
use Stu\Component\Spacecraft\System\Data\HullSystemData;
17
use Stu\Component\Spacecraft\System\Data\LssSystemData;
18
use Stu\Component\Spacecraft\System\Data\ProjectileLauncherSystemData;
19
use Stu\Component\Spacecraft\System\Data\ShieldSystemData;
20
use Stu\Component\Spacecraft\System\Data\SingularityCoreSystemData;
21
use Stu\Component\Spacecraft\System\Data\WarpCoreSystemData;
22
use Stu\Component\Spacecraft\System\Data\WarpDriveSystemData;
23
use Stu\Component\Spacecraft\System\Exception\SystemNotFoundException;
24
use Stu\Component\Spacecraft\System\SpacecraftSystemManagerInterface;
25
use Stu\Component\Spacecraft\System\SpacecraftSystemTypeEnum;
26
use Stu\Component\Spacecraft\System\SystemDataDeserializerInterface;
27
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...
28
use Stu\Module\Control\GameControllerInterface;
29
use Stu\Module\Spacecraft\Lib\Interaction\ShipTakeoverManagerInterface;
30
use Stu\Module\Spacecraft\Lib\ReactorWrapper;
31
use Stu\Module\Spacecraft\Lib\ReactorWrapperInterface;
32
use Stu\Module\Spacecraft\Lib\ShipRepairCost;
33
use Stu\Module\Spacecraft\Lib\SpacecraftStateChangerInterface;
34
use Stu\Module\Spacecraft\Lib\SpacecraftWrapperFactoryInterface;
35
use Stu\Module\Ship\Lib\ShipWrapperInterface;
36
use Stu\Module\Spacecraft\Lib\Ui\StateIconAndTitle;
37
use Stu\Orm\Entity\SpacecraftSystemInterface;
38
use Stu\Orm\Entity\ShipTakeoverInterface;
39
use Stu\Orm\Entity\SpacecraftInterface;
40
use Stu\Orm\Repository\TorpedoTypeRepositoryInterface;
41
42
//TODO increase coverage
43
/**
44
 * @template T of SpacecraftInterface
45
 */
46
abstract class SpacecraftWrapper implements SpacecraftWrapperInterface
47
{
48
    /** @var Collection<int, AbstractSystemData> */
49
    private Collection $shipSystemDataCache;
50
51
    private ?ReactorWrapperInterface $reactorWrapper = null;
52
53
    private ?int $epsUsage = null;
54
55
    /**
56
     * @param T $spacecraft
57 63
     */
58
    public function __construct(
59
        protected SpacecraftInterface $spacecraft,
60
        private SpacecraftSystemManagerInterface $spacecraftSystemManager,
61
        private SystemDataDeserializerInterface $systemDataDeserializer,
62
        private TorpedoTypeRepositoryInterface $torpedoTypeRepository,
63
        protected GameControllerInterface $game,
64
        protected SpacecraftWrapperFactoryInterface $spacecraftWrapperFactory,
65
        private SpacecraftStateChangerInterface $spacecraftStateChanger,
66
        private RepairUtilInterface $repairUtil,
67
        private StateIconAndTitle $stateIconAndTitle
68
    ) {
69 63
70
        $this->shipSystemDataCache = new ArrayCollection();
71
    }
72
73
    #[Override]
74
    public function get(): SpacecraftInterface
75
    {
76
        return $this->spacecraft;
77
    }
78
79
    #[Override]
80
    public function getSpacecraftWrapperFactory(): SpacecraftWrapperFactoryInterface
81
    {
82
        return $this->spacecraftWrapperFactory;
83
    }
84
85
    #[Override]
86
    public function getSpacecraftSystemManager(): SpacecraftSystemManagerInterface
87
    {
88
        return $this->spacecraftSystemManager;
89
    }
90 3
91
    #[Override]
92
    public function getEpsUsage(): int
93 3
    {
94 3
        if ($this->epsUsage === null) {
95
            $this->epsUsage = $this->reloadEpsUsage();
96 3
        }
97
        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...
98
    }
99
100
    #[Override]
101
    public function lowerEpsUsage(int $value): void
102
    {
103
        $this->epsUsage -= $value;
104
    }
105 3
106
    private function reloadEpsUsage(): int
107 3
    {
108
        $result = 0;
109 3
110 3
        foreach ($this->spacecraftSystemManager->getActiveSystems($this->spacecraft) as $shipSystem) {
111
            $result += $this->spacecraftSystemManager->getEnergyConsumption($shipSystem->getSystemType());
112
        }
113 3
114
        if ($this->spacecraft->getAlertState() == SpacecraftAlertStateEnum::ALERT_YELLOW) {
115
            $result += SpacecraftStateChangerInterface::ALERT_YELLOW_EPS_USAGE;
116 3
        }
117
        if ($this->spacecraft->getAlertState() == SpacecraftAlertStateEnum::ALERT_RED) {
118
            $result += SpacecraftStateChangerInterface::ALERT_RED_EPS_USAGE;
119
        }
120 3
121
        return $result;
122
    }
123 2
124
    public function getReactorUsage(): int
125 2
    {
126 2
        $reactor = $this->reactorWrapper;
127
        if ($reactor === null) {
128
            throw new RuntimeException('this should not happen');
129
        }
130 2
131
        return $this->getEpsUsage() + $reactor->getUsage();
132
    }
133 9
134
    #[Override]
135
    public function getReactorWrapper(): ?ReactorWrapperInterface
136 9
    {
137 9
        if ($this->reactorWrapper === null) {
138 9
            $ship = $this->spacecraft;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->spacecraft of type Stu\Orm\Entity\SpacecraftInterface is incompatible with the declared type Stu\Module\Spacecraft\Lib\T of property $spacecraft.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
139
            $reactorSystemData = null;
140
141 9
142 5
            if ($ship->hasSpacecraftSystem(SpacecraftSystemTypeEnum::WARPCORE)) {
143 5
                $reactorSystemData = $this->getSpecificShipSystem(
144 5
                    SpacecraftSystemTypeEnum::WARPCORE,
145 5
                    WarpCoreSystemData::class
146
                );
147 9
            }
148
            if ($ship->hasSpacecraftSystem(SpacecraftSystemTypeEnum::SINGULARITY_REACTOR)) {
149
                $reactorSystemData = $this->getSpecificShipSystem(
150
                    SpacecraftSystemTypeEnum::SINGULARITY_REACTOR,
151
                    SingularityCoreSystemData::class
152
                );
153 9
            }
154
            if ($ship->hasSpacecraftSystem(SpacecraftSystemTypeEnum::FUSION_REACTOR)) {
155
                $reactorSystemData = $this->getSpecificShipSystem(
156
                    SpacecraftSystemTypeEnum::FUSION_REACTOR,
157
                    FusionCoreSystemData::class
158
                );
159
            }
160 9
161 6
            if ($reactorSystemData === null) {
162
                return null;
163
            }
164 5
165
            $this->reactorWrapper = new ReactorWrapper($this, $reactorSystemData);
166
        }
167 5
168
        return $this->reactorWrapper;
169
    }
170
171
    #[Override]
172
    public function setAlertState(SpacecraftAlertStateEnum $alertState): ?string
173
    {
174
        $msg = $this->spacecraftStateChanger->changeAlertState($this, $alertState);
175
        $this->epsUsage = $this->reloadEpsUsage();
176
177
        return $msg;
178
    }
179
180
    #[Override]
181
    public function getSensorRange(): int
182
    {
183
        $lssSystemData = $this->getLssSystemData();
184 3
185
        return $lssSystemData !== null
186
            ? $lssSystemData->getSensorRange()
187 3
            : 0;
188 3
    }
189 3
190 2
191
    #[Override]
192
    public function getShieldRegenerationRate(): int
193
    {
194
        $regenerationPercentage = $this->get()->isSystemHealthy(SpacecraftSystemTypeEnum::SHIELDS) ? 10 : 0;
195
196
        return (int) ceil(($this->get()->getMaxShield() / 100) * $regenerationPercentage);
197 3
    }
198 3
199 3
    /**
200
     * highest damage first, then prio
201
     *
202
     * @return SpacecraftSystemInterface[]
203
     */
204 3
    #[Override]
205 3
    public function getDamagedSystems(): array
206
    {
207 3
        $damagedSystems = [];
208
        $prioArray = [];
209
        foreach ($this->spacecraft->getSystems() as $system) {
210 9
            if ($system->getStatus() < 100) {
211
                $damagedSystems[] = $system;
212
                $prioArray[$system->getSystemType()->value] = $this->spacecraftSystemManager->lookupSystem($system->getSystemType())->getPriority();
213 9
            }
214 9
        }
215
216
        // sort by damage and priority
217 2
        usort(
218
            $damagedSystems,
219
            function (SpacecraftSystemInterface $a, SpacecraftSystemInterface $b) use ($prioArray): int {
220 2
                if ($a->getStatus() === $b->getStatus()) {
221
                    return $prioArray[$b->getSystemType()->value] <=> $prioArray[$a->getSystemType()->value];
222
                }
223
                return ($a->getStatus() < $b->getStatus()) ? -1 : 1;
224 2
            }
225
        );
226
227
        return $damagedSystems;
228 2
    }
229
230
    #[Override]
231
    public function isSelectable(): bool
232 2
    {
233
        return $this->game->getUser() === $this->spacecraft->getUser()
234
            && $this->spacecraft->getType()->getModuleView() !== null;
235
    }
236 2
237
    #[Override]
238
    public function canBeRepaired(): bool
239 4
    {
240
        if ($this->spacecraft->getAlertState() !== SpacecraftAlertStateEnum::ALERT_GREEN) {
241
            return false;
242 4
        }
243 4
244 1
        if ($this->spacecraft->getShieldState()) {
245
            return false;
246 3
        }
247 1
248
        if ($this->spacecraft->isCloaked()) {
249
            return false;
250 2
        }
251 2
252
        if ($this->getDamagedSystems() !== []) {
253
            return true;
254
        }
255
256
        return $this->spacecraft->getHull() < $this->spacecraft->getMaxHull();
257
    }
258
259
    #[Override]
260
    public function canFire(): bool
261
    {
262
        $ship = $this->spacecraft;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->spacecraft of type Stu\Orm\Entity\SpacecraftInterface is incompatible with the declared type Stu\Module\Spacecraft\Lib\T of property $spacecraft.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
263
        if (!$ship->getNbs()) {
264
            return false;
265
        }
266
        if (!$ship->hasActiveWeapon()) {
267
            return false;
268
        }
269
270
        $epsSystem = $this->getEpsSystemData();
271
        return $epsSystem !== null && $epsSystem->getEps() !== 0;
272
    }
273
274
    #[Override]
275
    public function getRepairDuration(): int
276
    {
277
        return $this->repairUtil->getRepairDuration($this);
278
    }
279
280
    #[Override]
281
    public function getRepairDurationPreview(): int
282
    {
283
        return $this->repairUtil->getRepairDurationPreview($this);
284
    }
285
286
    #[Override]
287
    public function getRepairCosts(): array
288
    {
289
        $neededParts = $this->repairUtil->determineSpareParts($this, false);
290
291
        $neededSpareParts = $neededParts[CommodityTypeEnum::COMMODITY_SPARE_PART];
292
        $neededSystemComponents = $neededParts[CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT];
293
294
        return [
295
            new ShipRepairCost($neededSpareParts, CommodityTypeEnum::COMMODITY_SPARE_PART, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SPARE_PART)),
296
            new ShipRepairCost($neededSystemComponents, CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT))
297
        ];
298
    }
299
300
    #[Override]
301 4
    public function getPossibleTorpedoTypes(): array
302
    {
303
        if ($this->spacecraft->hasSpacecraftSystem(SpacecraftSystemTypeEnum::TORPEDO_STORAGE)) {
304 4
            return $this->torpedoTypeRepository->getAll();
305
        }
306
307
        return $this->torpedoTypeRepository->getByLevel($this->spacecraft->getRump()->getTorpedoLevel());
308
    }
309
310
    #[Override]
311
    public function getTractoredShipWrapper(): ?ShipWrapperInterface
312
    {
313
        $tractoredShip = $this->spacecraft->getTractoredShip();
314
        if ($tractoredShip === null) {
315
            return null;
316
        }
317
318
        return $this->spacecraftWrapperFactory->wrapShip($tractoredShip);
319
    }
320 6
321
    #[Override]
322
    public function getStateIconAndTitle(): ?array
323 6
    {
324 6
        return $this->stateIconAndTitle->getStateIconAndTitle($this);
325
    }
326 6
327 5
    #[Override]
328
    public function getTakeoverTicksLeft(?ShipTakeoverInterface $takeover = null): int
329
    {
330 3
        $takeover ??= $this->spacecraft->getTakeoverActive();
331
        if ($takeover === null) {
332
            throw new RuntimeException('should not call when active takeover is null');
333 9
        }
334
335
        $currentTurn = $this->game->getCurrentRound()->getTurn();
336 9
337 9
        return $takeover->getStartTurn() + ShipTakeoverManagerInterface::TURNS_TO_TAKEOVER - $currentTurn;
338 9
    }
339 9
340
    #[Override]
341 9
    public function getCrewStyle(): string
342
    {
343
        $ship = $this->spacecraft;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->spacecraft of type Stu\Orm\Entity\SpacecraftInterface is incompatible with the declared type Stu\Module\Spacecraft\Lib\T of property $spacecraft.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
344
        $excessCrew = $ship->getExcessCrewCount();
345 9
346
        if ($excessCrew === 0) {
347
            return "";
348 8
        }
349
350
        return $excessCrew > 0 ? "color: green;" : "color: red;";
351 8
    }
352 8
353 8
    #[Override]
354 8
    public function getHullSystemData(): HullSystemData
355
    {
356
        $hullSystemData = $this->getSpecificShipSystem(
357 18
            SpacecraftSystemTypeEnum::HULL,
358
            HullSystemData::class
359
        );
360 18
361 18
        if ($hullSystemData === null) {
362 18
            throw new SystemNotFoundException('no hull installed?');
363 18
        }
364
365
        return $hullSystemData;
366 4
    }
367
368
    #[Override]
369 4
    public function getShieldSystemData(): ?ShieldSystemData
370 4
    {
371 4
        return $this->getSpecificShipSystem(
372 4
            SpacecraftSystemTypeEnum::SHIELDS,
373
            ShieldSystemData::class
374
        );
375 1
    }
376
377
    #[Override]
378 1
    public function getEpsSystemData(): ?EpsSystemData
379 1
    {
380 1
        return $this->getSpecificShipSystem(
381 1
            SpacecraftSystemTypeEnum::EPS,
382
            EpsSystemData::class
383
        );
384
    }
385
386
    #[Override]
387
    public function getLssSystemData(): ?LssSystemData
388
    {
389
        return $this->getSpecificShipSystem(
390 22
            SpacecraftSystemTypeEnum::LSS,
391
            LssSystemData::class
392 22
        );
393 22
    }
394 22
395 22
    #[Override]
396 22
    public function getWarpDriveSystemData(): ?WarpDriveSystemData
397 22
    {
398 22
        return $this->getSpecificShipSystem(
399
            SpacecraftSystemTypeEnum::WARPDRIVE,
400
            WarpDriveSystemData::class
401
        );
402
    }
403
404
    #[Override]
405
    public function getProjectileLauncherSystemData(): ?ProjectileLauncherSystemData
406
    {
407
        return $this->getSpecificShipSystem(
408
            SpacecraftSystemTypeEnum::TORPEDO,
409
            ProjectileLauncherSystemData::class
410
        );
411
    }
412
413
    /**
414
     * @template T2
415
     * @param class-string<T2> $className
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T2> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T2>.
Loading history...
416
     *
417
     * @return T2|null
418
     */
419
    protected function getSpecificShipSystem(SpacecraftSystemTypeEnum $systemType, string $className)
420
    {
421
        return $this->systemDataDeserializer->getSpecificShipSystem(
422
            $this->spacecraft,
423
            $systemType,
424
            $className,
425
            $this->shipSystemDataCache,
426
            $this->spacecraftWrapperFactory
427
        );
428
    }
429
430
    #[Override]
431
    public function __toString(): string
432
    {
433
        $systems = implode(",\n", $this->spacecraft->getSystems()
434
            ->filter(fn($system): bool => $system->getData() !== null)
435
            ->map(fn($system): string => $system->__toString())
436
            ->toArray());
437
438
        return sprintf(
439
            "spacecraft: {%s,\n  systems: [\n%s\n}\n]",
440
            $this->spacecraft->__toString(),
441
            $systems
442
        );
443
    }
444
}
445