Skip to content

Commit 8f18c61

Browse files
committed
Move robot actions to new Action class. Update specs. Add top level documentation
1 parent 5047899 commit 8f18c61

File tree

9 files changed

+237
-169
lines changed

9 files changed

+237
-169
lines changed

lib/action.rb

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Action class
2+
class Action
3+
attr_reader :robot
4+
5+
def initialize(robot)
6+
@robot = robot
7+
end
8+
9+
# Place method
10+
# @param command [String]
11+
# @return Position
12+
def place(command)
13+
_command, x, y, f = command.tr(',', ' ').split
14+
15+
Position.new(x.to_i, y.to_i, f)
16+
end
17+
18+
# Move method
19+
# @param position [Object]
20+
# @return Position
21+
def move(position)
22+
y = position.y
23+
x = position.x
24+
f = position.f
25+
26+
y += 1 if f.match?('NORTH')
27+
x += 1 if f.match?('EAST')
28+
y -= 1 if f.match?('SOUTH')
29+
x -= 1 if f.match?('WEST')
30+
31+
Position.new(x, y, f)
32+
end
33+
34+
# Left method
35+
# @param position [Object]
36+
# @return Position
37+
def left(position)
38+
Position.new(position.x, position.y, prev_option(position.f))
39+
end
40+
41+
# Right method
42+
# @param position [Object]
43+
# @return Position
44+
def right(position)
45+
Position.new(position.x, position.y, next_option(position.f))
46+
end
47+
48+
# Return method
49+
# @param position [Object]
50+
# @return nil
51+
def report(position)
52+
message = "Output: #{position.x},#{position.y},#{position.f} \n"
53+
$stdout.print message
54+
end
55+
56+
private
57+
58+
OPTIONS = %w[WEST NORTH EAST SOUTH].freeze
59+
60+
# Prev Option method
61+
# Find previous value in the options array
62+
# @param direction [String]
63+
# @return previous direction
64+
def prev_option(direction)
65+
return unless OPTIONS.include?(direction)
66+
67+
return OPTIONS.last if direction == OPTIONS.first
68+
69+
i = OPTIONS.index { |e| e == direction }
70+
i -= 1
71+
72+
OPTIONS.fetch(i)
73+
end
74+
75+
# Next Option method
76+
# Find next value in the options array
77+
# @param direction [String]
78+
# @return next direction
79+
def next_option(direction)
80+
return unless OPTIONS.include?(direction)
81+
82+
return OPTIONS.first if direction == OPTIONS.last
83+
84+
i = OPTIONS.index { |e| e == direction }
85+
i += 1
86+
87+
OPTIONS.fetch(i)
88+
end
89+
end

lib/handle_input.rb

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,43 @@
1-
# HandleInput
1+
require_relative 'action'
2+
3+
# HandleInput class
24
class HandleInput
3-
attr_accessor :robot, :table
5+
attr_accessor :robot, :table, :action
46

57
# Command Options
6-
PLACE = /^PLACE\s+\d+\s*,\s*\d+\s*,\s*(WEST||NORTH||EAST||SOUTH)$/
7-
MOVE = /^MOVE$/
8-
LEFT = /^LEFT$/
9-
RIGHT = /^RIGHT$/
10-
REPORT = /^REPORT$/
8+
PLACE = /^PLACE\s+\d+\s*,\s*\d+\s*,\s*(WEST||NORTH||EAST||SOUTH)$/
9+
MOVE = /^MOVE$/
10+
LEFT = /^LEFT$/
11+
RIGHT = /^RIGHT$/
12+
REPORT = /^REPORT$/
1113

12-
def initialize(robot, table)
14+
def initialize(robot, table, action)
1315
@robot = robot
1416
@table = table
17+
@action = action
1518
end
1619

17-
# Interpret user Command
20+
# Interpret method
21+
# @param command [String]
22+
# @return Position
1823
def interpret(command)
19-
return exec(robot.place(command)) if PLACE.match?(command)
24+
return exec(action.place(command)) if PLACE.match?(command)
2025

2126
return if robot.not_in_place?
2227

23-
return exec(robot.move(robot.position)) if MOVE.match?(command)
24-
25-
return exec(robot.left(robot.position)) if LEFT.match?(command)
28+
return exec(action.move(robot.position)) if MOVE.match?(command)
2629

27-
return exec(robot.right(robot.position)) if RIGHT.match?(command)
30+
return exec(action.left(robot.position)) if LEFT.match?(command)
2831

29-
return robot.report(robot.position) if REPORT.match?(command)
32+
return exec(action.right(robot.position)) if RIGHT.match?(command)
3033

31-
# TODO: Exception handler
34+
return action.report(robot.position) if REPORT.match?(command)
3235
end
3336

37+
# Exec method
3438
# Update robot position if it's valid
39+
# @param position [Object]
40+
# @return Position
3541
def exec(position)
3642
return unless table.valid_position?(position)
3743

lib/position.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Position
1+
# Position class
22
class Position
33
attr_accessor :x, :y, :f
44

lib/robot.rb

Lines changed: 6 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,23 @@
11
require_relative 'position'
22

