Passed
Pull Request — master (#1685)
by Nico
30:06
created

TroopTransfer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 12
nc 1
nop 12
dl 0
loc 26
ccs 0
cts 13
cp 0
crap 2
rs 9.8666
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\Ship\Action\TroopTransfer;
6
7
use request;
8
use Stu\Component\Ship\System\Exception\ShipSystemException;
9
use Stu\Component\Ship\System\Exception\SystemNotActivatableException;
10
use Stu\Component\Ship\System\Exception\SystemNotFoundException;
11
use Stu\Component\Ship\System\ShipSystemManagerInterface;
12
use Stu\Component\Ship\System\ShipSystemModeEnum;
13
use Stu\Component\Ship\System\ShipSystemTypeEnum;
14
use Stu\Component\Ship\System\Type\UplinkShipSystem;
15
use Stu\Module\Colony\Lib\ColonyLibFactoryInterface;
16
use Stu\Module\Control\ActionControllerInterface;
17
use Stu\Module\Control\GameControllerInterface;
18
use Stu\Module\Logging\LoggerUtilFactoryInterface;
19
use Stu\Module\Logging\LoggerUtilInterface;
20
use Stu\Module\Message\Lib\PrivateMessageFolderSpecialEnum;
21
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
22
use Stu\Module\Ship\Lib\ActivatorDeactivatorHelperInterface;
23
use Stu\Module\Ship\Lib\Auxiliary\ShipShutdownInterface;
24
use Stu\Module\Ship\Lib\Interaction\DockPrivilegeUtilityInterface;
25
use Stu\Module\Ship\Lib\Interaction\InteractionChecker;
26
use Stu\Module\Ship\Lib\ShipLoaderInterface;
27
use Stu\Module\Ship\Lib\ShipWrapperFactoryInterface;
28
use Stu\Module\Ship\Lib\Crew\TroopTransferUtilityInterface;
29
use Stu\Module\Ship\Lib\ShipWrapperInterface;
30
use Stu\Module\Ship\View\ShowShip\ShowShip;
31
use Stu\Orm\Entity\ColonyInterface;
32
use Stu\Orm\Entity\ShipCrewInterface;
33
use Stu\Orm\Entity\ShipInterface;
34
use Stu\Orm\Repository\ColonyRepositoryInterface;
35
use Stu\Orm\Repository\ShipRepositoryInterface;
36
37
final class TroopTransfer implements ActionControllerInterface
38
{
39
    public const ACTION_IDENTIFIER = 'B_TROOP_TRANSFER';
40
41
    private ShipLoaderInterface $shipLoader;
42
43
    private ShipRepositoryInterface $shipRepository;
44
45
    private ColonyRepositoryInterface $colonyRepository;
46
47
    private TroopTransferUtilityInterface $transferUtility;
48
49
    private ActivatorDeactivatorHelperInterface $helper;
50
51
    private ShipSystemManagerInterface $shipSystemManager;
52
53
    private DockPrivilegeUtilityInterface $dockPrivilegeUtility;
54
55
    private ShipWrapperFactoryInterface $shipWrapperFactory;
56
57
    private PrivateMessageSenderInterface $privateMessageSender;
58
59
    private ColonyLibFactoryInterface $colonyLibFactory;
60
61
    private ShipShutdownInterface $shipShutdown;
62
63
    private LoggerUtilInterface $loggerUtil;
64
65
    public function __construct(
66
        ShipLoaderInterface $shipLoader,
67
        ShipRepositoryInterface $shipRepository,
68
        ColonyRepositoryInterface $colonyRepository,
69
        TroopTransferUtilityInterface $transferUtility,
70
        ActivatorDeactivatorHelperInterface $helper,
71
        ShipSystemManagerInterface $shipSystemManager,
72
        DockPrivilegeUtilityInterface $dockPrivilegeUtility,
73
        ShipWrapperFactoryInterface $shipWrapperFactory,
74
        PrivateMessageSenderInterface $privateMessageSender,
75
        ColonyLibFactoryInterface $colonyLibFactory,
76
        ShipShutdownInterface $shipShutdown,
77
        LoggerUtilFactoryInterface $loggerUtilFactory
78
    ) {
79
        $this->shipLoader = $shipLoader;
80
        $this->shipRepository = $shipRepository;
81
        $this->colonyRepository = $colonyRepository;
82
        $this->transferUtility = $transferUtility;
83
        $this->helper = $helper;
84
        $this->shipSystemManager = $shipSystemManager;
85
        $this->dockPrivilegeUtility = $dockPrivilegeUtility;
86
        $this->shipWrapperFactory = $shipWrapperFactory;
87
        $this->privateMessageSender = $privateMessageSender;
88
        $this->colonyLibFactory = $colonyLibFactory;
89
        $this->shipShutdown = $shipShutdown;
90
        $this->loggerUtil = $loggerUtilFactory->getLoggerUtil();
91
    }
92
93
    public function handle(GameControllerInterface $game): void
94
    {
95
        //$this->loggerUtil->init('stu', LoggerEnum::LEVEL_ERROR);
96
        $game->setView(ShowShip::VIEW_IDENTIFIER);
97
98
        $user = $game->getUser();
99
        $userId = $user->getId();
100
101
        $wrapper = $this->shipLoader->getWrapperByIdAndUser(
102
            request::indInt('id'),
103
            $userId
104
        );
105
        $ship = $wrapper->get();
106
107
        if (!$ship->hasEnoughCrew($game)) {
108
            return;
109
        }
110
111
        $isColony = request::has('isColony');
112
        if ($isColony) {
113
            $target = $this->colonyRepository->find(request::postIntFatal('target'));
114
        } else {
115
            $target = $this->shipRepository->find(request::postIntFatal('target'));
116
        }
117
        if ($target === null) {
118
            return;
119
        }
120
        if (!InteractionChecker::canInteractWith($ship, $target, $game, !$isColony)) {
121
            return;
122
        }
123
124
        if ($ship->hasShipSystem(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS)) {
125
            if (!$ship->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS)) {
126
                $game->addInformation(_("Die Truppenquartiere sind zerstört"));
127
                return;
128
            }
129
        }
130
131
        $epsSystem = $wrapper->getEpsSystemData();
132
        if ($epsSystem->getEps() == 0) {
133
            $game->addInformation(_("Keine Energie vorhanden"));
134
            return;
135
        }
136
        if ($ship->getCloakState()) {
137
            $game->addInformation(_("Die Tarnung ist aktiviert"));
138
            return;
139
        }
140
        if ($ship->getWarpState()) {
141
            $game->addInformation(_("Der Warpantrieb ist aktiviert"));
142
            return;
143
        }
144
        if ($ship->getShieldState()) {
145
            $game->addInformation(_("Die Schilde sind aktiviert"));
146
            return;
147
        }
148
149
        $isUnload = request::has('isUnload');
150
151
152
        if (!$isColony && $target->getWarpState()) {
153
            $game->addInformation(sprintf(_('Die %s befindet sich im Warp'), $target->getName()));
154
            return;
155
        }
156
        $requestedTransferCount = request::postInt('tcount');
157
158
        $amount = 0;
159
160
        try {
161
            if ($isColony) {
162
                if ($isUnload) {
163
                    $amount = $this->transferToColony($requestedTransferCount, $ship, $target);
164
                } else {
165
                    $amount = $this->transferFromColony($requestedTransferCount, $wrapper, $target, $game);
166
                }
167
            } else {
168
                $this->loggerUtil->log('A');
169
                $isUplinkSituation = false;
170
                $ownCrewOnTarget = $this->transferUtility->ownCrewOnTarget($user, $target);
171
172
                if ($target->getUser() !== $user) {
173
                    $this->loggerUtil->log('B');
174
                    if ($target->hasUplink()) {
175
                        $this->loggerUtil->log('C');
176
                        $isUplinkSituation = true;
177
                    } else {
178
                        return;
179
                    }
180
                }
181
182
                if ($isUnload) {
183
                    $this->loggerUtil->log('D');
184
                    if ($isUplinkSituation) {
185
                        $this->loggerUtil->log('E');
186
                        if (!$this->dockPrivilegeUtility->checkPrivilegeFor($target->getId(), $user)) {
187
                            $game->addInformation(_("Benötigte Andockerlaubnis wurde verweigert"));
188
                            return;
189
                        }
190
                        $this->loggerUtil->log('F');
191
                        if (!$target->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_UPLINK)) {
192
                            $this->loggerUtil->log('G');
193
                            $game->addInformation(_("Das Ziel verfügt über keinen intakten Uplink"));
194
                            return;
195
                        }
196
197
                        if ($this->transferUtility->foreignerCount($target) >= UplinkShipSystem::MAX_FOREIGNERS) {
198
                            $game->addInformation(_("Maximale Anzahl an fremden Crewman ist bereits erreicht"));
199
                        }
200
                    }
201
202
                    $amount = $this->transferToShip($requestedTransferCount, $ship, $target, $isUplinkSituation, $ownCrewOnTarget, $game);
203
                } else {
204
                    $amount = $this->transferFromShip($requestedTransferCount, $wrapper, $target, $isUplinkSituation, $ownCrewOnTarget, $game);
205
                }
206
            }
207
        } catch (ShipSystemException $e) {
208
            return;
209
        }
210
211
        $this->shipLoader->save($ship);
212
213
        $game->addInformation(
214
            sprintf(
215
                _('Die %s hat %d Crewman %s der %s transferiert'),
216
                $ship->getName(),
217
                $amount,
218
                $isUnload ? 'zu' : 'von',
219
                $target->getName()
220
            )
221
        );
222
223
        if ($ship->getCrewCount() <= $ship->getBuildplan()->getCrew()) {
224
            $this->helper->deactivate($wrapper, ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS, $game);
225
        }
226
    }
