1. dr0id
  2. symplehfsm

Commits

dr0id  committed 5800ce2

updated version
updated some doc strings

  • Participants
  • Parent commits 8461596
  • Branches default

Comments (0)

Files changed (7)

File trunk/symplehfsm/examples/TestHFSM/symplehfsm_demo.py

View file
 # -*- coding: utf-8 -*-
 
 """
-TODO: modul doc string
+
+It's all about:
+::
+
+    making a statemachine testable based on: http://accu.org/index.php/journals/1548
+
+
+    ------------------------------------------------------------------------------
+
+    Statechart used to test the SympleHFSM
+    based on 
+    [Samek] Miro Samek, Practical Statecharts in C/C++, CMP Books 2002. 
+    There's a companion website with additional information: http://www.quantum-leaps.com
+    taken from: http://accu.org/index.php/journals/252
+
+    see also: http://en.wikipedia.org/wiki/UML_state_machine#Local_versus_external_transitions
+    making a statemachine testable based on: http://accu.org/index.php/journals/1548
+
+              +-------------------------------------------------------------------------------------+
+    *--init-->|                                         s0                                          |
+              +-------------------------------------------------------------------------------------+
+              | entry/                                                                              |
+              | exit/                                                                               |
+              |       +-------------------------+    +------------------------------------------+   |
+              |   *-->|        s1               |    |               s2                         |   |
+              |       +-------------------------+    +------------------------------------------+   |
+              |       | entry/                  |-c->| entry/              +-----------------+  |   |
+              |<--d---| exit/                   |    | exit/               | h[!foo]/ foo=1; |  |   |
+              |       |     +---------------+   |<-c-|      +----------------------------+   |  |   |
+              |       | *-->|      s11      |   |    |  *-->|             s21            |<--+  |   |
+              |       |     +---------------+   |    |      +----------------------------+      |   |
+              |    +--|     | entry/        |   |    |      | entry/                     |      |   |
+              |   a|  |     | exit/         |<---f---|      | exit/                      |      |   |
+              |    +->|     | h[foo]/ foo=0;|   |    |      |       +--------------+     |      |   |
+              |       |     |               |   |    |      |   *-->|     s211     |     |      |   |
+              |       |--b->|               |   |    |      |       +--------------+     |      |   |
+              |       |     |               |   |--------f--------->| entry/       |     |      |   |
+              |       |     |               |   |    |      |       | exit/        |--------g------>|
+              |       |     |               |----------g----------->|              |     |      |   |
+              |       |     |               |   |    |      |--b--->|              |<-------e-------|
+              |       |     |               |   |    |      |<---d--|              |     |      |   |
+              |       |     |               |   |    |      |       +--------------+     |      |   |
+              |       |     +---------------+   |    |      +----------------------------+      |   |--exit-->O
+              |       |                         |    |                                          |   |
+              |       +-------------------------+    +------------------------------------------+   |
+              |                                                                                     |
+              +-------------------------------------------------------------------------------------+
+
+
+      As far as I understand it, current_state always points to either s11 or s211 (one of the leaf states).
+      Also for the transitions triggered by an event I assume it works as follows:
+
+      event| from -> to | transition actions
+       init:  s0 ->  s11:   s0.entry, s1.entry, s11.entry
+       exit:s211 ->   s0: s211.exit, s21.exit, s2.exit, s0.exit
+             s11 ->   s0:  s11.exit, s1.exit, s0.exit
+          a:  s1 ->   s1:  s11.exit,  s1.exit,  s1.entry, s11.entry
+          b:  s1 ->  s11:  s11.exit, s11.entry
+             s21 -> s211: s211.exit, s211.entry
+          c:  s1 ->   s2:  s11.exit,  s1.exit,  s2.entry, s21.entry, s211.entry
+              s2 ->   s1: s211.exit, s21.exit,  s2.exit, s1.entry, s11.entry
+          d:  s1 ->   s0:  s11.exit,  s1.exit,  s1.entry, s11.entry
+            s211 ->  s21: s211.exit, s211.entry
+          e:  s0 -> s211:  s11.exit,  s1.exit, s2.entry, s21.entry, s211.entry
+                          s211.exit, s21.exit,  s2.exit, s2.entry, s21.entry, s211.entry
+          f:  s2 ->  s11: s211.exit, s21.exit,  s2.exit, s1.entry, s11.entry
+              s1 -> s211:  s11.exit,  s1.exit,  s2.entry, s21.entry, s211.entry
+          g: s11 -> s211:  s11.exit,  s1.exit,  s2.entry, s21.entry, s211.entry
+            s211 ->   s0: s211.exit, s21.exit,  s2.exit,  s1.entry, s11.entry
+          h: s11 foo==True: actions.unset_foo
+             s11 foo==False: do nothing
+             s21 foo==False: s211.exit, s21.exit, actions.set_foo, s21.entry, s211.entry
+             s21 foo==True: do nothing
+          
+      Actions:
+          set_foo() => foo = 1
+          unset_foo() => foo = 0
+
+    The action specifications shown are:
+
+       *
+
+         The transition from s21 to itself (a self-transition). This is an example of a transition 
+         that has a guard (in brackets []) and an associated action (after the slash /). The guard 
+         is a condition that must evaluate to true to enable the transition. If it evaluates to false, 
+         the transition is not taken and none of the actions are executed. A self-transition exits and 
+         reenters the state, hence the associated exit and entry actions are executed.
+       *
+
+         The internal transition inside s11 is not drawn with an arrow. It merely specifies an action 
+         that is to be taken when a certain event occurs, but no transition to another state occurs, 
+         and no exit or entry actions are performed. In our case the internal transition has a guard, 
+         so the associated action (foo = 0) is only executed when the h key is pressed while foo 
+         evaluates to true.
+
+
+..todo: loop action back to event -> queue?
+
 """
 
