Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/sugar/tutorius/core.py149
1 files changed, 116 insertions, 33 deletions
diff --git a/src/sugar/tutorius/core.py b/src/sugar/tutorius/core.py
index 45eee3a..9d0cba2 100644
--- a/src/sugar/tutorius/core.py
+++ b/src/sugar/tutorius/core.py
@@ -122,72 +122,155 @@ class Tutorial (object):
class State:
"""This is a step in a tutorial. The state represents a collection of
- actions to undertake when entering the state, and a description of an
- event filter with associated actions to go to the next state."""
+ actions to undertake when entering the state, and a series of event filters
+ with associated actions that point to a possible next state."""
- def __init__(self):
+ def __init__(self, action_list=[], event_filter_list=[]):
"""Initializes the content of the state, as in loading the actions
- that are required and building the correct tests."""
- self.actions = []
- self.tests = []
+ that are required and building the correct tests.
+
+ @param action_list The list of actions to execute when entering this
+ state
+ @param event_filter_list A list of tuples of the form
+ (event_filter, next_state_name), that explains the outgoing links for
+ this state"""
+ self._actions = action_list
+
+ # Unused for now
+ #self.tests = []
+
+ self._event_filters = event_filter_list
def setup(self):
"""Install the state itself. This is the best time to pop-up a dialog
that has to remain for the duration of the state."""
- for act in self.actions:
+ for action in self._actions:
act.do()
-
def teardown(self):
"""Undo every action that was installed for this state. This means
removing dialogs that were displayed, removing highlights, etc..."""
- for act in self.actions:
+ for act in self._actions:
act.undo()
-
- def verify(self):
- """Run the internal tests to see if one of them passes. If it does,
- then do the associated processing to go in the next state."""
- for test in self.tests:
- if test.verify() == True:
- actions = test.get_actions()
- for act in actions:
- act.do()
- # Now that we execute the actions related to a test, we might
- # want to undo them right after --- should we use a callback or
- # a timer?
+ # Unused for now
+## def verify(self):
+## """Run the internal tests to see if one of them passes. If it does,
+## then do the associated processing to go in the next state."""
+## for test in self.tests:
+## if test.verify() == True:
+## actions = test.get_actions()
+## for act in actions:
+## act.do()
+## # Now that we execute the actions related to a test, we might
+## # want to undo them right after --- should we use a callback or
+## # a timer?
class FiniteStateMachine(State):
"""This is a collection of states, with a start state and an end callback.
It is used to simplify the development of the various tutorials by
encapsulating a collection of states that represent a given learning
process."""
- def __init__(self, start_state, setup_actions):
+
+ def __init__(self, state_dict={}, start_state_name="INIT", setup_actions=[]):
"""The constructor for a FSM. Pass in the start state and the setup
actions that need to be taken when the FSM itself start (which may be
- different from what is done in the first state of the machine)."""
+ different from what is done in the first state of the machine).
+
+ @param state_dict A dictionary containing the state names as keys and
+ the state themselves as entries.
+ @param start_state_name The name of the starting state, if different
+ from "INIT"
+ @param setup_actions The actions to undertake when initializing the FSM
+ """
State.__init__(self)
- self.start_state = start_state
+ # Dictionnary of states contained in the FSM
+ self._states = state_dict
+
+ # Remember the initial state - we might want to reset
+ # or rewind the FSM at a later moment
+ self.start_state = state_dict[start_state]
+
+ # Register the actions for the FSM - They will be processed at the
+ # FSM level, meaning that when the FSM will start, it will first
+ # execute those actions. When the FSM closes, it will tear down the
+ # inner actions of the state, then close its own actions
self.actions = setup_actions
self.current_state = self.start_state
+
+ # Flag to mention that the FSM was initialized
+ self._fsm_setup_done = False
+ # Flag that must be raised when the FSM is to be teared down
+ self._fsm_teardown_done = False
+ # Flag used to declare that the FSM has reached an end state
+ self._fsm_has_finished = False
+
def setup(self):
"""
- Set up the FSM
+ Set up the FSM the first time, then setup the inner state
"""
- for act in self.actions:
- act.do()
+ # If we never initialized the FSM itself, then we need to run all the
+ # actions associated with the FSM.
+ if self._fsm_setup_done == False:
+ # Flag the FSM level setup as done
+ self._fsm_setup_done = True
+ # Execute all the FSM level actions
+ for act in self.actions:
+ act.do()
+
+ # Then, we need to run the setup of the current state
+ self.current_state.setup()
+
+ def set_state(self, new_state_name):
+ """
+ This functions changes the current state of the finite state machine.
+
+ @param new_state The identifier of the state we need to go to
+ """
+ # Pass in the name to the internal state - it might be a FSM and
+ # this name will apply to it
+ self.current_state.set_state(new_state_name)
+
+ # Make sure the given state is owned by the FSM
+ if not self._states.haskey(new_state_name):
+ # If we did not recognize the name, then we do not possess any
+ # state by that name - we must ignore this state change request as
+ # it will be done elsewhere in the hierarchy (or it's just bogus).
+ return
+
+ new_state = self._states[new_state_name]
+
+ # Undo the actions of the old state
+ self.current_state.teardown()
+
+ # Insert the new state
+ self.current_state = new_state
+
+ # Call the initial actions in the new state
+ self.current_state.setup()
+
def teardown(self):
"""
Revert any changes done by setup()
"""
- for act in self.actions:
- act.undo()
-
- def verify(self):
- "Verify if the current state passes it's tests"""
- return self.current_state.verify()
+ # Teardown the current state
+ self.current_state.teardown()
+
+ # If we just finished the whole FSM, we need to also call the teardown
+ # on the FSM level actions
+ if self._fsm_has_finished == True:
+ # Flag the FSM teardown as not needed anymore
+ self._fsm_teardown_done = False
+ # Undo all the FSM level actions here
+ for act in self.actions:
+ act.undo()
+
+ #Unused for now
+## def verify(self):
+## """Verify if the current state passes its tests"""
+## return self.current_state.verify()