toy_robot 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 470b7ee06374f2b4e17346a8a842fb990766dd19
4
+ data.tar.gz: 5e6c4ba76194f3c01f500c54738518818b2317fb
5
+ SHA512:
6
+ metadata.gz: c23a350702a5d232edfc69c501c5c7bcc3f5e12fa61b7f570089886761d1e5df1983b0b2e78321056f17ff0f88e7825bab67239a36c8a6f932e9a31cd81d1f98
7
+ data.tar.gz: 0ee1187e09d65ae884102910bafa0d73bdb9bc68778f509ced990b03454a19b6ead3433dcca85a941ee0e96d4fa908fde82449dd12767984f26638ed82a91cd7
@@ -0,0 +1,34 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /lib/bundler/man/
26
+
27
+ # for a library or gem, you might want to ignore these files since the code is
28
+ # intended to run in multiple environments; otherwise, check them in:
29
+ Gemfile.lock
30
+ # .ruby-version
31
+ # .ruby-gemset
32
+
33
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 louman
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 all
13
+ 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 THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,18 @@
1
+ # Toy_Robot
2
+
3
+ Welcome to the toy robot simulator.
4
+
5
+ ## Usage
6
+
7
+ ```ruby
8
+ gem install toy_robot
9
+
10
+ toy_robot
11
+ ```
12
+ and follow instructions :)
13
+
14
+ ## Specs
15
+
16
+ ```ruby
17
+ rspec
18
+ ```
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../lib/toy_robot'
3
+
4
+ ToyRobot::Bin::Runner.new.start
@@ -0,0 +1,19 @@
1
+ require 'asciiart'
2
+ require 'forwardable'
3
+ require 'rainbow'
4
+ require 'terminal-table'
5
+
6
+ require 'toy_robot/roboto'
7
+ require 'toy_robot/roboto/brain'
8
+ require 'toy_robot/roboto/motor_cortex'
9
+ require 'toy_robot/roboto/speech'
10
+ require 'toy_robot/table'
11
+ require 'toy_robot/manifest_reader'
12
+ require 'toy_robot/simulator'
13
+
14
+ require 'toy_robot/bin/io_utils'
15
+ require 'toy_robot/bin/runner'
16
+
17
+ module ToyRobot
18
+
19
+ end
@@ -0,0 +1,38 @@
1
+ module ToyRobot
2
+ module Bin
3
+ module IOUtils
4
+
5
+ # puts a message and sleep
6
+ def print_with_delay(msg, delay_time=2)
7
+ _print msg
8
+ delay delay_time
9
+ end
10
+
11
+ # just a wrapper for puts
12
+ def _print(msg)
13
+ puts msg
14
+ end
15
+
16
+ # just a wrapper for sleep
17
+ def delay(delay_time)
18
+ sleep delay_time
19
+ end
20
+
21
+ # returns a yellowish string
22
+ def yellow(text)
23
+ Rainbow(text).yellow
24
+ end
25
+
26
+ # returns a greenish string
27
+ def green(text)
28
+ Rainbow(text).green
29
+ end
30
+
31
+ # returns a reddish string
32
+ def red(text)
33
+ Rainbow(text).red
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,108 @@
1
+ module ToyRobot
2
+ module Bin
3
+ class Runner
4
+
5
+ include IOUtils
6
+
7
+ attr_reader :simulator, :roboto, :selected_option
8
+
9
+ def initialize
10
+ @simulator = ToyRobot::Simulator.new
11
+ @roboto = @simulator.roboto
12
+ @roboto.name = robots.sample
13
+ end
14
+
15
+ def start
16
+ show_art
17
+ show_help
18
+ show_options
19
+ @selected_option = capture_input
20
+ handle_selected_option
21
+ end
22
+
23
+ private
24
+
25
+ def capture_input
26
+ gets.chomp.strip
27
+ end
28
+
29
+ def handle_selected_option
30
+ case selected_option
31
+ when '1'
32
+ input_by_hand
33
+ when '2'
34
+ input_from_file
35
+ else
36
+ _print 'Invalid option, terminating simulator.'
37
+ end
38
+ end
39
+
40
+ def input_by_hand
41
+ boot_roboto('Ok, preparing roboto for manual orders')
42
+ _print green("-- #{@roboto.name} reporting for duty. What is you first order sir?")
43
+ command = capture_input
44
+ while command
45
+ begin
46
+ @simulator.run([command])
47
+ rescue StandardError
48
+ _print red('Order not recognized, sir!')
49
+ end
50
+ _print green("#{@roboto.name} waiting for new orders, sir!")
51
+ command = capture_input
52
+ end
53
+ end
54
+
55
+ def input_from_file
56
+ boot_roboto('Ok, preparing roboto for orders manifest')
57
+ @simulator.run(read_manifest)
58
+ end
59
+
60
+ def read_manifest
61
+ ToyRobot::ManifestReader.new.read
62
+ end
63
+
64
+ def show_art
65
+ _print art
66
+ end
67
+
68
+ def show_help
69
+ _print help
70
+ end
71
+
72
+ def show_options
73
+ _print '1) Input orders by hand'
74
+ _print '2) Input orders from file'
75
+ end
76
+
77
+ def boot_roboto(acknowledge_message)
78
+ print_with_delay yellow(acknowledge_message)
79
+ print_with_delay yellow("Booting #{@roboto.name}")
80
+ print_with_delay yellow('Calibrating controls')
81
+ print_with_delay yellow('Activating AI')
82
+ print_with_delay yellow('1, 2, 3 testing')
83
+ end
84
+
85
+ def help
86
+ rows = []
87
+ rows << ['Type "exit" anytime to exit simulator']
88
+ rows << ['Valid commands are: PLACE, MOVE, LEFT, RIGHT, REPORT']
89
+ rows << ['PLACE: puts the toy robot on the table in position X,Y and facing NORTH, SOUTH, EAST or WEST.']
90
+ rows << ['MOVE: moves the toy robot one unit forward in the direction it is currently facing.']
91
+ rows << ['LEFT: rotates the robot 90 degrees counter-clockwise without changing the position of the robot.']
92
+ rows << ['RIGHT: rotates the robot 90 degrees clockwise without changing the position of the robot.']
93
+ rows << ['REPORT: announces the X,Y and F of the robot.']
94
+ table = Terminal::Table.new :rows => rows, title: 'Welcome to the Toy Robot Simulator!'
95
+ end
96
+
97
+ def robots
98
+ ['T-800', 'Optimus Prime', 'R2-D2', 'C-3PO', 'Data', 'Sonny', 'Wall-E', 'Rosey', 'Robocop', 'T-1000']
99
+ end
100
+
101
+ def art
102
+ art = AsciiArt.new(File.join(File.dirname(__FILE__), '..', 'files', 'roboto.jpg'))
103
+ art.to_ascii_art(width: 70)
104
+ end
105
+
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,9 @@
1
+ MOVE
2
+ PLACE 1,2,NORTH
3
+ LEFT
4
+ REPORT
5
+ LEFT
6
+ LEFT
7
+ REPORT
8
+ MOVE
9
+ REPORT
@@ -0,0 +1,16 @@
1
+ module ToyRobot
2
+ class ManifestReader
3
+
4
+ attr_reader :file
5
+
6
+ def initialize(file_path:nil)
7
+ @file_path = file_path || File.join(File.dirname(__FILE__), 'files', 'manifest.txt')
8
+ @file = File.open(@file_path)
9
+ end
10
+
11
+ def read
12
+ @file.each_line.map(&:strip)
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,90 @@
1
+ module ToyRobot
2
+ class Roboto
3
+
4
+ extend Forwardable
5
+
6
+ def_delegator :@brain, :speak
7
+ def_delegator :@brain, :motor_cortex, :location
8
+ def_delegator :@brain, :understand_order
9
+
10
+ attr_accessor :table_edges, :brain, :name
11
+
12
+ def initialize
13
+ @brain = Brain.new
14
+ @name = 'Roboto'
15
+ end
16
+
17
+ # Sends order's method
18
+ def execute_order(order)
19
+ if order[:args].nil?
20
+ send(order[:command])
21
+ else
22
+ send(order[:command], order[:args])
23
+ end
24
+ end
25
+
26
+ # Changes roboto location if is safe
27
+ # otherwise says advise message
28
+ def place(x:, y:, f:)
29
+ safe(x, y) do
30
+ location.reset(x: x.to_i, y: y.to_i, f: f.downcase.to_sym)
31
+ end
32
+ end
33
+
34
+ # Moves roboto one unit forward to facing direction if roboto is placed
35
+ # and it's safe
36
+ # otherwise says advise message
37
+ def move
38
+ if_placed do
39
+ x, y = location.forward_prediction
40
+ safe(x, y) do
41
+ location.forward
42
+ end
43
+ end
44
+ end
45
+
46
+ # Says current location if roboto is placed
47
+ # otherwise says advise message
48
+ def report
49
+ if_placed do
50
+ puts speak(location.to_s)
51
+ end
52
+ end
53
+
54
+ # Rotates roboto 90 degrees to the left if roboto is placed
55
+ # otherwise says advise message
56
+ def left
57
+ if_placed do
58
+ location.rotate_ccw
59
+ end
60
+ end
61
+
62
+ # Rotates roboto 90 degrees to the right if roboto is placed
63
+ # otherwise says advise message
64
+ def right
65
+ if_placed do
66
+ location.rotate_cw
67
+ end
68
+ end
69
+
70
+ # Returns true if location is nil
71
+ def placed?
72
+ !location.nil?
73
+ end
74
+
75
+ private
76
+
77
+ def safe(x, y)
78
+ to_safe_location?(x, y) ? yield : speak("No can do, sir! If #{name} move #{name} fall.")
79
+ end
80
+
81
+ def to_safe_location?(new_x, new_y)
82
+ new_x.between?(table_edges[:x][:min], table_edges[:x][:max]) && new_y.between?(table_edges[:y][:min], table_edges[:y][:max])
83
+ end
84
+
85
+ def if_placed
86
+ placed? ? yield : speak("#{name} not placed yet, sir!")
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,38 @@
1
+ module ToyRobot
2
+ class Roboto
3
+ class Brain
4
+
5
+ extend Forwardable
6
+
7
+ def_delegator :@speech, :speak
8
+
9
+ attr_accessor :motor_cortex, :speech
10
+
11
+ def initialize
12
+ @motor_cortex = MotorCortex.new
13
+ @speech = Speech.new
14
+ end
15
+
16
+ def understand_order(order)
17
+ order = sanitized_order(order).split(' ')
18
+ method = order.shift.downcase.to_sym
19
+ if order.any?
20
+ arguments = sanitized_args(order.shift)
21
+ end
22
+ { command: method, args: arguments }
23
+ end
24
+
25
+ private
26
+
27
+ def sanitized_order(order)
28
+ order.strip.squeeze(' ')
29
+ end
30
+
31
+ def sanitized_args(args)
32
+ args = args.gsub(/ /, '').split(',')
33
+ { x: args[0].to_i, y: args[1].to_i, f: args[2].downcase.to_sym }
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,67 @@
1
+ module ToyRobot
2
+ class Roboto
3
+ class MotorCortex
4
+
5
+ attr_accessor :x, :y, :f
6
+
7
+ CARDINAL_DIRECTIONS = [:north, :east, :south, :west]
8
+ MOVE = { north: { x: 0, y: 1 },
9
+ east: { x: 1, y: 0 },
10
+ south: { x: 0, y: -1 },
11
+ west: { x: -1, y: 0 } }
12
+
13
+ def initialize(x: nil, y: nil, f: nil)
14
+ reset(x: x, y: y, f: f)
15
+ end
16
+
17
+ # Sets X, Y and forwarding direction
18
+ def reset(x:, y:, f:)
19
+ raise "#{f} is not a recognized direction" unless f.nil? || CARDINAL_DIRECTIONS.include?(f)
20
+ @x = x
21
+ @y = y
22
+ @f = f
23
+ end
24
+
25
+ # Rotates -90 degrees
26
+ def rotate_ccw
27
+ @f = rotation(-1)
28
+ end
29
+
30
+ # Rotates 90 degrees
31
+ def rotate_cw
32
+ @f = rotation(1) || CARDINAL_DIRECTIONS[0]
33
+ end
34
+
35
+ # Increaseas one unit to forwarding direction
36
+ def forward
37
+ new_x, new_y = forward_prediction
38
+ reset(x: new_x, y: new_y, f: @f)
39
+ end
40
+
41
+ # Calculates new position to move forward
42
+ def forward_prediction
43
+ return @x + MOVE[@f][:x], @y + MOVE[@f][:y]
44
+ end
45
+
46
+ # Returns a formated string with axis and forwarding direction
47
+ def to_s
48
+ "X: #{value_or_not_available(@x)}, Y: #{value_or_not_available(@y)}, F: #{value_or_not_available(@f)}"
49
+ end
50
+
51
+ # Returns true X or Y or F is nil
52
+ def nil?
53
+ @x.nil? || @y.nil? || @f.nil?
54
+ end
55
+
56
+ private
57
+
58
+ def value_or_not_available(value)
59
+ value.nil? ? 'N/A' : value
60
+ end
61
+
62
+ def rotation(step)
63
+ CARDINAL_DIRECTIONS[CARDINAL_DIRECTIONS.index(@f) + step]
64
+ end
65
+ end
66
+ end
67
+ end