Test Failed
Push — dev ( cc891d...2da33f )
by Janko
09:11
created

Spacecraft::setShieldRegenerationTimer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
ccs 0
cts 3
cp 0
crap 2
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 42
    #[Override]
198
    public function getId(): int
199
    {
200 42
        if ($this->id === null) {
201
            throw new RuntimeException('entity not yet persisted');
202
        }
203
204 42
        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 isCloaked(): 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
    /**
607
     * proportional to tractor beam system status
608
     */
609
    #[Override]
610
    public function getTractorPayload(): int
611
    {
612
        if (!$this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::TRACTOR_BEAM)) {
613
            return 0;
614
        }
615
616 1
        return (int) (ceil($this->getRump()->getTractorPayload()
617
            * $this->getSpacecraftSystem(SpacecraftSystemTypeEnum::TRACTOR_BEAM)->getStatus() / 100));
618
    }
619 1
620
    #[Override]
621
    public function getShieldRegenerationTimer(): int
622
    {
623 1
        return $this->shield_regeneration_timer;
624 1
    }
625
626
    #[Override]
627
    public function getState(): SpacecraftStateEnum
628
    {
629
        return $this->state;
630
    }
631
632
    #[Override]
633
    public function setState(SpacecraftStateEnum $state): SpacecraftInterface
634
    {
635
        $this->state = $state;
636
        return $this;
637
    }
638
639
    #[Override]
640 5
    public function isInEmergency(): bool
641
    {
642
        return $this->in_emergency;
643 5
    }
644
645
    #[Override]
646
    public function setIsInEmergency(bool $inEmergency): SpacecraftInterface
647
    {
648
        $this->in_emergency = $inEmergency;
649
        return $this;
650
    }
651
652
    #[Override]
653 1
    public function isUnderRepair(): bool
654
    {
655
        return $this->getState() === SpacecraftStateEnum::SHIP_STATE_REPAIR_ACTIVE
656 1
            || $this->getState() === SpacecraftStateEnum::SHIP_STATE_REPAIR_PASSIVE;
657
    }
658
659
    #[Override]
660
    public function getCrewAssignments(): Collection
661
    {
662
        return $this->crew;
663
    }
664
665
    #[Override]
666
    public function getPosX(): int
667
    {
668
        return $this->location->getX();
669
    }
670
671
    #[Override]
672
    public function getPosY(): int
673 13
    {
674
        return $this->location->getY();
675
    }
676 13
677
    #[Override]
678
    public function getCrewCount(): int
679 5
    {
680
        return $this->getCrewAssignments()->count();
681
    }
682 5
683
    #[Override]
684
    public function getNeededCrewCount(): int
685 5
    {
686
        $buildplan = $this->getBuildplan();
687
        if ($buildplan === null) {
688 5
            return 0;
689
        }
690
691 12
        return $buildplan->getCrew();
692
    }
693
694 12
    #[Override]
695
    public function getExcessCrewCount(): int
696
    {
697 7
        return $this->getCrewCount() - $this->getNeededCrewCount();
698
    }
699
700 7
    #[Override]
701 7
    public function hasEnoughCrew(?GameControllerInterface $game = null): bool
702
    {
703
        $buildplan = $this->getBuildplan();
704
705 7
        if ($buildplan === null) {
706
            if ($game !== null) {
707
                $game->addInformation(_("Keine Crew vorhanden"));
708 6
            }
709
            return false;
710
        }
711 6
712
        $result = $buildplan->getCrew() <= 0
713
            || $this->getCrewCount() >= $buildplan->getCrew();
714 3
715
        if (!$result && $game !== null) {
716
            $game->addInformationf(
717 3
                _("Es werden %d Crewmitglieder benötigt"),
718
                $buildplan->getCrew()
719 3
            );
720
        }
721
722
        return $result;
723
    }
724
725
    #[Override]
726 3
    public function getUser(): UserInterface
727 3
    {
728
        return $this->user;
729 3
    }
730
731
    #[Override]
732
    public function setUser(UserInterface $user): SpacecraftInterface
733
    {
734
        $this->user = $user;
735
        return $this;
736 3
    }
737
738
    #[Override]
739 44
    public function getSystem(): ?StarSystemInterface
740
    {
741
        return $this->getStarsystemMap() !== null ? $this->getStarsystemMap()->getSystem() : null;
742 44
    }
743
744
    #[Override]
745
    public function getModules(): array
746
    {
747
        $modules = [];
748
749
        $buildplan = $this->getBuildplan();
750
        if ($buildplan === null) {
751
            return $modules;
752 6
        }
753
754
        foreach ($buildplan->getModulesOrdered() as $obj) {
755 6
            $module = $obj->getModule();
756
            $index = $module->getType() === SpacecraftModuleTypeEnum::SPECIAL ? $module->getId() : $module->getType()->value;
757
            $modules[$index] = $module;
758 2
        }
759
760
        return $modules;
761 2
    }
762
763 2
    #[Override]
764 2
    public function isDeflectorHealthy(): bool
765
    {
766
        return $this->isSystemHealthy(SpacecraftSystemTypeEnum::DEFLECTOR);
767
    }
768 2
769 2
    #[Override]
770 2
    public function isMatrixScannerHealthy(): bool
771 2
    {
772
        return $this->isSystemHealthy(SpacecraftSystemTypeEnum::MATRIX_SCANNER);
773
    }
774 2
775
    #[Override]
776
    public function isTorpedoStorageHealthy(): bool
777
    {
778
        return $this->isSystemHealthy(SpacecraftSystemTypeEnum::TORPEDO_STORAGE);
779
    }
780
781
    #[Override]
782
    public function isShuttleRampHealthy(): bool
783
    {
784
        return $this->isSystemHealthy(SpacecraftSystemTypeEnum::SHUTTLE_RAMP);
785
    }
786
787
    #[Override]
788
    public function isWebEmitterHealthy(): bool
789 10
    {
790
        return $this->isSystemHealthy(SpacecraftSystemTypeEnum::THOLIAN_WEB);
791
    }
792 10
793
    #[Override]
794
    public function isTractoring(): bool
795 1
    {
796
        return $this->getTractoredShip() !== null;
797
    }
798 1
799
    #[Override]
800
    public function isOverColony(): ?ColonyInterface
801 1
    {
802
        return $this->getStarsystemMap() !== null ? $this->getStarsystemMap()->getColony() : null;
803
    }
804 1
805
    #[Override]
806
    public function isOverSystem(): ?StarSystemInterface
807 2
    {
808
        $location = $this->getLocation();
809
        if ($location instanceof StarSystemMapInterface) {
810 2
            return null;
811
        }
812
813
        return $location->getSystem();
814
    }
815
816
    #[Override]
817
    public function isWarpPossible(): bool
818
    {
819 2
        return $this->hasSpacecraftSystem(SpacecraftSystemTypeEnum::WARPDRIVE) && $this->getSystem() === null;
820
    }
821
822 2
    #[Override]
823 2
    public function getTorpedo(): ?TorpedoTypeInterface
824
    {
825
        if ($this->getTorpedoStorage() === null) {
826
            return null;
827 2
        }
828
829
        return $this->getTorpedoStorage()->getTorpedo();
830 1
    }
831
832
    #[Override]
833 1
    public function getTorpedoStorage(): ?TorpedoStorageInterface
834
    {
835
        return $this->torpedoStorage;
836 1
    }
837
838
    #[Override]
839 1
    public function setTorpedoStorage(?TorpedoStorageInterface $torpedoStorage): SpacecraftInterface
840 1
    {
841
        $this->torpedoStorage = $torpedoStorage;
842
        return $this;
843
    }
844
845
    #[Override]
846 1
    public function getStorage(): Collection
847
    {
848
        return $this->storage;
849 1
    }
850
851
    #[Override]
852
    public function getLogbook(): Collection
853
    {
854
        return $this->logbook;
855
    }
856
857
    #[Override]
858
    public function getTakeoverActive(): ?ShipTakeoverInterface
859 15
    {
860
        return $this->takeoverActive;
861
    }
862 15
863
    #[Override]
864
    public function setTakeoverActive(?ShipTakeoverInterface $takeover): SpacecraftInterface
865 1
    {
866
        $this->takeoverActive = $takeover;
867
868 1
        return $this;
869
    }
870
871 4
    #[Override]
872
    public function getTakeoverPassive(): ?ShipTakeoverInterface
873
    {
874 4
        return $this->takeoverPassive;
875
    }
876
877
    #[Override]
878
    public function setTakeoverPassive(?ShipTakeoverInterface $takeover): SpacecraftInterface
879
    {
880
        $this->takeoverPassive = $takeover;
881
882
        return $this;
883
    }
884
885 4
    #[Override]
886
    public function getStorageSum(): int
887
    {
888 4
        return array_reduce(
889
            $this->getStorage()->getValues(),
890
            fn(int $sum, StorageInterface $storage): int => $sum + $storage->getAmount(),
891
            0
892
        );
893
    }
894
895
    #[Override]
896
    public function getMaxStorage(): int
897
    {
898
        return $this->getRump()->getStorage();
899 14
    }
900
901
    #[Override]
902 14
    public function getBeamableStorage(): Collection
903 14
    {
904 14
        return CommodityTransfer::excludeNonBeamable($this->storage);
905 14
    }
906 14
907
    #[Override]
908
    public function getMap(): ?MapInterface
909 13
    {
910
        if ($this->location instanceof MapInterface) {
911
            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...
912 13
        }
913
        if ($this->location instanceof StarSystemMapInterface) {
914
            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

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