Passed
Pull Request — master (#1866)
by Nico
52:42 queued 25:56
created

TroopTransferStrategy::transferToShip()   C

Complexity

Conditions 12
Paths 12

Size

Total Lines 58
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 156

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 31
c 1
b 0
f 0
nc 12
nop 6
dl 0
loc 58
ccs 0
cts 32
cp 0
crap 156
rs 6.9666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Lib\Transfer\Strategy;
6
7
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...
8
use request;
9
use Stu\Component\Ship\Crew\ShipCrewCalculatorInterface;
10
use Stu\Component\Ship\System\Exception\ShipSystemException;
11
use Stu\Component\Ship\System\Exception\SystemNotActivatableException;
12
use Stu\Component\Ship\System\Exception\SystemNotFoundException;
13
use Stu\Component\Ship\System\ShipSystemManagerInterface;
14
use Stu\Component\Ship\System\ShipSystemModeEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Ship\System\ShipSystemModeEnum 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...
15
use Stu\Component\Ship\System\ShipSystemTypeEnum;
16
use Stu\Component\Ship\System\Type\UplinkShipSystem;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Ship\System\Type\UplinkShipSystem 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...
17
use Stu\Lib\Information\InformationWrapper;
18
use Stu\Module\Colony\Lib\ColonyLibFactoryInterface;
19
use Stu\Module\Control\GameControllerInterface;
20
use Stu\Module\Logging\LoggerUtilFactoryInterface;
21
use Stu\Module\Logging\LoggerUtilInterface;
22
use Stu\Module\Message\Lib\PrivateMessageFolderTypeEnum;
23
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
24
use Stu\Module\Ship\Lib\ActivatorDeactivatorHelperInterface;
25
use Stu\Module\Ship\Lib\Auxiliary\ShipShutdownInterface;
26
use Stu\Module\Ship\Lib\Crew\TroopTransferUtilityInterface;
27
use Stu\Module\Ship\Lib\Interaction\DockPrivilegeUtilityInterface;
28
use Stu\Module\Ship\Lib\ShipWrapperFactoryInterface;
29
use Stu\Module\Ship\Lib\ShipWrapperInterface;
30
use Stu\Module\Ship\View\ShowShip\ShowShip;
0 ignored issues
show
Bug introduced by
The type Stu\Module\Ship\View\ShowShip\ShowShip 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...
31
use Stu\Orm\Entity\ColonyInterface;
32
use Stu\Orm\Entity\ShipCrewInterface;
33
use Stu\Orm\Entity\ShipInterface;
34
35
class TroopTransferStrategy implements TransferStrategyInterface
36
{
37
    private LoggerUtilInterface $logger;
38
39
    public function __construct(
40
        private ShipCrewCalculatorInterface $shipCrewCalculator,
41
        private TroopTransferUtilityInterface $transferUtility,
42
        private ColonyLibFactoryInterface $colonyLibFactory,
43
        private ShipSystemManagerInterface $shipSystemManager,
44
        private DockPrivilegeUtilityInterface $dockPrivilegeUtility,
45
        private ActivatorDeactivatorHelperInterface $helper,
46
        private ShipShutdownInterface $shipShutdown,
47
        private ShipWrapperFactoryInterface $shipWrapperFactory,
48
        private PrivateMessageSenderInterface $privateMessageSender,
49
        LoggerUtilFactoryInterface $loggerUtilFactory
50
    ) {
51
        $this->logger = $loggerUtilFactory->getLoggerUtil();
52
    }
53
54
    #[Override]
55
    public function setTemplateVariables(
56
        bool $isUnload,
57
        ShipInterface $ship,
58
        ShipInterface|ColonyInterface $target,
59
        GameControllerInterface $game
60
    ): void {
61
62
        $user = $game->getUser();
63
64
        if (
65
            $target instanceof ShipInterface
66
            && $target->getBuildplan() !== null
67
        ) {
68
            $game->setTemplateVar('SHOW_TARGET_CREW', true);
69
            $game->setTemplateVar('ACTUAL_TARGET_CREW', $target->getCrewCount());
70
            $game->setTemplateVar('MINIMUM_TARGET_CREW', $target->getBuildplan()->getCrew());
71
            $game->setTemplateVar(
72
                'MAXIMUM_TARGET_CREW',
73
                $this->shipCrewCalculator->getMaxCrewCountByShip($target)
74
            );
75
        }
76
77
        $isUplinkSituation = false;
78
79
        if ($target instanceof ColonyInterface) {
80
            if ($isUnload) {
81
                $max = $this->transferUtility->getBeamableTroopCount($ship);
82
            } else {
83
                $max = min(
84
                    $target->getCrewAssignmentAmount(),
85
                    $this->transferUtility->getFreeQuarters($ship)
86
                );
87
            }
88
        } else {
89
            $ownCrewOnTarget = $this->transferUtility->ownCrewOnTarget($user, $target);
90
91
            if ($target->getUser() !== $user) {
92
                if ($target->hasUplink()) {
93
                    $isUplinkSituation = true;
94
                } else {
95
                    return;
96
                }
97
            }
98
99
            if ($isUnload) {
100
                $max = min(
101
                    $this->transferUtility->getBeamableTroopCount($ship),
102
                    $this->transferUtility->getFreeQuarters($target),
103
                    $isUplinkSituation ? ($ownCrewOnTarget === 0 ? 1 : 0) : PHP_INT_MAX
104
                );
105
            } else {
106
                $max = min(
107
                    $ownCrewOnTarget,
108
                    $this->transferUtility->getFreeQuarters($ship)
109
                );
110
111
                echo $ownCrewOnTarget;
112
            }
113
        }
114
115
        if (!$isUplinkSituation && $target->getUser() !== $ship->getUser()) {
116
            return;
117
        }
118
119
        $game->setTemplateVar('MAXIMUM', $max);
120
    }
121
122
    #[Override]
123
    public function transfer(
124
        bool $isUnload,
125
        ShipWrapperInterface $wrapper,
126
        ShipInterface|ColonyInterface $target,
127
        InformationWrapper $informations
128
    ): void {
129
130
        $ship = $wrapper->get();
131
        $user = $ship->getUser();
132
133
        if ($ship->hasShipSystem(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS) && !$ship->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS)) {
134
            $informations->addInformation(_("Die Truppenquartiere sind zerstört"));
135
            return;
136
        }
137
138
        $epsSystem = $wrapper->getEpsSystemData();
139
        if ($epsSystem === null || $epsSystem->getEps() == 0) {
140
            $informations->addInformation(_("Keine Energie vorhanden"));
141
            return;
142
        }
143
        if ($ship->getCloakState()) {
144
            $informations->addInformation(_("Die Tarnung ist aktiviert"));
145
            return;
146
        }
147
        if ($ship->isWarped()) {
148
            $informations->addInformation("Schiff befindet sich im Warp");
149
            return;
150
        }
151
        if ($ship->getShieldState()) {
152
            $informations->addInformation(_("Die Schilde sind aktiviert"));
153
            return;
154
        }
155
156
        $requestedTransferCount = request::postInt('crewcount');
157
        $isColonyTarget = $target instanceof ColonyInterface;
158
        $amount = 0;
159
160
        try {
161
            if ($isColonyTarget) {
162
                if ($isUnload) {
163
                    $amount = $this->transferToColony($requestedTransferCount, $ship, $target);
164
                } else {
165
                    $amount = $this->transferFromColony($requestedTransferCount, $wrapper, $target, $informations);
166
                }
167
            } else {
168
                $isUplinkSituation = false;
169
                $ownCrewOnTarget = $this->transferUtility->ownCrewOnTarget($user, $target);
170
171
                if ($target->getUser() !== $user) {
172
                    if ($target->hasUplink()) {
173
                        $isUplinkSituation = true;
174
                    } else {
175
                        return;
176
                    }
177
                }
178
179
                if ($isUnload) {
180
                    if ($isUplinkSituation) {
181
                        if (!$this->dockPrivilegeUtility->checkPrivilegeFor($target->getId(), $user)) {
182
                            $informations->addInformation(_("Benötigte Andockerlaubnis wurde verweigert"));
183
                            return;
184
                        }
185
                        if (!$target->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_UPLINK)) {
186
                            $informations->addInformation(_("Das Ziel verfügt über keinen intakten Uplink"));
187
                            return;
188
                        }
189
190
                        if ($this->transferUtility->foreignerCount($target) >= UplinkShipSystem::MAX_FOREIGNERS) {
191
                            $informations->addInformation(_("Maximale Anzahl an fremden Crewman ist bereits erreicht"));
192
                        }
193
                    }
194
195
                    $amount = $this->transferToShip($requestedTransferCount, $ship, $target, $isUplinkSituation, $ownCrewOnTarget, $informations);
196
                } else {
197
                    $amount = $this->transferFromShip($requestedTransferCount, $wrapper, $target, $isUplinkSituation, $ownCrewOnTarget, $informations);
198
                }
199
            }
200
        } catch (ShipSystemException) {
201
            return;
202
        }
203
204
        $informations->addInformation(
205
            sprintf(
206
                _('Die %s hat %d Crewman %s der %s transferiert'),
207
                $ship->getName(),
208
                $amount,
209
                $isUnload ? 'zu' : 'von',
210
                $target->getName()
211
            )
212
        );
213
214
        if (
215
            $ship->hasShipSystem(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS)
216
            && $ship->getSystemState(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS)
217
            && $ship->getBuildplan() !== null && $ship->getCrewCount() <= $ship->getBuildplan()->getCrew()
218
        ) {
219
            $this->helper->deactivate($wrapper, ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS, $informations);
220
        }
221
    }
