vmsim 0.2.3
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.
- 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'
|