def test_epsilon_transition_is_triggered_automatically(self): a = TimedFiniteAutomaton("start") a.add_state("end") a.add_transition("start", "end", "event") a.add_transition("end", "start") a.feed("event") self.assertEqual("start", a.state)
def test_normal_and_timed_transitions_mix(self): a = TimedFiniteAutomaton("start") a.add_state("a") a.add_state("b") a.add_transition("start", "a", "foo") a.add_transition("start", "b", 1.0) a.feed("foo") self.assertEqual("a", a.state)
def test_tick_without_arguments(self): a = TimedFiniteAutomaton("start") a.add_state("end") a.add_transition("start", "end", .2) a.tick() self.assertEqual("start", a.state) time.sleep(.3) a.tick() self.assertEqual("end", a.state)
def test_callback_called_on_transition(self): a = TimedFiniteAutomaton("start") a.add_state("end") a.add_transition("start", "end", "event") transitions = [] a.add_state_change_listener(lambda *a: transitions.append(a)) a.feed("event") self.assertEqual( [("start", "end", "event")], transitions, )
def test_timed_transition_trigger_the_first_one(self): a = TimedFiniteAutomaton("start") a.add_state("a") a.add_state("b") a.add_transition("start", "a", 2.0) a.add_transition("start", "b", 1.0) a.tick(2.0) self.assertEqual("b", a.state)
def test_callback_called_on_transition_to_self_on_timer(self): a = TimedFiniteAutomaton("start") a.add_transition("start", "start", 1.0) transitions = [] a.add_state_change_listener(lambda *a: transitions.append(a)) a.tick(2.0) self.assertEqual( [("start", "start", 1.0)], transitions, )
def test_timed_transition(self): a = TimedFiniteAutomaton("start") a.add_state("end") a.add_transition("start", "end", 1.0) a.tick(2.0) self.assertEqual("end", a.state)
def test_adding_transition_and_walking_it(self): a = TimedFiniteAutomaton("start") a.add_state("end") a.add_transition("start", "end", "event") a.feed("event") self.assertEqual("end", a.state)
def __init__(self): self._volume = self.MINVOL self.playing = True automat = TimedFiniteAutomaton("idle") automat.add_state("volume_up") automat.add_state("volume_down") automat.add_state("nudge_up") automat.add_state("nudge_down") automat.add_state("volume_up_or_toggle") automat.add_state("volume_down_or_toggle") automat.add_state("toggle_play_pause") # waiting for either volume change or toggling play/pause automat.add_transition("idle", "volume_up_or_toggle", "volume+pressed") automat.add_transition("idle", "volume_down_or_toggle", "volume-pressed") # after self.SAME_TIME_THRESHOLD seconds, we will transition to volue up/down # we will re-enter the state on .5 timer events to further increase volume automat.add_transition("volume_up_or_toggle", "volume_up", self.SAME_TIME_THRESHOLD) automat.add_transition("volume_down_or_toggle", "volume_down", self.SAME_TIME_THRESHOLD) automat.add_transition("volume_up", "volume_up", .5) automat.add_transition("volume_down", "volume_down", .5) automat.add_transition("volume_up", "idle", "volume+released") automat.add_transition("volume_down", "idle", "volume-released") # when we wait for toggle_play_pause, but already release, # just nudge the volume once in the respective direction! automat.add_transition("volume_up_or_toggle", "nudge_up", "volume+released") automat.add_transition("nudge_up", "idle") automat.add_transition("volume_down_or_toggle", "nudge_down", "volume-released") automat.add_transition("nudge_down", "idle") # if within this timeframe the opposite key was pressed, toggle! automat.add_transition("volume_up_or_toggle", "toggle_play_pause", "volume-pressed") automat.add_transition("volume_down_or_toggle", "toggle_play_pause", "volume+pressed") # from play_pause, transition automatically back to idle automat.add_transition("toggle_play_pause", "idle") self._automat = automat self._automat.add_state_change_listener(self._react_to_state_changes) print(automat.dot())