another_toy_robot 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: 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: []