227
228
    private function transferToColony(int $requestedTransferCount, ShipInterface $ship, ColonyInterface $colony): int
229
    {
230
        $freeAssignmentCount = $this->colonyLibFactory->createColonyPopulationCalculator(
231
            $colony
232
        )->getFreeAssignmentCount();
233
234
        $amount = min(
235
            $requestedTransferCount,
236
            $this->transferUtility->getBeamableTroopCount($ship),
237
            $freeAssignmentCount
238
        );
239
240
        $assignments = $ship->getCrewAssignments()->getValues();
241
242
        for ($i = 0; $i < $amount; $i++) {
243
            //assign crew to colony
244
            $this->transferUtility->assignCrew($assignments[$i], $colony);
245
        }
246
247
        return $amount;
248
    }
249
250
    private function transferFromColony(int $requestedTransferCount, ShipWrapperInterface $wrapper, ColonyInterface $colony, GameControllerInterface $game): int
251
    {
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)) {
261
        if (
262
            $amount > 0
263
            && $ship->getShipSystem(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS)->getMode() === ShipSystemModeEnum::MODE_OFF
264
            && !$this->helper->activate($wrapper, ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS, $game)
265
        ) {
266
            throw new SystemNotActivatableException();
267
            }
268
        }
269
270
        $crewAssignments = $colony->getCrewAssignments();
271
272
        for ($i = 0; $i < $amount; $i++) {
273
            /** @var ShipCrewInterface $crewAssignment */
274
            $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

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