Passed
Push — master ( 996fbb...d0c183 )
by Nico
44:00 queued 29:21
created

SpacecraftWrapper::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 9
dl 0
loc 12
ccs 2
cts 2
cp 1
crap 1
rs 10

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\FusionCoreSystemData;
15
use Stu\Component\Spacecraft\System\Data\SingularityCoreSystemData;
16
use Stu\Component\Spacecraft\System\Data\WarpCoreSystemData;
17
use Stu\Component\Spacecraft\System\SpacecraftSystemManagerInterface;
18
use Stu\Component\Spacecraft\System\SpacecraftSystemTypeEnum;
19
use Stu\Component\Spacecraft\System\SystemDataDeserializerInterface;
20
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...
21
use Stu\Module\Control\GameControllerInterface;
22
use Stu\Module\Spacecraft\Lib\Interaction\ShipTakeoverManagerInterface;
23
use Stu\Module\Spacecraft\Lib\ReactorWrapper;
24
use Stu\Module\Spacecraft\Lib\ReactorWrapperInterface;
25
use Stu\Module\Spacecraft\Lib\ShipRepairCost;
26
use Stu\Module\Spacecraft\Lib\SpacecraftStateChangerInterface;
27
use Stu\Module\Spacecraft\Lib\SpacecraftWrapperFactoryInterface;
28
use Stu\Module\Ship\Lib\ShipWrapperInterface;
29
use Stu\Module\Spacecraft\Lib\Ui\StateIconAndTitle;
30
use Stu\Orm\Entity\SpacecraftSystemInterface;
31
use Stu\Orm\Entity\ShipTakeoverInterface;
32
use Stu\Orm\Entity\SpacecraftInterface;
33
use Stu\Orm\Repository\TorpedoTypeRepositoryInterface;
34
35
//TODO increase coverage
36
/**
37
 * @template T of SpacecraftInterface
38
 */
