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