Passed
Push — master ( 288b46...98b0e3 )
by Nico
31:30 queued 08:00
created

ShipLeaver::dumpCrewman()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 35
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 21
c 0
b 0
f 0
nc 3
nop 2
dl 0
loc 35
ccs 0
cts 22
cp 0
crap 12
rs 9.584
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Ship\Lib\Crew;
6
7
use RuntimeException;
8
use Stu\Component\Ship\ShipRumpEnum;
9
use Stu\Component\Ship\ShipStateEnum;
10
use Stu\Component\Ship\System\ShipSystemManagerInterface;
11
use Stu\Module\Message\Lib\PrivateMessageFolderSpecialEnum;
12
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
13
use Stu\Module\Ship\Lib\AstroEntryLibInterface;
14
use Stu\Module\Ship\Lib\Crew\LaunchEscapePodsInterface;
15
use Stu\Module\Ship\Lib\Fleet\LeaveFleetInterface;
16
use Stu\Module\Ship\Lib\ShipWrapperInterface;
17
use Stu\Orm\Entity\ShipCrewInterface;
18
use Stu\Orm\Entity\ShipInterface;
19
use Stu\Orm\Entity\UserInterface;
20
use Stu\Orm\Repository\CrewRepositoryInterface;
21
use Stu\Orm\Repository\ShipCrewRepositoryInterface;
22
use Stu\Orm\Repository\ShipRepositoryInterface;
23
use Stu\Orm\Repository\ShipRumpRepositoryInterface;
24
25
//TODO unit tests
26
final class ShipLeaver implements ShipLeaverInterface
27
{
28
    private ShipCrewRepositoryInterface $shipCrewRepository;
29
30
    private ShipRepositoryInterface $shipRepository;
31
32
    private ShipRumpRepositoryInterface $shipRumpRepository;
33
34
    private ShipSystemManagerInterface $shipSystemManager;
35
36
    private CrewRepositoryInterface $crewRepository;
37
38
    private AstroEntryLibInterface $astroEntryLib;
39
40
    private LeaveFleetInterface $leaveFleet;
41
42
    private LaunchEscapePodsInterface $launchEscapePods;
43
44
    private PrivateMessageSenderInterface $privateMessageSender;
45
46 1
    public function __construct(
47
        ShipCrewRepositoryInterface $shipCrewRepository,
48
        ShipRepositoryInterface $shipRepository,
49
        ShipRumpRepositoryInterface $shipRumpRepository,
50
        ShipSystemManagerInterface $shipSystemManager,
51
        CrewRepositoryInterface $crewRepository,
52
        AstroEntryLibInterface $astroEntryLib,
53
        LeaveFleetInterface $leaveFleet,
54
        LaunchEscapePodsInterface $launchEscapePods,
55
        PrivateMessageSenderInterface $privateMessageSender
56
    ) {
57 1
        $this->shipCrewRepository = $shipCrewRepository;
58 1
        $this->shipRepository = $shipRepository;
59 1
        $this->shipRumpRepository = $shipRumpRepository;
60 1
        $this->shipSystemManager = $shipSystemManager;
61 1
        $this->crewRepository = $crewRepository;
62 1
        $this->astroEntryLib = $astroEntryLib;
63 1
        $this->leaveFleet = $leaveFleet;
64 1
        $this->launchEscapePods = $launchEscapePods;
65 1
        $this->privateMessageSender = $privateMessageSender;
66
    }
67
68
    public function evacuate(ShipWrapperInterface $wrapper): string
69
    {
70
        $this->shipSystemManager->deactivateAll($wrapper);
71
72
        $ship = $wrapper->get();
73
74
        $this->leaveFleet->leaveFleet($ship);
75
76
        if ($ship->getDockedShipCount() > 0) {
77
            $this->undockShips($ship);
78
        }
79
80
        if ($ship->getState() === ShipStateEnum::SHIP_STATE_ASTRO_FINALIZING) {
81
            $this->astroEntryLib->cancelAstroFinalizing($ship);
82
        }
83
84
        $ship->setAlertStateGreen();
85
        $ship->setDockedTo(null);
86
        $this->shipRepository->save($ship);
87
88
        if ($ship->getRump()->isEscapePods()) {
89
            $this->letCrewDie($ship);
90
            return _('Die Rettungskapseln wurden zerstört, die Crew ist daher verstorben!');
91
        }
92
93
        $podRump = $this->shipRumpRepository->find($ship->getUser()->getFactionId() + ShipRumpEnum::SHIP_RUMP_BASE_ID_ESCAPE_PODS);
94
95
        if ($podRump === null) {
96
            $this->letCrewDie($ship);
97
            return _('Keine Rettungskapseln vorhanden, die Crew ist daher verstorben!');
98
        }
99
100
        $this->escapeIntoPods($ship);
101
102
        return _('Die Crew hat das Schiff in den Rettungskapseln verlassen!');
103
    }
104
105
    private function escapeIntoPods(ShipInterface $ship): void
106
    {
107
        //create pods entity
108
        $pods = $this->launchEscapePods->launch($ship);
109
110
        //transfer crew into pods
111
        //TODO not all...! depends on race config
112
        $crewList = $ship->getCrewlist();
113
        foreach ($crewList as $shipCrew) {
114
            $shipCrew->setShip($pods);
115
            $shipCrew->setSlot(null);
116
            $this->shipCrewRepository->save($shipCrew);
117
        }
118
    }
119
120
    public function dumpCrewman(ShipCrewInterface $shipCrew, string $message): string
121
    {
122
        $ship = $shipCrew->getShip();
123
        if ($ship === null) {
124
            throw new RuntimeException('can only dump crewman on ship');
125
        }
126
127
        //create pods entity
128
        $pods = $this->launchEscapePods->launch($ship);
129
130
        if ($pods == null) {
131
            $crew = $shipCrew->getCrew();
132
            $this->shipCrewRepository->delete($shipCrew);
133
            $this->crewRepository->delete($crew);
134
135
            $survivalMessage = _('Der Crewman wurde exekutiert!');
136
        } else {
137
138
            //transfer crewman into pods
139
            $shipCrew->setShip($pods);
140
            $shipCrew->setShipId($pods->getId());
141
            $ship->getCrewlist()->removeElement($shipCrew);
142
            $this->shipCrewRepository->save($shipCrew);
143
144
            $survivalMessage = _('Der Crewman hat das Schiff in einer Rettungskapsel verlassen!');
145
        }
146
147
        $this->sendPmToOwner(
148
            $ship->getUser(),
149
            $shipCrew->getUser(),
150
            $message,
151
            $survivalMessage
152
        );
153
154
        return $survivalMessage;
155
    }
156
157
    private function sendPmToOwner(
158
        UserInterface $sender,
159
        UserInterface $owner,
160
        string $message,
161
        string $survivalMessage
162
    ): void {
163
        $this->privateMessageSender->send(
164
            $sender->getId(),
165
            $owner->getId(),
166
            sprintf(
167
                "%s\n%s",
168
                $message,
169
                $survivalMessage
170
            ),
171
            PrivateMessageFolderSpecialEnum::PM_SPECIAL_SYSTEM
172
        );
173
    }
174
175
    private function letCrewDie(ShipInterface $ship): void
176
    {
177
        $crewArray = [];
178
        foreach ($ship->getCrewlist() as $shipCrew) {
179
            $crewArray[] = $shipCrew->getCrew();
180
        }
181
182
        $this->shipCrewRepository->truncateByShip($ship->getId());
183
184
        foreach ($crewArray as $crew) {
185
            $this->crewRepository->delete($crew);
186
        }
187
    }
188
189
    private function undockShips(ShipInterface $ship): void
190
    {
191
        foreach ($ship->getDockedShips() as $dockedShip) {
192
            $dockedShip->setDockedTo(null);
193
            $this->shipRepository->save($dockedShip);
194
        }
195
    }
196
}
197