Passed
Push — dev ( 238307...62244f )
by Nico
26:37
created

ShipTick::doAggregationSystemStuff()   C

Complexity

Conditions 13
Paths 39

Size

Total Lines 60
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 182

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 13
eloc 45
nc 39
nop 1
dl 0
loc 60
ccs 0
cts 46
cp 0
crap 182
rs 6.6166
c 1
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\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...
8
use Stu\Component\Ship\Repair\RepairUtilInterface;
9
use Stu\Component\Ship\ShipAlertStateEnum;
10
use Stu\Component\Ship\ShipStateEnum;
11
use Stu\Component\Ship\Storage\ShipStorageManagerInterface;
12
use Stu\Component\Ship\System\Data\EpsSystemData;
13
use Stu\Component\Ship\System\ShipSystemManagerInterface;
14
use Stu\Component\Ship\System\ShipSystemTypeEnum;
15
use Stu\Component\Station\StationUtilityInterface;
16
use Stu\Module\Control\GameControllerInterface;
17
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...
18
use Stu\Module\Database\Lib\CreateDatabaseEntryInterface;
19
use Stu\Module\Logging\LoggerUtilFactoryInterface;
20
use Stu\Module\Logging\LoggerUtilInterface;
21
use Stu\Module\Message\Lib\PrivateMessageFolderTypeEnum;
22
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
23
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...
24
use Stu\Module\Ship\Lib\AstroEntryLibInterface;
25
use Stu\Module\Ship\Lib\Crew\ShipLeaverInterface;
26
use Stu\Module\Ship\Lib\Interaction\ShipTakeoverManagerInterface;
27
use Stu\Module\Ship\Lib\Interaction\TrackerDeviceManagerInterface;
28
use Stu\Module\Ship\Lib\ReactorWrapperInterface;
29
use Stu\Module\Ship\Lib\ShipWrapperFactoryInterface;
30
use Stu\Module\Ship\Lib\ShipWrapperInterface;
31
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...
32
use Stu\Module\Tick\Ship\ManagerComponent\ManagerComponentInterface;
33
use Stu\Orm\Entity\DatabaseEntryInterface;
34
use Stu\Orm\Entity\ShipInterface;
35
use Stu\Orm\Repository\DatabaseUserRepositoryInterface;
36
use Stu\Orm\Repository\ShipRepositoryInterface;
37
use Stu\Orm\Repository\LocationMiningRepositoryInterface;
38
use Stu\Orm\Repository\CommodityRepositoryInterface;
39
use Stu\Orm\Repository\StorageRepositoryInterface;
40
41
final class ShipTick implements ShipTickInterface, ManagerComponentInterface
42
{
43
    private LoggerUtilInterface $loggerUtil;
44
45
    /**
46
     * @var array<string>
47
     */
48
    private array $msg = [];
49
50
    public function __construct(
51
        private ShipWrapperFactoryInterface $shipWrapperFactory,
52
        private PrivateMessageSenderInterface $privateMessageSender,
53
        private ShipRepositoryInterface $shipRepository,
54
        private ShipSystemManagerInterface $shipSystemManager,
55
        private ShipLeaverInterface $shipLeaver,
56
        private GameControllerInterface $game,
57
        private AstroEntryLibInterface $astroEntryLib,
58
        private DatabaseUserRepositoryInterface $databaseUserRepository,
59
        private CreateDatabaseEntryInterface $createDatabaseEntry,
60
        private StationUtilityInterface $stationUtility,
61
        private RepairUtilInterface $repairUtil,
62
        private ShipTakeoverManagerInterface $shipTakeoverManager,
63
        private TrackerDeviceManagerInterface $trackerDeviceManager,
64
        private ShipStorageManagerInterface $shipStorageManager,
65
        private LocationMiningRepositoryInterface $locationMiningRepository,
66
        private CommodityRepositoryInterface $commodityRepository,
67
        private StorageRepositoryInterface $storageRepository,
68
        LoggerUtilFactoryInterface $loggerUtilFactory
69
    ) {
70
        $this->loggerUtil = $loggerUtilFactory->getLoggerUtil(true);
71
    }
72
73
    #[Override]
74
    public function work(): void
75
    {
76
        foreach ($this->shipRepository->getPlayerShipsForTick() as $ship) {
77
            $this->workShip($this->shipWrapperFactory->wrapShip($ship));
78
        }
79
    }
80
81
    #[Override]
82
    public function workShip(ShipWrapperInterface $wrapper): void
83
    {
84
        $ship = $wrapper->get();
85
86
        $startTime = microtime(true);
87
88
        // do construction stuff
89
        if ($this->doConstructionStuff($ship)) {
90
            $this->shipRepository->save($ship);
91
            $this->sendMessages($ship);
92
            return;
93
        }
94
95
        $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

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

475
        $this->potentialLog($ship, "marker10.1", /** @scrutinizer ignore-type */ $startTime);
Loading history...
476
477
        $startTime = microtime(true);
478
        $isTakeoverReady = $this->shipTakeoverManager->isTakeoverReady($takeover);
479
        $this->potentialLog($ship, "marker10.2", $startTime);
480
481
        if ($isTakeoverReady) {
482
            $startTime = microtime(true);
483
            $this->shipTakeoverManager->finishTakeover($takeover);
484
            $this->potentialLog($ship, "marker10.3", $startTime);
485
        }
486
    }
487
488
    private function checkForFinishedAstroMapping(ShipWrapperInterface $wrapper): void
489
    {
490
        $ship = $wrapper->get();
491
492
        /** @var null|DatabaseEntryInterface $databaseEntry */
493
        [$message, $databaseEntry] = $this->getDatabaseEntryForShipLocation($ship);
494
495
        $astroLab = $wrapper->getAstroLaboratorySystemData();
496
497
        if (
498
            $ship->getState() === ShipStateEnum::SHIP_STATE_ASTRO_FINALIZING
499
            && $databaseEntry !== null
500
            && $astroLab !== null
501
            && $this->game->getCurrentRound()->getTurn() >= ($astroLab->getAstroStartTurn() + AstronomicalMappingEnum::TURNS_TO_FINISH)
502
        ) {
503
            $this->astroEntryLib->finish($wrapper);
504
505
            $this->msg[] = sprintf(
506
                _('Die Kartographierung %s wurde vollendet'),
507
                $message
508
            );
509
510
            $userId = $ship->getUser()->getId();
511
            $databaseEntryId = $databaseEntry->getId();
512
513
            if (!$this->databaseUserRepository->exists($userId, $databaseEntryId)) {
514
                $entry = $this->createDatabaseEntry->createDatabaseEntryForUser($ship->getUser(), $databaseEntryId);
515
516
                if ($entry !== null) {
517
                    $this->msg[] = sprintf(
518
                        _('Neuer Datenbankeintrag: %s (+%d Punkte)'),
519
                        $entry->getDescription(),
520
                        $entry->getCategory()->getPoints()
521
                    );
522
                }
523
            }
524
        }
525
    }
526
527
    /**
528
     * @return array{0: string|null, 1: DatabaseEntryInterface|null}
529
     */
530
    private function getDatabaseEntryForShipLocation(ShipInterface $ship): array
531
    {
532
        $system = $ship->getSystem();
533
        if ($system !== null) {
534
            return [
535
                'des Systems ' . $system->getName(),
536
                $system->getDatabaseEntry()
537
            ];
538
        }
539
540
        $mapRegion = $ship->getMapRegion();
541
        if ($mapRegion !== null) {
542
            return [
543
                'der Region ' . $mapRegion->getDescription(),
544
                $mapRegion->getDatabaseEntry()
545
            ];
546
        }
547
548
        return [null, null];
549
    }
550
551
    private function doTrackerDeviceStuff(ShipWrapperInterface $wrapper): void
552
    {
553
        $ship = $wrapper->get();
554
        $tracker = $wrapper->getTrackerSystemData();
555
556
        if ($tracker === null || $tracker->targetId === null) {
557
            return;
558
        }
559
560
        $targetWrapper = $tracker->getTargetWrapper();
561
        if ($targetWrapper === null) {
562
            throw new RuntimeException('should not happen');
563
        }
564
565
        $target = $targetWrapper->get();
566
        $shipLocation = $ship->getLocation();
567
        $targetLocation = $target->getLocation();
568
        $remainingTicks = $tracker->getRemainingTicks();
569
570
        $reduceByTicks = max(1, (int)ceil((abs($shipLocation->getCx() - $targetLocation->getCx())
571
            +  abs($shipLocation->getCy() - $targetLocation->getCy())) / 50));
572
573
        //reduce remaining ticks
574
        if ($remainingTicks > $reduceByTicks) {
575
            $tracker->setRemainingTicks($remainingTicks - $reduceByTicks)->update();
576
        } else {
577
            $this->trackerDeviceManager->deactivateTrackerIfActive($wrapper, true);
578
        }
579
    }
580
581
    private function doBussardCollectorStuff(ShipWrapperInterface $wrapper): void
582
    {
583
        $ship = $wrapper->get();
584
        $bussard = $wrapper->getBussardCollectorSystemData();
585
        $miningqueue = $ship->getMiningQueue();
586
587
        if ($bussard === null) {
588
            return;
589
        }
590
591
        if ($miningqueue == null) {
592
            return;
593
        } else {
594
            $locationmining = $miningqueue->getLocationMining();
595
            $actualAmount = $locationmining->getActualAmount();
596
            $freeStorage = $ship->getMaxStorage() - $ship->getStorageSum();
597
            $module = $ship->getShipSystem(ShipSystemTypeEnum::SYSTEM_BUSSARD_COLLECTOR)->getModule();
598
            $gathercount = 0;
599
600
            if ($module) {
601
                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...
602
                    $gathercount =  (int) min(min(round(mt_rand(95, 105)), $actualAmount), $freeStorage);
603
                } else {
604
                    $gathercount = (int) min(min(round(mt_rand(190, 220)), $actualAmount), $freeStorage);
605
                }
606
            }
607
608
            $newAmount = $actualAmount - $gathercount;
609
            if ($gathercount > 0 && $locationmining->getDepletedAt() !== null) {
610
                $locationmining->setDepletedAt(null);
611
            }
612
            if ($newAmount == 0 && $actualAmount > 0) {
613
                $locationmining->setDepletedAt(time());
614
            }
615
            $locationmining->setActualAmount($newAmount);
616
617
            $this->locationMiningRepository->save($locationmining);
618
619
            $this->shipStorageManager->upperStorage(
620
                $ship,
621
                $locationmining->getCommodity(),
622
                $gathercount
623
            );
624
        }
625
    }
