Passed
Push — master ( cc891d...b53f20 )
by Nico
11:42
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 63
    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 63
        $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
        if ($this->spacecraft->getAlertState() == SpacecraftAlertStateEnum::ALERT_YELLOW) {
115
            $result += SpacecraftStateChangerInterface::ALERT_YELLOW_EPS_USAGE;
116
        }
117 3
        if ($this->spacecraft->getAlertState() == SpacecraftAlertStateEnum::ALERT_RED) {
118
            $result += SpacecraftStateChangerInterface::ALERT_RED_EPS_USAGE;
119
        }
120
121 3
        return $result;
122
    }
123
124 2
    public function getReactorUsage(): int
125
    {
126 2
        $reactor = $this->reactorWrapper;
127 2
        if ($reactor === null) {
128
            throw new RuntimeException('this should not happen');
129
        }
130
131 2
        return $this->getEpsUsage() + $reactor->getUsage();
132
    }
133
134 9
    #[Override]
135
    public function getReactorWrapper(): ?ReactorWrapperInterface
136
    {
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 9
            $reactorSystemData = null;
140
141
142 9
            if ($ship->hasSpacecraftSystem(SpacecraftSystemTypeEnum::WARPCORE)) {
143 5
                $reactorSystemData = $this->getSpecificShipSystem(
144 5
                    SpacecraftSystemTypeEnum::WARPCORE,
145 5
                    WarpCoreSystemData::class
146 5
                );
147
            }
148 9
            if ($ship->hasSpacecraftSystem(SpacecraftSystemTypeEnum::SINGULARITY_REACTOR)) {
149
                $reactorSystemData = $this->getSpecificShipSystem(
150
                    SpacecraftSystemTypeEnum::SINGULARITY_REACTOR,
151
                    SingularityCoreSystemData::class
152
                );
153
            }
154 9
            if ($ship->hasSpacecraftSystem(SpacecraftSystemTypeEnum::FUSION_REACTOR)) {
155
                $reactorSystemData = $this->getSpecificShipSystem(
156
                    SpacecraftSystemTypeEnum::FUSION_REACTOR,
157
                    FusionCoreSystemData::class
158
                );
159
            }
160
161 9
            if ($reactorSystemData === null) {
162 6
                return null;
163
            }
164
165 5
            $this->reactorWrapper = new ReactorWrapper($this, $reactorSystemData);
166
        }
167
168 5
        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 1
    #[Override]
181
    public function getSensorRange(): int
182
    {
183 1
        $lssSystemData = $this->getLssSystemData();
184
185 1
        return $lssSystemData !== null
186 1
            ? $lssSystemData->getSensorRange()
187 1
            : 0;
188
    }
189
190
191 7
    #[Override]
192
    public function getShieldRegenerationRate(): int
193
    {
194 7
        $regenerationPercentage = $this->get()->isSystemHealthy(SpacecraftSystemTypeEnum::SHIELDS) ? 10 : 0;
195
196 7
        return (int) ceil(($this->get()->getMaxShield() / 100) * $regenerationPercentage);
197
    }
198
199
    /**
200
     * highest damage first, then prio
201
     *
202
     * @return SpacecraftSystemInterface[]
203
     */
204 3
    #[Override]
205
    public function getDamagedSystems(): array
206
    {
207 3
        $damagedSystems = [];
208 3
        $prioArray = [];
209 3
        foreach ($this->spacecraft->getSystems() as $system) {
210 2
            if ($system->getStatus() < 100) {
211
                $damagedSystems[] = $system;
212
                $prioArray[$system->getSystemType()->value] = $this->spacecraftSystemManager->lookupSystem($system->getSystemType())->getPriority();
213
            }
214
        }
215
216
        // sort by damage and priority
217 3
        usort(
218 3
            $damagedSystems,
219 3
            function (SpacecraftSystemInterface $a, SpacecraftSystemInterface $b) use ($prioArray): int {
220
                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 3
            }
225 3
        );
226
227 3
        return $damagedSystems;
228
    }
229
230 9
    #[Override]
231
    public function isSelectable(): bool
232
    {
233 9
        return $this->game->getUser() === $this->spacecraft->getUser()
234 9
            && $this->spacecraft->getType()->getModuleView() !== null;
235
    }
236
237 2
    #[Override]
238
    public function canBeRepaired(): bool
