Passed
Push — master ( 979da0...21dcf7 )
by Jesse
01:38
created

DynamicPathfinder::singlePathfinder()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 16
rs 9.6111
c 0
b 0
f 0
cc 5
nc 3
nop 3
1
<?php declare(strict_types=1);
2
3
namespace Stratadox\Pathfinder;
4
5
use Stratadox\Pathfinder\Distance\Euclidean;
6
use Stratadox\Pathfinder\Estimate\Estimate;
7
use Stratadox\Pathfinder\Estimate\Safely;
8
use Stratadox\Pathfinder\Graph\GeometricView;
9
10
final class DynamicPathfinder implements Pathfinder
11
{
12
    private $singlePath;
13
    private $multiPath;
14
15
    private function __construct(
16
        SinglePathfinder $singlePath,
17
        MultiPathfinder $multiPath
18
    ) {
19
        $this->singlePath = $singlePath;
20
        $this->multiPath = $multiPath;
21
    }
22
23
    public static function operatingIn(Network $environment): Pathfinder
24
    {
25
        return self::produceFor($environment, null);
26
    }
27
28
    public static function withHeuristic(Heuristic $heuristic): Pathfinder
29
    {
30
        return self::produceFor($heuristic->environment(), $heuristic);
31
    }
32
33
    private static function produceFor(
34
        Network $theWorld,
35
        ?Heuristic $heuristic
36
    ): Pathfinder {
37
        $negativeEdgeCosts = $theWorld->hasNegativeEdgeCosts();
38
        return new self(
39
            self::singlePathfinder($theWorld, $heuristic, $negativeEdgeCosts),
40
            $negativeEdgeCosts ?
41
                BellmanFordPathfinder::operatingIn($theWorld) :
42
                MultiDijkstraPathfinder::operatingIn($theWorld)
43
        );
44
    }
45
46
    private static function singlePathfinder(
47
        Network $theWorld,
48
        ?Heuristic $heuristic,
49
        bool $negativeEdgeCosts
50
    ): SinglePathfinder {
51
        if ($theWorld instanceof Environment) {
52
            return AStarPathfinder::withHeuristic($heuristic ?: Safely::apply(
53
                Estimate::costAs(Euclidean::distance(), $theWorld)
54
            ));
55
        }
56
        if ($negativeEdgeCosts) {
57
            return AStarPathfinder::withHeuristic($heuristic ?: Safely::apply(
58
                Estimate::costAs(Euclidean::distance(), GeometricView::of($theWorld))
59
            ));
60
        }
61
        return SingleDijkstraPathfinder::operatingIn($theWorld);
62
    }
63
64
    public function from(string $start): array
65
    {
66
        return $this->multiPath->from($start);
67
    }
68
69
    public function between(string $start, string $goal): array
70
    {
71
        return $this->singlePath->between($start, $goal);
72
    }
73
}
74