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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +2 -2
  3. data/README.md +166 -10
  4. data/lib/toy_robot/application.rb +1 -13
  5. data/lib/toy_robot/board.rb +1 -1
  6. data/lib/toy_robot/command/parser.rb +6 -3
  7. data/lib/toy_robot/command/parser/base.rb +4 -25
  8. data/lib/toy_robot/command/parser/left.rb +12 -0
  9. data/lib/toy_robot/command/parser/move.rb +12 -0
  10. data/lib/toy_robot/command/parser/place.rb +3 -4
  11. data/lib/toy_robot/command/parser/report.rb +12 -0
  12. data/lib/toy_robot/command/parser/right.rb +12 -0
  13. data/lib/toy_robot/controller.rb +32 -0
  14. data/lib/toy_robot/factory.rb +6 -18
  15. data/lib/toy_robot/pose.rb +19 -5
  16. data/lib/toy_robot/robot.rb +11 -15
  17. data/lib/toy_robot/view.rb +10 -12
  18. data/test/board_double.rb +5 -0
  19. data/test/integration/test_factory.rb +2 -2
  20. data/test/integration/test_toy_robot.rb +1 -1
  21. data/test/pose_double.rb +23 -0
  22. data/test/test_board.rb +7 -14
  23. data/test/test_board_double.rb +13 -0
  24. data/test/test_board_interface.rb +15 -0
  25. data/test/{test_command_matcher.rb → test_command_parser.rb} +6 -6
  26. data/test/{test_command_matcher_interface.rb → test_command_parser_interface.rb} +5 -5
  27. data/test/test_command_parser_left.rb +20 -0
  28. data/test/{test_command_matcher_move.rb → test_command_parser_move.rb} +5 -5
  29. data/test/{test_command_matcher_place.rb → test_command_parser_place.rb} +10 -10
  30. data/test/{test_command_matcher_report.rb → test_command_parser_report.rb} +5 -5
  31. data/test/test_command_parser_right.rb +20 -0
  32. data/test/test_controller.rb +64 -0
  33. data/test/test_pose.rb +16 -20
  34. data/test/test_pose_double.rb +15 -0
  35. data/test/test_pose_interface.rb +26 -0
  36. data/test/test_reporter_interface.rb +13 -1
  37. data/test/test_robot.rb +70 -27
  38. data/toyrobot.gemspec +1 -1
  39. metadata +35 -26
  40. data/lib/toy_robot/command/base.rb +0 -5
  41. data/lib/toy_robot/command/token.rb +0 -11
  42. data/lib/toy_robot/placement.rb +0 -34
  43. data/lib/toy_robot/robot_controller.rb +0 -35
  44. data/test/test_command.rb +0 -22
  45. data/test/test_command_matcher_left.rb +0 -20
  46. data/test/test_command_matcher_right.rb +0 -20
  47. data/test/test_placement.rb +0 -94
  48. 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
@@ -1,6 +1,5 @@
1
- require_relative 'robot_controller'
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
- RobotControllerFactory.create(opts)
14
+ ControllerFactory.create(opts)
16
15
  end
17
16
  end
18
17
 
