Loading calc.html +30 −0 Original line number Diff line number Diff line Loading @@ -216,6 +216,34 @@ console.assert(m.numberStack[0] === -9); console.assert(m.numberStack[1] === 29 * 2); }; const rpnTestNumberErrorHandling = function () { var m = new fsm.RPNCalculator(); m.sendKey("num0"); m.sendKey("num0"); console.assert(m.currentNumber === "0"); m = new fsm.RPNCalculator(); m.sendKey("dot"); console.assert(m.currentNumber === "0."); m.sendKey("backspace"); console.assert(m.currentNumber === "0"); m.sendKey("backspace"); console.assert(m.currentNumber === ""); m = new fsm.RPNCalculator(); m.sendKey("num1"); m.sendKey("dot"); m.sendKey("num2"); console.assert(m.currentNumber === "1.2"); m.sendKey("dot"); // future dot is ignored and show error. console.assert(m.currentNumber === "1.2"); m.sendKey("num3"); console.assert(m.currentNumber === "1.23"); m.sendKey("dot"); console.assert(m.currentNumber === "1.23"); m.sendKey("return"); console.assert(m.numberStack[0] === 1.23); }; /** * run all tests. Loading @@ -236,6 +264,8 @@ rpnTestNumberHandling(); rpnTestAutoCommitNumber(); rpnTestOperator(); rpnTestNumberErrorHandling(); }; // page init Loading fsm.js +66 −5 Original line number Diff line number Diff line Loading @@ -169,14 +169,66 @@ var fsm = function () { return keyName.substring(3); } }; /** * press keyName when existing number string is oldNumberString. * return [newNumberString, errMsg] * errMsg will be null if there is no error. */ const changeNumberString = function (keyName, oldNumberString) { if (oldNumberString === "0" && keyName === keyNames.num0) { return [oldNumberString, "more 0s are ignored"]; } else if (oldNumberString === "" && keyName === keyNames.dot) { return ["0.", null]; } else if (keyName === keyNames.dot && oldNumberString.indexOf(".") !== -1) { // Note: do not use indexOf(keyNames.dot) in if condition, // because the keyName is dot, not ".". return [oldNumberString, "more dots are ignored"]; } else { return [oldNumberString + numKeyToNumString(keyName), null]; } }; const testChangeNumberString = function () { var r = changeNumberString(keyNames.dot, ""); console.assert(r[0] === "0."); console.assert(r[1] === null); r = changeNumberString(keyNames.num1, ""); console.assert(r[0] === "1"); console.assert(r[1] === null); r = changeNumberString(keyNames.num1, "2"); console.assert(r[0] === "21"); console.assert(r[1] === null); r = changeNumberString(keyNames.num0, "0"); console.assert(r[0] === "0"); console.assert(r[1] !== null); r = changeNumberString(keyNames.num0, "12"); console.assert(r[0] === "120"); console.assert(r[1] === null); r = changeNumberString(keyNames.dot, "1.2"); console.assert(r[0] === "1.2"); console.assert(r[1] !== null); }; this.sendKey = function (keyName) { var num, num1, num2; var numString, errMsg; var r; switch (this.currentState) { case stateIdle: if (isNumberKey(keyName)) { // TODO handle errors and special cases this.currentNumber += numKeyToNumString(keyName); r = changeNumberString(keyName, this.currentNumber); numString = r[0]; errMsg = r[1]; if (errMsg === null) { this.currentNumber = numString; } else { this.setErrorMsg(errMsg); } // change state this.currentState = stateWaitingForNumberOrAction; } else { switch (keyName) { Loading Loading @@ -218,8 +270,14 @@ var fsm = function () { break; case stateWaitingForNumberOrAction: if (isNumberKey(keyName)) { // TODO handle errors and special cases this.currentNumber += numKeyToNumString(keyName); r = changeNumberString(keyName, this.currentNumber); numString = r[0]; errMsg = r[1]; if (errMsg === null) { this.currentNumber = numString; } else { this.setErrorMsg(errMsg); } // keep current state } else if (keyName === keyNames['return']) { this.numberStack.push(parseFloat(this.currentNumber)); Loading @@ -229,7 +287,7 @@ var fsm = function () { if (this.currentNumber.length > 0) { this.currentNumber = this.currentNumber.substring(0, this.currentNumber.length - 1); } else { setErrorMsg("no digits to delete"); this.setErrorMsg("no digits to delete"); } } else if (isOperator(keyName)) { // commit number Loading @@ -253,6 +311,9 @@ var fsm = function () { debug("sendKey " + keyName + ", currentState is " + this.currentState); return this.currentState; }; // run all tests; testChangeNumberString(); }; return { Loading Loading
calc.html +30 −0 Original line number Diff line number Diff line Loading @@ -216,6 +216,34 @@ console.assert(m.numberStack[0] === -9); console.assert(m.numberStack[1] === 29 * 2); }; const rpnTestNumberErrorHandling = function () { var m = new fsm.RPNCalculator(); m.sendKey("num0"); m.sendKey("num0"); console.assert(m.currentNumber === "0"); m = new fsm.RPNCalculator(); m.sendKey("dot"); console.assert(m.currentNumber === "0."); m.sendKey("backspace"); console.assert(m.currentNumber === "0"); m.sendKey("backspace"); console.assert(m.currentNumber === ""); m = new fsm.RPNCalculator(); m.sendKey("num1"); m.sendKey("dot"); m.sendKey("num2"); console.assert(m.currentNumber === "1.2"); m.sendKey("dot"); // future dot is ignored and show error. console.assert(m.currentNumber === "1.2"); m.sendKey("num3"); console.assert(m.currentNumber === "1.23"); m.sendKey("dot"); console.assert(m.currentNumber === "1.23"); m.sendKey("return"); console.assert(m.numberStack[0] === 1.23); }; /** * run all tests. Loading @@ -236,6 +264,8 @@ rpnTestNumberHandling(); rpnTestAutoCommitNumber(); rpnTestOperator(); rpnTestNumberErrorHandling(); }; // page init Loading
fsm.js +66 −5 Original line number Diff line number Diff line Loading @@ -169,14 +169,66 @@ var fsm = function () { return keyName.substring(3); } }; /** * press keyName when existing number string is oldNumberString. * return [newNumberString, errMsg] * errMsg will be null if there is no error. */ const changeNumberString = function (keyName, oldNumberString) { if (oldNumberString === "0" && keyName === keyNames.num0) { return [oldNumberString, "more 0s are ignored"]; } else if (oldNumberString === "" && keyName === keyNames.dot) { return ["0.", null]; } else if (keyName === keyNames.dot && oldNumberString.indexOf(".") !== -1) { // Note: do not use indexOf(keyNames.dot) in if condition, // because the keyName is dot, not ".". return [oldNumberString, "more dots are ignored"]; } else { return [oldNumberString + numKeyToNumString(keyName), null]; } }; const testChangeNumberString = function () { var r = changeNumberString(keyNames.dot, ""); console.assert(r[0] === "0."); console.assert(r[1] === null); r = changeNumberString(keyNames.num1, ""); console.assert(r[0] === "1"); console.assert(r[1] === null); r = changeNumberString(keyNames.num1, "2"); console.assert(r[0] === "21"); console.assert(r[1] === null); r = changeNumberString(keyNames.num0, "0"); console.assert(r[0] === "0"); console.assert(r[1] !== null); r = changeNumberString(keyNames.num0, "12"); console.assert(r[0] === "120"); console.assert(r[1] === null); r = changeNumberString(keyNames.dot, "1.2"); console.assert(r[0] === "1.2"); console.assert(r[1] !== null); }; this.sendKey = function (keyName) { var num, num1, num2; var numString, errMsg; var r; switch (this.currentState) { case stateIdle: if (isNumberKey(keyName)) { // TODO handle errors and special cases this.currentNumber += numKeyToNumString(keyName); r = changeNumberString(keyName, this.currentNumber); numString = r[0]; errMsg = r[1]; if (errMsg === null) { this.currentNumber = numString; } else { this.setErrorMsg(errMsg); } // change state this.currentState = stateWaitingForNumberOrAction; } else { switch (keyName) { Loading Loading @@ -218,8 +270,14 @@ var fsm = function () { break; case stateWaitingForNumberOrAction: if (isNumberKey(keyName)) { // TODO handle errors and special cases this.currentNumber += numKeyToNumString(keyName); r = changeNumberString(keyName, this.currentNumber); numString = r[0]; errMsg = r[1]; if (errMsg === null) { this.currentNumber = numString; } else { this.setErrorMsg(errMsg); } // keep current state } else if (keyName === keyNames['return']) { this.numberStack.push(parseFloat(this.currentNumber)); Loading @@ -229,7 +287,7 @@ var fsm = function () { if (this.currentNumber.length > 0) { this.currentNumber = this.currentNumber.substring(0, this.currentNumber.length - 1); } else { setErrorMsg("no digits to delete"); this.setErrorMsg("no digits to delete"); } } else if (isOperator(keyName)) { // commit number Loading @@ -253,6 +311,9 @@ var fsm = function () { debug("sendKey " + keyName + ", currentState is " + this.currentState); return this.currentState; }; // run all tests; testChangeNumberString(); }; return { Loading