Passed
Push — dev ( b9c6b0...c60bec )
by Nico
44:35 queued 20:19
created

ShipTakeoverManager::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 8
c 1
b 0
f 0
nc 1
nop 8
dl 0
loc 18
ccs 9
cts 9
cp 1
crap 1
rs 10

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\Lib\Interaction;
6
7
use Stu\Component\Ship\ShipStateEnum;
8
use Stu\Module\Control\GameControllerInterface;
9
use Stu\Module\History\Lib\EntryCreatorInterface;
10
use Stu\Module\Message\Lib\PrivateMessageFolderSpecialEnum;
11
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
12
use Stu\Module\PlayerSetting\Lib\UserEnum;
13
use Stu\Module\Prestige\Lib\CreatePrestigeLogInterface;
14
use Stu\Module\Ship\Lib\Fleet\LeaveFleetInterface;
15
use Stu\Module\Ship\View\ShowShip\ShowShip;
16
use Stu\Orm\Entity\BuildplanModuleInterface;
17
use Stu\Orm\Entity\ShipInterface;
18
use Stu\Orm\Entity\ShipTakeoverInterface;
19
use Stu\Orm\Entity\UserInterface;
20
use Stu\Orm\Repository\ShipRepositoryInterface;
21
use Stu\Orm\Repository\ShipTakeoverRepositoryInterface;
22
use Stu\Orm\Repository\StorageRepositoryInterface;
23
24
final class ShipTakeoverManager implements ShipTakeoverManagerInterface
25
{
26
    private ShipTakeoverRepositoryInterface $shipTakeoverRepository;
27
28
    private ShipRepositoryInterface $shipRepository;
29
30
    private StorageRepositoryInterface $storageRepository;
31
32
    private CreatePrestigeLogInterface $createPrestigeLog;
33
34
    private LeaveFleetInterface $leaveFleet;
35
36
    private EntryCreatorInterface $entryCreator;
37
38
    private PrivateMessageSenderInterface $privateMessageSender;
39
40
    private GameControllerInterface $game;
41
42 15
    public function __construct(
43
        ShipTakeoverRepositoryInterface $shipTakeoverRepository,
44
        ShipRepositoryInterface $shipRepository,
45
        StorageRepositoryInterface $storageRepository,
46
        CreatePrestigeLogInterface $createPrestigeLog,
47
        LeaveFleetInterface $leaveFleet,
48
        EntryCreatorInterface $entryCreator,
49
        PrivateMessageSenderInterface $privateMessageSender,
50
        GameControllerInterface $game
51
    ) {
52 15
        $this->shipTakeoverRepository = $shipTakeoverRepository;
53 15
        $this->shipRepository = $shipRepository;
54 15
        $this->storageRepository = $storageRepository;
55 15
        $this->createPrestigeLog = $createPrestigeLog;
56 15
        $this->leaveFleet = $leaveFleet;
57 15
        $this->entryCreator = $entryCreator;
58 15
        $this->privateMessageSender = $privateMessageSender;
59 15
        $this->game = $game;
60
    }
61
62 2
    public function getPrestigeForBoardingAttempt(ShipInterface $target): int
63
    {
64 2
        return (int)ceil($this->getPrestigeForTakeover($target) / 10);
65
    }
66
67 2
    public function getPrestigeForTakeover(ShipInterface $target): int
68
    {
69 2
        $buildplan = $target->getBuildplan();
70 2
        if ($buildplan === null) {
71 1
            return self::BOARDING_PRESTIGE_PER_TRY;
72
        }
73
74 1
        return array_reduce(
75 1
            $buildplan->getModules()->toArray(),
76 1
            fn (int $value, BuildplanModuleInterface $buildplanModule) => $value + $buildplanModule->getModule()->getLevel() * self::BOARDING_PRESTIGE_PER_MODULE_LEVEL,
77 1
            self::BOARDING_PRESTIGE_PER_TRY
78 1
        );
79
    }
80
81 2
    public function startTakeover(ShipInterface $source, ShipInterface $target, int $prestige): void
82
    {
83 2
        $takeover = $this->shipTakeoverRepository->prototype();
84 2
        $takeover
85 2
            ->setSourceShip($source)
86 2
            ->setTargetShip($target)
87 2
            ->setPrestige($prestige)
88 2
            ->setStartTurn($this->game->getCurrentRound()->getTurn());
89
90 2
        $this->shipTakeoverRepository->save($takeover);
91
92 2
        $source->setTakeoverActive($takeover);
93
94 2
        $this->createPrestigeLog->createLog(
95 2
            -$prestige,
96 2
            sprintf(
97 2
                '-%d Prestige erhalten für den Start der Übernahme der %s von Spieler %s',
98 2
                $prestige,
99 2
                $target->getName(),
100 2
                $target->getUser()->getName()
101 2
            ),
102 2
            $source->getUser(),
103 2
            time()
104 2
        );
105
106 2
        $isFleet = $target->getFleet() !== null;
107 2
        if ($isFleet) {
108 1
            $this->leaveFleet->leaveFleet($target);
109
        }
110
111 2
        $this->sendStartPm($takeover, $isFleet);
112
    }
113
114
115 2
    private function sendStartPm(ShipTakeoverInterface $takeover, bool $leftFleet): void
116
    {
117 2
        $sourceShip = $takeover->getSourceShip();
118 2
        $sourceUser = $sourceShip->getUser();
119 2
        $target = $takeover->getTargetShip();
120 2
        $targetUser = $target->getUser();
121
122 2
        $href = sprintf('ship.php?%s=1&id=%d', ShowShip::VIEW_IDENTIFIER, $target->getId());
123
124 2
        $this->privateMessageSender->send(
125 2
            $sourceUser->getId(),
126 2
            $targetUser->getId(),
127 2
            sprintf(
128 2
                "Die %s von Spieler %s hat mit der Übernahme der %s begonnen.\n%s\n\nÜbernahme erfolgt in %d Runden.",
129 2
                $sourceShip->getName(),
130 2
                $sourceUser->getName(),
131 2
                $target->getName(),
132 2
                $leftFleet ? 'Die Flotte wurde daher verlassen.' : '',
133 2
                self::TURNS_TO_TAKEOVER
134 2
            ),
135 2
            PrivateMessageFolderSpecialEnum::PM_SPECIAL_SHIP,
136 2
            $href
137 2
        );
138
    }
139
140 2
    public function isTakeoverReady(ShipTakeoverInterface $takeover): bool
141
    {
142 2
        $remainingTurns = $takeover->getStartTurn() + self::TURNS_TO_TAKEOVER - $this->game->getCurrentRound()->getTurn();
143 2
        if ($remainingTurns <= 0) {
144 1
            return true;
145
        }
146
147
        // message to owner of target ship
148 1
        $this->sendRemainingPm(
149 1
            $takeover,
150 1
            $takeover->getSourceShip()->getUser()->getId(),
151 1
            $takeover->getTargetShip(),
152 1
            $remainingTurns
153 1
        );
154
155
        // message to owner of source ship
156 1
        $this->sendRemainingPm(
157 1
            $takeover,
158 1
            UserEnum::USER_NOONE,
159 1
            $takeover->getSourceShip(),
160 1
            $remainingTurns
161 1
        );
162
163 1
        return false;
164
    }
165
166 1
    private function sendRemainingPm(
167
        ShipTakeoverInterface $takeover,
168
        int $fromId,
169
        ShipInterface $linked,
170
        int $remainingTurns
171
    ): void {
172 1
        $href = sprintf('ship.php?%s=1&id=%d', ShowShip::VIEW_IDENTIFIER, $linked->getId());
173
174 1
        $this->privateMessageSender->send(
175 1
            $fromId,
176 1
            $linked->getUser()->getId(),
177 1
            sprintf(
178 1
                'Die Übernahme der %s durch die %s erfolgt in %d Runde(n).',
179 1
                $takeover->getTargetShip()->getName(),
180 1
                $takeover->getSourceShip()->getName(),
181 1
                $remainingTurns
182 1
            ),
183 1
            PrivateMessageFolderSpecialEnum::PM_SPECIAL_SHIP,
184 1
            $href
185 1
        );
186
    }
187
188 4
    public function cancelTakeover(
189
        ?ShipTakeoverInterface $takeover,
190
        string $cause = null,
191
        bool $force = false
192
    ): void {
193
194 4
        if ($takeover === null) {
195 2
            return;
196
        }
197
198 2
        if (!$force && $this->isTargetTractoredBySource($takeover)) {
199
            return;
200
        }
201
202
        // message to owner of target ship
203 2
        $this->sendCancelPm(
204 2
            $takeover,
205 2
            $takeover->getSourceShip()->getUser()->getId(),
206 2
            $takeover->getTargetShip(),
207 2
            $cause
208 2
        );
209
210
        // message to owner of source ship
211 2
        $this->sendCancelPm(
212 2
            $takeover,
213 2
            UserEnum::USER_NOONE,
214 2
            $takeover->getSourceShip(),
215 2
            $cause
216 2
        );
217
218 2
        $this->createPrestigeLog->createLog(
219 2
            $takeover->getPrestige(),
220 2
            sprintf(
221 2
                '%d Prestige erhalten für Abbruch der Übernahme der %s von Spieler %s',
222 2
                $takeover->getPrestige(),
223 2
                $takeover->getTargetShip()->getName(),
224 2
                $takeover->getTargetShip()->getUser()->getName()
225 2
            ),
226 2
            $takeover->getSourceShip()->getUser(),
227 2
            time()
228 2
        );
229
230 2
        $this->removeTakeover($takeover);
231
    }
232
233 2
    private function isTargetTractoredBySource(ShipTakeoverInterface $takeover): bool
234
    {
235 2
        return $takeover->getSourceShip() === $takeover->getTargetShip()->getTractoringShip();
236
    }
237
238
    public function cancelBothTakeover(ShipInterface $ship, string $passiveCause = null): void
239
    {
240
        $this->cancelTakeover(
241
            $ship->getTakeoverActive()
242
        );
243
244
        $this->cancelTakeover(
245
            $ship->getTakeoverPassive(),
246
            $passiveCause
247
        );
248
    }
249
250 2
    private function sendCancelPm(
251
        ShipTakeoverInterface $takeover,
252
        int $fromId,
253
        ShipInterface $linked,
254
        ?string $cause
255
    ): void {
256 2
        $href = sprintf('ship.php?%s=1&id=%d', ShowShip::VIEW_IDENTIFIER, $linked->getId());
257
258 2
        $this->privateMessageSender->send(
259 2
            $fromId,
260 2
            $linked->getUser()->getId(),
261 2
            sprintf(
262 2
                'Die Übernahme der %s wurde abgebrochen%s',
263 2
                $takeover->getTargetShip()->getName(),
264 2
                $cause ?? ''
265 2
            ),
266 2
            PrivateMessageFolderSpecialEnum::PM_SPECIAL_SHIP,
267 2
            $href
268 2
        );
269
    }
270
271 1
    public function finishTakeover(ShipTakeoverInterface $takeover): void
272
    {
273 1
        $sourceUser = $takeover->getSourceShip()->getUser();
274 1
        $targetShip = $takeover->getTargetShip();
275 1
        $targetUser = $targetShip->getUser();
276
277
        // message to previous owner of target ship
278 1
        $this->sendFinishedPm(
279 1
            $takeover,
280 1
            $sourceUser->getId(),
281 1
            $targetUser,
282 1
            sprintf(
283 1
                'Die %s wurde von Spieler %s übernommen',
284 1
                $targetShip->getName(),
285 1
                $sourceUser->getName()
286 1
            ),
287 1
            false
288 1
        );
289
290
        // message to new owner of target ship
291 1
        $this->sendFinishedPm(
292 1
            $takeover,
293 1
            UserEnum::USER_NOONE,
294 1
            $sourceUser,
295 1
            sprintf(
296 1
                'Die %s von Spieler %s wurde übernommen',
297 1
                $targetShip->getName(),
298 1
                $targetUser->getName()
299 1
            ),
300 1
            true
301 1
        );
302
303 1
        $this->entryCreator->addShipEntry(sprintf(
304 1
            _('Die %s (%s) von Spieler %s wurde in Sektor %s durch %s übernommen'),
305 1
            $targetShip->getName(),
306 1
            $targetShip->getRump()->getName(),
307 1
            $targetUser->getName(),
308 1
            $targetShip->getSectorString(),
309 1
            $sourceUser->getName()
310 1
        ));
311
312 1
        $this->changeShipOwner($targetShip, $sourceUser);
313
314 1
        $this->removeTakeover($takeover);
315
    }
316
317 1
    private function changeShipOwner(ShipInterface $ship, UserInterface $user): void
318
    {
319 1
        $ship->setUser($user);
320 1
        $this->shipRepository->save($ship);
321
322
        // change storage owner
323 1
        foreach ($ship->getStorage() as $storage) { #
324
325 1
            if ($storage->getCommodity()->isBoundToAccount()) {
326 1
                $ship->getStorage()->removeElement($storage);
327 1
                $this->storageRepository->delete($storage);
328
            } else {
329 1
                $storage->setUser($user);
330 1
                $this->storageRepository->save($storage);
331
            }
332
        }
333
    }
334
335 1
    private function sendFinishedPm(
336
        ShipTakeoverInterface $takeover,
337
        int $fromId,
338
        UserInterface $to,
339
        string $message,
340
        bool $addHref
341
    ): void {
342 1
        $href = sprintf('ship.php?%s=1&id=%d', ShowShip::VIEW_IDENTIFIER, $takeover->getTargetShip()->getId());
343
344 1
        $this->privateMessageSender->send(
345 1
            $fromId,
346 1
            $to->getId(),
347 1
            $message,
348 1
            PrivateMessageFolderSpecialEnum::PM_SPECIAL_SHIP,
349 1
            $addHref ? $href : null
350 1
        );
351
    }
352
353 3
    private function removeTakeover(ShipTakeoverInterface $takeover): void
354
    {
355 3
        $sourceShip = $takeover->getSourceShip();
356 3
        $sourceShip
357 3
            ->setTakeoverActive(null)
358 3
            ->setState(ShipStateEnum::SHIP_STATE_NONE);
359
360 3
        $takeover->getTargetShip()->setTakeoverPassive(null);
361
362 3
        $this->shipTakeoverRepository->delete($takeover);
363 3
        $this->shipRepository->save($sourceShip);
364
    }
365
}
366