Test Failed
Push — dev ( 4abd48...6c393a )
by Janko
09:10
created

Spacecraft::getUserId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Orm\Entity;
6
7
use Doctrine\Common\Collections\ArrayCollection;
8
use Doctrine\Common\Collections\Collection;
9
use Doctrine\ORM\Mapping\Column;
10
use Doctrine\ORM\Mapping\DiscriminatorColumn;
11
use Doctrine\ORM\Mapping\DiscriminatorMap;
12
use Doctrine\ORM\Mapping\Entity;
13
use Doctrine\ORM\Mapping\GeneratedValue;
14
use Doctrine\ORM\Mapping\Id;
15
use Doctrine\ORM\Mapping\InheritanceType;
16
use Doctrine\ORM\Mapping\JoinColumn;
17
use Doctrine\ORM\Mapping\ManyToOne;
18
use Doctrine\ORM\Mapping\OneToMany;
19
use Doctrine\ORM\Mapping\OneToOne;
20
use Doctrine\ORM\Mapping\OrderBy;
21
use Doctrine\ORM\Mapping\Table;
22
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...
23
use RuntimeException;
24
use Stu\Component\Game\TimeConstants;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Game\TimeConstants 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...
25
use Stu\Component\Map\DirectionEnum;
26
use Stu\Component\Spacecraft\SpacecraftAlertStateEnum;
27
use Stu\Component\Spacecraft\SpacecraftModuleTypeEnum;
28
use Stu\Component\Spacecraft\SpacecraftRumpEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Spacecraft\SpacecraftRumpEnum 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...
29
use Stu\Component\Spacecraft\SpacecraftStateEnum;
30
use Stu\Component\Spacecraft\SpacecraftLssModeEnum;
31
use Stu\Component\Spacecraft\SpacecraftTypeEnum;
32
use Stu\Component\Spacecraft\System\SpacecraftSystemTypeEnum;
33
use Stu\Component\Spacecraft\System\Type\TorpedoStorageShipSystem;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Spacecraft...orpedoStorageShipSystem 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...
34
use Stu\Component\Spacecraft\System\Type\TractorBeamShipSystem;
35
use Stu\Lib\Transfer\CommodityTransfer;
36
use Stu\Module\Control\GameControllerInterface;
37
use Stu\Module\Logging\LoggerUtilInterface;
38
use Stu\Module\Spacecraft\Lib\Battle\FightLib;
39
use Stu\Orm\Repository\SpacecraftRepository;
40
41
#[Table(name: 'stu_spacecraft')]
42
#[Entity(repositoryClass: SpacecraftRepository::class)]
43
#[InheritanceType('JOINED')]
44
#[DiscriminatorColumn(name: 'type', type: 'string')]
45
#[DiscriminatorMap([
46
    SpacecraftTypeEnum::SHIP->value => Ship::class,
47
    SpacecraftTypeEnum::STATION->value => Station::class
