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

ShipTakeoverManager::sendRemainingPm()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 11
nc 1
nop 4
dl 0
loc 19
ccs 13
cts 13
cp 1
crap 1
rs 9.9
c 1
b 0
f 0
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