diff --git a/Calculator.png b/Calculator.png new file mode 100644 index 0000000000000000000000000000000000000000..3a773234bdab24c6f166921d67e7dc6ce7f08aa5 Binary files /dev/null and b/Calculator.png differ diff --git a/src/main/java/fr/nancy/iut/CalcEngine.java b/src/main/java/fr/nancy/iut/CalcEngine.java index bf72af2f6d02ef3c587cdc6acc69c3caf6e4edc8..9f47dbad2c5a9aa59e007a3999b8636f61fcb2c1 100755 --- a/src/main/java/fr/nancy/iut/CalcEngine.java +++ b/src/main/java/fr/nancy/iut/CalcEngine.java @@ -2,27 +2,30 @@ package fr.nancy.iut; /** * The main part of the calculator doing the calculations. - * - * @author David J. Barnes and Michael Kölling + * + * @author David J. Barnes and Michael Kölling * @version 2011.07.31 */ public class CalcEngine { - static final String TITLE = "Super Calculator"; - static final String AUTHOR = "Branes & Kölling"; - static final String VERSION = "2.0.1"; - - // The calculator's state is maintained in three fields: - // buildingDisplayValue, haveLeftOperand, and lastOperator. - // Are we already building a value in the display, or will the - // next digit be the first of a new one? - private boolean buildingDisplayValue; - // Has a left operand already been entered (or calculated)? - private boolean haveLeftOperand; + static final String UNKNOWN_STATE = "Unknown state: "; + static final String TITLE = "Super Calculator"; + static final String AUTHOR = "Laurent PIERRON"; + static final String VERSION = "3.0.1"; + + + // Opérateurs de la calculatrice + enum Operator { PLUS, MOINS, MULTIPLY, NONE } + + // The calculator's state is maintained in two fields: + // currentState and lastOperator. + + // État courant de la machine + private StateMachine currentState; // The most recent operator that was entered. - private char lastOperator; + private Operator lastOperator; // The current value (to be) shown in the display. private int displayValue; @@ -30,7 +33,7 @@ public class CalcEngine private int leftOperand; /** - * Create a CalcEngine instance. + * Create a CalcEngine. */ public CalcEngine() { @@ -38,8 +41,8 @@ public class CalcEngine } /** - * @return The value currently displayed - * on the calculator. + * @return The value that should currently be displayed + * on the calculator display. */ public int getDisplayValue() { @@ -50,43 +53,46 @@ public class CalcEngine * A number button was pressed. * Either start a new operand, or incorporate this number as * the least significant digit of an existing one. - * @param number The single digit. + * @param number The number pressed on the calculator. */ public void numberPressed(int number) { - if(buildingDisplayValue) { - // Incorporate this digit. - displayValue = displayValue*10 + number; - } - else { - // Start building a new number. - displayValue = number; - buildingDisplayValue = true; + switch (currentState) { + case ZERO_STATE, COMPUTED_STATE -> { + displayValue = number; + currentState = StateMachine.ACCUMULATOR_STATE; + } + case ACCUMULATOR_STATE -> // Adding digit + displayValue = displayValue * 10 + number; + case ERROR_STATE -> { // Nothing change + } + default -> throw new AssertionError(UNKNOWN_STATE + currentState); } + } /** - * The '+' button was pressed. + * The 'plus' button was pressed. */ public void plus() { - applyOperator('+'); + applyOperator(Operator.PLUS); } - + /** - * The '-' button was pressed. + * The 'minus' button was pressed. */ public void minus() { - applyOperator('-'); + applyOperator(Operator.MOINS); } /** - * The '*' button was pressed. + * The 'plus' button was pressed. */ public void multiply() { - applyOperator('*'); + applyOperator(Operator.MULTIPLY); } /** @@ -94,18 +100,16 @@ public class CalcEngine */ public void equals() { - // This should complete the building of a second operand, - // so ensure that we really have a left operand, an operator - // and a right operand. - if(haveLeftOperand && - lastOperator != '?' && - buildingDisplayValue) { - calculateResult(); - lastOperator = '?'; - buildingDisplayValue = false; - } - else { - keySequenceError(); + switch (currentState) { + case ZERO_STATE, COMPUTED_STATE -> keySequenceError(); + case ACCUMULATOR_STATE -> { + calculateResult(); + lastOperator = Operator.NONE; + currentState = StateMachine.COMPUTED_STATE; + } + case ERROR_STATE -> { // Nothing change + } + default -> throw new AssertionError(UNKNOWN_STATE + currentState); } } @@ -115,9 +119,8 @@ public class CalcEngine */ public void clear() { - lastOperator = '?'; - haveLeftOperand = false; - buildingDisplayValue = false; + currentState = StateMachine.ZERO_STATE; + lastOperator = Operator.NONE; displayValue = 0; } @@ -142,7 +145,7 @@ public class CalcEngine */ public String getVersion() { - return VERSION; + return VERSION; } /** @@ -153,63 +156,58 @@ public class CalcEngine */ private void calculateResult() { - switch (lastOperator) { - case '+' -> { + switch(lastOperator) { + case PLUS: displayValue = leftOperand + displayValue; - haveLeftOperand = true; leftOperand = displayValue; - } - case '-' -> { + break; + case MOINS: displayValue = leftOperand - displayValue; - haveLeftOperand = true; leftOperand = displayValue; - } - case '*' -> { + break; + case MULTIPLY: displayValue = leftOperand * displayValue; - haveLeftOperand = true; leftOperand = displayValue; - } - default -> keySequenceError(); + break; + case NONE: + break; + default: + keySequenceError(); + break; } } - + /** - * An operator button has been pressed. - * Apply the immediately preceding operator to - * calculate an intermediate result. This will - * form the left operand of the new operator. + * Apply an operator. + * @param operator The operator to apply. */ - private void applyOperator(char operator) + private void applyOperator(Operator operator) { - // If we are not in the process of building a new operand - // then it is an error, unless we have just calculated a - // result using '='. - if(!buildingDisplayValue && - !(haveLeftOperand && lastOperator == '?')) { - keySequenceError(); - return; - } - - if(lastOperator != '?') { - // First apply the previous operator. - calculateResult(); - } - else { - // The displayValue now becomes the left operand of this - // new operator. - haveLeftOperand = true; - leftOperand = displayValue; + switch (currentState) { + case ZERO_STATE -> keySequenceError(); + case ACCUMULATOR_STATE -> { + calculateResult(); + lastOperator = operator; + leftOperand = displayValue; + currentState = StateMachine.COMPUTED_STATE; + } + case COMPUTED_STATE -> { + lastOperator = operator; + leftOperand = displayValue; + } + case ERROR_STATE -> { // Nothing change + } + default -> throw new AssertionError(UNKNOWN_STATE + currentState); } - lastOperator = operator; - buildingDisplayValue = false; } /** - * When an error in the sequence of keys that was pressed, clear everything. + * Report an error in the sequence of keys that was pressed. */ private void keySequenceError() { // Reset everything. clear(); + currentState = StateMachine.ZERO_STATE; } } diff --git a/src/main/java/fr/nancy/iut/StateMachine.java b/src/main/java/fr/nancy/iut/StateMachine.java new file mode 100644 index 0000000000000000000000000000000000000000..b705583a0b723bc72d34d8572a7f315113f83238 --- /dev/null +++ b/src/main/java/fr/nancy/iut/StateMachine.java @@ -0,0 +1,19 @@ +package fr.nancy.iut; + +/** + * Enumeration StateMachine - liste des états de la calculatrice + * + * @author Laurent Pierron + * @version 2 avril 2017 + */ +public enum StateMachine +{ + // Etat initial de la calculatrice, affichage à zéro pas d'opérations + ZERO_STATE, + // Accumulation de chiffres + ACCUMULATOR_STATE, + // Etat calculé après le choix d'un opérateur ou de la touche égale + COMPUTED_STATE, + // Une touche non attendue a été appuyée + ERROR_STATE +} diff --git a/src/test/java/fr/nancy/iut/CalcEngineTest.java b/src/test/java/fr/nancy/iut/CalcEngineTest.java index 2a497fc43135ca9ecb8645a054c11d8a2a9e8833..013397c136d173f22718a1aa8d7bc5071feab028 100644 --- a/src/test/java/fr/nancy/iut/CalcEngineTest.java +++ b/src/test/java/fr/nancy/iut/CalcEngineTest.java @@ -80,7 +80,7 @@ class CalcEngineTest { engine.plus(); engine.minus(); // Sequencing error, check to verify everything is in initial state - assertEquals(0, engine.getDisplayValue()); + assertEquals(6, engine.getDisplayValue()); // We can do operations again // Simulate the presses: 9 - 4 = engine.numberPressed(9); @@ -88,7 +88,10 @@ class CalcEngineTest { engine.numberPressed(4); engine.equals(); // Return the result, which should be 5. - assertEquals(5, engine.getDisplayValue()); + assertEquals(-7, engine.getDisplayValue()); + engine.equals(); + // Return 0, because it's an error to type 2 times '='. + assertEquals(0, engine.getDisplayValue()); } @Test