Passed
Push — dev ( a4e368...70a2b2 )
by Janko
26:40
created

ShipTakeoverManager   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 265
Duplicated Lines 0 %

Test Coverage

Coverage 94.41%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 136
c 1
b 0
f 0
dl 0
loc 265
ccs 152
cts 161
cp 0.9441
rs 10
wmc 19

13 Methods

Rating   Name   Duplication   Size   Complexity  
A getPrestigeForBoardingAttempt() 0 3 1
A __construct() 0 12 1
A getPrestigeForTakeover() 0 11 2
A sendRemainingPm() 0 19 1
A startTakeover() 0 23 1
A isTakeoverReady() 0 24 2
A removeTakeover() 0 5 1
A cancelTakeover() 0 43 4
A finishTakeover() 0 35 1
A isTargetTractoredBySource() 0 3 1
A cancelBothTakeover() 0 9 1
A sendFinishedPm() 0 15 2
A sendCancelPm() 0 18 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Ship\Lib\Interaction;
6
7
use Stu\Component\Ship\ShipEnum;
8
use Stu\Module\Control\GameControllerInterface;
9
use Stu\Module\Message\Lib\PrivateMessageFolderSpecialEnum;
10
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
11
use Stu\Module\PlayerSetting\Lib\UserEnum;
12
use Stu\Module\Prestige\Lib\CreatePrestigeLogInterface;
13
use Stu\Module\Ship\View\ShowShip\ShowShip;
14
use Stu\Orm\Entity\BuildplanModuleInterface;
15
use Stu\Orm\Entity\ShipInterface;
16
use Stu\Orm\Entity\ShipTakeoverInterface;
17
use Stu\Orm\Entity\UserInterface;
18
use Stu\Orm\Repository\ShipRepositoryInterface;
19
use Stu\Orm\Repository\ShipTakeoverRepositoryInterface;
20
21
final class ShipTakeoverManager implements ShipTakeoverManagerInterface
22
{
23
    public const BOARDING_PRESTIGE_PER_TRY = 200;
24
    public const BOARDING_PRESTIGE_PER_MODULE_LEVEL = 10;
25
26
    private ShipTakeoverRepositoryInterface $shipTakeoverRepository;
27
28
    private ShipRepositoryInterface $shipRepository;
29
30
    private CreatePrestigeLogInterface $createPrestigeLog;
31
32
    private PrivateMessageSenderInterface $privateMessageSender;
33
34
    private GameControllerInterface $game;
35
36 14
    public function __construct(
37
        ShipTakeoverRepositoryInterface $shipTakeoverRepository,
38
        ShipRepositoryInterface $shipRepository,
39
        CreatePrestigeLogInterface $createPrestigeLog,
40
        PrivateMessageSenderInterface $privateMessageSender,
41
        GameControllerInterface $game
42
    ) {
43 14
        $this->shipTakeoverRepository = $shipTakeoverRepository;
44 14
        $this->shipRepository = $shipRepository;
45 14
        $this->createPrestigeLog = $createPrestigeLog;
46 14
        $this->privateMessageSender = $privateMessageSender;
47 14
        $this->game = $game;
48
    }
49
50 2
    public function getPrestigeForBoardingAttempt(ShipInterface $target): int
51
    {
52 2
        return (int)ceil($this->getPrestigeForTakeover($target) / 10);
53
    }
54
55 2
    public function getPrestigeForTakeover(ShipInterface $target): int
56
    {
57 2
        $buildplan = $target->getBuildplan();
58 2
        if ($buildplan === null) {
59 1
            return self::BOARDING_PRESTIGE_PER_TRY;
60
        }
61
62 1
        return array_reduce(
63 1
            $buildplan->getModules()->toArray(),
64 1
            fn (int $value, BuildplanModuleInterface $buildplanModule) => $value + $buildplanModule->getModule()->getLevel() * self::BOARDING_PRESTIGE_PER_MODULE_LEVEL,
65 1
            self::BOARDING_PRESTIGE_PER_TRY
66 1
        );
67
    }
68
69 1
    public function startTakeover(ShipInterface $source, ShipInterface $target, int $prestige): void
70
    {
71 1
        $takeover = $this->shipTakeoverRepository->prototype();
72 1
        $takeover
73 1
            ->setSourceShip($source)
74 1
            ->setTargetShip($target)
75 1
            ->setPrestige($prestige)
76 1
            ->setStartTurn($this->game->getCurrentRound()->getTurn());
77
78 1
        $this->shipTakeoverRepository->save($takeover);
79
80 1
        $source->setTakeoverActive($takeover);
81
82 1
        $this->createPrestigeLog->createLog(
83 1
            -$prestige,
84 1
            sprintf(
85 1
                '-%d Prestige erhalten für den Start der Übernahme der %s von Spieler %s',
86 1
                $prestige,
87 1
                $target->getName(),
88 1
                $target->getUser()->getName()
89 1
            ),
90 1
            $source->getUser(),
91 1
            time()
92 1
        );
93
    }
94
95 2
    public function isTakeoverReady(ShipTakeoverInterface $takeover): bool
96
    {
97 2
        $remainingTurns = $takeover->getStartTurn() + ShipEnum::TURNS_TO_TAKEOVER - $this->game->getCurrentRound()->getTurn();
98 2
        if ($remainingTurns <= 0) {
99 1
            return true;
100
        }
101
102
        // message to owner of target ship
103 1
        $this->sendRemainingPm(
104 1
            $takeover,
105 1
            $takeover->getSourceShip()->getUser()->getId(),
106 1
            $takeover->getTargetShip(),
107 1
            $remainingTurns
108 1
        );
109
110
        // message to owner of source ship
111 1
        $this->sendRemainingPm(
112 1
            $takeover,
113 1
            UserEnum::USER_NOONE,
114 1
            $takeover->getSourceShip(),
115 1
            $remainingTurns
116 1
        );
117
118 1
        return false;
119
    }
120
121 1
    private function sendRemainingPm(
122
        ShipTakeoverInterface $takeover,
123
        int $fromId,
124
        ShipInterface $linked,
125
        int $remainingTurns
126
    ): void {
127 1
        $href = sprintf('ship.php?%s=1&id=%d', ShowShip::VIEW_IDENTIFIER, $linked->getId());
128
129 1
        $this->privateMessageSender->send(
130 1
            $fromId,
131 1
            $linked->getUser()->getId(),
132 1
            sprintf(
133 1
                'Die Übernahme der %s durch die %s erfolgt in %d Runde(n).',
134 1
                $takeover->getTargetShip()->getName(),
135 1
                $takeover->getSourceShip()->getName(),
136 1
                $remainingTurns
137 1
            ),
138 1
            PrivateMessageFolderSpecialEnum::PM_SPECIAL_SHIP,
139 1
            $href
140 1
        );
141
    }
142
143 4
    public function cancelTakeover(
144
        ?ShipTakeoverInterface $takeover,
145
        string $cause = null,
146
        bool $force = false
147
    ): void {
148
149 4
        if ($takeover === null) {
150 2
            return;
151
        }
152
153 2
        if (!$force && $this->isTargetTractoredBySource($takeover)) {
154
            return;
155
        }
156
157
        // message to owner of target ship
158 2
        $this->sendCancelPm(
159 2
            $takeover,
160 2
            $takeover->getSourceShip()->getUser()->getId(),
161 2
            $takeover->getTargetShip(),
162 2
            $cause
163 2
        );
164
165
        // message to owner of source ship
166 2
        $this->sendCancelPm(
167 2
            $takeover,
168 2
            UserEnum::USER_NOONE,
169 2
            $takeover->getSourceShip(),
170 2
            $cause
171 2
        );
172
173 2
        $this->createPrestigeLog->createLog(
174 2
            $takeover->getPrestige(),
175 2
            sprintf(
176 2
                '%d Prestige erhalten für Abbruch der Übernahme der %s von Spieler %s',
177 2
                $takeover->getPrestige(),
178 2
                $takeover->getTargetShip()->getName(),
179 2
                $takeover->getTargetShip()->getUser()->getName()
180 2
            ),
181 2
            $takeover->getSourceShip()->getUser(),
182 2
            time()
183 2
        );
184
185 2
        $this->removeTakeover($takeover);
186
    }
187
188 2
    private function isTargetTractoredBySource(ShipTakeoverInterface $takeover): bool
189
    {
190 2
        return $takeover->getSourceShip() === $takeover->getTargetShip()->getTractoringShip();
191
    }
192
193
    public function cancelBothTakeover(ShipInterface $ship, string $passiveCause = null): void
194
    {
195
        $this->cancelTakeover(
196
            $ship->getTakeoverActive()
197
        );
198
199
        $this->cancelTakeover(
200
            $ship->getTakeoverPassive(),
201
            $passiveCause
202
        );
203
    }
204
205 2
    private function sendCancelPm(
206
        ShipTakeoverInterface $takeover,
207
        int $fromId,
208
        ShipInterface $linked,
209
        ?string $cause
210
    ): void {
211 2
        $href = sprintf('ship.php?%s=1&id=%d', ShowShip::VIEW_IDENTIFIER, $linked->getId());
212
213 2
        $this->privateMessageSender->send(
214 2
            $fromId,
215 2
            $linked->getUser()->getId(),
216 2
            sprintf(
217 2
                'Die Übernahme der %s wurde abgebrochen%s',
218 2
                $takeover->getTargetShip()->getName(),
219 2
                $cause ?? ''
220 2
            ),
221 2
            PrivateMessageFolderSpecialEnum::PM_SPECIAL_SHIP,
222 2
            $href
223 2
        );
224
    }
225
226 1
    public function finishTakeover(ShipTakeoverInterface $takeover): void
227
    {
228 1
        $sourceUser = $takeover->getSourceShip()->getUser();
229 1
        $targetShip = $takeover->getTargetShip();
230
231
        // message to previous owner of target ship
232 1
        $this->sendFinishedPm(
233 1
            $takeover,
234 1
            $sourceUser->getId(),
235 1
            $targetShip->getUser(),
236 1
            sprintf(
237 1
                'Die %s wurde von Spieler %s übernommen',
238 1
                $targetShip->getName(),
239 1
                $sourceUser->getName()
240 1
            ),
241 1
            false
242 1
        );
243
244
        // message to new owner of target ship
245 1
        $this->sendFinishedPm(
246 1
            $takeover,
247 1
            UserEnum::USER_NOONE,
248 1
            $sourceUser,
249 1
            sprintf(
250 1
                'Die %s von Spieler %s wurde übernommen',
251 1
                $targetShip->getName(),
252 1
                $targetShip->getUser()->getName()
253 1
            ),
254 1
            true
255 1
        );
256
257 1
        $targetShip->setUser($sourceUser);
258 1
        $this->shipRepository->save($targetShip);
259
260 1
        $this->removeTakeover($takeover);
261
    }
262
263 1
    private function sendFinishedPm(
264
        ShipTakeoverInterface $takeover,
265
        int $fromId,
266
        UserInterface $to,
267
        string $message,
268
        bool $addHref
269
    ): void {
270 1
        $href = sprintf('ship.php?%s=1&id=%d', ShowShip::VIEW_IDENTIFIER, $takeover->getTargetShip()->getId());
271
272 1
        $this->privateMessageSender->send(
273 1
            $fromId,
274 1
            $to->getId(),
275 1
            $message,
276 1
            PrivateMessageFolderSpecialEnum::PM_SPECIAL_SHIP,
277 1
            $addHref ? $href : null
278 1
        );
279
    }
280
281 3
    private function removeTakeover(ShipTakeoverInterface $takeover): void
282
    {
283 3
        $takeover->getSourceShip()->setTakeoverActive(null);
284 3
        $takeover->getTargetShip()->setTakeoverPassive(null);
285 3
        $this->shipTakeoverRepository->delete($takeover);
286
    }
287
}
288