Passed
Pull Request — master (#2027)
by Janko
10:08
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
        $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 7
    #[Override]
188
    public function getShieldRegenerationRate(): int
189
    {
190 7
        $regenerationPercentage = $this->get()->isSystemHealthy(SpacecraftSystemTypeEnum::SHIELDS) ? 10 : 0;
191
192 7
        return (int) ceil(($this->get()->getMaxShield() / 100) * $regenerationPercentage);
193
    }
194
195
    /**
196
     * highest damage first, then prio
197
     *
198
     * @return SpacecraftSystemInterface[]
199
     */
200 3
    #[Override]
201
    public function getDamagedSystems(): array
202
    {
203 3
        $damagedSystems = [];
204 3
        $prioArray = [];
205 3
        foreach ($this->spacecraft->getSystems() as $system) {
206 2
            if ($system->getStatus() < 100) {
207
                $damagedSystems[] = $system;
208
                $prioArray[$system->getSystemType()->value] = $this->spacecraftSystemManager->lookupSystem($system->getSystemType())->getPriority();
209
            }
210
        }
211
212
        // sort by damage and priority
213 3
        usort(
214 3
            $damagedSystems,
215 3
            function (SpacecraftSystemInterface $a, SpacecraftSystemInterface $b) use ($prioArray): int {
216
                if ($a->getStatus() === $b->getStatus()) {
217
                    return $prioArray[$b->getSystemType()->value] <=> $prioArray[$a->getSystemType()->value];
218
                }
219
                return ($a->getStatus() < $b->getStatus()) ? -1 : 1;
220 3
            }
221 3
        );
222
223 3
        return $damagedSystems;
224
    }
225
226 9
    #[Override]
227
    public function isSelectable(): bool
228
    {
229 9
        return $this->game->getUser() === $this->spacecraft->getUser()
230 9
            && $this->spacecraft->getType()->getModuleView() !== null;
231
    }
232
233 2
    #[Override]
234
    public function canBeRepaired(): bool
235
    {
236 2
        if ($this->spacecraft->getAlertState() !== SpacecraftAlertStateEnum::ALERT_GREEN) {
237
            return false;
238
        }
239
240 2
        if ($this->spacecraft->getShieldState()) {
241
            return false;
242
        }
243
244 2
        if ($this->spacecraft->isCloaked()) {
245
            return false;
246
        }
247
248 2
        if ($this->getDamagedSystems() !== []) {
249
            return true;
250
        }
251
252 2
        return $this->spacecraft->getHull() < $this->spacecraft->getMaxHull();
253
    }
254
255 4
    #[Override]
256
    public function canFire(): bool
257
    {
258 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...
259 4
        if (!$ship->getNbs()) {
260 1
            return false;
261
        }
262 3
        if (!$ship->hasActiveWeapon()) {
263 1
            return false;
264
        }
265
266 2
        $epsSystem = $this->getEpsSystemData();
267 2
        return $epsSystem !== null && $epsSystem->getEps() !== 0;
268
    }
269
270
    #[Override]
271
    public function getRepairDuration(): int
272
    {
273
        return $this->repairUtil->getRepairDuration($this);
274
    }
275
276
    #[Override]
277
    public function getRepairDurationPreview(): int
278
    {
279
        return $this->repairUtil->getRepairDurationPreview($this);
280
    }
281
282
    #[Override]
283
    public function getRepairCosts(): array
284
    {
285
        $neededParts = $this->repairUtil->determineSpareParts($this, false);
286
287
        $neededSpareParts = $neededParts[CommodityTypeEnum::COMMODITY_SPARE_PART];
288
        $neededSystemComponents = $neededParts[CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT];
289
290
        return [
291
            new ShipRepairCost($neededSpareParts, CommodityTypeEnum::COMMODITY_SPARE_PART, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SPARE_PART)),
292
            new ShipRepairCost($neededSystemComponents, CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT))
293
        ];
294
    }
295
296
    #[Override]
297
    public function getPossibleTorpedoTypes(): array
298
    {
299
        if ($this->spacecraft->hasSpacecraftSystem(SpacecraftSystemTypeEnum::TORPEDO_STORAGE)) {
300
            return $this->torpedoTypeRepository->getAll();
301
        }
302
303
        return $this->torpedoTypeRepository->getByLevel($this->spacecraft->getRump()->getTorpedoLevel());
304
    }
305
306
    #[Override]
307
    public function getTractoredShipWrapper(): ?ShipWrapperInterface