222
223
224
    private function transferToColony(int $requestedTransferCount, ShipInterface $ship, ColonyInterface $colony): int
225
    {
226
        $freeAssignmentCount = $this->colonyLibFactory->createColonyPopulationCalculator(
227
            $colony
228
        )->getFreeAssignmentCount();
229
230
        $amount = min(
231
            $requestedTransferCount,
232
            $this->transferUtility->getBeamableTroopCount($ship),
233
            $freeAssignmentCount
234
        );
235
236
        $assignments = $ship->getCrewAssignments()->getValues();
237
238
        for ($i = 0; $i < $amount; $i++) {
239
            //assign crew to colony
240
            $this->transferUtility->assignCrew($assignments[$i], $colony);
241
        }
242
243
        return $amount;
244
    }
245
246
    private function transferFromColony(
247
        int $requestedTransferCount,
248
        ShipWrapperInterface $wrapper,
249
        ColonyInterface $colony,
250
        InformationWrapper $informations
251
    ): int {
252
        $ship = $wrapper->get();
253
254
        $amount = min(
255
            $requestedTransferCount,
256
            $colony->getCrewAssignmentAmount(),
257
            $this->transferUtility->getFreeQuarters($ship)
258
        );
259
260
        if ($ship->hasShipSystem(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS) && ($amount > 0
261
            && $ship->getShipSystem(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS)->getMode() === ShipSystemModeEnum::MODE_OFF
262
            && !$this->helper->activate($wrapper, ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS, $informations))) {
263
            $amount = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $amount is dead and can be removed.
Loading history...
264
            throw new SystemNotActivatableException();
265
        }
266
267
        $crewAssignments = $colony->getCrewAssignments();
268
269
        for ($i = 0; $i < $amount; $i++) {
270
            /** @var ShipCrewInterface $crewAssignment */
271
            $crewAssignment = $crewAssignments->get(array_rand($crewAssignments->toArray()));
0 ignored issues
show
Bug introduced by
It seems like array_rand($crewAssignments->toArray()) can also be of type array; however, parameter $key of Doctrine\Common\Collecti...adableCollection::get() does only seem to accept integer|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

271
            $crewAssignment = $crewAssignments->get(/** @scrutinizer ignore-type */ array_rand($crewAssignments->toArray()));
Loading history...
272
273
            $this->transferUtility->assignCrew($crewAssignment, $ship);
274
        }
275
276
        return $amount;
277
    }
