Skip to content

Commit 870056f

Browse files
authored
Introduced PreActions in state machine
1 parent b003632 commit 870056f

File tree

7 files changed

+152
-23
lines changed

7 files changed

+152
-23
lines changed

sample/sample3.xml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?xml version="1.0"?>
2+
<x:States xmlns:x="pystatemachine:sm">
3+
<State>
4+
<Name>Enter</Name>
5+
<Event>
6+
<Name>ToExit</Name>
7+
<ToState>Exit</ToState>
8+
<PreConditions>
9+
<Condition>
10+
<Expression>test3.everFalse</Expression>
11+
<Result>False</Result>
12+
</Condition>
13+
<Condition>
14+
<Expression>test3.test</Expression>
15+
<Result>2</Result>
16+
</Condition>
17+
</PreConditions>
18+
<PreActions>
19+
<Action>
20+
<Expression>test3.testPrint</Expression>
21+
</Action>
22+
</PreActions>
23+
</Event>
24+
</State>
25+
<State>
26+
<Name>Exit</Name>
27+
<Event>
28+
<Name>ToNull</Name>
29+
<ToState>Null</ToState>
30+
<PreConditions>
31+
<Condition>
32+
<Expression>test3.everFalse</Expression>
33+
<Result>True</Result>
34+
</Condition>
35+
</PreConditions>
36+
</Event>
37+
</State>
38+
<State>
39+
<Name>Null</Name>
40+
<Event>
41+
<Name>ToNull</Name>
42+
<ToState>Null</ToState>
43+
</Event>
44+
</State>
45+
<Initial_State>Enter</Initial_State>
46+
</x:States>

schema/StateMachine.xsd

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
xmlns:sm="pystatemachine:sm">
55
<!-- definition of simple elements -->
66
<!--xs:element name="Condition" type="sm:NonEmptyString"/-->
7-
<xs:element name="Action" type="sm:NonEmptyString"/>
7+
<!--xs:element name="Action" type="sm:NonEmptyString"/-->
88
<!-- definition of simple type -->
99
<xs:simpleType name="NonEmptyString"> <!-- we can describe our types separately to reuse them later -->
1010
<xs:restriction base="xs:string">
@@ -21,6 +21,12 @@
2121
</xs:sequence>
2222
</xs:complexType>
2323

24+
<xs:complexType name="Action">
25+
<xs:sequence>
26+
<xs:element name="Expression" type="sm:NonEmptyString" minOccurs="1" maxOccurs="1"/>
27+
</xs:sequence>
28+
</xs:complexType>
29+
2430

2531
<xs:complexType name="Conditions">
2632
<xs:sequence>
@@ -30,7 +36,7 @@
3036

3137
<xs:complexType name="Actions">
3238
<xs:sequence>
33-
<xs:element ref="sm:Action" minOccurs="1"/>
39+
<xs:element name="Action" type="sm:Action" minOccurs="1" maxOccurs="1"/>
3440
</xs:sequence>
3541
</xs:complexType>
3642

src/Action.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class Action:
2+
def __init__(self, expression :str):
3+
self.expression = expression
4+
5+
def to_string(self):
6+
result_s = ""
7+
return result_s

src/Actions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
class Actions:
2-
def __init__(self, action : str):
3-
self.action = action
2+
def __init__(self, actions = []):
3+
self.actions = actions
44

55
def to_string(self):
66
result_s = ""

src/ReadStateMachine.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from Condition import Condition
22
from Conditions import Conditions
33
from Actions import Actions
4+
from Action import Action
45
from Event import Event
56
from State import State
67
import xml.etree.ElementTree as ET
@@ -28,8 +29,8 @@ def ReadStateMachineFile(xml_file : str):
2829
to_state = ""
2930
pre_conditions = None # dummy
3031
post_conditions = None # dummy
31-
pre_actions = Actions("") #dummy
32-
post_actions = Actions("") #dummy
32+
pre_actions = None #dummy
33+
post_actions = None #dummy
3334

3435
for event_child in state_child:
3536

