Search code examples
javascriptstate-machine

Finite State Algorithm


In JavaScript I have drawn some states and trying to visualise a finite state machine. enter image description here But it seems not working as I expected. If I type in a B it moves to state s0, from there with a 'T' it goes to state s2 with a 'X' it's moving to state s3. So far so good. But if I am in state s3 and type in the value 'S' to move on to state s5 as it should be the console.log() is telling me the current state is s1. The same happens if I am in state s4 and want to type in the letter 'V' it's not moving to state s5 it's going up to state s3. I don't really see what I am doing wrong in my code. :(

const machine = {
        state: 'initialState',                                          // Initial state wait for input
        transitions: {
            initialState: {
                changeState: function(textfieldValue) {
                    if (textfieldValue.type === 'B') {
                        this.changeState('s0');                         // Update state
                        fillColors0();                                  // Call function fillColor
                        console.log('Current State: ' + this.state);
                    } else {
                        console.info(this.state);
                    }
                }
            },
            s0: {                                                       // State: s0
                changeState: function(textfieldValue) {
                    if (textfieldValue.type === 'P') {
                        this.changeState('s1');                         // Update state
                        fillColors1();                                  // Call function fillColor
                        console.log('Current State: ' + this.state);
                    } else if (textfieldValue.type === 'T') {
                        this.changeState('s2');                         // Update state
                        fillColors2();                                  // Call function fillColor
                        console.log('Current State: ' + this.state);
                    }
                }
            },
            s1: {                                                       // State: s1
                changeState: function(textfieldValue) {
                    if (textfieldValue.type === 'T') {
                        this.changeState('s1');                         // Update state
                        fillColors1();                                  // Call function fillColor
                        console.log('Current State: ' + this.state);
                    } else if (textfieldValue.type === 'V') {
                        this.changeState('s4');                         // Update state
                        fillColors4();                                  // Call function fillColor
                        console.log('Current State: ' + this.state);
                    }
                }
            },
            s2: {                                                       // State: s2
                changeState: function(textfieldValue) {
                    if (textfieldValue.type === 'S') {
                        this.changeState('s2');                         // Update state
                        fillColors2();                                  // Call function fillColor
                        console.log('Current State: ' + this.state);
                    } else if (textfieldValue.type === 'X') {
                        this.changeState('s3');                         // Update state
                        fillColors3();                                  // Call function fillColor
                        console.log('Current State: ' + this.state);
                    }
                }
            },
            s3: {                                                       // State: s3
                changeState: function(textfieldValue) {
                    if (textfieldValue.type === 'X') {
                        this.changeState('s1');                         // Update state
                        fillColors1();                                  // Call function fillColor
                        console.log('Current State: ' + this.state);
                    } else if (textfieldValue.type === 'S') {
                        this.changeState('s5');                         // Update state
                        fillColors5();                                  // Call function fillColor
                        console.log('Current State: ' + this.state);
                    }
                }
            },
            s4: {                                                       // State: s4
                changeState: function(textfieldValue) {
                    if (textfieldValue.type === 'P') {
                        this.changeState('s3');                         // Update state
                        fillColors3();                                  // Call function fillColor
                        console.log('Current State: ' + this.state);
                    } else if (textfieldValue.type === 'V') {
                        this.changeState('s5');                         // Update state
                        fillColors5();                                  // Call function fillColor
                        console.log('Current State: ' + this.state);
                    }
                }
            },
            s5: {                                                       // State: s5
                changeState: function(textfieldValue) {
                    if (textfieldValue.type === 'E') {
                        this.changeState('finiteState');                // Update state
                        fillColors6();                                  // Call function fillColor
                        console.log('Current State: ' + this.state);
                    }
                }
            },
        },
        dispatch(actionName, ...payload) {
            const action = this.transitions[this.state][actionName];

            if (action) {
                action.apply(machine, ...payload);
            } else {
                //action is not valid for current state
            }
        },
        changeState(newState) {
            this.state = newState;
        }
    };

    let currentState = Object.create(machine, {
        name: {
            writable: false,
            enumerable: true,
            value: "currentState"
        }
    });

    console.log('Current State: ' + currentState.state);

    $('#reberTextfield').keyup(function() {                             // Check value in textfield
        var value = $('#reberTextfield').val();                         // Read value from textfield
        $('#startBtn').on('click', function() {                         // Submit value if start button is clicked
            currentState.dispatch('changeState', [{ type: value }]);

            $('#reberTextfield').val('');                               // Clear input
        });
    });

Solution

  • It looks like, you get some old values to the input.

    $('#reberTextfield').keyup(function() { // Check value in textfield
        $('#startBtn').on('click', function() { // Submit value if start button is clicked
            var value = $('#reberTextfield').val(); // <<<<<<<<<<<<<<< move it here
            currentState.dispatch('changeState', [{ type: value }]);
    
            $('#reberTextfield').val(''); // Clear input
        });
    });