239
    {
240 2
        if ($this->spacecraft->getAlertState() !== SpacecraftAlertStateEnum::ALERT_GREEN) {
241
            return false;
242
        }
243
244 2
        if ($this->spacecraft->getShieldState()) {
245
            return false;
246
        }
247
248 2
        if ($this->spacecraft->isCloaked()) {
249
            return false;
250
        }
251
252 2
        if ($this->getDamagedSystems() !== []) {
253
            return true;
254
        }
255
256 2
        return $this->spacecraft->getHull() < $this->spacecraft->getMaxHull();
257
    }
258
259 4
    #[Override]
260
    public function canFire(): bool
261
    {
262 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...
263 4
        if (!$ship->getNbs()) {
264 1
            return false;
265
        }
266 3
        if (!$ship->hasActiveWeapon()) {
267 1
            return false;
268
        }
269
270 2
        $epsSystem = $this->getEpsSystemData();
271 2
        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
    public function getPossibleTorpedoTypes(): array
302
    {
303
        if ($this->spacecraft->hasSpacecraftSystem(SpacecraftSystemTypeEnum::TORPEDO_STORAGE)) {
304
            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
321 4
    #[Override]
322
    public function getStateIconAndTitle(): ?array
323
    {
324 4
        return $this->stateIconAndTitle->getStateIconAndTitle($this);
325
    }
326
327
    #[Override]
328
    public function getTakeoverTicksLeft(?ShipTakeoverInterface $takeover = null): int
329
    {
330
        $takeover ??= $this->spacecraft->getTakeoverActive();
331
        if ($takeover === null) {
332
            throw new RuntimeException('should not call when active takeover is null');
333
        }
334
335
        $currentTurn = $this->game->getCurrentRound()->getTurn();
336
337
        return $takeover->getStartTurn() + ShipTakeoverManagerInterface::TURNS_TO_TAKEOVER - $currentTurn;
338
    }
339
340 6
    #[Override]
341
    public function getCrewStyle(): string
342
    {
343 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...
344 6
        $excessCrew = $ship->getExcessCrewCount();
345
346 6
        if ($excessCrew === 0) {
347 5
            return "";
348
        }
349
350 3
        return $excessCrew > 0 ? "color: green;" : "color: red;";
351
    }
352
353 9
    #[Override]
354
    public function getHullSystemData(): HullSystemData
355
    {
356 9
        $hullSystemData = $this->getSpecificShipSystem(
357 9
            SpacecraftSystemTypeEnum::HULL,
358 9
            HullSystemData::class
359 9
        );
360
361 9
        if ($hullSystemData === null) {
362
            throw new SystemNotFoundException('no hull installed?');
363
        }
364
365 9
        return $hullSystemData;
366
    }
367
368 8
    #[Override]
369
    public function getShieldSystemData(): ?ShieldSystemData
370
    {
371 8
        return $this->getSpecificShipSystem(
372 8
            SpacecraftSystemTypeEnum::SHIELDS,
373 8
            ShieldSystemData::class
374 8
        );
375
    }
376
377 18
    #[Override]
378
    public function getEpsSystemData(): ?EpsSystemData
379
    {
380 18
        return $this->getSpecificShipSystem(
381 18
            SpacecraftSystemTypeEnum::EPS,
382 18
            EpsSystemData::class
383 18
        );
384
    }
385
386 2
    #[Override]
387
    public function getLssSystemData(): ?LssSystemData
388
    {
389 2
        return $this->getSpecificShipSystem(
390 2
            SpacecraftSystemTypeEnum::LSS,
391 2
            LssSystemData::class
392 2
        );
393
    }
394
395 4
    #[Override]
396
    public function getWarpDriveSystemData(): ?WarpDriveSystemData
397
    {
398 4
        return $this->getSpecificShipSystem(
399 4
            SpacecraftSystemTypeEnum::WARPDRIVE,
400 4
            WarpDriveSystemData::class
401 4
        );
402
    }
403
404 1
    #[Override]
405
    public function getProjectileLauncherSystemData(): ?ProjectileLauncherSystemData
406
    {
407 1
        return $this->getSpecificShipSystem(
408 1
            SpacecraftSystemTypeEnum::TORPEDO,
409 1
            ProjectileLauncherSystemData::class
410 1
        );
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 22
    protected function getSpecificShipSystem(SpacecraftSystemTypeEnum $systemType, string $className)
420
    {
421 22
        return $this->systemDataDeserializer->getSpecificShipSystem(
422 22
            $this->spacecraft,
423 22
            $systemType,
424 22
            $className,
425 22
            $this->shipSystemDataCache,
426 22
            $this->spacecraftWrapperFactory
427 22
        );
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