statemachine 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. data/.gitignore +12 -0
  2. data/Gemfile +6 -0
  3. data/Gemfile.lock +12 -0
  4. data/Rakefile +21 -20
  5. data/doc/website/README +6 -0
  6. data/doc/website/config.yaml +2 -0
  7. data/doc/website/index.html +39 -0
  8. data/doc/website/src/default.css +110 -0
  9. data/doc/website/src/default.template +41 -0
  10. data/doc/website/src/documentation.page +45 -0
  11. data/doc/website/src/example.page +13 -0
  12. data/doc/website/src/example1.page +59 -0
  13. data/doc/website/src/example2.page +96 -0
  14. data/doc/website/src/example3.page +76 -0
  15. data/doc/website/src/example4.page +65 -0
  16. data/doc/website/src/images/8l_star.png +0 -0
  17. data/doc/website/src/images/bg.png +0 -0
  18. data/doc/website/src/images/bottom_border.png +0 -0
  19. data/doc/website/src/images/bottom_edge.png +0 -0
  20. data/doc/website/src/images/examples/vending_machine.png +0 -0
  21. data/doc/website/src/images/examples/vending_machine2.png +0 -0
  22. data/doc/website/src/images/examples/vending_machine3.png +0 -0
  23. data/doc/website/src/images/examples/vending_machine4a.png +0 -0
  24. data/doc/website/src/images/examples/vending_machine4b.png +0 -0
  25. data/doc/website/src/images/left_edge.png +0 -0
  26. data/doc/website/src/images/logo.png +0 -0
  27. data/doc/website/src/images/right_edge.png +0 -0
  28. data/doc/website/src/images/side_borders.png +0 -0
  29. data/doc/website/src/index.page +20 -0
  30. data/generate_tests/dot_graph/turnstile.rb +29 -0
  31. data/generate_tests/dot_graph/turnstile2.rb +48 -0
  32. data/generate_tests/java/turnstile.rb +54 -0
  33. data/generate_tests/java/turnstile2.rb +72 -0
  34. data/lib/statemachine/action_invokation.rb +0 -19
  35. data/lib/statemachine/version.rb +2 -2
  36. data/rails_plugin/README +183 -0
  37. data/rails_plugin/Rakefile +11 -0
  38. data/rails_plugin/app/controllers/admin_controller.rb +43 -0
  39. data/rails_plugin/app/controllers/application.rb +7 -0
  40. data/rails_plugin/app/controllers/main_controller.rb +34 -0
  41. data/rails_plugin/app/helpers/admin_helper.rb +2 -0
  42. data/rails_plugin/app/helpers/application_helper.rb +3 -0
  43. data/rails_plugin/app/helpers/main_helper.rb +7 -0
  44. data/rails_plugin/app/models/product.rb +21 -0
  45. data/rails_plugin/app/models/vending_machine.rb +36 -0
  46. data/rails_plugin/app/models/vending_machine_interface.rb +101 -0
  47. data/rails_plugin/app/models/vending_statemachine.rb +41 -0
  48. data/rails_plugin/app/views/admin/index.rhtml +45 -0
  49. data/rails_plugin/app/views/layouts/main.rhtml +12 -0
  50. data/rails_plugin/app/views/main/_info.rhtml +13 -0
  51. data/rails_plugin/app/views/main/event.rjs +27 -0
  52. data/rails_plugin/app/views/main/index.rhtml +38 -0
  53. data/rails_plugin/config/boot.rb +45 -0
  54. data/rails_plugin/config/database.yml +21 -0
  55. data/rails_plugin/config/environment.rb +60 -0
  56. data/rails_plugin/config/environments/development.rb +21 -0
  57. data/rails_plugin/config/environments/production.rb +18 -0
  58. data/rails_plugin/config/environments/test.rb +19 -0
  59. data/rails_plugin/config/routes.rb +23 -0
  60. data/rails_plugin/db/migrate/001_create_vending_machines.rb +12 -0
  61. data/rails_plugin/db/migrate/002_create_products.rb +14 -0
  62. data/rails_plugin/db/migrate/003_add_position_to_products.rb +9 -0
  63. data/rails_plugin/db/schema.rb +20 -0
  64. data/rails_plugin/doc/README_FOR_APP +2 -0
  65. data/rails_plugin/lib/tasks/base.rake +5 -0
  66. data/rails_plugin/public/.htaccess +40 -0
  67. data/rails_plugin/public/404.html +30 -0
  68. data/rails_plugin/public/500.html +30 -0
  69. data/rails_plugin/public/dispatch.cgi +10 -0
  70. data/rails_plugin/public/dispatch.fcgi +24 -0
  71. data/rails_plugin/public/dispatch.rb +10 -0
  72. data/rails_plugin/public/favicon.ico +0 -0
  73. data/rails_plugin/public/images/bricks.jpg +0 -0
  74. data/rails_plugin/public/images/cash_release_button.png +0 -0
  75. data/rails_plugin/public/images/change.png +0 -0
  76. data/rails_plugin/public/images/dime.png +0 -0
  77. data/rails_plugin/public/images/dollar.png +0 -0
  78. data/rails_plugin/public/images/money_panel.png +0 -0
  79. data/rails_plugin/public/images/nickel.png +0 -0
  80. data/rails_plugin/public/images/quarter.png +0 -0
  81. data/rails_plugin/public/images/rails.png +0 -0
  82. data/rails_plugin/public/images/vending_machine_body.png +0 -0
  83. data/rails_plugin/public/index.html +277 -0
  84. data/rails_plugin/public/javascripts/application.js +2 -0
  85. data/rails_plugin/public/javascripts/controls.js +833 -0
  86. data/rails_plugin/public/javascripts/dragdrop.js +942 -0
  87. data/rails_plugin/public/javascripts/effects.js +1088 -0
  88. data/rails_plugin/public/javascripts/prototype.js +2515 -0
  89. data/rails_plugin/public/robots.txt +1 -0
  90. data/rails_plugin/public/stylesheets/layout.css +163 -0
  91. data/rails_plugin/script/about +3 -0
  92. data/rails_plugin/script/breakpointer +3 -0
  93. data/rails_plugin/script/console +3 -0
  94. data/rails_plugin/script/destroy +3 -0
  95. data/rails_plugin/script/generate +3 -0
  96. data/rails_plugin/script/performance/benchmarker +3 -0
  97. data/rails_plugin/script/performance/profiler +3 -0
  98. data/rails_plugin/script/plugin +3 -0
  99. data/rails_plugin/script/process/inspector +3 -0
  100. data/rails_plugin/script/process/reaper +3 -0
  101. data/rails_plugin/script/process/spawner +3 -0
  102. data/rails_plugin/script/rails_spec +11 -0
  103. data/rails_plugin/script/rails_spec_server +43 -0
  104. data/rails_plugin/script/runner +3 -0
  105. data/rails_plugin/script/server +3 -0
  106. data/rails_plugin/spec/controllers/admin_controller_spec.rb +7 -0
  107. data/rails_plugin/spec/controllers/main_controller_spec.rb +38 -0
  108. data/rails_plugin/spec/fixtures/products.yml +2 -0
  109. data/rails_plugin/spec/fixtures/vending_machines.yml +2 -0
  110. data/rails_plugin/spec/helpers/admin_helper_spec.rb +5 -0
  111. data/rails_plugin/spec/helpers/main_helper_spec.rb +5 -0
  112. data/rails_plugin/spec/models/product_spec.rb +16 -0
  113. data/rails_plugin/spec/models/vending_machine_interface_spec.rb +168 -0
  114. data/rails_plugin/spec/models/vending_machine_spec.rb +30 -0
  115. data/rails_plugin/spec/models/vending_statemachine_spec.rb +130 -0
  116. data/rails_plugin/spec/plugins/context_support_spec.rb +28 -0
  117. data/rails_plugin/spec/plugins/controller_support_spec.rb +98 -0
  118. data/rails_plugin/spec/spec.opts +1 -0
  119. data/rails_plugin/spec/spec_helper.rb +28 -0
  120. data/rails_plugin/spec/views/main/event_spec.rb +61 -0
  121. data/rails_plugin/vendor/plugins/statemachine/README +4 -0
  122. data/rails_plugin/vendor/plugins/statemachine/Rakefile +22 -0
  123. data/rails_plugin/vendor/plugins/statemachine/init.rb +2 -0
  124. data/rails_plugin/vendor/plugins/statemachine/install.rb +1 -0
  125. data/rails_plugin/vendor/plugins/statemachine/lib/context_support.rb +22 -0
  126. data/rails_plugin/vendor/plugins/statemachine/lib/controller_support.rb +85 -0
  127. data/rails_plugin/vendor/plugins/statemachine/lib/statemachine_on_rails.rb +11 -0
  128. data/rails_plugin/vendor/plugins/statemachine/tasks/statemachine_tasks.rake +4 -0
  129. data/spec/action_invokation_spec.rb +1 -1
  130. data/spec/builder_spec.rb +1 -1
  131. data/spec/default_transition_spec.rb +1 -1
  132. data/spec/generate/dot_graph/dot_graph_stagemachine_spec.rb +1 -1
  133. data/spec/history_spec.rb +1 -1
  134. data/spec/sm_action_parameterization_spec.rb +1 -1
  135. data/spec/sm_entry_exit_actions_spec.rb +1 -1
  136. data/spec/sm_odds_n_ends_spec.rb +1 -1
  137. data/spec/sm_simple_spec.rb +1 -1
  138. data/spec/sm_super_state_spec.rb +1 -1
  139. data/spec/sm_turnstile_spec.rb +1 -1
  140. data/spec/transition_spec.rb +1 -1
  141. metadata +162 -46
