Class: BabyBots::BabyBot
- Inherits:
-
Object
- Object
- BabyBots::BabyBot
- Defined in:
- lib/baby_bots/baby_bot.rb
Overview
A tiny finite-state automata class.
Instance Attribute Summary collapse
-
#curr ⇒ Object
Returns the value of attribute curr.
-
#start ⇒ Object
Returns the value of attribute start.
-
#states ⇒ Object
Returns the value of attribute states.
Instance Method Summary collapse
-
#==(another_baby) ⇒ Object
Equality is based on if all the states are the same, and if the machines are currently in the same state.
-
#add_state(state, start = nil) ⇒ Object
Adds a new state to the finite-state automata, also accepts an optional start flag, which will set the supplied state as the initial state.
-
#build(table, no_first = false) ⇒ Object
Build up this machine’s states with a given state table.
-
#initialize(states = {}) ⇒ BabyBot
constructor
Accepts an optional hash of states.
-
#process(event = nil) ⇒ Object
Process the finite state automata with the given event.
-
#restart ⇒ Object
Restart the current state to be the start state.
-
#state ⇒ Object
Return the current state’s actual state.
Constructor Details
#initialize(states = {}) ⇒ BabyBot
Accepts an optional hash of states.
25 26 27 28 29 30 31 32 33 |
# File 'lib/baby_bots/baby_bot.rb', line 25 def initialize(states={}) # Hash of state names to state objects @states = {} if !states.empty? then build states end # Initial state @start = nil # Current state @curr = nil end |
Instance Attribute Details
#curr ⇒ Object
Returns the value of attribute curr.
22 23 24 |
# File 'lib/baby_bots/baby_bot.rb', line 22 def curr @curr end |
#start ⇒ Object
Returns the value of attribute start.
22 23 24 |
# File 'lib/baby_bots/baby_bot.rb', line 22 def start @start end |
#states ⇒ Object
Returns the value of attribute states.
22 23 24 |
# File 'lib/baby_bots/baby_bot.rb', line 22 def states @states end |
Instance Method Details
#==(another_baby) ⇒ Object
Equality is based on if all the states are the same, and if the machines are currently in the same state.
145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/baby_bots/baby_bot.rb', line 145 def ==(another_baby) if @curr != another_baby.curr return false end @states.keys.each do |k| if @states[k] != another_baby.states[k] then return false end end return true end |
#add_state(state, start = nil) ⇒ Object
Adds a new state to the finite-state automata, also accepts an optional start flag, which will set the supplied state as the initial state. Note that this machine may only have one start state. Additionally, adding the first start state will set @curr to be this state, after this has been done @curr will remain on whatever state it is currently residing on, and must be reset using the restart method.
41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/baby_bots/baby_bot.rb', line 41 def add_state(state, start=nil) # key on state names to the actual state object @states[state.state] = state # if this is a start state if start @start = state # only set the current state to the start state if @curr is nil. if @curr.nil? then @curr = @start end end end |
#build(table, no_first = false) ⇒ Object
Build up this machine’s states with a given state table. The format of this table is assumed to be => {event1 => transition1, …}. build assumes that the first state provided is the start state, although the optional no_first parameter may be set to override this.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/baby_bots/baby_bot.rb', line 58 def build(table, no_first=false) first_state = !no_first # iterate through each provided state table entries table.each do |state, state_table| temp_state = State.new(state) # iterate through the current state table, adding events => transition state_table.each do |event, transition| temp_state.add_transition(event, transition) end # finally, add the state to the machine, and since we've already # added a start state, clear the first_state flag add_state(temp_state, first_state) first_state = false end end |
#process(event = nil) ⇒ Object
Process the finite state automata with the given event. This will first see if the finite state automata has a defined method named “pre_current_state”, and if so “cook” the input event with this method. Process will then use the cooked input if available, or the raw input if there is none to compute the transition. Before actually transitioning, it will then send the raw output to a method of “post_current_state”, which will be the return value. If a method named “post_cook_current_state” is supplied, it will send the cooked event to this method instead of using “post_current_state”.
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/baby_bots/baby_bot.rb', line 91 def process(event=nil) # get the current state curr_state = @curr # check if we need to preprocess the event if respond_to?("pre_#{@curr.state}") cooked_event = my_send("pre_#{@curr.state}", event) end # calculate the next state if !cooked_event.nil? next_state = @states[curr.table[cooked_event]] else next_state = @states[curr.table[event]] end # if there is no such transition, see if there is an a translation # known as else, and use that as the next state if next_state.nil? next_state = @states[curr.table[:else]] end # if the event is nil, and there is no :else clause, # throw an exception if next_state.nil? raise NoSuchTransitionException, "No valid transition #{event} for #{@curr.state}" end # check if we need to postprocess the event, this will act # as the "return" from any state transition (even self-looping transitions) if respond_to?("post_#{@curr.state}") ret_val = my_send("post_#{@curr.state}", event) elsif respond_to?("post_cooked_#{curr.state}") ret_val = my_send("post_#{@curr.state}", cooked_event) end # actually transition, and make sure such a transition exists @curr = next_state if @curr.nil? raise NoSuchStateException, "No valid state #{@curr} for transition #{event} from #{curr_state}" end return ret_val end |
#restart ⇒ Object
Restart the current state to be the start state.
139 140 141 |
# File 'lib/baby_bots/baby_bot.rb', line 139 def restart @curr = @start end |
#state ⇒ Object
Return the current state’s actual state.
78 79 80 |
# File 'lib/baby_bots/baby_bot.rb', line 78 def state @curr.state end |