AdaptedEnvironment   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 47
dl 0
loc 110
rs 10
c 0
b 0
f 0
wmc 23

10 Methods

Rating   Name   Duplication   Size   Complexity  
A from() 0 3 1
A hasNegativeEdgeCosts() 0 9 3
A has() 0 3 1
A movementCostBetween() 0 17 4
A neighboursOf() 0 13 3
A positionOf() 0 15 4
A areNeighbours() 0 15 4
A __construct() 0 4 1
A from3D() 0 3 1
A all() 0 3 1
1
<?php declare(strict_types=1);
2
3
namespace Stratadox\GraphpFinder;
4
5
use function array_key_exists;
6
use Fhaculty\Graph\Edge\Base as Edge;
7
use Fhaculty\Graph\Exception\OutOfBoundsException;
8
use Fhaculty\Graph\Graph;
9
use InvalidArgumentException;
10
use Stratadox\Pathfinder\Environment;
11
use Stratadox\Pathfinder\Graph\At;
12
use Stratadox\Pathfinder\Graph\Ids;
13
use Stratadox\Pathfinder\Labels;
14
use Stratadox\Pathfinder\Position;
15
16
final class AdaptedEnvironment implements Environment
17
{
18
    private $graph;
19
    private $coordinate;
20
    private $position = [];
21
22
    private function __construct(Graph $graph, array $coordinateOffset)
23
    {
24
        $this->graph = $graph;
25
        $this->coordinate = $coordinateOffset;
26
    }
27
28
    public static function from(Graph $graph): Environment
29
    {
30
        return new self($graph, ['x', 'y']);
31
    }
32
33
    public static function from3D(Graph $graph): Environment
34
    {
35
        return new self($graph, ['x', 'y', 'z']);
36
    }
37
38
    public function all(): Labels
39
    {
40
        return Ids::consistingOf(...$this->graph->getVertices()->getIds());
41
    }
42
43
    public function neighboursOf(string $node): Labels
44
    {
45
        $neighbours = [];
46
        try {
47
            $start = $this->graph->getVertices()->getVertexId($node);
48
            /** @var Edge $edge */
49
            foreach ($start->getEdgesOut() as $edge) {
50
                $neighbours[] = (string) $edge->getVertexToFrom($start)->getId();
51
            }
52
        } catch (OutOfBoundsException $e) {
53
            // no node, no neighbours
54
        }
55
        return Ids::consistingOf(...$neighbours);
56
    }
57
58
    public function areNeighbours(string $source, string $neighbour): bool
59
    {
60
        try {
61
            $start = $this->graph->getVertices()->getVertexId($source);
62
        } catch (OutOfBoundsException $e) {
63
            // no source node, no neighbours
64
            return false;
65
        }
66
        /** @var Edge $edge */
67
        foreach ($start->getEdgesOut() as $edge) {
68
            if ((string) $edge->getVertexToFrom($start)->getId() === $neighbour) {
69
                return true;
70
            }
71
        }
72
        return false;
73
    }
74
75
    public function has(string $node): bool
76
    {
77
        return $this->graph->hasVertex($node);
78
    }
79
80
    public function movementCostBetween(
81
        string $source,
82
        string $neighbour
83
    ): float {
84
        try {
85
            $start = $this->graph->getVertices()->getVertexId($source);
86
        } catch (OutOfBoundsException $e) {
87
            throw new InvalidArgumentException("Vertex $source not found.");
88
        }
89
        /** @var Edge $edge */
90
        foreach ($start->getEdgesOut() as $edge) {
91
            if ((string) $edge->getVertexToFrom($start)->getId() === $neighbour) {
92
                return (float) $edge->getWeight();
93
            }
94
        }
95
        throw new InvalidArgumentException(
96
            "Vertices $source and $neighbour are not neighbours."
97
        );
98
    }
99
100
    public function hasNegativeEdgeCosts(): bool
101
    {
102
        /** @var Edge $edge */
103
        foreach ($this->graph->getEdges() as $edge) {
104
            if ($edge->getWeight() < 0) {
105
                return true;
106
            }
107
        }
108
        return false;
109
    }
110
111
    public function positionOf(string $node): Position
112
    {
113
        if (!array_key_exists($node, $this->position)) {
114
            try {
115
                $vertex = $this->graph->getVertices()->getVertexId($node);
116
            } catch (OutOfBoundsException $e) {
117
                throw new InvalidArgumentException($e->getMessage(), 0, $e);
118
            }
119
            $coordinates = [];
120
            foreach ($this->coordinate as $key) {
121
                $coordinates[] = $vertex->getAttribute($key, 0);
122
            }
123
            $this->position[$node] = At::position(...$coordinates);
124
        }
125
        return $this->position[$node];
126
    }
127
}
128