Passed
Push — dev ( 80c162...225d4f )
by Janko
09:12
created

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

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