FMS2 provides Dart implementation of the core design aspects of the UML state diagrams.

Overview

FSM2 provides an implementation of the core design aspects of the UML2 state diagrams.

FMS2 supports:

  • Nested States
  • Concurrent Regions
  • Guard Conditions
  • sideEffects
  • onEnter/onExit
  • streams
  • static analysis tools
  • visualisation tools.

Overview

FSM2 uses a builder to delcare each state machine.

Your application may declare as many statemachines as necessary.

Example

((b) {}) )); ">
import 'package:fsm2/fsm2.dart';

void main() {
  final machine = StateMachine.create((g) => g
    ..initialState(Solid())
    ..state<Solid>((b) => b
      ..on<OnMelted, Liquid>(), sideEffect: (e) => print("I'm melting"))
    ..state<Liquid>((b) {})
 ));

The above examples creates a Finite State Machine (machine) which declares its initial state as being Solid and then declares a single transition which occurs when the event OnMelted event is triggered causing a transition to a new state Liquid.

To trigger an event:

machine.applyEvent(OnMelted());

Documentation

Full documentation is available on gitbooks at:

https://noojee.gitbook.io/fsm2/

Example 2

A simple example showing the life cycle of H2O.

import 'package:fsm2/fsm2.dart';

void main() {
  final machine = StateMachine.create((g) => g
    ..initialState(Solid())
    ..state<Solid>((b) => b
      ..on<OnMelted, Liquid>(sideEffect: (e) => print('Melted'),
          )))
    ..state<Liquid>((b) => b
      ..onEnter((s, e) => print('Entering ${s.runtimeType} State'))
      ..onExit((s, e) => print('Exiting ${s.runtimeType} State'))
      ..on<OnFroze, Solid>(sideEffect: (e) => print('Frozen')))
      ..on<OnVaporized, Gas>(sideEffect: (e) => print('Vaporized'))))
    ..state<Gas>((b) => b
      ..on<OnCondensed, Liquid>(sideEffect: (e) => print('Condensed'))))
    ..onTransition((t) => print(
        'Received Event ${t.event.runtimeType} in State ${t.fromState.runtimeType} transitioning to State ${t.toState.runtimeType}')));

  print(machine.currentState is Solid); // TRUE

  machine.transition(OnMelted());
  print(machine.currentState is Liquid); // TRUE

  machine.transition(OnFroze());
  print(machine.currentState is Solid); // TRUE
}

Credits:

FMS2 is derived from the FSM library which in turn was inspired by Tinder StateMachine library.