626
627
    private function doAggregationSystemStuff(ShipWrapperInterface $wrapper): void
628
    {
629
        $ship = $wrapper->get();
630
        $aggsys = $wrapper->getAggregationSystemSystemData();
631
632
        if ($aggsys === null) {
633
            return;
634
        } else {
635
            $module = $ship->getShipSystem(ShipSystemTypeEnum::SYSTEM_AGGREGATION_SYSTEM)->getModule();
636
            $producedAmount = 0;
637
            $usedAmount = 0;
638
            $usedCommodity = null;
639
            $producedCommodity = null;
640
641
642
            if ($module) {
643
                $commodity = $aggsys->getCommodityId();
644
                $commodities = CommodityTypeEnum::COMMODITY_CONVERSIONS;
645
646
                if ($commodity > 0) {
647
                    foreach ($commodities as $entry) {
648
                        if ($entry[0] === $commodity) {
649
                            $producedCommodityId = $entry[1];
650
                            $producedCommodity = $this->commodityRepository->find($producedCommodityId);
651
                            $usedCommodity = $this->commodityRepository->find($entry[0]);
652
                            $usedAmount = $entry[2];
653
                            break;
654
                        }
655
                    }
656
657
                    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...
658
                        $producedAmount = 1;
659
                    } else {
660
                        $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
}