Loading calc.html +11 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,7 @@ </div> </div> <script type="text/javascript" src="vendor/jquery.min.js"></script> <script type="text/javascript" src="fsm.js"></script> <script type="text/javascript"> (function () { /** Loading @@ -129,6 +130,16 @@ // page init showDumbData(); console.assert(fsm.matchesSubstringAbb("123abb123") === true); console.assert(fsm.matchesSubstringAbb("123ab123") === true); console.assert(fsm.matchesSubstringAbb("123abaabb123") === true); console.assert(fsm.matchesSubstringAbb("123abbb123") === true); console.assert(fsm.matchesSubstringAbb("123ababab123") === false); console.assert(fsm.matchesSubstringAbb("") === false); console.assert(fsm.matchesSubstringAbb("123") === false); console.assert(fsm.matchesSubstringAbb("123ab") === false); console.assert(fsm.matchesSubstringAbb("123abb") === true); console.assert(fsm.matchesSubstringAbb("abb") === true); // setup event handler $('.keyboard td').click(function (evt) { Loading fsm.js 0 → 100644 +76 −0 Original line number Diff line number Diff line var fsm = function () { const debugging = false; const debug = function (msg) { if (debugging) { console.log(msg); } }; /** * a fsm that tries to match string "abb". see function * matchesSubstringAbb. */ const matchAbbMachine = function () { this.stateWaitForA = "wait for a"; this.stateWaitForFirstB = "wait for 1st b"; this.stateWaitForSecondB = "wait for 2nd b"; this.stateSucceed = "succeed"; this.currentState = "wait for a"; this.readch = function (ch) { switch (this.currentState) { case this.stateWaitForA: if (ch === 'a') { this.currentState = this.stateWaitForFirstB; } else { this.currentState = this.stateWaitForA; } break; case this.stateWaitForFirstB: if (ch === 'b') { this.currentState = this.stateWaitForSecondB; } else if (ch === 'a') { // do nothing, keep current state. } else { this.currentState = this.stateWaitForA; } break; case this.stateWaitForSecondB: if (ch === 'b') { this.currentState = this.stateSucceed; } else if (ch === 'a') { this.currentState = this.stateWaitForFirstB; } else { this.currentState = this.stateWaitForA; } break; case this.succeed: // do nothing, keep current state. break; } debug("readch " + ch + ", currentState is " + this.currentState); return this.currentState; }; }; /** * return true if given string has substring "abb" in it. * implemented using fsm. */ const matchesSubstringAbb = function (str) { var machine = new matchAbbMachine(); for (i = 0; i < str.length; ++i) { machine.readch(str[i]); if (machine.currentState === "succeed") { // console.log("matches"); return true; } } return false; }; return { matchesSubstringAbb: matchesSubstringAbb }; }(); operational +45 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,36 @@ the parent DOM. * current :entry: ** ** 2017-01-26 design data structure for the calculator. - this can be written and tested independently from the web UI. - basic data: - stack of numbers. - current state and data in finite state machine (fsm). - data for undo. I think I can just take a snapshot of the fsm. - how many states are there? init state is "waiting for number". | this state | event | next state | |------------------------------+---------------------------+--------------------------------------------------| | waiting | press num keys or dot key | modify number, then waiting for number or action | | waiting for number or action | press num keys or dot key | modify number, then waiting for number or action | | waiting for number or action | press return key | commit number, then waiting | | waiting for number or action | press +-*/ | commit number, do op, then waiting | | waiting for number or action | press < key | modify number, then waiting for number or action | There is no "ending state", the machine can always accept new keyboard events. - a few display and error handling. - when number is "0", press more num0 will just show error and not modify the number. - when number is "", press dot will change number to "0." - when number already has a dot in it, future dot will just show error and not modify the number. ** 2017-01-26 make basic number input and arithmetic work - DONE make event work. - TODO add some visual feedback when clicking a button. like in material design. Loading @@ -37,5 +67,20 @@ trail cache. it's not a problem. - make DUP and SWP work - make trail work * done :entry: ** 2017-01-26 how to write a fsm simulator in javascript. - try write an easier example before writing the real thing. - easy example: check whether a string has substring "abb". states: | this state | event | next state | |------------------+-----------------------+-----------------------------------------------------------------------------------------------| | wait for "a" | read new character ch | if ch is "a", wait for 1st "b"; otherwise, wait for "a" | | wait for 1st "b" | read new character ch | if ch is "b" => wait for 2nd "b"; if ch is "a" => wait for 1st "b"; otherwise => wait for "a" | | wait for 2nd "b" | read new character ch | if ch is "b" => succeed; if ch is "a" => wait for 1st "b"; otherwise => wait for "a" | | succeed | ∅ | ∅ | - it works. ** 2017-01-26 draw the keyboard using HTML and CSS * wontfix :entry: Loading
calc.html +11 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,7 @@ </div> </div> <script type="text/javascript" src="vendor/jquery.min.js"></script> <script type="text/javascript" src="fsm.js"></script> <script type="text/javascript"> (function () { /** Loading @@ -129,6 +130,16 @@ // page init showDumbData(); console.assert(fsm.matchesSubstringAbb("123abb123") === true); console.assert(fsm.matchesSubstringAbb("123ab123") === true); console.assert(fsm.matchesSubstringAbb("123abaabb123") === true); console.assert(fsm.matchesSubstringAbb("123abbb123") === true); console.assert(fsm.matchesSubstringAbb("123ababab123") === false); console.assert(fsm.matchesSubstringAbb("") === false); console.assert(fsm.matchesSubstringAbb("123") === false); console.assert(fsm.matchesSubstringAbb("123ab") === false); console.assert(fsm.matchesSubstringAbb("123abb") === true); console.assert(fsm.matchesSubstringAbb("abb") === true); // setup event handler $('.keyboard td').click(function (evt) { Loading
fsm.js 0 → 100644 +76 −0 Original line number Diff line number Diff line var fsm = function () { const debugging = false; const debug = function (msg) { if (debugging) { console.log(msg); } }; /** * a fsm that tries to match string "abb". see function * matchesSubstringAbb. */ const matchAbbMachine = function () { this.stateWaitForA = "wait for a"; this.stateWaitForFirstB = "wait for 1st b"; this.stateWaitForSecondB = "wait for 2nd b"; this.stateSucceed = "succeed"; this.currentState = "wait for a"; this.readch = function (ch) { switch (this.currentState) { case this.stateWaitForA: if (ch === 'a') { this.currentState = this.stateWaitForFirstB; } else { this.currentState = this.stateWaitForA; } break; case this.stateWaitForFirstB: if (ch === 'b') { this.currentState = this.stateWaitForSecondB; } else if (ch === 'a') { // do nothing, keep current state. } else { this.currentState = this.stateWaitForA; } break; case this.stateWaitForSecondB: if (ch === 'b') { this.currentState = this.stateSucceed; } else if (ch === 'a') { this.currentState = this.stateWaitForFirstB; } else { this.currentState = this.stateWaitForA; } break; case this.succeed: // do nothing, keep current state. break; } debug("readch " + ch + ", currentState is " + this.currentState); return this.currentState; }; }; /** * return true if given string has substring "abb" in it. * implemented using fsm. */ const matchesSubstringAbb = function (str) { var machine = new matchAbbMachine(); for (i = 0; i < str.length; ++i) { machine.readch(str[i]); if (machine.currentState === "succeed") { // console.log("matches"); return true; } } return false; }; return { matchesSubstringAbb: matchesSubstringAbb }; }();
operational +45 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,36 @@ the parent DOM. * current :entry: ** ** 2017-01-26 design data structure for the calculator. - this can be written and tested independently from the web UI. - basic data: - stack of numbers. - current state and data in finite state machine (fsm). - data for undo. I think I can just take a snapshot of the fsm. - how many states are there? init state is "waiting for number". | this state | event | next state | |------------------------------+---------------------------+--------------------------------------------------| | waiting | press num keys or dot key | modify number, then waiting for number or action | | waiting for number or action | press num keys or dot key | modify number, then waiting for number or action | | waiting for number or action | press return key | commit number, then waiting | | waiting for number or action | press +-*/ | commit number, do op, then waiting | | waiting for number or action | press < key | modify number, then waiting for number or action | There is no "ending state", the machine can always accept new keyboard events. - a few display and error handling. - when number is "0", press more num0 will just show error and not modify the number. - when number is "", press dot will change number to "0." - when number already has a dot in it, future dot will just show error and not modify the number. ** 2017-01-26 make basic number input and arithmetic work - DONE make event work. - TODO add some visual feedback when clicking a button. like in material design. Loading @@ -37,5 +67,20 @@ trail cache. it's not a problem. - make DUP and SWP work - make trail work * done :entry: ** 2017-01-26 how to write a fsm simulator in javascript. - try write an easier example before writing the real thing. - easy example: check whether a string has substring "abb". states: | this state | event | next state | |------------------+-----------------------+-----------------------------------------------------------------------------------------------| | wait for "a" | read new character ch | if ch is "a", wait for 1st "b"; otherwise, wait for "a" | | wait for 1st "b" | read new character ch | if ch is "b" => wait for 2nd "b"; if ch is "a" => wait for 1st "b"; otherwise => wait for "a" | | wait for 2nd "b" | read new character ch | if ch is "b" => succeed; if ch is "a" => wait for 1st "b"; otherwise => wait for "a" | | succeed | ∅ | ∅ | - it works. ** 2017-01-26 draw the keyboard using HTML and CSS * wontfix :entry: