All Projects → open-jumpco → kfsm

open-jumpco / kfsm

Licence: MIT license
Finite State Machine in Kotlin

Programming Languages

kotlin
9241 projects

Projects that are alternatives of or similar to kfsm

thelema-engine
Thelema - 3D graphics engine, written in Kotlin. Based on sources of libGDX.
Stars: ✭ 51 (-32.89%)
Mutual labels:  kotlin-js, kotlin-native, kotlin-multiplatform
KotlinMultiplatformAndoridParcelize
Use the Parcelize Annotation of the Kotlin Android Extensions in Kotin Multiplatform projects
Stars: ✭ 16 (-78.95%)
Mutual labels:  kotlin-js, kotlin-native, kotlin-multiplatform
tmdb-api
This Kotlin Multiplatform library is for accessing the TMDB API to get movie and TV show content. Using for Android, iOS, and JS projects.
Stars: ✭ 31 (-59.21%)
Mutual labels:  kotlin-js, kotlin-native, kotlin-multiplatform
KParser
Kotlin Multiplatform Arithmatic Parser
Stars: ✭ 32 (-57.89%)
Mutual labels:  kotlin-native, kotlin-multiplatform, kotlin-mpp
kotlin-multiplatform-example
A Kotlin multiplatform example app that targets Android, ReactJS, iOS, JavaFx, and Spring Boot
Stars: ✭ 115 (+51.32%)
Mutual labels:  kotlin-js, kotlin-native, kotlin-multiplatform
KMQTT
Embeddable and standalone Kotlin Multiplatform MQTT broker
Stars: ✭ 56 (-26.32%)
Mutual labels:  kotlin-native, kotlin-multiplatform
vjson
A simple JSON parser and (de)serializer library for java/kotlin and kotlin-native/js. Also provides a strongly-typed language: vjson-lang.
Stars: ✭ 31 (-59.21%)
Mutual labels:  kotlin-js, kotlin-native
MultiplatformPlayground
Kotlin Multiplatform project in Jetpack Compose & SwiftUI with shared ViewModel layer and File upload
Stars: ✭ 72 (-5.26%)
Mutual labels:  kotlin-native, kotlin-multiplatform
kinsight-multiplatform
Kotlin Multiplatform Concept - iOS, MacOS, WatchOS (SwiftUI), Android (phone and Wear OS), JVM Web Server - Alpha Capture
Stars: ✭ 38 (-50%)
Mutual labels:  kotlin-native, kotlin-multiplatform
hello-kotlin-multiplatform
Multiplatform Kotlin Hello World (Android/Java/JavaScript)
Stars: ✭ 64 (-15.79%)
Mutual labels:  kotlin-js, kotlin-multiplatform
CompleteKotlin
Gradle Plugin to enable auto-completion and symbol resolution for all Kotlin/Native platforms.
Stars: ✭ 236 (+210.53%)
Mutual labels:  kotlin-native, kotlin-multiplatform
moko-geo
Geolocation access for mobile (android & ios) Kotlin Multiplatform development
Stars: ✭ 41 (-46.05%)
Mutual labels:  kotlin-native, kotlin-multiplatform
Sheasy
This an Android App that helps you share/manage your files on your Android Device through a WebInterface in the Browser - Built with Ktor and Kotlin-React
Stars: ✭ 34 (-55.26%)
Mutual labels:  kotlin-js, kotlin-multiplatform
ktcc
C Compiler that generates readable Kotlin and C# - Written in Kotlin + Small web-based Editor with autocompletion
Stars: ✭ 54 (-28.95%)
Mutual labels:  kotlin-js, kotlin-native
mqtt
Kotlin cross-platform, coroutine based, reflectionless MQTT 3.1.1 & 5.0 client & server
Stars: ✭ 31 (-59.21%)
Mutual labels:  kotlin-js, kotlin-native
Splitties
A collection of hand-crafted extensions for your Kotlin projects.
Stars: ✭ 1,945 (+2459.21%)
Mutual labels:  kotlin-native, kotlin-multiplatform
cognito-idp
Lightweight AWS Cognito Identity Provider client for Kotlin Multiplatform and Typescript projects.
Stars: ✭ 14 (-81.58%)
Mutual labels:  kotlin-native, kotlin-multiplatform
TMDbMultiplatform
Step-by-step guide on Kotlin Multiplatform
Stars: ✭ 86 (+13.16%)
Mutual labels:  kotlin-native, kotlin-multiplatform
kmm-production-sample
This is an open-source, mobile, cross-platform application built with Kotlin Multiplatform Mobile. It's a simple RSS reader, and you can download it from the App Store and Google Play. It's been designed to demonstrate how KMM can be used in real production projects.
Stars: ✭ 1,476 (+1842.11%)
Mutual labels:  kotlin-native, kotlin-multiplatform
StarWars
Minimal GraphQL based Jetpack Compose, Wear Compose and SwiftUI Kotlin Multiplatform sample (using StarWars endpoint - https://graphql.org/swapi-graphql)
Stars: ✭ 165 (+117.11%)
Mutual labels:  kotlin-native, kotlin-multiplatform

Kotlin Finite-state machine

This work is licensed under Apache License 2.0

This is a small implementation of an FSM in Kotlin.

Getting Started

The state machine implementation supports events triggering transitions from one state to another while performing an optional action as well as entry and exit actions.

Features

  • Event driven state machine.

  • External and internal transitions

  • State entry and exit actions.

  • Default state actions.

  • Default entry and exit actions.

  • Determine allowed events.

  • Multiple state maps with push / pop transitions

  • Automatic transitions

  • Externalisation of state.

  • Typed event parameters and return values.

Todo

  • ✓ Multiple state maps

  • ✓ Push / pop transitions

  • ✓ Automatic transitions

  • ✓ Externalisation of state

  • ✓ Typed event parameters

  • ✓ Typed event return values

  • ✓ Simple Visualization

  • ✓ Detail Visualization

  • ✓ Gradle Plugin for Visualization

  • ✓ Timeouts

  • ✓ Corountines

  • ❏ Different type of contexts for Nested statemaps

Quick Tutorial

This is the classic turnstile FSM model from [SMC](http://smc.sourceforge.net/)

Simple turnstile example

Assume we and to manage the state on a simple lock. We want to ensure that the lock() function is only called when the lock is not locked and we want unlock() to be called when locked.

Then we use the DSL to declare a definition of a statemachine matching the diagram:

State Diagram

Turnstile state diagram

State Table

Start State Event End State Action

LOCKED

PASS

LOCKED

alarm

LOCKED

COIN

UNLOCKED

unlock

UNLOCKED

PASS

LOCKED

lock

UNLOCKED

COIN

UNLOCKED

returnCoin

Context class

class Turnstile(var locked: Boolean = true) {
    fun unlock() {
        assert(locked) { "Cannot unlock when not locked" }
        println("Unlock")
        locked = false
    }

    fun lock() {
        assert(!locked) { "Cannot lock when locked" }
        println("Lock")
        locked = true
    }

    fun alarm() {
        println("Alarm")
    }

    fun returnCoin() {
        println("Return coin")
    }
    override fun toString(): String {
        return "Turnstile(locked=$locked)"
    }
}

Enums for States and Events

We declare 2 enums, one for the possible states and one for the possible events.

enum class TurnstileStates {
    LOCKED,
    UNLOCKED
}

enum class TurnstileEvents {
    COIN,
    PASS
}

Packaged definition and execution

class TurnstileFSM(turnstile: Turnstile) {
    private val fsm = definition.create(turnstile)

    fun coin() = fsm.sendEvent(TurnstileEvents.COIN)
    fun pass() = fsm.sendEvent(TurnstileEvents.PASS)
    companion object {
        private val definition = stateMachine(
            TurnstileStates.values().toSet(),
            TurnstileEvents::class,
            Turnstile::class
        ) {
            initialState {
            if (locked)
                TurnstileStates.LOCKED
            else
                TurnstileStates.UNLOCKED
            }
            default {
                onEntry { startState, targetState, _ ->
                    println("entering:$startState -> $targetState for $this")
                }
                // default transition will invoke alarm
                action { state, event, _ ->
                    println("Default action for state($state) -> event($event) for $this")
                    alarm()
                }
                onExit { startState, targetState, _ ->
                    println("exiting:$startState -> $targetState for $this")
                }
            }
            // when current state is LOCKED
            whenState(TurnstileStates.LOCKED) {
                // external transition on COIN to UNLOCKED state
                onEvent(TurnstileEvents.COIN to TurnstileStates.UNLOCKED) {
                    unlock()
                }
            }
            // when current state is UNLOCKED
            whenState(TurnstileStates.UNLOCKED) {
                // internal transition on COIN
                onEvent(TurnstileEvents.COIN) {
                    returnCoin()
                }
                // external transition on PASS to LOCKED state
                onEvent(TurnstileEvents.PASS to TurnstileStates.LOCKED) {
                    lock()
                }
            }
        }.build()
    }
}

With this definition we are saying: When the state is LOCKED and on a COIN event then transition to UNLOCKED and execute the lambda which is treated as a member of the context { unlock() }

When the state is LOCKED and on event PASS we perform the action alarm() without changing the end state.

Usage

Then we instantiate the FSM and provide a context to operate on:

val turnstile = Turnstile()
val fsm = TurnstileFSM(turnstile)

Now we have a context that is independent of the FSM.

Sending events may invoke actions:

// State state is LOCKED
fsm.coin()
// Expect unlock action end state is UNLOCKED
fsm.pass()
// Expect lock() action and end state is LOCKED
fsm.pass()
// Expect alarm() action and end state is LOCKED
fsm.coin()
// Expect unlock() and end state is UNLOCKED
fsm.coin()
// Expect returnCoin() and end state is UNLOCKED

This model means the FSM can be instantiated as needed if the context has values that represent the state. The idea is that the context will properly maintain it’s internal state.

The FSM can derive the formal state from the value(s) of properties of the context.

The Documentation contains more detail on creating finite state machine implementations.

The documentation contains examples for:

Repository

Use this repository for SNAPSHOT builds. Releases are on Maven Central

repositories {
    maven {
        url 'https://oss.sonatype.org/content/groups/public'
    }
}

Dependencies

KMP Projects

The dependency used in common modules.

dependencies {
    implementation 'io.jumpco.open:kfsm:1.6.1'
}

JVM Projects

dependencies {
    implementation 'io.jumpco.open:kfsm-jvm:1.6.1'
}

KotlinJS Projects

dependencies {
    implementation 'io.jumpco.open:kfsm-js:1.6.1'
}

Kotlin/Native Projects using LinuxX64

dependencies {
    implementation 'io.jumpco.open:kfsm-linuxX64:1.6.1'
}

Kotlin/Native Projects using MinGW64

dependencies {
    implementation 'io.jumpco.open:kfsm-mingwX64:1.6.1'
}

Kotlin/Native Projects using macOS

dependencies {
    implementation 'io.jumpco.open:kfsm-macosX64:1.6.1'
}

Simple Visualisation

By using the StateMachineDefinition created by the DSL we do not have access to the details of guard expressions or actions.

For more detailed visualization use kfsm-io.jumpco.open.kfsm.viz

@Test
fun produceVisualizationTurnstileFSM() {
    println("== TurnStile")
    val visualization = visualize(TurnstileFSM.definition)
    File("generated", "turnstile.plantuml").writeText(plantUml(visualization))
}

Plantuml

Turnstile FSM

turnstile

Paying Turnstile FSM

paying turnstile

Secure Turnstile FSM

secure turnstile

Packer Reader FSM

packet reader

Questions:

  • Should entry / exit actions receive state or event as arguments?

  • Should default actions receive state or event as arguments?

  • Is there a more elegant way to define States and Events using sealed classes?

  • Are any features missing from the implementation?

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].