Comments
  • onEnter does not execute if state is initialState

    onEnter does not execute if state is initialState

    Hi, i am doing some tests using your great lib :)

    Unfortunately i am running into a problem where onEnter does not execute

    test('foo', () async {
        int i = 0;
        final machine = StateMachine.create((g) => g
          ..initialState<StateA>()
          ..state<StateA>((b) => b..onEnter((_, __) async => i++)));
        await machine.waitUntilQuiescent;
        expect(i, equals(1));
      });
    

    onEnter will never execute if you are using .initialState<>. This does also not work for nested trees. I am using version 0.10.1

    opened by smiLLe 12
  • An amazing state machine plugin! Possible to describe it using script language ?

    An amazing state machine plugin! Possible to describe it using script language ?

    Hi Brett, This is not a issue but a feature request.

    I am a fan to state machine which I think it's another language with higher level abstraction to describe the complex world. The fsm2 is really what I am searching for. The syntax of state machine is extremely well organized and neat with DART style. I really love it! The homepage also explains very detailed principle and advice to author a good state machine. Thank you very much for this great work.

    I notice that fsm2 description is very Declarative compared to other Imperative programming .How can it be possible to describe fsm2 model with a script language , maybe a customized DSL. This can make it possible to write the state machine without the need to compile. The usage scenario is very wide such as test automation, model based development.

    If there is no plan to make fsm2 scriptable, any suggestion for the script language is welcome. Thank you!

    opened by delphi007 7
  • onFork ignores the provided Condition

    onFork ignores the provided Condition

    I'm creating an example with Forks, and looking at the documentation I found an example with condition defined:

        .onFork<OnCheckAir>((b) => b
            ..target<HandleFan>()
            ..target<HandleLamp>(), condition: (s, e) => e.quality < 10)
    

    But when trying out in my example, the condition didn't seem to have any effect.

    Looking at the source code, it doesn't seem to be using the provided condition:

      void onFork<E extends Event>(BuildFork<E> buildFork, {Function(State, E)? condition}) {
        final builder = ForkBuilder<E>();
        buildFork(builder);
        final definition = builder.build();
    
        final choice = ForkTransitionDefinition<S, E>(_stateDefinition, definition);
    
        _stateDefinition.addTransition(choice);
      }
    
    opened by canastro 5
  • Docs link is broken

    Docs link is broken

    Just a notice, that the link https://bsutton.gitbook.io/fsm2/ redirects to https://bsutton.gitbook.io/sounds/fsm2/ , which looks like another library, so the link is kind of broken :)

    opened by cmaster11 3
  • JoinTransitionDefinition re-initialisation of late property

    JoinTransitionDefinition re-initialisation of late property

    Given the following state machine:

    StateMachine.create((g) => g
          ..initialState<Idle>()
          ..state<Idle>((b) => b..on<OnFocus, Typing>())
          ..state<Typing>((b) => b
            ..on<OnBlur, Idle>()
            ..onFork<OnValueChange>(
                (b) => b..target<Point>()..target<Autocomplete>(),
                condition: (e) => e.isFormula)
            ..coregion<TypingFormula>((b) => b
              ..onJoin<OnValueChange, Typing>(condition: (e) => !e.isFormula)
    
              // Autocomplete state machine
              ..state<Autocomplete>((b) => b)
              // Point mode state-mahcine
              ..state<Point>((b) => b)))
          ..onTransition((from, e, to) => print(
              'Received Event $e in State ${from!.stateType} transitioning to State ${to!.stateType}')));
    
    class OnValueChange implements Event {
      final bool isFormula;
      const OnValueChange({required this.isFormula});
    }
    

    When running the following unit test:

    test('First Test', () async {
          var machine = MyMachine().machine;
    
          expect(machine.isInState<Idle>(), isTrue);
    
          machine.applyEvent(OnFocus());
          machine.applyEvent(OnValueChange(isFormula: true));
          await machine.waitUntilQuiescent;
    
          expect(machine.isInState<TypingFormula>(), isTrue);
    
          machine.applyEvent(OnValueChange(isFormula: false));
          await machine.waitUntilQuiescent;
    
          expect(machine.isInState<Typing>(), isTrue);
          expect(machine.isInState<TypingFormula>(), isFalse);
        });
    

    I get the following error:

    LateInitializationError: Field '_triggeredBy@70402403' has already been initialized.
    

    Which seems to be related with JoinTransitionDefinition and late final E _triggeredBy;.

    Not sure if this is an actual issue, or a problem with the way I have setup my machine.

    opened by canastro 2
  • Install and run the fsm2 viewer tool

    Install and run the fsm2 viewer tool

    I've created a StateMachine and I was now trying to follow the steps to generate the visualization:

    $ flutter pub global activate fsm2
    $ flutter pub global list
    fsm2 2.0.1
    fvm 1.3.7
    
    $ fsm2 --install        
    Failed to precompile fsm2:fsm2:
    Dart_LoadScriptFromKernel: The binary program does not contain 'main'.
    pub finished with exit code 1
    
    $ fsm2 --show packages/xyz/lib/my_state_machine.dart
    Failed to precompile fsm2:fsm2:
    Dart_LoadScriptFromKernel: The binary program does not contain 'main'.
    pub finished with exit code 1
    

    Is there anything wrong/missing in the steps I took?

    opened by canastro 2
  • OnExit sending fromState instead of toState

    OnExit sending fromState instead of toState

    When adding an OnExit the autocomplete added a parameter toState, maybe due to this definition.

    Yet, when trying out it seems to be returning the fromState from here.

    I could use the toState parameter in something I'm working on, but I'm not sure if the issue is the type definition or the actual wrong parameter being sent.

    opened by canastro 0
  • InitialState for nested states doesnt seem to work

    InitialState for nested states doesnt seem to work

    Given the following state machine When I transition to a nested state Then transition to this state's initial state

    In reality it the statemachine is currently ignoring the initial state and it just transitions to the root of the nested state.

    Example:

    Given the following statemachine:

      final machine = StateMachine.create(
        (g) => g
          ..initialState<Start>()
          ..state<Start>((g) => g..on<OnKickStart, Main>())
          ..state<Main>(
            (g) => g
              ..on<OnTickFirst, First>()
              ..on<OnTickSecond, Second>()
              ..coregion<First>(
                (g) => g
                  ..initialState<One>()
                  ..state<One>((g) => g..on<OnToggle, Two>())
                  ..state<Two>((g) => g..on<OnToggle, One>()),
              )
              ..coregion<Second>(
                (g) => g
                  ..initialState<Three>()
                  ..state<Three>((g) => g..on<OnToggle, Four>())
                  ..state<Four>((g) => g..on<OnToggle, Three>()),
              ),
          ),
      );
    

    When: applying a OnKickStart event Reality: the statemachine transitions to Main->VirtualRoot" Expected: the statemachine transitions to Main->First->One->VirtualRoot and Main->Second->Three->VirtualRoot.

    In this XState visualizer you can see that by triggering "Kickstart" the machine transitions to all initial states of the parallel machines.

    In this PR you can see a failing test for this scenario.

    opened by canastro 7
  • IntialEvent triggered multiple times and sets state to the first leaf state

    IntialEvent triggered multiple times and sets state to the first leaf state

    Given a state machine with nested states and coregions When i boot the state machine Expected it should set the initial state (in the following case it should be Typing) Actual it triggers multiple InitialEvent until it reaches the first leaf

    I'm not sure if I'm failing to see any specificity on the definition of a state machine, but this seems unexpected

    import 'package:fsm2/fsm2.dart';
    
    void main() {
      StateMachine.create((g) => g
        ..initialState<Typing>()
        ..state<Typing>((b) => b
          ..onFork<OnValueChange>(
            (b) => b..target<Point>()..target<Autocomplete>(),
            condition: (e) => true, // Some logic to check if it is a formula
          )
          ..coregion<TypingFormula>((b) => b
            ..onJoin<OnValueChange, Typing>(
              condition: (e) => false, // Some logic to check if it is a formula
            )
    
            // Autocomplete state machine
            ..state<Autocomplete>((b) => b
              // Autocomplete events
              ..on<OnCandidateSelection, AutocompleteList>()
              ..on<OnFunctionSelection, AutocompleteDetails>()
              ..on<OnAutocompleteInvalidSelection, AutocompleteUnavailable>()
              // Autocomplete states
              ..state<AutocompleteList>((b) => b)
              ..state<AutocompleteDetails>((b) => b)
              ..state<AutocompleteUnavailable>((b) => b))
            // Point mode state-mahcine
            ..state<Point>((b) => b
              // Point mode events
              ..on<OnReferenceSelection, PointReference>()
              ..on<OnSlotSelection, PointSlot>()
              ..on<OnDisablePoint, PointDisabled>()
              ..on<OnPointInvalidSelection, PointUnavailable>()
              // Point mode states
              ..state<PointUnavailable>((b) => b)
              ..state<PointSlot>((b) => b)
              ..state<PointReference>((b) => b)
              ..state<PointDisabled>((b) => b))))
        ..onTransition((from, e, to) => print(
            'Received Event $e in State ${from!.stateType} transitioning to State ${to!.stateType}')));
    }
    
    
    // Definition of states and events, they are all just empty states and events so I removed them from this sample
    

    When I execute this, the InitialEvent gets triggered and takes my machine directly to AutocompleteList.

    Received Event Instance of 'InitialEvent' in State VirtualRoot transitioning to State Typing
    Received Event Instance of 'InitialEvent' in State VirtualRoot transitioning to State TypingFormula
    Received Event Instance of 'InitialEvent' in State VirtualRoot transitioning to State Autocomplete
    Received Event Instance of 'InitialEvent' in State VirtualRoot transitioning to State AutocompleteList
    
    opened by canastro 1
Owner
Brett Sutton
Long time hacker with a background in C/C++/Java. I'm currently sampling the delights of dart and flutter.
Brett Sutton
A flutter plugin which provides Crop Widget for cropping images.

A flutter plugin which provides Crop Widget for cropping images. crop_your_image provides only minimum UI for deciding cropping area inside images. Other UI parts, such as "Crop" button or "Change Aspect Ratio" button, need to be prepared by each app developers.

Chooyan 96 Dec 31, 2022
A powerful official extension library of image, which support placeholder(loading)/ failed state, cache network, zoom pan image, photo view, slide out page, editor(crop,rotate,flip), paint custom etc.

extended_image Language: English| 中文简体 A powerful official extension library of image, which support placeholder(loading)/ failed state, cache network

FlutterCandies 1.6k Dec 31, 2022
Crop any widget/image in Android, iOS, Web and Desktop with fancy and customizable UI, in pure Dart code.

crop A Flutter package for cropping any widget, not only images. This package is entirely written in Dart and supports Android, iOS, Web and Desktop.

Mahdi 225 Jan 6, 2023
A Dart port of zxing that encode and decode multiple 1D/2D barcodes.

ZXing-Dart A Dart port of zxing that encode and decode multiple 1D/2D barcodes. Progress Core package translate Core test translate Core unit test(all

shirne 35 Dec 14, 2022
A dart implementation of the chord.js javascript package to display beautiful chord diagrams

flutter_guitar_tabs This is a dart implementation of the chord.js javascript package to display beautiful chord diagrams like the ones below. Where to

null 20 Nov 16, 2022
Dart JS interop for Mermaid - The Javascript tool that makes use of a markdown based syntax to render customizable diagrams, charts and visualizations.

Mermaid (Dart) Dart JS interop for Mermaid - Javascript library that makes use of a markdown based syntax to render customizable diagrams, charts and

Tim Maffett 3 Dec 12, 2022
It's OK to love Flutter and hate hand-coding design elements. Parabeac-Core converts design files into Flutter code.

Parabeac-Core Parabeac-Core converts design files into Flutter code driven by open-source & community. Contribute · Discord Community · Designer Proto

Parabeac 536 Jan 4, 2023
Flutter Package used to 'edit' basics aspects [Brightness, Contrast, Saturation, etc...] from a widget or image.

on_image_matrix on_image_matrix is a Flutter Package used to 'edit' basics aspects [Brightness, Contrast, Saturation, etc...] from a widget or image.

Lucas Josino 6 Oct 23, 2022
State Persistence - Persist state across app launches. By default this library store state as a local JSON file called `data.json` in the applications data directory. Maintainer: @slightfoot

State Persistence Persist state across app launches. By default this library store state as a local JSON file called data.json in the applications dat

Flutter Community 70 Sep 28, 2022
The Dart SDK, including the VM, dart2js, core libraries, and more.

Dart A client-optimized language for fast apps on any platform Dart is: Optimized for UI: Develop with a programming language specialized around the n

Dart 8.7k Jan 2, 2023
Flutter plugin that provides a quick&dirty workaround for incompatibility between VMWare Airwatch MDM solution and Dart Sockets implementation

airwatch_socket_workaround This plugin has been created to enable flutter apps to reach endpoints that are only reachable using a VMWare airwatch per

Gonçalo Silva 5 Nov 11, 2022
GetDoctor is a complete app developed in Flutter, Firebase and Blazor,.Net Core API and SQL Server

GetDoctor ?? ?? ?? GetDoctor is a complete app developed in Flutter, Firebase and Blazor,DotNet Core API and SQL Server GetDoctor is a complete packag

Sunil Vijayan 69 Dec 19, 2022
A complete grocery store developed with Flutter, .Net Core, Firebase, One Signal and SQL Server as backend

# Grocery-Store developed in Flutter,DotNet Core, Firebase, One-Signal, SQL-Server, Stripe, Razorpay, Paypal A complete grocery store developed with F

Sunil Vijayan 31 Jan 1, 2023
dartevel core framework

dartevel-framework dartevel core framework start project: 2021-08-23 - ۱۴۰۰/۰۶/۰۱ Getting Started Install Dart. Activate Dartevel pub global activate

Dartevel Framework 10 Dec 24, 2022
The core application for the briefcase network.

briefcase An experimental peer-to-peer network. Compiling Before compiling, be sure to update the versioning information with: pub run pubspec_extract

null 3 Jan 5, 2022
A Flutter application implementing AR core, Text-to-speech, and Speech-to-text technologies.

ar_x_ai A Flutter application implementing AR core, Text to speech and Speech to text technologies. Getting Started This project is a starting point f

Alston Fernandes 1 Dec 17, 2021
Passwall Server is the core backend infrastructure for Passwall platform

PassWall Server PassWall Server is the core backend for open source password manager PassWall platform. Using this server, you can safely store your p

PassWall 669 Dec 20, 2022
Flutter's core Dropdown Button widget with steady dropdown menu and many options you can customize to your needs.

Flutter DropdownButton2 Intro Flutter's core Dropdown Button widget with steady dropdown menu and many options you can customize to your needs. Featur

AHMED ELSAYED 125 Jan 4, 2023
A Package providing Core functionality/Template to start off a Clean Architecture based project

A Package providing Core functionality/Template to start off a Clean Architecture based project Features Provides with APIResult & UseCaseResult model

null 1 Dec 25, 2021