All Projects → bykof → Stateful

bykof / Stateful

Licence: mit
Finite state machine for Go

Programming Languages

go
31211 projects - #10 most used programming language
golang
3204 projects

Projects that are alternatives of or similar to Stateful

nodify
High performance and modular controls for node-based editors designed for data-binding and MVVM.
Stars: ✭ 282 (+63.95%)
Mutual labels:  state-machine, graph
Rosmaro
Visual automata-based programming in functional JavaScript
Stars: ✭ 176 (+2.33%)
Mutual labels:  graph, state-machine
Core
UI-Router Core: Framework agnostic, State-based routing for JavaScript Single Page Apps
Stars: ✭ 112 (-34.88%)
Mutual labels:  state-machine, transitions
kstatemachine
KStateMachine is a Kotlin DSL library for creating finite state machines (FSM) and hierarchical state machines (HSM).
Stars: ✭ 63 (-63.37%)
Mutual labels:  state-machine, transitions
Diagram Maker
A library to display an interactive editor for any graph-like data.
Stars: ✭ 2,086 (+1112.79%)
Mutual labels:  graph, state-machine
Alga Paper
A minimalistic, elegant and powerful approach to working with graphs in a functional programming language
Stars: ✭ 163 (-5.23%)
Mutual labels:  graph
Cargo Deps
Cargo subcommand for building dependency graphs of Rust projects
Stars: ✭ 168 (-2.33%)
Mutual labels:  graph
Neo4j 3d Force Graph
Experiments with Neo4j & 3d-force-graph https://github.com/vasturiano/3d-force-graph
Stars: ✭ 159 (-7.56%)
Mutual labels:  graph
Hgp Sl
Hierarchical Graph Pooling with Structure Learning
Stars: ✭ 159 (-7.56%)
Mutual labels:  graph
React Router Native Stack
A stack navigation component for react-router-native
Stars: ✭ 171 (-0.58%)
Mutual labels:  transitions
Relation Graph
Vue 关联关系图谱组件,可以展示如组织机构图谱、股权架构图谱、集团关系图谱等知识图谱,可提供多种图谱布局,包括树状布局、中心布局、力学布局自动布局等。Vue component for relationship graph , which can display knowledge graphs, such as organization graph, equity structure graph, group relationship graph,
Stars: ✭ 166 (-3.49%)
Mutual labels:  graph
Easy States
The simple, stupid state machine for Java
Stars: ✭ 167 (-2.91%)
Mutual labels:  state-machine
Animatedgraph
Animated Graph which you can include in your application to show information in more attractive way
Stars: ✭ 162 (-5.81%)
Mutual labels:  graph
Dragon
Dragon: A Computation Graph Virtual Machine Based Deep Learning Framework.
Stars: ✭ 168 (-2.33%)
Mutual labels:  graph
Awesome Graph Attack Papers
Adversarial attacks and defenses on Graph Neural Networks.
Stars: ✭ 162 (-5.81%)
Mutual labels:  graph
Libgrape Lite
🍇 A C++ library for parallel graph processing 🍇
Stars: ✭ 169 (-1.74%)
Mutual labels:  graph
Baklavajs
Graph / node editor in the browser using VueJS
Stars: ✭ 157 (-8.72%)
Mutual labels:  graph
Blocks.js
JavaScript dataflow graph editor
Stars: ✭ 165 (-4.07%)
Mutual labels:  graph
Awesome Gnn Recommendation
Graph Neural Network
Stars: ✭ 168 (-2.33%)
Mutual labels:  graph
Ui Motion
How to apply meaningful and delightful motion in a sample Android app
Stars: ✭ 165 (-4.07%)
Mutual labels:  transitions

Welcome to stateful 👋

Travis CI License: MIT

Twitter: michaelbykovski

Create easy state machines with your existing code

Table of Contents

  1. Documentation
  2. Usage
  3. Draw graph
  4. Wildcards
  5. Examples
  6. Credits

Documentation

You can find the documentation here: https://pkg.go.dev/github.com/bykof/stateful?tab=doc

Usage

It is very easy to use stateful. Just create a struct and implement the stateful interface

import "github.com/bykof/stateful"