@@ -0,0 +1,11 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require(File.join(File.dirname(__FILE__), 'config', 'boot'))
5
+
6
+ require 'rake'
7
+ require 'rake/testtask'
8
+ require 'rake/rdoctask'
9
+
10
+ require 'tasks/rails'
11
+
@@ -0,0 +1,43 @@
1
+ class AdminController < ApplicationController
2
+ layout "main"
3
+
4
+ def index
5
+ @vending_machines = VendingMachine.find(:all)
6
+ end
7
+
8
+ def save
9
+ create_vending_machine
10
+
11
+ @vending_machines = VendingMachine.find(:all)
12
+ render :template => "/admin/index"
13
+ end
14
+
15
+ def delete
16
+ VendingMachine.find(params[:id]).destroy
17
+
18
+ @vending_machines = VendingMachine.find(:all)
19
+ render :template => "/admin/index"
20
+ end
21
+
22
+ private
23
+
24
+ def create_vending_machine
25
+ vending_machine = VendingMachine.new
26
+ vending_machine.location = params[:location]
27
+ vending_machine.cash = params[:cash].to_i
28
+
29
+ 8.times do |i|
30
+ name = params["name_#{i}".to_sym]
31
+ price = params["price_#{i}".to_sym].to_i
32
+ inventory = params["inventory_#{i}".to_sym].to_i
33
+ if name.length > 0
34
+ vending_machine.products << Product.new(:name => name,
35
+ :price => price,
36
+ :inventory => inventory
37
+ )
38
+ end
39
+ end
40
+ vending_machine.save!
41
+ end
42
+
43
+ end
@@ -0,0 +1,7 @@
1
+ # Filters added to this controller apply to all controllers in the application.
2
+ # Likewise, all the methods added will be available for all controllers.
3
+
4
+ class ApplicationController < ActionController::Base
5
+ # Pick a unique cookie name to distinguish our session data from others'
6
+ session :session_key => '_rails_plugin_session_id'
7
+ end
@@ -0,0 +1,34 @@
1
+ require "vending_statemachine"
2
+
3
+ class MainController < ApplicationController
4
+
5
+ supported_by_statemachine VendingMachineInterface, lambda { VendingStatemachine.statemachine }
6
+
7
+ def index
8
+ return redirect_to("/admin") if (params[:id] == nil)
9
+ begin
10
+ @vending_machine = VendingMachine.find(params[:id])
11
+ rescue Exception => e
12
+ return redirect_to("/admin")
13
+ end
14
+ new_context
15
+ end
16
+
17
+ def insert_money
18
+ params[:event] = params[:id]
19
+ self.event
20
+ render :template => "/main/event", :layout => false
21
+ end
22
+
23
+ protected
24
+
25
+ def after_event
26
+ @vending_machine = @context.vending_machine
27
+ @vending_machine.save!
28
+ end
29
+
30
+ def initialize_context
31
+ @context.vending_machine = @vending_machine
32
+ end
33
+
34
+ end
@@ -0,0 +1,2 @@
1
+ module AdminHelper
2
+ end
@@ -0,0 +1,3 @@
1
+ # Methods added to this helper will be available to all templates in the application.
2
+ module ApplicationHelper
3
+ end
@@ -0,0 +1,7 @@
1
+ module MainHelper
2
+
3
+ def product_label(product)
4
+ return "#{product.name}<br/><span id=\"product_#{product.id}_price\">#{product.price_str}</span>"
5
+ end
6
+
7
+ end
@@ -0,0 +1,21 @@
1
+ class Product < ActiveRecord::Base
2
+ belongs_to :vending_machine
3
+ acts_as_list :scope => :vending_machine_id
4
+
5
+ def sold_out?
6
+ return self[:inventory] <= 0
7
+ end
8
+
9
+ def price_str
10
+ return sprintf("$%.2f", self[:price]/100.0)
11
+ end
12
+
13
+ def sold
14
+ self[:inventory] = self[:inventory] - 1
15
+ save!
16
+ end
17
+
18
+ def in_stock?
19
+ return self[:inventory] > 0
20
+ end
21
+ end
@@ -0,0 +1,36 @@
1
+ class VendingMachine < ActiveRecord::Base
2
+ has_many :products, :order => :position
3
+
4
+ def initialize(hash = nil)
5
+ super(hash)
6
+ self[:cash] = 0 if not self[:cash]
7
+ end
8
+
9
+ def add_product(inventory, name, price)
10
+ product = Product.new(:inventory => inventory, :name => name, :price => price)
11
+ products << product
12
+ return product
13
+ end
14
+
15
+ def max_price
16
+ max = 0
17
+ self.products.each { |product| max = product.price if product.price > max }
18
+ return max
19
+ end
20
+
21
+ def add_cash(amount)
22
+ self[:cash] = self[:cash] + amount
23
+ end
24
+
25
+ def cash_str
26
+ return sprintf("$%.2f", self[:cash]/100.0)
27
+ end
28
+
29
+ def product_with_id(id)
30
+ products.each do |product|
31
+ return product if product.id.to_s == id.to_s
32
+ end
33
+ raise Exception.new("No product found with id: #{id}")
34
+ end
35
+
36
+ end
@@ -0,0 +1,101 @@
1
+ class VendingMachineInterface
2
+
3
+ include Statemachine::ContextSupport
4
+
5
+ attr_reader :amount_tendered, :accepting_money, :dispensed_item, :change
6
+ attr_accessor :vending_machine
7
+
8
+ def initialize
9
+ @amount_tendered = 0
10
+ @accepting_money = true
11
+ end
12
+
13
+ def message
14
+ if @amount_tendered <= 0
15
+ return "Insert Money"
16
+ elsif not @accepting_money
17
+ return "Select Item"
18
+ else
19
+ return sprintf("$%.2f", @amount_tendered/100.0)
20
+ end
21
+ end
22
+
23
+ def affordable_items
24
+ return @vending_machine.products.reject { |product| product.sold_out? or product.price > @amount_tendered }
25
+ end
26
+
27
+ def non_affordable_items
28
+ return @vending_machine.products.reject { |product| product.sold_out? or product.price <= @amount_tendered }
29
+ end
30
+
31
+ def sold_out_items
32
+ return @vending_machine.products.reject { |product| !product.sold_out? }
33
+ end
34
+
35
+ def add_dollar
36
+ @amount_tendered = @amount_tendered + 100
37
+ end
38
+
39
+ def add_quarter
40
+ @amount_tendered = @amount_tendered + 25
41
+ end
42
+
43
+ def add_dime
44
+ @amount_tendered = @amount_tendered + 10
45
+ end
46
+
47
+ def add_nickel
48
+ @amount_tendered = @amount_tendered + 5
49
+ end
50
+
51
+ def check_max_price
52
+ if @amount_tendered >= @vending_machine.max_price
53
+ @statemachine.process_event(:reached_max_price)
54
+ end
55
+ end
56
+
57
+ def accept_money
58
+ @accepting_money = true
59
+ end
60
+
61
+ def refuse_money
62
+ @accepting_money = false
63
+ end
64
+
65
+ def load_product(id)
66
+ @selected_product = @vending_machine.product_with_id(id)
67
+ end
68
+
69
+ def check_affordability
70
+ if @amount_tendered >= @selected_product.price and @selected_product.in_stock?
71
+ @statemachine.accept_purchase
72
+ else
73
+ @statemachine.refuse_purchase
74
+ end
75
+ end
76
+
77
+ def make_sale
78
+ @dispensed_item = @selected_product
79
+ change_pennies = @amount_tendered - @selected_product.price
80
+ @change = sprintf("$%.2f", change_pennies/100.0)
81
+ @amount_tendered = 0
82
+ @selected_product.sold
83
+ @vending_machine.add_cash @selected_product.price
84
+ @accepting_money = true
85
+ end
86
+
87
+ def dispense_change
88
+ @change = sprintf("$%.2f", @amount_tendered/100.0)
89
+ @amount_tendered = 0
90
+ end
91
+
92
+ def clear_dispensers
93
+ @dispensed_item = nil
94
+ @change = nil
95
+ end
96
+
97
+ def load_and_make_sale(id)
98
+ load_product(id)
99
+ make_sale
100
+ end
101
+ end
@@ -0,0 +1,41 @@
1
+ module VendingStatemachine
2
+
3
+ def self.statemachine
4
+ return Statemachine.build do
5
+ startstate :standby
6
+ superstate :accepting_money do
7
+ on_entry :accept_money
8
+ on_exit :refuse_money
9
+ event :dollar, :collecting_money, :add_dollar
10
+ event :quarter, :collecting_money, :add_quarter
11
+ event :dime, :collecting_money, :add_dime
12
+ event :nickel, :collecting_money, :add_nickel
13
+ state :standby do
14
+ on_exit :clear_dispensers
15
+ event :selection, :standby
16
+ event :release_money, :standby
17
+ end
18
+ state :collecting_money do
19
+ on_entry :check_max_price
20
+ event :reached_max_price, :max_price_tendered
21
+ event :selection, :validating_purchase, :load_product
22
+ event :release_money, :standby, :dispense_change
23
+ end
24
+ state :validating_purchase do
25
+ on_entry :check_affordability
26
+ event :accept_purchase, :standby, :make_sale
27
+ event :refuse_purchase, :collecting_money
28
+ end
29
+ end
30
+ state :max_price_tendered do
31
+ event :selection, :standby, :load_and_make_sale
32
+ event :dollar, :max_price_tendered
33
+ event :quarter, :max_price_tendered
34
+ event :dime, :max_price_tendered
35
+ event :nickel, :max_price_tendered
36
+ event :release_money, :standby, :dispense_change
37
+ end
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,45 @@
1
+ <div style="float: left; width: 50%; text-align: center; font-size: 1.5em;">
2
+ <h3>Vending Machines</h3>
3
+ <table width="100%" cellspacing="0" cellpadding="0">
4
+ <tr>
5
+ <th>Id</th>
6
+ <th>Location</th>
7
+ <th>Cash</th>
8
+ <th>Products</th>
9
+ <th>Delete</th>
10
+ </tr>
11
+ <% @vending_machines.each do |vending_machine| %>
12
+ <tr>
13
+ <td><%= vending_machine.id %></td>
14
+ <td><%= link_to vending_machine.location, :action => "index", :controller => "main", :id => vending_machine.id %></td>
15
+ <td><%= vending_machine.cash_str %></td>
16
+ <td><%= vending_machine.products.length %></td>
17
+ <td><%= link_to "delete", :action => "delete", :id => vending_machine.id %>
18
+ </tr>
19
+ <% end %>
20
+ </table>
21
+ </div>
22
+ <div style="float: right; width: 50%;">
23
+ <h3>Create New Vending Machine</h3>
24
+ <%= form_tag :action => "save" %>
25
+ Location: <input type="text" name="location"><br />
26
+ Cash (in pennies): <input type="text" name="cash"><br />
27
+ <table width="100%" cellspacing="0" cellpadding="0">
28
+ <tr>
29
+ <th></th>
30
+ <th>Name</th>
31
+ <th>Price (in pennies)</th>
32
+ <th>Inventory</th>
33
+ </tr>
34
+ <% 8.times do |i| %>
35
+ <tr>
36
+ <td>Product #<%= i + 1 %></td>
37
+ <td><input type="text" name="name_<%= i %>"></td>
38
+ <td><input type="text" name="price_<%= i %>"></td>
39
+ <td><input type="text" name="inventory_<%= i %>"></td>
40
+ </tr>
41
+ <% end %>
42
+ </table>
43
+ <%= submit_tag "Save" %>
44
+ <%= end_form_tag %>
45
+ </div>
@@ -0,0 +1,12 @@
1
+ <html>
2
+ <head>
3
+ <title>Statemachine Vending</title>
4
+ <%= stylesheet_link_tag "layout", :media => "all" %>
5
+ <%= javascript_include_tag "prototype", "effects", "dragdrop", "controls" %>
6
+ </head>
7
+ <body>
8
+
9
+ <%= @content_for_layout %>
10
+
11
+ </body>
12
+ </html>
@@ -0,0 +1,13 @@
1
+ <h3>Info</h3>
2
+ <b>Location</b> <%= @vending_machine.location %> <br />
3
+ <b>Cash:</b> <%= @vending_machine.cash_str %> <br />
4
+ <table border="0" cellspacing="10" cellpadding="0">
5
+ <tr><th>Product</th><th>Price</th><th>Inventory</th></tr>
6
+ <% @vending_machine.products.each do |product| %>
7
+ <tr>
8
+ <td><%= product.name %></td>
9
+ <td><%= product.price_str %></td>
10
+ <td><%= product.inventory %></td>
11
+ </tr>
12
+ <% end %>
13
+ </table>
@@ -0,0 +1,27 @@
1
+ page.replace_html "quartz_screen", @context.message
2
+
3
+ @context.affordable_items.each do |product|
4
+ page << "document.getElementById('product_#{product.id}').className = 'affordable';"
5
+ end
6
+
7
+ @context.non_affordable_items.each do |product|
8
+ page << "document.getElementById('product_#{product.id}').className = 'non_affordable';"
9
+ end
10
+
11
+ @context.sold_out_items.each do |product|
12
+ page.replace_html "product_#{product.id}_price", "<span style=\"color: red;\">SOLD OUT</span>"
13
+ end
14
+
15
+ if @context.dispensed_item
16
+ page.replace_html "dispenser", "<p>#{@context.dispensed_item.name}</p>"
17
+ page.show "dispenser"
18
+ page.visual_effect :fade, "dispenser", :duration => 3
19
+ end
20
+
21
+ if @context.change
22
+ page.replace_html "change_amount", "<p>#{@context.change}</p>"
23
+ page.show "change_amount"
24
+ page.visual_effect :fade, "change_amount", :duration => 3
25
+ end
26
+
27
+ page.replace_html "info", :partial => "main/info"
@@ -0,0 +1,38 @@
1
+
2
+ <img id="vending_machine_body" src="/images/vending_machine_body.png">
3
+ <div id="links"><%= link_to "Manage Vending Machines", :action => "index", :controller => "admin" %></div>
4
+ <img id="money_panel" src="/images/money_panel.png">
5
+ <%= link_to_remote '<img src="/images/cash_release_button.png">',
6
+ {:url => { :action => "event", :event => "release_money"}},
7
+ { :id => "cash_release_button"} %>
8
+ <div id="product_list">
9
+ <% @vending_machine.products.each do |product| %>
10
+ <%= link_to_remote product_label(product),
11
+ {:url => { :action => "event", :event => "selection", :arg => product.id }},
12
+ { :id => "product_#{product.id}", :class => "non_affordable" } %>
13
+ <% end %>
14
+ </div>
15
+ <img id="change" src="/images/change.png">
16
+ <div id="change_amount"></div>
17
+ <div id="cash">
18
+ <h3>Cash</h3>
19
+ (drag and drop the money)<br/>
20
+ <img id="dollar" class="money" src="/images/dollar.png"><br/>
21
+ <img id="quarter" class="money" src="/images/quarter.png">
22
+ <img id="dime" class="money" src="/images/dime.png">
23
+ <img id="nickel" class="money" src="/images/nickel.png">
24
+ </div>
25
+
26
+ <div id="quartz_screen">Insert Money</div>
27
+ <div id="dispenser"></div>
28
+ <div id="info">
29
+ <%= render :partial => "info" %>
30
+ </div>
31
+
32
+ <%= draggable_element "dollar", :revert => true %>
33
+ <%= draggable_element "quarter", :revert => true %>
34
+ <%= draggable_element "dime", :revert => true %>
35
+ <%= draggable_element "nickel", :revert => true %>
36
+ <%= drop_receiving_element "money_panel",
37
+ :url => { :action => "insert_money" },
38
+ :accept => "money", :hoverclass => "money_active" %>