Passed
Push — master ( 92a2e9...9d73f4 )
by Nico
41:55
created

ShipTick::doAggregationSystemStuff()   C

Complexity

Conditions 13
Paths 39

Size

Total Lines 59
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 182

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 13
eloc 44
nc 39
nop 1
dl 0
loc 59
ccs 0
cts 46
cp 0
crap 182
rs 6.6166
c 2
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Stu\Module\Tick\Ship;
4
5
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...
6
use RuntimeException;
7
use Stu\Component\Faction\FactionEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Faction\FactionEnum 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...
8
use Stu\Component\Ship\AstronomicalMappingEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Ship\AstronomicalMappingEnum 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\Ship\Repair\RepairUtilInterface;
10
use Stu\Component\Ship\ShipAlertStateEnum;
11
use Stu\Component\Ship\ShipStateEnum;
12
use Stu\Component\Ship\Storage\ShipStorageManagerInterface;
13
use Stu\Component\Ship\System\Data\EpsSystemData;
14
use Stu\Component\Ship\System\ShipSystemManagerInterface;
15
use Stu\Component\Ship\System\ShipSystemTypeEnum;
16
use Stu\Component\Station\StationUtilityInterface;
17
use Stu\Module\Control\GameControllerInterface;
18
use Stu\Module\Commodity\CommodityTypeEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Module\Commodity\CommodityTypeEnum 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...
19
use Stu\Module\Database\Lib\CreateDatabaseEntryInterface;
20
use Stu\Module\Logging\LoggerUtilFactoryInterface;
21
use Stu\Module\Logging\LoggerUtilInterface;
22
use Stu\Module\Message\Lib\PrivateMessageFolderTypeEnum;
23
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
24
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...
25
use Stu\Module\Ship\Lib\AstroEntryLibInterface;
26
use Stu\Module\Ship\Lib\Crew\ShipLeaverInterface;
27
use Stu\Module\Ship\Lib\Interaction\ShipTakeoverManagerInterface;
28
use Stu\Module\Ship\Lib\Interaction\TrackerDeviceManagerInterface;
29
use Stu\Module\Ship\Lib\ReactorWrapperInterface;
30
use Stu\Module\Ship\Lib\ShipWrapperFactoryInterface;
31
use Stu\Module\Ship\Lib\ShipWrapperInterface;
32
use Stu\Module\Ship\View\ShowShip\ShowShip;
0 ignored issues
show
Bug introduced by
The type Stu\Module\Ship\View\ShowShip\ShowShip 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...
33
use Stu\Module\Tick\Ship\ManagerComponent\ManagerComponentInterface;
34
use Stu\Orm\Entity\DatabaseEntryInterface;
35
use Stu\Orm\Entity\ShipInterface;
36
use Stu\Orm\Repository\DatabaseUserRepositoryInterface;
37
use Stu\Orm\Repository\ShipRepositoryInterface;
38
use Stu\Orm\Repository\LocationMiningRepositoryInterface;
39
use Stu\Orm\Repository\CommodityRepositoryInterface;
40
use Stu\Orm\Repository\StorageRepositoryInterface;
41
42
final class ShipTick implements ShipTickInterface, ManagerComponentInterface
43
{
44
    private LoggerUtilInterface $loggerUtil;
45
46
    /**
47
     * @var array<string>
48
     */
49
    private array $msg = [];
50
51
    public function __construct(
52
        private ShipWrapperFactoryInterface $shipWrapperFactory,
53
        private PrivateMessageSenderInterface $privateMessageSender,
54
        private ShipRepositoryInterface $shipRepository,
55
        private ShipSystemManagerInterface $shipSystemManager,
56
        private ShipLeaverInterface $shipLeaver,
57
        private GameControllerInterface $game,
58
        private AstroEntryLibInterface $astroEntryLib,
59
        private DatabaseUserRepositoryInterface $databaseUserRepository,
60
        private CreateDatabaseEntryInterface $createDatabaseEntry,
61
        private StationUtilityInterface $stationUtility,
62
        private RepairUtilInterface $repairUtil,
63
        private ShipTakeoverManagerInterface $shipTakeoverManager,
64
        private TrackerDeviceManagerInterface $trackerDeviceManager,
65
        private ShipStorageManagerInterface $shipStorageManager,
66
        private LocationMiningRepositoryInterface $locationMiningRepository,
67
        private CommodityRepositoryInterface $commodityRepository,
68
        private StorageRepositoryInterface $storageRepository,
69
        LoggerUtilFactoryInterface $loggerUtilFactory
70
    ) {
71
        $this->loggerUtil = $loggerUtilFactory->getLoggerUtil(true);
72
    }
73
74
    #[Override]
75
    public function work(): void
76
    {
77
        foreach ($this->shipRepository->getPlayerShipsForTick() as $ship) {
78
            $this->workShip($this->shipWrapperFactory->wrapShip($ship));
79
        }
80
    }
81
82
    #[Override]
83
    public function workShip(ShipWrapperInterface $wrapper): void
84
    {
85
        $ship = $wrapper->get();
86
87
        $startTime = microtime(true);
88
89
        // do construction stuff
90
        if ($this->doConstructionStuff($ship)) {
91
            $this->shipRepository->save($ship);
92
            $this->sendMessages($ship);
93
            return;
94
        }
95
96
        $this->potentialLog($ship, "marker0", $startTime);
0 ignored issues
show
Bug introduced by
It seems like $startTime can also be of type string; however, parameter $startTime of Stu\Module\Tick\Ship\ShipTick::potentialLog() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

96
        $this->potentialLog($ship, "marker0", /** @scrutinizer ignore-type */ $startTime);
Loading history...
97
98
99
        $startTime = microtime(true);
100
        // repair station
101
        if ($ship->isBase() && $ship->getState() === ShipStateEnum::SHIP_STATE_REPAIR_PASSIVE) {
102
            $this->doRepairStation($wrapper);
103
        }
104
        $this->potentialLog($ship, "marker1", $startTime);
105
106
        $startTime = microtime(true);
107
        // leave ship
108
        if ($ship->getCrewCount() > 0 && !$ship->isSystemHealthy(ShipSystemTypeEnum::SYSTEM_LIFE_SUPPORT)) {
109
            $this->msg[] = _('Die Lebenserhaltung ist ausgefallen:');
110
            $this->msg[] = $this->shipLeaver->evacuate($wrapper);
111
            $this->sendMessages($ship);
112
            $this->potentialLog($ship, "marker2", $startTime);
113
            return;
114
        }
115
116
        $startTime = microtime(true);
117
        $eps = $wrapper->getEpsSystemData();
118
        $reactor = $wrapper->getReactorWrapper();
119
        if ($eps === null) {
120
            $this->potentialLog($ship, "marker3", $startTime);
121
            return;
122
        }
123
124
        $startTime = microtime(true);
125
        $hasEnoughCrew = $ship->hasEnoughCrew();
126
127
        // not enough crew
128
        if (!$hasEnoughCrew) {
129
            $this->msg[] = _('Zu wenig Crew an Bord, Schiff ist nicht voll funktionsfähig! Systeme werden deaktiviert!');
130
131
            //deactivate all systems except life support
132
            foreach ($this->shipSystemManager->getActiveSystems($ship) as $system) {
133
                if ($system->getSystemType() != ShipSystemTypeEnum::SYSTEM_LIFE_SUPPORT) {
134
                    $this->shipSystemManager->deactivate($wrapper, $system->getSystemType(), true);
135
                }
136
            }
137
        }
138
        $this->potentialLog($ship, "marker4", $startTime);
139
140
        $startTime = microtime(true);
141
        $reactorUsageForWarpdrive = $this->loadWarpdrive(
142
            $wrapper,
143
            $hasEnoughCrew
144
        );
145
        $this->potentialLog($ship, "marker5", $startTime);
146
147
        $startTime = microtime(true);
148
        $availableEps = $this->getAvailableEps(
149
            $wrapper,
150
            $eps,
151
            $reactor,
152
            $hasEnoughCrew,
153
            $reactorUsageForWarpdrive
154
        );
155
        $this->potentialLog($ship, "marker6", $startTime);
156
157
        $startTime = microtime(true);
158
        //try to save energy by reducing alert state
159
        if ($wrapper->getEpsUsage() > $availableEps) {
160
            $malus = $wrapper->getEpsUsage() - $availableEps;
161
            $alertUsage = $ship->getAlertState()->value - 1;
162
163
            if ($alertUsage > 0) {
164
                $preState = $ship->getAlertState();
165
                $reduce = (int)min($malus, $alertUsage);
166
167
                $ship->setAlertState(ShipAlertStateEnum::from($preState->value - $reduce));
168
                $this->msg[] = sprintf(
169
                    _('Wechsel von %s auf %s wegen Energiemangel'),
170
                    $preState->getDescription(),
171
                    $ship->getAlertState()->getDescription()
172
                );
173
            }
174
        }
175
        $this->potentialLog($ship, "marker7", $startTime);
176
177
        $startTime = microtime(true);
178
        //try to save energy by deactivating systems from low to high priority
179
        if ($wrapper->getEpsUsage() > $availableEps) {
180
            $activeSystems = $this->shipSystemManager->getActiveSystems($ship, true);
181
182
            foreach ($activeSystems as $system) {
183
                $energyConsumption = $this->shipSystemManager->getEnergyConsumption($system->getSystemType());
184
                if ($energyConsumption < 1) {
185
                    continue;
186
                }
187
188
                //echo "- eps: ".$eps." - usage: ".$wrapper->getEpsUsage()."\n";
189
                if ($availableEps - $wrapper->getEpsUsage() - $energyConsumption < 0) {
190
                    //echo "-- hit system: ".$system->getDescription()."\n";
191
192
                    $this->shipSystemManager->deactivate($wrapper, $system->getSystemType(), true);
193
194
                    $wrapper->lowerEpsUsage($energyConsumption);
195
                    $this->msg[] = $system->getSystemType()->getDescription() . ' deaktiviert wegen Energiemangel';
196
197
                    if ($ship->getCrewCount() > 0 && $system->getSystemType() == ShipSystemTypeEnum::SYSTEM_LIFE_SUPPORT) {
198
                        $this->msg[] = _('Die Lebenserhaltung ist ausgefallen:');
199
                        $this->msg[] = $this->shipLeaver->evacuate($wrapper);
200
                        $this->sendMessages($ship);
201
                        return;
202
                    }
203
                }
204
                if ($wrapper->getEpsUsage() <= $availableEps) {
205
                    break;
206
                }
207
            }
208
        }
209
210
        $this->potentialLog($ship, "marker8", $startTime);
211
        $startTime = microtime(true);
212
213
        $newEps = $availableEps - $wrapper->getEpsUsage();
214
        $batteryReload = $ship->isBase()
215
            && $eps->reloadBattery()
216
            && $newEps > $eps->getEps()
217
            ? min(
218
                (int) ceil($eps->getMaxBattery() / 10),
219
                $newEps - $eps->getEps(),
220
                $eps->getMaxBattery() - $eps->getBattery()
221
            ) : 0;
222
223
        $newEps -= $batteryReload;
224
        if ($newEps > $eps->getMaxEps()) {
225
            $newEps = $eps->getMaxEps();
226
        }
227
228
229
        $usedEnergy = $wrapper->getEpsUsage() + $batteryReload + ($newEps - $eps->getEps()) + $reactorUsageForWarpdrive;
230
231
        //echo "--- Generated Id ".$ship->getId()." - eps: ".$eps." - usage: ".$wrapper->getEpsUsage()." - old eps: ".$ship->getEps()." - wk: ".$wkuse."\n";
232
        $eps->setEps($newEps)
233
            ->setBattery($eps->getBattery() + $batteryReload)
234
            ->update();
235
236
        if ($usedEnergy > 0 && $reactor !== null) {
237
            $reactor->changeLoad(-$usedEnergy);
238
        }
239
240
        $this->potentialLog($ship, "marker9", $startTime);
241
242
        $startTime = microtime(true);
243
        $this->checkForFinishedTakeover($ship);
244
        $this->potentialLog($ship, "marker10", $startTime);
245
246
        $startTime = microtime(true);
247
        $this->checkForFinishedAstroMapping($wrapper);
248
        $this->potentialLog($ship, "marker11", $startTime);
249
250
        //update tracker status
251
        $startTime = microtime(true);
252
        $this->doTrackerDeviceStuff($wrapper);
253
        $this->potentialLog($ship, "marker12", $startTime);
254
255
        $startTime = microtime(true);
256
        $this->shipRepository->save($ship);
257
        $this->potentialLog($ship, "marker13", $startTime);
258
259
        $startTime = microtime(true);
260
        $this->sendMessages($ship);
261
        $this->potentialLog($ship, "marker14", $startTime);
262
263
        $startTime = microtime(true);
264
        $this->doBussardCollectorStuff($wrapper);
265
        $this->potentialLog($ship, "marker15", $startTime);
266
267
        $startTime = microtime(true);
268
        $this->doAggregationSystemStuff($wrapper);
269
        $this->potentialLog($ship, "marker16", $startTime);
270
    }
271
272
    private function potentialLog(ShipInterface $ship, string $marker, float $startTime): void
273
    {
274
        $endTime = microtime(true);
275
276
        if (
277
            $endTime - $startTime > 0.01
278
        ) {
279
            $this->loggerUtil->log(sprintf(
280
                "\t\t\t%s of %d, seconds: %F",
281
                $marker,
282
                $ship->getId(),
283
                $endTime - $startTime
284
            ));
285
        }
286
    }
287
288
    private function getAvailableEps(
289
        ShipWrapperInterface $wrapper,
290
        EpsSystemData $eps,
291
        ?ReactorWrapperInterface $reactor,
292
        bool $hasEnoughCrew,
293
        int $reactorUsageForWarpdrive
294
    ): int {
295
        if ($hasEnoughCrew && $reactor !== null) {
296
297
            return $eps->getEps() + $reactor->getEpsProduction() +  $this->getCarryOver(
298
                $wrapper,
299
                $reactor,
300
                $reactorUsageForWarpdrive
301
            );
302
        }
303
304
        return $eps->getEps();
305
    }
306
307
    private function getCarryOver(
308
        ShipWrapperInterface $wrapper,
309
        ReactorWrapperInterface $reactor,
310
        int $reactorUsageForWarpdrive
311
    ): int {
312
        $warpdrive = $wrapper->getWarpDriveSystemData();
313
        if ($warpdrive === null || !$warpdrive->getAutoCarryOver()) {
314
            return 0;
315
        }
316
317
        return $reactor->getOutputCappedByLoad() - $reactor->getEpsProduction() - $reactorUsageForWarpdrive;
318
    }
319
320
    private function loadWarpdrive(ShipWrapperInterface $wrapper, bool $hasEnoughCrew): int
321
    {
322
        if (!$hasEnoughCrew) {
323
            return 0;
324
        }
325
326
        $reactor = $wrapper->getReactorWrapper();
327
        $warpdrive = $wrapper->getWarpDriveSystemData();
328
        if ($warpdrive === null || $reactor === null) {
329
            return 0;
330
        }
331
332
        $effectiveWarpdriveProduction = $reactor->getEffectiveWarpDriveProduction();
333
        if ($effectiveWarpdriveProduction === 0) {
334
            return 0;
335
        }
336
337
        $currentLoad = $warpdrive->getWarpDrive();
338
339
        $warpdrive->setWarpDrive($currentLoad + $effectiveWarpdriveProduction)->update();
340
341
        return $effectiveWarpdriveProduction * $wrapper->get()->getRump()->getFlightECost();
342
    }
343
344
    private function doConstructionStuff(ShipInterface $ship): bool
345
    {
346
        $progress =  $this->stationUtility->getConstructionProgress($ship);
347
348
        if ($progress === null) {
349
            return false;
350
        }
351
352
        if ($progress->getRemainingTicks() === 0) {
353
            return false;
354
        }
355
356
        $isUnderConstruction = $ship->getState() === ShipStateEnum::SHIP_STATE_UNDER_CONSTRUCTION;
357
358
        if (!$this->stationUtility->hasEnoughDockedWorkbees($ship, $ship->getRump())) {
359
            $neededWorkbees = $isUnderConstruction ? $ship->getRump()->getNeededWorkbees() :
360
                (int)ceil($ship->getRump()->getNeededWorkbees() / 2);
361
362
            $this->msg[] = sprintf(
363
                _('Nicht genügend Workbees (%d/%d) angedockt um %s weiterführen zu können'),
364
                $this->stationUtility->getDockedWorkbeeCount($ship),
365
                $neededWorkbees,
366
                $isUnderConstruction ? 'den Bau' : 'die Demontage'
367
            );
368
            return true;
369
        }
370
371
        if ($progress->getRemainingTicks() === 1) {
372
            if ($isUnderConstruction) {
373
                $this->stationUtility->finishStation($ship, $progress);
374
            } else {
375
                $this->stationUtility->finishScrapping($ship, $progress);
376
            }
377
378
            $this->msg[] = sprintf(
379
                _('%s: %s bei %s fertiggestellt'),
380
                $ship->getRump()->getName(),
381
                $isUnderConstruction ? 'Bau' : 'Demontage',
382
                $ship->getSectorString()
383
            );
384
        } else {
385
            $this->stationUtility->reduceRemainingTicks($progress);
386
387
            if ($isUnderConstruction) {
388
                // raise hull
389
                $increase = intdiv($ship->getMaxHull(), 2 * $ship->getRump()->getBuildtime());
390
                $ship->setHuell($ship->getHull() + $increase);
391
            }
392
        }
393
394
        return true;
395
    }
396
397
    private function doRepairStation(ShipWrapperInterface $wrapper): void
398
    {
399
        $station = $wrapper->get();
400
401
        if (!$this->stationUtility->hasEnoughDockedWorkbees($station, $station->getRump())) {
402
            $neededWorkbees = (int)ceil($station->getRump()->getNeededWorkbees() / 5);
403
404
            $this->msg[] = sprintf(
405
                _('Nicht genügend Workbees (%d/%d) angedockt um die Reparatur weiterführen zu können'),
406
                $this->stationUtility->getDockedWorkbeeCount($station),
407
                $neededWorkbees
408
            );
409
            return;
410
        }
411
412
        $neededParts = $this->repairUtil->determineSpareParts($wrapper, true);
413
414
        // parts stored?
415
        if (!$this->repairUtil->enoughSparePartsOnEntity($neededParts, $station, $station)) {
416
            return;
417
        }
418
419
        //repair hull
420
        $station->setHuell($station->getHull() + $station->getRepairRate());
421
        if ($station->getHull() > $station->getMaxHull()) {
422
            $station->setHuell($station->getMaxHull());
423
        }
424
425
        //repair station systems
426
        $damagedSystems = $wrapper->getDamagedSystems();
427
        if ($damagedSystems !== []) {
428
            $firstSystem = $damagedSystems[0];
429
            $firstSystem->setStatus(100);
430
431
            if ($station->getCrewCount() > 0) {
432
                $firstSystem->setMode($this->shipSystemManager->lookupSystem($firstSystem->getSystemType())->getDefaultMode());
433
            }
434
435
            // maximum of two systems get repaired
436
            if (count($damagedSystems) > 1) {
437
                $secondSystem = $damagedSystems[1];
438
                $secondSystem->setStatus(100);
439
440
                if ($station->getCrewCount() > 0) {
441
                    $secondSystem->setMode($this->shipSystemManager->lookupSystem($secondSystem->getSystemType())->getDefaultMode());
442
                }
443
            }
444
        }
445
446
        // consume spare parts
447
        $this->repairUtil->consumeSpareParts($neededParts, $station);
448
449
        if (!$wrapper->canBeRepaired()) {
450
            $station->setHuell($station->getMaxHull());
451
            $station->setState(ShipStateEnum::SHIP_STATE_NONE);
452
453
            $shipOwnerMessage = sprintf(
454
                "Die Reparatur der %s wurde in Sektor %s fertiggestellt",
455
                $station->getName(),
456
                $station->getSectorString()
457
            );
458
459
            $this->privateMessageSender->send(
460
                UserEnum::USER_NOONE,
461
                $station->getUser()->getId(),
462
                $shipOwnerMessage,
463
                PrivateMessageFolderTypeEnum::SPECIAL_STATION
464
            );
465
        }
466
        $this->shipRepository->save($station);
467
    }
468
469
    private function checkForFinishedTakeover(ShipInterface $ship): void
470
    {
471
        $startTime = microtime(true);
472
        $takeover = $ship->getTakeoverActive();
473
        if ($takeover === null) {
474
            return;
475
        }
476
        $this->potentialLog($ship, "marker10.1", $startTime);
0 ignored issues
show
Bug introduced by
It seems like $startTime can also be of type string; however, parameter $startTime of Stu\Module\Tick\Ship\ShipTick::potentialLog() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

476
        $this->potentialLog($ship, "marker10.1", /** @scrutinizer ignore-type */ $startTime);
Loading history...
477
478
        $startTime = microtime(true);
479
        $isTakeoverReady = $this->shipTakeoverManager->isTakeoverReady($takeover);
480
        $this->potentialLog($ship, "marker10.2", $startTime);
481
482
        if ($isTakeoverReady) {
483
            $startTime = microtime(true);
484
            $this->shipTakeoverManager->finishTakeover($takeover);
485
            $this->potentialLog($ship, "marker10.3", $startTime);
486
        }
487
    }
488
489
    private function checkForFinishedAstroMapping(ShipWrapperInterface $wrapper): void
490
    {
491
        $ship = $wrapper->get();
492
493
        /** @var null|DatabaseEntryInterface $databaseEntry */
494
        [$message, $databaseEntry] = $this->getDatabaseEntryForShipLocation($ship);
495
496
        $astroLab = $wrapper->getAstroLaboratorySystemData();
497
498
        if (
499
            $ship->getState() === ShipStateEnum::SHIP_STATE_ASTRO_FINALIZING
500
            && $databaseEntry !== null
501
            && $astroLab !== null
502
            && $this->game->getCurrentRound()->getTurn() >= ($astroLab->getAstroStartTurn() + AstronomicalMappingEnum::TURNS_TO_FINISH)
503
        ) {
504
            $this->astroEntryLib->finish($wrapper);
505
506
            $this->msg[] = sprintf(
507
                _('Die Kartographierung %s wurde vollendet'),
508
                $message
509
            );
510
511
            $userId = $ship->getUser()->getId();
512
            $databaseEntryId = $databaseEntry->getId();
513
514
            if (!$this->databaseUserRepository->exists($userId, $databaseEntryId)) {
515
                $entry = $this->createDatabaseEntry->createDatabaseEntryForUser($ship->getUser(), $databaseEntryId);
516
517
                if ($entry !== null) {
518
                    $this->msg[] = sprintf(
519
                        _('Neuer Datenbankeintrag: %s (+%d Punkte)'),
520
                        $entry->getDescription(),
521
                        $entry->getCategory()->getPoints()
522
                    );
523
                }
524
            }
525
        }
526
    }
527
528
    /**
529
     * @return array{0: string|null, 1: DatabaseEntryInterface|null}
530
     */
531
    private function getDatabaseEntryForShipLocation(ShipInterface $ship): array
532
    {
533
        $system = $ship->getSystem();
534
        if ($system !== null) {
535
            return [
536
                'des Systems ' . $system->getName(),
537
                $system->getDatabaseEntry()
538
            ];
539
        }
540
541
        $mapRegion = $ship->getMapRegion();
542
        if ($mapRegion !== null) {
543
            return [
544
                'der Region ' . $mapRegion->getDescription(),
545
                $mapRegion->getDatabaseEntry()
546
            ];
547
        }
548
549
        return [null, null];
550
    }
551
552
    private function doTrackerDeviceStuff(ShipWrapperInterface $wrapper): void
553
    {
554
        $ship = $wrapper->get();
555
        $tracker = $wrapper->getTrackerSystemData();
556
557
        if ($tracker === null || $tracker->targetId === null) {
558
            return;
559
        }
560
561
        $targetWrapper = $tracker->getTargetWrapper();
562
        if ($targetWrapper === null) {
563
            throw new RuntimeException('should not happen');
564
        }
565
566
        $target = $targetWrapper->get();
567
        $shipLocation = $ship->getLocation();
568
        $targetLocation = $target->getLocation();
569
        $remainingTicks = $tracker->getRemainingTicks();
570
571
        $reduceByTicks = max(1, (int)ceil((abs($shipLocation->getCx() - $targetLocation->getCx())
572
            +  abs($shipLocation->getCy() - $targetLocation->getCy())) / 50));
573
574
        //reduce remaining ticks
575
        if ($remainingTicks > $reduceByTicks) {
576
            $tracker->setRemainingTicks($remainingTicks - $reduceByTicks)->update();
577
        } else {
578
            $this->trackerDeviceManager->deactivateTrackerIfActive($wrapper, true);
579
        }
580
    }
581
582
    private function doBussardCollectorStuff(ShipWrapperInterface $wrapper): void
583
    {
584
        $ship = $wrapper->get();
585
        $bussard = $wrapper->getBussardCollectorSystemData();
586
        $miningqueue = $ship->getMiningQueue();
587
588
        if ($bussard === null) {
589
            return;
590
        }
591
592
        if ($miningqueue == null) {
593
            return;
594
        } else {
595
            $locationmining = $miningqueue->getLocationMining();
596
            $actualAmount = $locationmining->getActualAmount();
597
            $freeStorage = $ship->getMaxStorage() - $ship->getStorageSum();
598
            $module = $ship->getShipSystem(ShipSystemTypeEnum::SYSTEM_BUSSARD_COLLECTOR)->getModule();
599
            $gathercount = 0;
600
601
            if ($module) {
602
                if ($module->getFactionId() == null) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $module->getFactionId() of type integer|null against null; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
603
                    $gathercount =  (int) min(min(round(mt_rand(95, 105)), $actualAmount), $freeStorage);
604
                } else {
605
                    $gathercount = (int) min(min(round(mt_rand(190, 220)), $actualAmount), $freeStorage);
606
                }
607
            }
608
609
            $newAmount = $actualAmount - $gathercount;
610
            if ($gathercount > 0 && $locationmining->getDepletedAt() !== null) {
611
                $locationmining->setDepletedAt(null);
612
            }
613
            if ($newAmount == 0 && $actualAmount > 0) {
614
                $locationmining->setDepletedAt(time());
615
            }
616
            $locationmining->setActualAmount($newAmount);
617
618
            $this->locationMiningRepository->save($locationmining);
619
620
            $this->shipStorageManager->upperStorage(
621
                $ship,
622
                $locationmining->getCommodity(),
623
                $gathercount
624
            );
625
        }
626
    }
