rubbot 0.1.0
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 +7 -0
- data/bin/rubbot +10 -0
- data/lib/grid.rb +2 -0
- data/lib/position.rb +49 -0
- data/lib/robot.rb +44 -0
- data/lib/rubbot.rb +29 -0
- data/lib/rubbot_cli.rb +98 -0
- data/lib/utils.rb +21 -0
- metadata +107 -0
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
data/lib/grid.rb
ADDED
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: []
|