Passed
Pull Request — master (#1716)
by Nico
23:15
created

ShipTickManager::lowerStationConstructionHull()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 13
nc 3
nop 0
dl 0
loc 19
ccs 0
cts 15
cp 0
crap 12
rs 9.8333
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Tick\Ship;
6
7
use Stu\Component\Anomaly\AnomalyHandlingInterface;
8
use Stu\Module\Colony\Lib\ColonyLibFactoryInterface;
9
use Stu\Module\History\Lib\EntryCreatorInterface;
10
use Stu\Module\Logging\LoggerEnum;
11
use Stu\Module\Logging\LoggerUtilFactoryInterface;
12
use Stu\Module\Logging\LoggerUtilInterface;
13
use Stu\Module\Message\Lib\PrivateMessageFolderSpecialEnum;
14
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
15
use Stu\Module\PlayerSetting\Lib\UserEnum;
16
use Stu\Module\Ship\Lib\ShipRemoverInterface;
17
use Stu\Module\Ship\Lib\ShipWrapperFactoryInterface;
18
use Stu\Module\Tick\AbstractTickManager;
19
use Stu\Module\Tick\Lock\LockManagerInterface;
20
use Stu\Module\Tick\Lock\LockTypeEnum;
21
use Stu\Module\Tick\Ship\Crew\CrewLimitationsInterface;
22
use Stu\Module\Tick\Ship\Repair\RepairActionsInterface;
23
use Stu\Orm\Entity\ColonyInterface;
24
use Stu\Orm\Entity\ShipInterface;
25
use Stu\Orm\Repository\ShipCrewRepositoryInterface;
26
use Stu\Orm\Repository\ShipRepositoryInterface;
27
use Stu\Orm\Repository\TradePostRepositoryInterface;
28
use Ubench;
29
30
final class ShipTickManager extends AbstractTickManager implements ShipTickManagerInterface
31
{
32
    private CrewLimitationsInterface $crewLimitations;
33
34
    private PrivateMessageSenderInterface $privateMessageSender;
35
36
    private ShipRemoverInterface $shipRemover;
37
38
    private ShipTickInterface $shipTick;
39
40
    private ShipRepositoryInterface $shipRepository;
41
42
    private ShipCrewRepositoryInterface $shipCrewRepository;
43
44
    private TradePostRepositoryInterface $tradePostRepository;
45
46
    private ShipWrapperFactoryInterface $shipWrapperFactory;
47
48
    private EntryCreatorInterface $entryCreator;
49
50
    private ColonyLibFactoryInterface $colonyLibFactory;
51
52
    private RepairActionsInterface $repairActions;
53
54
    private AnomalyHandlingInterface $anomalyHandling;
55
56
    private LockManagerInterface $lockManager;
57
58
    private LoggerUtilInterface $loggerUtil;
59
60
    private Ubench $benchmark;
61
62
    public function __construct(
63
        CrewLimitationsInterface $crewLimitations,
64
        PrivateMessageSenderInterface $privateMessageSender,
65
        ShipRemoverInterface $shipRemover,
66
        ShipTickInterface $shipTick,
67
        ShipRepositoryInterface $shipRepository,
68
        ShipCrewRepositoryInterface $shipCrewRepository,
69
        TradePostRepositoryInterface $tradePostRepository,
70
        ShipWrapperFactoryInterface $shipWrapperFactory,
71
        EntryCreatorInterface $entryCreator,
72
        ColonyLibFactoryInterface $colonyLibFactory,
73
        RepairActionsInterface $repairActions,
74
        AnomalyHandlingInterface $anomalyHandling,
75
        LockManagerInterface $lockManager,
76
        LoggerUtilFactoryInterface $loggerUtilFactory,
77
        Ubench $benchmark
78
    ) {
79
        $this->crewLimitations = $crewLimitations;
80
        $this->privateMessageSender = $privateMessageSender;
81
        $this->shipRemover = $shipRemover;
82
        $this->shipTick = $shipTick;
83
        $this->shipRepository = $shipRepository;
84
        $this->shipCrewRepository = $shipCrewRepository;
85
        $this->tradePostRepository = $tradePostRepository;
86
        $this->shipWrapperFactory = $shipWrapperFactory;
87
        $this->entryCreator = $entryCreator;
88
        $this->colonyLibFactory = $colonyLibFactory;
89
        $this->repairActions = $repairActions;
90
        $this->anomalyHandling = $anomalyHandling;
91
        $this->lockManager = $lockManager;
92
        $this->loggerUtil = $loggerUtilFactory->getLoggerUtil();
93
        $this->benchmark = $benchmark;
94
    }
95
96
    public function work(): void
97
    {
98
        $this->setLock(1);
99
100
        try {
101
            $this->anomalyHandling->processExistingAnomalies();
102
            $this->crewLimitations->work();
103
104
            $startTime = microtime(true);
105
            $this->handleEscapePods();
106
            if ($this->loggerUtil->doLog()) {
107
                $endTime = microtime(true);
108
                $this->loggerUtil->log(sprintf("\t\thandleEscapePods, seconds: %F", $endTime - $startTime));
109
            }
110
            $this->repairActions->work();
111
112
            $startTime = microtime(true);
113
            $entityCount = 0;
114
            foreach ($this->shipRepository->getPlayerShipsForTick() as $ship) {
115
                //echo "Processing Ship ".$ship->getId()." at ".microtime()."\n";
116
117
                $this->shipTick->work($this->shipWrapperFactory->wrapShip($ship));
118
                $entityCount++;
119
            }
120
            if ($this->loggerUtil->doLog()) {
121
                $endTime = microtime(true);
122
                $this->loggerUtil->log(sprintf("\t\tshipTick, seconds: %F", $endTime - $startTime));
123
            }
124
125
            $startTime = microtime(true);
126
            $this->handleNPCShips();
127
            if ($this->loggerUtil->doLog()) {
128
                $endTime = microtime(true);
129
                $this->loggerUtil->log(sprintf("\t\thandleNPCShips, seconds: %F", $endTime - $startTime));
130
            }
131
132
            $startTime = microtime(true);
133
            $this->lowerTrumfieldHull();
134
            $this->lowerOrphanizedTradepostHull();
135
            $this->lowerStationConstructionHull();
136
            if ($this->loggerUtil->doLog()) {
137
                $endTime = microtime(true);
138
                $this->loggerUtil->log(sprintf("\t\tloweringTrumfieldConstruction, seconds: %F", $endTime - $startTime));
139
            }
140
141
            $this->loggerUtil->init('SHIPTICK', LoggerEnum::LEVEL_WARNING);
142
            $this->logBenchmarkResult($entityCount);
143
144
            $this->anomalyHandling->createNewAnomalies();
145
        } finally {
146
            $this->clearLock(1);
147
        }
148
    }
149
150
    private function handleEscapePods(): void
151
    {
152
        $escapedToColonies = [];
153
154
        foreach ($this->shipRepository->getEscapePods() as $escapePod) {
155
            if ($escapePod->getCrewCount() === 0) {
156
                $this->shipRemover->remove($escapePod);
157
            }
158
159
            if ($escapePod->getStarsystemMap() !== null) {
160
                $colony = $escapePod->getStarsystemMap()->getColony();
161
162
                if ($colony !== null) {
163
                    $count = $this->transferOwnCrewToColony($escapePod, $colony);
164
165
                    if ($count > 0) {
166
                        if (array_key_exists($colony->getId(), $escapedToColonies)) {
167
                            $oldCount = $escapedToColonies[$colony->getId()][1];
168
169
                            $escapedToColonies[$colony->getId()][1] = $oldCount +  $count;
170
                        } else {
171
                            $escapedToColonies[$colony->getId()] = [$colony, $count];
172
                        }
173
                    }
174
                }
175
            }
176
        }
177
178
        foreach ($escapedToColonies as [$colony, $count]) {
179
            $msg = sprintf(_('%d deiner Crewman sind aus Fluchtkapseln auf deiner Kolonie %s gelandet'), $count, $colony->getName());
180
            $this->privateMessageSender->send(
181
                UserEnum::USER_NOONE,
182
                $colony->getUser()->getId(),
183
                $msg,
184
                PrivateMessageFolderSpecialEnum::PM_SPECIAL_COLONY
185
            );
186
        }
187
    }
188
189
    private function transferOwnCrewToColony(ShipInterface $escapePod, ColonyInterface $colony): int
190
    {
191
        $count = 0;
192
193
        foreach ($escapePod->getCrewAssignments() as $crewAssignment) {
194
            if ($crewAssignment->getUser() !== $colony->getUser()) {
195
                continue;
196
            }
197
198
            $freeAssignmentCount = $this->colonyLibFactory->createColonyPopulationCalculator(
199
                $colony
200
            )->getFreeAssignmentCount();
201
202
            if ($freeAssignmentCount === 0) {
203
                break;
204
            }
205
206
            $count++;
207
            $crewAssignment->setShip(null);
208
            $crewAssignment->setSlot(null);
209
            $crewAssignment->setColony($colony);
210
            $escapePod->getCrewAssignments()->removeElement($crewAssignment);
211
            $colony->getCrewAssignments()->add($crewAssignment);
212
            $this->shipCrewRepository->save($crewAssignment);
213
        }
214
215
        return $count;
216
    }
217
218
    private function lowerTrumfieldHull(): void
219
    {
220
        foreach ($this->shipRepository->getDebrisFields() as $ship) {
221
            $lower = random_int(5, 15);
222
            if ($ship->getHull() <= $lower) {
223
                $this->shipRemover->remove($ship);
224
                continue;
225
            }
226
            $ship->setHuell($ship->getHull() - $lower);
227
228
            $this->shipRepository->save($ship);
229
        }
230
    }
231
232
    private function lowerOrphanizedTradepostHull(): void
233
    {
234
        foreach ($this->tradePostRepository->getByUser(UserEnum::USER_NOONE) as $tradepost) {
235
            $ship = $tradepost->getShip();
236
237
            $lower = (int)ceil($ship->getMaxHull() / 100);
238
239
            if ($ship->getHull() <= $lower) {
240
                $this->shipRemover->destroy($this->shipWrapperFactory->wrapShip($ship));
241
242
                $this->entryCreator->addStationEntry(
243
                    'Der verlassene Handelsposten in Sektor ' . $ship->getSectorString() . ' ist zerfallen',
244
                    $ship->getUser()->getId()
245
                );
246
                continue;
247
            }
248
            $ship->setHuell($ship->getHull() - $lower);
249
250
            $this->shipRepository->save($ship);
251
        }
252
    }
253
254
    private function lowerStationConstructionHull(): void
255
    {
256
        foreach ($this->shipRepository->getStationConstructions() as $ship) {
257
            $lower = random_int(5, 15);
258
            if ($ship->getHull() <= $lower) {
259
                $msg = sprintf(_('Dein Konstrukt bei %s war zu lange ungenutzt und ist daher zerfallen'), $ship->getSectorString());
260
                $this->privateMessageSender->send(
261
                    UserEnum::USER_NOONE,
262
                    $ship->getUser()->getId(),
263
                    $msg,
264
                    PrivateMessageFolderSpecialEnum::PM_SPECIAL_STATION
265
                );
266
267
                $this->shipRemover->remove($ship);
268
                continue;
269
            }
270
            $ship->setHuell($ship->getHull() - $lower);
271
272
            $this->shipRepository->save($ship);
273
        }
274
    }
275
276
    private function handleNPCShips(): void
277
    {
278
        // @todo
279
        foreach ($this->shipRepository->getNpcShipsForTick() as $ship) {
280
            $wrapper = $this->shipWrapperFactory->wrapShip($ship);
281
            $reactor = $wrapper->getReactorWrapper();
282
            if ($reactor === null) {
283
                continue;
284
            }
285
286
            $epsSystem = $wrapper->getEpsSystemData();
287
            $warpdrive = $wrapper->getWarpDriveSystemData();
288
289
            //load EPS
290
            if ($epsSystem !== null) {
291
                $epsSystem->setEps($epsSystem->getEps() + $reactor->getEffectiveEpsProduction())->update();
292
            }
293
294
            //load warpdrive
295
            if ($warpdrive !== null) {
296
                $warpdrive->setWarpDrive($warpdrive->getWarpDrive() + $reactor->getEffectiveWarpDriveProduction())->update();
297
            }
298
        }
299
    }
300
301
    private function setLock(int $batchGroupId): void
302
    {
303
        $this->lockManager->setLock($batchGroupId, LockTypeEnum::SHIP_GROUP);
304
    }
305
306
    private function clearLock(int $batchGroupId): void
307
    {
308
        $this->lockManager->clearLock($batchGroupId, LockTypeEnum::SHIP_GROUP);
309
    }
310
311
    protected function getBenchmark(): Ubench
312
    {
313
        return $this->benchmark;
314
    }
315
316
    protected function getLoggerUtil(): LoggerUtilInterface
317
    {
318
        return $this->loggerUtil;
319
    }
320
}
321