toyrobot 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +2 -2
- data/README.md +166 -10
- data/lib/toy_robot/application.rb +1 -13
- data/lib/toy_robot/board.rb +1 -1
- data/lib/toy_robot/command/parser.rb +6 -3
- data/lib/toy_robot/command/parser/base.rb +4 -25
- data/lib/toy_robot/command/parser/left.rb +12 -0
- data/lib/toy_robot/command/parser/move.rb +12 -0
- data/lib/toy_robot/command/parser/place.rb +3 -4
- data/lib/toy_robot/command/parser/report.rb +12 -0
- data/lib/toy_robot/command/parser/right.rb +12 -0
- data/lib/toy_robot/controller.rb +32 -0
- data/lib/toy_robot/factory.rb +6 -18
- data/lib/toy_robot/pose.rb +19 -5
- data/lib/toy_robot/robot.rb +11 -15
- data/lib/toy_robot/view.rb +10 -12
- data/test/board_double.rb +5 -0
- data/test/integration/test_factory.rb +2 -2
- data/test/integration/test_toy_robot.rb +1 -1
- data/test/pose_double.rb +23 -0
- data/test/test_board.rb +7 -14
- data/test/test_board_double.rb +13 -0
- data/test/test_board_interface.rb +15 -0
- data/test/{test_command_matcher.rb → test_command_parser.rb} +6 -6
- data/test/{test_command_matcher_interface.rb → test_command_parser_interface.rb} +5 -5
- data/test/test_command_parser_left.rb +20 -0
- data/test/{test_command_matcher_move.rb → test_command_parser_move.rb} +5 -5
- data/test/{test_command_matcher_place.rb → test_command_parser_place.rb} +10 -10
- data/test/{test_command_matcher_report.rb → test_command_parser_report.rb} +5 -5
- data/test/test_command_parser_right.rb +20 -0
- data/test/test_controller.rb +64 -0
- data/test/test_pose.rb +16 -20
- data/test/test_pose_double.rb +15 -0
- data/test/test_pose_interface.rb +26 -0
- data/test/test_reporter_interface.rb +13 -1
- data/test/test_robot.rb +70 -27
- data/toyrobot.gemspec +1 -1
- metadata +35 -26
- data/lib/toy_robot/command/base.rb +0 -5
- data/lib/toy_robot/command/token.rb +0 -11
- data/lib/toy_robot/placement.rb +0 -34
- data/lib/toy_robot/robot_controller.rb +0 -35
- data/test/test_command.rb +0 -22
- data/test/test_command_matcher_left.rb +0 -20
- data/test/test_command_matcher_right.rb +0 -20
- data/test/test_placement.rb +0 -94
- data/test/test_robot_controller.rb +0 -62
@@ -0,0 +1,32 @@
|
|
1
|
+
module ToyRobot
|
2
|
+
class Controller
|
3
|
+
def initialize(args)
|
4
|
+
@robot = args[:robot]
|
5
|
+
@view = args[:view]
|
6
|
+
end
|
7
|
+
|
8
|
+
def place(*args)
|
9
|
+
robot.place(*args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def move(*_)
|
13
|
+
robot.move
|
14
|
+
end
|
15
|
+
|
16
|
+
def left(*_)
|
17
|
+
robot.left
|
18
|
+
end
|
19
|
+
|
20
|
+
def right(*_)
|
21
|
+
robot.right
|
22
|
+
end
|
23
|
+
|
24
|
+
def report(*_)
|
25
|
+
view.report
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :robot, :view
|
31
|
+
end
|
32
|
+
end
|
data/lib/toy_robot/factory.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
require_relative '
|
1
|
+
require_relative 'controller'
|
2
2
|
require_relative 'robot'
|
3
|
-
require_relative 'placement'
|
4
3
|
require_relative 'board'
|
5
4
|
require_relative 'pose'
|
6
5
|
require_relative 'view'
|
@@ -12,18 +11,18 @@ module ToyRobot
|
|
12
11
|
def create(identifier, opts = {})
|
13
12
|
case identifier
|
14
13
|
when :controller
|
15
|
-
|
14
|
+
ControllerFactory.create(opts)
|
16
15
|
end
|
17
16
|
end
|
18
17
|
|
19
|
-
module
|
18
|
+
module ControllerFactory
|
20
19
|
module_function
|
21
20
|
|
22
21
|
def create(opts = {})
|
23
22
|
robot = opts[:robot] || RobotFactory.create
|
24
23
|
view = opts[:view] || ViewFactory.create(robot: robot)
|
25
24
|
|
26
|
-
ToyRobot::
|
25
|
+
ToyRobot::Controller.new(
|
27
26
|
robot: robot,
|
28
27
|
view: view
|
29
28
|
)
|
@@ -47,22 +46,11 @@ module ToyRobot
|
|
47
46
|
module RobotFactory
|
48
47
|
module_function
|
49
48
|
|
50
|
-
def create(opts = {})
|
51
|
-
placement = opts[:placement] || PlacementFactory.create
|
52
|
-
|
53
|
-
ToyRobot::Robot.new(
|
54
|
-
placement: placement
|
55
|
-
)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
module PlacementFactory
|
60
|
-
module_function
|
61
|
-
|
62
49
|
def create(opts = {})
|
63
50
|
board = opts[:board] || BoardFactory.create
|
64
51
|
pose = opts[:pose] || ToyRobot::Pose.new
|
65
|
-
|
52
|
+
|
53
|
+
ToyRobot::Robot.new(
|
66
54
|
board: board,
|
67
55
|
pose: pose
|
68
56
|
)
|
data/lib/toy_robot/pose.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
1
3
|
module ToyRobot
|
2
4
|
class Pose
|
3
5
|
module Orientation
|
@@ -7,14 +9,19 @@ module ToyRobot
|
|
7
9
|
SOUTH = :south
|
8
10
|
end
|
9
11
|
|
10
|
-
attr_accessor :x, :y, :orientation
|
11
|
-
|
12
12
|
def initialize(args = {})
|
13
13
|
@x = args[:x]
|
14
14
|
@y = args[:y]
|
15
15
|
@orientation = args[:orientation]
|
16
16
|
end
|
17
17
|
|
18
|
+
def mutate!(attrs = {})
|
19
|
+
self.x = attrs[:x] || x
|
20
|
+
self.y = attrs[:y] || y
|
21
|
+
self.orientation = attrs[:orientation] || orientation
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
18
25
|
def adjacent
|
19
26
|
dup.send(:adjacent!)
|
20
27
|
end
|
@@ -22,6 +29,7 @@ module ToyRobot
|
|
22
29
|
def rotate!(degrees)
|
23
30
|
step = (degrees % 90) + (degrees/degrees.abs)
|
24
31
|
self.orientation = step_orientation(step)
|
32
|
+
self
|
25
33
|
end
|
26
34
|
|
27
35
|
def report
|
@@ -32,8 +40,14 @@ module ToyRobot
|
|
32
40
|
}
|
33
41
|
end
|
34
42
|
|
43
|
+
def [](key)
|
44
|
+
report.send(:[], key)
|
45
|
+
end
|
46
|
+
|
35
47
|
private
|
36
48
|
|
49
|
+
attr_accessor :x, :y, :orientation
|
50
|
+
|
37
51
|
def step_orientation(by = 1)
|
38
52
|
orientations = [
|
39
53
|
Pose::Orientation::NORTH,
|
@@ -60,14 +74,14 @@ module ToyRobot
|
|
60
74
|
end
|
61
75
|
|
62
76
|
def increment!(coordinate, by = 1)
|
63
|
-
|
77
|
+
update_coordinate!(coordinate, by)
|
64
78
|
end
|
65
79
|
|
66
80
|
def decrement!(coordinate, by = -1)
|
67
|
-
|
81
|
+
update_coordinate!(coordinate, by)
|
68
82
|
end
|
69
83
|
|
70
|
-
def
|
84
|
+
def update_coordinate!(coordinate, by)
|
71
85
|
case coordinate
|
72
86
|
when :x
|
73
87
|
self.x = x + by
|
data/lib/toy_robot/robot.rb
CHANGED
@@ -1,41 +1,37 @@
|
|
1
|
-
require 'forwardable'
|
2
|
-
|
3
1
|
module ToyRobot
|
4
2
|
class Robot
|
5
|
-
extend Forwardable
|
6
|
-
|
7
3
|
def initialize(args)
|
8
|
-
@
|
4
|
+
@board = args[:board]
|
5
|
+
@pose = args[:pose]
|
9
6
|
end
|
10
7
|
|
11
|
-
def place(
|
12
|
-
|
8
|
+
def place(a_new_pose)
|
9
|
+
pose.mutate!(a_new_pose) if board.valid_pose?(a_new_pose)
|
10
|
+
nil
|
13
11
|
end
|
14
12
|
|
15
13
|
def move
|
16
|
-
with_placement {
|
14
|
+
with_placement { place(pose.adjacent) and nil }
|
17
15
|
end
|
18
16
|
|
19
17
|
def right
|
20
|
-
with_placement {
|
18
|
+
with_placement { pose.rotate!(90) and nil }
|
21
19
|
end
|
22
20
|
|
23
21
|
def left
|
24
|
-
with_placement {
|
22
|
+
with_placement { pose.rotate!(-90) and nil }
|
25
23
|
end
|
26
24
|
|
27
25
|
def report
|
28
|
-
with_placement {
|
26
|
+
with_placement { pose.report }
|
29
27
|
end
|
30
28
|
|
31
29
|
private
|
32
30
|
|
33
|
-
|
31
|
+
attr_reader :board, :pose
|
34
32
|
|
35
33
|
def with_placement
|
36
|
-
if
|
37
|
-
yield
|
38
|
-
end
|
34
|
+
yield if board && board.valid_pose?(pose)
|
39
35
|
end
|
40
36
|
end
|
41
37
|
end
|
data/lib/toy_robot/view.rb
CHANGED
@@ -1,22 +1,20 @@
|
|
1
1
|
module ToyRobot
|
2
|
-
View
|
2
|
+
class View
|
3
|
+
def initialize(args)
|
4
|
+
@robot = args[:robot]
|
5
|
+
@output = args[:output] || $stdout
|
6
|
+
end
|
7
|
+
|
3
8
|
def report
|
4
|
-
|
5
|
-
output.puts report_string(report) if report
|
9
|
+
output.puts format_report(robot.report)
|
6
10
|
end
|
7
11
|
|
8
12
|
private
|
9
13
|
|
10
|
-
|
11
|
-
"#{report[:x]},#{report[:y]},#{report[:orientation].upcase}"
|
12
|
-
end
|
13
|
-
|
14
|
-
def robot
|
15
|
-
args[:robot]
|
16
|
-
end
|
14
|
+
attr_reader :robot, :output
|
17
15
|
|
18
|
-
def
|
19
|
-
|
16
|
+
def format_report(report)
|
17
|
+
"#{report[:x]},#{report[:y]},#{report[:orientation].upcase}" if report
|
20
18
|
end
|
21
19
|
end
|
22
20
|
end
|
@@ -11,8 +11,8 @@ module ToyRobot
|
|
11
11
|
assert_respond_to @object, :create
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
assert_instance_of
|
14
|
+
def test_that_create_returns_a_controller
|
15
|
+
assert_instance_of Controller, @object.create(:controller)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
data/test/pose_double.rb
ADDED
data/test/test_board.rb
CHANGED
@@ -1,31 +1,24 @@
|
|
1
1
|
require_relative '../lib/toy_robot/board'
|
2
|
+
require_relative 'test_board_interface'
|
2
3
|
require 'minitest/autorun'
|
3
4
|
|
4
5
|
module ToyRobot
|
5
6
|
class BoardTest < MiniTest::Unit::TestCase
|
6
|
-
|
7
|
-
PoseDouble = Struct.new(:x, :y)
|
8
|
-
|
7
|
+
include BoardInterfaceTest
|
9
8
|
def setup
|
10
|
-
@board = Board.new(5,5)
|
9
|
+
@board = @object = Board.new(5,5)
|
11
10
|
end
|
12
11
|
|
13
12
|
def test_that_knows_a_valid_pose
|
14
|
-
|
15
|
-
|
16
|
-
assert @board.valid_pose?(pose_double)
|
13
|
+
pose = {x: 0, y: 0}
|
14
|
+
assert @board.valid_pose?(pose)
|
17
15
|
end
|
18
16
|
|
19
17
|
def test_that_knows_an_invalid_pose
|
20
18
|
[[-1,0], [0,-1], [6,0], [0,6]].each do |out_of_range|
|
21
|
-
|
22
|
-
|
23
|
-
refute @board.valid_pose?(pose_double), "Pose #{pose_double} should be invalid"
|
19
|
+
pose = {x: out_of_range[0], y: out_of_range[1]}
|
20
|
+
refute @board.valid_pose?(pose), "Pose #{pose} should be invalid"
|
24
21
|
end
|
25
22
|
end
|
26
|
-
|
27
|
-
def test_that_a_nil_pose_is_invalid
|
28
|
-
refute @board.valid_pose?(nil)
|
29
|
-
end
|
30
23
|
end
|
31
24
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'board_double'
|
2
|
+
require_relative 'test_board_interface'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
|
5
|
+
module ToyRobot
|
6
|
+
class BoardDoubleTest < MiniTest::Unit::TestCase
|
7
|
+
include BoardInterfaceTest
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@object = BoardDouble.new
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ToyRobot
|
2
|
+
module BoardInterfaceTest
|
3
|
+
def test_board_public_interface
|
4
|
+
assert_respond_to @object, :valid_pose?
|
5
|
+
end
|
6
|
+
|
7
|
+
def test_that_valid_pose_returns_nil
|
8
|
+
assert_nil @object.valid_pose?(nil)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_that_valid_pose_returns_true_or_false
|
12
|
+
assert_includes [true, false], @object.valid_pose?({})
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -2,21 +2,21 @@ require_relative '../lib/toy_robot/command/parser'
|
|
2
2
|
require 'minitest/autorun'
|
3
3
|
|
4
4
|
module ToyRobot
|
5
|
-
class
|
5
|
+
class CommandParserTest < MiniTest::Unit::TestCase
|
6
6
|
def setup
|
7
|
-
@
|
7
|
+
@parser = Command::Parser
|
8
8
|
end
|
9
9
|
|
10
10
|
def test_that_it_can_parse
|
11
|
-
refute_equal nil, @
|
11
|
+
refute_equal nil, @parser.parse('PLACE 0,0,NORTH')
|
12
12
|
end
|
13
13
|
|
14
14
|
def test_that_parsing_can_fail
|
15
|
-
assert_equal nil, @
|
15
|
+
assert_equal nil, @parser.parse('PLACE 0,0,NORTHISH')
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
all = @
|
18
|
+
def test_that_it_knows_all_parsers
|
19
|
+
all = @parser.all
|
20
20
|
|
21
21
|
assert_includes all, Command::Parser::Place
|
22
22
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module ToyRobot
|
2
|
-
module
|
3
|
-
def
|
2
|
+
module CommandParserInterfaceTest
|
3
|
+
def test_it_implement_the_command_parser_interface
|
4
4
|
assert_respond_to @object, :build_with_match
|
5
5
|
end
|
6
6
|
|
@@ -14,9 +14,9 @@ module ToyRobot
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
18
|
-
assert_equal @
|
19
|
-
@object.build_with_match(@object_valid_str).
|
17
|
+
def test_that_response_knows_msg
|
18
|
+
assert_equal @object_msg,
|
19
|
+
@object.build_with_match(@object_valid_str).msg
|
20
20
|
end
|
21
21
|
|
22
22
|
def test_that_response_knows_args
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative '../lib/toy_robot/command/parser/left'
|
2
|
+
require_relative 'test_command_parser_interface'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
|
5
|
+
module ToyRobot
|
6
|
+
class CommandParserLeftTest < MiniTest::Unit::TestCase
|
7
|
+
include CommandParserInterfaceTest
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@object = Command::Parser::Left
|
11
|
+
@object_msg = :left
|
12
|
+
@object_valid_str = 'LEFT'
|
13
|
+
@object_invalid_strs = [
|
14
|
+
'LEFT ',
|
15
|
+
'LEFTY',
|
16
|
+
'LEFT 180'
|
17
|
+
]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
|
-
require_relative '../lib/toy_robot/command/parser/
|
2
|
-
require_relative '
|
1
|
+
require_relative '../lib/toy_robot/command/parser/move'
|
2
|
+
require_relative 'test_command_parser_interface'
|
3
3
|
require 'minitest/autorun'
|
4
4
|
|
5
5
|
module ToyRobot
|
6
|
-
class
|
7
|
-
include
|
6
|
+
class CommandParserMoveTest < MiniTest::Unit::TestCase
|
7
|
+
include CommandParserInterfaceTest
|
8
8
|
|
9
9
|
def setup
|
10
10
|
@object = Command::Parser::Move
|
11
|
-
@
|
11
|
+
@object_msg = :move
|
12
12
|
@object_valid_str = 'MOVE'
|
13
13
|
@object_invalid_strs = [
|
14
14
|
'MOVE ',
|