Passed
Push — master ( c06e17...8a7133 )
by Nico
25:46 queued 11:50
created

SpacecraftWrapper::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
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 9
dl 0
loc 13
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\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
     */
58 66
    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
70 66
        $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
91 3
    #[Override]
92
    public function getEpsUsage(): int
93
    {
94 3
        if ($this->epsUsage === null) {
95 3
            $this->epsUsage = $this->reloadEpsUsage();
96
        }
97 3
        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
106 3
    private function reloadEpsUsage(): int
107
    {
108 3
        $result = 0;
109
110 3
        foreach ($this->spacecraftSystemManager->getActiveSystems($this->spacecraft) as $shipSystem) {
111 3
            $result += $this->spacecraftSystemManager->getEnergyConsumption($shipSystem->getSystemType());
112
        }
113
114 3
        $result += $this->spacecraft->getAlertState()->getEpsUsage();
115
116 3
        return $result;
117
    }
118
119 2
    public function getReactorUsage(): int
120
    {
121 2
        $reactor = $this->reactorWrapper;
122 2
        if ($reactor === null) {
123
            throw new RuntimeException('this should not happen');
124
        }
125
126 2
        return $this->getEpsUsage() + $reactor->getUsage();
127
    }
128
129 9
    #[Override]
130
    public function getReactorWrapper(): ?ReactorWrapperInterface
131
    {
132 9
        if ($this->reactorWrapper === null) {
133 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...
134 9
            $reactorSystemData = null;
135
136
137 9
            if ($ship->hasSpacecraftSystem(SpacecraftSystemTypeEnum::WARPCORE)) {
138 5
                $reactorSystemData = $this->getSpecificShipSystem(
139 5
                    SpacecraftSystemTypeEnum::WARPCORE,
140 5
                    WarpCoreSystemData::class
141 5
                );
142
            }
143 9
            if ($ship->hasSpacecraftSystem(SpacecraftSystemTypeEnum::SINGULARITY_REACTOR)) {
144
                $reactorSystemData = $this->getSpecificShipSystem(
145
                    SpacecraftSystemTypeEnum::SINGULARITY_REACTOR,
146
                    SingularityCoreSystemData::class
147
                );
148
            }
149 9
            if ($ship->hasSpacecraftSystem(SpacecraftSystemTypeEnum::FUSION_REACTOR)) {
150
                $reactorSystemData = $this->getSpecificShipSystem(
151
                    SpacecraftSystemTypeEnum::FUSION_REACTOR,
152
                    FusionCoreSystemData::class
153
                );
154
            }
155
156 9
            if ($reactorSystemData === null) {
157 6
                return null;
158
            }
159
160 5
            $this->reactorWrapper = new ReactorWrapper($this, $reactorSystemData);
161
        }
162
163 5
        return $this->reactorWrapper;
164
    }
165
166
    #[Override]
167
    public function setAlertState(SpacecraftAlertStateEnum $alertState): ?string
168
    {
169
        $msg = $this->spacecraftStateChanger->changeAlertState($this, $alertState);
170
        $this->epsUsage = $this->reloadEpsUsage();
171
172
        return $msg;
173
    }
174
175 1
    #[Override]
176
    public function getSensorRange(): int
177
    {
178 1
        $lssSystemData = $this->getLssSystemData();
179 1
        if ($lssSystemData === null) {
180
            return 0;
181
        }
182
183 1
        return (int) (ceil($lssSystemData->getSensorRange()
184 1
            * $this->get()->getSpacecraftSystem(SpacecraftSystemTypeEnum::LSS)->getStatus() / 100));
185
    }
186
187 3
    #[Override]
188
    public function getShieldRegenerationRate(): int
189
    {
190 3
        $regenerationPercentage = $this->get()->isSystemHealthy(SpacecraftSystemTypeEnum::SHIELDS) ? 10 : 0;
191
192 3
        $shield = $this->get()->getShield();
193 3
        $maxshield = $this->get()->getMaxShield();
194
195 3
        $result = (int) ceil(($maxshield / 100) * $regenerationPercentage);
196
197 3
        if ($result > $maxshield - $shield) {
198 1
            $result = $maxshield - $shield;
199
        }
200
201 3
        return $result;
202
    }
203
204
    /**
205
     * highest damage first, then prio
206
     *
207
     * @return SpacecraftSystemInterface[]
208
     */
209 3
    #[Override]
210
    public function getDamagedSystems(): array
211
    {
212 3
        $damagedSystems = [];
213 3
        $prioArray = [];
214 3
        foreach ($this->spacecraft->getSystems() as $system) {
215 2
            if ($system->getStatus() < 100) {
216
                $damagedSystems[] = $system;
217
                $prioArray[$system->getSystemType()->value] = $this->spacecraftSystemManager->lookupSystem($system->getSystemType())->getPriority();
218
            }
219
        }
220
221
        // sort by damage and priority
222 3
        usort(
223 3
            $damagedSystems,
224 3
            function (SpacecraftSystemInterface $a, SpacecraftSystemInterface $b) use ($prioArray): int {
225
                if ($a->getStatus() === $b->getStatus()) {
226
                    return $prioArray[$b->getSystemType()->value] <=> $prioArray[$a->getSystemType()->value];
227
                }
228
                return ($a->getStatus() < $b->getStatus()) ? -1 : 1;
229 3
            }
230 3
        );
231
232 3
        return $damagedSystems;
233
    }
234
235 10
    #[Override]
236
    public function isSelectable(): bool
237
    {
238 10
        return $this->game->getUser() === $this->spacecraft->getUser()
239 10
            && $this->spacecraft->getType()->getModuleView() !== null;
240
    }
241
242 2
    #[Override]
243
    public function canBeRepaired(): bool
244
    {
245 2
        if ($this->spacecraft->getAlertState() !== SpacecraftAlertStateEnum::ALERT_GREEN) {
246
            return false;
247
        }
248
249 2
        if ($this->spacecraft->isShielded()) {
250
            return false;
251
        }
252
253 2
        if ($this->spacecraft->isCloaked()) {
254
            return false;
255
        }
256
257 2
        if ($this->getDamagedSystems() !== []) {
258
            return true;
259
        }
260
261 2
        return $this->spacecraft->getHull() < $this->spacecraft->getMaxHull();
262
    }
263
264 4
    #[Override]
265
    public function canFire(): bool
266
    {
267 4
        $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...
268 4
        if (!$ship->getNbs()) {
269 1
            return false;
270
        }
271 3
        if (!$ship->hasActiveWeapon()) {
272 1
            return false;
273
        }
274
275 2
        $epsSystem = $this->getEpsSystemData();
276 2
        return $epsSystem !== null && $epsSystem->getEps() !== 0;
277
    }
278
279
    #[Override]
280
    public function getRepairDuration(): int
281
    {
282
        return $this->repairUtil->getRepairDuration($this);
283
    }
284
285
    #[Override]
286
    public function getRepairDurationPreview(): int
287
    {
288
        return $this->repairUtil->getRepairDurationPreview($this);
289
    }
290
291
    #[Override]
292
    public function getRepairCosts(): array
293
    {
294
        $neededParts = $this->repairUtil->determineSpareParts($this, false);
295
296
        $neededSpareParts = $neededParts[CommodityTypeEnum::COMMODITY_SPARE_PART];
297
        $neededSystemComponents = $neededParts[CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT];
298
299
        return [
300
            new ShipRepairCost($neededSpareParts, CommodityTypeEnum::COMMODITY_SPARE_PART, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SPARE_PART)),
301
            new ShipRepairCost($neededSystemComponents, CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT))
302
        ];
