SpacecraftWrapper::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
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 11
dl 0
loc 14
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 BadMethodCallException;
8
use Doctrine\Common\Collections\ArrayCollection;
9
use Doctrine\Common\Collections\Collection;
10
use Stu\Component\Spacecraft\Repair\RepairUtilInterface;
11
use Stu\Component\Spacecraft\SpacecraftAlertStateEnum;
12
use Stu\Component\Spacecraft\System\Data\AbstractSystemData;
13
use Stu\Component\Spacecraft\System\SpacecraftSystemManagerInterface;
14
use Stu\Component\Spacecraft\System\SpacecraftSystemTypeEnum;
15
use Stu\Component\Spacecraft\System\SystemDataDeserializerInterface;
16
use Stu\Module\Colony\Lib\ColonyLibFactoryInterface;
17
use Stu\Module\Commodity\CommodityTypeConstants;
0 ignored issues
show
Bug introduced by
The type Stu\Module\Commodity\CommodityTypeConstants 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...
18
use Stu\Module\Control\GameControllerInterface;
19
use Stu\Module\Spacecraft\Lib\Interaction\ShipTakeoverManagerInterface;
20
use Stu\Module\Spacecraft\Lib\ReactorWrapperInterface;
21
use Stu\Module\Spacecraft\Lib\ShipRepairCost;
22
use Stu\Module\Spacecraft\Lib\SpacecraftStateChangerInterface;
23
use Stu\Module\Spacecraft\Lib\SpacecraftWrapperFactoryInterface;
24
use Stu\Module\Ship\Lib\ShipWrapperInterface;
25
use Stu\Module\Spacecraft\Lib\Reactor\ReactorWrapperFactoryInterface;
26
use Stu\Module\Spacecraft\Lib\Ui\StateIconAndTitle;
27
use Stu\Orm\Entity\SpacecraftSystem;
28
use Stu\Orm\Entity\ShipTakeover;
29
use Stu\Orm\Entity\Spacecraft;
30
use Stu\Orm\Repository\TorpedoTypeRepositoryInterface;
31
32
//TODO increase coverage
33
/**
34
 * @template T of Spacecraft
35
 */
