Skip to content

Instantly share code, notes, and snippets.

@alpaca-tc
Last active September 11, 2018 07:47
Show Gist options
  • Save alpaca-tc/396384020bc7941d040cc0734dc03463 to your computer and use it in GitHub Desktop.
Save alpaca-tc/396384020bc7941d040cc0734dc03463 to your computer and use it in GitHub Desktop.
class Automata
class Error < StandardError; end
class InvalidTransition < Error; end
attr_reader :current_state
def initialize(initial_state:, &block)
@initial_state = initial_state
@current_state = nil
@events = {}
instance_exec(&block) if block_given?
end
def define_event(event_name, from: [], to:)
@events[event_name.to_s] = { from: from, to: to }
end
def start
@current_state = @initial_state
end
def fire(event_name)
event = @events.fetch(event_name.to_s)
raise InvalidTransition, "'#{event_name}' can not transition from #{@current_state}" unless event[:from].include?(current_state)
@current_state = event[:to]
end
end
automata = Automata.new(initial_state: '寝ている') do
define_event('起きる', from: ['寝ている', '休んでいる'], to: '起きている')
define_event('走る', from: ['休んでいる', '起きている', '泣いている'], to: '走っている')
define_event('休む', from: ['走っている', '泣いている'], to: '起きている')
define_event('泣く', from: ['走っている', '起きている'], to: '泣いている')
define_event('寝る', from: ['起きている', '泣いている'], to: '寝ている')
end
automata.start
event_names = ['起きる', '走る', '休む', '寝る']
event_names.each { |event_name| automata.fire(event_name) }
puts automata.current_state #=> 寝ている
# ---
automata.start
event_names = ['起きる', '走る', '寝る']
event_names.each { |event_name| automata.fire(event_name) } #=> raise Automata::InvalidTransition
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment