diffusion
Version:
Diffusion JavaScript client
100 lines (99 loc) • 3.31 kB
JavaScript
;
/**
* @module Util.FSM
*
* @brief A miniman finite state machine
*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.FSM = void 0;
var emitter_1 = require("./../events/emitter");
var stream_1 = require("./../events/stream");
/**
* Minimal finite state machine implementation. Allows directed transitions
* between states.
*
* States are provided as an object, with each key being single distinct state.
* Each state's value within the object should be an array of strings, which
* dictates the available states that are legal to transition to.
*
* If a state may transition to any other state, the string `'*'`
* may be provided instead of an array.
*
* If a state is terminal, it should simply provide an empty array.
*
* **Example:**
* ```
* // Create a state machine with three states:
* // 'a' may transition to 'b' or 'c'
* // 'b' is a terminal state
* // 'c' may transition to any state
*
* var states = {
* a : ['b', 'c'],
* b : [],
* c : '*'
* };
*
* var fsm = new FSM('a', states);
*
* states.change('c'); // => true
* states.change('a'); // => true
* states.change('b'); // => true
* states.change('c'); // => false
* states.change('a'); // => false
* ```
*/
var FSM = /** @class */ (function (_super) {
__extends(FSM, _super);
/**
* Create a new finite state machine
*
* @param initial the initial state that this FSM should be in
* @param states the set of possible states to transition between
*/
function FSM(initial, states) {
var _this = this;
var factory = emitter_1.Emitter.create();
_this = _super.call(this, factory) || this;
_this.emitter = factory.emitter(_this);
_this.states = states;
_this.current = states[initial];
_this.state = initial;
return _this;
}
/**
* Change the state. Will return whether the transition was allowed or not.
*
* @param state the new state
* @return `true` is the change of state was successful
*/
FSM.prototype.change = function (state) {
if (this.state === state) {
return true;
}
if (this.states[state] && (this.current === '*' || this.current.indexOf(state) > -1)) {
this.emitter.emit('change', this.state, state);
this.current = this.states[state];
this.state = state;
return true;
}
return false;
};
return FSM;
}(stream_1.StreamImpl));
exports.FSM = FSM;