48
])]
49
abstract class Spacecraft implements SpacecraftInterface
50
{
51
    #[Id]
52
    #[Column(type: 'integer')]
53
    #[GeneratedValue(strategy: 'IDENTITY')]
54
    private ?int $id = null;
55
56
    #[Column(type: 'integer')]
57
    private int $user_id = 0;
58
59
    #[Column(type: 'integer')]
60
    private int $rump_id = 0;
0 ignored issues
show
introduced by
The private property $rump_id is not used, and could be removed.
Loading history...
61
62
    #[Column(type: 'integer', nullable: true)]
63
    private ?int $plan_id = null;
0 ignored issues
show
introduced by
The private property $plan_id is not used, and could be removed.
Loading history...
64
65
    #[Column(type: 'smallint', length: 1, enumType: DirectionEnum::class, nullable: true)]
66
    private ?DirectionEnum $direction = null;
67
68
    #[Column(type: 'string')]
69
    private string $name = '';
70
71
    #[Column(type: 'smallint', length: 1, enumType: SpacecraftAlertStateEnum::class)]
72
    private SpacecraftAlertStateEnum $alvl = SpacecraftAlertStateEnum::ALERT_GREEN;
73
74
    #[Column(type: 'smallint', length: 1, enumType: SpacecraftLssModeEnum::class)]
75
    private SpacecraftLssModeEnum $lss_mode = SpacecraftLssModeEnum::LSS_NORMAL;
76
77
    #[Column(type: 'integer', length: 6)]
78
    private int $huelle = 0;
79
80
    #[Column(type: 'integer', length: 6)]
81
    private int $max_huelle = 0;
82
83
    #[Column(type: 'integer', length: 6)]
84
    private int $schilde = 0;
85
86
    #[Column(type: 'integer', length: 6)]
87
    private int $max_schilde = 0;
88
89
    #[Column(type: 'integer', nullable: true)]
90
    private ?int $tractored_ship_id = null;
0 ignored issues
show
introduced by
The private property $tractored_ship_id is not used, and could be removed.
Loading history...
91
92
    #[Column(type: 'integer', nullable: true)]
93
    private ?int $holding_web_id = null;
0 ignored issues
show
introduced by
The private property $holding_web_id is not used, and could be removed.
Loading history...
94
95
    #[Column(type: 'integer', nullable: true)]
96
    private ?int $database_id = null;
97
98
    private bool $is_destroyed = false;
99
100
    #[Column(type: 'boolean')]
101
    private bool $disabled = false;
102
103
    #[Column(type: 'smallint', length: 3)]
104
    private int $hit_chance = 0;
105
106
    #[Column(type: 'smallint', length: 3)]
107
    private int $evade_chance = 0;
108
109
    #[Column(type: 'smallint', length: 4)]
110
    private int $base_damage = 0;
111
112
    #[Column(type: 'smallint', length: 3)]
113
    private int $sensor_range = 0;
114
115
    #[Column(type: 'integer')]
116
    private int $shield_regeneration_timer = 0;
117
118
    #[Column(type: 'smallint', enumType: SpacecraftStateEnum::class)]
119
    private SpacecraftStateEnum $state = SpacecraftStateEnum::SHIP_STATE_NONE;
120
121
    #[Column(type: 'integer')]
122
    private int $location_id = 0;
0 ignored issues
show
introduced by
The private property $location_id is not used, and could be removed.
Loading history...
123
124
    #[Column(type: 'boolean')]
125
    private bool $in_emergency = false;
126
127
    #[OneToOne(targetEntity: 'Ship')]
128
    #[JoinColumn(name: 'tractored_ship_id', referencedColumnName: 'id')]
129
    private ?ShipInterface $tractoredShip = null;
130
131
    #[ManyToOne(targetEntity: 'TholianWeb')]
132
    #[JoinColumn(name: 'holding_web_id', referencedColumnName: 'id')]
133
    private ?TholianWebInterface $holdingWeb = null;
134
135
    #[ManyToOne(targetEntity: 'User')]
136
    #[JoinColumn(name: 'user_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
137
    private UserInterface $user;
138
139
    /**
140
     * @var ArrayCollection<int, CrewAssignmentInterface>
141
     */
142
    #[OneToMany(targetEntity: 'CrewAssignment', mappedBy: 'spacecraft', indexBy: 'id')]
143
    #[OrderBy(['id' => 'ASC'])]
144
    private Collection $crew;
145
146
    #[OneToOne(targetEntity: 'TorpedoStorage', mappedBy: 'spacecraft')]
147
    private ?TorpedoStorageInterface $torpedoStorage = null;
148
149
    /**
150
     * @var ArrayCollection<int, SpacecraftSystemInterface>
151
     */
152
    #[OneToMany(targetEntity: 'SpacecraftSystem', mappedBy: 'spacecraft', indexBy: 'system_type')]
153
    #[OrderBy(['system_type' => 'ASC'])]
154
    private Collection $systems;
155
156
    #[ManyToOne(targetEntity: 'SpacecraftRump')]
157
    #[JoinColumn(name: 'rump_id', referencedColumnName: 'id')]
158
    private SpacecraftRumpInterface $rump;
159
160
    #[ManyToOne(targetEntity: 'SpacecraftBuildplan')]
161
    #[JoinColumn(name: 'plan_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
162
    private ?SpacecraftBuildplanInterface $buildplan = null;
163
164
    /**
165
     * @var ArrayCollection<int, StorageInterface>
166
     */
167
    #[OneToMany(targetEntity: 'Storage', mappedBy: 'spacecraft', indexBy: 'commodity_id')]
168
    #[OrderBy(['commodity_id' => 'ASC'])]
169
    private Collection $storage;
170
171
    #[ManyToOne(targetEntity: 'Location')]
172
    #[JoinColumn(name: 'location_id', referencedColumnName: 'id')]
173
    private LocationInterface $location;
174
175
    /**
176
     * @var ArrayCollection<int, ShipLogInterface>
177
     */
178
    #[OneToMany(targetEntity: 'ShipLog', mappedBy: 'spacecraft', fetch: 'EXTRA_LAZY')]
179
    #[OrderBy(['id' => 'DESC'])]
180
    private Collection $logbook;
181
182
    #[OneToOne(targetEntity: 'ShipTakeover', mappedBy: 'source')]
183
    private ?ShipTakeoverInterface $takeoverActive = null;
184
185
    #[OneToOne(targetEntity: 'ShipTakeover', mappedBy: 'target')]
186
    private ?ShipTakeoverInterface $takeoverPassive = null;
187
188 3
    public function __construct()
189
    {
190 3
        $this->crew = new ArrayCollection();
191 3
        $this->systems = new ArrayCollection();
192 3
        $this->storage = new ArrayCollection();
193 3
        $this->logbook = new ArrayCollection();
194
    }
195
196 41
    #[Override]
197
    public function getId(): int
198
    {
199 41
        if ($this->id === null) {
200
            throw new RuntimeException('entity not yet persisted');
201
        }
202
203 41
        return $this->id;
204
    }
205
206 1
    #[Override]
207
    public function getUserId(): int
208
    {
209 1
        return $this->user_id;
210
    }
211
212 6
    #[Override]
213
    public function getUserName(): string
214
    {
215 6
        return $this->getUser()->getName();
216
    }
217
218
    #[Override]
219
    public function getSystemsId(): ?int
220
    {
221
        return $this->getSystem() !== null ? $this->getSystem()->getId() : null;
222
    }
223
224 3
    #[Override]
225
    public function getLayer(): ?LayerInterface
226
    {
227 3
        return $this->getLocation()->getLayer();
228
    }
229
230
    #[Override]
231
    public function getFlightDirection(): ?DirectionEnum
232
    {
233
        return $this->direction;
234
    }
235
236
    #[Override]
237
    public function setFlightDirection(DirectionEnum $direction): SpacecraftInterface
238
    {
239
        $this->direction = $direction;
240
        return $this;
241
    }
242
243 34
    #[Override]
244
    public function getName(): string
245
    {
246 34
        return $this->name;
247
    }
248
249
    #[Override]
250
    public function setName(string $name): SpacecraftInterface
251
    {
252
        $this->name = $name;
253
        return $this;
254
    }
255
256 2
    #[Override]
257
    public function getLssMode(): SpacecraftLssModeEnum
258
    {
259 2
        return $this->lss_mode;
260
    }
261
262
    #[Override]
263
    public function setLssMode(SpacecraftLssModeEnum $lssMode): SpacecraftInterface
264
    {
265
        $this->lss_mode = $lssMode;
266
        return $this;
267
    }
268
269 6
    #[Override]
270
    public function getAlertState(): SpacecraftAlertStateEnum
271
    {
272 6
        return $this->alvl;
273
    }
274
275
    #[Override]
276
    public function setAlertState(SpacecraftAlertStateEnum $state): SpacecraftInterface
277
    {
278
        $this->alvl = $state;
279
        return $this;
280
    }
281
282
    #[Override]
283
    public function setAlertStateGreen(): SpacecraftInterface
284
    {
285
        return $this->setAlertState(SpacecraftAlertStateEnum::ALERT_GREEN);
286
    }
287
288 20
    #[Override]
289
    public function isSystemHealthy(SpacecraftSystemTypeEnum $type): bool
290
    {
291 20
        if (!$this->hasSpacecraftSystem($type)) {
292 17
            return false;
293
        }
294
295 7
        return $this->getSpacecraftSystem($type)->isHealthy();
296
    }
297
298 32
    #[Override]
299
    public function getSystemState(SpacecraftSystemTypeEnum $type): bool
300
    {
301 32
        if (!$this->hasSpacecraftSystem($type)) {
302 30
            return false;
303
        }
304
305 12
        return $this->getSpacecraftSystem($type)->getMode()->isActivated();
306
    }
307
308 4
    #[Override]
309
    public function getImpulseState(): bool
310
    {
311 4
        return $this->getSystemState(SpacecraftSystemTypeEnum::IMPULSEDRIVE);
312
    }
313
314 6
    #[Override]
315
    public function getWarpDriveState(): bool
316
    {
317 6
        return $this->getSystemState(SpacecraftSystemTypeEnum::WARPDRIVE);
318
    }
319
320 2
    #[Override]
321
    public function isWarped(): bool
322
    {
323 2
        return $this->getWarpDriveState();
324
    }
325
326 4
    #[Override]
327
    public function isHeldByTholianWeb(): bool
328
    {
329 4
        return $this->getHoldingWeb() !== null;
330
    }
331
332 30
    #[Override]
333
    public function getCloakState(): bool
334
    {
335 30
        return $this->getSystemState(SpacecraftSystemTypeEnum::CLOAK);
336
    }
337
338 2
    #[Override]
339
    public function getTachyonState(): bool
340
    {
341 2
        return $this->getSystemState(SpacecraftSystemTypeEnum::TACHYON_SCANNER);
342
    }
343
344 1
    #[Override]
345
    public function getSubspaceState(): bool
346
    {
347 1
        return $this->getSystemState(SpacecraftSystemTypeEnum::SUBSPACE_SCANNER);
348
    }
349
350
    #[Override]
351
    public function getRPGModuleState(): bool
352
    {
353
        return $this->getSystemState(SpacecraftSystemTypeEnum::RPG_MODULE);
354
    }
355
356 14
    #[Override]
357
    public function getHull(): int
358
    {
359 14
        return $this->huelle;
360
    }
361
362
    #[Override]
363
    public function setHuell(int $hull): SpacecraftInterface
364
    {
365
        $this->huelle = $hull;
366
        return $this;
367
    }
368
369 14
    #[Override]
370
    public function getMaxHull(): int
371
    {
372 14
        return $this->max_huelle;
373
    }
374
375
    #[Override]
376
    public function setMaxHuell(int $maxHull): SpacecraftInterface
377
    {
378
        $this->max_huelle = $maxHull;
379
        return $this;
380
    }
381
382 9
    #[Override]
383
    public function getShield(): int
384
    {
385 9
        return $this->schilde;
386
    }
387
388
    #[Override]
389
    public function setShield(int $schilde): SpacecraftInterface
390
    {
391
        $this->schilde = $schilde;
392
        return $this;
393
    }
394
395
    /**
396
     * proportional to shield system status
397
     */
398 9
    #[Override]
399
    public function getMaxShield(bool $isTheoretical = false): int
400
    {
401 9
        if ($isTheoretical || !$this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::SHIELDS)) {
402 5
            return $this->max_schilde;
403
        }
404
405 7
        return (int) (ceil($this->max_schilde
406 7
            * $this->getSpacecraftSystem(SpacecraftSystemTypeEnum::SHIELDS)->getStatus() / 100));
407
    }
