Skip to content

Instantly share code, notes, and snippets.

@raulbrito
Created November 28, 2009 21:28
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save raulbrito/244657 to your computer and use it in GitHub Desktop.
package calculator;
public class CalculatorController {
private final CalculatorModel model;
private Calculation calculation;
public CalculatorController(CalculatorModel model, Calculation calculation) {
this.model = model;
this.calculation = calculation;
}
public void push(char charAt) {
int number;
if (SignMapper.isSign(charAt)) {
calculation.sign(SignMapper.getSign(charAt));
} else {
number = Numeric.getNumeric(charAt);
calculation.number(number);
}
String displayString = transformValue(calculation.getValue());
model.setDisplay(displayString);
}
private String transformValue(double currentValue) {
String stringValue = "" + currentValue;
if (Math.floor(currentValue) != currentValue) {
return stringValue;
} else {
return stringValue.substring(0, stringValue.length() - 1);
}
}
}
package calculator;
import calculator.CalculatorController;
import calculator.CalculatorModel;
import junit.framework.TestCase;
public class CalculatorControllerTest extends TestCase {
CalculatorModel model = new CalculatorModel();
Calculation calculation = new StandardCalculation();
CalculatorController controller;
public void setUp() {
controller = new CalculatorController(model, calculation);
}
public void testItShouldInitializeToZero() throws Exception {
controller.push('C');
assertEquals("0.", model.getDisplay());
}
public void testItShouldConcatenateTwoNumberPresses() {
controller.push('1');
controller.push('2');
assertEquals("12.", model.getDisplay());
}
public void testItShouldConcatenateThreeNumberPresses() {
bulkPush("369");
assertEquals("369.", model.getDisplay());
}
public void testItShouldSupportDecimalPoint() {
bulkPush("4.7");
assertEquals("4.7", model.getDisplay());
}
public void testItShouldNotCareAboutSecondDecimalPoint() {
bulkPush("4.7..");
assertEquals("4.7", model.getDisplay());
}
public void testDoPlus() {
bulkPush("4+5=");
assertEquals("9.", model.getDisplay());
}
public void testDoMinus() {
bulkPush("2-4=");
assertEquals("-2.", model.getDisplay());
}
public void testDoMultiply() {
bulkPush("2*4=");
assertEquals("8.", model.getDisplay());
}
public void testDoDivision() {
bulkPush("2/4=");
assertEquals("0.5", model.getDisplay());
}
public void testPutSignal() {
controller.push('2');
controller.push('±');
assertEquals("-2.", model.getDisplay());
}
public void testDoDivisionWithOtherSymbol() {
bulkPush("2÷4=");
assertEquals("0.5", model.getDisplay());
}
public void testGetValueAfterSign() {
controller.push('2');
controller.push('+');
assertEquals("2.", model.getDisplay());
}
public void testDoSquareRoot() {
bulkPush("4√2=");
assertEquals("2.", model.getDisplay());
}
public void testDoPower() {
bulkPush("4^4=");
assertEquals("256.", model.getDisplay());
}
private void bulkPush(String push) {
char[] list = push.toCharArray();
for (int i = 0; i < list.length; i++) {
controller.push(list[i]);
}
}
}
public class StandardCalculation implements Calculation {
private double leftValue = 0;
private double currentValue = 0;
private double decimalLevel = 0;
private CalculationState operationTerm = CalculationState.LEFT_TERM;
private Sign operationType;
private static final int INTEGER_PART = 10;
private static final double DECIMAL_PART = 0.1;
@Override
public double getValue() {
return currentValue;
}
@Override
public void number(int number) {
double doubleNumber = number;
if (operationTerm == CalculationState.OPERATION) {
currentValue = 0;
operationTerm = CalculationState.RIGHT_TERM;
}
if (isDecimal()) {
currentValue *= INTEGER_PART;
} else {
doubleNumber = decimalLevel * doubleNumber;
decimalLevel *= DECIMAL_PART;
}
if (isNegative()) {
currentValue -= doubleNumber;
} else {
currentValue += doubleNumber;
}
}
private boolean isNegative() {
return currentValue < 0;
}
private boolean isDecimal() {
return decimalLevel == 0;
}
@Override
public void sign(Sign symbol) {
switch(symbol) {
case CLEAR:
resetInformation();
break;
case DOT:
decimalLevel = DECIMAL_PART;
break;
case PLUS:
case MINUS:
case MULTIPLY:
case DIVISION:
case ROOT:
case POWER:
if (isLeftTerm()) {
changeToOperationTerm(symbol);
}
if (isRightTerm()) {
this.sign(Sign.EQUALS);
}
break;
case EQUALS:
if (isNotEqualsTerm()) {
calculateResult();
currentValue = leftValue;
operationTerm = CalculationState.EQUALS;
}
break;
case SIGNAL:
if (isLeftTerm() || isRightTerm()) {
currentValue *= -1;
}
break;
default:
throw new UnsupportedOperationException();
}
}
private boolean isRightTerm() {
return operationTerm == CalculationState.RIGHT_TERM;
}
private void resetInformation() {
leftValue = 0;
currentValue = 0;
operationTerm = CalculationState.LEFT_TERM;
decimalLevel = 0;
}
private void calculateResult() {
if (operationType == Sign.PLUS) {
leftValue += currentValue;
}
if (operationType == Sign.MINUS) {
leftValue -= currentValue;
}
if (operationType == Sign.MULTIPLY) {
leftValue *= currentValue;
}
if (operationType == Sign.DIVISION) {
leftValue /= currentValue;
}
if (operationType == Sign.ROOT) {
leftValue = Math.pow(leftValue, 1.0/currentValue);
}
if (operationType == Sign.POWER) {
leftValue = Math.pow(leftValue, currentValue);
}
}
private boolean isNotEqualsTerm() {
return operationTerm != CalculationState.EQUALS;
}
private void changeToOperationTerm(Sign operation) {
operationType = operation;
leftValue = currentValue;
decimalLevel = 0;
operationTerm = CalculationState.OPERATION;
}
private boolean isLeftTerm() {
return operationTerm == CalculationState.LEFT_TERM;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment