Completed
Push — master ( 8184b0...a4b4a5 )
by Douglas
02:13
created

Robot::moveEastward()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 0
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\Robot;
12
13
use MathPHP\LinearAlgebra\Vector;
14
use Assert\Assert;
15
use Assert\Assertion;
16
use Reith\ToyRobot\Domain\Space\SpaceInterface;
17
use Reith\ToyRobot\Domain\Robot\Exception\NotPlacedInSpaceException;
18
19
class Robot
20
{
21
    /**
22
     * Purchased by Rupert, then tanked :).
23
     *
24
     * @var SpaceInterface
25
     */
26
    private $mySpace;
27
28
    private $position;
29
30
    private $facingDirection;
31
32 10
    private function __construct(
33
        SpaceInterface $space,
34
        Vector $position,
35
        Direction $facingDirection
36
    ) {
37 10
        $this->mySpace = $space;
38 10
        $this->position = $position;
39 10
        $this->facingDirection = $facingDirection;
40 10
    }
41
42
    /**
43
     * @param SpaceInterface $space
44
     * @param Vector         $position
45
     * @param string|null    $facingDirection
46
     *
47
     * @return Robot
48
     *
49
     * @throws Assert\AssertionFailedException
50
     */
51 11
    public static function create(
52
        SpaceInterface $space,
53
        Vector $position,
54
        ?string $facingDirection = 'E'
55
    ): Robot {
56
57 11
        $facingDirection = $facingDirection ?: 'E';
58
59 11
        return new static(
60 11
            $space,
61 11
            $position,
62 11
            new Direction($facingDirection)
63
        );
64
    }
65
66
    /**
67
     * @return Robot
68
     */
69
    public function move(): Robot
70
    {
71
        $this->validateCanMove();
72
73
        $this->position = $this->mySpace->move(
74
            $this->position,
75
            $this->facingDirection->getDirectionAsVector()
76
        );
77
78
        return $this;
79
    }
80
81
    /**
82
     * @return Robot
83
     */
84
    public function left(): Robot
85
    {
86
        $this->facingDirection->rotateLeft();
87
88
        return $this;
89
    }
90
91
    /**
92
     * @return Robot
93
     */
94
    public function right(): Robot
95
    {
96
        $this->facingDirection->rotateRight();
97
98
        return $this;
99
    }
100
101
    /**
102
     * @return Robot
103
     */
104 2
    public function moveNorthward(): Robot
105
    {
106 2
        $this->validateCanMove();
107
108 2
        $this->position = $this->mySpace->move(
109 2
            $this->position,
110 2
            $this->facingDirection->northward()
111
        );
112
113 2
        return $this;
114
    }
115
116
    /**
117
     * @return Robot
118
     */
119 1
    public function moveEastward(): Robot
120
    {
121 1
        $this->validateCanMove();
122
123 1
        $this->position = $this->mySpace->move(
124 1
            $this->position,
125 1
            $this->facingDirection->eastward()
126
        );
127
128 1
        return $this;
129
    }
130
131
    /**
132
     * @return Robot
133
     */
134 2
    public function moveSouthward(): Robot
135
    {
136 2
        $this->validateCanMove();
137
138 2
        $this->position = $this->mySpace->move(
139 2
            $this->position,
140 2
            $this->facingDirection->southward()
141
        );
142
143 1
        return $this;
144
    }
145
146
    /**
147
     * @return Robot
148
     */
149 2
    public function moveWestward(): Robot
150
    {
151 2
        $this->validateCanMove();
152
153 2
        $this->position = $this->mySpace->move(
154 2
            $this->position,
155 2
            $this->facingDirection->westward()
156
        );
157
158 1
        return $this;
159
    }
160
161
    /**
162
     * @return Vector
163
     */
164 1
    public function getPosition(): Vector
165
    {
166 1
        return $this->position;
167
    }
168
169
    /**
170
     * @return string In the form 'X,Y,F'
171
     */
172 5
    public function getReportAsString(): string
173
    {
174 5
        $positionAsString = implode(',', $this->position->getVector());
175
176 5
        return $positionAsString . ',' . $this->getFacingDirectionAsString();
177
    }
178
179
    /**
180
     * @return string
181
     */
182 5
    private function getFacingDirectionAsString(): string
183
    {
184 5
        return $this->facingDirection->getDirectionAsString();
185
    }
186
187
    /**
188
     * validateCanMove.
189
     *
190
     * The robot requires a space during construction, however,
191
     * this is extra precautionary in case the space is removed
192
     *
193
     * @throws NotPlacedInSpaceException
194
     */
195 4
    private function validateCanMove(): void
196
    {
197 4
        if (!$this->mySpace) {
198
            throw new NotPlacedInSpaceException(
199
                'I cannot move until placed in space'
200
            );
201
        }
202 4
    }
203
}
204