627
628
    private function doAggregationSystemStuff(ShipWrapperInterface $wrapper): void
629
    {
630
        $ship = $wrapper->get();
631
        $aggsys = $wrapper->getAggregationSystemSystemData();
632
633
        if ($aggsys === null) {
634
            return;
635
        } else {
636
            $module = $ship->getShipSystem(ShipSystemTypeEnum::SYSTEM_AGGREGATION_SYSTEM)->getModule();
637
            $producedAmount = 0;
638
            $usedAmount = 0;
639
            $usedCommodity = null;
640
            $producedCommodity = null;
641
642
643
            if ($module) {
644
                $commodity = $aggsys->getCommodityId();
645
                $commodities = CommodityTypeEnum::COMMODITY_CONVERSIONS;
646
647
                if ($commodity > 0) {
648
                    foreach ($commodities as $entry) {
649
                        if ($entry[0] === $commodity) {
650
                            $producedCommodityId = $entry[1];
651
                            $producedCommodity = $this->commodityRepository->find($producedCommodityId);
652
                            $usedCommodity = $this->commodityRepository->find($entry[0]);
653
                            $usedAmount = $entry[2];
654
                            $producedAmount = $entry[3];
655
                            break;
656
                        }
657
                    }
658
659
                    if ($module->getFactionId() == FactionEnum::FACTION_FERENGI) {
660
                        $producedAmount = $producedAmount * 2;
661
                        $usedAmount = $usedAmount * 2;
662
                    }
663
                    $storage = $this->storageRepository->findOneBy([
664
                        'commodity' => $usedCommodity,
665
                        'ship' => $ship
666
                    ]);
667
                    if (!$storage && $usedCommodity) {
668
                        $this->msg[] = sprintf('Es ist kein %s vorhanden!', $usedCommodity->getName());
669
                        $this->sendMessages($ship);
670
                    }
671
672
                    if ($storage && $producedCommodity && $usedCommodity) {
673
                        if ($storage->getAmount() >= $usedAmount) {
674
                            $this->shipStorageManager->lowerStorage(
675
                                $ship,
676
                                $usedCommodity,
677
                                $usedAmount
678
                            );
679
                            $this->shipStorageManager->upperStorage(
680
                                $ship,
681
                                $producedCommodity,
682
                                $producedAmount
683
                            );
684
                        } else {
685
                            $this->msg[] = sprintf('Nicht genügend %s vorhanden!', $usedCommodity->getName());
686
                            $this->sendMessages($ship);
687
                        }
688
                    }
689
                }
690
            }
691
        }
692
    }
693
694
695
696
    private function sendMessages(ShipInterface $ship): void
697
    {
698
        if ($this->msg === []) {
699
            return;
700
        }
701
        $text = "Tickreport der " . $ship->getName() . "\n";
702
        foreach ($this->msg as $msg) {
703
            $text .= $msg . "\n";
704
        }
705
706
        $href = sprintf('ship.php?%s=1&id=%d', ShowShip::VIEW_IDENTIFIER, $ship->getId());
707
708
        $this->privateMessageSender->send(
709
            UserEnum::USER_NOONE,
710
            $ship->getUser()->getId(),
711
            $text,
712
            $ship->isBase() ? PrivateMessageFolderTypeEnum::SPECIAL_STATION : PrivateMessageFolderTypeEnum::SPECIAL_SHIP,
713
            $href
714
        );
715
716
        $this->msg = [];
717
    }
718
}
719