Passed
Push — master ( f4068b...77f637 )
by Nico
40:27 queued 14:09
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->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS)) {
125
            $game->addInformation(_("Die Truppenquartiere sind zerstört"));
126
            return;
127
        }
128
129
        $epsSystem = $wrapper->getEpsSystemData();
130
        if ($epsSystem->getEps() == 0) {
131
            $game->addInformation(_("Keine Energie vorhanden"));
132
            return;
133
        }
134
        if ($ship->getCloakState()) {
135
            $game->addInformation(_("Die Tarnung ist aktiviert"));
136
            return;
137
        }
138
        if ($ship->getWarpState()) {
139
            $game->addInformation(_("Der Warpantrieb ist aktiviert"));
140
            return;
141
        }
142
        if ($ship->getShieldState()) {
143
            $game->addInformation(_("Die Schilde sind aktiviert"));
144
            return;
145
        }
146
147
        $isUnload = request::has('isUnload');
148
149
150
        if (!$isColony && $target->getWarpState()) {
151
            $game->addInformation(sprintf(_('Die %s befindet sich im Warp'), $target->getName()));
152
            return;
153
        }
154
        $requestedTransferCount = request::postInt('tcount');
155
156
        $amount = 0;
157
158
        try {
159
            if ($isColony) {
160
                if ($isUnload) {
161
                    $amount = $this->transferToColony($requestedTransferCount, $ship, $target);
162
                } else {
163
                    $amount = $this->transferFromColony($requestedTransferCount, $wrapper, $target, $game);
164
                }
165
            } else {
166
                $this->loggerUtil->log('A');
167
                $isUplinkSituation = false;
168
                $ownCrewOnTarget = $this->transferUtility->ownCrewOnTarget($user, $target);
169
170
                if ($target->getUser() !== $user) {
171
                    $this->loggerUtil->log('B');
172
                    if ($target->hasUplink()) {
173
                        $this->loggerUtil->log('C');
174
                        $isUplinkSituation = true;
175
                    } else {
176
                        return;
177
                    }
178
                }
179
180
                if ($isUnload) {
181
                    $this->loggerUtil->log('D');
182
                    if ($isUplinkSituation) {
183
                        $this->loggerUtil->log('E');
184
                        if (!$this->dockPrivilegeUtility->checkPrivilegeFor($target->getId(), $user)) {
185
                            $game->addInformation(_("Benötigte Andockerlaubnis wurde verweigert"));
186
                            return;
187
                        }
188
                        $this->loggerUtil->log('F');
189
                        if (!$target->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_UPLINK)) {
190
                            $this->loggerUtil->log('G');
191
                            $game->addInformation(_("Das Ziel verfügt über keinen intakten Uplink"));
192
                            return;
193
                        }
194
195
                        if ($this->transferUtility->foreignerCount($target) >= UplinkShipSystem::MAX_FOREIGNERS) {
196
                            $game->addInformation(_("Maximale Anzahl an fremden Crewman ist bereits erreicht"));
197
                        }
198
                    }
199
200
                    $amount = $this->transferToShip($requestedTransferCount, $ship, $target, $isUplinkSituation, $ownCrewOnTarget, $game);
201
                } else {
202
                    $amount = $this->transferFromShip($requestedTransferCount, $wrapper, $target, $isUplinkSituation, $ownCrewOnTarget, $game);
203
                }
204
            }
205
        } catch (ShipSystemException $e) {
206
            return;
207
        }
208
209
        $this->shipLoader->save($ship);
210
211
        $game->addInformation(
212
            sprintf(
213
                _('Die %s hat %d Crewman %s der %s transferiert'),
214
                $ship->getName(),
215
                $amount,
216
                $isUnload ? 'zu' : 'von',
217
                $target->getName()
218
            )
219
        );
220
221
        if ($ship->getCrewCount() <= $ship->getBuildplan()->getCrew()) {
222
            $this->helper->deactivate($wrapper, ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS, $game);
223
        }
224
    }
225
226
    private function transferToColony(int $requestedTransferCount, ShipInterface $ship, ColonyInterface $colony): int
227
    {
228
        $freeAssignmentCount = $this->colonyLibFactory->createColonyPopulationCalculator(
229
            $colony
230
        )->getFreeAssignmentCount();
231
232
        $amount = min(
233
            $requestedTransferCount,
234
            $this->transferUtility->getBeamableTroopCount($ship),
235
            $freeAssignmentCount
236
        );
237
238
        $assignments = $ship->getCrewAssignments()->getValues();
239
240
        for ($i = 0; $i < $amount; $i++) {
241
            //assign crew to colony
242
            $this->transferUtility->assignCrew($assignments[$i], $colony);
243
        }
244
245
        return $amount;
246
    }
247
248
    private function transferFromColony(int $requestedTransferCount, ShipWrapperInterface $wrapper, ColonyInterface $colony, GameControllerInterface $game): int
249
    {
250
        $ship = $wrapper->get();
251
252
        $amount = min(
253
            $requestedTransferCount,
254
            $colony->getCrewAssignmentAmount(),
255
            $this->transferUtility->getFreeQuarters($ship)
256
        );
257
258
        if (
259
            $amount > 0
260
            && $ship->getShipSystem(ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS)->getMode() === ShipSystemModeEnum::MODE_OFF
261
            && !$this->helper->activate($wrapper, ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS, $game)
262
        ) {
263
            throw new SystemNotActivatableException();
264
        }
265
266
        $crewAssignments = $colony->getCrewAssignments();
267
268
        for ($i = 0; $i < $amount; $i++) {
269
            /** @var ShipCrewInterface $crewAssignment */
270
            $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

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