A library for finite state machine realization

Overview

A library for finite state machine realization in Dart. Inspired by Tinder StateMachine library.

Usage

A simple usage example (using dfunc library for generating sealed classes):

import 'package:dfunc/dfunc.dart';
import 'package:fsm/fsm.dart';

part 'fsm_example.g.dart';

void main() {
  final machine = StateMachine<State, Event, SideEffect>.create((g) => g
    ..initialState(Solid())
    ..state<Solid>((b) => b
      ..on<OnMelted>(
          (Solid s, OnMelted e) => b.transitionTo(Liquid(), LogMelted())))
    ..state<Liquid>((b) => b
      ..onEnter((s) => print('Entering ${s.runtimeType} state'))
      ..onExit((s) => print('Exiting ${s.runtimeType} state'))
      ..on<OnFroze>(
          (Liquid s, OnFroze e) => b.transitionTo(Solid(), LogFrozen()))
      ..on<OnVaporized>(
          (Liquid s, OnVaporized e) => b.transitionTo(Gas(), LogVaporized())))
    ..state<Gas>((b) => b
      ..on<OnCondensed>(
          (Gas s, OnCondensed e) => b.transitionTo(Liquid(), LogCondensed())))
    ..onTransition((t) => t.match((v) => print(v.sideEffect), (_) {})));

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

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

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

@sealed
abstract class State with _$State {}

class Solid extends State {}

class Liquid extends State {}

class Gas extends State {}

@sealed
abstract class Event with _$Event {}

class OnMelted extends Event {}

class OnFroze extends Event {}

class OnVaporized extends Event {}

class OnCondensed extends Event {}

@sealed
abstract class SideEffect with _$SideEffect {}

class LogMelted extends SideEffect {}

class LogFrozen extends SideEffect {}

class LogVaporized extends SideEffect {}

class LogCondensed extends SideEffect {}

Features and bugs

Please file feature requests and bugs at the issue tracker.

You might also like...

Timer based on provider state manager

timer_provider Timer based on provider state manager Getting Started This project is a starting point for a Flutter application. A few resources to ge

Aug 10, 2022

App for Shop Management and State Management Learning

App for Shop Management and State Management Learning

๐ŸŒŸ E-Commerce ๐ŸŒŸ App for Shop Management and State Management Learning ๐ŸŒ Links ๐ŸŒ ๐Ÿ“‚ Repo ยท ๐Ÿš€ Got Issue ๐Ÿš€ Features Authentication System Using Fire

Jul 19, 2022

A new practical project made with Flutter and some native widgets, movie API, provider state and more.

A new practical project made with Flutter and some native widgets, movie API, provider state and more.

Flutter Movie App This project was created with Flutter and some native Widgets like SingleChildScrollView, Hero Animation, SliverAppBar, StreamBuilde

Jul 12, 2022

A Dice App for flutter beginners when building with State

dicee A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if this is

Nov 15, 2021

An example of how to mock state for testing widgets when using riverpod StateNotifierProvider

Testing Riverpod StateNotifierProvider An example of how to mock state for testing widgets when using riverpod StateNotifierProvider. These tests work

Dec 13, 2022

A Flutter plugin for handling Connectivity and REAL Connection state in the mobile, web and desktop platforms. Supports iOS, Android, Web, Windows, Linux and macOS.

A Flutter plugin for handling Connectivity and REAL Connection state in the mobile, web and desktop platforms. Supports iOS, Android, Web, Windows, Linux and macOS.

cross_connectivity A Flutter plugin for handling Connectivity and REAL Connection state in the mobile, web and desktop platforms. Supports iOS, Androi

Nov 15, 2022

Concepts used Flutter layout,State management, Blockchain integration, Http api integration, Smart contracts

HS_CryptoCoin_Wallet First project using Flutter with Blockchain Getting Started This project is a starting point for a Flutter application. A few res

Dec 23, 2021

A super-fast and efficient state management solution for Flutter...

turbo A super-fast, efficient state management solution for Flutter. Turbo does not use streams, which are extremely inefficient, or use complex abstr

Oct 16, 2022

Todo app - an application maintaining user's todo list. Made to learn state management

todo_app A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if this

Mar 15, 2022
Comments
  • Generating code for tests

    Generating code for tests

    I'm having trouble compiling the test methods as the file 'fsm_test.g.dart' doesn't exists.

    I'm assuming this is generated by build_running but running a build does nothing:

    pub run build_runner build 
    [INFO] Generating build script completed, took 211ms
    [SEVERE] Nothing can be built, yet a build was requested.
    [INFO] Reading cached asset graph completed, took 35ms
    [INFO] Checking for updates since last build completed, took 304ms
    [INFO] Running build completed, took 2ms
    [INFO] Caching finalized dependency graph completed, took 25ms
    [INFO] Succeeded after 36ms with 0 outputs (0 actions)
    
    opened by bsutton 2
  • Proposed breaking change to the on clause

    Proposed breaking change to the on clause

    The current on clause takes two arguments. This tends to make the FSM definitions fairly dense.

    I'm proposing a breaking change to the api so that the on clause on takes a single argument.

    This changes has two advantages:

    1. the code will be easier to read
    2. we reduce the risk of further breaking changs as the single argument will be a class which can contain additional arguments if required at a later date.

    Whilst this change will break existing code the updates to the code will be straight forward and mechanical in nature.

    Here is an example of what the existing code looks like:

    As such I'm proposing the following alteration to the '.on' method.

    
    
    ..s_stateMachine = StateMachine<State, Event, SideEffect>.create(
          (g) => g
            ..initialState(AppLaunched())
    
            /// AppLaunched
            ..state<AppLaunched>((builder) => builder
              ..onEnter((s) => s.onEnter())
              ..on<ForceRegistration>((initialState, forceRegistration) =>   ForcedRegistrationRequired())
              ..on<HasApiKey>((initialState, hasApiKey) => RegistrationRequired())
              ..on<MissingApiKey>((initialState, missingApiKey) => Registered()))
    
    

    Here is an example of what the new code would look like:

    _stateMachine = StateMachine<State, Event, SideEffect>.create(
          (g) => g
            ..initialState(AppLaunched())
    
            /// AppLaunched
                  ..state<AppLaunched>((builder) => builder
              ..onEnter((s) => s.onEnter())
              ..on<ForceRegistration>((details) =>   ForcedRegistrationRequired())
              ..on<HasApiKey>((details) => RegistrationRequired())
              ..on<MissingApiKey>((details) => Registered()))
    

    The details argument would be:

    class TransitionDetails<STATE, EVENT>
    {
          STATE state;
          EVENT event;
    }
    
    typedef TranstionFunction<STATE, EVENT> = TransitionTo<STATE, SIDE_EFFET> Function(TransitionDetails details);
    
    

    Thoughts?

    opened by bsutton 0
  • Implement Choice Pseudo-State

    Implement Choice Pseudo-State

    I'm looking to encapsulate some of the transition logic in the state. I think this is essentially a guard condition.

    An event comes into a state and depending on data in the event the states transition needs to be selected dynamically.

    So the question is, what is the appropriate why to dynamically select the next state when an event arrives.

    
       /// HasMobileNo
            ..state<MobileNoAcquired>((builder) => builder
            ..on<ApplyUserDetails>((mobileNoAcquired, applyUserDetails) => mobileNoAcquired.applyUserDetails(applyUserDetails))
            ..on<NoUserForMobile>((mobileNoAcquired, noUserForMobile) => EmailRequired().transitionTo(builder, noUserForMobile))
            ..on<UserDisabled>((mobileNoAcquired, userDisabled) => AccountDisabled().transitionTo(builder, userDisabled))
    
    
    class MobileNoAcquired extends State {
      TransitionTo<State, SideEffect> applyUserDetails(ApplyUserDetails details) {
        switch (details.details.userStatus) {
          case UserStatus.NOT_FOUND:
            return super.transitionTo(NoUserForMobile()));
            break;
          case UserStatus.DISABLED:
            return FSM().transition(UserDisabled());
            break;
        }
      }
    }
    

    You can see from the above code I've considered a couple of alternatives but neither seems corret.

    The first version where I call super.transitionTo returns the wrong type. The second where I call FSM().transition just seems wrong as I'm calling back into the fsm at the very top level (FSM is a StateMachine) whilst already in a state transition.

    So what is the correct way of doing this?

    opened by bsutton 3
  • Improve onTransition to include prior state, new state and event.

    Improve onTransition to include prior state, new state and event.

    To help with debugging I'm currently adding an onEnter and onExit method to each state.

    It would be much nice if this could be done globally.

    The GraphBuilder.onTransition listener seems an natural place to hook all transitions and log these events.

    The problem is that the Transition object that the listener passes has little information that is of use.

    Ideally the Transition object should contain:

    Prior state New state Event SideEffect.

    This would then allow it to be used for debug logging and reduce clutter in the state machine declaration.

    opened by bsutton 1
Owner
Kirill Bubochkin
Mobile/Web developer. Head of Applications at Mews.
Kirill Bubochkin
Drishti is an open-source cross-platform mobile application project at Incubate Nepal that incorporates Machine Learning and Artificial Intelligence

Drishti is an open-source cross-platform mobile application project at Incubate Nepal that incorporates Machine Learning and Artificial Intelligence to help visually impaired people recognize different currency bills and perform daily cash transactions more effectively. We plan to expand Drishti to other applications like Short Text and Document Reading in the future.

Drishti Nepal 23 Oct 8, 2022
Aplikasi Android konsultasi dokter dan vending machine

doctor_apps A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if t

Heri Nur Alim 1 Nov 11, 2021
Machine learning algorithms in Dart programming language

Machine learning algorithms for Dart developers What is the ml_algo for? The main purpose of the library is to give native Dart implementation of mach

Ilya Gyrdymov 134 Jan 4, 2023
A playground for me to learn the Riverpod state management library in Flutter.

clothes_shop A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if

Benhenneda Majid 2 Oct 25, 2021
A weather app with a minimalist design using the flutter_bloc library for state management.

weather_bloc_app_v2 A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you star

null 1 Jul 9, 2022
A flutter todo/task listing example app with advance state management using `Momentum` library.

A flutter todo/task listing example app with advanced state management using Momentum library. Simple on the outside but powerful in the inside. This

xamantra 17 Oct 11, 2022
Todo Flutter application with sqflite as a local database and bloc state management.

Todo App A Flutter application developed to add todo tasks and handles it I used Sqflite as a local database to store all the tasks I used flutter_sli

Muhhamed Sallam 14 Oct 17, 2022
Shopping app with riverpod state management

Shopify Shopify admin rest api demo project. We are try to use riverpod as state management to improve widget rebuilding performance. May be at some p

null 35 Nov 19, 2022
BMI Calculator Flutter App with State Management

BMI Calculator ?? Our Goal The objective of this tutorial is to look at how we can customise Flutter Widgets to achieve our own beautiful user interfa

Pawan Kumar 53 Dec 13, 2022
Weather App built in Flutter and Riverpod state management

?? Weather App built with Riverpod This is a weather app built using Riverpod as it's State Management. This project is an attempt to rewrite the Weat

Temitope Ajiboye 49 Dec 7, 2022