Passed
Push — master ( 1fd7d6...01abcf )
by Witali
02:28
created

Astar::enableDiagonal()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
namespace BlackScorp\Astar;
3
4
use BlackScorp\Astar\Heuristic\Manhattan;
5
6
class Astar
7
{
8
9
    private $diagonal = false;
10
    private $blocked = array();
11
    /**
12
     * @var HeuristicInterface
13
     */
14
    private $heuristic = null;
15
    private $grid = null;
16
17
18 1
    public function blocked(array $types)
19
    {
20 1
        $this->blocked = $types;
21 1
    }
22
23 1
    public function enableDiagonal()
24
    {
25 1
        $this->diagonal = true;
26 1
    }
27
28 5
    public function __construct(Grid $grid)
29
    {
30 5
        $this->grid = $grid;
31 5
    }
32
33 5
    public function setHeuristic(HeuristicInterface $heuristic)
34
    {
35 5
        $this->heuristic = $heuristic;
36 5
    }
37
38 5
    public function search(Node $start, Node $end)
39
    {
40
41 5
        if (!$this->heuristic) {
42 3
            $this->setHeuristic(new Manhattan());
43 3
        }
44
45 5
        $heap = new ScoreHeap();
46 5
        $heap->insert($start);
47
48 5
        $current = $this->fillHeap($heap, $start, $end);
49 5
        if ($current !== $end) {
50 1
            return [];
51
        }
52 4
        return $this->getReversedPath($current);
53
54
    }
55
56
    /**
57
     * @param Node $end
58
     * @param $heap
59
     * @param $current
60
     * @return Node
61
     */
62 5
    private function fillHeap(\SplHeap $heap, Node $current, Node $end)
63
    {
64 5
        while ($heap->valid() && $current !== $end) {
65
            /**
66
             * @var Node $current
67
             */
68 5
            $current = $heap->extract();
69
70 5
            $current->close();
71 5
            $neighbors = $this->grid->getNeighbors($current, $this->diagonal);
72 5
            foreach ($neighbors as $neighbor) {
73 5
                if ($neighbor->isClosed() || in_array($neighbor->getCosts(), $this->blocked)) {
74 5
                    continue;
75
                }
76 5
                $score = $current->getScore() + $neighbor->getCosts();
77 5
                $visited = $neighbor->isVisited();
78 5
                if (!$visited || $score < $neighbor->getScore()) {
79 5
                    $neighbor->visit();
80 5
                    $neighbor->setParent($current);
81 5
                    $neighbor->setGuessedScore($this->heuristic->compare($neighbor, $end));
82 5
                    $neighbor->setScore($score);
83 5
                    $neighbor->setTotalScore($neighbor->getScore() + $neighbor->getGuessedScore());
84 5
                    if (!$visited) {
85 5
                        $heap->insert($neighbor);
86 5
                    }
87 5
                }
88
89 5
            }
90 5
        }
91 5
        return $current;
92
    }
93
94
    /**
95
     * @param Node $current
96
     * @return array
97
     */
98 4
    private function getReversedPath(Node $current)
99
    {
100 4
        $result = [];
101 4
        while ($current->getParent()) {
102 4
            $result[] = $current;
103 4
            $current = $current->getParent();
104 4
        }
105 4
        return array_reverse($result);
106
    }
107
}