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 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
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.13.1
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
+ [![Code Climate](https://codeclimate.com/github/drzel/toy_robot/badges/gpa.svg)](https://codeclimate.com/github/drzel/toy_robot)
2
+ [![Test Coverage](https://codeclimate.com/github/drzel/toy_robot/badges/coverage.svg)](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
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
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
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/bin/toy_robot ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "toy_robot"
4
+ ToyRobot.main
@@ -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
@@ -0,0 +1,3 @@
1
+ module ToyRobot
2
+ VERSION = "0.1.0"
3
+ 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: []