vmsim 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +27 -0
- data/README.txt +1 -0
- data/Rakefile +40 -0
- data/VERSION +1 -0
- data/bin/vmdeploy +23 -0
- data/bin/vmsim +37 -0
- data/doc/actuators_and_sensors.txt +32 -0
- data/doc/handout.odt +0 -0
- data/doc/machine.jpg +0 -0
- data/doc/todo.txt +25 -0
- data/lib/adapter/actuator_collection.rb +61 -0
- data/lib/adapter/sensor_collection.rb +57 -0
- data/lib/archive_builder.rb +64 -0
- data/lib/control/main.rb +21 -0
- data/lib/control.rb +3 -0
- data/lib/deploy/deployer.rb +96 -0
- data/lib/deploy.rb +1 -0
- data/lib/devices/devices.rb +73 -0
- data/lib/devices.rb +1 -0
- data/lib/gui/SimulatorGui.gtk +289 -0
- data/lib/gui/simulator_gtk.rb +57 -0
- data/lib/gui/simulator_gui.rb +64 -0
- data/lib/gui.rb +2 -0
- data/lib/hardware/bin.rb +28 -0
- data/lib/hardware/button.rb +18 -0
- data/lib/hardware/can.rb +9 -0
- data/lib/hardware/cash_register.rb +79 -0
- data/lib/hardware/component.rb +56 -0
- data/lib/hardware/display.rb +29 -0
- data/lib/hardware/drawer.rb +45 -0
- data/lib/hardware/enum.rb +20 -0
- data/lib/hardware/simulator.rb +98 -0
- data/lib/hardware.rb +10 -0
- data/lib/hardware_adapter.rb +11 -0
- data/lib/vmlog.rb +5 -0
- data/test/adapter/actuator_collection_test.rb +106 -0
- data/test/adapter/sensor_collection_test.rb +51 -0
- data/test/deploy/deployer_test.rb +114 -0
- data/test/deploy/was_run.sh +5 -0
- data/test/devices/devices_test.rb +78 -0
- data/test/hardware/bin_test.rb +57 -0
- data/test/hardware/button_test.rb +23 -0
- data/test/hardware/can_test.rb +11 -0
- data/test/hardware/cash_register_test.rb +157 -0
- data/test/hardware/component_test.rb +37 -0
- data/test/hardware/display_test.rb +94 -0
- data/test/hardware/drawer_test.rb +100 -0
- data/test/hardware/enum_test.rb +33 -0
- data/test/hardware/simulator_test.rb +189 -0
- data/test/test_helper.rb +5 -0
- data/vmsim.gemspec +89 -0
- metadata +131 -0
data/.autotest
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
class Autotest
|
2
|
+
def path_to_classname(s)
|
3
|
+
sep = File::SEPARATOR
|
4
|
+
f = s.sub(/^test#{sep}/, '').sub(/\.rb$/, '').split(sep)
|
5
|
+
f = f.map { |path| path.split(/_|(\d+)/).map { |seg| seg.capitalize }.join }
|
6
|
+
|
7
|
+
f.join('::')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
Autotest.add_hook :initialize do |autotest|
|
13
|
+
autotest.add_mapping(%r%^test/.*\.rb$%) do |filename, _|
|
14
|
+
filename
|
15
|
+
end
|
16
|
+
autotest.add_mapping(%r%^lib/(.*)\.rb$%) do |_, m|
|
17
|
+
["test/#{m[1]}_test.rb"]
|
18
|
+
end
|
19
|
+
autotest.add_mapping(%r%^test/test_helper.rb$%) do
|
20
|
+
files_matching %r%^test/.*_test\.rb$%
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
Autotest.add_discovery do
|
26
|
+
"testunit"
|
27
|
+
end
|
data/README.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
vendingmachine exercise in Ruby
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
#Gem::manage_gems
|
3
|
+
require 'rubygems/package_task'
|
4
|
+
require 'rake/testtask'
|
5
|
+
|
6
|
+
|
7
|
+
desc 'Running all unit tests'
|
8
|
+
task :default => :test
|
9
|
+
|
10
|
+
Rake::TestTask.new(:test) do |t|
|
11
|
+
t.test_files = FileList['test/**/*test.rb', 'test/*test.rb']
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'Measures test coverage'
|
15
|
+
task :coverage do
|
16
|
+
rm_f "coverage"
|
17
|
+
rm_f "coverage.data"
|
18
|
+
rcov = "rcov --aggregate coverage.data"
|
19
|
+
system("#{rcov} --html test/*test.rb")
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
require 'jeweler'
|
24
|
+
Jeweler::Tasks.new do |gem|
|
25
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
26
|
+
gem.name = "vmsim"
|
27
|
+
gem.executables << 'vmsim'
|
28
|
+
gem.executables << 'vmdeploy'
|
29
|
+
gem.license = "MIT"
|
30
|
+
gem.summary = %Q{Vending machine simulator - part of the vendingmachine tdd bdd case}
|
31
|
+
gem.description = %Q{Vending machine; this simulator starts a vendingmachine ui which behaviour can be programmed with control code}
|
32
|
+
gem.email = "info@qwan.it"
|
33
|
+
gem.authors = ["Rob Westgeest, Marc Evers, Willem van den Ende"]
|
34
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
35
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
36
|
+
#gem.add_runtime_dependency 'gtk2', '>= 1.0.3'
|
37
|
+
gem.add_development_dependency 'mocha', '> 0.9.8'
|
38
|
+
end
|
39
|
+
Jeweler::RubygemsDotOrgTasks.new
|
40
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.3
|
data/bin/vmdeploy
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.join(File.dirname(__FILE__),'..','lib')
|
3
|
+
|
4
|
+
require 'deploy'
|
5
|
+
|
6
|
+
def usage(errormessage = "")
|
7
|
+
puts errormessage
|
8
|
+
puts "usage: "
|
9
|
+
puts " vmdeploy <archive> [executable]"
|
10
|
+
puts ""
|
11
|
+
puts " archive : the archive to deploy"
|
12
|
+
puts " executable: the executable to execute after deployment - default : 'vmsim'"
|
13
|
+
puts ""
|
14
|
+
exit 1
|
15
|
+
end
|
16
|
+
|
17
|
+
archive = ARGV[0]
|
18
|
+
executable = ARGV[1] || 'vmsim'
|
19
|
+
usage unless archive
|
20
|
+
usage("archive #{archive} does not exist") unless File.exists?(archive)
|
21
|
+
|
22
|
+
Deploy::Deployer.new(executable).deploy ARGV[0]
|
23
|
+
|
data/bin/vmsim
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$: << File.expand_path(File.join(File.dirname(__FILE__),'..','lib'))
|
4
|
+
require 'fileutils'
|
5
|
+
require 'hardware_adapter'
|
6
|
+
require 'hardware'
|
7
|
+
require 'gui'
|
8
|
+
|
9
|
+
simulator = Hardware::Simulator.new
|
10
|
+
simulator.assemble_hardware
|
11
|
+
|
12
|
+
simulator_gui = Gui::SimulatorGui.new(simulator)
|
13
|
+
simulator_gui.show
|
14
|
+
|
15
|
+
simulator.on_boot do
|
16
|
+
simulator.drawer(0).fill(Hardware::Can.cola, 2, 0)
|
17
|
+
simulator.drawer(1).fill(Hardware::Can.fanta, 2, 0)
|
18
|
+
simulator.drawer(2).fill(Hardware::Can.sprite, 2, 0)
|
19
|
+
simulator.drawer(3).fill(Hardware::Can.sisi, 2, 0)
|
20
|
+
|
21
|
+
simulator.cash_register.fill(Hardware::Coin.two_euro, 3, 0)
|
22
|
+
simulator.cash_register.fill(Hardware::Coin.one_euro, 3, 0)
|
23
|
+
simulator.cash_register.fill(Hardware::Coin.fifty_cents, 3, 0)
|
24
|
+
end
|
25
|
+
|
26
|
+
FileUtils.cd(File.expand_path('~/.vendingmachine/control')) do
|
27
|
+
$: << 'lib'
|
28
|
+
load 'main.rb'
|
29
|
+
Control.main if defined?(Control.main)
|
30
|
+
end
|
31
|
+
|
32
|
+
simulator.boot
|
33
|
+
|
34
|
+
while !simulator_gui.stopped? do
|
35
|
+
Gtk.main_iteration while Gtk.events_pending?
|
36
|
+
end
|
37
|
+
puts "vending machine going home drunk"
|
@@ -0,0 +1,32 @@
|
|
1
|
+
actuators
|
2
|
+
:cash_drop_100
|
3
|
+
:cash_drop_200
|
4
|
+
:cash_drop_50
|
5
|
+
:display_show, <line>, <message>
|
6
|
+
:drawer_drop_can_0
|
7
|
+
:drawer_drop_can_1
|
8
|
+
:drawer_drop_can_2
|
9
|
+
:drawer_drop_can_3
|
10
|
+
|
11
|
+
|
12
|
+
sensors
|
13
|
+
:bin_entry
|
14
|
+
:bin_fetch_all
|
15
|
+
:button_press_0
|
16
|
+
:button_press_1
|
17
|
+
:button_press_2
|
18
|
+
:button_press_3
|
19
|
+
:cash_fill_100
|
20
|
+
:cash_fill_200
|
21
|
+
:cash_fill_50
|
22
|
+
:cash_insert_100
|
23
|
+
:cash_insert_200
|
24
|
+
:cash_insert_50
|
25
|
+
:drawer_drop_can_0
|
26
|
+
:drawer_drop_can_1
|
27
|
+
:drawer_drop_can_2
|
28
|
+
:drawer_drop_can_3
|
29
|
+
:drawer_fill_can_0
|
30
|
+
:drawer_fill_can_1
|
31
|
+
:drawer_fill_can_2
|
32
|
+
:drawer_fill_can_3
|
data/doc/handout.odt
ADDED
Binary file
|
data/doc/machine.jpg
ADDED
Binary file
|
data/doc/todo.txt
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
- vmsim start - required in ~/.vendingmachine/control/main.rb
|
2
|
+
- zut in gem
|
3
|
+
- gem voor
|
4
|
+
- api voor display (show (line, message))
|
5
|
+
Devices.display_show(line, message)
|
6
|
+
Devices.on_button_pressed(0) { }
|
7
|
+
|
8
|
+
Devices.get_display().show(line, message)
|
9
|
+
Actuators(:display).fire(:show, line, message)
|
10
|
+
- api voor buttons (list, on_pres(0))
|
11
|
+
VM.get_button(0).on_press { }
|
12
|
+
Sensors.on(
|
13
|
+
- api voor drawers (on_pres(0), drop(0))
|
14
|
+
VM.get_drawer(0).drop()
|
15
|
+
- api voor bin (on_entry, on_fetch_all)
|
16
|
+
- api voor cashregister (on_fill(100), on_insert(100), drop(100))
|
17
|
+
|
18
|
+
============== DONEDONEDONE ====================
|
19
|
+
- vmdeploy exe
|
20
|
+
- vmdeploy
|
21
|
+
- stopt vmsim als running
|
22
|
+
-
|
23
|
+
- start vmsim
|
24
|
+
|
25
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Adapter
|
2
|
+
class NoActuatorBlockGiven < Exception
|
3
|
+
end
|
4
|
+
class DuplicateActuatorException < Exception
|
5
|
+
end
|
6
|
+
class NoSuchActuatorException < Exception
|
7
|
+
end
|
8
|
+
|
9
|
+
class AsynchronousFirer
|
10
|
+
attr_reader :block
|
11
|
+
protected :block
|
12
|
+
|
13
|
+
def initialize(&block)
|
14
|
+
@block = block
|
15
|
+
end
|
16
|
+
|
17
|
+
def fire(*params)
|
18
|
+
Thread.start { block.call(*params) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class SynchronousFirer < AsynchronousFirer
|
23
|
+
def fire(*params)
|
24
|
+
block.call *params
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
class ActuatorCollection
|
30
|
+
class Null
|
31
|
+
def create_actuator_for(actuator_name, &block)
|
32
|
+
end
|
33
|
+
def fire(actuator_name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.null
|
38
|
+
Null.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize(firer_class = AsynchronousFirer)
|
42
|
+
@actuators = {}
|
43
|
+
@firer_class = firer_class
|
44
|
+
end
|
45
|
+
|
46
|
+
def list
|
47
|
+
@actuators.entries.collect {|e| e[0].to_s}.sort.collect{|e| e.to_sym}
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_actuator_for(actuator_name, &block)
|
51
|
+
raise NoActuatorBlockGiven.new("must supply a code block for an actuator - none given") unless block_given?
|
52
|
+
raise DuplicateActuatorException.new("actuator :#{actuator_name} already exists") if @actuators.has_key?(actuator_name)
|
53
|
+
@actuators[actuator_name.to_sym] = @firer_class.new(&block)
|
54
|
+
end
|
55
|
+
|
56
|
+
def fire(actuator_name, *params)
|
57
|
+
raise NoSuchActuatorException.new("actuator :#{actuator_name} does not exist") unless @actuators.has_key?(actuator_name)
|
58
|
+
@actuators[actuator_name.to_sym].fire(*params)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Adapter
|
2
|
+
class Sensor
|
3
|
+
def fire
|
4
|
+
@on_fire_block.call if @on_fire_block
|
5
|
+
end
|
6
|
+
def on_fire_do(&block)
|
7
|
+
@on_fire_block = block
|
8
|
+
end
|
9
|
+
def remove_fire_listener
|
10
|
+
@on_fire_block = nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class NoSuchSensorException < Exception
|
15
|
+
end
|
16
|
+
|
17
|
+
class SensorCollection
|
18
|
+
class Null
|
19
|
+
def on(sensor)
|
20
|
+
end
|
21
|
+
def create_sensor_for(event)
|
22
|
+
end
|
23
|
+
def fire(sensor)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@sensors = {}
|
29
|
+
@sensors.default = Sensor.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.null
|
33
|
+
Null.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def list
|
37
|
+
@sensors.entries.collect { |e| e[0].to_s }.sort.collect{ |e| e.to_sym }
|
38
|
+
end
|
39
|
+
|
40
|
+
def on(sensor, &block)
|
41
|
+
raise NoSuchSensorException.new("sensor :#{sensor} does not exist") unless @sensors.has_key?(sensor.to_sym)
|
42
|
+
@sensors[sensor.to_sym].on_fire_do(&block)
|
43
|
+
end
|
44
|
+
|
45
|
+
def create_sensor_for(event)
|
46
|
+
@sensors[event.to_sym] = Sensor.new
|
47
|
+
end
|
48
|
+
|
49
|
+
def fire(sensor)
|
50
|
+
@sensors[sensor.to_sym].fire
|
51
|
+
end
|
52
|
+
|
53
|
+
def remove_fire_listeners
|
54
|
+
@sensors.collect {|name, sensor| sensor.remove_fire_listener }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
module ArchiveBuilder
|
3
|
+
|
4
|
+
def an_archive(filename, work_dir = Dir.tmpdir, &block)
|
5
|
+
archive = ArchiveBuilder.new(filename, work_dir)
|
6
|
+
archive.in_work_dir(&block) if block_given?
|
7
|
+
return archive.build.file_path
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'fileutils'
|
11
|
+
class ArchiveBuilder
|
12
|
+
include FileUtils
|
13
|
+
def initialize(filename, work_dir = Dir.tmpdir)
|
14
|
+
@filename = filename
|
15
|
+
@work_dir = File.join(work_dir, 'archive_builder')
|
16
|
+
end
|
17
|
+
|
18
|
+
def a_file(filename)
|
19
|
+
FileBuilder.new(filename)
|
20
|
+
end
|
21
|
+
|
22
|
+
def in_work_dir(&block)
|
23
|
+
mk_work_dir
|
24
|
+
cd(@work_dir) do
|
25
|
+
instance_eval(&block)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def build
|
30
|
+
cd(@work_dir) do
|
31
|
+
system "zip -r #{@filename} * >> /dev/null"
|
32
|
+
end
|
33
|
+
return self
|
34
|
+
end
|
35
|
+
|
36
|
+
def file_path
|
37
|
+
File.join(@work_dir, @filename)
|
38
|
+
end
|
39
|
+
private
|
40
|
+
def mk_work_dir
|
41
|
+
rm_r(@work_dir) if File.exists?(@work_dir) && @work_dir =~ /^\/tmp/
|
42
|
+
mkdir_p(@work_dir) unless File.exists?(@work_dir)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class FileBuilder
|
47
|
+
include FileUtils
|
48
|
+
attr_reader :filename
|
49
|
+
def initialize(filename)
|
50
|
+
@filename = filename
|
51
|
+
end
|
52
|
+
|
53
|
+
def with(content)
|
54
|
+
create_dirs
|
55
|
+
File.open(filename, "w+") { |f| f.puts content }
|
56
|
+
return self
|
57
|
+
end
|
58
|
+
def create_dirs
|
59
|
+
dirname = File.dirname(filename)
|
60
|
+
mkdir_p dirname unless File.exists?(dirname)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
data/lib/control/main.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require "vmlog"
|
2
|
+
require 'devices'
|
3
|
+
|
4
|
+
include VMLog
|
5
|
+
|
6
|
+
module Control
|
7
|
+
def self.main
|
8
|
+
# here, you should load your vending machine control software
|
9
|
+
|
10
|
+
# as an example of using the actuators and sensors (see doc/actuators_and_sensors)
|
11
|
+
Devices.display_show(0, 'Choose')
|
12
|
+
Devices.display_show(1, 'Please...')
|
13
|
+
|
14
|
+
Devices.on_button_pressed(0) do
|
15
|
+
log "cola pressed"
|
16
|
+
|
17
|
+
Devices.display_show(0, 'Cola')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
data/lib/control.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
|
2
|
+
require 'fileutils'
|
3
|
+
module Deploy
|
4
|
+
def self.deploy(file)
|
5
|
+
Deployer.new(file).deploy
|
6
|
+
end
|
7
|
+
class Deployer
|
8
|
+
include FileUtils
|
9
|
+
DEPLOYED_DIR = File.expand_path("~/.vendingmachine/control")
|
10
|
+
PIDFILE = File.expand_path("~/.vendingmachine/pid")
|
11
|
+
|
12
|
+
attr_reader :executable, :current_pid
|
13
|
+
|
14
|
+
def initialize(executable)
|
15
|
+
@executable = executable
|
16
|
+
@log = ""
|
17
|
+
$: << DEPLOYED_DIR unless $:.include?(DEPLOYED_DIR)
|
18
|
+
end
|
19
|
+
|
20
|
+
def run_log
|
21
|
+
@log
|
22
|
+
end
|
23
|
+
|
24
|
+
def deploy(file_path)
|
25
|
+
create_deployment_environment
|
26
|
+
read_current_pid
|
27
|
+
kill_running_process
|
28
|
+
install_deployed_code(file_path)
|
29
|
+
start_deployed_code
|
30
|
+
end
|
31
|
+
|
32
|
+
def kill
|
33
|
+
read_current_pid
|
34
|
+
kill_running_process
|
35
|
+
end
|
36
|
+
|
37
|
+
def wait_for
|
38
|
+
@running_thread.join if @running_thread
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
def start_deployed_code
|
44
|
+
@running_thread = Thread.start do
|
45
|
+
IO.popen(executable) do |io|
|
46
|
+
save_current_pid io.pid
|
47
|
+
while !io.eof? do
|
48
|
+
@log << io.gets
|
49
|
+
end
|
50
|
+
end
|
51
|
+
clear_current_pid
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def install_deployed_code(file_path)
|
56
|
+
rm_r Dir.glob(File.join(DEPLOYED_DIR, '*'))
|
57
|
+
file_path = File.expand_path(file_path)
|
58
|
+
cd(DEPLOYED_DIR) do
|
59
|
+
sh "unzip #{file_path}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def kill_running_process
|
64
|
+
begin
|
65
|
+
p current_pid
|
66
|
+
Process.kill("SIGKILL", current_pid) if current_pid
|
67
|
+
rescue Errno::ESRCH => e
|
68
|
+
# thats fine
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def save_current_pid(pid)
|
73
|
+
@current_pid = pid
|
74
|
+
File.open(PIDFILE, 'w+') { |f| f.write(@current_pid.to_s) }
|
75
|
+
end
|
76
|
+
|
77
|
+
def read_current_pid
|
78
|
+
@current_pid = File.read(PIDFILE).to_i if File.exists?(PIDFILE)
|
79
|
+
end
|
80
|
+
|
81
|
+
def clear_current_pid
|
82
|
+
@current_pid = nil
|
83
|
+
rm PIDFILE if File.exists?(PIDFILE)
|
84
|
+
end
|
85
|
+
|
86
|
+
def create_deployment_environment
|
87
|
+
mkdir_p DEPLOYED_DIR unless File.exists?(DEPLOYED_DIR)
|
88
|
+
end
|
89
|
+
|
90
|
+
def sh(command)
|
91
|
+
system "#{command} >> /dev/null"
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
data/lib/deploy.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'deploy/deployer'
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'hardware_adapter'
|
2
|
+
module Devices
|
3
|
+
|
4
|
+
def self.method_missing(method_sym, *arguments, &block)
|
5
|
+
devices = Devices.new
|
6
|
+
devices.send(method_sym, *arguments, &block)
|
7
|
+
end
|
8
|
+
|
9
|
+
class Devices
|
10
|
+
def initialize(actuators = Adapter.actuators, sensors = Adapter.sensors)
|
11
|
+
@actuators = actuators
|
12
|
+
@sensors = sensors
|
13
|
+
end
|
14
|
+
|
15
|
+
# display a a message on the specified line on the display
|
16
|
+
# the line is a 0 based index in the available lines on the display
|
17
|
+
def display_show(line, message)
|
18
|
+
actuators.fire(:display_show, line, message)
|
19
|
+
end
|
20
|
+
|
21
|
+
# drops a coin in the bin where:
|
22
|
+
# coin is 50 100 or 200 cts
|
23
|
+
def cash_drop_coin(coin)
|
24
|
+
actuators.fire(:"cash_drop_#{coin}")
|
25
|
+
end
|
26
|
+
|
27
|
+
# register a handler on filling coin of a specific
|
28
|
+
# kind in the cash register
|
29
|
+
def on_cash_filled(coin, &block)
|
30
|
+
sensors.on(:"cash_fill_#{coin}", &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
# register a handler on inserting a specifica coin
|
34
|
+
# in the cash register as part of paying
|
35
|
+
def on_cash_inserted(coin, &block)
|
36
|
+
sensors.on(:"cash_insert_#{coin}", &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
# register a handler on getting something being dropped in the bin
|
40
|
+
def on_bin_entry(&block)
|
41
|
+
sensors.on(:bin_entry, &block)
|
42
|
+
end
|
43
|
+
|
44
|
+
# register a handler on sbdy getting stuff from the bin
|
45
|
+
def on_bin_fetch_all(&block)
|
46
|
+
sensors.on(:bin_fetch_all, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
# register a handleer on sbgy pressing a specific button
|
50
|
+
# where button can be one of 0 1 2 or three
|
51
|
+
def on_button_pressed(button, &block)
|
52
|
+
sensors.on(:"button_press_#{button}", &block)
|
53
|
+
end
|
54
|
+
|
55
|
+
# drops a can from a specified drawer
|
56
|
+
def drawer_drop_can(drawer)
|
57
|
+
actuators.fire(:"drawer_drop_can_#{drawer}")
|
58
|
+
end
|
59
|
+
|
60
|
+
# register a handler on a drawer dropping a can
|
61
|
+
def on_drawer_dropped(drawer, &block)
|
62
|
+
sensors.on(:"drawer_drop_can_#{drawer}", &block)
|
63
|
+
end
|
64
|
+
|
65
|
+
# register a handler on a drawer being filled with a can
|
66
|
+
def on_drawer_filled(drawer, &block)
|
67
|
+
sensors.on(:"drawer_fill_can_#{drawer}", &block)
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
attr_reader :actuators, :sensors
|
72
|
+
end
|
73
|
+
end
|
data/lib/devices.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'devices/devices'
|