Passed
Push — dev ( eeaa0f...91a85a )
by Janko
26:10
created

CrewLimitations::work()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 0
dl 0
loc 12
ccs 0
cts 6
cp 0
crap 12
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Tick\Ship\ManagerComponent;
6
7
use InvalidArgumentException;
8
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...
9
use Stu\Component\Event\EventManagerInterface;
10
use Stu\Component\Event\EventQueueInterface;
11
use Stu\Component\Event\EventTypeEnum;
12
use Stu\Component\Event\Payload\PayloadWithId;
13
use Stu\Component\Player\CrewLimitCalculatorInterface;
14
use Stu\Component\Ship\System\ShipSystemManagerInterface;
15
use Stu\Module\Message\Lib\PrivateMessageFolderTypeEnum;
16
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
17
use Stu\Module\PlayerSetting\Lib\UserEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Module\PlayerSetting\Lib\UserEnum 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...
18
use Stu\Module\Ship\Lib\ShipWrapperFactoryInterface;
19
use Stu\Module\Tick\User\UserTickComponentInterface;
20
use Stu\Orm\Entity\UserInterface;
21
use Stu\Orm\Repository\CrewRepositoryInterface;
22
use Stu\Orm\Repository\ShipCrewRepositoryInterface;
23
use Stu\Orm\Repository\ShipRepositoryInterface;
24
use Stu\Orm\Repository\UserRepositoryInterface;
25
26
final class CrewLimitations implements ManagerComponentInterface, UserTickComponentInterface
27
{
28
    public function __construct(
29
        private PrivateMessageSenderInterface $privateMessageSender,
30
        private ShipRepositoryInterface $shipRepository,
31
        private UserRepositoryInterface $userRepository,
32
        private CrewRepositoryInterface $crewRepository,
33
        private ShipCrewRepositoryInterface $shipCrewRepository,
34
        private ShipSystemManagerInterface $shipSystemManager,
35
        private ShipWrapperFactoryInterface $shipWrapperFactory,
36
        private CrewLimitCalculatorInterface $crewLimitCalculator,
37
        private EventManagerInterface $eventManager,
38
        private EventQueueInterface $eventQueue
39
    ) {
40
    }
41
42
    #[Override]
43
    public function processUser(UserInterface $user): void
44
    {
45
        $userId = $user->getId();
46
47
        $crewLimit = $this->crewLimitCalculator->getGlobalCrewLimit($user);
48
        $crewOnColonies = $this->shipCrewRepository->getAmountByUserOnColonies($user->getId());
49
        $crewOnShips = $this->shipCrewRepository->getAmountByUserOnShips($user);
50
        $crewAtTradeposts = $this->shipCrewRepository->getAmountByUserAtTradeposts($user);
51
52
        $crewToQuit = max(0, $crewOnColonies + $crewOnShips + $crewAtTradeposts - $crewLimit);
53
54
        //mutiny order: colonies, ships, tradeposts, escape pods
55
        if ($crewToQuit > 0 && $crewOnColonies > 0) {
56
            $crewToQuit -= $this->letColonyAssignmentsQuit($userId, $crewToQuit);
57
        }
58
        if ($crewToQuit > 0 && $crewOnShips > 0) {
59
            $crewToQuit -= $this->letShipAssignmentsQuit($userId, $crewToQuit);
60
        }
61
        if ($crewToQuit > 0 && $crewAtTradeposts > 0) {
62
            $crewToQuit -= $this->letTradepostAssignmentsQuit($userId, $crewToQuit);
63
        }
64
        if ($crewToQuit > 0) {
65
            $this->letEscapePodAssignmentsQuit($userId, $crewToQuit);
66
        }
67
    }
68
69
    #[Override]
70
    public function work(): void
71
    {
72
        $userList = $this->userRepository->getNonNpcList();
73
74
        foreach ($userList as $user) {
75
            //only handle user that are not on vacation
76
            if ($user->isVacationRequestOldEnough()) {
77
                return;
78
            }
79
80
            $this->processUser($user);
81
        }
82
    }
83
84
    private function letColonyAssignmentsQuit(int $userId, int $crewToQuit): int
85
    {
86
        $amount = 0;
87
88
        foreach ($this->shipCrewRepository->getByUserAtColonies($userId) as $crewAssignment) {
89
            if ($amount === $crewToQuit) {
90
                break;
91
            }
92
93
            $amount++;
94
            $this->crewRepository->delete($crewAssignment->getCrew());
95
        }
96
97
        if ($amount > 0) {
98
            $msg = sprintf(_('Wegen Überschreitung des globalen Crewlimits haben %d Crewman ihren Dienst auf deinen Kolonien quittiert'), $amount);
99
            $this->privateMessageSender->send(
100
                UserEnum::USER_NOONE,
101
                $userId,
102
                $msg,
103
                PrivateMessageFolderTypeEnum::SPECIAL_COLONY
104
            );
105
        }
106
107
        return $amount;
108
    }
109
110
    private function letTradepostAssignmentsQuit(int $userId, int $crewToQuit): int
111
    {
112
        $amount = 0;
113
114
        foreach ($this->shipCrewRepository->getByUserAtTradeposts($userId) as $crewAssignment) {
115
            if ($amount === $crewToQuit) {
116
                break;
117
            }
118
119
            $amount++;
120
            $this->crewRepository->delete($crewAssignment->getCrew());
121
        }
122
123
        if ($amount > 0) {
124
            $msg = sprintf(_('Wegen Überschreitung des globalen Crewlimits haben %d deiner Crewman auf Handelsposten ihren Dienst quittiert'), $amount);
125
            $this->privateMessageSender->send(
126
                UserEnum::USER_NOONE,
127
                $userId,
128
                $msg,
129
                PrivateMessageFolderTypeEnum::SPECIAL_SYSTEM
130
            );
131
        }
132
133
        return $amount;
134
    }
135
136
    private function letEscapePodAssignmentsQuit(int $userId, int $crewToQuit): int
137
    {
138
        $amount = 0;
139
140
        foreach ($this->shipCrewRepository->getByUserOnEscapePods($userId) as $crewAssignment) {
141
            if ($amount === $crewToQuit) {
142
                break;
143
            }
144
145
            $amount++;
146
            $this->crewRepository->delete($crewAssignment->getCrew());
147
        }
148
149
        if ($amount > 0) {
150
            $msg = sprintf(_('Wegen Überschreitung des globalen Crewlimits haben %d deiner Crewman auf Fluchtkapseln ihren Dienst quittiert'), $amount);
151
            $this->privateMessageSender->send(
152
                UserEnum::USER_NOONE,
153
                $userId,
154
                $msg,
155
                PrivateMessageFolderTypeEnum::SPECIAL_SYSTEM
156
            );
157
        }
158
159
        return $amount;
160
    }
161
162
    private function letShipAssignmentsQuit(int $userId, int $crewToQuit): int
163
    {
164
        $wipedShipsIds = [];
165
        $amount = 0;
166
167
        $wipedShipIds = [];
168
169
        while ($amount < $crewToQuit) {
170
            $randomShipId = $this->shipRepository->getRandomShipIdWithCrewByUser($userId);
171
172
            //if no more ships available
173
            if ($randomShipId === null) {
174
                break;
175
            }
176
177
            //if ship already wiped, go to next
178
            if (in_array($randomShipId, $wipedShipIds)) {
179
                continue;
180
            }
181
182
            //wipe ship crew
183
            $wipedShipsIds[] = $randomShipId;
184
            $amount += $this->letCrewQuit($randomShipId, $userId);
185
        }
186
187
        return $amount;
188
    }
189
190
    private function letCrewQuit(int $randomShipId, int $userId): int
191
    {
192
        $randomShip = $this->shipRepository->find($randomShipId);
193
194
        if ($randomShip === null) {
195
            throw new InvalidArgumentException('randomShipId should exist');
196
        }
197
198
        $wrapper = $this->shipWrapperFactory->wrapShip($randomShip);
199
        $doAlertRedCheck = $randomShip->getWarpDriveState() || $randomShip->getCloakState();
200
        //deactivate ship
201
        $this->shipSystemManager->deactivateAll($wrapper);
202
        $randomShip->setAlertStateGreen();
203
204
        $this->shipRepository->save($randomShip);
205
206
        $crewArray = [];
207
        foreach ($randomShip->getCrewAssignments() as $shipCrew) {
208
            $crewArray[] = $shipCrew->getCrew();
209
        }
210
        $randomShip->getCrewAssignments()->clear();
211
212
        //remove crew
213
        $this->shipCrewRepository->truncateByShip($randomShipId);
214
        foreach ($crewArray as $crew) {
215
            $this->crewRepository->delete($crew);
216
        }
217
218
        $msg = sprintf(_('Wegen Überschreitung des globalen Crewlimits hat die Crew der %s gemeutert und das Schiff verlassen'), $randomShip->getName());
219
        $this->privateMessageSender->send(
220
            UserEnum::USER_NOONE,
221
            $userId,
222
            $msg,
223
            $randomShip->isBase() ? PrivateMessageFolderTypeEnum::SPECIAL_STATION : PrivateMessageFolderTypeEnum::SPECIAL_SHIP
224
        );
225
226
        //do alert red stuff
227
        if ($doAlertRedCheck) {
228
            $event = $this->eventManager->createEvent(
229
                EventTypeEnum::ALERT_REACTION,
230
                new PayloadWithId($randomShip->getId())
231
            );
232
            $this->eventQueue->addEvent($event);
233
        }
234
235
        return count($crewArray);
236
    }
237
}
238