408
409
    #[Override]
410
    public function setMaxShield(int $maxShields): SpacecraftInterface
411
    {
412
        $this->max_schilde = $maxShields;
413
        return $this;
414
    }
415
416
    #[Override]
417
    public function getHealthPercentage(): float
418
    {
419
        return ($this->getHull() + $this->getShield())
420
            / ($this->getMaxHull() + $this->getMaxShield(true)) * 100;
421
    }
422
423 20
    #[Override]
424
    public function getShieldState(): bool
425
    {
426 20
        return $this->getSystemState(SpacecraftSystemTypeEnum::SHIELDS);
427
    }
428
429 6
    #[Override]
430
    public function getNbs(): bool
431
    {
432 6
        return $this->getSystemState(SpacecraftSystemTypeEnum::NBS);
433
    }
434
435 6
    #[Override]
436
    public function getLss(): bool
437
    {
438 6
        return $this->getSystemState(SpacecraftSystemTypeEnum::LSS);
439
    }
440
441 3
    #[Override]
442
    public function getPhaserState(): bool
443
    {
444 3
        return $this->getSystemState(SpacecraftSystemTypeEnum::PHASER);
445
    }
446
447 1
    #[Override]
448
    public function isAlertGreen(): bool
449
    {
450 1
        return $this->getAlertState() === SpacecraftAlertStateEnum::ALERT_GREEN;
451
    }
452
453 1
    #[Override]
454
    public function getTorpedoState(): bool
455
    {
456 1
        return $this->getSystemState(SpacecraftSystemTypeEnum::TORPEDO);
457
    }
458
459
    #[Override]
460
    public function getTorpedoCount(): int
