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

ShipTick::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 15
dl 0
loc 18
ccs 0
cts 2
cp 0
crap 2
rs 10
c 1
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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

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

472
        $this->potentialLog($ship, "marker10.1", /** @scrutinizer ignore-type */ $startTime);
Loading history...
473
474
        $startTime = microtime(true);
475
        $isTakeoverReady = $this->shipTakeoverManager->isTakeoverReady($takeover);
476
        $this->potentialLog($ship, "marker10.2", $startTime);
477
478
        if ($isTakeoverReady) {
479
            $startTime = microtime(true);
480
            $this->shipTakeoverManager->finishTakeover($takeover);
481
            $this->potentialLog($ship, "marker10.3", $startTime);
482
        }
483
    }
484
485
    private function checkForFinishedAstroMapping(ShipWrapperInterface $wrapper): void
486
    {
487
        $ship = $wrapper->get();
488
489
        /** @var null|DatabaseEntryInterface $databaseEntry */
490
        [$message, $databaseEntry] = $this->getDatabaseEntryForShipLocation($ship);
491
492
        $astroLab = $wrapper->getAstroLaboratorySystemData();
493
494
        if (
495
            $ship->getState() === ShipStateEnum::SHIP_STATE_ASTRO_FINALIZING
496
            && $databaseEntry !== null
497
            && $astroLab !== null
498
            && $this->game->getCurrentRound()->getTurn() >= ($astroLab->getAstroStartTurn() + AstronomicalMappingEnum::TURNS_TO_FINISH)
499
        ) {
500
            $this->astroEntryLib->finish($wrapper);
501
502
            $this->msg[] = sprintf(
503
                _('Die Kartographierung %s wurde vollendet'),
504
                $message
505
            );
506
507
            $userId = $ship->getUser()->getId();
508
            $databaseEntryId = $databaseEntry->getId();
509
510
            if (!$this->databaseUserRepository->exists($userId, $databaseEntryId)) {
511
                $entry = $this->createDatabaseEntry->createDatabaseEntryForUser($ship->getUser(), $databaseEntryId);
512
513
                if ($entry !== null) {
514
                    $this->msg[] = sprintf(
515
                        _('Neuer Datenbankeintrag: %s (+%d Punkte)'),
516
                        $entry->getDescription(),
517
                        $entry->getCategory()->getPoints()
518
                    );
519
                }
520
            }
521
        }
522
    }
523
524
    /**
525
     * @return array{0: string|null, 1: DatabaseEntryInterface|null}
526
     */
527
    private function getDatabaseEntryForShipLocation(ShipInterface $ship): array
528
    {
529
        $system = $ship->getSystem();
530
        if ($system !== null) {
531
            return [
532
                'des Systems ' . $system->getName(),
533
                $system->getDatabaseEntry()
534
            ];
535
        }
536
537
        $mapRegion = $ship->getMapRegion();
538
        if ($mapRegion !== null) {
539
            return [
540
                'der Region ' . $mapRegion->getDescription(),
541
                $mapRegion->getDatabaseEntry()
542
            ];
543
        }
544
545
        return [null, null];
546
    }
547
548
    private function doTrackerDeviceStuff(ShipWrapperInterface $wrapper): void
549
    {
550
        $ship = $wrapper->get();
551
        $tracker = $wrapper->getTrackerSystemData();
552
553
        if ($tracker === null || $tracker->targetId === null) {
554
            return;
555
        }
556
557
        $targetWrapper = $tracker->getTargetWrapper();
558
        if ($targetWrapper === null) {
559
            throw new RuntimeException('should not happen');
560
        }
561
562
        $target = $targetWrapper->get();
563
        $shipLocation = $ship->getLocation();
564
        $targetLocation = $target->getLocation();
565
        $remainingTicks = $tracker->getRemainingTicks();
566
567
        $reduceByTicks = max(1, (int)ceil((abs($shipLocation->getCx() - $targetLocation->getCx())
568
            +  abs($shipLocation->getCy() - $targetLocation->getCy())) / 50));
569
570
        //reduce remaining ticks
571
        if ($remainingTicks > $reduceByTicks) {
572
            $tracker->setRemainingTicks($remainingTicks - $reduceByTicks)->update();
573
        } else {
574
            $this->trackerDeviceManager->deactivateTrackerIfActive($wrapper, true);
575
        }
576
    }
577
578
    private function sendMessages(ShipInterface $ship): void
579
    {
580
        if ($this->msg === []) {
581
            return;
582
        }
583
        $text = "Tickreport der " . $ship->getName() . "\n";
584
        foreach ($this->msg as $msg) {
585
            $text .= $msg . "\n";
586
        }
587
588
        $href = sprintf('ship.php?%s=1&id=%d', ShowShip::VIEW_IDENTIFIER, $ship->getId());
589
590
        $this->privateMessageSender->send(
591
            UserEnum::USER_NOONE,
592
            $ship->getUser()->getId(),
593
            $text,
594
            $ship->isBase() ? PrivateMessageFolderTypeEnum::SPECIAL_STATION : PrivateMessageFolderTypeEnum::SPECIAL_SHIP,
595
            $href
596
        );
597
598
        $this->msg = [];
599
    }
600
601
602
    private function lowerStationConstructionHull(UserInterface $user): void
603
    {
604
        foreach ($this->shipRepository->getStationConstructions($user) as $ship) {
605
            $lower = random_int(5, 15);
606
            if ($ship->getHull() <= $lower) {
607
                $msg = sprintf(_('Dein Konstrukt bei %s war zu lange ungenutzt und ist daher zerfallen'), $ship->getSectorString());
608
                $this->privateMessageSender->send(
609
                    UserEnum::USER_NOONE,
610
                    $ship->getUser()->getId(),
611
                    $msg,
612
                    PrivateMessageFolderTypeEnum::SPECIAL_STATION
613
                );
614
615
                $this->shipRemover->remove($ship);
616
                continue;
617
            }
618
            $ship->setHull($ship->getHull() - $lower);
619
620
            $this->shipRepository->save($ship);
621
        }
622
    }
623
}
624