Passed
Pull Request — master (#1969)
by Janko
22:34 queued 10:03
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 59
    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 59
        $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->hasShipSystem(SpacecraftSystemTypeEnum::SYSTEM_WARPCORE)) {
142 5
                $reactorSystemData = $this->getSpecificShipSystem(
143 5
                    SpacecraftSystemTypeEnum::SYSTEM_WARPCORE,
144 5
                    WarpCoreSystemData::class
145 5
                );
146
            }
147 9
            if ($ship->hasShipSystem(SpacecraftSystemTypeEnum::SYSTEM_SINGULARITY_REACTOR)) {
148
                $reactorSystemData = $this->getSpecificShipSystem(
149
                    SpacecraftSystemTypeEnum::SYSTEM_SINGULARITY_REACTOR,
150
                    SingularityCoreSystemData::class
151
                );
152
            }
153 9
            if ($ship->hasShipSystem(SpacecraftSystemTypeEnum::SYSTEM_FUSION_REACTOR)) {
154
                $reactorSystemData = $this->getSpecificShipSystem(
155
                    SpacecraftSystemTypeEnum::SYSTEM_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 isOwnedByCurrentUser(): bool
212
    {
213 9
        return $this->game->getUser() === $this->spacecraft->getUser();
214
    }
215
216 2
    #[Override]
217
    public function canBeRepaired(): bool
218
    {
219 2
        if ($this->spacecraft->getAlertState() !== SpacecraftAlertStateEnum::ALERT_GREEN) {
220
            return false;
221
        }
222
223 2
        if ($this->spacecraft->getShieldState()) {
224
            return false;
225
        }
226
227 2
        if ($this->spacecraft->getCloakState()) {
228
            return false;
229
        }
230
231 2
        if ($this->getDamagedSystems() !== []) {
232
            return true;
233
        }
234
235 2
        return $this->spacecraft->getHull() < $this->spacecraft->getMaxHull();
236
    }
237
238 4
    #[Override]
239
    public function canFire(): bool
240
    {
241 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...
242 4
        if (!$ship->getNbs()) {
243 1
            return false;
244
        }
245 3
        if (!$ship->hasActiveWeapon()) {
246 1
            return false;
247
        }
248
249 2
        $epsSystem = $this->getEpsSystemData();
250 2
        return $epsSystem !== null && $epsSystem->getEps() !== 0;
251
    }
252
253
    #[Override]
254
    public function getRepairDuration(): int
255
    {
256
        return $this->repairUtil->getRepairDuration($this);
257
    }
258
259
    #[Override]
260
    public function getRepairDurationPreview(): int
261
    {
262
        return $this->repairUtil->getRepairDurationPreview($this);
263
    }
264
265
    #[Override]
266
    public function getRepairCosts(): array
267
    {
268
        $neededParts = $this->repairUtil->determineSpareParts($this, false);
269
270
        $neededSpareParts = $neededParts[CommodityTypeEnum::COMMODITY_SPARE_PART];
271
        $neededSystemComponents = $neededParts[CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT];
272
273
        return [
274
            new ShipRepairCost($neededSpareParts, CommodityTypeEnum::COMMODITY_SPARE_PART, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SPARE_PART)),
275
            new ShipRepairCost($neededSystemComponents, CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT, CommodityTypeEnum::getDescription(CommodityTypeEnum::COMMODITY_SYSTEM_COMPONENT))
276
        ];
277
    }
278
279
    #[Override]
280
    public function getPossibleTorpedoTypes(): array
281
    {
282
        if ($this->spacecraft->hasShipSystem(SpacecraftSystemTypeEnum::SYSTEM_TORPEDO_STORAGE)) {
283
            return $this->torpedoTypeRepository->getAll();
284
        }
285
286
        return $this->torpedoTypeRepository->getByLevel($this->spacecraft->getRump()->getTorpedoLevel());
287
    }
288
289
    #[Override]
290
    public function getTractoredShipWrapper(): ?ShipWrapperInterface
291
    {
292
        $tractoredShip = $this->spacecraft->getTractoredShip();
293
        if ($tractoredShip === null) {
294
            return null;
295
        }
296
297
        return $this->spacecraftWrapperFactory->wrapShip($tractoredShip);
298
    }
299
300 4
    #[Override]
301
    public function getStateIconAndTitle(): ?array
302
    {
303 4
        return $this->stateIconAndTitle->getStateIconAndTitle($this);
304
    }
305
306
    #[Override]
307
    public function getTakeoverTicksLeft(?ShipTakeoverInterface $takeover = null): int
308
    {
309
        $takeover ??= $this->spacecraft->getTakeoverActive();
310
        if ($takeover === null) {
311
            throw new RuntimeException('should not call when active takeover is null');
312
        }
313
314
        $currentTurn = $this->game->getCurrentRound()->getTurn();
315
316
        return $takeover->getStartTurn() + ShipTakeoverManagerInterface::TURNS_TO_TAKEOVER - $currentTurn;
317
    }
318
319 6
    #[Override]
320
    public function getCrewStyle(): string
321
    {
322 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...
323 6
        $excessCrew = $ship->getExcessCrewCount();
324
325 6
        if ($excessCrew === 0) {
326 5
            return "";
327
        }
328
329 3
        return $excessCrew > 0 ? "color: green;" : "color: red;";
330
    }
331
332 9
    #[Override]
333
    public function getHullSystemData(): HullSystemData
334
    {
335 9
        $hullSystemData = $this->getSpecificShipSystem(
336 9
            SpacecraftSystemTypeEnum::SYSTEM_HULL,
337 9
            HullSystemData::class
338 9
        );
339
340 9
        if ($hullSystemData === null) {
341
            throw new SystemNotFoundException('no hull installed?');
342
        }
343
344 9
        return $hullSystemData;
345
    }
346
347 8
    #[Override]
348
    public function getShieldSystemData(): ?ShieldSystemData
349
    {
350 8
        return $this->getSpecificShipSystem(
351 8
            SpacecraftSystemTypeEnum::SYSTEM_SHIELDS,
352 8
            ShieldSystemData::class
353 8
        );
354
    }
355
356 18
    #[Override]
357
    public function getEpsSystemData(): ?EpsSystemData
358
    {
359 18
        return $this->getSpecificShipSystem(
360 18
            SpacecraftSystemTypeEnum::SYSTEM_EPS,
361 18
            EpsSystemData::class
362 18
        );
363
    }
364
365 4
    #[Override]
366
    public function getWarpDriveSystemData(): ?WarpDriveSystemData
367
    {
368 4
        return $this->getSpecificShipSystem(
369 4
            SpacecraftSystemTypeEnum::SYSTEM_WARPDRIVE,
370 4
            WarpDriveSystemData::class
371 4
        );
372
    }
373
374 1
    #[Override]
375
    public function getProjectileLauncherSystemData(): ?ProjectileLauncherSystemData
376
    {
377 1
        return $this->getSpecificShipSystem(
378 1
            SpacecraftSystemTypeEnum::SYSTEM_TORPEDO,
379 1
            ProjectileLauncherSystemData::class
380 1
        );
381
    }
382
383
    /**
384
     * @template T2
385
     * @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...
386
     *
387
     * @return T2|null
388
     */
389 19
    protected function getSpecificShipSystem(SpacecraftSystemTypeEnum $systemType, string $className)
390
    {
391 19
        return $this->systemDataDeserializer->getSpecificShipSystem(
392 19
            $this->spacecraft,
393 19
            $systemType,
394 19
            $className,
395 19
            $this->shipSystemDataCache,
396 19
            $this->spacecraftWrapperFactory
397 19
        );
398
    }
399
}
400