Passed
Push — dev ( c4f015...eeaa0f )
by Janko
27:51
created

CrewLimitations::processUser()   B

Complexity

Conditions 8
Paths 16

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

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