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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ef33dd6ab2797541d85647722519e50e1fcf5c56
4
- data.tar.gz: 2695c38bbc217dd317ba7ab67cfc6681e4034be7
3
+ metadata.gz: 5bcc03fc9e471fbe3836c3d97c8f4b2c1781c3b4
4
+ data.tar.gz: 3422b70bf9684df8760c86aee333509d3c3ea18f
5
5
  SHA512:
6
- metadata.gz: 713365f6dd107ae2ac6410e192d5f77d4da7fd60590f289b409967e29dad9a83987103a6be79800092d0d02eba6b27a15b1f28dec10ac205736b1b4b0db69526
7
- data.tar.gz: 511a8c28a3cfcd05ceb5b925f15c4cebfa250ca6a7b219657403c80d829add94e1c070248112b6260641a6805a94f505aa4a49828696ba914941d776663de2ac
6
+ metadata.gz: f6e1f94945da2600e5d87060c1d86a38609e38b762c2b270a2f603306b7bd762aa93883a1b6627d82a9a545d6f5a07471337a266bb1af7b4b11c1141f5a8a4d5
7
+ data.tar.gz: 1a543d54eb4229da4fe29d915b1f4f9251d31e9d9b56f76d34807d611193cfcec09c9cc3e2b1f60338d934224669109cf8ab08bea020c7c78acda7ef30f5b053
@@ -22,13 +22,13 @@ module LocoBot
22
22
  'EAST'
23
23
  end
24
24
 
25
- # Returns the given coordinates in a Hash, modified to reflect the Direction.
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 modified x and y coordinates
28
+ # @return [Hash] the vectorial x and y coordinates
29
29
  # @example
30
- # Direction::East.coordinates(1, 2) # => {x: 2, y: 2}
31
- def self.coordinates(x, y)
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
- # Returns the given coordinates in a Hash, modified to reflect the Direction.
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 modified x and y coordinates
28
+ # @return [Hash] the vectorial x and y coordinates
29
29
  # @example
30
- # Direction::North.coordinates(1, 2) # => {x: 1, y: 3}
31
- def self.coordinates(x, y)
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
- # Returns the given coordinates in a Hash, modified to reflect the Direction.
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 modified x and y coordinates
28
+ # @return [Hash] the vectorial x and y coordinates
29
29
  # @example
30
- # Direction::South.coordinates(1, 2) # => {x: 1, y: 1}
31
- def self.coordinates(x, y)
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
- # Returns the given coordinates in a Hash, modified to reflect the Direction.
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 modified x and y coordinates
28
+ # @return [Hash] the vectorial x and y coordinates
29
29
  # @example
30
- # Direction::West.coordinates(1, 2) # => {x: 0, y: 2}
31
- def self.coordinates(x, y)
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
@@ -4,21 +4,21 @@ module LocoBot
4
4
  # Representation of a robot, placeable on tables.
5
5
  class Robot
6
6
 
7
- # @!attribute [rw] table
7
+ # @!attribute [r] table
8
8
  # @return [Table] the Table the Robot is currently placed on
9
- attr_accessor :table
9
+ attr_reader :table
10
10
 
11
- # @!attribute [rw] x
11
+ # @!attribute [r] x
12
12
  # @return [Integer] the x-axis coordinate the Robot is currently at on the Table
13
- attr_accessor :x
13
+ attr_reader :x
14
14
 
15
- # @!attribute [rw] y
15
+ # @!attribute [r] y
16
16
  # @return [Integer] the y-axis coordinate the Robot is currently at on the Table
17
- attr_accessor :y
17
+ attr_reader :y
18
18
 
19
- # @!attribute [rw] direction
19
+ # @!attribute [r] direction
20
20
  # @return [Direction] the Direction the Robot is currently facing on the Table
21
- attr_accessor :direction
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 if table.nil? or !table.position_valid?(next_position[:x], next_position[:y])
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.next_direction # => {x: 0, y: 2}
95
+ # robot.next_position # => {x: 0, y: 2}
96
96
  def next_position
97
97
  return {} if table.nil?
98
98
 
99
- direction.coordinates(x, y)
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
@@ -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.table.remove_robot(robot) if robot.table
35
+ robot.remove if robot.table
41
36
 
42
- robot.table = self
43
- robot.direction = direction
44
- robot.x = x
45
- robot.y = y
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 = nil
59
- robot.x = nil
60
- robot.y = nil
61
- robot.direction = nil
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)
@@ -1,4 +1,4 @@
1
1
  module LocoBot
2
2
  # The gem's current version
3
- VERSION = '1.0.0'
3
+ VERSION = '2.0.0'
4
4
  end
@@ -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 '.coordinates' do
21
- subject { described_class.coordinates(21, 17) }
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 '.coordinates' do
21
- subject { described_class.coordinates(21, 17) }
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 '.coordinates' do
21
- subject { described_class.coordinates(21, 17) }
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 '.coordinates' do
21
- subject { described_class.coordinates(21, 17) }
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
@@ -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
- subject { robot }
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
- it 'calls Table#place_robot' do
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
- subject.place(table, 9, 3, LocoBot::Robot::Direction::East)
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 'calls Table#remove_robot' do
22
- expect(table).to receive(:remove_robot).with(robot).once
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
- subject
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
@@ -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 lists' do
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 lists' do
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: 1.0.0
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: 2014-10-06 00:00:00.000000000 Z
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.2.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.