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