Passed
Push — master ( 130a84...94bf46 )
by Jose
05:30 queued 02:40
created

Algorithm::run()   B

Complexity

Conditions 8
Paths 2

Size

Total Lines 49
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 8

Importance

Changes 6
Bugs 0 Features 0
Metric Value
eloc 25
c 6
b 0
f 0
dl 0
loc 49
ccs 26
cts 26
cp 1
rs 8.4444
cc 8
nc 2
nop 2
crap 8
1
<?php
2
3
namespace JMGQ\AStar;
4
5
abstract class Algorithm
6
{
7
    private $openList;
8
    private $closedList;
9
10 21
    public function __construct()
11
    {
12 21
        $this->openList = new NodeList();
13 21
        $this->closedList = new NodeList();
14 21
    }
15
16
    /**
17
     * @param Node $node
18
     * @return Node[]
19
     */
20
    abstract public function generateAdjacentNodes(Node $node);
21
22
    /**
23
     * @param Node $node
24
     * @param Node $adjacent
25
     * @return integer | float
26
     */
27
    abstract public function calculateRealCost(Node $node, Node $adjacent);
28
29
    /**
30
     * @param Node $start
31
     * @param Node $end
32
     * @return integer | float
33
     */
34
    abstract public function calculateEstimatedCost(Node $start, Node $end);
35
36
    /**
37
     * @return NodeList
38
     */
39 17
    public function getOpenList()
40
    {
41 17
        return $this->openList;
42
    }
43
44
    /**
45
     * @return NodeList
46
     */
47 17
    public function getClosedList()
48
    {
49 17
        return $this->closedList;
50
    }
51
52
    /**
53
     * Sets the algorithm to its initial state
54
     */
55 16
    public function clear()
56
    {
57 16
        $this->getOpenList()->clear();
58 16
        $this->getClosedList()->clear();
59 16
    }
60
61
    /**
62
     * @param Node $start
63
     * @param Node $goal
64
     * @return Node[]
65
     */
66 15
    public function run(Node $start, Node $goal)
67
    {
68 15
        $path = array();
69
70 15
        $this->clear();
71
72 15
        $start->setG(0);
73 15
        $start->setH($this->calculateEstimatedCost($start, $goal));
74
75 15
        $this->getOpenList()->add($start);
76
77 15
        while (!$this->getOpenList()->isEmpty()) {
78 15
            $currentNode = $this->getOpenList()->extractBest();
79
80 15
            $this->getClosedList()->add($currentNode);
0 ignored issues
show
Bug introduced by
It seems like $currentNode can also be of type null; however, parameter $node of JMGQ\AStar\NodeList::add() does only seem to accept JMGQ\AStar\Node, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

80
            $this->getClosedList()->add(/** @scrutinizer ignore-type */ $currentNode);
Loading history...
81
82 15
            if ($currentNode->getID() === $goal->getID()) {
83 13
                $path = $this->generatePathFromStartNodeTo($currentNode);
0 ignored issues
show
Bug introduced by
It seems like $currentNode can also be of type null; however, parameter $node of JMGQ\AStar\Algorithm::ge...tePathFromStartNodeTo() does only seem to accept JMGQ\AStar\Node, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

83
                $path = $this->generatePathFromStartNodeTo(/** @scrutinizer ignore-type */ $currentNode);
Loading history...
84 13
                break;
85
            }
86
87 12
            $successors = $this->computeAdjacentNodes($currentNode, $goal);
0 ignored issues
show
Bug introduced by
It seems like $currentNode can also be of type null; however, parameter $node of JMGQ\AStar\Algorithm::computeAdjacentNodes() does only seem to accept JMGQ\AStar\Node, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

87
            $successors = $this->computeAdjacentNodes(/** @scrutinizer ignore-type */ $currentNode, $goal);
Loading history...
88
89 12
            foreach ($successors as $successor) {
90 10
                if ($this->getOpenList()->contains($successor)) {
91 7
                    $successorInOpenList = $this->getOpenList()->get($successor);
92
93 7
                    if ($successor->getG() >= $successorInOpenList->getG()) {
94 6
                        continue;
95
                    }
96
                }
97
98 10
                if ($this->getClosedList()->contains($successor)) {
99 7
                    $successorInClosedList = $this->getClosedList()->get($successor);
100
101 7
                    if ($successor->getG() >= $successorInClosedList->getG()) {
102 7
                        continue;
103
                    }
104
                }
105
106 10
                $successor->setParent($currentNode);
0 ignored issues
show
Bug introduced by
It seems like $currentNode can also be of type null; however, parameter $parent of JMGQ\AStar\Node::setParent() does only seem to accept JMGQ\AStar\Node, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

106
                $successor->setParent(/** @scrutinizer ignore-type */ $currentNode);
Loading history...
107
108 10
                $this->getClosedList()->remove($successor);
109
110 10
                $this->getOpenList()->add($successor);
111
            }
112
        }
113
114 15
        return $path;
115
    }
116
117 13
    private function generatePathFromStartNodeTo(Node $node)
118
    {
119 13
        $path = array();
120
121 13
        $currentNode = $node;
122
123 13
        while ($currentNode !== null) {
124 13
            array_unshift($path, $currentNode);
125
126 13
            $currentNode = $currentNode->getParent();
127
        }
128
129 13
        return $path;
130
    }
131
132 12
    private function computeAdjacentNodes(Node $node, Node $goal)
133
    {
134 12
        $nodes = $this->generateAdjacentNodes($node);
135
136 12
        foreach ($nodes as $adjacentNode) {
137 10
            $adjacentNode->setG($node->getG() + $this->calculateRealCost($node, $adjacentNode));
138 10
            $adjacentNode->setH($this->calculateEstimatedCost($adjacentNode, $goal));
139
        }
140
141 12
        return $nodes;
142
    }
143
}
144