loco_bot 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/loco_bot/robot/direction/east.rb +4 -4
- data/lib/loco_bot/robot/direction/north.rb +4 -4
- data/lib/loco_bot/robot/direction/south.rb +4 -4
- data/lib/loco_bot/robot/direction/west.rb +4 -4
- data/lib/loco_bot/robot.rb +20 -12
- data/lib/loco_bot/table.rb +16 -15
- data/lib/loco_bot/version.rb +1 -1
- data/spec/loco_bot/cli_spec.rb +11 -0
- data/spec/loco_bot/robot/direction/east_spec.rb +2 -2
- data/spec/loco_bot/robot/direction/north_spec.rb +2 -2
- data/spec/loco_bot/robot/direction/south_spec.rb +2 -2
- data/spec/loco_bot/robot/direction/west_spec.rb +2 -2
- data/spec/loco_bot/robot_spec.rb +110 -7
- data/spec/loco_bot/table_spec.rb +2 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5bcc03fc9e471fbe3836c3d97c8f4b2c1781c3b4
|
4
|
+
data.tar.gz: 3422b70bf9684df8760c86aee333509d3c3ea18f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6e1f94945da2600e5d87060c1d86a38609e38b762c2b270a2f603306b7bd762aa93883a1b6627d82a9a545d6f5a07471337a266bb1af7b4b11c1141f5a8a4d5
|
7
|
+
data.tar.gz: 1a543d54eb4229da4fe29d915b1f4f9251d31e9d9b56f76d34807d611193cfcec09c9cc3e2b1f60338d934224669109cf8ab08bea020c7c78acda7ef30f5b053
|
@@ -22,13 +22,13 @@ module LocoBot
|
|
22
22
|
'EAST'
|
23
23
|
end
|
24
24
|
|
25
|
-
#
|
25
|
+
# The Direction is applied to the given coordinates and returns vectorial coordinates in a Hash.
|
26
26
|
# @param x [Integer] the x-axis coordinate
|
27
27
|
# @param y [Integer] the y-axis coordinate
|
28
|
-
# @return [Hash] the
|
28
|
+
# @return [Hash] the vectorial x and y coordinates
|
29
29
|
# @example
|
30
|
-
# Direction::East.
|
31
|
-
def self.
|
30
|
+
# Direction::East.vector(1, 2) # => {x: 2, y: 2}
|
31
|
+
def self.vector(x, y)
|
32
32
|
{ x: x + 1, y: y }
|
33
33
|
end
|
34
34
|
end
|
@@ -22,13 +22,13 @@ module LocoBot
|
|
22
22
|
'NORTH'
|
23
23
|
end
|
24
24
|
|
25
|
-
#
|
25
|
+
# The Direction is applied to the given coordinates and returns vectorial coordinates in a Hash.
|
26
26
|
# @param x [Integer] the x-axis coordinate
|
27
27
|
# @param y [Integer] the y-axis coordinate
|
28
|
-
# @return [Hash] the
|
28
|
+
# @return [Hash] the vectorial x and y coordinates
|
29
29
|
# @example
|
30
|
-
# Direction::North.
|
31
|
-
def self.
|
30
|
+
# Direction::North.vector(1, 2) # => {x: 1, y: 3}
|
31
|
+
def self.vector(x, y)
|
32
32
|
{ x: x, y: y + 1 }
|
33
33
|
end
|
34
34
|
end
|
@@ -22,13 +22,13 @@ module LocoBot
|
|
22
22
|
'SOUTH'
|
23
23
|
end
|
24
24
|
|
25
|
-
#
|
25
|
+
# The Direction is applied to the given coordinates and returns vectorial coordinates in a Hash.
|
26
26
|
# @param x [Integer] the x-axis coordinate
|
27
27
|
# @param y [Integer] the y-axis coordinate
|
28
|
-
# @return [Hash] the
|
28
|
+
# @return [Hash] the vectorial x and y coordinates
|
29
29
|
# @example
|
30
|
-
# Direction::South.
|
31
|
-
def self.
|
30
|
+
# Direction::South.vector(1, 2) # => {x: 1, y: 1}
|
31
|
+
def self.vector(x, y)
|
32
32
|
{ x: x, y: y - 1 }
|
33
33
|
end
|
34
34
|
end
|
@@ -22,13 +22,13 @@ module LocoBot
|
|
22
22
|
'WEST'
|
23
23
|
end
|
24
24
|
|
25
|
-
#
|
25
|
+
# The Direction is applied to the given coordinates and returns vectorial coordinates in a Hash.
|
26
26
|
# @param x [Integer] the x-axis coordinate
|
27
27
|
# @param y [Integer] the y-axis coordinate
|
28
|
-
# @return [Hash] the
|
28
|
+
# @return [Hash] the vectorial x and y coordinates
|
29
29
|
# @example
|
30
|
-
# Direction::West.
|
31
|
-
def self.
|
30
|
+
# Direction::West.vector(1, 2) # => {x: 0, y: 2}
|
31
|
+
def self.vector(x, y)
|
32
32
|
{ x: x - 1, y: y }
|
33
33
|
end
|
34
34
|
end
|
data/lib/loco_bot/robot.rb
CHANGED
@@ -4,21 +4,21 @@ module LocoBot
|
|
4
4
|
# Representation of a robot, placeable on tables.
|
5
5
|
class Robot
|
6
6
|
|
7
|
-
# @!attribute [
|
7
|
+
# @!attribute [r] table
|
8
8
|
# @return [Table] the Table the Robot is currently placed on
|
9
|
-
|
9
|
+
attr_reader :table
|
10
10
|
|
11
|
-
# @!attribute [
|
11
|
+
# @!attribute [r] x
|
12
12
|
# @return [Integer] the x-axis coordinate the Robot is currently at on the Table
|
13
|
-
|
13
|
+
attr_reader :x
|
14
14
|
|
15
|
-
# @!attribute [
|
15
|
+
# @!attribute [r] y
|
16
16
|
# @return [Integer] the y-axis coordinate the Robot is currently at on the Table
|
17
|
-
|
17
|
+
attr_reader :y
|
18
18
|
|
19
|
-
# @!attribute [
|
19
|
+
# @!attribute [r] direction
|
20
20
|
# @return [Direction] the Direction the Robot is currently facing on the Table
|
21
|
-
|
21
|
+
attr_reader :direction
|
22
22
|
|
23
23
|
# Places the Robot on the given Table at the given coordinates, facing the given Direction.
|
24
24
|
# If the Robot was previously on another Table, it is removed from it before being placed on the given.
|
@@ -31,7 +31,7 @@ module LocoBot
|
|
31
31
|
table.place_robot(self, x, y, direction)
|
32
32
|
end
|
33
33
|
|
34
|
-
# Removes the Robot its current Table. Position attributes of the Robot are set to nil.
|
34
|
+
# Removes the Robot from its current Table. Position attributes of the Robot are set to nil.
|
35
35
|
# @return [Boolean] true if removing was successful, false otherwise.
|
36
36
|
def remove
|
37
37
|
return false if table.nil?
|
@@ -42,7 +42,7 @@ module LocoBot
|
|
42
42
|
# Moves the robot one unit forward in the direction it is currently facing.
|
43
43
|
# @return [Boolean] true if moving was successful, false otherwise.
|
44
44
|
def move
|
45
|
-
return false
|
45
|
+
return false unless next_position_valid?
|
46
46
|
|
47
47
|
@x = next_position[:x]
|
48
48
|
@y = next_position[:y]
|
@@ -92,11 +92,19 @@ module LocoBot
|
|
92
92
|
# @return [Hash] the next x and y coordinates of the Robot.
|
93
93
|
# @example
|
94
94
|
# robot.place(1, 2, Direction::West)
|
95
|
-
# robot.
|
95
|
+
# robot.next_position # => {x: 0, y: 2}
|
96
96
|
def next_position
|
97
97
|
return {} if table.nil?
|
98
98
|
|
99
|
-
direction.
|
99
|
+
direction.vector(x, y)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Determines if the next position position of the Robot is valid according to its Table.
|
103
|
+
# @return [Boolean] true if the position is valid, false otherwise.
|
104
|
+
def next_position_valid?
|
105
|
+
return false if table.nil?
|
106
|
+
|
107
|
+
table.position_valid?(next_position[:x], next_position[:y])
|
100
108
|
end
|
101
109
|
end
|
102
110
|
end
|
data/lib/loco_bot/table.rb
CHANGED
@@ -12,11 +12,6 @@ module LocoBot
|
|
12
12
|
# Determines the farthest accessible point on the Table's y-axis.
|
13
13
|
attr_reader :height
|
14
14
|
|
15
|
-
# @!attribute [r] robots
|
16
|
-
# @return [Array<Robot>] a collection of [Robot]
|
17
|
-
# The collection of Robots currently placed on the Table.
|
18
|
-
attr_reader :robots
|
19
|
-
|
20
15
|
# @param width [Integer] The width of the Table
|
21
16
|
# @param height [Integer] The height of the Table
|
22
17
|
def initialize(width = 5, height = 5)
|
@@ -37,28 +32,28 @@ module LocoBot
|
|
37
32
|
def place_robot(robot, x, y, direction)
|
38
33
|
return false unless position_valid?(x, y)
|
39
34
|
|
40
|
-
robot.
|
35
|
+
robot.remove if robot.table
|
41
36
|
|
42
|
-
robot.table
|
43
|
-
robot.
|
44
|
-
robot.
|
45
|
-
robot.
|
37
|
+
robot.instance_variable_set(:@table, self)
|
38
|
+
robot.instance_variable_set(:@x, x)
|
39
|
+
robot.instance_variable_set(:@y, y)
|
40
|
+
robot.instance_variable_set(:@direction, direction)
|
46
41
|
|
47
42
|
@robots.push(robot) unless robots.include?(robot)
|
48
43
|
|
49
44
|
true
|
50
45
|
end
|
51
46
|
|
52
|
-
# Removes the given Robot from the Table. Position attributes of the Robot are set to nil
|
47
|
+
# Removes the given Robot from the Table. Position attributes of the Robot are set to nil.
|
53
48
|
# @param robot [Robot] the Robot to remove from the Table
|
54
49
|
# @return [Boolean] true if removing was successful, false otherwise.
|
55
50
|
def remove_robot(robot)
|
56
51
|
return false unless robots.include?(robot)
|
57
52
|
|
58
|
-
robot.table
|
59
|
-
robot.x
|
60
|
-
robot.y
|
61
|
-
robot.direction
|
53
|
+
robot.instance_variable_set(:@table, nil)
|
54
|
+
robot.instance_variable_set(:@x, nil)
|
55
|
+
robot.instance_variable_set(:@y, nil)
|
56
|
+
robot.instance_variable_set(:@direction, nil)
|
62
57
|
|
63
58
|
@robots.delete(robot)
|
64
59
|
|
@@ -73,6 +68,12 @@ module LocoBot
|
|
73
68
|
position_within_bounds?(x, y) and position_free?(x, y)
|
74
69
|
end
|
75
70
|
|
71
|
+
# The collection of Robots currently placed on the Table.
|
72
|
+
# @return [Array<Robot>] a collection of Robots
|
73
|
+
def robots
|
74
|
+
@robots.dup
|
75
|
+
end
|
76
|
+
|
76
77
|
private
|
77
78
|
|
78
79
|
def position_within_bounds?(x, y)
|
data/lib/loco_bot/version.rb
CHANGED
data/spec/loco_bot/cli_spec.rb
CHANGED
@@ -14,6 +14,17 @@ RSpec.describe LocoBot::CLI do
|
|
14
14
|
|
15
15
|
context 'with a valid number of arguments' do
|
16
16
|
let(:arguments) { '1, 3, SOUTH' }
|
17
|
+
let(:command_class_double) { double }
|
18
|
+
|
19
|
+
it 'calls the correct command' do
|
20
|
+
expect(LocoBot::CLI::Command::Place).to receive(:new).
|
21
|
+
with(subject.robot, subject.table).
|
22
|
+
once.and_return(command_class_double)
|
23
|
+
|
24
|
+
expect(command_class_double).to receive(:execute).with('1', '3', 'SOUTH').once
|
25
|
+
|
26
|
+
subject.input!(input)
|
27
|
+
end
|
17
28
|
end
|
18
29
|
|
19
30
|
context 'with an invalid number of arguments' do
|
@@ -17,8 +17,8 @@ RSpec.describe LocoBot::Robot::Direction::East do
|
|
17
17
|
it { is_expected.to eql 'EAST' }
|
18
18
|
end
|
19
19
|
|
20
|
-
describe '.
|
21
|
-
subject { described_class.
|
20
|
+
describe '.vector' do
|
21
|
+
subject { described_class.vector(21, 17) }
|
22
22
|
|
23
23
|
it { is_expected.to eql({ x: 22, y: 17 }) }
|
24
24
|
end
|
@@ -17,8 +17,8 @@ RSpec.describe LocoBot::Robot::Direction::North do
|
|
17
17
|
it { is_expected.to eql 'NORTH' }
|
18
18
|
end
|
19
19
|
|
20
|
-
describe '.
|
21
|
-
subject { described_class.
|
20
|
+
describe '.vector' do
|
21
|
+
subject { described_class.vector(21, 17) }
|
22
22
|
|
23
23
|
it { is_expected.to eql({ x: 21, y: 18 }) }
|
24
24
|
end
|
@@ -17,8 +17,8 @@ RSpec.describe LocoBot::Robot::Direction::South do
|
|
17
17
|
it { is_expected.to eql 'SOUTH' }
|
18
18
|
end
|
19
19
|
|
20
|
-
describe '.
|
21
|
-
subject { described_class.
|
20
|
+
describe '.vector' do
|
21
|
+
subject { described_class.vector(21, 17) }
|
22
22
|
|
23
23
|
it { is_expected.to eql({ x: 21, y: 16 }) }
|
24
24
|
end
|
@@ -17,8 +17,8 @@ RSpec.describe LocoBot::Robot::Direction::West do
|
|
17
17
|
it { is_expected.to eql 'WEST' }
|
18
18
|
end
|
19
19
|
|
20
|
-
describe '.
|
21
|
-
subject { described_class.
|
20
|
+
describe '.vector' do
|
21
|
+
subject { described_class.vector(21, 17) }
|
22
22
|
|
23
23
|
it { is_expected.to eql({ x: 20, y: 17 }) }
|
24
24
|
end
|
data/spec/loco_bot/robot_spec.rb
CHANGED
@@ -3,26 +3,104 @@ RSpec.describe LocoBot::Robot do
|
|
3
3
|
let(:table) { LocoBot::Table.new(20, 20) }
|
4
4
|
|
5
5
|
describe '#place' do
|
6
|
-
|
6
|
+
let(:other_table) { LocoBot::Table.new(10, 10) }
|
7
|
+
let(:robot) { described_class.new }
|
8
|
+
|
9
|
+
before { robot.place(other_table, 5, 7, LocoBot::Robot::Direction::West) }
|
10
|
+
|
11
|
+
context 'with a valid position' do
|
12
|
+
it "modifies the table's robot list" do
|
13
|
+
expect(other_table.robots).to include(robot)
|
14
|
+
expect(table.robots).not_to include(robot)
|
15
|
+
|
16
|
+
robot.place(table, 12, 14, LocoBot::Robot::Direction::South)
|
17
|
+
|
18
|
+
expect(other_table.robots).not_to include(robot)
|
19
|
+
expect(table.robots).to include(robot)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'changes the robot table, x, y and position' do
|
23
|
+
expect(robot.table).to eql other_table
|
24
|
+
expect(robot.x).to eql 5
|
25
|
+
expect(robot.y).to eql 7
|
26
|
+
expect(robot.direction).to eql LocoBot::Robot::Direction::West
|
27
|
+
|
28
|
+
robot.place(table, 12, 14, LocoBot::Robot::Direction::South)
|
29
|
+
|
30
|
+
expect(robot.table).to eql table
|
31
|
+
expect(robot.x).to eql 12
|
32
|
+
expect(robot.y).to eql 14
|
33
|
+
expect(robot.direction).to eql LocoBot::Robot::Direction::South
|
34
|
+
end
|
35
|
+
|
36
|
+
it { expect(robot.place(table, 12, 14, LocoBot::Robot::Direction::South)).to be true }
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with an invalid position' do
|
40
|
+
it "does not modify the table's robot list" do
|
41
|
+
expect(other_table.robots).to include(robot)
|
42
|
+
expect(table.robots).not_to include(robot)
|
43
|
+
|
44
|
+
robot.place(table, 617, 9001, LocoBot::Robot::Direction::South)
|
45
|
+
|
46
|
+
expect(other_table.robots).to include(robot)
|
47
|
+
expect(table.robots).not_to include(robot)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'does not change the robot table, x, y and position' do
|
51
|
+
expect(robot.table).to eql other_table
|
52
|
+
expect(robot.x).to eql 5
|
53
|
+
expect(robot.y).to eql 7
|
54
|
+
expect(robot.direction).to eql LocoBot::Robot::Direction::West
|
7
55
|
|
8
|
-
|
9
|
-
expect(table).to receive(:place_robot).with(subject, 9, 3, LocoBot::Robot::Direction::East).once
|
56
|
+
robot.place(table, 617, 9001, LocoBot::Robot::Direction::South)
|
10
57
|
|
11
|
-
|
58
|
+
expect(robot.table).to eql other_table
|
59
|
+
expect(robot.x).to eql 5
|
60
|
+
expect(robot.y).to eql 7
|
61
|
+
expect(robot.direction).to eql LocoBot::Robot::Direction::West
|
62
|
+
end
|
63
|
+
|
64
|
+
it { expect(robot.place(table, 617, 9001, LocoBot::Robot::Direction::South)).to be false }
|
12
65
|
end
|
13
66
|
end
|
14
67
|
|
15
68
|
describe '#remove' do
|
16
69
|
subject { robot.remove }
|
17
70
|
|
71
|
+
before do
|
72
|
+
table.place_robot(LocoBot::Robot.new, 3, 4, LocoBot::Robot::Direction::North)
|
73
|
+
table.place_robot(LocoBot::Robot.new, 1, 8, LocoBot::Robot::Direction::West)
|
74
|
+
end
|
75
|
+
|
18
76
|
context 'when placed on a table' do
|
19
77
|
before { robot.place(table, 6, 17, LocoBot::Robot::Direction::East) }
|
20
78
|
|
21
|
-
it
|
22
|
-
expect(table).to
|
79
|
+
it "removes the robot from the table's list" do
|
80
|
+
expect(table.robots.count).to eql 3
|
81
|
+
expect(table.robots).to include(robot)
|
82
|
+
|
83
|
+
robot.remove
|
23
84
|
|
24
|
-
|
85
|
+
expect(table.robots.count).to eql 2
|
86
|
+
expect(table.robots).not_to include(robot)
|
25
87
|
end
|
88
|
+
|
89
|
+
it 'sets to nil robot table, x, y and direction' do
|
90
|
+
expect(robot.table).to eql table
|
91
|
+
expect(robot.x).to eql 6
|
92
|
+
expect(robot.y).to eql 17
|
93
|
+
expect(robot.direction).to eql LocoBot::Robot::Direction::East
|
94
|
+
|
95
|
+
robot.remove
|
96
|
+
|
97
|
+
expect(robot.table).to be_nil
|
98
|
+
expect(robot.x).to be_nil
|
99
|
+
expect(robot.y).to be_nil
|
100
|
+
expect(robot.direction).to be_nil
|
101
|
+
end
|
102
|
+
|
103
|
+
it { expect(subject).to be true }
|
26
104
|
end
|
27
105
|
|
28
106
|
context 'when not placed on a table' do
|
@@ -244,4 +322,29 @@ RSpec.describe LocoBot::Robot do
|
|
244
322
|
end
|
245
323
|
end
|
246
324
|
end
|
325
|
+
|
326
|
+
describe '#next_position_valid?' do
|
327
|
+
subject { robot.next_position_valid? }
|
328
|
+
|
329
|
+
context 'when not placed on a table' do
|
330
|
+
it { is_expected.to be false }
|
331
|
+
end
|
332
|
+
|
333
|
+
|
334
|
+
context 'when placed on a table' do
|
335
|
+
before { robot.place(table, 0, 0, direction) }
|
336
|
+
|
337
|
+
context 'facing a invalid position' do
|
338
|
+
let(:direction) { LocoBot::Robot::Direction::West }
|
339
|
+
|
340
|
+
it { is_expected.to be false }
|
341
|
+
end
|
342
|
+
|
343
|
+
context 'facing a valid position' do
|
344
|
+
let(:direction) { LocoBot::Robot::Direction::North }
|
345
|
+
|
346
|
+
it { is_expected.to be true }
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
247
350
|
end
|
data/spec/loco_bot/table_spec.rb
CHANGED
@@ -36,7 +36,7 @@ RSpec.describe LocoBot::Table do
|
|
36
36
|
before { other_table.place_robot(robot, 5, 7, LocoBot::Robot::Direction::West) }
|
37
37
|
|
38
38
|
context 'with a valid position' do
|
39
|
-
it 'modifies the robot
|
39
|
+
it 'modifies the robot list' do
|
40
40
|
expect(other_table.robots).to include(robot)
|
41
41
|
expect(table.robots).not_to include(robot)
|
42
42
|
|
@@ -64,7 +64,7 @@ RSpec.describe LocoBot::Table do
|
|
64
64
|
end
|
65
65
|
|
66
66
|
context 'with an invalid position' do
|
67
|
-
it 'does not modify the robot
|
67
|
+
it 'does not modify the robot list' do
|
68
68
|
expect(other_table.robots).to include(robot)
|
69
69
|
expect(table.robots).not_to include(robot)
|
70
70
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: loco_bot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rafaël Gonzalez
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -156,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
156
|
version: '0'
|
157
157
|
requirements: []
|
158
158
|
rubyforge_project:
|
159
|
-
rubygems_version: 2.
|
159
|
+
rubygems_version: 2.4.6
|
160
160
|
signing_key:
|
161
161
|
specification_version: 4
|
162
162
|
summary: Ruby gem of crazy robots and benevolent tables that keep watching over them.
|