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

ShipTick::lowerStationConstructionHull()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 13
nc 3
nop 1
dl 0
loc 19
ccs 0
cts 15
cp 0
crap 12
rs 9.8333
c 0
b 0
f 0
1
<?php
2
3
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\ShipWrapperFactoryInterface;
28
use Stu\Module\Ship\Lib\ShipWrapperInterface;
29
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...
30
use Stu\Module\Tick\Ship\ManagerComponent\ManagerComponentInterface;
31
use Stu\Orm\Entity\DatabaseEntryInterface;
32
use Stu\Orm\Entity\ShipInterface;
33
use Stu\Orm\Repository\DatabaseUserRepositoryInterface;
34
use Stu\Orm\Repository\ShipRepositoryInterface;
35
36
final class ShipTick implements ShipTickInterface, ManagerComponentInterface
37
{
38
    private LoggerUtilInterface $loggerUtil;
39
40
    /**
41
     * @var array<string>
42
     */
43
    private array $msg = [];
44
45
    public function __construct(
46
        private ShipWrapperFactoryInterface $shipWrapperFactory,
47
        private PrivateMessageSenderInterface $privateMessageSender,
48
        private ShipRepositoryInterface $shipRepository,
49
        private ShipSystemManagerInterface $shipSystemManager,
50
        private ShipLeaverInterface $shipLeaver,
51
        private GameControllerInterface $game,
52
        private AstroEntryLibInterface $astroEntryLib,
53
        private DatabaseUserRepositoryInterface $databaseUserRepository,
54
        private CreateDatabaseEntryInterface $createDatabaseEntry,
55
        private StationUtilityInterface $stationUtility,
56
        private RepairUtilInterface $repairUtil,
57
        private ShipTakeoverManagerInterface $shipTakeoverManager,
58
        private TrackerDeviceManagerInterface $trackerDeviceManager,
59
        LoggerUtilFactoryInterface $loggerUtilFactory
60
    ) {
61
        $this->loggerUtil = $loggerUtilFactory->getLoggerUtil(true);
62
    }
63
64
    #[Override]
65
    public function work(): void
66
    {
67
        foreach ($this->shipRepository->getPlayerShipsForTick() as $ship) {
68
            $this->workShip($this->shipWrapperFactory->wrapShip($ship));
69
        }
70
    }
71
72
    #[Override]
73
    public function workShip(ShipWrapperInterface $wrapper): void
74
    {
75
        $ship = $wrapper->get();
76
77
        $startTime = microtime(true);
78
79
        // do construction stuff
80
        if ($this->doConstructionStuff($ship)) {
81
            $this->shipRepository->save($ship);
82
            $this->sendMessages($ship);
83
            return;
84
        }
85
86
        $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

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

458
        $this->potentialLog($ship, "marker10.1", /** @scrutinizer ignore-type */ $startTime);
Loading history...
459
460
        $startTime = microtime(true);
461
        $isTakeoverReady = $this->shipTakeoverManager->isTakeoverReady($takeover);
462
        $this->potentialLog($ship, "marker10.2", $startTime);
463
464
        if ($isTakeoverReady) {
465
            $startTime = microtime(true);
466
            $this->shipTakeoverManager->finishTakeover($takeover);
467
            $this->potentialLog($ship, "marker10.3", $startTime);
468
        }
469
    }
470
471
    private function checkForFinishedAstroMapping(ShipWrapperInterface $wrapper): void
472
    {
473
        $ship = $wrapper->get();
474
475
        /** @var null|DatabaseEntryInterface $databaseEntry */
476
        [$message, $databaseEntry] = $this->getDatabaseEntryForShipLocation($ship);
477
478
        $astroLab = $wrapper->getAstroLaboratorySystemData();
479
480
        if (
481
            $ship->getState() === ShipStateEnum::SHIP_STATE_ASTRO_FINALIZING
482
            && $databaseEntry !== null
483
            && $astroLab !== null
484
            && $this->game->getCurrentRound()->getTurn() >= ($astroLab->getAstroStartTurn() + AstronomicalMappingEnum::TURNS_TO_FINISH)
485
        ) {
486
            $this->astroEntryLib->finish($wrapper);
487
488
            $this->msg[] = sprintf(
489
                _('Die Kartographierung %s wurde vollendet'),
490
                $message
491
            );
492
493
            $userId = $ship->getUser()->getId();
494
            $databaseEntryId = $databaseEntry->getId();
495
496
            if (!$this->databaseUserRepository->exists($userId, $databaseEntryId)) {
497
                $entry = $this->createDatabaseEntry->createDatabaseEntryForUser($ship->getUser(), $databaseEntryId);
498
499
                if ($entry !== null) {
500
                    $this->msg[] = sprintf(
501
                        _('Neuer Datenbankeintrag: %s (+%d Punkte)'),
502
                        $entry->getDescription(),
503
                        $entry->getCategory()->getPoints()
504
                    );
505
                }
506
            }
507
        }
508
    }
509
510
    /**
511
     * @return array{0: string|null, 1: DatabaseEntryInterface|null}
512
     */
513
    private function getDatabaseEntryForShipLocation(ShipInterface $ship): array
514
    {
515
        $system = $ship->getSystem();
516
        if ($system !== null) {
517
            return [
518
                'des Systems ' . $system->getName(),
519
                $system->getDatabaseEntry()
520
            ];
521
        }
522
523
        $mapRegion = $ship->getMapRegion();
524
        if ($mapRegion !== null) {
525
            return [
526
                'der Region ' . $mapRegion->getDescription(),
527
                $mapRegion->getDatabaseEntry()
528
            ];
529
        }
530
531
        return [null, null];
532
    }
533
534
    private function doTrackerDeviceStuff(ShipWrapperInterface $wrapper): void
535
    {
536
        $ship = $wrapper->get();
537
        $tracker = $wrapper->getTrackerSystemData();
538
539
        if ($tracker === null || $tracker->targetId === null) {
540
            return;
541
        }
542
543
        $targetWrapper = $tracker->getTargetWrapper();
544
        if ($targetWrapper === null) {
545
            throw new RuntimeException('should not happen');
546
        }
547
548
        $target = $targetWrapper->get();
549
        $shipLocation = $ship->getLocation();
550
        $targetLocation = $target->getLocation();
551
        $remainingTicks = $tracker->getRemainingTicks();
552
553
        $reduceByTicks = max(1, (int)ceil((abs($shipLocation->getCx() - $targetLocation->getCx())
554
            +  abs($shipLocation->getCy() - $targetLocation->getCy())) / 50));
555
556
        //reduce remaining ticks
557
        if ($remainingTicks > $reduceByTicks) {
558
            $tracker->setRemainingTicks($remainingTicks - $reduceByTicks)->update();
559
        } else {
560
            $this->trackerDeviceManager->deactivateTrackerIfActive($wrapper, true);
561
        }
562
    }
563
564
    private function sendMessages(ShipInterface $ship): void
565
    {
566
        if ($this->msg === []) {
567
            return;
568
        }
569
        $text = "Tickreport der " . $ship->getName() . "\n";
570
        foreach ($this->msg as $msg) {
571
            $text .= $msg . "\n";
572
        }
573
574
        $href = sprintf('ship.php?%s=1&id=%d', ShowShip::VIEW_IDENTIFIER, $ship->getId());
575
576
        $this->privateMessageSender->send(
577
            UserEnum::USER_NOONE,
578
            $ship->getUser()->getId(),
579
            $text,
580
            $ship->isBase() ? PrivateMessageFolderTypeEnum::SPECIAL_STATION : PrivateMessageFolderTypeEnum::SPECIAL_SHIP,
581
            $href
582
        );
583
584
        $this->msg = [];
585
    }
586
}
587