Replies: 2 comments
-
Hello @pmi123, you could implement a state history as discussed here and add an from transitions import Machine
import collections
class Model(object):
def __init__(self, history_length):
self.state_history = collections.deque(maxlen=history_length)
@property
def state(self):
return self.state_history[-1]
@state.setter
def state(self, value):
self.state_history.append(value)
def undo(self):
if len(self.state_history) > 1:
# let's assume history is [A, B, C].
# Thus, current state is C and previous state is B.
# Move to previous state B (second last)
self.trigger(f"to_{self.state_history[-2]}")
# The history is now [A, B, C, B].
# Clear history by removing the last two elements.
self.state_history.pop()
self.state_history.pop()
model = Model(5)
machine = Machine(model, states=["A", "B", "C"], ordered_transitions=True, initial="A")
model.next_state() # -> B [A, B]
model.next_state() # -> C [A, B, C]
assert model.is_C()
model.next_state() # -> A [A, B, C, A]
assert model.is_A()
model.undo() # C <- [A, B, C]
model.undo() # B <- [A, B]
assert model.is_B()
model.undo() # A <- [A]
model.undo() # no state change [A]
model.undo() # no state change [A]
assert model.is_A() |
Beta Was this translation helpful? Give feedback.
0 replies
-
Another version that also features redo (with a mode flag): from transitions import Machine
import collections
import enum
class StateMode(enum.Enum):
DEFAULT = 0
UNDO = 1
REDO = 2
class Model(object):
def __init__(self, history_length):
self.state_undo = collections.deque(maxlen=history_length)
self.state_redo = collections.deque(maxlen=history_length)
self.state_mode = StateMode.DEFAULT
@property
def state(self):
return self.state_undo[-1]
@state.setter
def state(self, value):
if self.state_mode == StateMode.UNDO:
self.state_redo.append(self.state_undo.pop())
else:
self.state_undo.append(value)
if self.state_redo and self.state_mode == StateMode.DEFAULT:
self.state_redo.clear()
def undo(self):
if len(self.state_undo) > 1:
self.state_mode = StateMode.UNDO
self.trigger(f"to_{self.state_undo[-1]}")
self.state_mode = StateMode.DEFAULT
return True
return False
def redo(self):
if self.state_redo:
self.state_mode = StateMode.REDO
self.trigger(f"to_{self.state_redo.pop()}")
self.state_mode = StateMode.DEFAULT
return True
return False
model = Model(history_length=5)
machine = Machine(model, states=["A", "B", "C"], ordered_transitions=True, initial="A")
assert model.next_state() # -> B [A, B]
assert model.next_state() # -> C [A, B, C]
assert model.is_C()
assert model.next_state() # -> A [A, B, C, A]
assert model.is_A()
assert model.undo() # C <- [A, B, C]
assert model.undo() # B <- [A, B]
assert model.is_B()
assert model.undo() # A <- [A]
assert not model.undo() # no state change [A]
assert not model.undo() # no state change [A]
assert model.is_A()
assert model.redo()
assert model.redo()
assert model.is_C()
assert model.redo()
assert not model.redo()
assert model.undo()
assert model.is_C()
assert model.to_B()
assert not model.redo()
assert model.undo()
assert model.is_C()
# history is limited to history_length=5 states
# also works with previous version
assert model.next_state()
assert model.next_state()
assert model.next_state()
assert model.next_state()
assert model.next_state()
assert model.next_state()
assert model.next_state()
assert model.next_state()
assert model.next_state()
assert model.undo()
assert model.undo()
assert model.undo()
assert model.undo()
assert not model.undo() |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
I need a transition to take me back to the previous state. Is there such a thing? My use case.
I have a web site with a dashboard (set of buttons in an html snippet) on every page. Each page represents a state in the FSM. However, when I click on a button on the dashboard, it takes me to a new state, test_1, with an associated page test_1.html. I want to have a button on the test_1.html called 'exit', which takes me back to whichever state I came from to get to state test_1.
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions