Passed
Push — dev ( b53f20...068554 )
by Janko
09:40
created

Spacecraft::getSensorRange()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 5
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 9
ccs 0
cts 5
cp 0
crap 6
rs 10

1 Method

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

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