278
279
    private function transferToShip(
280
        int $requestedTransferCount,
281
        ShipInterface $ship,
282
        ShipInterface $target,
283
        bool $isUplinkSituation,
284
        int $ownCrewOnTarget,
285
        InformationWrapper $informations
286
    ): int {
287
        if (!$target->hasShipSystem(ShipSystemTypeEnum::SYSTEM_LIFE_SUPPORT)) {
288
            $informations->addInformation(sprintf(_('Die %s hat keine Lebenserhaltungssysteme'), $target->getName()));
289
290
            throw new SystemNotFoundException();
291
        }
292
293
        $this->logger->log(sprintf(
294
            'toShip, requested: %d, beamableOfSource: %d, freeOfTarget: %d',
295
            $requestedTransferCount,
296
            $this->transferUtility->getBeamableTroopCount($ship),
297
            $this->transferUtility->getFreeQuarters($target)
298
        ));
299
300
        $amount = min(
301
            $requestedTransferCount,
302
            $this->transferUtility->getBeamableTroopCount($ship),
303
            $this->transferUtility->getFreeQuarters($target),
304
            $isUplinkSituation ? ($ownCrewOnTarget === 0 ? 1 : 0) : PHP_INT_MAX
305
        );
306
307
        $assignments = $ship->getCrewAssignments()->getValues();
308
309
        if (
310
            $target->hasShipSystem(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS)
311
            && ($target->getShipSystem(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS)->getMode() === ShipSystemModeEnum::MODE_OFF
312
                && !$this->helper->activate($this->shipWrapperFactory->wrapShip($target), ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS, $informations))
313
        ) {
314
            $amount = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $amount is dead and can be removed.
Loading history...
315
            throw new SystemNotActivatableException();
316
        }
317
318
        for ($i = 0; $i < $amount; $i++) {
319
            $this->transferUtility->assignCrew($assignments[$i], $target);
320
        }
321
322
        if ($amount > 0) {
323
            if (
324
                $target->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_LIFE_SUPPORT)
325
                && $target->getShipSystem(ShipSystemTypeEnum::SYSTEM_LIFE_SUPPORT)->getMode() == ShipSystemModeEnum::MODE_OFF
326
            ) {
327
                $this->shipSystemManager->activate($this->shipWrapperFactory->wrapShip($target), ShipSystemTypeEnum::SYSTEM_LIFE_SUPPORT, true);
328
            }
329
330
            if ($isUplinkSituation) {
331
                $target->getShipSystem(ShipSystemTypeEnum::SYSTEM_UPLINK)->setMode(ShipSystemModeEnum::MODE_ON);
332
                $this->sendUplinkMessage(true, true, $ship, $target);
333
            }
334
        }
