Completed
Push — new-implementation ( 0cc7b9 )
by Jose
11:19
created

DomainLogic::calculateRealCost()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
cc 2
nc 2
nop 2
crap 2
1
<?php
2
3
namespace JMGQ\AStar\Example\Terrain;
4
5
use JMGQ\AStar\DomainLogicInterface;
6
7
class DomainLogic implements DomainLogicInterface
8
{
9
    private TerrainCost $terrainCost;
10
    /** @var Position[][] */
11
    private array $positions;
12
13 15
    public function __construct(TerrainCost $terrainCost)
14
    {
15 15
        $this->terrainCost = $terrainCost;
16
17
        // We store all the Position objects in a matrix for efficiency, so that we don't need to create new Position
18
        // instances every time we call "getAdjacentNodes". If we created new positions with every call, the algorithm
19
        // would still work correctly but it would be a bit slower.
20 15
        $this->positions = $this->generatePositions($terrainCost);
21 15
    }
22
23
    /**
24
     * @param Position $node
25
     * @return Position[]
26
     */
27 10
    public function getAdjacentNodes(mixed $node): iterable
28
    {
29 10
        $adjacentNodes = [];
30
31 10
        if ($node->getRow() === 0) {
32 8
            $startingRow = 0;
33
        } else {
34 8
            $startingRow = $node->getRow() - 1;
35
        }
36
37 10
        if ($node->getRow() === $this->terrainCost->getTotalRows() - 1) {
38 5
            $endingRow = $node->getRow();
39
        } else {
40 9
            $endingRow = $node->getRow() + 1;
41
        }
42
43 10
        if ($node->getColumn() === 0) {
44 8
            $startingColumn = 0;
45
        } else {
46 8
            $startingColumn = $node->getColumn() - 1;
47
        }
48
49 10
        if ($node->getColumn() === $this->terrainCost->getTotalColumns() - 1) {
50 4
            $endingColumn = $node->getColumn();
51
        } else {
52 9
            $endingColumn = $node->getColumn() + 1;
53
        }
54
55 10
        for ($row = $startingRow; $row <= $endingRow; $row++) {
56 10
            for ($column = $startingColumn; $column <= $endingColumn; $column++) {
57 10
                $adjacentNode = $this->positions[$row][$column];
58
59 10
                if (!$node->isEqualTo($adjacentNode)) {
60 10
                    $adjacentNodes[] = $adjacentNode;
61
                }
62
            }
63
        }
64
65 10
        return $adjacentNodes;
66
    }
67
68
    /**
69
     * @param Position $node
70
     * @param Position $adjacent
71
     * @return float|int
72
     */
73 8
    public function calculateRealCost(mixed $node, mixed $adjacent): float | int
74
    {
75 8
        if ($node->isAdjacentTo($adjacent)) {
76 7
            return $this->terrainCost->getCost($adjacent->getRow(), $adjacent->getColumn());
77
        }
78
79 1
        return TerrainCost::INFINITE;
80
    }
81
82
    /**
83
     * @param Position $fromNode
84
     * @param Position $toNode
85
     * @return float|int
86
     */
87 8
    public function calculateEstimatedCost(mixed $fromNode, mixed $toNode): float | int
88
    {
89 8
        return $this->euclideanDistance($fromNode, $toNode);
90
    }
91
92 8
    private function euclideanDistance(Position $a, Position $b): float
93
    {
94 8
        $rowFactor = ($a->getRow() - $b->getRow()) ** 2;
95 8
        $columnFactor = ($a->getColumn() - $b->getColumn()) ** 2;
96
97 8
        return sqrt($rowFactor + $columnFactor);
98
    }
99
100
    /**
101
     * @param TerrainCost $terrainCost
102
     * @return Position[][]
103
     */
104 15
    private function generatePositions(TerrainCost $terrainCost): array
105
    {
106 15
        $positions = [];
107
108 15
        for ($row = 0; $row < $terrainCost->getTotalRows(); $row++) {
109 15
            for ($column = 0; $column < $terrainCost->getTotalColumns(); $column++) {
110 15
                $positions[$row][$column] = new Position($row, $column);
111
            }
112
        }
113
114 15
        return $positions;
115
    }
116
}
117