@@ -66,10 +67,18 @@ def ReadStateMachineFile(xml_file : str):
6667
None
6768
elif event_child.tag == "PreActions":
6869
# State->Event->PreActions Element
70+
pre_action_elements = []
6971
for preactions_child in event_child:
7072
#print(preactions_child.text)
7173
# State->Event->PreActions->Action Element
72-
None
74+
if preactions_child.tag == "Action":
75+
expression = ""
76+
for action_child in preactions_child:
77+
if action_child.tag == "Expression":
78+
expression = action_child.text
79+
pre_action_elements.append(Action(expression))
80+
pre_actions = Actions(pre_action_elements)
81+
7382
elif event_child.tag == "PostActions":
7483
# State->Event->PostActions Element
7584
for postactions_child in event_child:

src/StateMachine.py

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,47 @@ def __init__(self, xml_file : str):
99
self.current_state = ""
1010
self.context = {}
1111

12-
def __CheckCondition(self,conditions):
12+
def __CheckConditions(self,conditions):
1313
all_conditions_satisfied = True
1414
if(conditions != None):
15-
conditions = conditions.conditions
16-
for condition in conditions:
15+
_conditions = conditions.conditions
16+
for condition in _conditions:
1717
if condition.expression in self.context:
1818
func = self.context[condition.expression]
1919
result = None
20-
if callable(func):
21-
result = func()
20+
if callable(func):
21+
result = func()
22+
else:
23+
result = func
24+
if str(result) != condition.result:
25+
all_conditions_satisfied = False
26+
break
2227
else:
23-
result = func
24-
if str(result) != condition.result:
25-
all_conditions_satisfied = False
26-
break
28+
print("No Found Condition Expression ", condition.expression ," in Context")
29+
all_conditions_satisfied = False
2730
else:
28-
print("No Precondition")
31+
print("No Condition")
2932
return all_conditions_satisfied
3033

34+
def __ExecActions(self,actions):
35+
all_action_executed = True
36+
if(actions != None):
37+
_actions = actions.actions
38+
for action in _actions:
39+
if action.expression in self.context:
40+
func = self.context[action.expression]
41+
if callable(func):
42+
#print("Call ",action.expression)
43+
func()
44+
else:
45+
func
46+
else:
47+
print("No Found Action Expression ", action.expression ," in Context")
48+
all_action_executed = False;
49+
else:
50+
print("No Action")
51+
return all_action_executed
52+
3153
def get_current_state(self):
3254
return self.current_state
3355

@@ -49,14 +71,16 @@ def InjectEvent(self, event : str):
4971
if event in possible_events:
5072
handled_event = possible_events[event]
5173
## Preconditions
52-
all_pre_conditions_satisfied = self.__CheckCondition(handled_event.pre_conditions)
74+
all_pre_conditions_satisfied = self.__CheckConditions(handled_event.pre_conditions)
5375
if(all_pre_conditions_satisfied):
5476
## Preactions
55-
## Transition
56-
print("Transition ", self.current_state, " ------> ", handled_event.to_state)
57-
self.current_state = handled_event.to_state
58-
## Postactions
59-
## Postconditions
77+
all_pre_actions_executed = self.__ExecActions(handled_event.pre_actions)
78+
if(all_pre_actions_executed):
79+
## Transition
80+
print("Transition ", self.current_state, " ------> ", handled_event.to_state)
81+
self.current_state = handled_event.to_state
82+
## Postactions
83+
## Postconditions
6084
else:
6185
print("Not all PreConditions satisfied")
6286
else:

tests/test3.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import sys
2+
sys.path.append('../src')
3+
4+
from StateMachine import StateMachine
5+
6+
test = 2
7+
8+
def main():
9+
10+
sm = StateMachine("../sample/sample3.xml")
11+
12+
sm.LoadStateMachine()
13+
14+
sm.addVariableToContext("test3", "everFalse")
15+
sm.addVariableToContext("test3", "test")
16+
sm.addVariableToContext("test3", "testPrint")
17+
18+
print(sm.get_current_state())
19+
sm.InjectEvent("ToExit")
20+
print(sm.get_current_state())
21+
sm.InjectEvent("ToExit")
22+
print(sm.get_current_state())
23+
sm.InjectEvent("ToNull")
24+
print(sm.get_current_state())
25+
sm.InjectEvent("ToExit")
26+
print(sm.get_current_state())
27+
sm.InjectEvent("ToNull")
28+
29+
def everFalse():
30+
return False
31+
32+
def testPrint():
33+
print("Test")
34+
35+
36+
if __name__ == "__main__":
37+
main()

0 commit comments

Comments
 (0)