461
    {
462
        if ($this->getTorpedoStorage() === null) {
463
            return 0;
464
        }
465
466
        return $this->getTorpedoStorage()->getStorage()->getAmount();
467
    }
468
469 7
    #[Override]
470
    public function isStation(): bool
471
    {
472 7
        return $this instanceof StationInterface;
473
    }
474
475 1
    #[Override]
476
    public function isShuttle(): bool
477
    {
478 1
        return $this->getRump()->getCategoryId() === SpacecraftRumpEnum::SHIP_CATEGORY_SHUTTLE;
479
    }
480
481 2
    #[Override]
482
    public function isConstruction(): bool
483
    {
484 2
        return $this->getRump()->getCategoryId() === SpacecraftRumpEnum::SHIP_CATEGORY_CONSTRUCTION;
485
    }
486
487 1
    #[Override]
488
    public function getDatabaseId(): ?int
489
    {
490 1
        return $this->database_id;
491
    }
492
493
    #[Override]
494
    public function setDatabaseId(?int $databaseEntryId): SpacecraftInterface
495
    {
496
        $this->database_id = $databaseEntryId;
497
        return $this;
498
    }
499
500 10
    #[Override]
501
    public function isDestroyed(): bool
502
    {
503 10
        return $this->is_destroyed;
504
    }
505
506
    #[Override]
507
    public function setIsDestroyed(bool $isDestroyed): SpacecraftInterface
508
    {
509
        $this->is_destroyed = $isDestroyed;
510
        return $this;
511
    }
512
513
    #[Override]
514
    public function isDisabled(): bool
515
    {
516
        return $this->disabled;
517
    }
518
519
    #[Override]
520
    public function setDisabled(bool $isDisabled): SpacecraftInterface
521
    {
522
        $this->disabled = $isDisabled;
523
        return $this;
524
    }
525
526
527
528
    /**
529
     * proportional to computer system status
530
     */
531 1
    #[Override]
532
    public function getHitChance(): int
533
    {
534 1
        if (!$this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::COMPUTER)) {
535
            return $this->hit_chance;
536
        }
537
538 1
        return (int) (ceil($this->hit_chance
539 1
            * $this->getSpacecraftSystem(SpacecraftSystemTypeEnum::COMPUTER)->getStatus() / 100));
540
    }
541
542
    #[Override]
543
    public function setHitChance(int $hitChance): SpacecraftInterface
544
    {
545
        $this->hit_chance = $hitChance;
546
        return $this;
547
    }
548
549
    /**
550
     * proportional to impulsedrive system status
551
     */
552 1
    #[Override]
553
    public function getEvadeChance(): int
554
    {
555 1
        if (!$this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::IMPULSEDRIVE)) {
556
            return $this->evade_chance;
557
        }
558
559 1
        return (int) (ceil($this->evade_chance
560 1
            * $this->getSpacecraftSystem(SpacecraftSystemTypeEnum::IMPULSEDRIVE)->getStatus() / 100));
561
    }
562
563
    #[Override]
564
    public function setEvadeChance(int $evadeChance): SpacecraftInterface
565
    {
566
        $this->evade_chance = $evadeChance;
567
        return $this;
568
    }
569
570
    /**
571
     * proportional to energy weapon system status
572
     */
573 1
    #[Override]
574
    public function getBaseDamage(): int
575
    {
576 1
        if (!$this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::PHASER)) {
577
            return $this->base_damage;
578
        }
579
580 1
        return (int) (ceil($this->base_damage
581 1
            * $this->getSpacecraftSystem(SpacecraftSystemTypeEnum::PHASER)->getStatus() / 100));
582
    }
583
584
    #[Override]
585
    public function setBaseDamage(int $baseDamage): SpacecraftInterface
586
    {
587
        $this->base_damage = $baseDamage;
588
        return $this;
589
    }
590
591
    /**
592
     * proportional to sensor system status
593
     */
594 2
    #[Override]
595
    public function getSensorRange(): int
596
    {
597 2
        if (!$this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::LSS)) {
598
            return $this->sensor_range;
599
        }
600
601 2
        return (int) (ceil($this->sensor_range
602 2
            * $this->getSpacecraftSystem(SpacecraftSystemTypeEnum::LSS)->getStatus() / 100));
603
    }
604
605
    #[Override]
606
    public function setSensorRange(int $sensorRange): SpacecraftInterface
607
    {
608
        $this->sensor_range = $sensorRange;
609
        return $this;
610
    }
611
612
    /**
613
     * proportional to tractor beam system status
614
     */
615 1
    #[Override]
616
    public function getTractorPayload(): int
617
    {
618 1
        if (!$this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::TRACTOR_BEAM)) {
619
            return 0;
620
        }
621
622 1
        return (int) (ceil($this->getRump()->getTractorPayload()
623 1
            * $this->getSpacecraftSystem(SpacecraftSystemTypeEnum::TRACTOR_BEAM)->getStatus() / 100));
624
    }
625
626
    #[Override]
627
    public function getShieldRegenerationTimer(): int
628
    {
629
        return $this->shield_regeneration_timer;
630
    }
631
632
    #[Override]
633
    public function setShieldRegenerationTimer(int $shieldRegenerationTimer): SpacecraftInterface
634
    {
635
        $this->shield_regeneration_timer = $shieldRegenerationTimer;
636
        return $this;
637
    }
638
639 5
    #[Override]
640
    public function getState(): SpacecraftStateEnum
641
    {
642 5
        return $this->state;
643
    }
644
645
    #[Override]
646
    public function setState(SpacecraftStateEnum $state): SpacecraftInterface
647
    {
648
        $this->state = $state;
649
        return $this;
650
    }
651
652 1
    #[Override]
653
    public function isInEmergency(): bool
654
    {
655 1
        return $this->in_emergency;
656
    }
657
658
    #[Override]
659
    public function setIsInEmergency(bool $inEmergency): SpacecraftInterface
660
    {
661
        $this->in_emergency = $inEmergency;
662
        return $this;
663
    }
664
665
    #[Override]
666
    public function isUnderRepair(): bool
667
    {
668
        return $this->getState() === SpacecraftStateEnum::SHIP_STATE_REPAIR_ACTIVE
669
            || $this->getState() === SpacecraftStateEnum::SHIP_STATE_REPAIR_PASSIVE;
670
    }
671
672 13
    #[Override]
673
    public function getCrewAssignments(): Collection
674
    {
675 13
        return $this->crew;
676
    }
677
678 5
    #[Override]
679
    public function getPosX(): int
680
    {
681 5
        return $this->location->getX();
682
    }
683
684 5
    #[Override]
685
    public function getPosY(): int
686
    {
687 5
        return $this->location->getY();
688
    }
689
690 12
    #[Override]
691
    public function getCrewCount(): int
692
    {
693 12
        return $this->getCrewAssignments()->count();
694
    }
695
696 7
    #[Override]
697
    public function getNeededCrewCount(): int
698
    {
699 7
        $buildplan = $this->getBuildplan();
700 7
        if ($buildplan === null) {
701
            return 0;
702
        }
703
704 7
        return $buildplan->getCrew();
705
    }
706
707 6
    #[Override]
708
    public function getExcessCrewCount(): int
709
    {
710 6
        return $this->getCrewCount() - $this->getNeededCrewCount();
711
    }
712
713 3
    #[Override]
714
    public function hasEnoughCrew(?GameControllerInterface $game = null): bool
715
    {
716 3
        $buildplan = $this->getBuildplan();
717
718 3
        if ($buildplan === null) {
719
            if ($game !== null) {
720
                $game->addInformation(_("Keine Crew vorhanden"));
721
            }
722
            return false;
723
        }
724
725 3
        $result = $buildplan->getCrew() <= 0
726 3
            || $this->getCrewCount() >= $buildplan->getCrew();
727
728 3
        if (!$result && $game !== null) {
729
            $game->addInformationf(
730
                _("Es werden %d Crewmitglieder benötigt"),
731
                $buildplan->getCrew()
732
            );
733
        }
734
735 3
        return $result;
736
    }
737
738 44
    #[Override]
739
    public function getUser(): UserInterface
740
    {
741 44
        return $this->user;
742
    }
743
744
    #[Override]
745
    public function setUser(UserInterface $user): SpacecraftInterface
746
    {
747
        $this->user = $user;
748
        return $this;
749
    }
750
751 6
    #[Override]
752
    public function getSystem(): ?StarSystemInterface
753
    {
754 6
        return $this->getStarsystemMap() !== null ? $this->getStarsystemMap()->getSystem() : null;
755
    }
756
757 2
    #[Override]
758
    public function getModules(): array
759
    {
760 2
        $modules = [];
761
762 2
        $buildplan = $this->getBuildplan();
763 2
        if ($buildplan === null) {
764
            return $modules;
765
        }
766
767 2
        foreach ($buildplan->getModulesOrdered() as $obj) {
768 2
            $module = $obj->getModule();
769 2
            $index = $module->getType() === SpacecraftModuleTypeEnum::SPECIAL ? $module->getId() : $module->getType()->value;
770 2
            $modules[$index] = $module;
771
        }
772
773 2
        return $modules;
774
    }
775
776
    #[Override]
777
    public function isDeflectorHealthy(): bool
778
    {
779
        return $this->isSystemHealthy(SpacecraftSystemTypeEnum::DEFLECTOR);
780
    }
781
782
    #[Override]
783
    public function isMatrixScannerHealthy(): bool
784
    {
785
        return $this->isSystemHealthy(SpacecraftSystemTypeEnum::MATRIX_SCANNER);
786
    }
787
788 10
    #[Override]
789
    public function isTorpedoStorageHealthy(): bool
790
    {
791 10
        return $this->isSystemHealthy(SpacecraftSystemTypeEnum::TORPEDO_STORAGE);
792
    }
793
794 1
    #[Override]
795
    public function isShuttleRampHealthy(): bool
796
    {
797 1
        return $this->isSystemHealthy(SpacecraftSystemTypeEnum::SHUTTLE_RAMP);
798
    }
799
800 1
    #[Override]
801
    public function isWebEmitterHealthy(): bool
802
    {
803 1
        return $this->isSystemHealthy(SpacecraftSystemTypeEnum::THOLIAN_WEB);
804
    }
805
806 2
    #[Override]
807
    public function isTractoring(): bool
808
    {
809 2
        return $this->getTractoredShip() !== null;
810
    }
811
812
    #[Override]
813
    public function isOverColony(): ?ColonyInterface
814
    {
815
        return $this->getStarsystemMap() !== null ? $this->getStarsystemMap()->getColony() : null;
816
    }
817
818 2
    #[Override]
819
    public function isOverSystem(): ?StarSystemInterface
820
    {
821 2
        $location = $this->getLocation();
822 2
        if ($location instanceof StarSystemMapInterface) {
823
            return null;
824
        }
825
826 2
        return $location->getSystem();
827
    }
828
829 1
    #[Override]
830
    public function isWarpPossible(): bool
831
    {
832 1
        return $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::WARPDRIVE) && $this->getSystem() === null;
833
    }
834
835 1
    #[Override]
836
    public function getTorpedo(): ?TorpedoTypeInterface
837
    {
838 1
        if ($this->getTorpedoStorage() === null) {
839 1
            return null;
840
        }
841
842
        return $this->getTorpedoStorage()->getTorpedo();
843
    }
844
845 1
    #[Override]
846
    public function getTorpedoStorage(): ?TorpedoStorageInterface
