robert2d-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 +15 -0
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/.rubocop.yml +7 -0
- data/.ruby-version +1 -0
- data/.travis.yml +14 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +99 -0
- data/Guardfile +13 -0
- data/README.md +33 -0
- data/Rakefile +15 -0
- data/bin/robot +8 -0
- data/instructions.txt +61 -0
- data/lib/robot.rb +95 -0
- data/lib/robot/command_centre.rb +46 -0
- data/lib/robot/matrix.rb +53 -0
- data/lib/robot/table.rb +29 -0
- data/lib/robot/version.rb +3 -0
- data/robert2d-robot.gemspec +28 -0
- data/spec/lib/robot/command_centre_spec.rb +90 -0
- data/spec/lib/robot/matrix_spec.rb +18 -0
- data/spec/lib/robot/table_spec.rb +54 -0
- data/spec/lib/robot_spec.rb +151 -0
- data/spec/spec_helper.rb +15 -0
- data/test_data.txt +20 -0
- metadata +186 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
!binary "U0hBMQ==":
|
|
3
|
+
metadata.gz: !binary |-
|
|
4
|
+
NWJhMzE5NDQ2Mjk2ZDI2MzFhOTQ5NzRjYmMwMWVkOWRjODIzOWU1Nw==
|
|
5
|
+
data.tar.gz: !binary |-
|
|
6
|
+
MDY3MzFmYTQ1YTVlYzZiYTgzYTdkMWQ4ODljOTYyNGRjYmY5N2M4ZQ==
|
|
7
|
+
SHA512:
|
|
8
|
+
metadata.gz: !binary |-
|
|
9
|
+
YTMwNTgyZDlmYjJkNTMwNDdkYjhjNjYyNjEzMDllZDUxNmFiNzA0ODI0NmVh
|
|
10
|
+
OGFjMjIxNDg4YzI3Mzc2MDU1NWU3NzRhNDQxMmRmZTEzYTc1OWU5YzkxYzVi
|
|
11
|
+
ZjMxZjhlMTBjMjIzYjE5YjM0NzMxMmZjNmE2ODFmZDk5YTJhYmI=
|
|
12
|
+
data.tar.gz: !binary |-
|
|
13
|
+
YWQ4ZDcwZWUzZGU2ZjYwMjU0YThiNTk1MWUyNDgzOTVhZmQzYmRlYzZlYzE0
|
|
14
|
+
MWIwMjYzNGVhYTlkY2E5ZDY4NzlhN2FlNTkwYzM5MzY2ZmQ5ODM1NzE2NTI2
|
|
15
|
+
Mzc3MzFjNDVjMzY1YjMyNzBhNDg4NzY1MTg3OTdjYzUwNGU5MjE=
|
data/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
coverage
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ruby-2.1.2
|
data/.travis.yml
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
language: ruby
|
|
2
|
+
rvm:
|
|
3
|
+
- 2.0
|
|
4
|
+
- 2.1
|
|
5
|
+
- 2.2
|
|
6
|
+
deploy:
|
|
7
|
+
provider: rubygems
|
|
8
|
+
api_key:
|
|
9
|
+
secure: GBnhPCF3UiTHXVjmVl/U4LOtRYKBg3iluB2YYWZuBt8LPRSdi41VI6TEVhJ9S7XpJQhmt9Nq3PGr2b74fqmBGAmSAaCKfnHHLrc5SqKdzc0zd9h5VORHGmUJWp/w1Qq/96fnpMfbNqlBIdAs1JaXVuwV0H8KAeTRASzLNjfahoeZR1uWzKLsvgHmJ17qAC/v3mZBfaYY6nnf1GBOs9N6WebaR/MC8SvTxmiLldl/QVuMUdiSJURlJ0dJnHMLq9P1LB0t4ECNLmC7hNKfnTJ3+CPq5Ow7go3Yt1/46liaa0edkXja05VHaBijEQColQqNkjfxL/Xb/n/QnHGIcZ4Au961Nw57/CZLmJ/U6bRXjamtkodKI8eYAS/3bAdVHr/266ZAHXj5jGqzjpIPqDueuOAR+b1iNlyCw5kKEcm2plPLIxslUmrZIPH4VHcPHvXcal46AX6BH399Mv2RZ9iyxyTZlrPQErl+urN8Gu+Zp2kmjtaA5QrUwaS50uj8eRL/tSz7mtrQn/2lw6JPcB1tzla5LpslDD39OZFa5Ejs8vNzbrYpSda5IY1bBjpqZ+O/3T1s54bqVNxWTLiGLXwWnexLldc6L5u+fgsUK0saQ8KlUQtSIVW+iVcVcWBhgkFN522S8EofF79AX2MtVJkw7679YywuLAplPbLyreunIsk=
|
|
10
|
+
gem: robert2d-robot
|
|
11
|
+
gemspec: robert2d-robot.gemspec
|
|
12
|
+
on:
|
|
13
|
+
tags: true
|
|
14
|
+
repo: robert2d/robot
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
robert2d-robot (0.1.0)
|
|
5
|
+
|
|
6
|
+
GEM
|
|
7
|
+
remote: https://rubygems.org/
|
|
8
|
+
specs:
|
|
9
|
+
ast (2.0.0)
|
|
10
|
+
astrolabe (1.3.1)
|
|
11
|
+
parser (~> 2.2)
|
|
12
|
+
codeclimate-test-reporter (0.2.0)
|
|
13
|
+
simplecov (>= 0.7.1, < 1.0.0)
|
|
14
|
+
coderay (1.1.0)
|
|
15
|
+
diff-lcs (1.2.5)
|
|
16
|
+
docile (1.1.5)
|
|
17
|
+
ffi (1.9.10)
|
|
18
|
+
formatador (0.2.5)
|
|
19
|
+
guard (2.12.8)
|
|
20
|
+
formatador (>= 0.2.4)
|
|
21
|
+
listen (>= 2.7, <= 4.0)
|
|
22
|
+
lumberjack (~> 1.0)
|
|
23
|
+
nenv (~> 0.1)
|
|
24
|
+
notiffany (~> 0.0)
|
|
25
|
+
pry (>= 0.9.12)
|
|
26
|
+
shellany (~> 0.0)
|
|
27
|
+
thor (>= 0.18.1)
|
|
28
|
+
guard-compat (1.2.1)
|
|
29
|
+
guard-rspec (4.6.2)
|
|
30
|
+
guard (~> 2.1)
|
|
31
|
+
guard-compat (~> 1.1)
|
|
32
|
+
rspec (>= 2.99.0, < 4.0)
|
|
33
|
+
json (1.8.3)
|
|
34
|
+
listen (3.0.2)
|
|
35
|
+
rb-fsevent (>= 0.9.3)
|
|
36
|
+
rb-inotify (>= 0.9)
|
|
37
|
+
lumberjack (1.0.9)
|
|
38
|
+
method_source (0.8.2)
|
|
39
|
+
nenv (0.2.0)
|
|
40
|
+
notiffany (0.0.6)
|
|
41
|
+
nenv (~> 0.1)
|
|
42
|
+
shellany (~> 0.0)
|
|
43
|
+
parser (2.2.2.6)
|
|
44
|
+
ast (>= 1.1, < 3.0)
|
|
45
|
+
powerpack (0.1.1)
|
|
46
|
+
pry (0.10.1)
|
|
47
|
+
coderay (~> 1.1.0)
|
|
48
|
+
method_source (~> 0.8.1)
|
|
49
|
+
slop (~> 3.4)
|
|
50
|
+
rainbow (2.0.0)
|
|
51
|
+
rake (10.4.2)
|
|
52
|
+
rb-fsevent (0.9.5)
|
|
53
|
+
rb-inotify (0.9.5)
|
|
54
|
+
ffi (>= 0.5.0)
|
|
55
|
+
rspec (3.3.0)
|
|
56
|
+
rspec-core (~> 3.3.0)
|
|
57
|
+
rspec-expectations (~> 3.3.0)
|
|
58
|
+
rspec-mocks (~> 3.3.0)
|
|
59
|
+
rspec-core (3.3.2)
|
|
60
|
+
rspec-support (~> 3.3.0)
|
|
61
|
+
rspec-expectations (3.3.1)
|
|
62
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
63
|
+
rspec-support (~> 3.3.0)
|
|
64
|
+
rspec-mocks (3.3.2)
|
|
65
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
66
|
+
rspec-support (~> 3.3.0)
|
|
67
|
+
rspec-support (3.3.0)
|
|
68
|
+
rubocop (0.32.1)
|
|
69
|
+
astrolabe (~> 1.3)
|
|
70
|
+
parser (>= 2.2.2.5, < 3.0)
|
|
71
|
+
powerpack (~> 0.1)
|
|
72
|
+
rainbow (>= 1.99.1, < 3.0)
|
|
73
|
+
ruby-progressbar (~> 1.4)
|
|
74
|
+
ruby-progressbar (1.7.5)
|
|
75
|
+
shellany (0.0.1)
|
|
76
|
+
simplecov (0.10.0)
|
|
77
|
+
docile (~> 1.1.0)
|
|
78
|
+
json (~> 1.8)
|
|
79
|
+
simplecov-html (~> 0.10.0)
|
|
80
|
+
simplecov-html (0.10.0)
|
|
81
|
+
slop (3.6.0)
|
|
82
|
+
thor (0.19.1)
|
|
83
|
+
|
|
84
|
+
PLATFORMS
|
|
85
|
+
ruby
|
|
86
|
+
|
|
87
|
+
DEPENDENCIES
|
|
88
|
+
bundler (~> 1.10.5)
|
|
89
|
+
codeclimate-test-reporter (~> 0.2.0)
|
|
90
|
+
guard (~> 2.12.8)
|
|
91
|
+
guard-rspec (~> 4.6.2)
|
|
92
|
+
rake (~> 10.4.2)
|
|
93
|
+
robert2d-robot!
|
|
94
|
+
rspec (~> 3.3.0)
|
|
95
|
+
rubocop (~> 0.32.1)
|
|
96
|
+
simplecov (~> 0.10.0)
|
|
97
|
+
|
|
98
|
+
BUNDLED WITH
|
|
99
|
+
1.10.5
|
data/Guardfile
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# To exclude automatic running of tests, use the group filter e.g.
|
|
2
|
+
# `be guard -g no-tests`
|
|
3
|
+
# The above will only run global definitions and the group 'no-tests',
|
|
4
|
+
# which doesn't exist. This is to support starting a guard process in one
|
|
5
|
+
# window and then manually running `bundle exec rspec spec/<spec>` in
|
|
6
|
+
# another.
|
|
7
|
+
group :tests do
|
|
8
|
+
guard :rspec, cmd: 'rspec --color' do
|
|
9
|
+
watch(%r{^spec/.+_spec\.rb$})
|
|
10
|
+
watch('spec/spec_helper.rb') { 'spec/' }
|
|
11
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
|
12
|
+
end
|
|
13
|
+
end
|
data/README.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# TOY ROBOT TEST
|
|
2
|
+
[](https://travis-ci.org/robert2d/robot)
|
|
3
|
+
[](https://codeclimate.com/github/robert2d/robot/coverage)
|
|
4
|
+
[](https://codeclimate.com/github/robert2d/robot)
|
|
5
|
+
|
|
6
|
+
See instructions.txt for the specification. If run on OSX you can turn your speakers on to get more feedback from the robot. There is also a visual component to the REPORT command, which even though it wasn't required I left in anyway.
|
|
7
|
+
|
|
8
|
+
## INSTALLING
|
|
9
|
+
|
|
10
|
+
git clone git://github.com/robert2d/rea-robot.git
|
|
11
|
+
cd rea-robot
|
|
12
|
+
gem install bundler
|
|
13
|
+
bundle install
|
|
14
|
+
|
|
15
|
+
## USE
|
|
16
|
+
|
|
17
|
+
### Interactive:
|
|
18
|
+
|
|
19
|
+
$ ./robot.rb
|
|
20
|
+
PLACE 1,2,EAST
|
|
21
|
+
MOVE
|
|
22
|
+
MOVE
|
|
23
|
+
LEFT
|
|
24
|
+
MOVE
|
|
25
|
+
REPORT
|
|
26
|
+
|
|
27
|
+
### Passing a file:
|
|
28
|
+
|
|
29
|
+
$ ./robot.rb test_data.txt
|
|
30
|
+
|
|
31
|
+
## TESTS
|
|
32
|
+
|
|
33
|
+
$ rspec
|
data/Rakefile
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'bundler'
|
|
2
|
+
require 'rubocop/rake_task'
|
|
3
|
+
require 'rspec/core'
|
|
4
|
+
require 'rspec/core/rake_task'
|
|
5
|
+
|
|
6
|
+
RuboCop::RakeTask.new do |t|
|
|
7
|
+
t.formatters = %w(progress json)
|
|
8
|
+
t.options = %w(--out coverage/rubocop.json)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
|
12
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
task default: [:spec, :rubocop]
|
data/bin/robot
ADDED
data/instructions.txt
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
-----------
|
|
2
|
+
Toy Robot Simulator
|
|
3
|
+
|
|
4
|
+
Description:
|
|
5
|
+
. The application is a simulation of a toy robot moving on a square tabletop, of dimensions 5 units x 5 units.
|
|
6
|
+
. There are no other obstructions on the table surface.
|
|
7
|
+
. The robot is free to roam around the surface of the table, but must be prevented from falling to destruction. Any movement
|
|
8
|
+
that would result in the robot falling from the table must be prevented, however further valid movement commands must still
|
|
9
|
+
be allowed.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
. Create an application that can read in commands of the following form -
|
|
13
|
+
PLACE X,Y,F
|
|
14
|
+
MOVE
|
|
15
|
+
LEFT
|
|
16
|
+
RIGHT
|
|
17
|
+
REPORT
|
|
18
|
+
|
|
19
|
+
. PLACE will put the toy robot on the table in position X,Y and facing NORTH, SOUTH, EAST or WEST.
|
|
20
|
+
. The origin (0,0) can be considered to be the SOUTH WEST most corner.
|
|
21
|
+
. The first valid command to the robot is a PLACE command, after that, any sequence of commands may be issued, in any order, including another PLACE command. The application should discard all commands in the sequence until a valid PLACE command has been executed.
|
|
22
|
+
. MOVE will move the toy robot one unit forward in the direction it is currently facing.
|
|
23
|
+
. LEFT and RIGHT will rotate the robot 90 degrees in the specified direction without changing the position of the robot.
|
|
24
|
+
. REPORT will announce the X,Y and F of the robot. This can be in any form, but standard output is sufficient.
|
|
25
|
+
|
|
26
|
+
. A robot that is not on the table can choose the ignore the MOVE, LEFT, RIGHT and REPORT commands.
|
|
27
|
+
. Input can be from a file, or from standard input, as the developer chooses.
|
|
28
|
+
. Provide test data to exercise the application.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
Constraints:
|
|
32
|
+
The toy robot must not fall off the table during movement. This also includes the initial placement of the toy robot.
|
|
33
|
+
Any move that would cause the robot to fall must be ignored.
|
|
34
|
+
|
|
35
|
+
Example Input and Output:
|
|
36
|
+
a)
|
|
37
|
+
PLACE 0,0,NORTH
|
|
38
|
+
MOVE
|
|
39
|
+
REPORT
|
|
40
|
+
Output: 0,1,NORTH
|
|
41
|
+
|
|
42
|
+
b)
|
|
43
|
+
PLACE 0,0,NORTH
|
|
44
|
+
LEFT
|
|
45
|
+
REPORT
|
|
46
|
+
Output: 0,0,WEST
|
|
47
|
+
|
|
48
|
+
c)
|
|
49
|
+
PLACE 1,2,EAST
|
|
50
|
+
MOVE
|
|
51
|
+
MOVE
|
|
52
|
+
LEFT
|
|
53
|
+
MOVE
|
|
54
|
+
REPORT
|
|
55
|
+
Output: 3,3,NORTH
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
Deliverables:
|
|
59
|
+
The Ruby source files, the test data and any test code.
|
|
60
|
+
It is not required to provide any graphical output showing the movement of the toy robot.
|
|
61
|
+
-------
|
data/lib/robot.rb
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
require 'singleton'
|
|
2
|
+
require 'robot/table'
|
|
3
|
+
require 'robot/matrix'
|
|
4
|
+
require 'robot/command_centre'
|
|
5
|
+
|
|
6
|
+
class Robot
|
|
7
|
+
include Singleton
|
|
8
|
+
|
|
9
|
+
MOVEMENT_DIRECTIONS = {
|
|
10
|
+
north: { x: 0, y: 1 },
|
|
11
|
+
east: { x: 1, y: 0 },
|
|
12
|
+
south: { x: 0, y: -1 },
|
|
13
|
+
west: { x: -1, y: 0 }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
attr_reader :table, :direction
|
|
17
|
+
|
|
18
|
+
def initialize
|
|
19
|
+
@table = Table.instance
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# trys to move in current direction one place
|
|
24
|
+
def move
|
|
25
|
+
postition = new_position
|
|
26
|
+
return if table.place(postition[:x], postition[:y])
|
|
27
|
+
puts 'Cannot move off the table'
|
|
28
|
+
CommandCentre.instance.say('Does not compute, I will fall to my death')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# rotates compass faces and uses current face as index
|
|
33
|
+
# to retrieve new direction
|
|
34
|
+
def right
|
|
35
|
+
rotate(:right)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def left
|
|
39
|
+
rotate(:left)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
##
|
|
43
|
+
# outputs the x,y,position of the robot also includes a position matrix
|
|
44
|
+
def report
|
|
45
|
+
puts to_s
|
|
46
|
+
puts Matrix.new(table.position, direction).to_s
|
|
47
|
+
say_position
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def to_s
|
|
51
|
+
"#{table.position[:x]}, #{table.position[:y]} #{direction.upcase}"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def place(args)
|
|
55
|
+
return unless args
|
|
56
|
+
x, y, face = args.split(',')
|
|
57
|
+
return unless x && y && face
|
|
58
|
+
return unless table.place(x, y)
|
|
59
|
+
self.direction = face.downcase.to_sym
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def say_position
|
|
65
|
+
CommandCentre.instance.say("My position is currently #{table.position[:x]}/
|
|
66
|
+
by #{table.position[:y]} and facing #{direction}")
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
# fetches new coordinates and adds them to existing coords
|
|
71
|
+
def new_position
|
|
72
|
+
table.position.merge(move_coordinates) { |_key, memo, value| memo + value }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def move_coordinates
|
|
76
|
+
MOVEMENT_DIRECTIONS[direction]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def direction=(face)
|
|
80
|
+
@direction = face if MOVEMENT_DIRECTIONS.keys.include?(face)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def rotate(direction)
|
|
84
|
+
index = direction == :left ? -1 : 1
|
|
85
|
+
self.direction = faces.rotate(index)[face_index]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def faces
|
|
89
|
+
MOVEMENT_DIRECTIONS.keys
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def face_index
|
|
93
|
+
faces.index(direction)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require 'singleton'
|
|
2
|
+
|
|
3
|
+
class Robot
|
|
4
|
+
class CommandCentre
|
|
5
|
+
include Singleton
|
|
6
|
+
|
|
7
|
+
COMMANDS = %w(PLACE MOVE LEFT RIGHT REPORT)
|
|
8
|
+
|
|
9
|
+
def parse_and_execute(command_string)
|
|
10
|
+
command = Command.new(command_string.strip.upcase)
|
|
11
|
+
return unless command.validate
|
|
12
|
+
command.execute
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# feature just for fun only for mac users
|
|
17
|
+
def say(message)
|
|
18
|
+
IO.popen(
|
|
19
|
+
"say -v Ralph '#{message}'"
|
|
20
|
+
) if RbConfig::CONFIG['host_os'].match(/darwin|mac os/)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class Command
|
|
24
|
+
attr_reader :command, :args, :robot
|
|
25
|
+
|
|
26
|
+
def initialize(command_string)
|
|
27
|
+
@command, @args = command_string.split(' ')
|
|
28
|
+
@robot = Robot.instance
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def execute
|
|
32
|
+
return robot.place(args) if place?
|
|
33
|
+
return robot.send(:"#{command.downcase}") if robot.table.placed?
|
|
34
|
+
CommandCentre.instance.say('Does not compute, You must place me first')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def place?
|
|
38
|
+
command == 'PLACE'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def validate
|
|
42
|
+
COMMANDS.include?(command)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/robot/matrix.rb
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
class Robot
|
|
2
|
+
class Matrix
|
|
3
|
+
attr_reader :position, :direction
|
|
4
|
+
attr_accessor :matrix
|
|
5
|
+
|
|
6
|
+
DIRECTION_ARROWS = {
|
|
7
|
+
north: '^',
|
|
8
|
+
east: '>',
|
|
9
|
+
south: 'v',
|
|
10
|
+
west: '<'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
def initialize(position, direction)
|
|
14
|
+
@position = position
|
|
15
|
+
@direction = direction
|
|
16
|
+
@matrix = generate_matrix
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
# puts an arrow pointing in the direction of the current x,y of the robot
|
|
21
|
+
# on a matrix and returns a string of the matrix
|
|
22
|
+
def to_s
|
|
23
|
+
set_current_position!
|
|
24
|
+
matrix.reverse.map { |row| row.join(' ') }.join("\n")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
##
|
|
30
|
+
# sets the current position x,y coords to a directional arrow
|
|
31
|
+
def set_current_position!
|
|
32
|
+
matrix[
|
|
33
|
+
position[:y]
|
|
34
|
+
][
|
|
35
|
+
position[:x]
|
|
36
|
+
] = DIRECTION_ARROWS[direction]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# constructs a matrix of positions
|
|
41
|
+
# Output:
|
|
42
|
+
# [
|
|
43
|
+
# ["X", "X", "X", "X", "X"],
|
|
44
|
+
# ["X", "X", "X", "X", "X"],
|
|
45
|
+
# ["X", "X", "X", "X", "X"],
|
|
46
|
+
# ["X", "X", "X", "X", "X"],
|
|
47
|
+
# ["X", "X", "X", "X", "X"]
|
|
48
|
+
# ]
|
|
49
|
+
def generate_matrix
|
|
50
|
+
[].tap { |a| 25.times { a << 'X' } }.each_slice(5).to_a
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
data/lib/robot/table.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'singleton'
|
|
2
|
+
|
|
3
|
+
class Robot
|
|
4
|
+
class Table
|
|
5
|
+
include Singleton
|
|
6
|
+
|
|
7
|
+
attr_accessor :position
|
|
8
|
+
attr_reader :width, :height
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@width = 4
|
|
12
|
+
@height = 4
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def place(x, y)
|
|
16
|
+
position = { x: x.to_i, y: y.to_i }
|
|
17
|
+
self.position = position if valid_position?(position)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def placed?
|
|
21
|
+
!position.nil?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def valid_position?(position)
|
|
25
|
+
position[:x] <= width && position[:x] >= 0 && \
|
|
26
|
+
position[:y] <= height && position[:y] >= 0
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'robot/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = 'robert2d-robot'
|
|
8
|
+
spec.version = Robot::VERSION
|
|
9
|
+
spec.authors = ['Dave Robertson']
|
|
10
|
+
spec.email = ['dave.andrew.robertson.nz@gmail.com']
|
|
11
|
+
spec.summary = 'Toy Robot CLI'
|
|
12
|
+
spec.homepage = ''
|
|
13
|
+
spec.license = 'MIT'
|
|
14
|
+
|
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
17
|
+
spec.test_files = spec.files.grep(%r{^(spec)/})
|
|
18
|
+
spec.require_paths = ['lib']
|
|
19
|
+
|
|
20
|
+
spec.add_development_dependency 'bundler', '~>1.10.5'
|
|
21
|
+
spec.add_development_dependency 'rake', '~>10.4.2'
|
|
22
|
+
spec.add_development_dependency 'rspec', '~>3.3.0'
|
|
23
|
+
spec.add_development_dependency 'guard', '~>2.12.8'
|
|
24
|
+
spec.add_development_dependency 'guard-rspec', '~>4.6.2'
|
|
25
|
+
spec.add_development_dependency 'simplecov', '~>0.10.0'
|
|
26
|
+
spec.add_development_dependency 'rubocop', '~>0.32.1'
|
|
27
|
+
spec.add_development_dependency 'codeclimate-test-reporter', '~>0.2.0'
|
|
28
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
describe Robot::CommandCentre do
|
|
2
|
+
let(:command) { Robot::CommandCentre::Command }
|
|
3
|
+
let(:commands) { Robot::CommandCentre::COMMANDS }
|
|
4
|
+
|
|
5
|
+
subject { Singleton.__init__(described_class).instance }
|
|
6
|
+
|
|
7
|
+
before do
|
|
8
|
+
allow(subject).to receive(:puts)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe '#parse_and_execute' do
|
|
12
|
+
context 'invalid command' do
|
|
13
|
+
let(:command) { double('Command') }
|
|
14
|
+
|
|
15
|
+
it 'returns without executing' do
|
|
16
|
+
expect(described_class::Command).to receive(:new).and_return(command)
|
|
17
|
+
expect(command).to receive(:validate)
|
|
18
|
+
expect(command).not_to receive(:execute)
|
|
19
|
+
subject.parse_and_execute('test')
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context 'valid command' do
|
|
24
|
+
it 'validates and executes command' do
|
|
25
|
+
expect_any_instance_of(command).to receive(:execute)
|
|
26
|
+
subject.parse_and_execute(commands.sample)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe Robot::CommandCentre::Command do
|
|
32
|
+
describe '#new' do
|
|
33
|
+
subject { command }
|
|
34
|
+
|
|
35
|
+
it 'constucts valid Command' do
|
|
36
|
+
expect(subject.new('test')).to respond_to(:command, :args, :robot)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
describe '#validate' do
|
|
41
|
+
context 'is invalid' do
|
|
42
|
+
subject { command.new('test') }
|
|
43
|
+
|
|
44
|
+
it 'returns false' do
|
|
45
|
+
expect(subject.validate).not_to be
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
context 'is valid' do
|
|
50
|
+
subject { command.new(commands.sample) }
|
|
51
|
+
|
|
52
|
+
it 'returns false' do
|
|
53
|
+
expect(subject.validate).to be
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe '#execute' do
|
|
59
|
+
context 'with PLACE command' do
|
|
60
|
+
subject { command.new('PLACE 1,2,north') }
|
|
61
|
+
|
|
62
|
+
it 'delegates to robot passing args' do
|
|
63
|
+
expect(subject.robot).to receive(:place).with('1,2,north')
|
|
64
|
+
subject.execute
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context 'with all other commands' do
|
|
69
|
+
subject { command.new('move') }
|
|
70
|
+
|
|
71
|
+
context 'when not placed' do
|
|
72
|
+
it 'delegates to robot' do
|
|
73
|
+
expect(Robot::CommandCentre.instance).to receive(:say)
|
|
74
|
+
expect(subject.robot.table).to receive(:placed?)
|
|
75
|
+
expect(subject.robot).not_to receive(:move)
|
|
76
|
+
subject.execute
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context 'when placed' do
|
|
81
|
+
it 'delegates to robot' do
|
|
82
|
+
expect(subject.robot.table).to receive(:placed?).and_return(true)
|
|
83
|
+
expect(subject.robot).to receive(:move)
|
|
84
|
+
subject.execute
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
describe Robot::Matrix do
|
|
2
|
+
subject { described_class.new({ x: 1, y: 1 }, :north) }
|
|
3
|
+
|
|
4
|
+
describe '#to_s' do
|
|
5
|
+
let(:expected) do
|
|
6
|
+
<<-TEXT.gsub(/^\s+/, '')
|
|
7
|
+
X X X X X
|
|
8
|
+
X X X X X
|
|
9
|
+
X X X X X
|
|
10
|
+
X ^ X X X
|
|
11
|
+
X X X X X
|
|
12
|
+
TEXT
|
|
13
|
+
end
|
|
14
|
+
it 'provides correct matrix for given inputs' do
|
|
15
|
+
expect(subject.to_s).to eq(expected.strip)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
describe Robot::Table do
|
|
2
|
+
# ensure fresh singleton for each spec
|
|
3
|
+
subject(:table) { Singleton.__init__(Robot::Table).instance }
|
|
4
|
+
|
|
5
|
+
describe '#place' do
|
|
6
|
+
context 'with valid position' do
|
|
7
|
+
it 'sets position on table' do
|
|
8
|
+
table.place('1', '2')
|
|
9
|
+
expect(table.placed?).to be
|
|
10
|
+
expect(table.position).to eq(x: 1, y: 2)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
context 'with invalid position' do
|
|
14
|
+
it 'does not set position' do
|
|
15
|
+
table.place('-1', '7')
|
|
16
|
+
expect(table.placed?).not_to be
|
|
17
|
+
expect(table.position).to be_nil
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe '#placed?' do
|
|
23
|
+
it 'is false when not placed yet' do
|
|
24
|
+
expect(table.placed?).not_to be
|
|
25
|
+
end
|
|
26
|
+
it 'is true when has position' do
|
|
27
|
+
table.place('1', '2')
|
|
28
|
+
expect(table.placed?).to be
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe '#valid_position?' do
|
|
33
|
+
context 'with invalid position coordinates' do
|
|
34
|
+
let(:position) do
|
|
35
|
+
{
|
|
36
|
+
x: -1,
|
|
37
|
+
y: 10
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
it 'returns false' do
|
|
41
|
+
expect(table.valid_position?(position)).not_to be
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
context 'with all valid position coordinates' do
|
|
45
|
+
it 'returns true' do
|
|
46
|
+
5.times do |x|
|
|
47
|
+
5.times do |y|
|
|
48
|
+
expect(table.valid_position?(x: x, y: y)).to be
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
describe Robot do
|
|
2
|
+
let(:position) do
|
|
3
|
+
{
|
|
4
|
+
x: 1,
|
|
5
|
+
y: 2
|
|
6
|
+
}
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# ensure fresh singleton for each spec
|
|
10
|
+
subject(:robot) { Singleton.__init__(Robot).instance }
|
|
11
|
+
|
|
12
|
+
before do
|
|
13
|
+
allow(robot).to receive(:puts)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'has a version' do
|
|
17
|
+
expect(Robot::VERSION).to be
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe 'relationship to table' do
|
|
21
|
+
it 'should create relationship to table' do
|
|
22
|
+
expect(robot).to respond_to(:table)
|
|
23
|
+
expect(robot.table).to be_an_instance_of(Robot::Table)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe '#move' do
|
|
28
|
+
context 'with valid placement on table' do
|
|
29
|
+
it 'returns valid placement' do
|
|
30
|
+
expect(robot).to receive(:new_position).and_return(position)
|
|
31
|
+
expect(robot.table).to receive(:place).and_call_original
|
|
32
|
+
expect(Robot::CommandCentre.instance).not_to receive(:say)
|
|
33
|
+
robot.move
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context 'invalid placement on table' do
|
|
38
|
+
it 'alerts user of failed move' do
|
|
39
|
+
expect(robot).to receive(:new_position).and_return(position)
|
|
40
|
+
expect(robot.table).to receive(:place)
|
|
41
|
+
expect(Robot::CommandCentre.instance).to receive(:say)
|
|
42
|
+
robot.move
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe '#new_position' do
|
|
48
|
+
it 'fetches coordinates for move' do
|
|
49
|
+
expect(robot.table).to receive(:position).and_return(position)
|
|
50
|
+
expect(robot).to receive(:move_coordinates).and_return(position)
|
|
51
|
+
expect(robot.send(:new_position)).to eq(x: 2, y: 4)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe '#to_s' do
|
|
56
|
+
it 'provides position and direction in string' do
|
|
57
|
+
robot.send(:direction=, :north)
|
|
58
|
+
allow(robot.table).to receive(:position).and_return(position)
|
|
59
|
+
expect(robot.to_s).to eq('1, 2 NORTH')
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe '#move_coordinates' do
|
|
64
|
+
it 'returns coords from current face' do
|
|
65
|
+
robot.send(:direction=, :north)
|
|
66
|
+
expect(robot.send(:move_coordinates)).to eq(x: 0, y: 1)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
describe '#right' do
|
|
71
|
+
it 'returns correct face clockwise' do
|
|
72
|
+
robot.send(:direction=, :north)
|
|
73
|
+
expect(robot).to receive(:direction=).with(:east)
|
|
74
|
+
expect(robot.right).to eq(:east)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe '#left' do
|
|
79
|
+
it 'returns correct face anti-clockwise' do
|
|
80
|
+
robot.send(:direction=, :west)
|
|
81
|
+
expect(robot).to receive(:direction=).with(:south)
|
|
82
|
+
expect(robot.left).to eq(:south)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
describe '#report' do
|
|
87
|
+
let(:table) { double(Robot::Table, position: { x: 1, y: 2 }) }
|
|
88
|
+
|
|
89
|
+
it 'outputs text and calls say' do
|
|
90
|
+
expect(robot).to receive(:direction).exactly(3).times.and_return(:north)
|
|
91
|
+
allow(robot).to receive(:table).and_return(table)
|
|
92
|
+
expect(Robot::CommandCentre.instance).to receive(:say)
|
|
93
|
+
robot.report
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
describe '#place' do
|
|
98
|
+
context 'with invalid args' do
|
|
99
|
+
it 'does nothing with nil args' do
|
|
100
|
+
expect(robot.table).not_to receive(:place)
|
|
101
|
+
robot.place(nil)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'does nothing with blank string' do
|
|
105
|
+
expect(robot.table).not_to receive(:place)
|
|
106
|
+
robot.place(' ')
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'does nothing with malformed args' do
|
|
110
|
+
expect(robot.table).not_to receive(:place)
|
|
111
|
+
robot.place('1,2north')
|
|
112
|
+
robot.place('north')
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
context 'with valid args' do
|
|
117
|
+
context 'and valid placement' do
|
|
118
|
+
it 'sets direction' do
|
|
119
|
+
expect(robot.table).to receive(:place).with(
|
|
120
|
+
'1', '2'
|
|
121
|
+
).and_call_original
|
|
122
|
+
expect(robot).to receive(:direction=).with(:north)
|
|
123
|
+
robot.place('1,2,north')
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
context 'and invalid placement' do
|
|
128
|
+
it 'does not set direction when place fails' do
|
|
129
|
+
expect(robot.table).to receive(:place).with('1', '2')
|
|
130
|
+
expect(robot).not_to receive(:direction=)
|
|
131
|
+
robot.place('1,2,north')
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
describe '#direction=' do
|
|
138
|
+
context 'direction is invalid' do
|
|
139
|
+
it 'does not save position' do
|
|
140
|
+
robot.send(:direction=, :up)
|
|
141
|
+
expect(robot.direction).not_to be
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
context 'direction is valid' do
|
|
145
|
+
it 'does save to singleton' do
|
|
146
|
+
robot.send(:direction=, :west)
|
|
147
|
+
expect(robot.direction).to eq(:west)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'simplecov'
|
|
4
|
+
require 'codeclimate-test-reporter'
|
|
5
|
+
CodeClimate::TestReporter.start
|
|
6
|
+
|
|
7
|
+
SimpleCov.start
|
|
8
|
+
|
|
9
|
+
require 'robot'
|
|
10
|
+
|
|
11
|
+
RSpec.configure do |config|
|
|
12
|
+
config.disable_monkey_patching!
|
|
13
|
+
config.expose_dsl_globally = true
|
|
14
|
+
config.order = :random
|
|
15
|
+
end
|
data/test_data.txt
ADDED
metadata
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: robert2d-robot
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Dave Robertson
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-07-20 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ~>
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 1.10.5
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ~>
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 1.10.5
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ~>
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 10.4.2
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ~>
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: 10.4.2
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rspec
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ~>
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: 3.3.0
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ~>
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: 3.3.0
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: guard
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ~>
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 2.12.8
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ~>
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 2.12.8
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: guard-rspec
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ~>
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 4.6.2
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ~>
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 4.6.2
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: simplecov
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ~>
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: 0.10.0
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ~>
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: 0.10.0
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: rubocop
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ~>
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: 0.32.1
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ~>
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: 0.32.1
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: codeclimate-test-reporter
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - ~>
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: 0.2.0
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - ~>
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: 0.2.0
|
|
125
|
+
description:
|
|
126
|
+
email:
|
|
127
|
+
- dave.andrew.robertson.nz@gmail.com
|
|
128
|
+
executables:
|
|
129
|
+
- robot
|
|
130
|
+
extensions: []
|
|
131
|
+
extra_rdoc_files: []
|
|
132
|
+
files:
|
|
133
|
+
- .gitignore
|
|
134
|
+
- .rspec
|
|
135
|
+
- .rubocop.yml
|
|
136
|
+
- .ruby-version
|
|
137
|
+
- .travis.yml
|
|
138
|
+
- Gemfile
|
|
139
|
+
- Gemfile.lock
|
|
140
|
+
- Guardfile
|
|
141
|
+
- README.md
|
|
142
|
+
- Rakefile
|
|
143
|
+
- bin/robot
|
|
144
|
+
- instructions.txt
|
|
145
|
+
- lib/robot.rb
|
|
146
|
+
- lib/robot/command_centre.rb
|
|
147
|
+
- lib/robot/matrix.rb
|
|
148
|
+
- lib/robot/table.rb
|
|
149
|
+
- lib/robot/version.rb
|
|
150
|
+
- robert2d-robot.gemspec
|
|
151
|
+
- spec/lib/robot/command_centre_spec.rb
|
|
152
|
+
- spec/lib/robot/matrix_spec.rb
|
|
153
|
+
- spec/lib/robot/table_spec.rb
|
|
154
|
+
- spec/lib/robot_spec.rb
|
|
155
|
+
- spec/spec_helper.rb
|
|
156
|
+
- test_data.txt
|
|
157
|
+
homepage: ''
|
|
158
|
+
licenses:
|
|
159
|
+
- MIT
|
|
160
|
+
metadata: {}
|
|
161
|
+
post_install_message:
|
|
162
|
+
rdoc_options: []
|
|
163
|
+
require_paths:
|
|
164
|
+
- lib
|
|
165
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
166
|
+
requirements:
|
|
167
|
+
- - ! '>='
|
|
168
|
+
- !ruby/object:Gem::Version
|
|
169
|
+
version: '0'
|
|
170
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
171
|
+
requirements:
|
|
172
|
+
- - ! '>='
|
|
173
|
+
- !ruby/object:Gem::Version
|
|
174
|
+
version: '0'
|
|
175
|
+
requirements: []
|
|
176
|
+
rubyforge_project:
|
|
177
|
+
rubygems_version: 2.4.5
|
|
178
|
+
signing_key:
|
|
179
|
+
specification_version: 4
|
|
180
|
+
summary: Toy Robot CLI
|
|
181
|
+
test_files:
|
|
182
|
+
- spec/lib/robot/command_centre_spec.rb
|
|
183
|
+
- spec/lib/robot/matrix_spec.rb
|
|
184
|
+
- spec/lib/robot/table_spec.rb
|
|
185
|
+
- spec/lib/robot_spec.rb
|
|
186
|
+
- spec/spec_helper.rb
|