-__version__ = "0.0.1.dev"
+__version__ = "1.0.3.0"
 __author__ = "dr0iddr0id {at} gmail [dot] com (C) 2012"
 
 import operator
 
 
 # ------------------------------------------------------------------------------
-# TODO: loop action back to event -> queue?
-# ------------------------------------------------------------------------------
-
-# making a statemachine testable based on: http://accu.org/index.php/journals/1548
-
-
-# ------------------------------------------------------------------------------
-#
-# Statechart used to test the SympleHFSM
-# based on 
-# [Samek] Miro Samek, Practical Statecharts in C/C++, CMP Books 2002. 
-# There's a companion website with additional information: http://www.quantum-leaps.com
-# taken from: http://accu.org/index.php/journals/252
-#
-# see also: http://en.wikipedia.org/wiki/UML_state_machine#Local_versus_external_transitions
-# making a statemachine testable based on: http://accu.org/index.php/journals/1548
-#
-#           +-------------------------------------------------------------------------------------+
-# *--init-->|                                         s0                                          |
-#           +-------------------------------------------------------------------------------------+
-#           | entry/                                                                              |
-#           | exit/                                                                               |
-#           |       +-------------------------+    +------------------------------------------+   |
-#           |   *-->|        s1               |    |               s2                         |   |
-#           |       +-------------------------+    +------------------------------------------+   |
-#           |       | entry/                  |-c->| entry/              +-----------------+  |   |
-#           |<--d---| exit/                   |    | exit/               | h[!foo]/ foo=1; |  |   |
-#           |       |     +---------------+   |<-c-|      +----------------------------+   |  |   |
-#           |       | *-->|      s11      |   |    |  *-->|             s21            |<--+  |   |
-#           |       |     +---------------+   |    |      +----------------------------+      |   |
-#           |    +--|     | entry/        |   |    |      | entry/                     |      |   |
-#           |   a|  |     | exit/         |<---f---|      | exit/                      |      |   |
-#           |    +->|     | h[foo]/ foo=0;|   |    |      |       +--------------+     |      |   |
-#           |       |     |               |   |    |      |   *-->|     s211     |     |      |   |
-#           |       |--b->|               |   |    |      |       +--------------+     |      |   |
-#           |       |     |               |   |--------f--------->| entry/       |     |      |   |
-#           |       |     |               |   |    |      |       | exit/        |--------g------>|
-#           |       |     |               |----------g----------->|              |     |      |   |
-#           |       |     |               |   |    |      |--b--->|              |<-------e-------|
-#           |       |     |               |   |    |      |<---d--|              |     |      |   |
-#           |       |     |               |   |    |      |       +--------------+     |      |   |
-#           |       |     +---------------+   |    |      +----------------------------+      |   |--exit-->O
-#           |       |                         |    |                                          |   |
-#           |       +-------------------------+    +------------------------------------------+   |
-#           |                                                                                     |
-#           +-------------------------------------------------------------------------------------+
-#
-#
-#   As far as I understand it, current_state always points to either s11 or s211 (one of the leaf states).
-#   Also for the transitions triggered by an event I assume it works as follows:
-#
-#   event| from -> to | transition actions
-#    init:  s0 ->  s11:   s0.entry, s1.entry, s11.entry
-#    exit:s211 ->   s0: s211.exit, s21.exit, s2.exit, s0.exit
-#          s11 ->   s0:  s11.exit, s1.exit, s0.exit
-#       a:  s1 ->   s1:  s11.exit,  s1.exit,  s1.entry, s11.entry
-#       b:  s1 ->  s11:  s11.exit, s11.entry
-#          s21 -> s211: s211.exit, s211.entry
-#       c:  s1 ->   s2:  s11.exit,  s1.exit,  s2.entry, s21.entry, s211.entry
-#           s2 ->   s1: s211.exit, s21.exit,  s2.exit, s1.entry, s11.entry
-#       d:  s1 ->   s0:  s11.exit,  s1.exit,  s1.entry, s11.entry
-#         s211 ->  s21: s211.exit, s211.entry
-#       e:  s0 -> s211:  s11.exit,  s1.exit, s2.entry, s21.entry, s211.entry
-#                       s211.exit, s21.exit,  s2.exit, s2.entry, s21.entry, s211.entry
-#       f:  s2 ->  s11: s211.exit, s21.exit,  s2.exit, s1.entry, s11.entry
-#           s1 -> s211:  s11.exit,  s1.exit,  s2.entry, s21.entry, s211.entry
-#       g: s11 -> s211:  s11.exit,  s1.exit,  s2.entry, s21.entry, s211.entry
-#         s211 ->   s0: s211.exit, s21.exit,  s2.exit,  s1.entry, s11.entry
-#       h: s11 foo==True: actions.unset_foo
-#          s11 foo==False: do nothing
-#          s21 foo==False: s211.exit, s21.exit, actions.set_foo, s21.entry, s211.entry
-#          s21 foo==True: do nothing
-#       
-#   Actions:
-#       set_foo() => foo = 1
-#       unset_foo() => foo = 0
-#
-#The action specifications shown are:
-#
-#    *
-#
-#      The transition from s21 to itself (a self-transition). This is an example of a transition 
-#      that has a guard (in brackets []) and an associated action (after the slash /). The guard 
-#      is a condition that must evaluate to true to enable the transition. If it evaluates to false, 
-#      the transition is not taken and none of the actions are executed. A self-transition exits and 
-#      reenters the state, hence the associated exit and entry actions are executed.
-#    *
-#
-#      The internal transition inside s11 is not drawn with an arrow. It merely specifies an action 
-#      that is to be taken when a certain event occurs, but no transition to another state occurs, 
-#      and no exit or entry actions are performed. In our case the internal transition has a guard, 
-#      so the associated action (foo = 0) is only executed when the h key is pressed while foo 
-#      evaluates to true.
-#
-#
-#
-# ------------------------------------------------------------------------------
 
 class Actions(object):
     """
 
 # interactive demo of the same state machine, but using different actions implementation to print
 # out the actions
-def demo():
+def demo():
+    """
+    The demo. This is the main method that runs the interactive demo.
+    """
     import sys
     
     class PrintActions(Actions):

File trunk/symplehfsm/examples/mousefollower/mousefollower.py

View file
 # -*- coding: utf-8 -*-
 
 """