303
    }
304
305
    #[Override]
306
    public function getPossibleTorpedoTypes(): array
307
    {
308
        if ($this->spacecraft->hasSpacecraftSystem(SpacecraftSystemTypeEnum::TORPEDO_STORAGE)) {
309
            return $this->torpedoTypeRepository->getAll();
310
        }
311
312
        return $this->torpedoTypeRepository->getByLevel($this->spacecraft->getRump()->getTorpedoLevel());
313
    }
314
315
    #[Override]
316
    public function getTractoredShipWrapper(): ?ShipWrapperInterface
317
    {
318
        $tractoredShip = $this->spacecraft->getTractoredShip();
319
        if ($tractoredShip === null) {
320
            return null;
321
        }
322
323
        return $this->spacecraftWrapperFactory->wrapShip($tractoredShip);
324
    }
325
326 4
    #[Override]
327
    public function getStateIconAndTitle(): ?array
328
    {
329 4
        return $this->stateIconAndTitle->getStateIconAndTitle($this);
330
    }
331
332
    #[Override]
333
    public function getTakeoverTicksLeft(?ShipTakeoverInterface $takeover = null): int
334
    {
335
        $takeover ??= $this->spacecraft->getTakeoverActive();
336
        if ($takeover === null) {
337
            throw new RuntimeException('should not call when active takeover is null');
338
        }
339
340
        $currentTurn = $this->game->getCurrentRound()->getTurn();
341
342
        return $takeover->getStartTurn() + ShipTakeoverManagerInterface::TURNS_TO_TAKEOVER - $currentTurn;
343
    }
