ruby_robot 0.1.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +133 -0
- data/Guardfile +77 -0
- data/LICENSE.txt +21 -0
- data/README.md +50 -0
- data/Rakefile +24 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/ruby_robot +34 -0
- data/exe/ruby_robot_grpc_client +53 -0
- data/exe/ruby_robot_grpc_server +46 -0
- data/exe/ruby_robot_web +19 -0
- data/json_schema/request.schema.json +37 -0
- data/json_schema/response.schema.json +24 -0
- data/lib/public/favicon-16x16.png +0 -0
- data/lib/public/favicon-32x32.png +0 -0
- data/lib/public/index.html +95 -0
- data/lib/public/swagger-ui-bundle.js +93 -0
- data/lib/public/swagger-ui-standalone-preset.js +13 -0
- data/lib/public/swagger-ui.css +3 -0
- data/lib/public/swagger-ui.js +8 -0
- data/lib/public/swagger.json +179 -0
- data/lib/ruby_robot.rb +16 -0
- data/lib/ruby_robot/cacerts.crt +92 -0
- data/lib/ruby_robot/construction_error.rb +4 -0
- data/lib/ruby_robot/grpc/robot_service.rb +102 -0
- data/lib/ruby_robot/grpc/ruby_robot_services_pb.rb +34 -0
- data/lib/ruby_robot/grpc_helper.rb +15 -0
- data/lib/ruby_robot/grpc_ruby/ruby_robot_pb.rb +36 -0
- data/lib/ruby_robot/grpc_shell.rb +85 -0
- data/lib/ruby_robot/netflix_tabletop.rb +14 -0
- data/lib/ruby_robot/placement_error.rb +4 -0
- data/lib/ruby_robot/robot.rb +71 -0
- data/lib/ruby_robot/ruby_robot.proto +53 -0
- data/lib/ruby_robot/schema_loader.rb +10 -0
- data/lib/ruby_robot/shell.rb +204 -0
- data/lib/ruby_robot/tabletop.rb +120 -0
- data/lib/ruby_robot/version.rb +3 -0
- data/lib/ruby_robot/webapp.rb +263 -0
- data/ruby_robot.gemspec +48 -0
- metadata +258 -0
data/lib/ruby_robot.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require "ruby_robot/version"
|
2
|
+
require "ruby_robot/tabletop"
|
3
|
+
require "ruby_robot/netflix_tabletop"
|
4
|
+
require "ruby_robot/robot"
|
5
|
+
require "ruby_robot/construction_error"
|
6
|
+
require "ruby_robot/schema_loader"
|
7
|
+
require "ruby_robot/placement_error"
|
8
|
+
require "ruby_robot/shell"
|
9
|
+
require "ruby_robot/webapp"
|
10
|
+
require "ruby_robot/grpc_helper"
|
11
|
+
require "ruby_robot/grpc_shell"
|
12
|
+
require "ruby_robot/grpc_ruby/ruby_robot_pb"
|
13
|
+
require 'ruby_robot/grpc_helper'
|
14
|
+
|
15
|
+
module RubyRobot
|
16
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
|
3
|
+
MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
|
4
|
+
IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
|
5
|
+
MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
|
6
|
+
FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
|
7
|
+
bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
|
8
|
+
dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
|
9
|
+
H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
|
10
|
+
uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
|
11
|
+
mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
|
12
|
+
a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
|
13
|
+
E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
|
14
|
+
WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
|
15
|
+
VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
|
16
|
+
Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
|
17
|
+
cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
|
18
|
+
IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
|
19
|
+
AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
|
20
|
+
YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
|
21
|
+
6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
|
22
|
+
Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
|
23
|
+
c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
|
24
|
+
mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
|
25
|
+
-----END CERTIFICATE-----
|
26
|
+
-----BEGIN CERTIFICATE-----
|
27
|
+
MIIFdDCCBFygAwIBAgIQJ2buVutJ846r13Ci/ITeIjANBgkqhkiG9w0BAQwFADBv
|
28
|
+
MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk
|
29
|
+
ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF
|
30
|
+
eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow
|
31
|
+
gYUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
|
32
|
+
BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYD
|
33
|
+
VQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkq
|
34
|
+
hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAkehUktIKVrGsDSTdxc9EZ3SZKzejfSNw
|
35
|
+
AHG8U9/E+ioSj0t/EFa9n3Byt2F/yUsPF6c947AEYe7/EZfH9IY+Cvo+XPmT5jR6
|
36
|
+
2RRr55yzhaCCenavcZDX7P0N+pxs+t+wgvQUfvm+xKYvT3+Zf7X8Z0NyvQwA1onr
|
37
|
+
ayzT7Y+YHBSrfuXjbvzYqOSSJNpDa2K4Vf3qwbxstovzDo2a5JtsaZn4eEgwRdWt
|
38
|
+
4Q08RWD8MpZRJ7xnw8outmvqRsfHIKCxH2XeSAi6pE6p8oNGN4Tr6MyBSENnTnIq
|
39
|
+
m1y9TBsoilwie7SrmNnu4FGDwwlGTm0+mfqVF9p8M1dBPI1R7Qu2XK8sYxrfV8g/
|
40
|
+
vOldxJuvRZnio1oktLqpVj3Pb6r/SVi+8Kj/9Lit6Tf7urj0Czr56ENCHonYhMsT
|
41
|
+
8dm74YlguIwoVqwUHZwK53Hrzw7dPamWoUi9PPevtQ0iTMARgexWO/bTouJbt7IE
|
42
|
+
IlKVgJNp6I5MZfGRAy1wdALqi2cVKWlSArvX31BqVUa/oKMoYX9w0MOiqiwhqkfO
|
43
|
+
KJwGRXa/ghgntNWutMtQ5mv0TIZxMOmm3xaG4Nj/QN370EKIf6MzOi5cHkERgWPO
|
44
|
+
GHFrK+ymircxXDpqR+DDeVnWIBqv8mqYqnK8V0rSS527EPywTEHl7R09XiidnMy/
|
45
|
+
s1Hap0flhFMCAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTvA73g
|
46
|
+
JMtUGjAdBgNVHQ4EFgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQD
|
47
|
+
AgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1UdHwQ9
|
48
|
+
MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4dGVy
|
49
|
+
bmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6
|
50
|
+
Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggEBAGS/g/FfmoXQ
|
51
|
+
zbihKVcN6Fr30ek+8nYEbvFScLsePP9NDXRqzIGCJdPDoCpdTPW6i6FtxFQJdcfj
|
52
|
+
Jw5dhHk3QBN39bSsHNA7qxcS1u80GH4r6XnTq1dFDK8o+tDb5VCViLvfhVdpfZLY
|
53
|
+
Uspzgb8c8+a4bmYRBbMelC1/kZWSWfFMzqORcUx8Rww7Cxn2obFshj5cqsQugsv5
|
54
|
+
B5a6SE2Q8pTIqXOi6wZ7I53eovNNVZ96YUWYGGjHXkBrI/V5eu+MtWuLt29G9Hvx
|
55
|
+
PUsE2JOAWVrgQSQdso8VYFhH2+9uRv0V9dlfmrPb2LjkQLPNlzmuhbsdjrzch5vR
|
56
|
+
pu/xO28QOG8=
|
57
|
+
-----END CERTIFICATE-----
|
58
|
+
-----BEGIN CERTIFICATE-----
|
59
|
+
MIIGCDCCA/CgAwIBAgIQKy5u6tl1NmwUim7bo3yMBzANBgkqhkiG9w0BAQwFADCB
|
60
|
+
hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
|
61
|
+
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
|
62
|
+
BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwMjEy
|
63
|
+
MDAwMDAwWhcNMjkwMjExMjM1OTU5WjCBkDELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
|
64
|
+
EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
|
65
|
+
Q09NT0RPIENBIExpbWl0ZWQxNjA0BgNVBAMTLUNPTU9ETyBSU0EgRG9tYWluIFZh
|
66
|
+
bGlkYXRpb24gU2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
67
|
+
ADCCAQoCggEBAI7CAhnhoFmk6zg1jSz9AdDTScBkxwtiBUUWOqigwAwCfx3M28Sh
|
68
|
+
bXcDow+G+eMGnD4LgYqbSRutA776S9uMIO3Vzl5ljj4Nr0zCsLdFXlIvNN5IJGS0
|
69
|
+
Qa4Al/e+Z96e0HqnU4A7fK31llVvl0cKfIWLIpeNs4TgllfQcBhglo/uLQeTnaG6
|
70
|
+
ytHNe+nEKpooIZFNb5JPJaXyejXdJtxGpdCsWTWM/06RQ1A/WZMebFEh7lgUq/51
|
71
|
+
UHg+TLAchhP6a5i84DuUHoVS3AOTJBhuyydRReZw3iVDpA3hSqXttn7IzW3uLh0n
|
72
|
+
c13cRTCAquOyQQuvvUSH2rnlG51/ruWFgqUCAwEAAaOCAWUwggFhMB8GA1UdIwQY
|
73
|
+
MBaAFLuvfgI9+qbxPISOre44mOzZMjLUMB0GA1UdDgQWBBSQr2o6lFoL2JDqElZz
|
74
|
+
30O0Oija5zAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNV
|
75
|
+
HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgG
|
76
|
+
BmeBDAECATBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNv
|
77
|
+
bS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggrBgEFBQcB
|
78
|
+
AQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9E
|
79
|
+
T1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21v
|
80
|
+
ZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAE4rdk+SHGI2ibp3wScF9BzWRJ2p
|
81
|
+
mj6q1WZmAT7qSeaiNbz69t2Vjpk1mA42GHWx3d1Qcnyu3HeIzg/3kCDKo2cuH1Z/
|
82
|
+
e+FE6kKVxF0NAVBGFfKBiVlsit2M8RKhjTpCipj4SzR7JzsItG8kO3KdY3RYPBps
|
83
|
+
P0/HEZrIqPW1N+8QRcZs2eBelSaz662jue5/DJpmNXMyYE7l3YphLG5SEXdoltMY
|
84
|
+
dVEVABt0iN3hxzgEQyjpFv3ZBdRdRydg1vs4O2xyopT4Qhrf7W8GjEXCBgCq5Ojc
|
85
|
+
2bXhc3js9iPc0d1sjhqPpepUfJa3w/5Vjo1JXvxku88+vZbrac2/4EjxYoIQ5QxG
|
86
|
+
V/Iz2tDIY+3GH5QFlkoakdH368+PUq4NCNk+qKBR6cGHdNXJ93SrLlP7u3r7l+L4
|
87
|
+
HyaPs9Kg4DdbKDsx5Q5XLVq4rXmsXiBmGqW5prU5wfWYQ//u+aen/e7KJD2AFsQX
|
88
|
+
j4rBYKEMrltDR5FL1ZoXX/nUh8HCjLfn4g8wGTeGrODcQgPmlKidrv0PJFGUzpII
|
89
|
+
0fxQ8ANAe4hZ7Q7drNJ3gjTcBpUC2JD5Leo31Rpg0Gcg19hCC0Wvgmje3WYkN5Ap
|
90
|
+
lBlGGSW4gNfL1IYoakRwJiNiqZ+Gb7+6kHDSVneFeO/qJakXzlByjAA6quPbYzSf
|
91
|
+
+AZxAeKCINT+b72x
|
92
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'grpc'
|
3
|
+
# Tweak the load path so ruby_robot_services_pb can
|
4
|
+
# load ruby_robot_pb
|
5
|
+
$: << File.dirname(__FILE__) + '/../grpc_ruby'
|
6
|
+
require 'ruby_robot/grpc/ruby_robot_services_pb'
|
7
|
+
require 'logger'
|
8
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
|
9
|
+
require 'ruby_robot'
|
10
|
+
|
11
|
+
module RubyRobot
|
12
|
+
module Grpc
|
13
|
+
class RobotService < ::RubyRobot::RubyRobot::Service
|
14
|
+
def logger
|
15
|
+
@logger ||= proc {
|
16
|
+
Logger.new(STDOUT)
|
17
|
+
}.call
|
18
|
+
end
|
19
|
+
|
20
|
+
def robot
|
21
|
+
@@robot ||= proc {
|
22
|
+
rr = ::RubyRobot::Shell.new
|
23
|
+
def rr.placed?
|
24
|
+
!@robot.nil?
|
25
|
+
end
|
26
|
+
rr
|
27
|
+
}.call
|
28
|
+
end
|
29
|
+
|
30
|
+
def not_placed_error
|
31
|
+
::RubyRobot::RubyRobotResponse.new(
|
32
|
+
error: ::RubyRobot::RubyRobotError.new(error: 400, message: "Robot is not currently placed")
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
def position_report
|
37
|
+
rr = robot.REPORT(false)
|
38
|
+
|
39
|
+
::RubyRobot::RubyRobotResponse.new(
|
40
|
+
current_state: ::RubyRobot::RubyRobotRequest.new(
|
41
|
+
x: rr[:x],
|
42
|
+
y: rr[:y],
|
43
|
+
direction: rr[:direction].to_s.upcase.to_sym
|
44
|
+
)
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
def left(empty, _unused_call)
|
49
|
+
logger.info "#{__method__} called (robot.placed?==#{robot.placed?})"
|
50
|
+
if robot.placed?
|
51
|
+
robot.LEFT
|
52
|
+
position_report
|
53
|
+
else
|
54
|
+
not_placed_error
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def move(empty, _unused_call)
|
59
|
+
logger.info "#{__method__} called (robot.placed?==#{robot.placed?})"
|
60
|
+
if robot.placed?
|
61
|
+
robot.MOVE
|
62
|
+
position_report
|
63
|
+
else
|
64
|
+
not_placed_error
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def place(robot_request, _unused_call)
|
69
|
+
input = { x: robot_request.x, y: robot_request.y, direction: robot_request.direction }
|
70
|
+
logger.info "#{__method__} called with #{input.to_json}"
|
71
|
+
|
72
|
+
robot.PLACE(robot_request.x, robot_request.y, robot_request.direction.to_s.downcase)
|
73
|
+
position_report
|
74
|
+
end
|
75
|
+
|
76
|
+
def remove(empty, _unused_call)
|
77
|
+
logger.info "#{__method__} called"
|
78
|
+
@@robot = nil
|
79
|
+
::Google::Protobuf::Empty.new
|
80
|
+
end
|
81
|
+
|
82
|
+
def report(empty, _unused_call)
|
83
|
+
logger.info "#{__method__} called (robot.placed?==#{robot.placed?})"
|
84
|
+
if robot.placed?
|
85
|
+
position_report
|
86
|
+
else
|
87
|
+
not_placed_error
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def right(empty, _unused_call)
|
92
|
+
logger.info "#{__method__} called (robot.placed?==#{robot.placed?})"
|
93
|
+
if robot.placed?
|
94
|
+
robot.RIGHT
|
95
|
+
position_report
|
96
|
+
else
|
97
|
+
not_placed_error
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# Source: ruby_robot.proto for package 'RubyRobot'
|
3
|
+
# Original file comments:
|
4
|
+
#
|
5
|
+
# gRPC service definition for the RubyRobot.
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'grpc'
|
9
|
+
require 'ruby_robot_pb'
|
10
|
+
|
11
|
+
module RubyRobot
|
12
|
+
module RubyRobot
|
13
|
+
#
|
14
|
+
# Service definitions
|
15
|
+
#
|
16
|
+
class Service
|
17
|
+
|
18
|
+
include GRPC::GenericService
|
19
|
+
|
20
|
+
self.marshal_class_method = :encode
|
21
|
+
self.unmarshal_class_method = :decode
|
22
|
+
self.service_name = 'RubyRobot.RubyRobot'
|
23
|
+
|
24
|
+
rpc :Left, Google::Protobuf::Empty, RubyRobotResponse
|
25
|
+
rpc :Move, Google::Protobuf::Empty, RubyRobotResponse
|
26
|
+
rpc :Place, RubyRobotRequest, RubyRobotResponse
|
27
|
+
rpc :Remove, Google::Protobuf::Empty, Google::Protobuf::Empty
|
28
|
+
rpc :Report, Google::Protobuf::Empty, RubyRobotResponse
|
29
|
+
rpc :Right, Google::Protobuf::Empty, RubyRobotResponse
|
30
|
+
end
|
31
|
+
|
32
|
+
Stub = Service.rpc_stub_class
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'ruby_robot/grpc_ruby/ruby_robot_pb'
|
2
|
+
#
|
3
|
+
# Define #to_json on ::RubyRobot::RubyRobotRequest for prettier printing.
|
4
|
+
#
|
5
|
+
module RubyRobot
|
6
|
+
class RubyRobotRequest
|
7
|
+
def to_json
|
8
|
+
{
|
9
|
+
x: self.x,
|
10
|
+
y: self.y,
|
11
|
+
direction: self.direction.to_s
|
12
|
+
}.to_json
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# source: ruby_robot.proto
|
3
|
+
|
4
|
+
require 'google/protobuf'
|
5
|
+
|
6
|
+
require 'google/protobuf/empty_pb'
|
7
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
8
|
+
add_message "RubyRobot.RubyRobotRequest" do
|
9
|
+
optional :x, :int32, 1
|
10
|
+
optional :y, :int32, 2
|
11
|
+
optional :direction, :enum, 3, "RubyRobot.RubyRobotRequest.Direction"
|
12
|
+
end
|
13
|
+
add_enum "RubyRobot.RubyRobotRequest.Direction" do
|
14
|
+
value :NORTH, 0
|
15
|
+
value :EAST, 1
|
16
|
+
value :SOUTH, 2
|
17
|
+
value :WEST, 3
|
18
|
+
end
|
19
|
+
add_message "RubyRobot.RubyRobotError" do
|
20
|
+
optional :error, :int32, 1
|
21
|
+
optional :message, :string, 2
|
22
|
+
end
|
23
|
+
add_message "RubyRobot.RubyRobotResponse" do
|
24
|
+
oneof :response do
|
25
|
+
optional :current_state, :message, 1, "RubyRobot.RubyRobotRequest"
|
26
|
+
optional :error, :message, 2, "RubyRobot.RubyRobotError"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module RubyRobot
|
32
|
+
RubyRobotRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("RubyRobot.RubyRobotRequest").msgclass
|
33
|
+
RubyRobotRequest::Direction = Google::Protobuf::DescriptorPool.generated_pool.lookup("RubyRobot.RubyRobotRequest.Direction").enummodule
|
34
|
+
RubyRobotError = Google::Protobuf::DescriptorPool.generated_pool.lookup("RubyRobot.RubyRobotError").msgclass
|
35
|
+
RubyRobotResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("RubyRobot.RubyRobotResponse").msgclass
|
36
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'bombshell'
|
2
|
+
require 'logger'
|
3
|
+
require 'ruby_robot/shell'
|
4
|
+
require 'ruby_robot/grpc_helper'
|
5
|
+
$: << File.dirname(__FILE__) + '/grpc_ruby'
|
6
|
+
require 'ruby_robot/grpc/ruby_robot_services_pb'
|
7
|
+
|
8
|
+
module RubyRobot
|
9
|
+
#
|
10
|
+
# Override all methods inherited from Shell
|
11
|
+
# such that they use gRPC to communicate
|
12
|
+
# with a remote Robot.
|
13
|
+
#
|
14
|
+
# TODO: RPC error handling (more info at
|
15
|
+
# https://grpc.io/docs/guides/error.html).
|
16
|
+
#
|
17
|
+
class GrpcShell < ::Bombshell::Environment
|
18
|
+
include ::Bombshell::Shell
|
19
|
+
|
20
|
+
prompt_with 'ILoveNetflixStudio&gRPC'
|
21
|
+
|
22
|
+
# TODO: Figure out if there's a way to pass args down into
|
23
|
+
# ::Bombshell#launch so this isn't a class attr.
|
24
|
+
def self.remote_url=(new_url)
|
25
|
+
# Convert to URI if String
|
26
|
+
@@remote_url = new_url.kind_of?(String) ? URI.parse(new_url) : new_url
|
27
|
+
end
|
28
|
+
def initialize
|
29
|
+
# TODO: Enable SSL/TLS
|
30
|
+
# Totally cheating here: if URI is grpc://netflix.avilla.net,
|
31
|
+
# then load up the cert (stored in the gem).
|
32
|
+
if @@remote_url.to_s.start_with?("grpcs://netflix.avilla.net")
|
33
|
+
ca_path = File.join(File.dirname(__FILE__), "cacerts.crt")
|
34
|
+
channel_creds = GRPC::Core::ChannelCredentials.new(File.read(ca_path))
|
35
|
+
stub_opts = {
|
36
|
+
:creds => channel_creds,
|
37
|
+
GRPC::Core::Channel::SSL_TARGET => @@remote_url.host
|
38
|
+
}
|
39
|
+
@stub = ::RubyRobot::RubyRobot::Stub.new(
|
40
|
+
"#{@@remote_url.host}:#{@@remote_url.port}", channel_creds
|
41
|
+
)
|
42
|
+
else
|
43
|
+
@stub = ::RubyRobot::RubyRobot::Stub.new("#{@@remote_url.host}:#{@@remote_url.port}", :this_channel_is_insecure)
|
44
|
+
end
|
45
|
+
puts "Checking state of Robot at #{@@remote_url}"
|
46
|
+
self.REPORT()
|
47
|
+
end
|
48
|
+
|
49
|
+
def PLACE(x, y, direction)
|
50
|
+
@stub.place(::RubyRobot::RubyRobotRequest.new(x: x, y: y, direction: direction.to_s.upcase.to_sym))
|
51
|
+
end
|
52
|
+
|
53
|
+
def MOVE
|
54
|
+
@stub.move(Google::Protobuf::Empty.new)
|
55
|
+
end
|
56
|
+
|
57
|
+
def LEFT
|
58
|
+
@stub.left(Google::Protobuf::Empty.new)
|
59
|
+
end
|
60
|
+
|
61
|
+
def RIGHT
|
62
|
+
@stub.right(Google::Protobuf::Empty.new)
|
63
|
+
end
|
64
|
+
|
65
|
+
def REPORT(to_stderr=false)
|
66
|
+
resp = @stub.report(Google::Protobuf::Empty.new)
|
67
|
+
if resp.error
|
68
|
+
puts resp.error.message
|
69
|
+
else
|
70
|
+
puts resp.current_state.to_json
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def REMOVE
|
75
|
+
@stub.remove(Google::Protobuf::Empty.new)
|
76
|
+
end
|
77
|
+
|
78
|
+
alias :QUIT :quit
|
79
|
+
end
|
80
|
+
end
|
81
|
+
module Bombshell
|
82
|
+
module Shell
|
83
|
+
REMOVE=:remove
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module RubyRobot
|
2
|
+
class Robot
|
3
|
+
|
4
|
+
# Directions are clockwise from north
|
5
|
+
VALID_DIRECTIONS = [:north, :east, :south, :west]
|
6
|
+
|
7
|
+
attr_reader :direction
|
8
|
+
attr_reader :tabletop
|
9
|
+
|
10
|
+
def initialize(direction)
|
11
|
+
orig_direction = direction
|
12
|
+
err_msg = "New Robots must have direction value of one of the following symbols: #{VALID_DIRECTIONS.join(', ')}; invalid value '#{orig_direction}'"
|
13
|
+
direction = direction.kind_of?(String) ? direction.downcase.to_sym : direction
|
14
|
+
raise ConstructionError.new(err_msg) unless VALID_DIRECTIONS.include?(direction)
|
15
|
+
@direction = direction
|
16
|
+
@tabletop = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def inspect
|
20
|
+
case @direction
|
21
|
+
when :north then "^"
|
22
|
+
when :south then "|"
|
23
|
+
when :east then ">"
|
24
|
+
# :west
|
25
|
+
else "<"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def left
|
30
|
+
# A little cheating here...index -1 will effectively wrap around and
|
31
|
+
# return the last element
|
32
|
+
@direction = VALID_DIRECTIONS[dir_idx - 1]
|
33
|
+
end
|
34
|
+
|
35
|
+
def right
|
36
|
+
@direction = VALID_DIRECTIONS[(dir_idx + 1) % VALID_DIRECTIONS.size]
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Called by a Tabletop where this has been placed
|
41
|
+
#
|
42
|
+
def place(tabletop)
|
43
|
+
@tabletop = tabletop
|
44
|
+
end
|
45
|
+
|
46
|
+
def report
|
47
|
+
@tabletop.position(self).merge(direction: direction)
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# TODO: Error checking for if @tabletop.nil?
|
52
|
+
# Also, @tabletop.move and @tabletop.move? together
|
53
|
+
# should be synchronized if multithreaded where > 1
|
54
|
+
# Robot are on a Tabletop.
|
55
|
+
#
|
56
|
+
# Return #report after call, whether it was successful
|
57
|
+
# or not (assuming it _is_ in fact placed on a board).
|
58
|
+
#
|
59
|
+
def move
|
60
|
+
@tabletop.move(self, direction) if @tabletop.move?(self, direction)
|
61
|
+
report
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def dir_idx
|
67
|
+
VALID_DIRECTIONS.index(@direction)
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|