Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Abstract actions into their own classes, tidy up input handler. Add s…
…pecs for each action
- Loading branch information
Showing
with
226 additions
and 169 deletions.
- +39 −0 lib/actions/move.rb
- +16 −0 lib/actions/place.rb
- +12 −0 lib/actions/report.rb
- +45 −0 lib/actions/turn.rb
- +0 −36 lib/direction.rb
- +17 −77 lib/handle_input.rb
- +0 −5 lib/robot.rb
- +0 −39 spec/direction_spec.rb
- +3 −4 spec/handle_input_spec.rb
- +19 −0 spec/move_spec.rb
- +19 −0 spec/place_spec.rb
- +13 −0 spec/report_spec.rb
- +0 −8 spec/robot_spec.rb
- +43 −0 spec/turn_spec.rb
@@ -0,0 +1,39 @@ | ||
class Move | ||
attr_reader :robot, :table | ||
|
||
def initialize(robot, table) | ||
@robot = robot | ||
@table = table | ||
end | ||
|
||
def perform | ||
case robot.position.f | ||
when 'NORTH' | ||
y = robot.position.y | ||
y += 1 | ||
position = Position.new(robot.position.x, y, robot.position.f) | ||
|
||
robot.update_robot(position) if table.valid_position?(robot.position.x, position.y) | ||
when 'EAST' | ||
x = robot.position.x | ||
x += 1 | ||
|
||
position = Position.new(x, robot.position.y, robot.position.f) | ||
|
||
robot.update_robot(position) if table.valid_position?(position.x, robot.position.y) | ||
when 'SOUTH' | ||
y = robot.position.y | ||
y -= 1 | ||
position = Position.new(robot.position.x, y, robot.position.f) | ||
|
||
robot.update_robot(position) if table.valid_position?(robot.position.x, position.y) | ||
when 'WEST' | ||
x = robot.position.x | ||
x -= 1 | ||
|
||
position = Position.new(x, robot.position.y, robot.position.f) | ||
|
||
robot.update_robot(position) if table.valid_position?(position.x, robot.position.y) | ||
end | ||
end | ||
end |
@@ -0,0 +1,16 @@ | ||
class Place | ||
attr_reader :robot, :table | ||
|
||
def initialize(robot, table) | ||
@robot = robot | ||
@table = table | ||
end | ||
|
||
def perform(command) | ||
_command, x, y, f = command.tr(',', ' ').split | ||
|
||
position = Position.new(x.to_i, y.to_i, f) | ||
|
||
robot.update_robot(position) if table.valid_position?(position.x, position.y) | ||
end | ||
end |
@@ -0,0 +1,12 @@ | ||
class Report | ||
attr_reader :robot | ||
|
||
def initialize(robot) | ||
@robot = robot | ||
end | ||
|
||
def perform | ||
message = "Output: #{robot.position.x},#{robot.position.y},#{robot.position.f} \n" | ||
$stdout.print message | ||
end | ||
end |
@@ -0,0 +1,45 @@ | ||
class Turn | ||
attr_reader :robot | ||
|
||
OPTIONS = %w[WEST NORTH EAST SOUTH].freeze | ||
|
||
def initialize(robot) | ||
@robot = robot | ||
end | ||
|
||
def left | ||
robot.position.f = prev_option(robot.position.f) | ||
|
||
robot.update_robot(robot.position) | ||
end | ||
|
||
def right | ||
robot.position.f = next_option(robot.position.f) | ||
|
||
robot.update_robot(robot.position) | ||
end | ||
|
||
private | ||
|
||
def prev_option(direction) | ||
return unless OPTIONS.include?(direction) | ||
|
||
return OPTIONS.last if direction == OPTIONS.first | ||
|
||
i = OPTIONS.index { |e| e == direction } | ||
i -= 1 | ||
|
||
OPTIONS.fetch(i) | ||
end | ||
|
||
def next_option(direction) | ||
return unless OPTIONS.include?(direction) | ||
|
||
return OPTIONS.first if direction == OPTIONS.last | ||
|
||
i = OPTIONS.index { |e| e == direction } | ||
i += 1 | ||
|
||
OPTIONS.fetch(i) | ||
end | ||
end |
@@ -1,98 +1,38 @@ | ||
require_relative 'direction' | ||
require_relative 'position' | ||
require_relative './actions/place' | ||
require_relative './actions/move' | ||
require_relative './actions/turn' | ||
require_relative './actions/report' | ||
|
||
# HandleInput class | ||
class HandleInput | ||
attr_accessor :robot, :table | ||
|
||
# Command Options | ||
PLACE = /^PLACE\s+\d+\s*,\s*\d+\s*,\s*(WEST||NORTH||EAST||SOUTH)$/ | ||
MOVE = /^MOVE$/ | ||
LEFT = /^LEFT$/ | ||
RIGHT = /^RIGHT$/ | ||
REPORT = /^REPORT$/ | ||
|
||
def initialize(robot, table) | ||
@robot = robot | ||
@table = table | ||
end | ||
|
||
# Interpret user Command | ||
def interpret(command) | ||
# Valid command patterns | ||
# TODO: Add direction to place command | ||
place = /^PLACE\s+\d+\s*,\s*\d+\s*,\s*(WEST||NORTH||EAST||SOUTH)$/ | ||
move = /^MOVE$/ | ||
left = /^LEFT$/ | ||
right = /^RIGHT$/ | ||
report = /^REPORT$/ | ||
|
||
# PLACE | ||
if place.match?(command) | ||
command, x, y, f = command.tr(',', ' ').split | ||
|
||
position = @robot.place(x.to_i, y.to_i, f) | ||
|
||
# Only update robot if the position is valid on the table | ||
robot.update_robot(position) if @table.valid_position?(position.x, position.y) | ||
return Place.new(robot, table).perform(command) if PLACE.match?(command) | ||
|
||
puts "CMD: #{command} #{position.x},#{position.y},#{position.f}" | ||
|
||
puts 'placed!' unless robot.not_in_place? | ||
return "#{command} #{position.x},#{position.y},#{position.f}" unless robot.not_in_place? | ||
end | ||
|
||
# PLACE is the only valid command unless robot is in place | ||
return if robot.not_in_place? | ||
|
||
# LEFT | ||
if left.match?(command) | ||
# Turn left and update the robots direction | ||
robot.position.f = Direction.new.turn_left(robot.position.f) | ||
|
||
robot.update_robot(robot.position) | ||
|
||
puts "New position #{robot.position.x},#{robot.position.y},#{robot.position.f}" | ||
end | ||
|
||
# RIGHT | ||
if right.match?(command) | ||
# Turn right and update the robots direction | ||
robot.position.f = Direction.new.turn_right(robot.position.f) | ||
|
||
robot.update_robot(robot.position) | ||
|
||
puts "New position #{robot.position.x},#{robot.position.y},#{robot.position.f}" | ||
end | ||
|
||
# MOVE | ||
if move.match?(command) | ||
case robot.position.f | ||
when 'NORTH' | ||
y = robot.position.y | ||
y += 1 | ||
position = Position.new(robot.position.x, y, robot.position.f) | ||
|
||
robot.update_robot(position) if table.valid_position?(robot.position.x, position.y) | ||
when 'EAST' | ||
x = robot.position.x | ||
x += 1 | ||
|
||
position = Position.new(x, robot.position.y, robot.position.f) | ||
|
||
robot.update_robot(position) if table.valid_position?(position.x, robot.position.y) | ||
when 'SOUTH' | ||
y = robot.position.y | ||
y -= 1 | ||
position = Position.new(robot.position.x, y, robot.position.f) | ||
return Move.new(robot, table).perform if MOVE.match?(command) | ||
|
||
robot.update_robot(position) if table.valid_position?(robot.position.x, position.y) | ||
when 'WEST' | ||
x = robot.position.x | ||
x -= 1 | ||
return Turn.new(robot).left if LEFT.match?(command) | ||
|
||
position = Position.new(x, robot.position.y, robot.position.f) | ||
return Turn.new(robot).right if RIGHT.match?(command) | ||
|
||
robot.update_robot(position) if table.valid_position?(position.x, robot.position.y) | ||
end | ||
end | ||
return Report.new(robot).perform if REPORT.match?(command) | ||
|
||
# puts 'reporting' if report.match?(command) | ||
if report.match?(command) | ||
puts "Output: #{robot.position.x},#{robot.position.y},#{robot.position.f}" | ||
end | ||
# TODO: Exception handler | ||
end | ||
end |
@@ -0,0 +1,19 @@ | ||
require 'rspec' | ||
require 'spec_helper' | ||
require './lib/actions/move' | ||
|
||
describe Move do | ||
describe '#initialize' do | ||
it 'should have a robot attribute which is nil' do | ||
instance = Move.new(@robot, @table) | ||
|
||
expect(instance.robot).to be_nil | ||
end | ||
|
||
it 'should have a table attribute which is nil' do | ||
instance = Move.new(@robot, @table) | ||
|
||
expect(instance.table).to be_nil | ||
end | ||
end | ||
end |
@@ -0,0 +1,19 @@ | ||
require 'rspec' | ||
require 'spec_helper' | ||
require './lib/actions/place' | ||
|
||
describe Place do | ||
describe '#initialize' do | ||
it 'should have a robot attribute which is nil' do | ||
instance = Place.new(@robot, @table) | ||
|
||
expect(instance.robot).to be_nil | ||
end | ||
|
||
it 'should have a table attribute which is nil' do | ||
instance = Place.new(@robot, @table) | ||
|
||
expect(instance.table).to be_nil | ||
end | ||
end | ||
end |
@@ -0,0 +1,13 @@ | ||
require 'rspec' | ||
require 'spec_helper' | ||
require './lib/actions/report' | ||
|
||
describe Report do | ||
describe '#initialize' do | ||
it 'should have a robot attribute which is nil' do | ||
instance = Report.new(@robot) | ||
|
||
expect(instance.robot).to be_nil | ||
end | ||
end | ||
end |
Oops, something went wrong.