3-
# Robot
3+
# Robot class
44
class Robot
55
attr_reader :position
66

77
def intialize
88
@position = nil
99
end
1010

11-
def place(command)
12-
_command, x, y, f = command.tr(',', ' ').split
13-
14-
Position.new(x.to_i, y.to_i, f)
15-
end
16-
17-
def move(position)
18-
y = position.y
19-
x = position.x
20-
f = position.f
21-
22-
y += 1 if f.match?('NORTH')
23-
x += 1 if f.match?('EAST')
24-
y -= 1 if f.match?('SOUTH')
25-
x -= 1 if f.match?('WEST')
26-
27-
Position.new(x, y, f)
28-
end
29-
30-
def left(position)
31-
Position.new(position.x, position.y, prev_option(position.f))
32-
end
33-
34-
def right(position)
35-
Position.new(position.x, position.y, next_option(position.f))
36-
end
37-
38-
def report(position)
39-
message = "Output: #{position.x},#{position.y},#{position.f} \n"
40-
$stdout.print message
41-
end
42-
11+
# Update Robot method
12+
# @param new_position [Object]
13+
# @return Position
4314
def update_robot(new_position)
4415
@position = new_position
4516
end
4617

18+
# Not In Place method
19+
# @return Boolean
4720
def not_in_place?
4821
@position.nil?
4922
end
50-
51-
private
52-
53-
OPTIONS = %w[WEST NORTH EAST SOUTH].freeze
54-
55-
def prev_option(direction)
56-
return unless OPTIONS.include?(direction)
57-
58-
return OPTIONS.last if direction == OPTIONS.first
59-
60-
i = OPTIONS.index { |e| e == direction }
61-
i -= 1
62-
63-
OPTIONS.fetch(i)
64-
end
65-
66-
def next_option(direction)
67-
return unless OPTIONS.include?(direction)
68-
69-
return OPTIONS.first if direction == OPTIONS.last
70-
71-
i = OPTIONS.index { |e| e == direction }
72-
i += 1
73-
74-
OPTIONS.fetch(i)
75-
end
7623
end

lib/table.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Table
1+
# Table class
22
class Table
33
attr_reader :x, :y
44

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

10+
# Valid Position method
11+
# @params position [Object]
12+
# @return Boolean
1013
def valid_position?(position)
1114
@x.cover?(position.x) && @y.cover?(position.y)
1215
end

spec/action_spec.rb

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
require 'rspec'
2+
require 'spec_helper'
3+
require './lib/action'
4+
5+
describe Action do
6+
describe '#initialize' do
7+
it 'should have a current_position attribute which is nil' do
8+
instance = Action.new(@robot)
9+
10+
expect(instance.robot).to be_nil
11+
end
12+
end
13+
14+
describe '#place' do
15+
it 'should return an instance of Position' do
16+
instance = Action.new(@robot)
17+
command = 'PLACE 0,0,NORTH'
18+
19+
expect(instance.place(command)).to be_a Position
20+
end
21+
end
22+
23+
describe '#move' do
24+
it 'should return an instance of Position' do
25+
instance = Action.new(@robot)
26+
position = Position.new(0, 0, 'NORTH')
27+
28+
expect(instance.move(position)).to be_a Position
29+
end
30+
end
31+
32+
describe '#left' do
33+
it 'should return an instance of Position' do
34+
instance = Action.new(@robot)
35+
position = Position.new(0, 0, 'NORTH')
36+
37+
expect(instance.left(position)).to be_a Position
38+
end
39+
end
40+
41+
describe '#right' do
42+
it 'should return an instance of Position' do
43+
instance = Action.new(@robot)
44+
position = Position.new(0, 0, 'NORTH')
45+
46+
expect(instance.right(position)).to be_a Position
47+
end
48+
end
49+
50+
describe '#report' do
51+
it 'should return nil' do
52+
instance = Action.new(@robot)
53+
position = Position.new(0, 0, 'NORTH')
54+
55+
expect(instance.report(position)).to be_nil
56+
end
57+
end
58+
59+
describe '#prev_option' do
60+
it 'should return the previous value in the OPTIONS array' do
61+
instance = Action.new(@robot)
62+
63+
expect(instance.send(:prev_option, 'NORTH')).to be_a String
64+
expect(instance.send(:prev_option, 'NORTH')).to eq 'WEST'
65+
end
66+
67+
it 'should return nil if the direction param is empty' do
68+
instance = Action.new(@robot)
69+
70+
expect(instance.send(:prev_option, '')).to be_nil
71+
end
72+
end
73+
74+
describe '#next_option' do
75+
it 'should return the next value in the OPTIONS array' do
76+
instance = Action.new(@robot)
77+
78+
expect(instance.send(:next_option, 'NORTH')).to be_a String
79+
expect(instance.send(:next_option, 'NORTH')).to eq 'EAST'
80+
end
81+
82+
it 'should return nil if the direction param is empty' do
83+
instance = Action.new(@robot)
84+
85+
expect(instance.send(:next_option, '')).to be_nil
86+
end
87+
end
88+
end

0 commit comments

Comments
 (0)