Passed
Push — master ( 48bfaa...170129 )
by Nico
25:44
created

ActivatorDeactivatorHelper::setLSSMode()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 3
nop 3
dl 0
loc 19
ccs 0
cts 12
cp 0
crap 12
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Ship\Lib;
6
7
use RuntimeException;
8
use Stu\Component\Ship\ShipAlertStateEnum;
9
use Stu\Component\Ship\ShipLSSModeEnum;
10
use Stu\Component\Ship\System\Exception\ActivationConditionsNotMetException;
11
use Stu\Component\Ship\System\Exception\AlreadyActiveException;
12
use Stu\Component\Ship\System\Exception\AlreadyOffException;
13
use Stu\Component\Ship\System\Exception\DeactivationConditionsNotMetException;
14
use Stu\Component\Ship\System\Exception\InsufficientCrewException;
15
use Stu\Component\Ship\System\Exception\InsufficientEnergyException;
16
use Stu\Component\Ship\System\Exception\ShipSystemException;
17
use Stu\Component\Ship\System\Exception\SystemCooldownException;
18
use Stu\Component\Ship\System\Exception\SystemDamagedException;
19
use Stu\Component\Ship\System\Exception\SystemNotActivatableException;
20
use Stu\Component\Ship\System\Exception\SystemNotDeactivatableException;
21
use Stu\Component\Ship\System\Exception\SystemNotFoundException;
22
use Stu\Component\Ship\System\ShipSystemManagerInterface;
23
use Stu\Component\Ship\System\ShipSystemTypeEnum;
24
use Stu\Lib\Information\InformationInterface;
25
use Stu\Module\Control\GameControllerInterface;
26
use Stu\Module\Ship\Lib\Movement\Component\PreFlight\ConditionCheckResult;
27
use Stu\Module\Tal\TalHelper;
28
use Stu\Orm\Entity\ShipInterface;
29
use Stu\Orm\Repository\ShipRepositoryInterface;
30
31
final class ActivatorDeactivatorHelper implements ActivatorDeactivatorHelperInterface
32
{
33
    private ShipLoaderInterface $shipLoader;
34
35
    private ShipRepositoryInterface $shipRepository;
36
37
    private ShipSystemManagerInterface $shipSystemManager;
38
39
    private GameControllerInterface $game;
40
41 1
    public function __construct(
42
        ShipLoaderInterface $shipLoader,
43
        ShipRepositoryInterface $shipRepository,
44
        ShipSystemManagerInterface $shipSystemManager,
45
        GameControllerInterface $game
46
    ) {
47 1
        $this->shipLoader = $shipLoader;
48 1
        $this->shipRepository = $shipRepository;
49 1
        $this->shipSystemManager = $shipSystemManager;
50 1
        $this->game = $game;
51
    }
52
53
    public function activate(
54
        ShipWrapperInterface|int $target,
55
        shipSystemTypeEnum $type,
56
        ConditionCheckResult|InformationInterface $logger,
57
        bool $allowUplink = false,
58
        bool $isDryRun = false
59
    ): bool {
60
        $wrapper = $this->getTargetWrapper(
61
            $target,
62
            $allowUplink
63
        );
64
65
        return $this->activateIntern($wrapper, $type, $logger, $isDryRun);
66
    }
67
68
    private function getTargetWrapper(
69
        ShipWrapperInterface|int $target,
70
        bool $allowUplink
71
    ): ShipWrapperInterface {
72
        if ($target instanceof ShipWrapperInterface) {
73
            return $target;
74
        }
75
76
        return $this->shipLoader->getWrapperByIdAndUser(
77
            $target,
78
            $this->game->getUser()->getId(),
79
            $allowUplink
80
        );
81
    }
82
83
    private function activateIntern(
84
        ShipWrapperInterface $wrapper,
85
        shipSystemTypeEnum $type,
86
        ConditionCheckResult|InformationInterface $logger,
87
        bool $isDryRun
88
    ): bool {
89
        $systemName = $type->getDescription();
90
        $ship = $wrapper->get();
91
92
        try {
93
            $this->shipSystemManager->activate($wrapper, $type, false, $isDryRun);
94
            $this->shipRepository->save($ship);
95
            if ($logger instanceof InformationInterface) {
96
                $logger->addInformationf(_('%s: System %s aktiviert'), $ship->getName(), $systemName);
97
            }
98
            return true;
99
        } catch (AlreadyActiveException $e) {
100
            if ($logger instanceof InformationInterface) {
101
                $logger->addInformationf(_('%s: System %s ist bereits aktiviert'), $ship->getName(), $systemName);
102
            }
103
        } catch (SystemNotActivatableException $e) {
104
            $this->logError($ship, sprintf(_('%s: [b][color=#ff2626]System %s besitzt keinen Aktivierungsmodus[/color][/b]'), $ship->getName(), $systemName), $logger);
105
        } catch (InsufficientEnergyException $e) {
106
            $this->logError($ship, sprintf(
107
                _('%s: [b][color=#ff2626]System %s kann aufgrund Energiemangels (%d benötigt) nicht aktiviert werden[/color][/b]'),
108
                $ship->getName(),
109
                $systemName,
110
                $e->getNeededEnergy()
111
            ), $logger);
112
        } catch (SystemCooldownException $e) {
113
            $this->logError($ship, sprintf(
114
                _('%s: [b][color=#ff2626]System %s kann nicht aktiviert werden, Cooldown noch %s[/color][/b]'),
115
                $ship->getName(),
116
                $systemName,
117
                TalHelper::formatSeconds((string) $e->getRemainingSeconds())
118
            ), $logger);
119
        } catch (SystemDamagedException $e) {
120
            $this->logError($ship, sprintf(_('%s: [b][color=#ff2626]System %s ist beschädigt und kann daher nicht aktiviert werden[/color][/b]'), $ship->getName(), $systemName), $logger);
121
        } catch (ActivationConditionsNotMetException $e) {
122
            $this->logError($ship, sprintf(_('%s: [b][color=#ff2626]System %s konnte nicht aktiviert werden, weil %s[/color][/b]'), $ship->getName(), $systemName, $e->getMessage()), $logger);
123
        } catch (SystemNotFoundException $e) {
124
            $this->logError($ship, sprintf(_('%s: [b][color=#ff2626]System %s nicht vorhanden[/color][/b]'), $ship->getName(), $systemName), $logger);
125
        } catch (InsufficientCrewException $e) {
126
            $this->logError($ship, sprintf(_('%s: [b][color=#ff2626]System %s konnte wegen Mangel an Crew nicht aktiviert werden[/color][/b]'), $ship->getName(), $systemName), $logger);
127
        } catch (ShipSystemException $e) {
128
            $this->logError($ship, sprintf(_('%s: [b][color=#ff2626]System %s konnte nicht aktiviert werden[/color][/b]'), $ship->getName(), $systemName), $logger);
129
        }
130
131
        return false;
132
    }
133
134
    private function logError(ShipInterface $ship, string $message, ConditionCheckResult|InformationInterface $logger): void
135
    {
136
        if ($logger instanceof InformationInterface) {
137
            $logger->addInformation($message);
138
        } else {
139
            $logger->addBlockedShip($ship, $message);
140
        }
141
    }
142
143
    public function activateFleet(
144
        int $shipId,
145
        shipSystemTypeEnum $type,
146
        GameControllerInterface $game
147
    ): void {
148
        $userId = $game->getUser()->getId();
149
150
        $wrapper = $this->shipLoader->getWrapperByIdAndUser(
151
            $shipId,
152
            $userId
153
        );
154
155
        $fleetWrapper = $wrapper->getFleetWrapper();
156
        if ($fleetWrapper === null) {
157
            throw new RuntimeException('ship not in fleet');
158
        }
159
160
        $success = false;
161
        foreach ($fleetWrapper->getShipWrappers() as $wrapper) {
162
            if ($this->activateIntern($wrapper, $type, $game, false)) {
163
                $success = true;
164
            }
165
        }
166
167
        // only show info if at least one ship was able to change
168
        if (!$success) {
169
            return;
170
        }
171
172
        $game->addInformation(sprintf(
173
            _('Flottenbefehl ausgeführt: System %s aktiviert'),
174
            $type->getDescription()
175
        ));
176
    }
177
178
    public function deactivate(
179
        ShipWrapperInterface|int $target,
180
        shipSystemTypeEnum $type,
181
        InformationInterface $informations,
182
        bool $allowUplink = false
183
    ): bool {
184
        $wrapper = $this->getTargetWrapper(
185
            $target,
186
            $allowUplink
187
        );
188
189
        return $this->deactivateIntern($wrapper, $type, $informations);
190
    }
191
192
    private function deactivateIntern(
193
        ShipWrapperInterface $wrapper,
194
        shipSystemTypeEnum $type,
195
        InformationInterface $informations
196
    ): bool {
197
        $systemName = $type->getDescription();
198
        $ship = $wrapper->get();
199
200
        try {
201
            $this->shipSystemManager->deactivate($wrapper, $type);
202
            $this->shipRepository->save($ship);
203
            $informations->addInformationf(_('%s: System %s deaktiviert'), $ship->getName(), $systemName);
204
            return true;
205
        } catch (AlreadyOffException $e) {
206
            $informations->addInformationf(_('%s: System %s ist bereits deaktiviert'), $ship->getName(), $systemName);
207
        } catch (SystemNotDeactivatableException $e) {
208
            $informations->addInformationf(_('%s: [b][color=#ff2626]System %s besitzt keinen Deaktivierungsmodus[/color][/b]'), $ship->getName(), $systemName);
209
        } catch (DeactivationConditionsNotMetException $e) {
210
            $informations->addInformationf(_('%s: [b][color=#ff2626]System %s konnte nicht deaktiviert werden, weil %s[/color][/b]'), $ship->getName(), $systemName, $e->getMessage());
211
        } catch (SystemNotFoundException $e) {
212
            $informations->addInformationf(_('%s: System %s nicht vorhanden'), $ship->getName(), $systemName);
213
        }
214
215
        return false;
216
    }
217
218
    public function deactivateFleet(
219
        ShipWrapperInterface|int $target,
220
        shipSystemTypeEnum $type,
221
        InformationInterface $informations
222
    ): bool {
223
        $wrapper = $this->getTargetWrapper(
224
            $target,
225
            false
226
        );
227
228
        return $this->deactivateFleetIntern($wrapper, $type, $informations);
229
    }
230
231
    private function deactivateFleetIntern(
232
        ShipWrapperInterface $wrapper,
233
        shipSystemTypeEnum $type,
234
        InformationInterface $informations
235
    ): bool {
236
237
        $fleetWrapper = $wrapper->getFleetWrapper();
238
        if ($fleetWrapper === null) {
239
            throw new RuntimeException('ship not in fleet');
240
        }
241
242
        $success = false;
243
        foreach ($fleetWrapper->getShipWrappers() as $wrapper) {
244
            if ($this->deactivateIntern($wrapper, $type, $informations)) {
245
                $success = true;
246
            }
247
        }
248
249
        // only show info if at least one ship was able to change
250
        if (!$success) {
251
            return false;
252
        }
253
254
        $informations->addInformationf(
255
            'Flottenbefehl ausgeführt: System %s deaktiviert',
256
            $type->getDescription()
257
        );
258
259
        return true;
260
    }
261
262
    public function setLSSMode(
263
        int $shipId,
264
        int $lssMode,
265
        GameControllerInterface $game
266
    ): void {
267
        $userId = $game->getUser()->getId();
268
269
        $ship = $this->shipLoader->getByIdAndUser(
270
            $shipId,
271
            $userId
272
        );
273
274
        $ship->setLSSMode($lssMode);
275
        $this->shipRepository->save($ship);
276
277
        if ($lssMode === ShipLSSModeEnum::LSS_NORMAL) {
278
            $game->addInformation("Territoriale Grenzanzeige deaktiviert");
279
        } elseif ($lssMode === ShipLSSModeEnum::LSS_BORDER) {
280
            $game->addInformation("Territoriale Grenzanzeige aktiviert");
281
        }
282
    }
283
284
    public function setAlertState(
285
        ShipWrapperInterface|int $shipId,
286
        ShipAlertStateEnum $alertState,
287
        GameControllerInterface $game
288
    ): void {
289
        $wrapper = $this->getTargetWrapper(
290
            $shipId,
291
            false
292
        );
293
294
        if (!$this->setAlertStateShip($wrapper, $alertState, $game)) {
295
            return;
296
        }
297
298
        if ($alertState === ShipAlertStateEnum::ALERT_RED) {
299
            $game->addInformation("Die Alarmstufe wurde auf [b][color=red]Rot[/color][/b] geändert");
300
        } elseif ($alertState === ShipAlertStateEnum::ALERT_YELLOW) {
301
            $game->addInformation("Die Alarmstufe wurde auf [b][color=yellow]Gelb[/color][/b] geändert");
302
        } elseif ($alertState === ShipAlertStateEnum::ALERT_GREEN) {
303
            $game->addInformation("Die Alarmstufe wurde auf [b][color=green]Grün[/color][/b] geändert");
304
        }
305
    }
306
307
    public function setAlertStateFleet(
308
        int $shipId,
309
        ShipAlertStateEnum $alertState,
310
        GameControllerInterface $game
311
    ): void {
312
        $userId = $game->getUser()->getId();
313
314
        $wrapper = $this->shipLoader->getWrapperByIdAndUser(
315
            $shipId,
316
            $userId
317
        );
318
319
        $fleetWrapper = $wrapper->getFleetWrapper();
320
        if ($fleetWrapper === null) {
321
            throw new RuntimeException('ship not in fleet');
322
        }
323
324
        $success = false;
325
        foreach ($fleetWrapper->getShipWrappers() as $wrapper) {
326
            $success = $this->setAlertStateShip($wrapper, $alertState, $game) || $success;
327
        }
328
329
        // only show info if at least one ship was able to change
330
        if (!$success) {
331
            return;
332
        }
333
334
        if ($alertState === ShipAlertStateEnum::ALERT_RED) {
335
            $game->addInformation(_('Flottenbefehl ausgeführt: Alarmstufe [b][color=red]Rot[/color][/b]'));
336
        } elseif ($alertState === ShipAlertStateEnum::ALERT_YELLOW) {
337
            $game->addInformation(_('Flottenbefehl ausgeführt: Alarmstufe [b][color=yellow]Gelb[/color][/b]'));
338
        } elseif ($alertState === ShipAlertStateEnum::ALERT_GREEN) {
339
            $game->addInformation(_('Flottenbefehl ausgeführt: Alarmstufe [b][color=green]Grün[/color][/b]'));
340
        }
341
    }
342
343
    private function setAlertStateShip(ShipWrapperInterface $wrapper, ShipAlertStateEnum $alertState, GameControllerInterface $game): bool
344
    {
345
        $ship = $wrapper->get();
346
347
        // station constructions can't change alert state
348
        if ($ship->isConstruction()) {
349
            $game->addInformation(sprintf(_('%s: [b][color=#ff2626]Konstrukte können die Alarmstufe nicht ändern[/color][/b]'), $ship->getName()));
350
            return false;
351
        }
352
353
        // can only change when there is enough crew
354
        if (!$ship->hasEnoughCrew()) {
355
            $game->addInformation(sprintf(_('%s: [b][color=#ff2626]Mangel an Crew verhindert den Wechsel der Alarmstufe[/color][/b]'), $ship->getName()));
356
            return false;
357
        }
358
359
        if ($alertState === ShipAlertStateEnum::ALERT_RED && $ship->getCloakState()) {
360
            $game->addInformation(sprintf(_('%s: [b][color=#ff2626]Tarnung verhindert den Wechsel zu Alarm-Rot[/color][/b]'), $ship->getName()));
361
            return false;
362
        }
363
364
        try {
365
            $alertMsg = $wrapper->setAlertState($alertState);
366
            $this->shipRepository->save($ship);
367
368
            if ($alertMsg !== null) {
369
                $game->addInformation(sprintf(_('%s: [b][color=FAFA03]%s[/color][/b]'), $ship->getName(), $alertMsg));
370
            }
371
        } catch (InsufficientEnergyException $e) {
372
            $game->addInformation(sprintf(_('%s: [b][color=#ff2626]Nicht genügend Energie um die Alarmstufe zu wechseln (%d benötigt)[/color][/b]'), $ship->getName(), $e->getNeededEnergy()));
373
            return false;
374
        }
375
376
        switch ($alertState) {
377
            case ShipAlertStateEnum::ALERT_RED:
378
                $this->setAlertRed($wrapper, $game);
379
                break;
380
            case ShipAlertStateEnum::ALERT_YELLOW:
381
                $this->setAlertYellow($wrapper, $game);
382
                break;
383
            case ShipAlertStateEnum::ALERT_GREEN:
384
                $this->setAlertGreen($wrapper, $game);
385
                break;
386
        }
387
388
        $this->shipRepository->save($ship);
389
390
        return true;
391
    }
392
393
    private function setAlertRed(ShipWrapperInterface $wrapper, GameControllerInterface $game): void
394
    {
395
        $alertSystems = [
396
            ShipSystemTypeEnum::SYSTEM_SHIELDS,
397
            ShipSystemTypeEnum::SYSTEM_NBS,
398
            ShipSystemTypeEnum::SYSTEM_PHASER,
399
            ShipSystemTypeEnum::SYSTEM_TORPEDO
400
        ];
401
402
        foreach ($alertSystems as $type) {
403
            $this->activateIntern($wrapper, $type, $game, false);
404
        }
405
    }
406
407
    private function setAlertYellow(ShipWrapperInterface $wrapper, GameControllerInterface $game): void
408
    {
409
        $alertSystems = [
410
            ShipSystemTypeEnum::SYSTEM_NBS
411
        ];
412
413
        foreach ($alertSystems as $type) {
414
            $this->activateIntern($wrapper, $type, $game, false);
415
        }
416
    }
417
418
    private function setAlertGreen(ShipWrapperInterface $wrapper, GameControllerInterface $game): void
419
    {
420
        $deactivateSystems = [
421
            ShipSystemTypeEnum::SYSTEM_PHASER,
422
            ShipSystemTypeEnum::SYSTEM_TORPEDO,
423
            ShipSystemTypeEnum::SYSTEM_SHIELDS
424
        ];
425
426
        foreach ($deactivateSystems as $type) {
427
            if ($wrapper->get()->hasShipSystem($type)) {
428
                $this->deactivateIntern($wrapper, $type, $game);
429
            }
430
        }
431
    }
432
}
433