loco_bot 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.
|