Passed
Push — master ( 3b0b34...71d31a )
by Nico
05:19
created

ShipTakeoverManager::cancelTakeover()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 46
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 29
CRAP Score 5.0009

Importance

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