36
abstract class SpacecraftWrapper implements SpacecraftWrapperInterface
37
{
38
    use SpacecraftWrapperSystemDataTrait;
39
40
    /** @var Collection<int, AbstractSystemData> */
41
    private Collection $shipSystemDataCache;
42
43
    private ?ReactorWrapperInterface $reactorWrapper = null;
44
45
    private ?int $epsUsage = null;
46
47
    /**
48
     * @param T $spacecraft
49
     */
50 183
    public function __construct(
51
        protected readonly Spacecraft $spacecraft,
52
        private readonly SpacecraftSystemManagerInterface $spacecraftSystemManager,
53
        private readonly SystemDataDeserializerInterface $systemDataDeserializer,
54
        private readonly TorpedoTypeRepositoryInterface $torpedoTypeRepository,
55
        protected readonly GameControllerInterface $game,
56
        protected readonly SpacecraftWrapperFactoryInterface $spacecraftWrapperFactory,
57
        private readonly ReactorWrapperFactoryInterface $reactorWrapperFactory,
58
        private readonly SpacecraftStateChangerInterface $spacecraftStateChanger,
59
        private readonly RepairUtilInterface $repairUtil,
60
        private readonly StateIconAndTitle $stateIconAndTitle,
61
        protected readonly ColonyLibFactoryInterface $colonyLibFactory
62
    ) {
63 183
        $this->shipSystemDataCache = new ArrayCollection();
64
    }
65
66
    #[\Override]
67
    public function get(): Spacecraft
68
    {
69
        return $this->spacecraft;
70
    }
71
72 2
    #[\Override]
73
    public function getSpacecraftWrapperFactory(): SpacecraftWrapperFactoryInterface
74
    {
75 2
        return $this->spacecraftWrapperFactory;
76
    }
77
78 2
    #[\Override]
79
    public function getSpacecraftSystemManager(): SpacecraftSystemManagerInterface
80
    {
81 2
        return $this->spacecraftSystemManager;
82
    }
83
84 8
    #[\Override]
85
    public function getEpsUsage(): int
86
    {
87 8
        if ($this->epsUsage === null) {
88 8
            $this->epsUsage = $this->reloadEpsUsage();
89
        }
90 8
        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...
91
    }
92
93
    #[\Override]
94
    public function lowerEpsUsage(int $value): void
95
    {
96
        $this->epsUsage -= $value;
97
    }
98
99 15
    private function reloadEpsUsage(): int
100
    {
101 15
        $result = 0;
102
103 15
        foreach ($this->spacecraftSystemManager->getActiveSystems($this->spacecraft) as $shipSystem) {
104 15
            $result += $this->spacecraftSystemManager->getEnergyConsumption($shipSystem->getSystemType());
105
        }
106
107 15
        return $this->get()->hasComputer()
108 15
            ? $result + $this->getComputerSystemDataMandatory()->getAlertState()->getEpsUsage()
109 15
            : $result;
110
    }
111
112 4
    public function getReactorUsage(): int
113
    {
114 4
        $reactor = $this->reactorWrapper;
115 4
        if ($reactor === null) {
116
            throw new BadMethodCallException('this should not happen');
117
        }
118
119 4
        return $this->getEpsUsage() + $reactor->getUsage();
120
    }
121
122 18
    #[\Override]
123
    public function getReactorWrapper(): ?ReactorWrapperInterface
124
    {
125 18
        if ($this->reactorWrapper === null) {
126 18
            $this->reactorWrapper = $this->reactorWrapperFactory->createReactorWrapper($this);
127
        }
128
129 18
        return $this->reactorWrapper;
130
    }
131
132 21
    #[\Override]
133
    public function getAlertState(): SpacecraftAlertStateEnum
134
    {
135 21
        return $this->getComputerSystemDataMandatory()->getAlertState();
136
    }
137
138 8
    #[\Override]
139
    public function setAlertState(SpacecraftAlertStateEnum $alertState): ?string
140
    {
141 8
        $msg = $this->spacecraftStateChanger->changeAlertState($this, $alertState);
142 8
        $this->epsUsage = $this->reloadEpsUsage();
143
144 8
        return $msg;
145
    }
146
147 8
    #[\Override]
148
    public function isUnalerted(): bool
149
    {
150 8
        return !$this->spacecraft->hasSpacecraftSystem(SpacecraftSystemTypeEnum::COMPUTER)
151 8
            || $this->getComputerSystemDataMandatory()->isAlertGreen();
152
    }
153
154 3
    #[\Override]
155
    public function getShieldRegenerationRate(): int
156
    {
157 3
        $regenerationPercentage = $this->get()->isSystemHealthy(SpacecraftSystemTypeEnum::SHIELDS) ? 10 : 0;
158
159 3
        $shield = $this->get()->getCondition()->getShield();
160 3
        $maxshield = $this->get()->getMaxShield();
161
162 3
        $result = (int) ceil(($maxshield / 100) * $regenerationPercentage);
163
164 3
        if ($result > $maxshield - $shield) {
165 1
            $result = $maxshield - $shield;
166
        }
167
168 3
        return $result;
169
    }
170
171
    /**
172
     * highest damage first, then prio
173
     *
174
     * @return SpacecraftSystem[]
175
     */
176 1
    #[\Override]
177
    public function getDamagedSystems(): array
178
    {
179 1
        $damagedSystems = [];
180 1
        $prioArray = [];
181 1
        foreach ($this->spacecraft->getSystems() as $system) {
182 1
            if ($system->getStatus() < 100) {
183
                $damagedSystems[] = $system;
184
                $prioArray[$system->getSystemType()->value] = $system->getSystemType()->getPriority();
185
            }
186
        }
187
188
        // sort by damage and priority
189 1
        usort(
190 1
            $damagedSystems,
191 1
            function (SpacecraftSystem $a, SpacecraftSystem $b) use ($prioArray): int {
192
                if ($a->getStatus() === $b->getStatus()) {
193
                    return $prioArray[$b->getSystemType()->value] <=> $prioArray[$a->getSystemType()->value];
194
                }
195
                return ($a->getStatus() < $b->getStatus()) ? -1 : 1;
196 1
            }
197 1
        );
198
199 1
        return $damagedSystems;
200
    }
201
202 10
    #[\Override]
203
    public function isSelectable(): bool
204
    {
205 10
        return $this->game->getUser()->getId() === $this->spacecraft->getUser()->getId()
206 10
            && $this->spacecraft->getType()->getModuleView() !== null;
207
    }
208
209 3
    #[\Override]
210
    public function canBeRepaired(): bool
211
    {
212 3
        if (!$this->isUnalerted()) {
213 3
            return false;
214
        }
215
216
        if ($this->spacecraft->isShielded()) {
217
            return false;
218
        }
219
220
        if ($this->spacecraft->isCloaked()) {
221
            return false;
222
        }
223
224
        if ($this->getDamagedSystems() !== []) {
225
            return true;
226
        }
227
228
        return $this->spacecraft->getCondition()->getHull() < $this->spacecraft->getMaxHull();
229
    }
230
231 7
    #[\Override]
232
    public function canFire(): bool
233
    {
234 7
        $ship = $this->spacecraft;
235 7
        if (!$ship->getNbs()) {
236 4
            return false;
237
        }
238 4
        if (!$ship->hasActiveWeapon()) {
239 1
            return false;
240
        }
241
242 3
        $epsSystem = $this->getEpsSystemData();
243 3
        return $epsSystem !== null && $epsSystem->getEps() !== 0;
244
    }
245
246 2
    #[\Override]
247
    public function canMan(): bool
248
    {
249 2
        $buildplan = $this->spacecraft->getBuildplan();
250
251 2
        return $buildplan !== null
252 2
            && $buildplan->getCrew() > 0
253 2
            && $this->spacecraft->hasSpacecraftSystem(SpacecraftSystemTypeEnum::LIFE_SUPPORT);
254
    }
255
256
    #[\Override]
257
    public function getRepairDuration(): int
258
    {
259
        return $this->repairUtil->getRepairDuration($this);
260
    }
261
262
    #[\Override]
263
    public function getRepairDurationPreview(): int
264
    {
265
        return $this->repairUtil->getRepairDurationPreview($this);
266
    }
267
268
    #[\Override]
269
    public function getRepairCosts(): array
270
    {
271
        $neededParts = $this->repairUtil->determineSpareParts($this, false);
272
273
        $neededSpareParts = $neededParts[CommodityTypeConstants::COMMODITY_SPARE_PART];
274
        $neededSystemComponents = $neededParts[CommodityTypeConstants::COMMODITY_SYSTEM_COMPONENT];
275
276
        return [
277
            new ShipRepairCost($neededSpareParts, CommodityTypeConstants::COMMODITY_SPARE_PART, CommodityTypeConstants::getDescription(CommodityTypeConstants::COMMODITY_SPARE_PART)),
278
            new ShipRepairCost($neededSystemComponents, CommodityTypeConstants::COMMODITY_SYSTEM_COMPONENT, CommodityTypeConstants::getDescription(CommodityTypeConstants::COMMODITY_SYSTEM_COMPONENT))
279
        ];
280
    }
281
282
    #[\Override]
283
    public function getPossibleTorpedoTypes(): array
284
    {
285
        if ($this->spacecraft->hasSpacecraftSystem(SpacecraftSystemTypeEnum::TORPEDO_STORAGE)) {
286
            return $this->torpedoTypeRepository->getAll();
287
        }
288
289
        return $this->torpedoTypeRepository->getByLevel($this->spacecraft->getRump()->getTorpedoLevel());
290
    }
291
292 6
    #[\Override]
293
    public function getTractoredShipWrapper(): ?ShipWrapperInterface
294
    {
295 6
        $tractoredShip = $this->spacecraft->getTractoredShip();
296 6
        if ($tractoredShip === null) {
297 6
            return null;
298
        }
299
300
        return $this->spacecraftWrapperFactory->wrapShip($tractoredShip);
301
    }
302
303 4
    #[\Override]
304
    public function getStateIconAndTitle(): ?array
305
    {
306 4
        return $this->stateIconAndTitle->getStateIconAndTitle($this);
307
    }
308
309
    #[\Override]
310
    public function getTakeoverTicksLeft(?ShipTakeover $takeover = null): int
311
    {
312
        $takeover ??= $this->spacecraft->getTakeoverActive();
313
        if ($takeover === null) {
314
            throw new BadMethodCallException('should not call when active takeover is null');
315
        }
316
317
        $currentTurn = $this->game->getCurrentRound()->getTurn();
318
319
        return $takeover->getStartTurn() + ShipTakeoverManagerInterface::TURNS_TO_TAKEOVER - $currentTurn;
320
    }
321
322 7
    #[\Override]
323
    public function getCrewStyle(): string
324
    {
325 7
        $ship = $this->spacecraft;
326 7
        $excessCrew = $ship->getExcessCrewCount();
327
328 7
        if ($excessCrew === 0) {
329 6
            return "";
330
        }
331
332 3
        return $excessCrew > 0 ? "color: green;" : "color: red;";
333
    }
334
335
    /**
336
     * @template T2
337
     * @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...
338
     *
339
     * @return T2|null
340
     */
341 74
    public function getSpecificShipSystem(SpacecraftSystemTypeEnum $systemType, string $className)
342
    {
343 74
        return $this->systemDataDeserializer->getSpecificShipSystem(
344 74
            $this->spacecraft,
345 74
            $systemType,
346 74
            $className,
347 74
            $this->shipSystemDataCache,
348 74
            $this->spacecraftWrapperFactory
349 74
        );
350
    }
351
352 1
    #[\Override]
353
    public function __toString(): string
354
    {
355 1
        $systems = implode(",\n", $this->spacecraft->getSystems()
356 1
            ->filter(fn($system): bool => $system->getData() !== null)
357 1
            ->map(fn($system): string => $system->__toString())
358 1
            ->toArray());
359
360 1
        return sprintf(
361 1
            "spacecraft: {%s,\n  systems: [\n%s\n}\n]",
362 1
            $this->spacecraft->__toString(),
363 1
            $systems
364 1
        );
365
    }
366
}
367