Skip to content

Instantly share code, notes, and snippets.

@schmalz
Created September 6, 2017 15:05
Show Gist options
  • Save schmalz/3061d1defc968972212d4f84d817b3a2 to your computer and use it in GitHub Desktop.
Save schmalz/3061d1defc968972212d4f84d817b3a2 to your computer and use it in GitHub Desktop.
Designing for Scalability with Erlang/OTP - Ch 6 - Coffee FSM - LFE + OTP
(defmodule coffee-fsm
(behaviour gen_fsm)
(export
(start-link 0)
(stop 0)
(handle_sync_event 4)
(init 1)
(terminate 3)
(selection 2)
(payment 2)
(remove 2)
(tea 0)
(espresso 0)
(americano 0)
(cappuccino 0)
(pay 1)
(cup-removed 0)
(cancel 0)))
(defun server-name ()
(MODULE))
(defun callback-module ()
(MODULE))
(defun initial-data ()
'())
(defun opts ()
'())
(defun register-name ()
`#(local ,(server-name)))
(defun start-link ()
(gen_fsm:start_link (register-name) (callback-module) (initial-data) (opts)))
(defun init (_)
(hw:reboot)
(hw:display "make your selection" '())
(process_flag 'trap_exit 'true)
#(ok selection ()))
(defun stop ()
(gen_fsm:sync_send_all_state_event (MODULE) 'stop))
(defun tea ()
(gen_fsm:send_event (MODULE) #(selection tea 100)))
(defun espresso ()
(gen_fsm:send_event (MODULE) #(selection espresso 150)))
(defun americano ()
(gen_fsm:send_event (MODULE) #(selection americano 100)))
(defun cappuccino ()
(gen_fsm:send_event (MODULE) #(selection cappuccino 150)))
(defun cup-removed ()
(gen_fsm:send_event (MODULE) 'cup-removed))
(defun pay (coin)
(gen_fsm:send_event (MODULE) `#(pay ,coin)))
(defun cancel ()
(gen_fsm:send_event (MODULE) 'cancel))
(defun selection
((`#(selection ,brew ,price) _data)
(hw:display "please pay ~w" `(,price))
`#(next_state payment ,`#(,brew ,price 0)))
((`#(pay ,coin) data)
(hw:return-change coin)
`#(next_state selection ,data))
((_other data)
`#(next_state selection ,data)))
(defun payment
((`#(pay ,coin) `#(,brew ,price ,paid))
(when (< (+ coin paid) price))
(let ((paid (+ paid coin)))
(hw:display "please pay ~w" `(,(- price paid)))
`#(next_state payment ,`#(,brew ,price ,paid))))
((`#(pay ,coin) `#(,brew ,price ,paid))
(when (>= (+ coin paid) price))
(let ((paid (+ paid coin)))
(dispense brew price paid)
`#(next_state remove ())))
(('cancel `#(,_brew ,_price ,paid))
(hw:display "make your selection" '())
(hw:return-change paid)
#(next_state selection ()))
((_other data)
`#(next_state payment ,data)))
(defun remove
(('cup-removed data)
(hw:display "make your selection" '())
#(next_state selection ()))
((`#(pay ,coin) data)
(hw:return-change coin)
#(next_state remove ()))
((_other data)
#(next_state remove ())))
(defun handle_sync_event
(('stop _from _state data)
`#(stop normal ,data)))
(defun terminate
((_reason 'payment `#(,_brew ,_price ,paid))
(when (> paid 0))
(hw:return-change paid))
((_reason _state _data)
'ok))
(defun dispense (brew price paid)
(hw:display "preparing drink" '())
(if (> paid price)
(hw:return-change (- paid price)))
(hw:drop-cup)
(hw:prepare brew)
(hw:display "remove drink" '()))
@schmalz
Copy link
Author

schmalz commented Sep 6, 2017

And this is the coffee example, written to use gen_fsm.
It re-uses the hw file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment