Passed
Push — master ( 288b46...98b0e3 )
by Nico
31:30 queued 08:00
created

FlightRoute::isWarpDriveNeeded()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 7
c 0
b 0
f 0
nc 3
nop 0
dl 0
loc 13
ccs 0
cts 7
cp 0
crap 20
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Ship\Lib\Movement\Route;
6
7
use Doctrine\Common\Collections\ArrayCollection;
8
use Doctrine\Common\Collections\Collection;
9
use RuntimeException;
10
use Stu\Module\Ship\Lib\Message\MessageCollectionInterface;
11
use Stu\Module\Ship\Lib\Movement\Component\Consequence\FlightConsequenceInterface;
12
use Stu\Module\Ship\Lib\ShipWrapperInterface;
13
use Stu\Orm\Entity\MapInterface;
14
use Stu\Orm\Entity\ShipInterface;
15
use Stu\Orm\Entity\StarSystemMapInterface;
16
use Stu\Orm\Entity\WormholeEntryInterface;
17
18
final class FlightRoute implements FlightRouteInterface
19
{
20
    //Components
21
    private CheckDestinationInterface $checkDestination;
22
23
    private LoadWaypointsInterface $loadWaypoints;
24
25
    private EnterWaypointInterface $enterWaypoint;
26
27
    /** @var array<string, FlightConsequenceInterface>  */
28
    private array $flightConsequences;
29
30
    /** @var array<string, FlightConsequenceInterface> */
31
    private array $postFlightConsequences;
32
33
    //Members
34
    private bool $isTraversing = false;
35
36
    private int $routeMode = RouteModeEnum::ROUTE_MODE_FLIGHT;
37
38
    private MapInterface|StarSystemMapInterface $current;
39
40
    private ?WormholeEntryInterface $wormholeEntry = null;
41
42
    /**
43
     * @var Collection<int, MapInterface|StarSystemMapInterface>
44
     */
45
    private Collection $waypoints;
46
47
    /**
48
     * @param array<string, FlightConsequenceInterface> $flightConsequences
49
     * @param array<string, FlightConsequenceInterface> $postFlightConsequences
50
     */
51 11
    public function __construct(
52
        CheckDestinationInterface $checkDestination,
53
        LoadWaypointsInterface $loadWaypoints,
54
        EnterWaypointInterface $enterWaypoint,
55
        array $flightConsequences,
56
        array $postFlightConsequences,
57
    ) {
58 11
        $this->checkDestination = $checkDestination;
59 11
        $this->loadWaypoints = $loadWaypoints;
60 11
        $this->enterWaypoint = $enterWaypoint;
61 11
        $this->flightConsequences = $flightConsequences;
62 11
        $this->postFlightConsequences = $postFlightConsequences;
63
64 11
        $this->waypoints = new ArrayCollection();
65
    }
66
67 4
    public function setDestination(
68
        MapInterface|StarSystemMapInterface $destination,
69
        bool $isTranswarp
70
    ): FlightRouteInterface {
71 4
        $this->waypoints->add($destination);
72
73 4
        if ($destination instanceof MapInterface) {
74 3
            if ($isTranswarp) {
75 1
                $this->routeMode = RouteModeEnum::ROUTE_MODE_TRANSWARP;
76
            } else {
77 3
                $this->routeMode = RouteModeEnum::ROUTE_MODE_SYSTEM_EXIT;
78
            }
79
        } else {
80 1
            $this->routeMode = RouteModeEnum::ROUTE_MODE_SYSTEM_ENTRY;
81
        }
82
83 4
        return $this;
84
    }
85
86 2
    public function setDestinationViaWormhole(WormholeEntryInterface $wormholeEntry, bool $isEntry): FlightRouteInterface
87
    {
88 2
        $this->wormholeEntry = $wormholeEntry;
89 2
        if ($isEntry) {
90 1
            $this->waypoints->add($wormholeEntry->getSystemMap());
91 1
            $this->routeMode = RouteModeEnum::ROUTE_MODE_WORMHOLE_ENTRY;
92
        } else {
93 1
            $this->waypoints->add($wormholeEntry->getMap());
94 1
            $this->routeMode = RouteModeEnum::ROUTE_MODE_WORMHOLE_EXIT;
95
        }
96
97 2
        return $this;
98
    }
99
100 2
    public function setDestinationViaCoordinates(ShipInterface $ship, int $x, int $y): FlightRouteInterface
101
    {
102 2
        $start = $ship->getCurrentMapField();
103 2
        $this->current = $start;
104 2
        $destination = $this->checkDestination->validate($ship, $x, $y);
105
106 2
        if ($start !== $destination) {
107 1
            $this->waypoints = $this->loadWaypoints->load($start, $destination);
108 1
            $this->isTraversing = true;
109
        }
110
111 2
        return $this;
112
    }
113
114
    public function getCurrentWaypoint(): MapInterface|StarSystemMapInterface
115
    {
116
        return $this->current;
117
    }
118
119 8
    public function getNextWaypoint(): MapInterface|StarSystemMapInterface
120
    {
121 8
        if ($this->waypoints->isEmpty()) {
122 1
            throw new RuntimeException('isDestinationArrived has to be called beforehand');
123
        }
124
125 7
        return $this->waypoints->first();
126
    }
127
128 6
    public function stepForward(): void
129
    {
130 6
        $first =  $this->waypoints->first();
131
132 6
        if (!$first) {
133 1
            return;
134
        }
135
136 6
        $this->current = $first;
137 6
        $this->waypoints->removeElement($this->current);
138
    }
139
140 1
    public function abortFlight(): void
141
    {
142 1
        $this->waypoints->clear();
143
    }
144
145 6
    public function enterNextWaypoint(
146
        ShipWrapperInterface $wrapper,
147
        MessageCollectionInterface $messages
148
    ): void {
149
150
        // flight consequences
151 6
        $this->walkConsequences($this->flightConsequences, $wrapper, $messages);
152
153
        // enter waypoint
154 6
        $this->enterWaypoint->enterNextWaypoint(
155 6
            $wrapper->get(),
156 6
            $this->isTraversing,
157 6
            $this->getNextWaypoint(),
158 6
            $this->wormholeEntry
159 6
        );
160
161
        // post flight consequences
162 6
        $this->walkConsequences($this->postFlightConsequences, $wrapper, $messages);
163
    }
164
165
    /**
166
     * @param array<string, FlightConsequenceInterface> $consequences
167
     */
168 6
    private function walkConsequences(
169
        array $consequences,
170
        ShipWrapperInterface $wrapper,
171
        MessageCollectionInterface $messages
172
    ): void {
173 6
        array_walk(
174 6
            $consequences,
175 6
            fn (FlightConsequenceInterface $consequence) => $consequence->trigger($wrapper, $this, $messages)
176 6
        );
177
    }
178
179 8
    public function isDestinationArrived(): bool
180
    {
181 8
        return $this->waypoints->isEmpty();
182
    }
183
184 6
    public function getRouteMode(): int
185
    {
186 6
        return $this->routeMode;
187
    }
188
189
    public function isTraversing(): bool
190
    {
191
        return $this->isTraversing;
192
    }
193
194
    public function isImpulseDriveNeeded(): bool
195
    {
196
        $routeMode = $this->getRouteMode();
197
198
        if (
199
            $routeMode === RouteModeEnum::ROUTE_MODE_SYSTEM_ENTRY
200
            || $routeMode === RouteModeEnum::ROUTE_MODE_WORMHOLE_ENTRY
201
        ) {
202
            return true;
203
        }
204
205
        return $routeMode === RouteModeEnum::ROUTE_MODE_FLIGHT
206
            && $this->getNextWaypoint() instanceof StarSystemMapInterface;
207
    }
208
209
    public function isWarpDriveNeeded(): bool
210
    {
211
        $routeMode = $this->getRouteMode();
212
213
        if (
214
            $routeMode === RouteModeEnum::ROUTE_MODE_SYSTEM_EXIT
215
            || $routeMode === RouteModeEnum::ROUTE_MODE_TRANSWARP
216
        ) {
217
            return true;
218
        }
219
220
        return $routeMode === RouteModeEnum::ROUTE_MODE_FLIGHT
221
            && $this->getNextWaypoint() instanceof MapInterface;
222
    }
223
224
    public function isTranswarpCoilNeeded(): bool
225
    {
226
        return $this->getRouteMode() === RouteModeEnum::ROUTE_MODE_TRANSWARP;
227
    }
228
}
229