-Example usage of the symplehfsm statemachine for a game entity using pygame.
+Example usage of the symplehfsm statemachine for a game entity using pygame. See inline comments!
 """
 
-__version__ = "0.0.1.dev"
+__version__ = "1.0.3.0"
 __author__ = "dr0iddr0id {at} gmail [dot] com (C) 2012"
 
 import math

File trunk/symplehfsm/examples/readme.txt

View file
+This are the examples for the symplehfsm project. Make sure that the symplehfsm module can be imported before running them.

File trunk/symplehfsm/examples/testablestatemachines/testablestatemachine.py

View file
 
 """
 
-__version__ = "0.0.1.dev"
+__version__ = "1.0.3.0"
 __author__ = "dr0iddr0id {at} gmail [dot] com (C) 2010"
 
 from operator import methodcaller

File trunk/symplehfsm/readme.txt

View file
 - switch case (not so elegant and gets messy fast)
 - state pattern (simple, does not help with state hirarchy)
 - state transition tables (how does this work with hirarchical statemachines??)
-- dynamic tree like structures (
+- dynamic tree like structures
    
    
 example
     
 http://homepage.usask.ca/~ctl271/810/lowest_common_ancestor.pdf    
     
-class StateA(objecto):
 
-    @staticmethod
-    def event1(args):
-        pass
     
-    @staticmethod
-    def event2(args):
-        pass
-    
-# etc.    
-    
-class MyStateMachine(object):
 
 
-    def __init__(self):
-        self._root = None
-        self._current_node = None
-        self._state_node_cache = {} # {state:node}
 
-    def set_states(self, root_node):
-        self._root = root_node
-        # travers all nodes to build state_node_cache
-        nodes = [self._root]
-        while nodes:
-            node = nodes.pop()
-            nodes.extend(node.children)
-            if node in self._state_node_cache:
-                raise Exception("same state in two different nodes")
-            self._state_node_cache[node.sate] = node
-            
-    def _get_cur_state(self):
-        return self._current_node.state
-    current_state = property(_get_cur_state)
 
-    def init(self, initial_state, do_entry=False):
-        if do_entry:
-            self.do_transition_to(initial_state)
-        else:
-            self._current_node = self._state_node_cache[initial_state]
-            
-    def do_transition_to(self, state):
-        trans = self._caclulate_transition(None, initial_state)
-        trans.execute(self)
-        
-    def _caclulate_transition(self, from_state, to_state, action=None):
-        from_node = self._state_node_cache[from_state]
-        to_node = self._state_node_cache[to_state]
-        common_node = self._get_common_parent(from_node, to_node)
-        exit_nodes = []
-        node = from_node
-        while node != common_node:
-            exit_nodes.append(node)
-            node = from_node.parent
-        
-    def _get_nodes_path(self, from_node, to_node):
-        
-        
-        
-        
-    def _get_common_parent(self, from_node, to_node):
-        node = to_node
-        nodes = []
-        while node.parent:
-            nodes.insert(node, 0)
-            node = node.parent
-        node = from_node
-        while node.parent:
-            for idx, down in enumerate(nodes):
-                if down == node:
-                    return node
-            node = node.parent
-        raise Exception("no common parent node found for %s and %s" % (from_state, to_state))
-            
-        
-class Transition(object):
-    def __init__(self, exit_states, entry_states, callback=None):
-        self._exit_states = exit_states
-        self.entry_states = entry_states
-        
-    def execute(self, sm):
-        for state in self._exit_states:
-            state.exit(sm)
-            
-        new_target = None
-        if callback:
-            new_target = callback(sm)
-            
-        if new_target:
-            # calc new path
-            
-        else:
-            for state in self_entry_states:
-                state.entry(sm)
 
-class StateMachineNode(object):
-    def __init__(self, state, parent_node, children_nodes=[]):
-        self.state = state
-        self.parent = parent_node
-        if parent_node:
-            parent_node.add(self)
-        self.children = children_nodes
-    def add(self, node):
-        self.children.append(node)
 
 
-nodeA = StateMachineNode(StateA, None)
-nodeB = StateMachineNode(StateB, nodeA)
-nodeC = StateMachineNode(StateC, nodeA)
-nodeD = StateMachineNode(StateD, nodeA)
-nodeE = StateMachineNode(StateE, nodeB)
-nodeF = StateMachineNode(StateF, nodeB)
-nodeG = StateMachineNode(StateG, nodeB)
-nodeH = StateMachineNode(StateH, nodeD)
-nodeI = StateMachineNode(StateI, nodeD)
 
-sm = MyStateMachine()
 
-sm.set_states(nodeA)
 
-sm.init(StateE) # initial transition
 
 
 
 
 
 
-
-
-
-
-
-
-
-
-

File trunk/symplehfsm/symplehfsm.py

View file
 .. todo:: move BaseState and Transition into Structure class (because they are kinda private classes) ??
 """
 
-__version__ = "0.0.1.dev"
+# Versioning scheme based on: 
+#          http://en.wikipedia.org/wiki/Versioning#Designating_development_stage
+#
+#   +-- api change, probably incompatible with older versions
+#   |     +-- enhancements but no api change
+#   |     |
+# major.minor[.build[.revision]]
+#                |
+#                +-|* 0 for alpha (status)
+#                  |* 1 for beta (status)
+#                  |* 2 for release candidate
+#                  |* 3 for (public) release
+
+__version__ = "1.0.3.0"
 __author__ = "dr0iddr0id {at} gmail [dot] com (C) 2012"
 
 import unittest

File trunk/symplehfsm/test/test_symplehfsm.py

View file
 TODO: modul doc string
 """
 
-__version__ = u"0.0.1.dev"
 __author__ = u"dr0iddr0id {at} gmail [dot] com (C) 2010"
 
 import operator