Foundations.Control.FSM

Implements a Finite State Machine (FSM) with "states" and "events". States are defined in an object and are transitioned to via events.

Using Foundations.Control.FSM

FSMs model behavior where responses to future events depend upon previous events. FSMs consist of:

FSMs are most useful in situations where many different types of events drive behavior, and the response to a particular event depends on the sequence of previous events.

States are a way to remember previous events, and transitions are a way to organize responses to future events.

FSMs are typically represented in one of two ways:

  1. Directed graphs -- Balloons represent states, and arrows between them represent transitions, which are labeled with events and actions.
  2. Two-dimensional tables -- Rows and columns represent events and states, and cells contain actions and transitions.

A full discussion of FSMs is beyond the scope of this documentation, but there are numerous resources available on the Internet.

Implementing a Finite State Machine

Typically, to implement a FSM, you would create a "states" object that defines states, events, and transition processing similar to the following:

var states = {
  stateOne: {
      eventOne: function() {
          // Do some processing and transition to another state
      },
      eventTwo: function() {
      }
  },
  stateTwo: {
      eventThree: function() {
      },
      eventFour: function() {
      }
  },
  // ....
};

Allocating a Finite State Machine

The following is a simple example of allocating a FSM:

// Load Foundation libraries
var libraries = MojoLoader.require({ name: "foundations", version: "1.0" });  

// Create reference to FSM code
var FSM = libraries["foundations"].FSM; 

// Create states, events, and transition processing object     
var states = {
  one: {
      gotoTwo: function() {
          // Event/Transition processing here...
          this.go("two");  // FSM method
      },
      gotoThree: function() {
          this.go("three");
      }
  },
  two: {
      gotoOne: function() {
          this.go("one");
      },
      gotoThree: function() {
          this.go("three");
      }
  },
  three: {
      gotoTwo: function() {
          this.go("two");
      },
      gotoOne: function() {
          this.go("one");
      }
  }
};
var context = {}; // some object

// Allocate FSM    
var fsm = new FSM(states, context); 

If no "context" is provided, then the states object is used as the context. If you only need one instance of a particular FSM, there is no reason for a separate context object.


FSM Methods


FSM.currentState

Get FSM's current state.

Syntax

FSM.currentState();

Parameters

None.

Returns

FSM current state.

Example

// Use example from "Allocating..."
var fsm = new FSM(states, context);

// Get initial state
Mojo.Log.info("fsm current state = "+ fsm.currentState());

Example Output

fsm current state = __uninitialized


FSM.event

Calls the named event method for the current state. This usually, but not always, results in a state transition.

Syntax

    boolean FSM.event(event, arguments);

Parameters

Argument Required Type Description
event Yes string Event to call.
arguments No any array Arguments to pass to event function.

Returns

true or false

Example

// Use example from "Allocating..."
fsm.go("three");   
Mojo.Log.info("fsm event gotoOne = "+ fsm.event("gotoOne"));   

Example Output

fsm event gotoOne = true


FSM.go

Transition from the current state to to the specified new state. Though used in the FSM implementation, calling this is not really necessary - in general, you would want to use an event to switch between states. If not already there, this method transitions the FSM to the named state.

Syntax

    FSM.go(nstate);

Parameters

Argument Required Type Description
nstate No any Name of state to transition to.

Returns

None.

Example

// Use example from "Allocating..."
fsm.go("two");
// Get new state
Mojo.Log.info("fsm current state = "+ fsm.currentState());

Example Output

fsm current state = two