39
abstract class SpacecraftWrapper implements SpacecraftWrapperInterface
40
{
41
    use SpacecraftWrapperSystemDataTrait;
42
43
    /** @var Collection<int, AbstractSystemData> */
44
    private Collection $shipSystemDataCache;
45
46
    private ?ReactorWrapperInterface $reactorWrapper = null;
47
48
    private ?int $epsUsage = null;
49
50
    /**
51
     * @param T $spacecraft
52
     */
53 66
    public function __construct(
54
        protected SpacecraftInterface $spacecraft,
55
        private SpacecraftSystemManagerInterface $spacecraftSystemManager,
56
        private SystemDataDeserializerInterface $systemDataDeserializer,
57
        private TorpedoTypeRepositoryInterface $torpedoTypeRepository,
58
        protected GameControllerInterface $game,
59
        protected SpacecraftWrapperFactoryInterface $spacecraftWrapperFactory,
60
        private SpacecraftStateChangerInterface $spacecraftStateChanger,
61
        private RepairUtilInterface $repairUtil,
62
        private StateIconAndTitle $stateIconAndTitle
63
    ) {
64 66
        $this->shipSystemDataCache = new ArrayCollection();
65
    }
66
67
    #[Override]
68
    public function get(): SpacecraftInterface
69
    {
70
        return $this->spacecraft;
71
    }
72
73
    #[Override]
74
    public function getSpacecraftWrapperFactory(): SpacecraftWrapperFactoryInterface
75
    {
76
        return $this->spacecraftWrapperFactory;
77
    }
78
79
    #[Override]
80
    public function getSpacecraftSystemManager(): SpacecraftSystemManagerInterface
81
    {
82
        return $this->spacecraftSystemManager;
83
    }
84
85 3
    #[Override]
86
    public function getEpsUsage(): int
87
    {
88 3
        if ($this->epsUsage === null) {
89 3
            $this->epsUsage = $this->reloadEpsUsage();
90
        }
91 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...
92
    }
93
94
    #[Override]
95
    public function lowerEpsUsage(int $value): void
96
    {
97
        $this->epsUsage -= $value;
98
    }
99
100 3
    private function reloadEpsUsage(): int
101
    {
102 3
        $result = 0;
103
104 3
        foreach ($this->spacecraftSystemManager->getActiveSystems($this->spacecraft) as $shipSystem) {
105 3
            $result += $this->spacecraftSystemManager->getEnergyConsumption($shipSystem->getSystemType());
106
        }
107
108 3
        return $this->get()->hasComputer()
109 3
            ? $result + $this->getComputerSystemDataMandatory()->getAlertState()->getEpsUsage()
110 3
            : $result;
111
    }
112
113 2
    public function getReactorUsage(): int
114
    {
115 2
        $reactor = $this->reactorWrapper;
116 2
        if ($reactor === null) {
117
            throw new RuntimeException('this should not happen');
118
        }
119
120 2
        return $this->getEpsUsage() + $reactor->getUsage();
121
    }
122
123 9
    #[Override]
124
    public function getReactorWrapper(): ?ReactorWrapperInterface
125
    {
126 9
        if ($this->reactorWrapper === null) {
127 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...
128 9
            $reactorSystemData = null;
129
130
131 9
            if ($ship->hasSpacecraftSystem(SpacecraftSystemTypeEnum::WARPCORE)) {
132 5
                $reactorSystemData = $this->getSpecificShipSystem(
133 5
                    SpacecraftSystemTypeEnum::WARPCORE,
134 5
                    WarpCoreSystemData::class
135 5
                );
136
            }
137 9
            if ($ship->hasSpacecraftSystem(SpacecraftSystemTypeEnum::SINGULARITY_REACTOR)) {
138
                $reactorSystemData = $this->getSpecificShipSystem(
139
                    SpacecraftSystemTypeEnum::SINGULARITY_REACTOR,
140
                    SingularityCoreSystemData::class
141
                );
142
            }
143 9
            if ($ship->hasSpacecraftSystem(SpacecraftSystemTypeEnum::FUSION_REACTOR)) {
144
                $reactorSystemData = $this->getSpecificShipSystem(
145
                    SpacecraftSystemTypeEnum::FUSION_REACTOR,
146
                    FusionCoreSystemData::class
147
                );
148
            }
149
150 9
            if ($reactorSystemData === null) {
151 6
                return null;
152
            }
153
154 5
            $this->reactorWrapper = new ReactorWrapper($this, $reactorSystemData);
155
        }
156
157 5
        return $this->reactorWrapper;
158
    }
159
160 3
    #[Override]
161
    public function getAlertState(): SpacecraftAlertStateEnum
162
    {
163 3
        return $this->getComputerSystemDataMandatory()->getAlertState();
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 2
    #[Override]
176
    public function isUnalerted(): bool
177
    {
178 2
        return !$this->spacecraft->hasSpacecraftSystem(SpacecraftSystemTypeEnum::COMPUTER)
179 2
            || $this->getComputerSystemDataMandatory()->isAlertGreen();
180
    }
181
182 3
    #[Override]
183
    public function getShieldRegenerationRate(): int
184
    {
185 3
        $regenerationPercentage = $this->get()->isSystemHealthy(SpacecraftSystemTypeEnum::SHIELDS) ? 10 : 0;
186
187 3
        $shield = $this->get()->getCondition()->getShield();
188 3
        $maxshield = $this->get()->getMaxShield();
189
190 3
        $result = (int) ceil(($maxshield / 100) * $regenerationPercentage);
191
192 3
        if ($result > $maxshield - $shield) {
193 1
            $result = $maxshield - $shield;
194
        }
195
196 3
        return $result;
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 10
    #[Override]
231
    public function isSelectable(): bool
232
    {
233 10
        return $this->game->getUser() === $this->spacecraft->getUser()
234 10
            && $this->spacecraft->getType()->getModuleView() !== null;
235
    }
236
237 2
    #[Override]
238
    public function canBeRepaired(): bool
239
    {
240 2
        if (!$this->isUnalerted()) {
241
            return false;
242
        }
243
244 2
        if ($this->spacecraft->isShielded()) {
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->getCondition()->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 2
    #[Override]
275
    public function canMan(): bool
276
    {
277 2
        $buildplan = $this->spacecraft->getBuildplan();
278
279 2
        return $buildplan !== null
280 2
            && $buildplan->getCrew() > 0
281 2
            && $this->spacecraft->hasSpacecraftSystem(SpacecraftSystemTypeEnum::LIFE_SUPPORT);
282
    }
283
284
    #[Override]
285
    public function getRepairDuration(): int
286
    {
287
        return $this->repairUtil->getRepairDuration($this);
288
    }
289
290
    #[Override]
291
    public function getRepairDurationPreview(): int
292
    {
293
        return $this->repairUtil->getRepairDurationPreview($this);
294
    }
295
296
    #[Override]
297
    public function getRepairCosts(): array
298
    {
299
        $neededParts = $this->repairUtil->determineSpareParts($this, false);
300
301
        $neededSpareParts = $neededParts[CommodityTypeEnum::COMMODITY_SPARE_PART];
302
        $neededSystemComponents = $neededParts[CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT];
303
304
        return [
305
            new ShipRepairCost($neededSpareParts, CommodityTypeEnum::COMMODITY_SPARE_PART, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SPARE_PART)),
306
            new ShipRepairCost($neededSystemComponents, CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT))
307
        ];
308
    }
309
310
    #[Override]
311
    public function getPossibleTorpedoTypes(): array
312
    {
313
        if ($this->spacecraft->hasSpacecraftSystem(SpacecraftSystemTypeEnum::TORPEDO_STORAGE)) {
314
            return $this->torpedoTypeRepository->getAll();
315
        }
316
317
        return $this->torpedoTypeRepository->getByLevel($this->spacecraft->getRump()->getTorpedoLevel());
318
    }
319
320
    #[Override]
321
    public function getTractoredShipWrapper(): ?ShipWrapperInterface
322
    {
323
        $tractoredShip = $this->spacecraft->getTractoredShip();
324
        if ($tractoredShip === null) {
325
            return null;
326
        }
327
328
        return $this->spacecraftWrapperFactory->wrapShip($tractoredShip);
329
    }
330
331 4
    #[Override]
332
    public function getStateIconAndTitle(): ?array
333
    {
334 4
        return $this->stateIconAndTitle->getStateIconAndTitle($this);
335
    }
336
337
    #[Override]
338
    public function getTakeoverTicksLeft(?ShipTakeoverInterface $takeover = null): int
339
    {
340
        $takeover ??= $this->spacecraft->getTakeoverActive();
341
        if ($takeover === null) {
342
            throw new RuntimeException('should not call when active takeover is null');
343
        }
344
345
        $currentTurn = $this->game->getCurrentRound()->getTurn();
346
347
        return $takeover->getStartTurn() + ShipTakeoverManagerInterface::TURNS_TO_TAKEOVER - $currentTurn;
348
    }
349
350 6
    #[Override]
351
    public function getCrewStyle(): string
352
    {
353 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...
354 6
        $excessCrew = $ship->getExcessCrewCount();
355
356 6
        if ($excessCrew === 0) {
357 5
            return "";
358
        }
359
360 3
        return $excessCrew > 0 ? "color: green;" : "color: red;";
361
    }
362
363
    /**
364
     * @template T2
365
     * @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...
366
     *
367
     * @return T2|null
368
     */
369 26
    public function getSpecificShipSystem(SpacecraftSystemTypeEnum $systemType, string $className)
370
    {
371 26
        return $this->systemDataDeserializer->getSpecificShipSystem(
372 26
            $this->spacecraft,
373 26
            $systemType,
374 26
            $className,
375 26
            $this->shipSystemDataCache,
376 26
            $this->spacecraftWrapperFactory
377 26
        );
378
    }
379
380
    #[Override]
381
    public function __toString(): string
382
    {
383
        $systems = implode(",\n", $this->spacecraft->getSystems()
384
            ->filter(fn($system): bool => $system->getData() !== null)
385
            ->map(fn($system): string => $system->__toString())
386
            ->toArray());
387
388
        return sprintf(
389
            "spacecraft: {%s,\n  systems: [\n%s\n}\n]",
390
            $this->spacecraft->__toString(),
391
            $systems
392
        );
393
    }
394
}
395