In the real system, the predicates are not as simple as this. An example from my requirements is:
a implies b && (c ∥ d) && e where each letter is a particular state of a piece of equipment. The states are also more complex, for example, one state might be item1 is inside item2 exclusion zone. There are also transition states, such as "Turning On", and "Turning Off".
# ,----------------------------,
# v |
# ,----------[BothOffState]--------, |
# | turnOn1() | turnOn2() |
# v v |
# [Item1_OnState[item1_OnState ] [Item2_OnState][item2_OnState] |
# | turnOff1() | turnOff2() |
# `---------------------------'-------------'
#
class IState(metaclass=ABCMeta):
def __init__(self, fsm):
print("system : " + fsm.currentState.__class__.__name__ + " -> " + self.__class__.__name__)
self._fsm = fsm
class BothOffState(IState):
def __init__(self, fsm):
super().__init__(fsm)
def turnOn1(self):
self._fsm.currentState = Item1_OnStateitem1_OnState(self._fsm)
def turnOn2(self):
self._fsm.currentState = Item2_OnStateitem2_OnState(self._fsm)
class Item1_OnStateitem1_OnState(IState):
def __init__(self, fsm):
super().__init__(fsm)
def turnOff1(self):
self._fsm.currentState = BothOffState(self._fsm)
class Item2_OnStateitem2_OnState(IState):
def __init__(self, fsm):
super().__init__(fsm)
def turnOff2(self):
self._fsm.currentState = BothOffState(self._fsm)
class FSM:
currentState = None
def __init__(self):
self.currentState = BothOffState(self)
if __name__ == "__main__":
system = FSM()
print("<turning on 1>")
system.currentState.turnOn1()
#system.currentState.turnOn2() AttributeError because this state transition doesn't exist
print("<turning off 1>")
system.currentState.turnOff1()
print("<turning on 2>")
system.currentState.turnOn2()
#Output:
#
# system : NoneType -> BothOffState
# <turning on 1>
# system : BothOffState -> Item1_OnStateitem1_OnState
# <turning off 1>
# system : Item1_OnStateitem1_OnState -> BothOffState
# <turning on 2>
# system : BothOffState -> Item2_OnStateitem2_OnState