SpacecraftSystemManager   A
last analyzed

Complexity

Total Complexity 41

Size/Duplication

Total Lines 210
Duplicated Lines 0 %

Test Coverage

Coverage 84.21%

Importance

Changes 0
Metric Value
eloc 93
dl 0
loc 210
ccs 80
cts 95
cp 0.8421
rs 9.1199
c 0
b 0
f 0
wmc 41

13 Methods

Rating   Name   Duplication   Size   Complexity  
B checkActivationConditions() 0 42 11
A setCooldown() 0 9 3
A handleDamagedSystem() 0 6 1
A getEnergyConsumption() 0 6 1
A lookupSystem() 0 9 2
A deactivate() 0 10 2
A __construct() 0 1 1
A handleDestroyedSystem() 0 6 1
A checkDeactivationConditions() 0 26 6
A getEnergyUsageForActivation() 0 6 1
A getActiveSystems() 0 22 5
A activate() 0 26 4
A deactivateAll() 0 8 3

How to fix   Complexity   

Complex Class

Complex classes like SpacecraftSystemManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SpacecraftSystemManager, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Component\Spacecraft\System;
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 Stu\Component\Spacecraft\System\Exception\ActivationConditionsNotMetException;
11
use Stu\Component\Spacecraft\System\Exception\AlreadyActiveException;
12
use Stu\Component\Spacecraft\System\Exception\AlreadyOffException;
13
use Stu\Component\Spacecraft\System\Exception\DeactivationConditionsNotMetException;
14
use Stu\Component\Spacecraft\System\Exception\InsufficientCrewException;
15
use Stu\Component\Spacecraft\System\Exception\InsufficientEnergyException;
16
use Stu\Component\Spacecraft\System\Exception\InvalidSystemException;
17
use Stu\Component\Spacecraft\System\Exception\SpacecraftSystemException;
18
use Stu\Component\Spacecraft\System\Exception\SystemCooldownException;
19
use Stu\Component\Spacecraft\System\Exception\SystemDamagedException;
20
use Stu\Component\Spacecraft\System\Exception\SystemNotActivatableException;
21
use Stu\Component\Spacecraft\System\Exception\SystemNotDeactivatableException;
22
use Stu\Component\Spacecraft\System\Exception\SystemNotFoundException;
23
use Stu\Module\Control\StuTime;
24
use Stu\Module\Spacecraft\Lib\SpacecraftWrapperInterface;
25
use Stu\Orm\Entity\SpacecraftSystem;
26
use Stu\Orm\Entity\Spacecraft;
27
28
final class SpacecraftSystemManager implements SpacecraftSystemManagerInterface
29
{
30
    /**
31
     * @param array<SpacecraftSystemTypeInterface> $systemList
32
     */
33 20
    public function __construct(private array $systemList, private StuTime $stuTime) {}
34
35 11
    #[Override]
36
    public function activate(
37
        SpacecraftWrapperInterface $wrapper,
38
        SpacecraftSystemTypeEnum $type,
39
        bool $force = false,
40
        bool $isDryRun = false
41
    ): void {
42 11
        $time = $this->stuTime->time();
43 11
        $system = $this->lookupSystem($type);
44
45 11
        if (!$force) {
46 11
            $this->checkActivationConditions($wrapper, $system, $type, $time);
47
        }
48
49 3
        if ($isDryRun) {
50 1
            return;
51
        }
52
53 2
        $epsSystem = $wrapper->getEpsSystemData();
54 2
        if ($epsSystem !== null) {
55 2
            $epsSystem->lowerEps($system->getEnergyUsageForActivation())->update();
56
        }
57
58 2
        $this->setCooldown($wrapper, $type, $time, $system);
59
60 2
        $system->activate($wrapper, $this);
61
    }
62
63 2
    private function setCooldown(
64
        SpacecraftWrapperInterface $wrapper,
65
        SpacecraftSystemTypeEnum $type,
66
        int $time,
67
        SpacecraftSystemTypeInterface $system
68
    ): void {
69 2
        $shipSystem = $wrapper->get()->getSystems()[$type->value] ?? null;
70 2
        if ($shipSystem !== null && $system->getCooldownSeconds() !== null) {
71 1
            $shipSystem->setCooldown($time + $system->getCooldownSeconds());
72
        }
73
    }
74
75 7
    #[Override]
76
    public function deactivate(SpacecraftWrapperInterface $wrapper, SpacecraftSystemTypeEnum $type, bool $force = false): void
77
    {
78 7
        $system = $this->lookupSystem($type);
79
80 6
        if (!$force) {
81 4
            $this->checkDeactivationConditions($wrapper, $system, $type);
82
        }
83
84 3
        $system->deactivate($wrapper);
85
    }
86
87 2
    #[Override]
88
    public function deactivateAll(SpacecraftWrapperInterface $wrapper): void
89
    {
90 2
        foreach ($wrapper->get()->getSystems() as $shipSystem) {
91
            try {
92 2
                $this->deactivate($wrapper, $shipSystem->getSystemType(), true);
93 1
            } catch (SpacecraftSystemException) {
94 1
                continue;
95
            }
96
        }
97
    }
98
99
    #[Override]
100
    public function getEnergyUsageForActivation(SpacecraftSystemTypeEnum $type): int
101
    {
102
        $system = $this->lookupSystem($type);
103
104
        return $system->getEnergyUsageForActivation();
105
    }
106
107 4
    #[Override]
108
    public function getEnergyConsumption(SpacecraftSystemTypeEnum $type): int
109
    {
110 4
        $system = $this->lookupSystem($type);
111
112 4
        return $system->getEnergyConsumption();
113
    }
114
115 22
    #[Override]
116
    public function lookupSystem(SpacecraftSystemTypeEnum $type): SpacecraftSystemTypeInterface
117
    {
118 22
        $system = $this->systemList[$type->value] ?? null;
119 22
        if ($system === null) {
120 1
            throw new InvalidSystemException();
121
        }
122
123 21
        return $system;
124
    }
125
126 11
    private function checkActivationConditions(
127
        SpacecraftWrapperInterface $wrapper,
128
        SpacecraftSystemTypeInterface $system,
129
        SpacecraftSystemTypeEnum $type,
130
        int $time
131
    ): void {
132 11
        $ship = $wrapper->get();
133 11
        $shipSystem = $ship->getSystems()[$type->value] ?? null;
134 11
        if ($shipSystem === null) {
135 1
            throw new SystemNotFoundException();
136
        }
137
138 10
        if ($shipSystem->getStatus() === 0) {
139 1
            throw new SystemDamagedException();
140
        }
141
142 9
        $mode = $shipSystem->getMode();
143 9
        if ($mode === SpacecraftSystemModeEnum::MODE_ALWAYS_OFF) {
144 1
            throw new SystemNotActivatableException();
145
        }
146
147 8
        if ($mode->isActivated()) {
148 1
            throw new AlreadyActiveException();
149
        }
150
151 7
        if (!$ship->hasEnoughCrew()) {
152 1
            throw new InsufficientCrewException();
153
        }
154
155 6
        $epsSystem = $wrapper->getEpsSystemData();
156 6
        if ($epsSystem === null || $epsSystem->getEps() < $system->getEnergyUsageForActivation()) {
157 1
            throw new InsufficientEnergyException($system->getEnergyUsageForActivation());
158
        }
159
160 5
        $cooldown = $shipSystem->getCooldown();
161 5
        if ($cooldown !== null && $cooldown > $time) {
162 1
            throw new SystemCooldownException($cooldown - $time);
163
        }
164
165 4
        $reason = '';
166 4
        if (!$system->checkActivationConditions($wrapper, $reason)) {
167 1
            throw new ActivationConditionsNotMetException($reason);
168
        }
169
    }
170
171 4
    private function checkDeactivationConditions(
172
        SpacecraftWrapperInterface $wrapper,
173
        SpacecraftSystemTypeInterface $system,
174
        SpacecraftSystemTypeEnum $type
175
    ): void {
176 4
        $ship = $wrapper->get();
177 4
        $shipSystem = $ship->getSystems()[$type->value] ?? null;
178 4
        if ($shipSystem === null) {
179
            throw new SystemNotFoundException();
180
        }
181
182 4
        $mode = $shipSystem->getMode();
183 4
        if ($mode === SpacecraftSystemModeEnum::MODE_ALWAYS_ON) {
184 1
            throw new SystemNotDeactivatableException();
185
        }
186
187
        if (
188 3
            $mode === SpacecraftSystemModeEnum::MODE_OFF
189 3
            ||  $mode === SpacecraftSystemModeEnum::MODE_ALWAYS_OFF
190
        ) {
191 1
            throw new AlreadyOffException();
192
        }
193
194 2
        $reason = '';
195 2
        if (!$system->checkDeactivationConditions($wrapper, $reason)) {
196 1
            throw new DeactivationConditionsNotMetException($reason);
197
        }
198
    }
199
200
    #[Override]
201
    public function handleDestroyedSystem(SpacecraftWrapperInterface $wrapper, SpacecraftSystemTypeEnum $type): void
202
    {
203
        $system = $this->lookupSystem($type);
204
205
        $system->handleDestruction($wrapper);
206
    }
207
208
    #[Override]
209
    public function handleDamagedSystem(SpacecraftWrapperInterface $wrapper, SpacecraftSystemTypeEnum $type): void
210
    {
211
        $system = $this->lookupSystem($type);
212
213
        $system->handleDamage($wrapper);
214
    }
215
216 5
    #[Override]
217
    public function getActiveSystems(Spacecraft $ship, bool $sort = false): Collection
218
    {
219 5
        $activeSystems = [];
220 5
        $prioArray = [];
221 5
        foreach ($ship->getSystems() as $system) {
222 4
            if ($system->getMode()->isActivated()) {
223 4
                $activeSystems[] = $system;
224 4
                if ($sort) {
225
                    $prioArray[$system->getSystemType()->value] = $system->getSystemType()->getPriority();
226
                }
227
            }
228
        }
229
230 5
        if ($sort) {
231
            usort(
232
                $activeSystems,
233
                fn(SpacecraftSystem $a, SpacecraftSystem $b): int => $prioArray[$a->getSystemType()->value] <=> $prioArray[$b->getSystemType()->value]
234
            );
235
        }
236
237 5
        return new ArrayCollection($activeSystems);
238
    }
239
}
240