• Stars
    star
    328
  • Rank 128,352 (Top 3 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 7 years ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Fast, easy Javascript finite state machines with visualizations; enjoy a one liner FSM instead of pages. MIT; Typescripted; 100% test coverage. Implements the FSL language.

jssm 5.89.1

Easy. Small. Fast. TS, es6, es5. Node, Browser. 100% coverage. Property tests. Fuzz tests. Language tests for a dozen languages and emoji. Easy to share online. Easy to embed.

Readable, useful state machines as one-liner strings.

4,923 tests run 5,814 times. 4,914 specs with 100.0% coverage, 9 fuzz tests with 13.2% coverage. With 2,828 lines, that's about 1.7 tests per line, or {{line_run_ratio}} generated tests per line.

Meet your new state machine library.

TRY THE LIVE EDITOR

Discord community - Documentation - Issue tracker - CI build history

Discord community



Wouldn't it be nice if your TypeScript and Javascript state machines were simple and readable one-liners?

import { sm } from 'jssm';

const TrafficLight = sm`Red -> Green -> Yellow -> Red;`;

Wouldn't it be great if they were easy to work with?

const log = s => console.log(s);

log( TrafficLight.state() );  // 'Red'

Machine.transition('Green');  // true
log( TrafficLight.state() );  // 'Green'

What if the notation supported action names easily?

const TLWA = sm`Red 'next' -> Green 'next' -> Yellow 'next' -> Red;`;  // TLWA = Traffic Light With Actions

log( TLWA.state() );  // 'Red'

TLWA.action('next');  // true
log( TLWA.state() );  // 'Green'

TLWA.action('next');  // true
log( TLWA.state() );  // 'Yellow'

TLWA.action('next');  // true
log( TLWA.state() );  // 'Red'

What if integration with the outside was straightforward?

const MTL = sm`Red 'next' -> Green 'next' -> Yellow 'next' -> Red;`  // MTL = More Traffic Lights
              .hook('Red', 'Green', () => log('GO GO GO') )          // node will jump the gun when you hit return, though
              .hook_entry('Red', () => log('STOP') );                // so put it on one line in node

log( MTL.state() );  // 'Red'

TLWA.action('next');  // true, console logs 'GO GO GO'
log( TLWA.state() );  // 'Green'

TLWA.action('next');  // true
log( TLWA.state() );  // 'Yellow'

TLWA.action('next');  // true, console logs 'STOP'
log( TLWA.state() );  // 'Red'

What if the machine followed JS standards, and distinguished refusals as false from mistakes as thrown?

const ATL = sm`Red -> Green -> Yellow -> Red;`;  // ATL = Another Traffic Light

log( ATL.state() );         // 'Red' - uses 1st state unless told otherwise
ATL.transition('Yellow');   // false (Yellow isn't allowed from Red)
ATL.transition('Blue');     // throws (Blue isn't a state at all)

What if there were easy convenience notations for lists, and for designating main-path => vs available path -> vs only-when-forced ~> ?

const TrafficLightWithOff = sm`
  Red => Green => Yellow => Red;
  [Red Yellow Green] ~> Off -> Red;
`;

What if that were easy to render visually?

const TrafficLightWithOff = sm`
  Red => Green => Yellow => Red;
  [Red Yellow Green] ~> Off -> Red;
`;


What if that were easy to render visually, with styling, in PNG, JPEG, or SVG?

const TrafficLightWithOff = sm`
  Red => Green => Yellow => Red;
  [Red Yellow Green] ~> Off -> Red;

  flow: left;

  state Red    : { background-color: pink;        corners: rounded; };
  state Yellow : { background-color: lightyellow; corners: rounded; };
  state Green  : { background-color: lightgreen;  corners: rounded; };

  state Off : {
    background-color : steelblue;
    text-color       : white;
    shape            : octagon;
    linestyle        : dashed;
  };
`;


What if the machine was lighting fast, able to do tens of millions of transitions per second?


  • What if the machine and language had extensive 100% test coverage with thousands of cases?
  • What if the machine gave extensive Typescript introspection support?
  • What if the machine had been around and active since May 2017?
  • What if the machine was MIT licensed, end to end?

But, above all else:

What if it was easy?



Introducing JSSM

Meet JSSM: the Javascript State Machine.

State machines can make your code cleaner, safer, and more trustworthy.

And, with the right language, state machines can be easy and fun.

TRY THE LIVE EDITOR


What is JSSM?

JSSM is a Javascript state machine implementing Finite State Language, with a terse DSL and a simple API. 100% test coverage; typed with Flowtype. MIT licensed.

The NPM package includes pure es6, a cjs es5 bundle, and .d.ts typings. The repository includes the original typescript, the bundle, the es6, documentation, tests, tutorials, and so on.

Try it live!

Visualize with jssm-viz, or at the command line with jssm-viz-cli.

Language test cases for Belorussian, English, German, Hebrew, Italian, Russian, Spanish, Ukrainian, and Emoji. Please help to make sure that your language is well handled!

Actions Status

GitHub forks GitHub watchers GitHub stars GitHub followers

License Open issues Closed issues Travis status Coveralls status

NPM version CDNjs version NPM downloads



TL;DR

Specify finite state machines with a brief syntax. Run them; they're fast. Make mistakes; they're strict. Derive charts. Save and load states, and histories. Make machine factories to churn out dozens or thousands of instances. Impress friends and loved ones. Cure corns and callouses.

Red 'Proceed' -> Green 'Proceed' -> Yellow 'Proceed' -> Red;

This will produce the following FSM (graphed with jssm-viz):

You'll build an executable state machine.



Why

As usual, a valid question.


Why state machines

State machines are a method of making your software better able to prevent illegal states. Similar to type systems, SQL constraints, and linters, state machines are a way to teach the software to catch mistakes in ways you define, to help lead to better software.

The major mechanism of a state machine is to define states, the transitions between them, and sometimes associated data and other niceties. The minor mechanism of state machines is to attach actions to the transitions, such that the state machine can partially run itself.

So, to look at the same traffic light as above, you'll notice some things.

  1. A sufficiently smart implementation will know that it's okay for Green to switch to Yellow, but not to Red
  2. A sufficiently smart implementation knows there's no such thing as Blue
  3. A sufficiently smart implementation knows that when in Green, to be told to Proceed means to go to Yellow, but when in Yellow, it means to go to Red instead

Along with other common sense things, a good state machine implementation can help eliminate large classes of error in software. State machines are often applied when the stakes on having things correct are high.


Why this implementation

Brevity.

High quality testing. JSSM has 100% coverage, and has partial stochastic test coverage.

Feature parity, especially around the DSL and data control.

Data integrity. JSSM allows a much stricter form of state machine than is common, with a relatively low performance and storage overhead. It also offers an extremely terse domain specific language (though it does not require said DSL) to produce state machines in otherwise comparatively tiny and easily read code.



Quick Start

A state machine in JSSM is defined in one of two ways: through the DSL, or through a datastructure.

So yeah, let's start by getting some terminology out of the way, and then we can go right back to that impenetrable sentence, so that it'll make sense.


Quick Terminology

Finite state machines have been around forever, are used by everyone, and are hugely important. As a result, the terminology is a mess, is in conflict, and is very poorly chosen, in accordince with everything-is-horrible law.

This section describes the terminology as used by this library. The author has done his best to choose a terminology that matches common use and will be familiar to most. Conflicts are explained in the following section, to keep this simple.

For this quick overview, we'll define six basic concepts:

  1. Finite state machines
  2. Machines
  3. States
  4. Current state
  5. Transitions
  6. Actions

There's other stuff, of course, but these five are enough to wrap your head around finite state machines.


Basic concepts

This is a trivial traffic light FSM, with three states, three transitions, and one action:

Red 'Proceed' -> Green 'Proceed' -> Yellow 'Proceed' -> Red;

Let's review its pieces.

  • finite state machines

    • A finite state machine (or FSM) is a collection of states, and rules about how you can transition between the states.
    • We tend to refer to a design for a machine as "an FSM."
    • In this example, the traffic light's structure is "a traffic light FSM."
  • states

    • FSMs always have at least one state, and nearly always many states
    • In this example,
      • the states are Red, Yellow, and Green
      • Something made from this FSM will only ever be one of those colors - not, say, Blue
  • machines

    • Single instances of an FSM are referred to as a machine
    • We might have a thousand instances of the traffic light designed above
    • We would say "My intersection has four machines of the standard three color light FSM."
  • current state

    • A machine has a current state, though an FSM does not
      • "This specific traffic light is currently Red"
    • Traffic lights in general do not have a current color, only specific lights
    • FSMs do not have a current state, only specific machines
    • A given machine will always have exactly one state - never multiple, never none
  • transitions

    • FSMs nearly always have transitions
    • Transitions govern whether a state may be reached from another state
      • This restriction is much of the value of FSMs
    • In this example,
      • the transitions are
        • Green → Yellow
        • Yellow → Red
        • Red → Green
      • a machine whose current state is Green may switch to Yellow, because there is an appropriate transition
      • a machine whose current state is Green may not switch to Red, or to Green anew, because there is no such transition
        • A machine in Yellow which is told to transition to Green (which isn't legal) will know to refuse
        • This makes FSMs an effective tool for error prevention
  • actions

    • Many FSMs have actions, which represent events from the outside world.
    • In this example, there is only one action - Proceed
      • The action Proceed is available from all three colors
    • At any time we may indicate to this light to go to its next color, without taking the time to know what it is.
      • This allows FSMs like the light to self-manage.
      • A machine in Yellow which is told to take the action Proceed will know on its own to switch its current state to Red.
      • This makes FSMs an effective tool for complexity reduction

Those six ideas in hand - FSMs, states, machines, current state, transitions, and actions - and you're ready to move forwards.

One other quick definition - a DSL, or domain specific language, is when someone makes a language and embeds it into a different language, for the purpose of attacking a specific job. When React uses a precompiler to embed stuff that looks like HTML in Javascript, that's a DSL.

This library implements a simple language for defining finite state machines inside of strings. For example, this DSL defines that 'a -> b;' actually means "create two states, create a transition between them, assign the first as the initial state", et cetera. That micro-language is the DSL that we'll be referring to a lot, coming up. This DSL's parser's original name was jssm-dot, because it's a descendant-in-spirit of an older flowcharting language DOT, from graphviz, which is also used to make the visualizations in jssm-viz by way of viz-js.

Enough history lesson. On with the tooling.


And now, that Quick Start we were talking about

So let's put together a trivial four-state traffic light: the three colors, plus Off. This will give us an opportunity to go over the basic facilities in the language.

At any time, you can take the code and put it into the graph explorer for an opportunity to mess with the code as you see fit.


0: Lights always have an off state

Our light will start in the Off state, with the ability to switch to the Red state.

Since that's a normal, not-notable thing, we'll just make it a regular -> legal transition.

Off -> Red;

We will give that transition an action, and call it TurnOn.

Off 'TurnOn' -> Red;

So far, our machine is simple:


1: Traffic lights have a three-color cycle

The main path of a traffic light is cycling from Green to Yellow, then to Red, then back again. Because this is the main path, we'll mark these steps => main transitions.

Off 'TurnOn' -> Red => Green => Yellow => Red;

We will give those all the same action name, Proceed, indicating "next color" without needing to know what we're currently on.

Off 'TurnOn' -> Red 'Proceed' => Green 'Proceed' => Yellow 'Proceed' => Red;

Machine's still pretty simple:


2: Traffic lights can be shut down

We'd also like to be able to turn this light back off. Because that's expected to be a rarity, we'll require that it be a ~> forced transition.

We could write

Off 'TurnOn' -> Red 'Proceed' => Green 'Proceed' => Yellow 'Proceed' => Red;
Red ~> Off;
Yellow ~> Off;
Green ~> Off;

But that takes a lot of space even with this short list, so, instead we'll use the array notation

Off 'TurnOn' -> Red 'Proceed' => Green 'Proceed' => Yellow 'Proceed' => Red;
[Red Yellow Green] ~> Off;

And we'd like those all to have the action TurnOff, so

Off 'TurnOn' -> Red 'Proceed' => Green 'Proceed' => Yellow 'Proceed' => Red;
[Red Yellow Green] 'TurnOff' ~> Off;

Machine's still not too bad:


Let's actually use the traffic light

That's actually the bulk of the language. There are other little add-ons here and there, but, primarily you now know how to write a state machine.

Let's load it and use it! 😀

loading into node

loading into html

jssm-viz

redistribution on npm


An introduction to machine design

Let's make a state machine for ATMs. In the process, we will use a lot of core concepts of finite state machines and of fsl, this library's DSL.

We're going to improve on this NCSU ATM diagram that I found:

Remember, at any time, you can take the code and put it into the graph explorer for an opportunity to mess with the code as you see fit.


0: Empty machine

We'll start with an empty machine.

EmptyWaiting 'Wait' -> EmptyWaiting;


1: Should be able to eject cards

We'll add the ability to physically eject the user's card and reset to the empty and waiting state. Right now it'll dangle around un-used at the top, but later it'll become useful.

This is expressed as the path EjectCardAndReset -> EmptyWaiting;

EmptyWaiting 'Wait' -> EmptyWaiting;
EjectCardAndReset -> EmptyWaiting;


2: Should be able to insert cards

We'll add the ability to physically insert a card, next. You know, the, uh, thing ATMs are pretty much for.

To get this, add the path leg EmptyWaiting 'InsertCard' -> HasCardNoAuth;

EmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;
EjectCardAndReset -> EmptyWaiting;

Notice that the new state, HasCardNoAuth, has been rendered red. This is because it is terminal - there is no exit from this node currently. (EmptyAndWaiting did not render that way because it had a transition to itself.) That will change as we go back to adding more nodes. terminal nodes are usually either mistakes or the last single state of a given FSM.


3: Should be able to cancel and recover the card

Next, we should have a cancel, because the ATM's 7 key is broken, and we need our card back. Cancel will exit to the main menu, and return our card credential.

To that end, we add the path HasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;

EmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;

HasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;

EjectCardAndReset -> EmptyWaiting;


4: Can give the wrong PIN

Next, let's give the ability to get the password ... wrong. 😂 Because we all know that one ATM that only has the wrong-PIN path, so, apparently that's a product to someone.

When they get the PIN wrong, they're prompted to try again (or to cancel.)

We'll add the path HasCardNoAuth 'WrongPIN' -> HasCardNoAuth;

EmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;

HasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;
HasCardNoAuth 'WrongPIN' -> HasCardNoAuth;

EjectCardAndReset -> EmptyWaiting;


5: Can give the correct PIN

Next, let's give the ability to get the password right.

We'll add two paths. The first gets the password right: HasCardNoAuth 'RightPIN' -> MainMenu;

The second, from our new state MainMenu, gives people the ability to leave: MainMenu 'ExitReturnCard' -> EjectCardAndReset;

EmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;

HasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;
HasCardNoAuth 'WrongPIN' -> HasCardNoAuth;
HasCardNoAuth 'RightPIN' -> MainMenu;

MainMenu 'ExitReturnCard' -> EjectCardAndReset;

EjectCardAndReset -> EmptyWaiting;


6: Can check balance from main menu

Hooray, now we're getting somewhere.

Let's add the ability to check your balance. First pick that from the main menu, then pick which account to see the balance of, then you're shown a screen with the information you requested; then go back to the main menu.

That's MainMenu 'CheckBalance' -> PickAccount -> DisplayBalance -> MainMenu;.

EmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;

HasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;
HasCardNoAuth 'WrongPIN' -> HasCardNoAuth;
HasCardNoAuth 'RightPIN' -> MainMenu;

MainMenu 'ExitReturnCard' -> EjectCardAndReset;
MainMenu 'CheckBalance' -> PickAccount -> DisplayBalance -> MainMenu;

EjectCardAndReset -> EmptyWaiting;


7: Can deposit money from main menu

Let's add something difficult. Their state machine just proceeds assuming everything is okay.

To desposit money:

  1. Accept physical money
  2. If accept failed (eg door jammed,) reject physical object, go to main menu
  3. If accept succeeded, ask human expected value
  4. Pick an account this should go into
  5. Contact bank. Request to credit for theoretical physical money.
  6. Three results: yes, no, offer-after-audit.
  7. If no, reject physical object, go to main menu.
  8. If yes, consume physical object, tell user consumed, go to main menu
  9. If offer-after-audit, ask human what to do
  10. if human-yes, consume physical object, tell user consumed, go to main menu
  11. if human-no, reject physical object, go to main menu

Writing this out in code is not only generally longer than the text form, but also error prone and hard to maintain.

... or there's the FSM DSL, which is usually as-brief-as the text, and frequently both briefer and more explicit.

  • Rules 1-2: MainMenu 'AcceptDeposit' -> TentativeAcceptMoney 'AcceptFail' -> RejectPhysicalMoney -> MainMenu;
  • Rules 3-6: TentativeAcceptMoney 'AcceptSucceed' -> PickDepositAccount -> RequestValue 'TellBank' -> BankResponse;
  • Rule 7: BankResponse 'BankNo' -> RejectPhysicalMoney;
  • Rule 8: BankResponse 'BankYes' -> ConsumeMoney -> NotifyConsumed -> MainMenu;
  • Rules 9-10: BankResponse 'BankAudit' -> BankAuditOffer 'HumanAcceptAudit' -> ConsumeMoney;
  • Rule 11: BankAuditOffer 'HumanRejectAudit' -> RejectPhysicalMoney;

Or, as a block,

MainMenu 'AcceptDeposit' -> TentativeAcceptMoney;

TentativeAcceptMoney 'AcceptFail' -> RejectPhysicalMoney -> MainMenu;
TentativeAcceptMoney 'AcceptSucceed' -> PickDepositAccount -> RequestValue 'TellBank' -> BankResponse;

BankResponse 'BankNo'    -> RejectPhysicalMoney;
BankResponse 'BankYes'   -> ConsumeMoney -> NotifyConsumed -> MainMenu;
BankResponse 'BankAudit' -> BankAuditOffer 'HumanAcceptAudit' -> ConsumeMoney;

BankAuditOffer 'HumanRejectAudit' -> RejectPhysicalMoney;

Which leaves us with the total code

EmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;

HasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;
HasCardNoAuth 'WrongPIN' -> HasCardNoAuth;
HasCardNoAuth 'RightPIN' -> MainMenu;

MainMenu 'AcceptDeposit'  -> TentativeAcceptMoney;
MainMenu 'ExitReturnCard' -> EjectCardAndReset;
MainMenu 'CheckBalance'   -> PickCheckBalanceAccount -> DisplayBalance -> MainMenu;

TentativeAcceptMoney 'AcceptFail'    -> RejectPhysicalMoney -> MainMenu;
TentativeAcceptMoney 'AcceptSucceed' -> PickDepositAccount -> RequestValue 'TellBank' -> BankResponse;

BankResponse 'BankNo'    -> RejectPhysicalMoney;
BankResponse 'BankYes'   -> ConsumeMoney -> NotifyConsumed -> MainMenu;
BankResponse 'BankAudit' -> BankAuditOffer 'HumanAcceptAudit' -> ConsumeMoney;

BankAuditOffer 'HumanRejectAudit' -> RejectPhysicalMoney;

EjectCardAndReset -> EmptyWaiting;


8: Can withdraw money from main menu

Let's also be able to take money from the machine. After this, we'll move on, since our example is pretty squarely made by now.

  1. Pick a withdrawl account, or cancel to the main menu
  2. Shown a balance, pick a withdrawl amount, or cancel to acct picker
  3. Is the withdrawl account too high? If so go to 2
  4. Does the machine actually have the money? If not go to 2
  5. Otherwise confirm intent w/ human
  6. Attempt to post the transaction.
  7. If fail, display reason and go to 1
  8. If succeed, dispense money and go to main menu
  • Rules 1-3: MainMenu -> PickWithdrawlAccount -> PickAmount -> AcctHasMoney? 'TooHighForAcct' -> PickWithdrawlAccount;
  • Rule 4: AcctHasMoney? -> MachineHasMoney? 'MachineLowOnCash' -> PickAmount;
  • Rule 5: MachineHasMoney? -> ConfirmWithdrawWithHuman 'MakeChanges' -> PickWithdrawlAmount;
  • Rule 6: ConfirmWithdrawWithHuman 'PostWithdrawl' -> BankWithdrawlResponse;
  • Rule 7: BankWithdrawlResponse 'WithdrawlFailure' -> WithdrawlFailureExplanation -> PickWithdrawlAccount;
  • Rule 8: BankWithdrawlResponse 'WithdrawlSuccess' -> DispenseMoney -> MainMenu;

Rule 1 canceller: PickWithdrawlAccount 'CancelWithdrawl' -> MainMenu; Rule 2 canceller: PickWithdrawlAmount 'SwitchAccounts' -> PickWithdrawlAccount;

Or as a whole, we're adding

MainMenu -> PickWithdrawlAccount -> PickAmount -> AcctHasMoney? 'TooHighForAcct' -> PickWithdrawlAccount;
AcctHasMoney? -> MachineHasMoney? 'MachineLowOnCash' -> PickAmount;
MachineHasMoney? -> ConfirmWithdrawWithHuman 'MakeChanges' -> PickWithdrawlAmount;
ConfirmWithdrawWithHuman 'PostWithdrawl' -> BankWithdrawlResponse;
BankWithdrawlResponse 'WithdrawlFailure' -> WithdrawlFailureExplanation -> PickWithdrawlAccount;
BankWithdrawlResponse 'WithdrawlSuccess' -> DispenseMoney -> MainMenu;

PickWithdrawlAccount 'CancelWithdrawl' -> MainMenu;
PickWithdrawlAmount 'SwitchAccounts' -> PickWithdrawlAccount;

Which leaves us with

EmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;

HasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;
HasCardNoAuth 'WrongPIN' -> HasCardNoAuth;
HasCardNoAuth 'RightPIN' -> MainMenu;

MainMenu 'AcceptDeposit'  -> TentativeAcceptMoney;
MainMenu 'ExitReturnCard' -> EjectCardAndReset;
MainMenu 'CheckBalance'   -> PickCheckBalanceAccount -> DisplayBalance -> MainMenu;

TentativeAcceptMoney 'AcceptFail'    -> RejectPhysicalMoney -> MainMenu;
TentativeAcceptMoney 'AcceptSucceed' -> PickDepositAccount -> RequestValue 'TellBank' -> BankResponse;

BankResponse 'BankNo'    -> RejectPhysicalMoney;
BankResponse 'BankYes'   -> ConsumeMoney -> NotifyConsumed -> MainMenu;
BankResponse 'BankAudit' -> BankAuditOffer 'HumanAcceptAudit' -> ConsumeMoney;

BankAuditOffer 'HumanRejectAudit' -> RejectPhysicalMoney;

MainMenu -> PickWithdrawlAccount -> PickAmount -> AcctHasMoney? 'TooHighForAcct' -> PickWithdrawlAccount;
AcctHasMoney? -> MachineHasMoney? 'MachineLowOnCash' -> PickAmount;
MachineHasMoney? -> ConfirmWithdrawWithHuman 'MakeChanges' -> PickWithdrawlAmount;
ConfirmWithdrawWithHuman 'PostWithdrawl' -> BankWithdrawlResponse;
BankWithdrawlResponse 'WithdrawlFailure' -> WithdrawlFailureExplanation -> PickWithdrawlAccount;
BankWithdrawlResponse 'WithdrawlSuccess' -> DispenseMoney -> MainMenu;

PickWithdrawlAccount 'CancelWithdrawl' -> MainMenu;
PickWithdrawlAmount 'SwitchAccounts' -> PickWithdrawlAccount;

EjectCardAndReset -> EmptyWaiting;

As you can see, building up even very complex state machines is actually relatively straightforward, in a short amount of time.



Features

DSL

States

Transitions

Cycles

Stripes

Named Ordered Lists

Atoms

Strings

Arrow types

Unicode representations

Node declarations

All the styling bullshit

Named edges

URL callouts

The 9 or whatever directives

How to publish a machine

Legal, main, and forced

Validators

State history

Automatic visualization



How to think in state machines



Example Machines

Door lock

Traffic lights

Basic three-state

RYG, Off, Flash-red, Flash-yellow

RYG, Off, Flash-red, Flash-yellow, Green-left, Yellow-left

Heirarchal intersection

ATM

HTTP

Better HTTP

TCP

Coin-op vending machine (data)

Video games

Pac-man Ghost (sensors)

Weather (probabilistics)

Roguelike monster (interface satisfaction)

Candy crush clone game flow (practical large use)

Vegas locked 21 dealer behavior

React SPA website (practical large use)

BGP

LibGCrypt FIPS mode FSM



How to debug



How to publish

It's really quite simple.

  1. Make a github repository.
  2. Put your code in a file inside, with the extension .fsl
  3. Make sure your code contains a machine_name

Once done, your work should show up here.



Notation Comparison

Their notations, one by one

Apples to Apples - Traffic Light



Other state machines

There are a lot of state machine impls for JS, many quite a bit more mature than this one. Here are some options:

  1. Finity 😮
  2. Stately.js
  3. machina.js
  4. Pastafarian
  5. Henderson
  6. fsm-as-promised
  7. state-machine
  8. mood
  9. FSM Workbench
  10. SimpleStateMachine
  11. shime/micro-machine
    1. soveran/micromachine (ruby)
  12. fabiospampinato/FSM
  13. HQarroum/FSM
  14. Finite-State-Automata
  15. finite-state-machine
  16. nfm

And some similar stuff:

  1. redux-machine
  2. ember-fsm
  3. State machine cat
  4. Workty 😮
  5. sam-simpler
  6. event_chain
  7. DRAKON
  8. Yakindu Statechart Tools
  9. GraphViz
    1. Viz.js, which we use




Thanks

JSSM and FSL have had a lot of help.



Internationalization

If I've overlooked you, please let me know.

If you'd like to help, it's straightforward.

  1. Easy mode: open a PR with this file translated into your language
  2. Extra mile: create a new repo containing this file translated



Code and Language

Vat Raghavan has participated extensively in language discussion and implemented several features.

Forest Belton has provided guidance, bugfixes, parser and language commentary.

Jordan Harbrand suggested two interesting features and provided strong feedback on the initial tutorial draft.

The biggest thanks must go to Michael Morgan, who has debated significant sections of the notation, invented several concepts and operators, helped with the parser, with system nomenclature, for having published the first not-by-me FSL machine, for encouragement, and generally just for having been as interested as he has been.

More Repositories

1

flocks.js

A radically simpler alternative to Flux - opinionated React state and rendering management
JavaScript
73
star
2

preact_ie7

Yes. Someone I know needs IE7 in 2019 and wants React. (dramatic lightning; thunder)
JavaScript
64
star
3

rogue_demo

A simple build of a roguelike in JS
HTML
21
star
4

canvolver

Man I was bored, so I created a low quality canvas polygon evolver
JavaScript
19
star
5

jssm-viz

Visualization of JSSM machines using viz.js
TypeScript
16
star
6

circular_buffer_js

Fast TS/JS implementation of a circular buffer (aka ring queue, cyclic list, etc.) Extremely well tested.
TypeScript
15
star
7

htstub

The HtStub erlang webserver
Erlang
14
star
8

scutil.github.com

John Haugeland's ScUtil utility library. Docs at http://scutil.com/docs/sc.html .
Erlang
12
star
9

oxford_3000

The Oxford English Dictionary's basic three thousand words, as a JSON
9
star
10

fsl

Finite State Language specification
9
star
11

todo_redux_to_not

Let's remove Redux from the Redux todo example 😂
8
star
12

flocks.rocks

The flocks.rocks promotional website for Flocks.JS
CSS
7
star
13

fslp

Finite State Language reference parser
JavaScript
6
star
14

jssm-viz-demo

Show how to use jssm-viz in a project, to render a jssm machine
JavaScript
6
star
15

husl_harmony

Use the HUSL library to generate more effective color harmonies
JavaScript
6
star
16

four_color.js

Four coloring of a graph, for Javascript
JavaScript
5
star
17

smokinjs

This thing rips
JavaScript
5
star
18

flocks-mini-todo

A tiny todo example of flocks.js for react.js
JavaScript
4
star
19

keyscan

Simple keyboard scanning
JavaScript
4
star
20

sctags

New tag components for x-tags/polymer
JavaScript
4
star
21

servehere

Serve from the local directory immediately
JavaScript
4
star
22

testdata-valid-email

A list of valid, frequently ugly email addresses for use in automated testing
JavaScript
4
star
23

fsl-pegjs

FSL grammar in PEG.js
3
star
24

DeepakChopra_Opal

Deepak Chopra nonsense phrase generator implementation in Opal
Opal
3
star
25

csv_by_rfc

High quality CSV encoding and decoding, according to RFC 4180. Well tested, documented, and typescripted.
TypeScript
3
star
26

sublime-apl

SublimeText highlighter (and TextMate I think?) for "A Programming Language" (APL)
3
star
27

crap.js

Complete React Application Platform for JS - crap.js
JavaScript
3
star
28

sc_nps

Net Promoter Score implementation in Erlang. MIT licensed.
Erlang
3
star
29

DeepakChopra_Julia

Deepak Chopra nonsense generator in Julia
Julia
3
star
30

demo_gulp_build

demo gulp build of react, es6, less
JavaScript
3
star
31

PhoneNumberRules

Rules on how to parse phone numbers automatically, by nation. Not language specific, but ships with examples.
3
star
32

crap_json

A crap JSON dumper for Erlang. Takes some liberties. Well tested and documented. MIT license.
Erlang
3
star
33

erlurl

Because I needed to stochastically test URL parsing. And the name was pithy.
Erlang
3
star
34

DeepakChopra_JavaScript

Deepak Chopra nonsense phrase generator implementation in JavaScript
JavaScript
3
star
35

twilierl

Twilierl is a Twilio client for erlang.
Erlang
3
star
36

hsluv.ts

Nevermind. The project's author doesn't want this
TypeScript
2
star
37

imbecile

Defiant generative testing for Javascript
2
star
38

nodelike

A node based roguelike
JavaScript
2
star
39

ReverseLodestone

Lodestones are for compasses to find things. Reverse lodestone is to help you find (and maybe remove) SASS Compass.
JavaScript
2
star
40

simple_s3_cloudfront_gulp_site

This is how to make an S3 backed, cloudfront fronted site in gulp
2
star
41

fsl_80211_csma_ca

FSL implementation of the 802.11 CSMA/CA state path
2
star
42

derp

Computers are great at doing stupid things. Serve your sites at the speed of derp.
CSS
2
star
43

fslc

Finite State Language reference compiler
2
star
44

quicknote

a quick note-taking tool for isaac
JavaScript
2
star
45

DeepakChopra_Bash

Deepak Chopra nonsense phrase generator implementation in Bash script
Shell
2
star
46

sc_cls

Implementation of Hunt, Marin, and Stone's CLS (Concept Learning System) decision tree builder 🌲
Erlang
2
star
47

gulp-strip-react-dom-comment

Strips the /** @jsx React.DOM */ from pipes to support tools that can't handle the comment
JavaScript
2
star
48

chessboard_html

A simple chess board in HTML. Used to show how to work with CSS transitions as "animations."
HTML
2
star
49

sc-eslint

A small wrapper of eslint, pre-configured to StoneCypher's preferences
JavaScript
2
star
50

sc_react_d3

D3.js charts wrapped up as React.js controls for much less struggleful chart dev
JavaScript
2
star
51

is_a_ts

Typescript implementation of generic type guard, inherited from work by Ran Lottem
TypeScript
2
star
52

UnderstandingReactiveProgramming

Understanding Reactive Programming
HTML
2
star
53

i18nFormattingNotes

Formatting notes and expectations for various languages.
2
star
54

soundtrack.js

Make handling the soundtracks to your HTML5/JS games somewhat easier. ES6/JS2015 with CommonJS bindings.
JavaScript
2
star
55

StoneCypher

General public things
2
star
56

DeepakChopra_Perl

Deepak Chopra nonsense phrase generator implementation in Perl
Perl
2
star
57

unreasonable_phi

The phi placer (one-, two-, three-, and n-dimensional) from The Unreasonable Effectiveness of Quasirandom Sequences
TypeScript
2
star
58

Docker_image_security_checklist

Let's make a checklist of things you're supposed to do
2
star
59

sc_erl_datasets

Various datasets that my other erlang garbage uses, because repeatability :rage2:
Erlang
2
star
60

ReactJsNewsTut

A simple tutorial for React JS News
JavaScript
2
star
61

sc_spintax

Simple implementation of "spintax," a text generation mechanism often abused for text farms and spam
Erlang
2
star
62

vorcoder

Voronoi image encoder in JS
JavaScript
2
star
63

stochpen_html

stochpen_html is a stochastic penetration library for html (generates attempts to hax0r your sox0rs; little bobby tables and etc)
2
star
64

node-validate-email

There are a lot of email validators out there; let's raise the bar a bit on quality. MIT licensed.
JavaScript
2
star
65

learn_tspeg

learning how to get typescript and peg to play together
TypeScript
1
star
66

sc_i18n_react

Simple internationalization controls for react.js ; largely a wrapper of sc_18n. MIT licensed.
1
star
67

sc_id3

Implementation of Ross Quinlan's ID3 (Iterative Dichotomizer 3) decision tree builder 🌲
Erlang
1
star
68

sc_os_monitor

Simple OS monitoring for machines with top in Erlang clusters
CSS
1
star
69

sc_bandit

Bandit algorithms for Erlang. MIT licensed.
1
star
70

haacker_news

Cliff Haack's new site template
1
star
71

sge.js

Southgate Engine - a simple roguelike engine for console, built in Node
1
star
72

fsl-lezer

Lezer grammar for making FSL available to CodeMirror 6
JavaScript
1
star
73

fsllang.com

Website for the FSL language
1
star
74

pbar

tiny progress bar widget in css3 and js es6 / js2015
JavaScript
1
star
75

sc_list

An erlang library full of list and string related functions.
Erlang
1
star
76

DeepakChopra_Fortran

Deepak Chopra nonsense generator implementation in Fortran-90
Fortran
1
star
77

unival

Unified validator for Javascript and Node. Wraps other peoples' validators. Stochastic and shootout selected.
1
star
78

checkers_mate

More generators for glenjamin's checkers.js
JavaScript
1
star
79

compass_rose

A simple, limited pure-SASS shim to ease getting out of Compass - because a Compass by any other name still smells as sweet
CSS
1
star
80

cldr_parser

Parse the CLDR into something tolerable. Erlang tested; your mother approved.
CSS
1
star
81

demo_es6_module

This is a demonstration of a simple nested es6 module structure
1
star
82

hexceed

erlang module implementing the rules to a silly little boardgame in my head
1
star
83

forest_belton

Forest Belton nonsense phrase generator implementation in Haskell
Haskell
1
star
84

fine_ill_learn_haskell_already

jesus christ, every time i sneeze, someone's telling me it's just an eigen co-swallow
Haskell
1
star
85

fsl_traffic_light

FSL 4-state Traffic Light. Used as a model for translation
1
star
86

randomness

Random number, sequence, and other randomization tools for JS, written for readable clarity
1
star
87

sublime-jssm

Sublime highlighter for JSSM files
1
star
88

short_offer

Write a shortened offer claim for WebRTC. Byte-safe. Typescript pair of peg parsers.
JavaScript
1
star
89

nnif1

Stonecypher's Neural Network Interconnect Function 1
C++
1
star
90

text_audit

quickly audit a directory tree for text samples, producing a build-appropriate colored table
JavaScript
1
star
91

Security_Checklist

A thing to remind us what to check, both at creation and periodically. Template repo. Clone me and check me.
1
star
92

DeepakChopra_Haskell

Deepak Chopra nonsense phrase generator implementation in Haskell
Haskell
1
star
93

markhov_redditor

A simple markhov trainer to create a bot using a redditor's comment history as source data
1
star
94

DeepakChopra_Lua

Deepak Chopra nonsense phrase generator implementation in Lua
Lua
1
star
95

es6_bio

es6 biotech library routines
JavaScript
1
star
96

i1

Internationalization tools for Javascript, exposed through a convenient template string tag
1
star
97

sc_pubsub

A trivial pub/sub service for Erlang
Erlang
1
star
98

sc_cssutil

My CSS utilities. Mostly classes that handle generic behavior.
CSS
1
star
99

Tower-of-Babble

Tech talk on Babel.js, ES6, and our better builds
1
star
100

bracket_gviz

Simple bracket drawing for graphviz for 16 players in single elimination. MIT License.
Graphviz (DOT)
1
star