another_toy_robot 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/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +21 -0
- data/README.md +79 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bin/toy_robot +4 -0
- data/lib/toy_robot/arena.rb +28 -0
- data/lib/toy_robot/client.rb +24 -0
- data/lib/toy_robot/command.rb +63 -0
- data/lib/toy_robot/position.rb +64 -0
- data/lib/toy_robot/robot.rb +23 -0
- data/lib/toy_robot/version.rb +3 -0
- data/lib/toy_robot.rb +19 -0
- data/toy_robot.gemspec +25 -0
- metadata +64 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 13301a7680a25a2891de7baf8406ca3e258109c1
|
4
|
+
data.tar.gz: 4df6c3e6ff61ea1acf1a6fcb691dcce15f74fcbc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4273e039a8a3d1c91d6c3f8990fdcf935247637f504fd70482ff1896c0d1e9209dcab2a8c78e0120765ca3ffca7055f09dcedd84a9bb6c1b8c65e6550d81667c
|
7
|
+
data.tar.gz: 409cc9a8252052dfad782e6a659268a75f72327a9cbecc47e3ff56f3550324d84e8739efd72e748739376a9e6811be9db5fbfc22d2ff34b5ed6944fbc2061aee
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gem "pry"
|
4
|
+
gem "rspec"
|
5
|
+
gem "factory_girl", "~> 4.0"
|
6
|
+
|
7
|
+
group :test do
|
8
|
+
gem 'simplecov', require: false
|
9
|
+
gem "codeclimate-test-reporter", "~> 1.0.0"
|
10
|
+
end
|
11
|
+
|
12
|
+
# Specify your gem's dependencies in toy_robot.gemspec
|
13
|
+
gemspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 drzel
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
[](https://codeclimate.com/github/drzel/toy_robot)
|
2
|
+
[](https://codeclimate.com/github/drzel/toy_robot/coverage)
|
3
|
+
|
4
|
+
#Toy Robot Simulator
|
5
|
+
|
6
|
+
##Description
|
7
|
+
- The application is a simulation of a toy robot moving on a square tabletop,
|
8
|
+
of dimensions 5 units x 5 units.
|
9
|
+
- There are no other obstructions on the table surface.
|
10
|
+
- The robot is free to roam around the surface of the table, but must be
|
11
|
+
prevented from falling to destruction. Any movement that would result in the
|
12
|
+
robot falling from the table must be prevented, however further valid
|
13
|
+
movement commands must still be allowed.
|
14
|
+
- Create an application that can read in commands of the following form:
|
15
|
+
|
16
|
+
````
|
17
|
+
PLACE X,Y,F
|
18
|
+
MOVE
|
19
|
+
LEFT
|
20
|
+
RIGHT
|
21
|
+
REPORT
|
22
|
+
````
|
23
|
+
|
24
|
+
- PLACE will put the toy robot on the table in position X,Y and facing NORTH,
|
25
|
+
SOUTH, EAST or WEST.
|
26
|
+
- The origin (0,0) can be considered to be the SOUTH WEST most corner.
|
27
|
+
- The first valid command to the robot is a PLACE command, after that, any
|
28
|
+
sequence of commands may be issued, in any order, including another PLACE
|
29
|
+
command. The application should discard all commands in the sequence until a
|
30
|
+
valid PLACE command has been executed.
|
31
|
+
- MOVE will move the toy robot one unit forward in the direction it is currently
|
32
|
+
facing.
|
33
|
+
- LEFT and RIGHT will rotate the robot 90 degrees in the specified direction
|
34
|
+
without changing the position of the robot.
|
35
|
+
- REPORT will announce the X,Y and F of the robot. This can be in any form, but
|
36
|
+
standard output is sufficient.
|
37
|
+
- A robot that is not on the table can choose the ignore the MOVE, LEFT, RIGHT
|
38
|
+
and REPORT commands.
|
39
|
+
- Input can be from a file, or from standard input, as the developer chooses.
|
40
|
+
- Provide test data to exercise the application.
|
41
|
+
|
42
|
+
##Constraints
|
43
|
+
The toy robot must not fall off the table during movement. This also includes
|
44
|
+
the initial placement of the toy robot. Any move that would cause the robot
|
45
|
+
to fall must be ignored.
|
46
|
+
|
47
|
+
##Example Input and Output
|
48
|
+
a)
|
49
|
+
````
|
50
|
+
PLACE 0,0,NORTH
|
51
|
+
MOVE
|
52
|
+
REPORT
|
53
|
+
````
|
54
|
+
Output: ````0,1,NORTH````
|
55
|
+
|
56
|
+
b)
|
57
|
+
````
|
58
|
+
PLACE 0,0,NORTH
|
59
|
+
LEFT
|
60
|
+
REPORT
|
61
|
+
````
|
62
|
+
Output: ````0,0,WEST````
|
63
|
+
|
64
|
+
c)
|
65
|
+
````
|
66
|
+
PLACE 1,2,EAST
|
67
|
+
MOVE
|
68
|
+
MOVE
|
69
|
+
LEFT
|
70
|
+
MOVE
|
71
|
+
REPORT
|
72
|
+
````
|
73
|
+
Output: ````3,3,NORTH````
|
74
|
+
|
75
|
+
##Deliverables
|
76
|
+
The source files, the test data and any test code.
|
77
|
+
|
78
|
+
It is not required to provide any graphical output showing the movement of the
|
79
|
+
toy robot.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "toy_robot"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/bin/toy_robot
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
class Arena
|
2
|
+
attr_accessor :width, :height
|
3
|
+
|
4
|
+
def initialize(width:, height:)
|
5
|
+
@width = width
|
6
|
+
@height = height
|
7
|
+
end
|
8
|
+
|
9
|
+
def inbounds?(x, y)
|
10
|
+
x.between?(0, max_x) && y.between?(0, max_y)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def max_x
|
16
|
+
width - 1
|
17
|
+
end
|
18
|
+
|
19
|
+
def max_y
|
20
|
+
height - 1
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class NullArena
|
25
|
+
def inbounds?(*)
|
26
|
+
true
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Client
|
2
|
+
def initialize
|
3
|
+
@robot = Robot.new
|
4
|
+
@table = Arena.new width: 5, height: 5
|
5
|
+
end
|
6
|
+
|
7
|
+
def instruction(input)
|
8
|
+
command = case input
|
9
|
+
when /place\s+(\d+,\s*){2}[nesw]/
|
10
|
+
PlaceCommand.new robot: @robot, arena: @table, command: input
|
11
|
+
when "move"
|
12
|
+
MoveCommand.new robot: @robot
|
13
|
+
when "left"
|
14
|
+
LeftCommand.new robot: @robot
|
15
|
+
when "right"
|
16
|
+
RightCommand.new robot: @robot
|
17
|
+
when "report"
|
18
|
+
ReportCommand.new robot: @robot
|
19
|
+
else
|
20
|
+
InvalidCommand.new
|
21
|
+
end
|
22
|
+
command.execute
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class PlaceCommand
|
2
|
+
def initialize(robot:, arena: NullArena.new, command:)
|
3
|
+
@robot = robot
|
4
|
+
@arena = arena
|
5
|
+
@params = command[/\s.*/].delete(" ").split(",")
|
6
|
+
end
|
7
|
+
|
8
|
+
def execute
|
9
|
+
position = NullPosition.new arena: @arena
|
10
|
+
position = position.go_to(x: @params[0].to_i,
|
11
|
+
y: @params[1].to_i,
|
12
|
+
direction: @params[2].to_sym)
|
13
|
+
@robot.position = position
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class MoveCommand
|
18
|
+
def initialize(robot:)
|
19
|
+
@robot = robot
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute
|
23
|
+
@robot.move
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class LeftCommand
|
28
|
+
def initialize(robot:)
|
29
|
+
@robot = robot
|
30
|
+
end
|
31
|
+
|
32
|
+
def execute
|
33
|
+
@robot.left
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class RightCommand
|
38
|
+
def initialize(robot:)
|
39
|
+
@robot = robot
|
40
|
+
end
|
41
|
+
|
42
|
+
def execute
|
43
|
+
@robot.right
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class ReportCommand
|
48
|
+
def initialize(robot:)
|
49
|
+
@robot = robot
|
50
|
+
end
|
51
|
+
|
52
|
+
def execute
|
53
|
+
@robot.report
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class InvalidCommand
|
58
|
+
def intialize; end
|
59
|
+
|
60
|
+
def execute
|
61
|
+
puts "Invalid command"
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class Position
|
2
|
+
attr_accessor :arena
|
3
|
+
|
4
|
+
def initialize(arena: NullArena.new, **args)
|
5
|
+
@arena = arena
|
6
|
+
post_initialize args
|
7
|
+
end
|
8
|
+
|
9
|
+
def go_to(x: @x_coord, y: @y_coord, direction: @direction)
|
10
|
+
if @arena.inbounds? x, y
|
11
|
+
RealPosition.new x: x, y: y, direction: direction, arena: @arena
|
12
|
+
else
|
13
|
+
self
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class RealPosition < Position
|
19
|
+
attr_accessor :x_coord, :y_coord, :direction
|
20
|
+
|
21
|
+
ROTATION = { left: -1, right: 1 }.freeze
|
22
|
+
DISPLACEMENT = { n: { x: 0, y: 1 },
|
23
|
+
e: { x: 1, y: 0 },
|
24
|
+
s: { x: 0, y: -1 },
|
25
|
+
w: { x: -1, y: 0 } }.freeze
|
26
|
+
|
27
|
+
def post_initialize(x: 0, y: 0, direction: :n)
|
28
|
+
@x_coord = x
|
29
|
+
@y_coord = y
|
30
|
+
@direction = direction
|
31
|
+
end
|
32
|
+
|
33
|
+
def advance
|
34
|
+
new_x = @x_coord + DISPLACEMENT[@direction][:x]
|
35
|
+
new_y = @y_coord + DISPLACEMENT[@direction][:y]
|
36
|
+
go_to x: new_x, y: new_y
|
37
|
+
end
|
38
|
+
|
39
|
+
def turn(hand_side)
|
40
|
+
compass = DISPLACEMENT.keys
|
41
|
+
index = (compass.find_index(@direction) + ROTATION[hand_side]) % 4
|
42
|
+
go_to direction: compass[index]
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
"#{@x_coord}, #{@y_coord}, #{@direction}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class NullPosition < Position
|
51
|
+
def post_initialize(*); end
|
52
|
+
|
53
|
+
def advance
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def turn(*)
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_s
|
62
|
+
"No position"
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Robot
|
2
|
+
attr_accessor :position
|
3
|
+
|
4
|
+
def initialize(position: NullPosition.new)
|
5
|
+
@position = position
|
6
|
+
end
|
7
|
+
|
8
|
+
def move
|
9
|
+
@position = @position.advance
|
10
|
+
end
|
11
|
+
|
12
|
+
def left
|
13
|
+
@position = @position.turn :left
|
14
|
+
end
|
15
|
+
|
16
|
+
def right
|
17
|
+
@position = @position.turn :right
|
18
|
+
end
|
19
|
+
|
20
|
+
def report
|
21
|
+
puts @position.to_s
|
22
|
+
end
|
23
|
+
end
|
data/lib/toy_robot.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "pry"
|
2
|
+
require "toy_robot/client"
|
3
|
+
require "toy_robot/robot"
|
4
|
+
require "toy_robot/arena"
|
5
|
+
require "toy_robot/command"
|
6
|
+
require "toy_robot/position"
|
7
|
+
|
8
|
+
module ToyRobot
|
9
|
+
def self.main
|
10
|
+
client = Client.new
|
11
|
+
|
12
|
+
loop do
|
13
|
+
print "Input command: "
|
14
|
+
input = gets.strip
|
15
|
+
break if input == "exit"
|
16
|
+
client.instruction input
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/toy_robot.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'toy_robot/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "another_toy_robot"
|
8
|
+
spec.version = ToyRobot::VERSION
|
9
|
+
spec.date = "2016-11-27"
|
10
|
+
spec.authors = "Sheldon J. Johnson"
|
11
|
+
spec.email = "sheldon.j.johnson@outlook.com"
|
12
|
+
spec.homepage = "https://github.com/drzel/toy_robot"
|
13
|
+
spec.summary = "Another toy robot demonstration app"
|
14
|
+
spec.description = "The application is a simulation of a toy robot " \
|
15
|
+
"moving on a square tabletop. It is an example of a well tested, object " \
|
16
|
+
"oriented design, employing the command design pattern."
|
17
|
+
spec.license = "MIT"
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
20
|
+
f.match(%r{^(test|spec|features)/})
|
21
|
+
end
|
22
|
+
|
23
|
+
spec.bindir = "bin"
|
24
|
+
spec.executables << "toy_robot"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: another_toy_robot
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sheldon J. Johnson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-11-27 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: The application is a simulation of a toy robot moving on a square tabletop.
|
14
|
+
It is an example of a well tested, object oriented design, employing the command
|
15
|
+
design pattern.
|
16
|
+
email: sheldon.j.johnson@outlook.com
|
17
|
+
executables:
|
18
|
+
- toy_robot
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- ".gitignore"
|
23
|
+
- ".rspec"
|
24
|
+
- ".travis.yml"
|
25
|
+
- Gemfile
|
26
|
+
- LICENSE.txt
|
27
|
+
- README.md
|
28
|
+
- Rakefile
|
29
|
+
- bin/console
|
30
|
+
- bin/setup
|
31
|
+
- bin/toy_robot
|
32
|
+
- lib/toy_robot.rb
|
33
|
+
- lib/toy_robot/arena.rb
|
34
|
+
- lib/toy_robot/client.rb
|
35
|
+
- lib/toy_robot/command.rb
|
36
|
+
- lib/toy_robot/position.rb
|
37
|
+
- lib/toy_robot/robot.rb
|
38
|
+
- lib/toy_robot/version.rb
|
39
|
+
- toy_robot.gemspec
|
40
|
+
homepage: https://github.com/drzel/toy_robot
|
41
|
+
licenses:
|
42
|
+
- MIT
|
43
|
+
metadata: {}
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
requirements: []
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 2.5.1
|
61
|
+
signing_key:
|
62
|
+
specification_version: 4
|
63
|
+
summary: Another toy robot demonstration app
|
64
|
+
test_files: []
|