344
345 6
    #[Override]
346
    public function getCrewStyle(): string
347
    {
348 6
        $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...
349 6
        $excessCrew = $ship->getExcessCrewCount();
350
351 6
        if ($excessCrew === 0) {
352 5
            return "";
353
        }
354
355 3
        return $excessCrew > 0 ? "color: green;" : "color: red;";
356
    }
357
358 10
    #[Override]
359
    public function getHullSystemData(): HullSystemData
360
    {
361 10
        $hullSystemData = $this->getSpecificShipSystem(
362 10
            SpacecraftSystemTypeEnum::HULL,
363 10
            HullSystemData::class
364 10
        );
365
366 10
        if ($hullSystemData === null) {
367
            throw new SystemNotFoundException('no hull installed?');
368
        }
369
370 10
        return $hullSystemData;
371
    }
372
373 9
    #[Override]
374
    public function getShieldSystemData(): ?ShieldSystemData
375
    {
376 9
        return $this->getSpecificShipSystem(
377 9
            SpacecraftSystemTypeEnum::SHIELDS,
378 9
            ShieldSystemData::class
379 9
        );
380
    }
381
382 20
    #[Override]
383
    public function getEpsSystemData(): ?EpsSystemData
384
    {
385 20
        return $this->getSpecificShipSystem(
386 20
            SpacecraftSystemTypeEnum::EPS,
387 20
            EpsSystemData::class
388 20
        );
389
    }
390
391 2
    #[Override]
392
    public function getLssSystemData(): ?LssSystemData
393
    {
394 2
        return $this->getSpecificShipSystem(
395 2
            SpacecraftSystemTypeEnum::LSS,
396 2
            LssSystemData::class
397 2
        );
398
    }
399
400 4
    #[Override]
401
    public function getWarpDriveSystemData(): ?WarpDriveSystemData
402
    {
403 4
        return $this->getSpecificShipSystem(
404 4
            SpacecraftSystemTypeEnum::WARPDRIVE,
405 4
            WarpDriveSystemData::class
406 4
        );
407
    }
408
409 1
    #[Override]
410
    public function getProjectileLauncherSystemData(): ?ProjectileLauncherSystemData
411
    {
412 1
        return $this->getSpecificShipSystem(
413 1
            SpacecraftSystemTypeEnum::TORPEDO,
414 1
            ProjectileLauncherSystemData::class
415 1
        );
416
    }
417
418
    /**
419
     * @template T2
420
     * @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...
421
     *
422
     * @return T2|null
423
     */
424 24
    protected function getSpecificShipSystem(SpacecraftSystemTypeEnum $systemType, string $className)
425
    {
426 24
        return $this->systemDataDeserializer->getSpecificShipSystem(
427 24
            $this->spacecraft,
428 24
            $systemType,
429 24
            $className,
430 24
            $this->shipSystemDataCache,
431 24
            $this->spacecraftWrapperFactory
432 24
        );
433
    }
434
435
    #[Override]
436
    public function __toString(): string
437
    {
438
        $systems = implode(",\n", $this->spacecraft->getSystems()
439
            ->filter(fn($system): bool => $system->getData() !== null)
440
            ->map(fn($system): string => $system->__toString())
441
            ->toArray());
442
443
        return sprintf(
444
            "spacecraft: {%s,\n  systems: [\n%s\n}\n]",
445
            $this->spacecraft->__toString(),
446
            $systems
447
        );
448
    }
449
}
450