Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Abstract actions into their own classes, tidy up input handler. Add s…
…pecs for each action
  • Loading branch information
SelenaSmall committed Aug 27, 2017
1 parent 5152d59 commit ceed3ff
Show file tree
Hide file tree
Showing 14 changed files with 226 additions and 169 deletions.
39 changes: 39 additions & 0 deletions lib/actions/move.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
16 changes: 16 additions & 0 deletions lib/actions/place.rb
@@ -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
12 changes: 12 additions & 0 deletions lib/actions/report.rb
@@ -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
45 changes: 45 additions & 0 deletions lib/actions/turn.rb
@@ -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
36 changes: 0 additions & 36 deletions lib/direction.rb

This file was deleted.

94 changes: 17 additions & 77 deletions lib/handle_input.rb
@@ -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
5 changes: 0 additions & 5 deletions lib/robot.rb
Expand Up @@ -8,11 +8,6 @@ def intialize
@position = nil
end

# Place the robot
def place(x, y, f)
Position.new(x, y, f)
end

# Update the robot's position
def update_robot(new_position)
@position = new_position
Expand Down
39 changes: 0 additions & 39 deletions spec/direction_spec.rb

This file was deleted.

7 changes: 3 additions & 4 deletions spec/handle_input_spec.rb
Expand Up @@ -18,12 +18,11 @@
end

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

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

it 'should return nil if command does not match a valid pattern' do
Expand Down
19 changes: 19 additions & 0 deletions spec/move_spec.rb
@@ -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
19 changes: 19 additions & 0 deletions spec/place_spec.rb
@@ -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
13 changes: 13 additions & 0 deletions spec/report_spec.rb
@@ -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

0 comments on commit ceed3ff

Please sign in to comment.