Skip to content

Commit ceed3ff

Browse files
committed
Abstract actions into their own classes, tidy up input handler. Add specs for each action
1 parent 5152d59 commit ceed3ff

14 files changed

+226
-169
lines changed

lib/actions/move.rb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
class Move
2+
attr_reader :robot, :table
3+
4+
def initialize(robot, table)
5+
@robot = robot
6+
@table = table
7+
end
8+
9+
def perform
10+
case robot.position.f
11+
when 'NORTH'
12+
y = robot.position.y
13+
y += 1
14+
position = Position.new(robot.position.x, y, robot.position.f)
15+
16+
robot.update_robot(position) if table.valid_position?(robot.position.x, position.y)
17+
when 'EAST'
18+
x = robot.position.x
19+
x += 1
20+
21+
position = Position.new(x, robot.position.y, robot.position.f)
22+
23+
robot.update_robot(position) if table.valid_position?(position.x, robot.position.y)
24+
when 'SOUTH'
25+
y = robot.position.y
26+
y -= 1
27+
position = Position.new(robot.position.x, y, robot.position.f)
28+
29+
robot.update_robot(position) if table.valid_position?(robot.position.x, position.y)
30+
when 'WEST'
31+
x = robot.position.x
32+
x -= 1
33+
34+
position = Position.new(x, robot.position.y, robot.position.f)
35+
36+
robot.update_robot(position) if table.valid_position?(position.x, robot.position.y)
37+
end
38+
end
39+
end

lib/actions/place.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class Place
2+
attr_reader :robot, :table
3+
4+
def initialize(robot, table)
5+
@robot = robot
6+
@table = table
7+
end
8+
9+
def perform(command)
10+
_command, x, y, f = command.tr(',', ' ').split
11+
12+
position = Position.new(x.to_i, y.to_i, f)
13+
14+
robot.update_robot(position) if table.valid_position?(position.x, position.y)
15+
end
16+
end

lib/actions/report.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class Report
2+
attr_reader :robot
3+
4+
def initialize(robot)
5+
@robot = robot
6+
end
7+
8+
def perform
9+
message = "Output: #{robot.position.x},#{robot.position.y},#{robot.position.f} \n"
10+
$stdout.print message
11+
end
12+
end

lib/actions/turn.rb

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
class Turn
2+
attr_reader :robot
3+
4+
OPTIONS = %w[WEST NORTH EAST SOUTH].freeze
5+
6+
def initialize(robot)
7+
@robot = robot
8+
end
9+
10+
def left
11+
robot.position.f = prev_option(robot.position.f)
12+
13+
robot.update_robot(robot.position)
14+
end
15+
16+
def right
17+
robot.position.f = next_option(robot.position.f)
18+
19+
robot.update_robot(robot.position)
20+
end
21+
22+
private
23+
24+
def prev_option(direction)
25+
return unless OPTIONS.include?(direction)
26+
27+
return OPTIONS.last if direction == OPTIONS.first
28+
29+
i = OPTIONS.index { |e| e == direction }
30+
i -= 1
31+
32+
OPTIONS.fetch(i)
33+
end
34+
35+
def next_option(direction)
36+
return unless OPTIONS.include?(direction)
37+
38+
return OPTIONS.first if direction == OPTIONS.last
39+
40+
i = OPTIONS.index { |e| e == direction }
41+
i += 1
42+
43+
OPTIONS.fetch(i)
44+
end
45+
end

lib/direction.rb

Lines changed: 0 additions & 36 deletions
This file was deleted.

lib/handle_input.rb

Lines changed: 17 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,38 @@
1-
require_relative 'direction'
2-
require_relative 'position'
1+
require_relative './actions/place'
2+
require_relative './actions/move'
3+
require_relative './actions/turn'
4+
require_relative './actions/report'
35

46
# HandleInput class
57
class HandleInput
68
attr_accessor :robot, :table
79

10+
# Command Options
11+
PLACE = /^PLACE\s+\d+\s*,\s*\d+\s*,\s*(WEST||NORTH||EAST||SOUTH)$/
12+
MOVE = /^MOVE$/
13+
LEFT = /^LEFT$/
14+
RIGHT = /^RIGHT$/
15+
REPORT = /^REPORT$/
16+
817
def initialize(robot, table)
918
@robot = robot
1019
@table = table
1120
end
1221

1322
# Interpret user Command
1423
def interpret(command)
15-
# Valid command patterns
16-
# TODO: Add direction to place command
17-
place = /^PLACE\s+\d+\s*,\s*\d+\s*,\s*(WEST||NORTH||EAST||SOUTH)$/
18-
move = /^MOVE$/
19-
left = /^LEFT$/
20-
right = /^RIGHT$/
21-
report = /^REPORT$/
22-
23-
# PLACE
24-
if place.match?(command)
25-
command, x, y, f = command.tr(',', ' ').split
26-
27-
position = @robot.place(x.to_i, y.to_i, f)
28-
29-
# Only update robot if the position is valid on the table
30-
robot.update_robot(position) if @table.valid_position?(position.x, position.y)
24+
return Place.new(robot, table).perform(command) if PLACE.match?(command)
3125