308
    {
309
        $tractoredShip = $this->spacecraft->getTractoredShip();
310
        if ($tractoredShip === null) {
311
            return null;
312
        }
313
314
        return $this->spacecraftWrapperFactory->wrapShip($tractoredShip);
315
    }
316
317 4
    #[Override]
318
    public function getStateIconAndTitle(): ?array
319
    {
320 4
        return $this->stateIconAndTitle->getStateIconAndTitle($this);
321
    }
322
323
    #[Override]
324
    public function getTakeoverTicksLeft(?ShipTakeoverInterface $takeover = null): int
325
    {
326
        $takeover ??= $this->spacecraft->getTakeoverActive();
327
        if ($takeover === null) {
328
            throw new RuntimeException('should not call when active takeover is null');
329
        }
330
331
        $currentTurn = $this->game->getCurrentRound()->getTurn();
332
333
        return $takeover->getStartTurn() + ShipTakeoverManagerInterface::TURNS_TO_TAKEOVER - $currentTurn;
334
    }
335
336 6
    #[Override]
337
    public function getCrewStyle(): string
338
    {
339 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...
340 6
        $excessCrew = $ship->getExcessCrewCount();
341
342 6
        if ($excessCrew === 0) {
343 5
            return "";
344
        }
345
346 3
        return $excessCrew > 0 ? "color: green;" : "color: red;";
347
    }
348
349 9
    #[Override]
350
    public function getHullSystemData(): HullSystemData
351
    {
352 9
        $hullSystemData = $this->getSpecificShipSystem(
353 9
            SpacecraftSystemTypeEnum::HULL,
354 9
            HullSystemData::class
355 9
        );
356
357 9
        if ($hullSystemData === null) {
358
            throw new SystemNotFoundException('no hull installed?');
359
        }
360
361 9
        return $hullSystemData;
362
    }
363
364 8
    #[Override]
365
    public function getShieldSystemData(): ?ShieldSystemData
366
    {
367 8
        return $this->getSpecificShipSystem(
368 8
            SpacecraftSystemTypeEnum::SHIELDS,
369 8
            ShieldSystemData::class
370 8
        );
371
    }
372
373 18
    #[Override]
374
    public function getEpsSystemData(): ?EpsSystemData
375
    {
376 18
        return $this->getSpecificShipSystem(
377 18
            SpacecraftSystemTypeEnum::EPS,
378 18
            EpsSystemData::class
379 18
        );
380
    }
381
382 2
    #[Override]
383
    public function getLssSystemData(): ?LssSystemData
384
    {
385 2
        return $this->getSpecificShipSystem(
386 2
            SpacecraftSystemTypeEnum::LSS,
387 2
            LssSystemData::class
388 2
        );
389
    }
390
391 4
    #[Override]
392
    public function getWarpDriveSystemData(): ?WarpDriveSystemData
393
    {
394 4
        return $this->getSpecificShipSystem(
395 4
            SpacecraftSystemTypeEnum::WARPDRIVE,
396 4
            WarpDriveSystemData::class
397 4
        );
398
    }
399
400 1
    #[Override]
401
    public function getProjectileLauncherSystemData(): ?ProjectileLauncherSystemData
402
    {
403 1
        return $this->getSpecificShipSystem(
404 1
            SpacecraftSystemTypeEnum::TORPEDO,
405 1
            ProjectileLauncherSystemData::class
406 1
        );
407
    }
408
409
    /**
410
     * @template T2
411
     * @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...
412
     *
413
     * @return T2|null
414
     */
415 22
    protected function getSpecificShipSystem(SpacecraftSystemTypeEnum $systemType, string $className)
416
    {
417 22
        return $this->systemDataDeserializer->getSpecificShipSystem(
418 22
            $this->spacecraft,
419 22
            $systemType,
420 22
            $className,
421 22
            $this->shipSystemDataCache,
422 22
            $this->spacecraftWrapperFactory
423 22
        );
424
    }
425
426
    #[Override]
427
    public function __toString(): string
428
    {
429
        $systems = implode(",\n", $this->spacecraft->getSystems()
430
            ->filter(fn($system): bool => $system->getData() !== null)
431
            ->map(fn($system): string => $system->__toString())
432
            ->toArray());
433
434
        return sprintf(
435
            "spacecraft: {%s,\n  systems: [\n%s\n}\n]",
436
            $this->spacecraft->__toString(),
437
            $systems
438
        );
439
    }
440
}
441