Completed
Branch master (597d40)
by Douglas
02:41 queued 01:20
created

AbstractSymmetricSpace::isAGoodPlace()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 1
crap 1
1
<?php
2
3
/**
4
 * (c) 2018 Douglas Reith.
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
declare(strict_types=1);
10
11
namespace Reith\ToyRobot\Domain\Space;
12
13
use Reith\ToyRobot\Domain\Space\Exception\PlaceDimensionsDoNotMatchSpaceException;
14
use Reith\ToyRobot\Domain\Robot\Robot;
15
use Reith\ToyRobot\Domain\Robot\Place;
16
17
abstract class AbstractSymmetricSpace implements SpaceInterface
18
{
19
    private $dimensions;
20
21
    private $boundarySize;
22
23
    private $boundaryCondition;
24
25
    /**
26
     * @param int $dimensions
27
     * @param int $boundarySize
28
     */
29 9
    protected function __construct(int $dimensions, int $boundarySize)
30
    {
31 9
        $this->dimensions = $dimensions;
32 9
        $this->boundarySize = $boundarySize;
33 9
        $this->boundaryCondition = BoundaryCondition::create($boundarySize);
34 9
    }
35
36
    /**
37
     * @return Place
38
     */
39 8
    protected function defaultPlacement(): Place
40
    {
41
        // Create a place with position [0,0,..n]
42 8
        return Place::create(array_fill(0, $this->dimensions, 0));
43
    }
44
45
    /**
46
     * @param ?Place $place
0 ignored issues
show
Documentation introduced by
The doc-type ?Place could not be parsed: Unknown type name "?Place" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
47
     *
48
     * @return Robot
49
     */
50 5
    public function placeRobot(?Place $place = null): Robot
51
    {
52 5
        $place = $place ?: $this->defaultPlacement();
53
54 5
        if ($this->isAGoodPlace($place)) {
55
            // A robot is in a space with a place
56 5
            return Robot::create($this, $place);
57
        }
58
    }
59
60
    /**
61
     * @param Place $place
62
     *
63
     * @return bool
64
     *
65
     * @throws \Reith\ToyRobot\Domain\Space\Exception\BoundaryTestException
66
     */
67 5
    public function isAGoodPlace(Place $place): bool
68
    {
69 5
        $condition = $this->boundaryCondition;
70
71 5
        $place->map(function ($value) use ($condition) {
72 5
            $condition->test($value);
73 5
        });
74
75 5
        return true;
76
    }
77
78
    /**
79
     * @param Place      $from
80
     * @param Place|null $to   If not supplied, origin is $from
81
     *
82
     * @throws PlaceDimensionsDoNotMatchSpaceException
83
     * @throws \Reith\ToyRobot\Domain\Space\Exception\BoundaryTestException
84
     */
85 7
    public function move(Place $from, ?Place $to = null): Place
86
    {
87 7
        if (!$to) {
88 3
            $to = $from;
89
            // Origin
90 3
            $from = $this->defaultPlacement();
91
        }
92
93
        // Ensure the movement is of the same dimension as the
94
        // space
95 7
        $this->validateDimensionality($from, $to);
96
97
        // Add the vectors to get the new position
98 4
        $final = Place::createFromVector($from->add($to));
99
100 4
        if ($this->isAGoodPlace($final)) {
101 2
            return $final;
102
        }
103
    }
104
105
    /**
106
     * For all the places passed, ensure they are of the same
107
     * dimensionality.
108
     *
109
     * @param Place $place ... Places to check
0 ignored issues
show
Documentation introduced by
There is no parameter named $place. Did you maybe mean $places?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
110
     *
111
     * @throws PlaceDimensionsDoNotMatchSpaceException
112
     */
113 7
    private function validateDimensionality(Place ...$places): void
114
    {
115 7
        $spaceDimensions = $this->dimensions;
116
117 7
        array_walk(
118 7
            $places,
119 7
            function (Place $place) use ($spaceDimensions) {
120 7
                $errorMsg = sprintf(
121 7
                    'Place has [%d] dimensions but space has [%d] dimensions',
122 7
                    $place->getN(),
123 7
                    $spaceDimensions
124
                );
125
126 7
                if ($place->getN() !== $spaceDimensions) {
127 3
                    throw new PlaceDimensionsDoNotMatchSpaceException(
128 3
                        $errorMsg
129
                    );
130
                }
131 7
            }
132
        );
133 4
    }
134
}
135