rubbot 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d62ad256e0b37caeff3ba3c5d4006ad13c769279
4
+ data.tar.gz: c58dafd156d9978418bd54263030999054b1b305
5
+ SHA512:
6
+ metadata.gz: c51d1bd20da054489b1fd78317160f8da079bd6d53c7a73ce85bf53d1d4ced15860e7d861191bb6f92846641c17ed7612e4b46c4de7938f7b5fbd29c9b8a8d78
7
+ data.tar.gz: 6e8dc052b02f7d688b33e4c31ee1070437e6514907008b111164048a36049abf0166127d7f652dbc196368937dfe573a32b4d15c0927d423568ea74276789547
data/bin/rubbot ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubbot'
4
+
5
+ puts "Welcome to Rubbot!"
6
+ puts "------------------"
7
+
8
+ # Init and run 'Rubbot'
9
+ rubbot = Rubbot.new(Grid.new(5, 5)) and rubbot.start
10
+
data/lib/grid.rb ADDED
@@ -0,0 +1,2 @@
1
+ class Grid < Struct.new(:width, :height)
2
+ end
data/lib/position.rb ADDED
@@ -0,0 +1,49 @@
1
+ class Position < Struct.new(:x, :y, :orientation)
2
+ NORTH = :north
3
+ EAST = :east
4
+ SOUTH = :south
5
+ WEST = :west
6
+
7
+ def advance
8
+ case orientation
9
+ when NORTH
10
+ Position.new(x, y + 1, orientation)
11
+ when EAST
12
+ Position.new(x + 1, y, orientation)
13
+ when SOUTH
14
+ Position.new(x, y - 1, orientation)
15
+ when WEST
16
+ Position.new(x - 1, y, orientation)
17
+ else
18
+ self
19
+ end
20
+ end
21
+
22
+ def left
23
+ rotate -1
24
+ end
25
+
26
+ def right
27
+ rotate 1
28
+ end
29
+
30
+ def valid?(grid)
31
+ (0...grid.width).include?(x) && (0...grid.height).include?(y)
32
+ end
33
+
34
+ def to_s
35
+ "#{x},#{y},#{orientation.to_s.upcase}"
36
+ end
37
+
38
+ private
39
+
40
+ def rotate(by)
41
+ facing_index = orientations.index(orientation)
42
+ facing = orientations.rotate(facing_index).rotate(by).first
43
+ Position.new(x, y, facing)
44
+ end
45
+
46
+ def orientations
47
+ [NORTH, EAST, SOUTH, WEST]
48
+ end
49
+ end
data/lib/robot.rb ADDED
@@ -0,0 +1,44 @@
1
+ require_relative 'grid'
2
+ require_relative 'position'
3
+
4
+ class Robot
5
+ attr_reader :position
6
+
7
+ UNPLACED_NOTICE = "Robot should be placed first."
8
+
9
+ def initialize(grid)
10
+ @grid = grid
11
+ @position = Position.new(nil, nil, nil)
12
+ end
13
+
14
+ def place(position)
15
+ update_position position
16
+ end
17
+
18
+ def move
19
+ update_position @position.advance
20
+ end
21
+
22
+ def rotate_left
23
+ update_position @position.left
24
+ end
25
+
26
+ def rotate_right
27
+ update_position @position.right
28
+ end
29
+
30
+ def report
31
+ return UNPLACED_NOTICE unless placed?
32
+ @position.to_s
33
+ end
34
+
35
+ def placed?
36
+ @position.valid? @grid
37
+ end
38
+
39
+ private
40
+
41
+ def update_position(new_position)
42
+ @position = new_position if new_position.valid? @grid
43
+ end
44
+ end
data/lib/rubbot.rb ADDED
@@ -0,0 +1,29 @@
1
+ # Trap early interrupts
2
+ Signal.trap("INT") do
3
+ puts "Bye-bye!"
4
+ exit 1
5
+ end
6
+
7
+ require_relative 'rubbot_cli'
8
+ require_relative 'robot'
9
+
10
+ class Rubbot
11
+ def initialize(grid, options = {})
12
+ # Optionally accept redefined standard I/O
13
+ @stdin = options.fetch(:stdin) { STDIN }
14
+ @stdout = options.fetch(:stdout) { STDOUT }
15
+ @robot = Robot.new(grid)
16
+ end
17
+
18
+ def start
19
+ while input = @stdin.gets
20
+ begin
21
+ cmd = Commands::parse(input)
22
+ cmd.execute(@robot, output: @stdout)
23
+ rescue Commands::NoCommandError, RobotInterface::Place::InvalidFormatError => e
24
+ @stdout << "Invalid input: #{e.message}\n"
25
+ @stdout << RobotInterface::Help::print_help
26
+ end
27
+ end
28
+ end
29
+ end
data/lib/rubbot_cli.rb ADDED
@@ -0,0 +1,98 @@
1
+ module RobotInterface
2
+ class Command
3
+ NoArgumentsError = Class.new(Exception)
4
+
5
+ def initialize(args = [])
6
+ @args = args
7
+ end
8
+ end
9
+
10
+ class Place < Command
11
+ FORMAT = /-?\d+,-?\d+,(NORTH|EAST|SOUTH|WEST)\s*$/mi
12
+
13
+ InvalidFormatError = Class.new(Exception)
14
+
15
+ def initialize(args)
16
+ super
17
+ validate_format args
18
+ @x = args.shift.to_i
19
+ @y = args.shift.to_i
20
+ @orientation = Position.const_get(args.shift.upcase)
21
+ end
22
+
23
+ def execute(robot, options = {})
24
+ robot.place Position.new(@x, @y, @orientation)
25
+ end
26
+
27
+ private
28
+
29
+ def validate_format(argv)
30
+ if args = argv.join(',') and args.match(FORMAT).nil?
31
+ raise InvalidFormatError.new "'PLACE' format is invalid : '#{args}'"
32
+ end
33
+ end
34
+ end
35
+
36
+ class Move < Command
37
+ def execute(robot, options = {}) robot.move end
38
+ end
39
+
40
+ class Left < Command
41
+ def execute(robot, options = {}) robot.rotate_left end
42
+ end
43
+
44
+ class Right < Command
45
+ def execute(robot, options = {}) robot.rotate_right end
46
+ end
47
+
48
+ class Report < Command
49
+ def execute(robot, options = {})
50
+ output = options.fetch(:output)
51
+ output << robot.report + "\n"
52
+ end
53
+ end
54
+
55
+ class Help < Command
56
+ def execute(robot, options = {})
57
+ options.fetch(:output) << self.class::print_help
58
+ end
59
+
60
+ def self.print_help
61
+ help_message = <<-END.gsub(/^ {8}/, '')
62
+ Robot Commands:
63
+ ------------------------------------------------------
64
+ PLACE Places the robot at X, Y facing an orientation
65
+ Orientations accepted: NORTH, EAST, SOUTH, WEST
66
+ Format: 'X,Y,ORIENTATION'. i.e.: '2,3,NORTH'
67
+ MOVE Moves the robot in current direction
68
+ LEFT Turns the robot left
69
+ RIGHT Turns the robot right
70
+ REPORT Prints current state of the robot
71
+ HELP Prints this help message
72
+ ------------------------------------------------------
73
+ END
74
+ end
75
+ end
76
+ end
77
+
78
+ module Commands
79
+ # Map input instructions to Robot actions
80
+ COMMANDS_MAP = {
81
+ "PLACE" => RobotInterface::Place,
82
+ "MOVE" => RobotInterface::Move,
83
+ "LEFT" => RobotInterface::Left,
84
+ "RIGHT" => RobotInterface::Right,
85
+ "REPORT" => RobotInterface::Report,
86
+ "HELP" => RobotInterface::Help
87
+ }
88
+
89
+ NoCommandError = Class.new(Exception)
90
+
91
+ def self.parse(input)
92
+ cmd, args = input.split
93
+ args = String(args).split(",")
94
+ cmd_class = COMMANDS_MAP[String(cmd).upcase]
95
+ raise NoCommandError.new "'#{cmd}'' is undefined." unless cmd_class
96
+ cmd_class.new args
97
+ end
98
+ end
data/lib/utils.rb ADDED
@@ -0,0 +1,21 @@
1
+ module Utils
2
+ # Standard input simulator
3
+ class StdinSimulator
4
+ attr_reader :input_queue
5
+
6
+ def initialize
7
+ # Represent an input queue as an array
8
+ @input_queue = []
9
+ end
10
+
11
+ def <<(input)
12
+ # Add an element to the input queue
13
+ @input_queue << input
14
+ end
15
+
16
+ def gets
17
+ # Dequeue the first element in the queue
18
+ @input_queue.shift
19
+ end
20
+ end
21
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubbot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Stankevich
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: turnip
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Toy Robot simulation implementation in Ruby.
70
+ email: standeo@gmail.com
71
+ executables:
72
+ - rubbot
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - bin/rubbot
77
+ - lib/grid.rb
78
+ - lib/position.rb
79
+ - lib/robot.rb
80
+ - lib/rubbot.rb
81
+ - lib/rubbot_cli.rb
82
+ - lib/utils.rb
83
+ homepage: http://rubygems.org/gems/rubbot
84
+ licenses:
85
+ - MIT
86
+ metadata: {}
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - '>='
94
+ - !ruby/object:Gem::Version
95
+ version: 2.0.0
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 2.2.2
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: Toy Robot simulation.
107
+ test_files: []