Skip to content
Permalink
Browse files

Move robot actions to new Action class. Update specs. Add top level d…

…ocumentation
  • Loading branch information...
SelenaSmall committed Aug 27, 2017
1 parent 5047899 commit 8f18c6136c21db3bcc38d98cf6fad619fa98d098
Showing with 237 additions and 169 deletions.
  1. +89 −0 lib/action.rb
  2. +22 −16 lib/handle_input.rb
  3. +1 −1 lib/position.rb
  4. +6 −59 lib/robot.rb
  5. +4 −1 lib/table.rb
  6. +88 −0 spec/action_spec.rb
  7. +22 −14 spec/handle_input_spec.rb
  8. +0 −75 spec/robot_spec.rb
  9. +5 −3 toy_robot.rb
@@ -0,0 +1,89 @@
# Action class
class Action
attr_reader :robot

def initialize(robot)
@robot = robot
end

# Place method
# @param command [String]
# @return Position
def place(command)
_command, x, y, f = command.tr(',', ' ').split

Position.new(x.to_i, y.to_i, f)
end

# Move method
# @param position [Object]
# @return Position
def move(position)
y = position.y
x = position.x
f = position.f

y += 1 if f.match?('NORTH')
x += 1 if f.match?('EAST')
y -= 1 if f.match?('SOUTH')
x -= 1 if f.match?('WEST')

Position.new(x, y, f)
end

# Left method
# @param position [Object]
# @return Position
def left(position)
Position.new(position.x, position.y, prev_option(position.f))
end

# Right method
# @param position [Object]
# @return Position
def right(position)
Position.new(position.x, position.y, next_option(position.f))
end

# Return method
# @param position [Object]
# @return nil
def report(position)
message = "Output: #{position.x},#{position.y},#{position.f} \n"
$stdout.print message
end

private

OPTIONS = %w[WEST NORTH EAST SOUTH].freeze

# Prev Option method
# Find previous value in the options array
# @param direction [String]
# @return previous direction
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

# Next Option method
# Find next value in the options array
# @param direction [String]
# @return next direction
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,37 +1,43 @@
# HandleInput
require_relative 'action'

# HandleInput class
class HandleInput
attr_accessor :robot, :table
attr_accessor :robot, :table, :action

# Command Options
PLACE = /^PLACE\s+\d+\s*,\s*\d+\s*,\s*(WEST||NORTH||EAST||SOUTH)$/
MOVE = /^MOVE$/
LEFT = /^LEFT$/
RIGHT = /^RIGHT$/
REPORT = /^REPORT$/
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)
def initialize(robot, table, action)
@robot = robot
@table = table
@action = action
end

# Interpret user Command
# Interpret method
# @param command [String]
# @return Position
def interpret(command)
return exec(robot.place(command)) if PLACE.match?(command)
return exec(action.place(command)) if PLACE.match?(command)

return if robot.not_in_place?

return exec(robot.move(robot.position)) if MOVE.match?(command)

return exec(robot.left(robot.position)) if LEFT.match?(command)
return exec(action.move(robot.position)) if MOVE.match?(command)

return exec(robot.right(robot.position)) if RIGHT.match?(command)
return exec(action.left(robot.position)) if LEFT.match?(command)

return robot.report(robot.position) if REPORT.match?(command)
return exec(action.right(robot.position)) if RIGHT.match?(command)

# TODO: Exception handler
return action.report(robot.position) if REPORT.match?(command)
end

# Exec method
# Update robot position if it's valid
# @param position [Object]
# @return Position
def exec(position)
return unless table.valid_position?(position)

@@ -1,4 +1,4 @@
# Position
# Position class
class Position
attr_accessor :x, :y, :f

@@ -1,76 +1,23 @@
require_relative 'position'

# Robot
# Robot class
class Robot
attr_reader :position

def intialize
@position = nil
end

def place(command)
_command, x, y, f = command.tr(',', ' ').split

Position.new(x.to_i, y.to_i, f)
end

def move(position)
y = position.y
x = position.x
f = position.f

y += 1 if f.match?('NORTH')
x += 1 if f.match?('EAST')
y -= 1 if f.match?('SOUTH')
x -= 1 if f.match?('WEST')

Position.new(x, y, f)
end

def left(position)
Position.new(position.x, position.y, prev_option(position.f))
end

def right(position)
Position.new(position.x, position.y, next_option(position.f))
end

def report(position)
message = "Output: #{position.x},#{position.y},#{position.f} \n"
$stdout.print message
end

# Update Robot method
# @param new_position [Object]
# @return Position
def update_robot(new_position)
@position = new_position
end

# Not In Place method
# @return Boolean
def not_in_place?
@position.nil?
end

private

OPTIONS = %w[WEST NORTH EAST SOUTH].freeze

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,4 +1,4 @@
# Table
# Table class
class Table
attr_reader :x, :y

@@ -7,6 +7,9 @@ def initialize(x = 5, y = 5)
@y = (0..(y - 1))
end

# Valid Position method
# @params position [Object]
# @return Boolean
def valid_position?(position)
@x.cover?(position.x) && @y.cover?(position.y)
end
@@ -0,0 +1,88 @@
require 'rspec'
require 'spec_helper'
require './lib/action'

describe Action do
describe '#initialize' do
it 'should have a current_position attribute which is nil' do
instance = Action.new(@robot)

expect(instance.robot).to be_nil
end
end

describe '#place' do
it 'should return an instance of Position' do
instance = Action.new(@robot)
command = 'PLACE 0,0,NORTH'

expect(instance.place(command)).to be_a Position
end
end

describe '#move' do
it 'should return an instance of Position' do
instance = Action.new(@robot)
position = Position.new(0, 0, 'NORTH')

expect(instance.move(position)).to be_a Position
end
end

describe '#left' do
it 'should return an instance of Position' do
instance = Action.new(@robot)
position = Position.new(0, 0, 'NORTH')

expect(instance.left(position)).to be_a Position
end
end

describe '#right' do
it 'should return an instance of Position' do
instance = Action.new(@robot)
position = Position.new(0, 0, 'NORTH')

expect(instance.right(position)).to be_a Position
end
end

describe '#report' do
it 'should return nil' do
instance = Action.new(@robot)
position = Position.new(0, 0, 'NORTH')

expect(instance.report(position)).to be_nil
end
end

describe '#prev_option' do
it 'should return the previous value in the OPTIONS array' do
instance = Action.new(@robot)

expect(instance.send(:prev_option, 'NORTH')).to be_a String
expect(instance.send(:prev_option, 'NORTH')).to eq 'WEST'
end

it 'should return nil if the direction param is empty' do
instance = Action.new(@robot)

expect(instance.send(:prev_option, '')).to be_nil
end
end

describe '#next_option' do
it 'should return the next value in the OPTIONS array' do
instance = Action.new(@robot)

expect(instance.send(:next_option, 'NORTH')).to be_a String
expect(instance.send(:next_option, 'NORTH')).to eq 'EAST'
end

it 'should return nil if the direction param is empty' do
instance = Action.new(@robot)

expect(instance.send(:next_option, '')).to be_nil
end
end
end

0 comments on commit 8f18c61

Please sign in to comment.
You can’t perform that action at this time.