FlightRoute::enterNextWaypoint()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 40
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 20
nc 1
nop 2
dl 0
loc 40
ccs 27
cts 27
cp 1
crap 1
rs 9.6
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Spacecraft\Lib\Movement\Route;
6
7
use Doctrine\Common\Collections\ArrayCollection;
8
use Doctrine\Common\Collections\Collection;
9
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...
10
use RuntimeException;
11
use Stu\Component\Map\Effects\EffectHandlingInterface;
12
use Stu\Lib\Map\FieldTypeEffectEnum;
13
use Stu\Module\Spacecraft\Lib\Message\MessageCollectionInterface;
14
use Stu\Module\Spacecraft\Lib\Movement\Component\Consequence\FlightConsequenceInterface;
15
use Stu\Module\Spacecraft\Lib\Movement\FlightCompany;
16
use Stu\Module\Spacecraft\Lib\SpacecraftWrapperInterface;
17
use Stu\Orm\Entity\Location;
18
use Stu\Orm\Entity\Map;
19
use Stu\Orm\Entity\Spacecraft;
20
use Stu\Orm\Entity\StarSystemMap;
21
use Stu\Orm\Entity\Station;
22
use Stu\Orm\Entity\WormholeEntry;
23
24
final class FlightRoute implements FlightRouteInterface
25
{
26
    //Members
27
    private bool $isTraversing = false;
28
29
    private RouteModeEnum $routeMode = RouteModeEnum::FLIGHT;
30
31
    private Location $current;
32
33
    private ?WormholeEntry $wormholeEntry = null;
34
35
    /**
36
     * @var Collection<int, Location>
37
     */
38
    private Collection $waypoints;
39
40
    /**
41
     * @param array<string, FlightConsequenceInterface> $flightConsequences
42
     * @param array<string, FlightConsequenceInterface> $postFlightConsequences
43
     */
44 21
    public function __construct(
45
        private CheckDestinationInterface $checkDestination,
46
        private LoadWaypointsInterface $loadWaypoints,
47
        private EnterWaypointInterface $enterWaypoint,
48
        private EffectHandlingInterface $effectHandling,
49
        private array $flightConsequences,
50
        private array $postFlightConsequences,
51
    ) {
52 21
        $this->waypoints = new ArrayCollection();
53
    }
54
55 8
    #[Override]
56
    public function setDestination(
57
        Map|StarSystemMap $destination,
58
        bool $isTranswarp
59
    ): FlightRouteInterface {
60 8
        $this->waypoints->add($destination);
61
62 8
        if ($destination instanceof Map) {
63 6
            if ($isTranswarp) {
64 1
                $this->routeMode = RouteModeEnum::TRANSWARP;
65
            } else {
66 5
                $this->routeMode = RouteModeEnum::SYSTEM_EXIT;
67
            }
68
        } else {
69 2
            $this->routeMode = RouteModeEnum::SYSTEM_ENTRY;
70
        }
71
72 8
        return $this;
73
    }
74
75 2
    #[Override]
76
    public function setDestinationViaWormhole(WormholeEntry $wormholeEntry, bool $isEntry): FlightRouteInterface
77
    {
78 2
        $this->wormholeEntry = $wormholeEntry;
79 2
        if ($isEntry) {
80 1
            $this->waypoints->add($wormholeEntry->getSystemMap());
81 1
            $this->routeMode = RouteModeEnum::WORMHOLE_ENTRY;
82
        } else {
83 1
            $this->waypoints->add($wormholeEntry->getMap());
84 1
            $this->routeMode = RouteModeEnum::WORMHOLE_EXIT;
85
        }
86
87 2
        return $this;
88
    }
89
90 8
    #[Override]
91
    public function setDestinationViaCoordinates(Spacecraft $spacecraft, int $x, int $y): FlightRouteInterface
92
    {
93 8
        $start = $spacecraft->getLocation();
94 8
        $this->current = $start;
95 8
        $destination = $this->checkDestination->validate($spacecraft, $x, $y);
96
97 8
        if ($start !== $destination) {
98 7
            $this->waypoints = $this->loadWaypoints->load($start, $destination);
99 7
            $this->isTraversing = true;
100
        }
101
102 8
        return $this;
103
    }
104
105
    #[Override]
106
    public function getCurrentWaypoint(): Location
107
    {
108
        return $this->current;
109
    }
110
111 8
    #[Override]
112
    public function getNextWaypoint(): Location
113
    {
114 8
        if ($this->waypoints->isEmpty()) {
115 1
            throw new RuntimeException('isDestinationArrived has to be called beforehand');
116
        }
117
118 7
        return $this->waypoints->first();
119
    }
120
121 6
    private function stepForward(): void
122
    {
123 6
        $first =  $this->waypoints->first();
124
125 6
        if (!$first) {
126
            return;
127
        }
128
129 6
        $this->current = $first;
130 6
        $this->waypoints->removeElement($this->current);
131
    }
132
133 1
    #[Override]
134
    public function abortFlight(): void
135
    {
136 1
        $this->waypoints->clear();
137
    }
138
139 6
    #[Override]
140
    public function enterNextWaypoint(
141
        FlightCompany $flightCompany,
142
        MessageCollectionInterface $messages
143
    ): void {
144
145 6
        $wrappers = $flightCompany->getActiveMembers();
146
147
        // flight consequences
148 6
        $this->walkWrappers(
149 6
            $wrappers,
150 6
            function (SpacecraftWrapperInterface $wrapper) use ($messages): void {
151 6
                $this->walkConsequences($this->flightConsequences, $wrapper, $messages);
152 6
            }
153 6
        );
154
155
        // enter waypoint
156 6
        $this->walkWrappers(
157 6
            $wrappers,
158 6
            function (SpacecraftWrapperInterface $wrapper): void {
159 6
                $this->enterWaypoint->enterNextWaypoint(
160 6
                    $wrapper->get(),
161 6
                    $this->isTraversing,
162 6
                    $this->getNextWaypoint(),
163 6
                    $this->wormholeEntry
164 6
                );
165 6
            }
166 6
        );
167
168 6
        $this->effectHandling->addFlightInformationForActiveEffects($this->getNextWaypoint(), $messages);
169
170
        // post flight consequences
171 6
        $this->walkWrappers(
172 6
            $wrappers,
173 6
            function (SpacecraftWrapperInterface $wrapper) use ($messages): void {
174 6
                $this->walkConsequences($this->postFlightConsequences, $wrapper, $messages);
175 6
            }
176 6
        );
177
178 6
        $this->stepForward();
179
    }
180
181
    /** @param Collection<int, SpacecraftWrapperInterface> $wrappers */
182 6
    private function walkWrappers(Collection $wrappers, callable $func): void
183
    {
184 6
        foreach ($wrappers as $wrapper) {
185 6
            $func($wrapper);
186
        }
187
    }
188
189
    /**
190
     * @param array<string, FlightConsequenceInterface> $consequences
191
     */
192 6
    private function walkConsequences(
193
        array $consequences,
194
        ?SpacecraftWrapperInterface $wrapper,
195
        MessageCollectionInterface $messages
196
    ): void {
197
198 6
        if ($wrapper === null) {
199 6
            return;
200
        }
201
202 6
        array_walk(
203 6
            $consequences,
204 6
            fn(FlightConsequenceInterface $consequence) => $consequence->trigger($wrapper, $this, $messages)
205 6
        );
206
207 6
        $this->walkConsequences($consequences, $wrapper->getTractoredShipWrapper(), $messages);
208
    }
209
210 8
    #[Override]
211
    public function isDestinationArrived(): bool
212
    {
213 8
        return $this->waypoints->isEmpty();
214
    }
215
216 6
    #[Override]
217
    public function getRouteMode(): RouteModeEnum
218
    {
219 6
        return $this->routeMode;
220
    }
221
222
    #[Override]
223
    public function isTraversing(): bool
224
    {
225
        return $this->isTraversing;
226
    }
227
228
    #[Override]
229
    public function isImpulseDriveNeeded(): bool
230
    {
231
        $routeMode = $this->routeMode;
232
233
        if (
234
            $routeMode === RouteModeEnum::SYSTEM_ENTRY
235
            || $routeMode === RouteModeEnum::WORMHOLE_ENTRY
236
        ) {
237
            return true;
238
        }
239
240
        return $routeMode === RouteModeEnum::FLIGHT
241
            && $this->getNextWaypoint() instanceof StarSystemMap;
242
    }
243
244
    #[Override]
245
    public function isWarpDriveNeeded(): bool
246
    {
247
        $routeMode = $this->routeMode;
248
249
        if (
250
            $routeMode === RouteModeEnum::SYSTEM_EXIT
251
            || $routeMode === RouteModeEnum::TRANSWARP
252
        ) {
253
            return true;
254
        }
255
256
        return $routeMode === RouteModeEnum::FLIGHT
257
            && $this->getNextWaypoint() instanceof Map;
258
    }
259
260
    #[Override]
261
    public function isTranswarpCoilNeeded(): bool
262
    {
263
        return $this->routeMode === RouteModeEnum::TRANSWARP;
264
    }
265
266 2
    #[Override]
267
    public function hasSpecialDamageOnField(): bool
268
    {
269 2
        foreach ($this->waypoints as $waypoint) {
270 2
            if ($waypoint->getFieldType()->getSpecialDamage() > 0) {
271 1
                return true;
272
            }
273
        }
274
275 1
        return false;
276
    }
277
278 2
    #[Override]
279
    public function hasEffectOnRoute(FieldTypeEffectEnum $effect): bool
280
    {
281 2
        foreach ($this->waypoints as $waypoint) {
282 2
            if ($waypoint->getFieldType()->hasEffect($effect)) {
283 1
                return true;
284
            }
285
        }
286
287 1
        return false;
288
    }
289
290 2
    #[Override]
291
    public function isDestinationInAdminRegion(array $regionIds): bool
292
    {
293 2
        $destination = $this->waypoints->last();
294
295 2
        return $destination instanceof Map
296 2
            && in_array($destination->getAdminRegionId(), $regionIds);
297
    }
298
299 4
    #[Override]
300
    public function isDestinationAtTradepost(): bool
301
    {
302 4
        $destination = $this->waypoints->last();
303
304 4
        return $destination instanceof Map
305 4
            && $destination->getSpacecrafts()->exists(fn(int $key, Spacecraft $spacecraft): bool => $spacecraft instanceof Station && $spacecraft->getTradePost() !== null);
306
    }
307
}
308