19
- module RobotControllerFactory
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::RobotController.new(
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
- ToyRobot::Placement.new(
52
+
53
+ ToyRobot::Robot.new(
66
54
  board: board,
67
55
  pose: pose
68
56
  )
@@ -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
- update!(coordinate, by)
77
+ update_coordinate!(coordinate, by)
64
78
  end
65
79
 
66
80
  def decrement!(coordinate, by = -1)
67
- update!(coordinate, by)
81
+ update_coordinate!(coordinate, by)
68
82
  end
69
83
 
70
- def update!(coordinate, by)
84
+ def update_coordinate!(coordinate, by)
71
85
  case coordinate
72
86
  when :x
73
87
  self.x = x + by
@@ -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
- @placement = args[:placement]
4
+ @board = args[:board]
5
+ @pose = args[:pose]
9
6
  end
10
7
 
11
- def place(*args)
12
- placement.update(*args)
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 { placement.advance }
14
+ with_placement { place(pose.adjacent) and nil }
17
15
  end
18
16
 
19
17
  def right
20
- with_placement { placement.rotate(90) }
18
+ with_placement { pose.rotate!(90) and nil }
21
19
  end
22
20
 
23
21
  def left
24
- with_placement { placement.rotate(-90) }
22
+ with_placement { pose.rotate!(-90) and nil }
25
23
  end
26
24
 
27
25
  def report
28
- with_placement { placement.report }
26
+ with_placement { pose.report }
29
27
  end
30
28
 
31
29
  private
32
30
 
33
- attr_accessor :placement
31
+ attr_reader :board, :pose
34
32
 
35
33
  def with_placement
36
- if placement.on_board?
37
- yield
38
- end
34
+ yield if board && board.valid_pose?(pose)
39
35
  end
40
36
  end
41
37
  end
@@ -1,22 +1,20 @@
1
1
  module ToyRobot
2
- View = Struct.new(:args) do
2
+ class View
3
+ def initialize(args)
4
+ @robot = args[:robot]
5
+ @output = args[:output] || $stdout
6
+ end
7
+
3
8
  def report
4
- report = robot.report
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
- def report_string(report)
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 output
19
- args[:output] || $stdout
16
+ def format_report(report)
17
+ "#{report[:x]},#{report[:y]},#{report[:orientation].upcase}" if report
20
18
  end
21
19
  end
22
20
  end
@@ -0,0 +1,5 @@
1
+ class BoardDouble
2
+ def valid_pose?(pose)
3
+ pose && true
4
+ end
5
+ end
@@ -11,8 +11,8 @@ module ToyRobot
11
11
  assert_respond_to @object, :create
12
12
  end
13
13
 
14
- def test_that_create_returns_a_robot_controller
15
- assert_instance_of RobotController, @object.create(:controller)
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
@@ -3,7 +3,7 @@ require 'minitest/autorun'
3
3
  module ToyRobot
4
4
  class ToyRobotTest < MiniTest::Unit::TestCase
5
5
  def test_that_it_is_executable
6
- assert system('[ -x bin/toyrobots ]')
6
+ assert system('[ -x bin/toyrobot ]')
7
7
  end
8
8
  end
9
9
  end
@@ -0,0 +1,23 @@
1
+ class PoseDouble
2
+ def mutate!(_ = nil)
3
+ self
4
+ end
5
+
6
+ def adjacent
7
+ self.class.new
8
+ end
9
+
10
+ def rotate!(_)
11
+ self
12
+ end
13
+
14
+ def report
15
+ {
16
+ x: 0,
17
+ y: 0,
18
+ orientation: :facing
19
+ }
20
+ end
21
+
22
+ def [](_); end;
23
+ end
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
- pose_double = PoseDouble.new(0,0)
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
- pose_double = PoseDouble.new(*out_of_range)
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 CommandMatcherTest < MiniTest::Unit::TestCase
5
+ class CommandParserTest < MiniTest::Unit::TestCase
6
6
  def setup
7
- @matcher = Command::Parser
7
+ @parser = Command::Parser
8
8
  end
9
9
 
10
10
  def test_that_it_can_parse
11
- refute_equal nil, @matcher.parse('PLACE 0,0,NORTH')
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, @matcher.parse('PLACE 0,0,NORTHISH')
15
+ assert_equal nil, @parser.parse('PLACE 0,0,NORTHISH')
16
16
  end
17
17
 
18
- def test_that_it_knows_all_matchers
19
- all = @matcher.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 CommandMatcherInterfaceTest
3
- def test_it_implement_the_command_matcher_interface
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 test_that_response_knows_token
18
- assert_equal @object_token,
19
- @object.build_with_match(@object_valid_str).token
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/base'
2
- require_relative 'test_command_matcher_interface'
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 CommandMatcherMoveTest < MiniTest::Unit::TestCase
7
- include CommandMatcherInterfaceTest
6
+ class CommandParserMoveTest < MiniTest::Unit::TestCase
7
+ include CommandParserInterfaceTest
8
8
 
9
9
  def setup
10
10
  @object = Command::Parser::Move
11
- @object_token = Command::Token::MOVE
11
+ @object_msg = :move
12
12
  @object_valid_str = 'MOVE'
13
13
  @object_invalid_strs = [
14
14
  'MOVE ',