Passed
Push — dev ( 6710c5...e67022 )
by Janko
21:17
created

ShipTick::potentialLog()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 8
c 0
b 0
f 0
nc 2
nop 3
dl 0
loc 12
ccs 0
cts 8
cp 0
crap 6
rs 10
1
<?php
2
3
namespace Stu\Module\Tick\Ship;
4
5
use RuntimeException;
6
use Stu\Component\Ship\AstronomicalMappingEnum;
7
use Stu\Component\Ship\Repair\RepairUtilInterface;
8
use Stu\Component\Ship\ShipAlertStateEnum;
9
use Stu\Component\Ship\ShipStateEnum;
10
use Stu\Component\Ship\System\Data\EpsSystemData;
11
use Stu\Component\Ship\System\ShipSystemManagerInterface;
12
use Stu\Component\Ship\System\ShipSystemTypeEnum;
13
use Stu\Component\Station\StationUtilityInterface;
14
use Stu\Module\Control\GameControllerInterface;
15
use Stu\Module\Database\Lib\CreateDatabaseEntryInterface;
16
use Stu\Module\Logging\LoggerUtilFactoryInterface;
17
use Stu\Module\Logging\LoggerUtilInterface;
18
use Stu\Module\Message\Lib\PrivateMessageFolderSpecialEnum;
19
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
20
use Stu\Module\PlayerSetting\Lib\UserEnum;
21
use Stu\Module\Ship\Lib\AstroEntryLibInterface;
22
use Stu\Module\Ship\Lib\Crew\ShipLeaverInterface;
23
use Stu\Module\Ship\Lib\Interaction\ShipTakeoverManagerInterface;
24
use Stu\Module\Ship\Lib\ReactorWrapperInterface;
25
use Stu\Module\Ship\Lib\ShipWrapperFactoryInterface;
26
use Stu\Module\Ship\Lib\ShipWrapperInterface;
27
use Stu\Module\Ship\View\ShowShip\ShowShip;
28
use Stu\Module\Tick\Ship\ManagerComponent\ManagerComponentInterface;
29
use Stu\Orm\Entity\DatabaseEntryInterface;
30
use Stu\Orm\Entity\ShipInterface;
31
use Stu\Orm\Entity\UserInterface;
32
use Stu\Orm\Repository\DatabaseUserRepositoryInterface;
33
use Stu\Orm\Repository\ShipRepositoryInterface;
34
35
final class ShipTick implements ShipTickInterface, ManagerComponentInterface
36
{
37
    private ShipWrapperFactoryInterface $shipWrapperFactory;
38
39
    private PrivateMessageSenderInterface $privateMessageSender;
40
41
    private ShipRepositoryInterface $shipRepository;
42
43
    private ShipSystemManagerInterface $shipSystemManager;
44
45
    private ShipLeaverInterface $shipLeaver;
46
47
    private GameControllerInterface $game;
48
49
    private AstroEntryLibInterface $astroEntryLib;
50
51
    private DatabaseUserRepositoryInterface $databaseUserRepository;
52
53
    private CreateDatabaseEntryInterface $createDatabaseEntry;
54
55
    private StationUtilityInterface $stationUtility;
56
57
    private RepairUtilInterface $repairUtil;
58
59
    private ShipTakeoverManagerInterface $shipTakeoverManager;
60
61
    private LoggerUtilInterface $loggerUtil;
62
63
    /**
64
     * @var array<string>
65
     */
66
    private array $msg = [];
67
68
    public function __construct(
69
        ShipWrapperFactoryInterface $shipWrapperFactory,
70
        PrivateMessageSenderInterface $privateMessageSender,
71
        ShipRepositoryInterface $shipRepository,
72
        ShipSystemManagerInterface $shipSystemManager,
73
        ShipLeaverInterface $shipLeaver,
74
        GameControllerInterface $game,
75
        AstroEntryLibInterface $astroEntryLib,
76
        DatabaseUserRepositoryInterface $databaseUserRepository,
77
        CreateDatabaseEntryInterface $createDatabaseEntry,
78
        StationUtilityInterface $stationUtility,
79
        RepairUtilInterface $repairUtil,
80
        ShipTakeoverManagerInterface $shipTakeoverManager,
81
        LoggerUtilFactoryInterface $loggerUtilFactory
82
    ) {
83
        $this->shipWrapperFactory = $shipWrapperFactory;
84
        $this->privateMessageSender = $privateMessageSender;
85
        $this->shipRepository = $shipRepository;
86
        $this->shipSystemManager = $shipSystemManager;
87
        $this->shipLeaver = $shipLeaver;
88
        $this->game = $game;
89
        $this->astroEntryLib = $astroEntryLib;
90
        $this->databaseUserRepository = $databaseUserRepository;
91
        $this->createDatabaseEntry = $createDatabaseEntry;
92
        $this->stationUtility = $stationUtility;
93
        $this->repairUtil = $repairUtil;
94
        $this->shipTakeoverManager = $shipTakeoverManager;
95
        $this->loggerUtil = $loggerUtilFactory->getLoggerUtil(true);
96
    }
97
98
    public function work(): void
99
    {
100
        foreach ($this->shipRepository->getPlayerShipsForTick() as $ship) {
101
            $this->workShip($this->shipWrapperFactory->wrapShip($ship));
102
        }
103
    }
104
105
    public function workShip(ShipWrapperInterface $wrapper): void
106
    {
107
        $ship = $wrapper->get();
108
109
        $startTime = microtime(true);
110
111
        // do construction stuff
112
        if ($this->doConstructionStuff($ship)) {
113
            $this->shipRepository->save($ship);
114
            $this->sendMessages($ship);
115
            return;
116
        }
117
118
        $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

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

490
        $this->potentialLog($ship, "marker10.1", /** @scrutinizer ignore-type */ $startTime);
Loading history...
491
492
        $startTime = microtime(true);
493
        $isTakeoverReady = $this->shipTakeoverManager->isTakeoverReady($takeover);
494
        $this->potentialLog($ship, "marker10.2", $startTime);
495
496
        if ($isTakeoverReady) {
497
            $startTime = microtime(true);
498
            $this->shipTakeoverManager->finishTakeover($takeover);
499
            $this->potentialLog($ship, "marker10.3", $startTime);
500
        }
501
    }
502
503
    private function checkForFinishedAstroMapping(ShipInterface $ship): void
504
    {
505
        /** @var null|DatabaseEntryInterface $databaseEntry */
506
        [$message, $databaseEntry] = $this->getDatabaseEntryForShipLocation($ship);
507
508
        if (
509
            $ship->getState() === ShipStateEnum::SHIP_STATE_ASTRO_FINALIZING
510
            && $databaseEntry !== null
511
            && $this->game->getCurrentRound()->getTurn() >= ($ship->getAstroStartTurn() + AstronomicalMappingEnum::TURNS_TO_FINISH)
512
        ) {
513
            $this->astroEntryLib->finish($ship);
514
515
            $this->msg[] = sprintf(
516
                _('Die Kartographierung %s wurde vollendet'),
517
                $message
518
            );
519
520
            $userId = $ship->getUser()->getId();
521
            $databaseEntryId = $databaseEntry->getId();
522
523
            if (!$this->databaseUserRepository->exists($userId, $databaseEntryId)) {
524
                $entry = $this->createDatabaseEntry->createDatabaseEntryForUser($ship->getUser(), $databaseEntryId);
525
526
                if ($entry !== null) {
527
                    $this->msg[] = sprintf(
528
                        _('Neuer Datenbankeintrag: %s (+%d Punkte)'),
529
                        $entry->getDescription(),
530
                        $entry->getCategory()->getPoints()
531
                    );
532
                }
533
            }
534
        }
535
    }
536
537
    /**
538
     * @return array{0: string|null, 1: DatabaseEntryInterface|null}
539
     */
540
    private function getDatabaseEntryForShipLocation(ShipInterface $ship): array
541
    {
542
        $system = $ship->getSystem();
543
        if ($system !== null) {
544
            return [
545
                'des Systems ' . $system->getName(),
546
                $system->getDatabaseEntry()
547
            ];
548
        }
549
550
        $mapRegion = $ship->getMapRegion();
551
        if ($mapRegion !== null) {
552
            return [
553
                'der Region ' . $mapRegion->getDescription(),
554
                $mapRegion->getDatabaseEntry()
555
            ];
556
        }
557
558
        return [null, null];
559
    }
560
561
    private function doTrackerDeviceStuff(ShipWrapperInterface $wrapper): void
562
    {
563
        $ship = $wrapper->get();
564
        $tracker = $wrapper->getTrackerSystemData();
565
566
        if ($tracker === null || $tracker->targetId === null) {
567
            return;
568
        }
569
570
        $targetWrapper = $tracker->getTargetWrapper();
571
        if ($targetWrapper === null) {
572
            throw new RuntimeException('should not happen');
573
        }
574
575
        $target = $targetWrapper->get();
576
        $remainingTicks = $tracker->getRemainingTicks();
577
578
        $reduceByTicks = max(1, (int)ceil((abs($ship->getCx() - $target->getCx()) +  abs($ship->getCy() - $target->getCy())) / 50));
579
580
        //reduce remaining ticks
581
        if ($remainingTicks > $reduceByTicks) {
582
            $tracker->setRemainingTicks($remainingTicks - $reduceByTicks)->update();
583
        } else {
584
            $this->shipSystemManager->deactivate($wrapper, ShipSystemTypeEnum::SYSTEM_TRACKER, true);
585
586
            if ($target->getUser() !== $ship->getUser()) {
587
                //send pm to target owner
588
                $this->privateMessageSender->send(
589
                    UserEnum::USER_NOONE,
590
                    $target->getUser()->getId(),
591
                    sprintf(
592
                        'Die Crew der %s hat einen Transponder gefunden und deaktiviert. %s',
593
                        $target->getName(),
594
                        $this->getTrackerSource($ship->getUser())
595
                    ),
596
                    PrivateMessageFolderSpecialEnum::PM_SPECIAL_SHIP
597
                );
598
599
                //send pm to tracker owner
600
                $this->privateMessageSender->send(
601
                    UserEnum::USER_NOONE,
602
                    $ship->getUser()->getId(),
603
                    sprintf(
604
                        'Die %s hat die Verbindung zum Tracker verloren',
605
                        $ship->getName()
606
                    ),
607
                    PrivateMessageFolderSpecialEnum::PM_SPECIAL_SHIP
608
                );
609
            }
610
        }
611
    }
612
613
    private function getTrackerSource(UserInterface $user): string
614
    {
615
        switch (random_int(0, 2)) {
616
            case 0:
617
                return _('Der Ursprung kann nicht identifiziert werden');
618
            case 1:
619
                return sprintf(_('Der Ursprung lässt auf %s schließen'), $user->getName());
620
            case 2:
621
                return sprintf(_('Der Ursprung lässt darauf schließen, dass er %s-Herkunft ist'), $user->getFaction()->getName());
622
            default:
623
                return '';
624
        }
625
    }
626
627
    private function sendMessages(ShipInterface $ship): void
628
    {
629
        if ($this->msg === []) {
630
            return;
631
        }
632
        $text = "Tickreport der " . $ship->getName() . "\n";
633
        foreach ($this->msg as $msg) {
634
            $text .= $msg . "\n";
635
        }
636
637
        $href = sprintf('ship.php?%s=1&id=%d', ShowShip::VIEW_IDENTIFIER, $ship->getId());
638
639
        $this->privateMessageSender->send(
640
            UserEnum::USER_NOONE,
641
            $ship->getUser()->getId(),
642
            $text,
643
            $ship->isBase() ? PrivateMessageFolderSpecialEnum::PM_SPECIAL_STATION : PrivateMessageFolderSpecialEnum::PM_SPECIAL_SHIP,
644
            $href
645
        );
646
647
        $this->msg = [];
648
    }
649
}
650