type (
    MyMachine struct {
        state   stateful.State
        amount  int
    }
	
    AmountParams struct {
        Amount  int
    }
)

func NewMyMachine() MyMachine {
    return MyMachine{
        state:  A,
        amount: 0,
    }
}

// State implement interface stateful 
func (mm MyMachine) State() stateful.State {
    return mm.state
}

//  SetState implement interface stateful
func (mm *MyMachine) SetState(state stateful.State) error {
    mm.state = state
    return nil
}

Declare some proper states:

const (
    A = stateful.DefaultState("A")
    B = stateful.DefaultState("B")
)

Then add some transitions to the machine:

// Declare a transition of you machine and return the new state of the machine. 
func (mm *MyMachine) FromAToB(transitionArguments stateful.TransitionArguments) (stateful.State, error) {
    amountParams, ok := transitionArguments.(AmountParams)
    if !ok {
        return nil, errors.New("could not parse AmountParams")
    }
	
    mm.amount += amountParams.Amount
    return B, nil
} 

func (mm *MyMachine) FromBToA(transitionArguments stateful.TransitionArguments) (stateful.State, error) {
    amountParams, ok := transitionArguments.(AmountParams)
    if !ok {
        return nil, errors.New("could not parse AmountParams")
    }
	
    mm.amount -= amountParams.Amount
    return A, nil
}

// The state machine will check, if you transfer to a proper and defined state in the machine. See below. 
func (mm *MyMachine) FromAToNotExistingC(_ stateful.TransitionArguments) (stateful.State, error) {
	return stateful.DefaultState("C")
}

And now initialize the machine:

myMachine := NewMyMachine()
stateMachine := &stateful.StateMachine{
    StatefulObject: &myMachine,
}

stateMachine.AddTransition(
    // The transition function 
    myMachine.FromAToB,
    // SourceStates
    stateful.States{A},
    // DestinationStates
    stateful.States{B},
)

stateMachine.AddTransition(
    myMachine.FromBToA,
    stateful.States{B},
    stateful.States{A},
)

Everything is done! Now run the machine:

_ := stateMachine.Run(
    // The transition function
    myMachine.FromAToB, 
    // The transition params which will be passed to the transition function
    stateful.TransitionArguments(AmountParams{Amount: 1}),
)

_ = stateMachine.Run(
    myMachine.FromBToA, 
    stateful.TransitionArguments(AmountParams{Amount: 1}),
)

err := stateMachine.Run(
   myMachine.FromBToA, 
   stateful.TransitionArguments(AmountParams{Amount: 1}),
)

// We cannot run the transition "FromBToA" from current state "A"... 
if err != nil {
    log.Fatal(err) // will print: you cannot run FromAToB from state A
}

// We cannot transfer the machine with current transition to returned state "C"
err = stateMachine.Run(
    myMachine.FromAToNotExistingC, 
    stateful.TransitionArguments(nil),
)

if err != nil {
    log.Fatal(err) // will print: you cannot transfer to state C 
}

That's it!

Draw graph

You can draw a graph of your state machine in dot format of graphviz.

Just pass in your created statemachine into the StateMachineGraph.

import "github.com/bykof/stateful/src/statefulGraph"
stateMachineGraph := statefulGraph.StateMachineGraph{StateMachine: *stateMachine}
_ = stateMachineGraph.DrawGraph()

This will print following to the console:

digraph  {
	A->B[ label="FromAToB" ];
	B->A[ label="FromBToA" ];
	A;
	B;
	
}

which is actually this graph:

MyMachine Transition Graph

Wildcards

You can also address wildcards as SourceStates or DestinationStates

stateMachine.AddTransition(
    myMachine.FromBToAllStates,
    stateful.States{B},
    stateful.States{stateful.AllStates},
)

This will give you the opportunity to jump e.g. B to AllStates.

Keep in mind that AllStates creates a lot of complexity and maybe a missbehavior. So use it only if you are knowing what you are doing

Examples

Have a look at the examples: examples

Credits

Thank you calhoun for the sweet gopher image!

Run tests

go test ./...

Author

👤 Michael Bykovski

Show your support

Give a ⭐️ if this project helped you!

📝 License

Copyright © 2019 Michael Bykovski.
This project is MIT licensed.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].