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

ShipTick::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 28
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 13
c 1
b 0
f 0
nc 1
nop 13
dl 0
loc 28
ccs 0
cts 14
cp 0
crap 2
rs 9.8333

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 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