File: development/js/utils/fsm.js
import objects from './object';
/**
* Implementation of a simple finite state machine class
*
* @module Utils
* @class Utils.FSM
* @static
*/
var isNewState = (xs, x) => xs.every((s) => s.name !== x.name);
/**
* Creates a Finite State Machine with addState(), removeState(), getState()
* and consume() methods
*
* @method FSM
* @for Utils.FSM
* @return {object} Finite State Machine (FSM)
*
* @example
* import FSM from './utils/fsm';
*
* var fsm = FSM().
* addState({name: 'first', events: {next: 'second'}}).
* addState({name: 'second', events: {next: 'third', previous: 'first'}}).
* addState({name: 'third', events: {previous: 'second'}});
*
* fsm.getState();
* // -> 'first'
*
* fsm.consume('next').getState();
* // -> 'second'
*
* fsm.consume('next').getState();
* // -> 'third'
*
* fsm.consume('next').getState();
* // -> 'third', since third has no next event
*
*/
const FSM = function () {
var states = [],
cur;
return {
addState(state) {
if (isNewState(states, state)) {
states.push(state);
if (cur == null) {
cur = state;
}
}
return this;
},
removeState(state) {
if (!isNewState(states, state)) {
states = states.filter((s) => s.name !== state.name);
if (cur === state) {
cur = null;
}
return this;
}
},
consume(eventName) {
if (cur != null && objects.has(eventName, cur.events)) {
states.forEach((s) => {
if (s.name === cur.events[eventName]) {
cur = s;
}
});
}
return this;
},
getState() {
return cur ? cur.name : null;
},
destroyStates() {
states = null;
cur = null;
}
};
}
export default FSM;