335
336
        return $amount;
337
    }
338
339
    private function transferFromShip(
340
        int $requestedTransferCount,
341
        ShipWrapperInterface $wrapper,
342
        ShipInterface $target,
343
        bool $isUplinkSituation,
344
        int $ownCrewOnTarget,
345
        InformationWrapper $informations
346
    ): int {
347
        $ship = $wrapper->get();
348
349
        $amount = min(
350
            $requestedTransferCount,
351
            $this->transferUtility->getFreeQuarters($ship),
352
            $ownCrewOnTarget
353
        );
354
355
        if ($amount === 0) {
356
            return 0;
357
        }
358
359
        if (
360
            $ship->hasShipSystem(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS)
361
            && ($ship->getShipSystem(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS)->getMode() === ShipSystemModeEnum::MODE_OFF
362
                && !$this->helper->activate($wrapper, ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS, $informations))
363
        ) {
364
            $amount = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $amount is dead and can be removed.
Loading history...
365
            throw new SystemNotActivatableException();
366
        }
367
368
        $array = $target->getCrewAssignments()->getValues();
369
        $targetCrewCount = $target->getCrewCount();
370
371
        $i = 0;
372
        foreach ($array as $crewAssignment) {
373
            if ($crewAssignment->getCrew()->getUser() !== $ship->getUser()) {
374
                continue;
375
            }
376
377
            $this->transferUtility->assignCrew($crewAssignment, $ship);
378
            $i++;
379
380
            if ($i === $amount) {
381
                break;
382
            }
383
        }
384
385
        if ($isUplinkSituation) {
386
            //no foreigners left, shut down uplink
387
            if ($this->transferUtility->foreignerCount($target) === 0) {
388
                $target->getShipSystem(ShipSystemTypeEnum::SYSTEM_UPLINK)->setMode(ShipSystemModeEnum::MODE_OFF);
389
                $this->sendUplinkMessage(false, false, $ship, $target);
390
            } else {
391
                $this->sendUplinkMessage(false, true, $ship, $target);
392
            }
393
        }
394
395
        $targetWrapper = $this->shipWrapperFactory->wrapShip($target);
396
397
        // no crew left
398
        if ($amount === $targetCrewCount) {
399
            $this->shipShutdown->shutdown($targetWrapper);
400
        } elseif (
401
            $target->hasShipSystem(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS)
402
            && $target->getSystemState(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS)
403
            && $target->getBuildplan() !== null && $target->getCrewCount() <= $target->getBuildplan()->getCrew()
404
        ) {
405
            $this->helper->deactivate($targetWrapper, ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS, $informations);
406
        }
407
408
        return $amount;
409
    }
410
411
    private function sendUplinkMessage(bool $isUnload, bool $isOn, ShipInterface $ship, ShipInterface $target): void
412
    {
413
        $href = sprintf('ship.php?%s=1&id=%d', ShowShip::VIEW_IDENTIFIER, $target->getId());
414
415
        $msg = sprintf(
416
            _('Die %s von Spieler %s hat 1 Crewman %s deiner Station %s gebeamt. Der Uplink ist %s'),
417
            $ship->getName(),
418
            $ship->getUser()->getName(),
419
            $isUnload ? 'zu' : 'von',
420
            $target->getName(),
421
            $isOn ? 'aktiviert' : 'deaktiviert'
422
        );
423
424
        $this->privateMessageSender->send(
425
            $ship->getUser()->getId(),
426
            $target->getUser()->getId(),
427
            $msg,
428
            PrivateMessageFolderTypeEnum::SPECIAL_STATION,
429
            $href
430
        );
431
    }
432
}
433