Passed
Pull Request — master (#1686)
by Nico
31:24
created

ShipSystemManager::getEnergyUsageForActivation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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