Skip to content

Transitions

Ricardo Canastro edited this page Mar 4, 2022 · 14 revisions

Defining events and transitions

Create events

In order to transition between states, you'll need to dispatch events. Very often you'll need some metadata to go along with your events so that you can guard some transitions or apply some side effects.

To create an Automata event, all you'll have to do is to extend the abstract Event class, and you're free to add any data that you want.

class Search extends Event {
  final String query;
  const Search(this.query);
}

Simple transitions

On the following example, both the transition defined in the Off and On states are simple transitions.

final machine = StateMachine.create(
  (g) => g
    ..initial<Off>()
    ..state<Off>(builder: (g) => g..on<OnToggle, On>())
    ..state<On>(builder: (g) => g..on<OnToggle, Off>())
);

Eventless transitions

On the following example we have a simple transition for the OnAwardPoints event, this transition will move the state to itself which will then trigger the Eventless transitions created with the always function. These transitions are executed every time regardless of the event that triggered it, they require a condition and will transition to the given target if it evaluates to true.

final machine = StateMachine.create(
  (g) => g
    ..initial<Playing>()
    ..state<Playing>(
      builder: (b) => b
        // Eventless transition
        // Will transition to either 'win' or 'lose' immediately upon
        // entering 'playing' state or receiving OnAwardPoints event
        // if the condition is met.
        ..always<Win>(condition: (_) => scoreboard.points > 99)
        ..always<Lose>(condition: (_) => scoreboard.points < 0)
        ..on<OnAwardPoints, Playing>(
          actions: [
            (OnAwardPoints e) {
              scoreboard.points += e.points;
            },
          ],
        ),
    )
    ..state<Win>(type: StateNodeType.terminal)
    ..state<Lose>(type: StateNodeType.terminal),
);

Triggering a transitions

TBA (talk about how a transition is picked)

Guards

Guards are the conditions defined in each transition. A transition is only applied if it's guard evaluates to true.

In the following example the first transition will match for the first 18 calls, afterwards that transition will evaluate to false and the applied transition will be the one that has MiddleAged as it's target.

final machine = StateMachine.create(
  (g) => g
    ..initial<Alive>()
    ..state<Alive>(
      builder: (b) => b
        ..initial<Young>()

        // Transitions
        ..on<OnBirthday, Young>(
          condition: (e) => human.age < 18,
          actions: [(e)  { human.age++; }],
        )
        ..on<OnBirthday, MiddleAged>(
          condition: (e) => human.age < 50,
          actions: [(e) { human.age++;}],
        )
        ..on<OnBirthday, Old>(
          condition: (e) => human.age < 80,
          actions: [(e) { human.age++; }],
        )
        ..on<OnDeath, Purgatory>()

        // States
        ..state<Young>()
        ..state<MiddleAged>()
        ..state<Old>(),
    )
    ..state<Dead>(),
);

Actions

actions

TBA

onEntry

TBA

onExit

TBA

Clone this wiki locally