Passed
Push — dev ( 0dbbcc...f29cfd )
by Janko
10:15
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\ProjectileLauncherSystemData;
18
use Stu\Component\Spacecraft\System\Data\ShieldSystemData;
19
use Stu\Component\Spacecraft\System\Data\SingularityCoreSystemData;
20
use Stu\Component\Spacecraft\System\Data\WarpCoreSystemData;
21
use Stu\Component\Spacecraft\System\Data\WarpDriveSystemData;
22
use Stu\Component\Spacecraft\System\Exception\SystemNotFoundException;
23
use Stu\Component\Spacecraft\System\SpacecraftSystemManagerInterface;
24
use Stu\Component\Spacecraft\System\SpacecraftSystemTypeEnum;
25
use Stu\Component\Spacecraft\System\SystemDataDeserializerInterface;
26
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...
27
use Stu\Module\Control\GameControllerInterface;
28
use Stu\Module\Spacecraft\Lib\Interaction\ShipTakeoverManagerInterface;
29
use Stu\Module\Spacecraft\Lib\ReactorWrapper;
30
use Stu\Module\Spacecraft\Lib\ReactorWrapperInterface;
31
use Stu\Module\Spacecraft\Lib\ShipRepairCost;
32
use Stu\Module\Spacecraft\Lib\SpacecraftStateChangerInterface;
33
use Stu\Module\Spacecraft\Lib\SpacecraftWrapperFactoryInterface;
34
use Stu\Module\Ship\Lib\ShipWrapperInterface;
35
use Stu\Module\Spacecraft\Lib\Ui\StateIconAndTitle;
36
use Stu\Orm\Entity\SpacecraftSystemInterface;
37
use Stu\Orm\Entity\ShipTakeoverInterface;
38
use Stu\Orm\Entity\SpacecraftInterface;
39
use Stu\Orm\Repository\TorpedoTypeRepositoryInterface;
40
41
//TODO increase coverage
42
/**
43
 * @template T of SpacecraftInterface
44
 */
45
abstract class SpacecraftWrapper implements SpacecraftWrapperInterface
46
{
47
    /** @var Collection<int, AbstractSystemData> */
48
    private Collection $shipSystemDataCache;
49
50
    private ?ReactorWrapperInterface $reactorWrapper = null;
51
52
    private ?int $epsUsage = null;
53
54
    /**
55
     * @param T $spacecraft
56
     */
57 63
    public function __construct(
58
        protected SpacecraftInterface $spacecraft,
59
        private SpacecraftSystemManagerInterface $spacecraftSystemManager,
60
        private SystemDataDeserializerInterface $systemDataDeserializer,
61
        private TorpedoTypeRepositoryInterface $torpedoTypeRepository,
62
        protected GameControllerInterface $game,
63
        protected SpacecraftWrapperFactoryInterface $spacecraftWrapperFactory,
64
        private SpacecraftStateChangerInterface $spacecraftStateChanger,
65
        private RepairUtilInterface $repairUtil,
66
        private StateIconAndTitle $stateIconAndTitle
67
    ) {
68
69 63
        $this->shipSystemDataCache = new ArrayCollection();
70
    }
71
72
    #[Override]
73
    public function get(): SpacecraftInterface
74
    {
75
        return $this->spacecraft;
76
    }
77
78
    #[Override]
79
    public function getSpacecraftWrapperFactory(): SpacecraftWrapperFactoryInterface
80
    {
81
        return $this->spacecraftWrapperFactory;
82
    }
83
84
    #[Override]
85
    public function getSpacecraftSystemManager(): SpacecraftSystemManagerInterface
86
    {
87
        return $this->spacecraftSystemManager;
88
    }
89
90 3
    #[Override]
91
    public function getEpsUsage(): int
92
    {
93 3
        if ($this->epsUsage === null) {
94 3
            $this->epsUsage = $this->reloadEpsUsage();
95
        }
96 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...
97
    }
98
99
    #[Override]
100
    public function lowerEpsUsage(int $value): void
101
    {
102
        $this->epsUsage -= $value;
103
    }
104
105 3
    private function reloadEpsUsage(): int
106
    {
107 3
        $result = 0;
108
109 3
        foreach ($this->spacecraftSystemManager->getActiveSystems($this->spacecraft) as $shipSystem) {
110 3
            $result += $this->spacecraftSystemManager->getEnergyConsumption($shipSystem->getSystemType());
111
        }
112
113 3
        if ($this->spacecraft->getAlertState() == SpacecraftAlertStateEnum::ALERT_YELLOW) {
114
            $result += SpacecraftStateChangerInterface::ALERT_YELLOW_EPS_USAGE;
115
        }
116 3
        if ($this->spacecraft->getAlertState() == SpacecraftAlertStateEnum::ALERT_RED) {
117
            $result += SpacecraftStateChangerInterface::ALERT_RED_EPS_USAGE;
118
        }
119
120 3
        return $result;
121
    }
122
123 2
    public function getReactorUsage(): int
124
    {
125 2
        $reactor = $this->reactorWrapper;
126 2
        if ($reactor === null) {
127
            throw new RuntimeException('this should not happen');
128
        }
129
130 2
        return $this->getEpsUsage() + $reactor->getUsage();
131
    }
132
133 9
    #[Override]
134
    public function getReactorWrapper(): ?ReactorWrapperInterface
135
    {
136 9
        if ($this->reactorWrapper === null) {
137 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...
138 9
            $reactorSystemData = null;
139
140
141 9
            if ($ship->hasSpacecraftSystem(SpacecraftSystemTypeEnum::WARPCORE)) {
142 5
                $reactorSystemData = $this->getSpecificShipSystem(
143 5
                    SpacecraftSystemTypeEnum::WARPCORE,
144 5
                    WarpCoreSystemData::class
145 5
                );
146
            }
147 9
            if ($ship->hasSpacecraftSystem(SpacecraftSystemTypeEnum::SINGULARITY_REACTOR)) {
148
                $reactorSystemData = $this->getSpecificShipSystem(
149
                    SpacecraftSystemTypeEnum::SINGULARITY_REACTOR,
150
                    SingularityCoreSystemData::class
151
                );
152
            }
153 9
            if ($ship->hasSpacecraftSystem(SpacecraftSystemTypeEnum::FUSION_REACTOR)) {
154
                $reactorSystemData = $this->getSpecificShipSystem(
155
                    SpacecraftSystemTypeEnum::FUSION_REACTOR,
156
                    FusionCoreSystemData::class
157
                );
158
            }
159
160 9
            if ($reactorSystemData === null) {
161 6
                return null;
162
            }
163
164 5
            $this->reactorWrapper = new ReactorWrapper($this, $reactorSystemData);
165
        }
166
167 5
        return $this->reactorWrapper;
168
    }
169
170
    #[Override]
171
    public function setAlertState(SpacecraftAlertStateEnum $alertState): ?string
172
    {
173
        $msg = $this->spacecraftStateChanger->changeAlertState($this, $alertState);
174
        $this->epsUsage = $this->reloadEpsUsage();
175
176
        return $msg;
177
    }
178
179
    /**
180
     * highest damage first, then prio
181
     *
182
     * @return SpacecraftSystemInterface[]
183
     */
184 3
    #[Override]
185
    public function getDamagedSystems(): array
186
    {
187 3
        $damagedSystems = [];
188 3
        $prioArray = [];
189 3
        foreach ($this->spacecraft->getSystems() as $system) {
190 2
            if ($system->getStatus() < 100) {
191
                $damagedSystems[] = $system;
192
                $prioArray[$system->getSystemType()->value] = $this->spacecraftSystemManager->lookupSystem($system->getSystemType())->getPriority();
193
            }
194
        }
195
196
        // sort by damage and priority
197 3
        usort(
198 3
            $damagedSystems,
199 3
            function (SpacecraftSystemInterface $a, SpacecraftSystemInterface $b) use ($prioArray): int {
200
                if ($a->getStatus() === $b->getStatus()) {
201
                    return $prioArray[$b->getSystemType()->value] <=> $prioArray[$a->getSystemType()->value];
202
                }
203
                return ($a->getStatus() < $b->getStatus()) ? -1 : 1;
204 3
            }
205 3
        );
206
207 3
        return $damagedSystems;
208
    }
209
210 9
    #[Override]
211
    public function isSelectable(): bool
212
    {
213 9
        return $this->game->getUser() === $this->spacecraft->getUser()
214 9
            && $this->spacecraft->getType()->getModuleView() !== null;
215
    }
216
217 2
    #[Override]
218
    public function canBeRepaired(): bool
219
    {
220 2
        if ($this->spacecraft->getAlertState() !== SpacecraftAlertStateEnum::ALERT_GREEN) {
221
            return false;
222
        }
223
224 2
        if ($this->spacecraft->getShieldState()) {
225
            return false;
226
        }
227
228 2
        if ($this->spacecraft->getCloakState()) {
229
            return false;
230
        }
231
232 2
        if ($this->getDamagedSystems() !== []) {
233
            return true;
234
        }
235
236 2
        return $this->spacecraft->getHull() < $this->spacecraft->getMaxHull();
237
    }
238
239 4
    #[Override]
240
    public function canFire(): bool
241
    {
242 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...
243 4
        if (!$ship->getNbs()) {
244 1
            return false;
245
        }
246 3
        if (!$ship->hasActiveWeapon()) {
247 1
            return false;
248
        }
249
250 2
        $epsSystem = $this->getEpsSystemData();
251 2
        return $epsSystem !== null && $epsSystem->getEps() !== 0;
252
    }
253
254
    #[Override]
255
    public function getRepairDuration(): int
256
    {
257
        return $this->repairUtil->getRepairDuration($this);
258
    }
259
260
    #[Override]
261
    public function getRepairDurationPreview(): int
262
    {
263
        return $this->repairUtil->getRepairDurationPreview($this);
264
    }
265
266
    #[Override]
267
    public function getRepairCosts(): array
268
    {
269
        $neededParts = $this->repairUtil->determineSpareParts($this, false);
270
271
        $neededSpareParts = $neededParts[CommodityTypeEnum::COMMODITY_SPARE_PART];
272
        $neededSystemComponents = $neededParts[CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT];
273
274
        return [
275
            new ShipRepairCost($neededSpareParts, CommodityTypeEnum::COMMODITY_SPARE_PART, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SPARE_PART)),
276
            new ShipRepairCost($neededSystemComponents, CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT))
277
        ];
278
    }
279
280
    #[Override]
281
    public function getPossibleTorpedoTypes(): array
282
    {
283
        if ($this->spacecraft->hasSpacecraftSystem(SpacecraftSystemTypeEnum::TORPEDO_STORAGE)) {
284
            return $this->torpedoTypeRepository->getAll();
285
        }
286
287
        return $this->torpedoTypeRepository->getByLevel($this->spacecraft->getRump()->getTorpedoLevel());
288
    }
289
290
    #[Override]
291
    public function getTractoredShipWrapper(): ?ShipWrapperInterface
292
    {
293
        $tractoredShip = $this->spacecraft->getTractoredShip();
294
        if ($tractoredShip === null) {
295
            return null;
296
        }
297
298
        return $this->spacecraftWrapperFactory->wrapShip($tractoredShip);
299
    }
300
301 4
    #[Override]
302
    public function getStateIconAndTitle(): ?array
303
    {
304 4
        return $this->stateIconAndTitle->getStateIconAndTitle($this);
305
    }
306
307
    #[Override]
308
    public function getTakeoverTicksLeft(?ShipTakeoverInterface $takeover = null): int
309
    {
310
        $takeover ??= $this->spacecraft->getTakeoverActive();
311
        if ($takeover === null) {
312
            throw new RuntimeException('should not call when active takeover is null');
313
        }
314
315
        $currentTurn = $this->game->getCurrentRound()->getTurn();
316
317
        return $takeover->getStartTurn() + ShipTakeoverManagerInterface::TURNS_TO_TAKEOVER - $currentTurn;
318
    }
319
320 6
    #[Override]
321
    public function getCrewStyle(): string
322
    {
323 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...
324 6
        $excessCrew = $ship->getExcessCrewCount();
325
326 6
        if ($excessCrew === 0) {
327 5
            return "";
328
        }
329
330 3
        return $excessCrew > 0 ? "color: green;" : "color: red;";
331
    }
332
333 9
    #[Override]
334
    public function getHullSystemData(): HullSystemData
335
    {
336 9
        $hullSystemData = $this->getSpecificShipSystem(
337 9
            SpacecraftSystemTypeEnum::HULL,
338 9
            HullSystemData::class
339 9
        );
340
341 9
        if ($hullSystemData === null) {
342
            throw new SystemNotFoundException('no hull installed?');
343
        }
344
345 9
        return $hullSystemData;
346
    }
347
348 8
    #[Override]
349
    public function getShieldSystemData(): ?ShieldSystemData
350
    {
351 8
        return $this->getSpecificShipSystem(
352 8
            SpacecraftSystemTypeEnum::SHIELDS,
353 8
            ShieldSystemData::class
354 8
        );
355
    }
356
357 18
    #[Override]
358
    public function getEpsSystemData(): ?EpsSystemData
359
    {
360 18
        return $this->getSpecificShipSystem(
361 18
            SpacecraftSystemTypeEnum::EPS,
362 18
            EpsSystemData::class
363 18
        );
364
    }
365
366 4
    #[Override]
367
    public function getWarpDriveSystemData(): ?WarpDriveSystemData
368
    {
369 4
        return $this->getSpecificShipSystem(
370 4
            SpacecraftSystemTypeEnum::WARPDRIVE,
371 4
            WarpDriveSystemData::class
372 4
        );
373
    }
374
375 1
    #[Override]
376
    public function getProjectileLauncherSystemData(): ?ProjectileLauncherSystemData
377
    {
378 1
        return $this->getSpecificShipSystem(
379 1
            SpacecraftSystemTypeEnum::TORPEDO,
380 1
            ProjectileLauncherSystemData::class
381 1
        );
382
    }
383
384
    /**
385
     * @template T2
386
     * @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...
387
     *
388
     * @return T2|null
389
     */
390 22
    protected function getSpecificShipSystem(SpacecraftSystemTypeEnum $systemType, string $className)
391
    {
392 22
        return $this->systemDataDeserializer->getSpecificShipSystem(
393 22
            $this->spacecraft,
394 22
            $systemType,
395 22
            $className,
396 22
            $this->shipSystemDataCache,
397 22
            $this->spacecraftWrapperFactory
398 22
        );
399
    }
400
401
    #[Override]
402
    public function __toString(): string
403
    {
404
        $systems = implode(",\n", $this->spacecraft->getSystems()
405
            ->filter(fn($system): bool => $system->getData() !== null)
406
            ->map(fn($system): string => $system->__toString())
407
            ->toArray());
408
409
        return sprintf(
410
            "spacecraft: {%s,\n  systems: [\n%s\n}\n]",
411
            $this->spacecraft->__toString(),
412
            $systems
413
        );
414
    }
415
}
416