847
    {
848 1
        return $this->torpedoStorage;
849
    }
850
851
    #[Override]
852
    public function setTorpedoStorage(?TorpedoStorageInterface $torpedoStorage): SpacecraftInterface
853
    {
854
        $this->torpedoStorage = $torpedoStorage;
855
        return $this;
856
    }
857
858 15
    #[Override]
859
    public function getStorage(): Collection
860
    {
861 15
        return $this->storage;
862
    }
863
864 1
    #[Override]
865
    public function getLogbook(): Collection
866
    {
867 1
        return $this->logbook;
868
    }
869
870 4
    #[Override]
871
    public function getTakeoverActive(): ?ShipTakeoverInterface
872
    {
873 4
        return $this->takeoverActive;
874
    }
875
876
    #[Override]
877
    public function setTakeoverActive(?ShipTakeoverInterface $takeover): SpacecraftInterface
878
    {
879
        $this->takeoverActive = $takeover;
880
881
        return $this;
882
    }
883
884 4
    #[Override]
885
    public function getTakeoverPassive(): ?ShipTakeoverInterface
886
    {
887 4
        return $this->takeoverPassive;
888
    }
889
890
    #[Override]
891
    public function setTakeoverPassive(?ShipTakeoverInterface $takeover): SpacecraftInterface
892
    {
893
        $this->takeoverPassive = $takeover;
894
895
        return $this;
896
    }
897
898 14
    #[Override]
899
    public function getStorageSum(): int
900
    {
901 14
        return array_reduce(
902 14
            $this->getStorage()->getValues(),
903 14
            fn(int $sum, StorageInterface $storage): int => $sum + $storage->getAmount(),
904 14
            0
905 14
        );
906
    }
907
908 13
    #[Override]
909
    public function getMaxStorage(): int
910
    {
911 13
        return $this->getRump()->getStorage();
912
    }
913
914 8
    #[Override]
915
    public function getBeamableStorage(): Collection
916
    {
917 8
        return CommodityTransfer::excludeNonBeamable($this->storage);
918
    }
919
920 8
    #[Override]
921
    public function getMap(): ?MapInterface
922
    {
923 8
        if ($this->location instanceof MapInterface) {
924 6
            return $this->location;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->location returns the type Stu\Orm\Entity\LocationInterface which includes types incompatible with the type-hinted return Stu\Orm\Entity\MapInterface|null.
Loading history...
925
        }
926 2
        if ($this->location instanceof StarSystemMapInterface) {
927 2
            return $this->location->getSystem()->getMap();
0 ignored issues
show
Bug introduced by
The method getSystem() does not exist on Stu\Orm\Entity\LocationInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Stu\Orm\Entity\Location. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

927
            return $this->location->/** @scrutinizer ignore-call */ getSystem()->getMap();
Loading history...
928
        }
929
930
        return null;
931
    }
932
933 2
    #[Override]
934
    public function getMapRegion(): ?MapRegionInterface
935
    {
936 2
        $systemMap = $this->getStarsystemMap();
937 2
        if ($systemMap !== null) {
938
            return null;
939
        }
940
941 2
        $map = $this->getMap();
942 2
        if ($map === null) {
943
            return null;
944
        }
945
946 2
        return $map->getMapRegion();
947
    }
948
949 3
    #[Override]
950
    public function setLocation(LocationInterface $location): SpacecraftInterface
951
    {
952 3
        $this->location = $location;
953
954 3
        return $this;
955
    }
956
957 9
    #[Override]
958
    public function getStarsystemMap(): ?StarSystemMapInterface
959
    {
960 9
        if ($this->location instanceof StarSystemMapInterface) {
961 5
            return $this->location;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->location returns the type Stu\Orm\Entity\LocationInterface which includes types incompatible with the type-hinted return Stu\Orm\Entity\StarSystemMapInterface|null.
Loading history...
962
        }
963
964 6
        return null;
965
    }
966
967 31
    #[Override]
968
    public function getLocation(): MapInterface|StarSystemMapInterface
969
    {
970
        if (
971 31
            $this->location instanceof MapInterface
972 31
            || $this->location instanceof StarSystemMapInterface
973
        ) {
974 31
            return $this->location;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->location returns the type Stu\Orm\Entity\LocationInterface which includes types incompatible with the type-hinted return Stu\Orm\Entity\MapInterf...\StarSystemMapInterface.
Loading history...
975
        }
976
977
        throw new RuntimeException('unknown type');
978
    }
979
980 11
    #[Override]
981
    public function getBeamFactor(): int
982
    {
983 11
        return $this->getRump()->getBeamFactor();
984
    }
985
986 4
    #[Override]
987
    public function getSectorString(): string
988
    {
989 4
        return $this->getLocation()->getSectorString();
990
    }
991
992 13
    #[Override]
993
    public function getBuildplan(): ?SpacecraftBuildplanInterface
994
    {
995 13
        return $this->buildplan;
996
    }
997
998
    #[Override]
999
    public function setBuildplan(?SpacecraftBuildplanInterface $spacecraftBuildplan): SpacecraftInterface
1000
    {
1001
        $this->buildplan = $spacecraftBuildplan;
1002
        return $this;
1003
    }
1004
1005 37
    #[Override]
1006
    public function getSystems(): Collection
1007
    {
1008 37
        return $this->systems;
1009
    }
1010
1011 36
    #[Override]
1012
    public function hasSpacecraftSystem(SpacecraftSystemTypeEnum $type): bool
1013
    {
1014 36
        return $this->getSystems()->containsKey($type->value);
1015
    }
1016
1017 17
    #[Override]
1018
    public function getSpacecraftSystem(SpacecraftSystemTypeEnum $type): SpacecraftSystemInterface
1019
    {
1020 17
        $system = $this->getSystems()->get($type->value);
1021 17
        if ($system === null) {
1022
            throw new RuntimeException(sprintf('system type %d does not exist on ship', $type->value));
1023
        }
1024
1025 17
        return $system;
1026
    }
1027
1028 1
    #[Override]
1029
    public function displayNbsActions(): bool
1030
    {
1031 1
        return !$this->getCloakState()
1032 1
            && !$this->isWarped();
1033
    }
1034
1035
    #[Override]
1036
    public function isTractorbeamPossible(): bool
1037
    {
1038
        return TractorBeamShipSystem::isTractorBeamPossible($this);
1039
    }
1040
1041
    #[Override]
1042
    public function isBoardingPossible(): bool
1043
    {
1044
        return FightLib::isBoardingPossible($this);
1045
    }
1046
1047
    #[Override]
1048
    public function isInterceptable(): bool
1049
    {
1050
        //TODO can tractored ships be intercepted?!
1051
        return $this->getWarpDriveState();
1052
    }
1053
1054 2
    #[Override]
1055
    public function getTractoredShip(): ?ShipInterface
1056
    {
1057 2
        return $this->tractoredShip;
1058
    }
1059
1060
    #[Override]
1061
    public function setTractoredShip(?ShipInterface $ship): SpacecraftInterface
1062
    {
1063
        $this->tractoredShip = $ship;
1064
        return $this;
1065
    }
1066
1067 8
    #[Override]
1068
    public function getHoldingWeb(): ?TholianWebInterface
1069
    {
1070 8
        return $this->holdingWeb;
1071
    }
1072
1073
    #[Override]
1074
    public function setHoldingWeb(?TholianWebInterface $web): SpacecraftInterface
1075
    {
1076
        $this->holdingWeb = $web;
1077
1078
        return $this;
1079
    }
1080
1081
    #[Override]
1082
    public function getHoldingWebBackgroundStyle(): string
1083
    {
1084
        if ($this->getHoldingWeb() === null) {
1085 4
            return '';
1086
        }
1087
1088 4
        if ($this->getHoldingWeb()->isFinished()) {
1089 4
            $icon =  'web.png';
1090
        } else {
1091
            $closeTofinish = $this->getHoldingWeb()->getFinishedTime() - time() < TimeConstants::ONE_HOUR_IN_SECONDS;
1092
1093
            $icon = $closeTofinish ? 'web_u.png' : 'web_u2.png';
1094
        }
1095
1096
        return sprintf('src="assets/buttons/%s"; class="indexedGraphics" style="z-index: 5;"', $icon);
1097
    }
1098
1099
    public function getHoldingWebImageStyle(): string
1100
    {
1101
        if ($this->getHoldingWeb() === null) {
1102
            return '';
1103
        }
1104
1105
        if ($this->getHoldingWeb()->isFinished()) {
1106
            $icon =  'webfill.png';
1107
        } else {
1108
            $closeTofinish = $this->getHoldingWeb()->getFinishedTime() - time() < TimeConstants::ONE_HOUR_IN_SECONDS;
1109
1110
            $icon = $closeTofinish ? 'web_ufill.png' : 'web_ufill2.png';
1111
        }
1112
1113
        return $icon;
1114
    }
1115
1116
    private function getShieldRegenerationPercentage(): int
1117
    {
1118
        return $this->isSystemHealthy(SpacecraftSystemTypeEnum::SHIELDS) ? 10 : 0;
1119
    }
1120 7
1121
    #[Override]
1122 7
    public function getShieldRegenerationRate(): int
1123
    {
1124
        return (int) ceil(($this->getMaxShield() / 100) * $this->getShieldRegenerationPercentage());
1125 7
    }
1126
1127
    #[Override]
1128 7
    public function canIntercept(): bool
1129
    {
1130
        return $this->isSystemHealthy(SpacecraftSystemTypeEnum::WARPDRIVE)
1131 1
            && !$this->isTractoring()
1132
            && (!$this instanceof ShipInterface || !$this->isTractored());
1133
    }
1134 1
1135 1
    #[Override]
1136 1
    public function canMove(): bool
1137
    {
1138
        return $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::WARPDRIVE)
1139 3
            || $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::IMPULSEDRIVE);
1140
    }
1141
1142 3
    #[Override]
1143 3
    public function hasActiveWeapon(): bool
1144
    {
1145
        return $this->getPhaserState() || $this->getTorpedoState();
1146 1
    }
1147
1148
    #[Override]
1149 1
    public function hasEscapePods(): bool
1150
    {
1151
        return $this->getRump()->isEscapePods() && $this->getCrewCount() > 0;
1152
    }
1153
1154
    #[Override]
1155
    public function getRepairRate(): int
1156
    {
1157
        // @todo
1158 1
        return 100;
1159
    }
1160
1161
    #[Override]
1162 1
    public function getRump(): SpacecraftRumpInterface
1163
    {
1164
        return $this->rump;
1165 35
    }
1166
1167
    #[Override]
1168 35
    public function getRumpId(): int
1169
    {
1170
        return $this->getRump()->getId();
1171 18
    }
1172
1173
    #[Override]
1174 18
    public function getRumpName(): string
1175
    {
1176
        return $this->getRump()->getName();
1177 18
    }
1178
1179
    #[Override]
1180 18
    public function setRump(SpacecraftRumpInterface $shipRump): SpacecraftInterface
1181
    {
1182
        $this->rump = $shipRump;
1183
        return $this;
1184
    }
1185
1186
    #[Override]
1187
    public function hasPhaser(): bool
1188
    {
1189
        return $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::PHASER);
1190 4
    }
1191
1192
    #[Override]
1193 4
    public function hasTorpedo(): bool
1194
    {
1195
        return $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::TORPEDO);
1196 6
    }
1197
1198
    #[Override]
1199 6
    public function hasCloak(): bool