32-
puts "CMD: #{command} #{position.x},#{position.y},#{position.f}"
33-
34-
puts 'placed!' unless robot.not_in_place?
35-
return "#{command} #{position.x},#{position.y},#{position.f}" unless robot.not_in_place?
36-
end
37-
38-
# PLACE is the only valid command unless robot is in place
3926
return if robot.not_in_place?
4027

41-
# LEFT
42-
if left.match?(command)
43-
# Turn left and update the robots direction
44-
robot.position.f = Direction.new.turn_left(robot.position.f)
45-
46-
robot.update_robot(robot.position)
47-
48-
puts "New position #{robot.position.x},#{robot.position.y},#{robot.position.f}"
49-
end
50-
51-
# RIGHT
52-
if right.match?(command)
53-
# Turn right and update the robots direction
54-
robot.position.f = Direction.new.turn_right(robot.position.f)
55-
56-
robot.update_robot(robot.position)
57-
58-
puts "New position #{robot.position.x},#{robot.position.y},#{robot.position.f}"
59-
end
60-
61-
# MOVE
62-
if move.match?(command)
63-
case robot.position.f
64-
when 'NORTH'
65-
y = robot.position.y
66-
y += 1
67-
position = Position.new(robot.position.x, y, robot.position.f)
68-
69-
robot.update_robot(position) if table.valid_position?(robot.position.x, position.y)
70-
when 'EAST'
71-
x = robot.position.x
72-
x += 1
73-
74-
position = Position.new(x, robot.position.y, robot.position.f)
75-
76-
robot.update_robot(position) if table.valid_position?(position.x, robot.position.y)
77-
when 'SOUTH'
78-
y = robot.position.y
79-
y -= 1
80-
position = Position.new(robot.position.x, y, robot.position.f)
28+
return Move.new(robot, table).perform if MOVE.match?(command)
8129

82-
robot.update_robot(position) if table.valid_position?(robot.position.x, position.y)
83-
when 'WEST'
84-
x = robot.position.x
85-
x -= 1
30+
return Turn.new(robot).left if LEFT.match?(command)
8631

87-
position = Position.new(x, robot.position.y, robot.position.f)
32+
return Turn.new(robot).right if RIGHT.match?(command)
8833

89-
robot.update_robot(position) if table.valid_position?(position.x, robot.position.y)
90-
end
91-
end
34+
return Report.new(robot).perform if REPORT.match?(command)
9235

93-
# puts 'reporting' if report.match?(command)
94-
if report.match?(command)
95-
puts "Output: #{robot.position.x},#{robot.position.y},#{robot.position.f}"
96-
end
36+
# TODO: Exception handler
9737
end
9838
end

lib/robot.rb

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@ def intialize
88
@position = nil
99
end
1010

11-
# Place the robot
12-
def place(x, y, f)
13-
Position.new(x, y, f)
14-
end
15-
1611
# Update the robot's position
1712
def update_robot(new_position)
1813
@position = new_position

spec/direction_spec.rb

Lines changed: 0 additions & 39 deletions
This file was deleted.

spec/handle_input_spec.rb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,11 @@
1818
end
1919

2020
describe '#interpret' do
21-
it 'should return a string if command matches place pattern' do
21+
it 'should return an instance of Position command matches place pattern' do
2222
instance = HandleInput.new(Robot.new, Table.new)
23-
command = 'PLACE 1,2,NORTH'
23+
command = 'PLACE 1,2,NORTH'
2424

25-
expect(instance.interpret(command)).to be_a String
26-
expect(instance.interpret(command)).to match(/^PLACE\s+\d+\s*,\s*\d+\s*,\s*(WEST||NORTH||EAST||SOUTH)$/)
25+
expect(instance.interpret(command)).to be_a Position
2726
end
2827

2928
it 'should return nil if command does not match a valid pattern' do

spec/move_spec.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
require 'rspec'
2+
require 'spec_helper'
3+
require './lib/actions/move'
4+
5+
describe Move do
6+
describe '#initialize' do
7+
it 'should have a robot attribute which is nil' do
8+
instance = Move.new(@robot, @table)
9+
10+
expect(instance.robot).to be_nil
11+
end
12+
13+
it 'should have a table attribute which is nil' do
14+
instance = Move.new(@robot, @table)
15+
16+
expect(instance.table).to be_nil
17+
end
18+
end
19+
end

0 commit comments

Comments
 (0)