1200
    {
1201
        return $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::CLOAK);
1202 4
    }
1203
1204
    #[Override]
1205 4
    public function hasShuttleRamp(): bool
1206
    {
1207
        return $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::SHUTTLE_RAMP);
1208 4
    }
1209
1210
    #[Override]
1211 4
    public function hasWarpdrive(): bool
1212
    {
1213
        return $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::WARPDRIVE);
1214 6
    }
1215
1216
    #[Override]
1217 6
    public function hasReactor(): bool
1218
    {
1219
        return $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::WARPCORE) ||
1220 1
            $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::FUSION_REACTOR) ||
1221
            $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::SINGULARITY_REACTOR);
1222
    }
1223 1
1224 1
    #[Override]
1225 1
    public function hasNbsLss(): bool
1226
    {
1227
        return $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::LSS);
1228 2
    }
1229
1230
    #[Override]
1231 2
    public function hasUplink(): bool
1232
    {
1233
        return $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::UPLINK);
1234 6
    }
1235
1236
    #[Override]
1237 6
    public function getMaxTorpedos(): int
1238
    {
1239
        return $this->getRump()->getBaseTorpedoStorage()
1240 3
            + ($this->isSystemHealthy(SpacecraftSystemTypeEnum::TORPEDO_STORAGE)
1241
                ? TorpedoStorageShipSystem::TORPEDO_CAPACITY : 0);
1242
    }
1243 3
1244 3
    #[Override]
1245 3
    public function hasFreeShuttleSpace(?LoggerUtilInterface $loggerUtil = null): bool
1246
    {
1247
        if ($loggerUtil !== null) {
1248
            $loggerUtil->log(sprintf('rumpShuttleSlots: %d', $this->getRump()->getShuttleSlots()));
1249
            $loggerUtil->log(sprintf('storedShuttleCount: %d', $this->getStoredShuttleCount()));
1250
        }
1251
        return $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::SHUTTLE_RAMP)
1252
            && $this->getRump()->getShuttleSlots() - $this->getStoredShuttleCount() > 0;
1253
    }
1254
1255
    #[Override]
1256
    public function getStoredShuttles(): array
1257
    {
1258
        $shuttles = [];
1259
1260
        foreach ($this->getStorage() as $stor) {
1261
            if ($stor->getCommodity()->isShuttle()) {
1262
                $shuttles[] = $stor->getCommodity();
1263
            }
1264
        }
1265
1266
        return $shuttles;
1267
    }
1268
1269
    #[Override]
1270
    public function getStoredShuttleCount(): int
1271
    {
1272
        $count = 0;
1273
1274
        foreach ($this->getStorage() as $stor) {
1275
            if ($stor->getCommodity()->isShuttle()) {
1276
                $count += $stor->getAmount();
1277
            }
1278
        }
1279
1280
        return $count;
1281
    }
1282
1283
    /**
1284
     * @return CommodityInterface[]
1285
     */
1286
    #[Override]
1287
    public function getStoredBuoy(): array
1288
    {
1289
        $buoy = [];
1290 2
1291
        foreach ($this->getStorage() as $stor) {
1292
            if ($stor->getCommodity()->isBouy()) {
1293 2
                $buoy[] = $stor->getCommodity();
1294
            }
1295 2
        }
1296 1
1297
        return $buoy;
1298
    }
1299
1300
1301 2
    #[Override]
1302
    public function hasStoredBuoy(): bool
1303
    {
1304
        return $this->getStoredBuoy() !== [];
1305 2
    }
1306
1307
    #[Override]
1308 2
    public function canMan(): bool
1309
    {
1310
        $buildplan = $this->getBuildplan();
1311 2
1312
        return $buildplan !== null
1313
            && $buildplan->getCrew() > 0
1314 2
            && $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::LIFE_SUPPORT);
1315
    }
1316 2
1317 2
    #[Override]
1318 2
    public function hasCrewmanOfUser(int $userId): bool
1319
    {
1320
        foreach ($this->getCrewAssignments() as $shipCrew) {
1321
            if ($shipCrew->getCrew()->getUser()->getId() === $userId) {
1322
                return true;
1323
            }
1324
        }
1325
1326
        return false;
1327
    }
1328
1329
    #[Override]
1330
    public function getHref(): string
1331
    {
1332
        return sprintf(
1333 4
            '%s?%s=1&id=%d',
1334
            $this->getType()->getModuleView()->getPhpPage(),
1335
            $this->getType()->getViewIdentifier(),
1336 4
            $this->getId()
1337 4
        );
1338 4
    }
1339 4
1340 4
    #[Override]
1341 4
    public function __toString(): string
1342
    {
1343
        if ($this->id !== null) {
1344
            return sprintf('id: %d, name: %s', $this->getId(), $this->getName());
1345
        }
1346
1347
        return $this->getName();
1348
    }
1349
1350
    #[Override]
1351
    public function getHullColorStyle(): string
1352
    {
1353
        return $this->getColorStyle($this->getHull(), $this->getMaxHull());
1354 4
    }
1355
1356
    private function getColorStyle(int $actual, int $max): string
1357 4
    {
1358
        // full
1359
        if ($actual === $max) {
1360 4
            return '';
1361
        }
1362
1363 4
        // less than 100% - green
1364 3
        if ($actual / $max > 0.75) {
1365
            return 'color: #19c100;';
1366
        }
1367
1368 1
        // less than 75% - yellow
1369 1
        if ($actual / $max > 0.50) {
1370
            return 'color: #f4e932;';
1371
        }
1372
1373
        // less than 50% - orange
1374
        if ($actual / $max > 0.25) {
1375
            return 'color: #f48b28;';
1376
        }
1377
1378
        // less than 25% - red
1379
        return 'color: #ff3c3c;';
1380
    }
1381
}
1382