Last active
November 30, 2017 10:14
-
-
Save alejandrolechuga/fea53bafe943b3792d7fa47191e82445 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* jshint esnext: true */ | |
var calculator = document.getElementById('calculator'); | |
var output = document.getElementById('calculator-output'); | |
calculator.addEventListener('click', calculatorClick); | |
function calculatorClick(event) { | |
var target = event.target; | |
var dataset = target.dataset; | |
var value = dataset.value; | |
var type = dataset.type; | |
if (type) { | |
calc.input(type, value); | |
result = calc.output() ; | |
output.innerHTML = result; | |
} | |
} | |
// ES6 | |
// Constants | |
// - States | |
const STATE_LEFT_OPERAND = 'left_operand'; | |
const STATE_OPERATOR = 'operator'; | |
const STATE_RIGHT_OPERAND = 'right_operand'; | |
const STATE_RESULT = 'result'; | |
// - Inputs | |
const TYPE_ACTION = 'action'; | |
const TYPE_OPERATOR = 'operator'; | |
const TYPE_NUMBER = 'number'; | |
// - Operators | |
const OPERATOR_DIVISION = '/'; | |
const OPERATOR_MULTIPLICATION = '*'; | |
const OPERATOR_ADDITION = '+'; | |
const OPERATOR_SUBTRACTION = '-'; | |
// - Actions | |
const ACTION_CLEAR = 'C'; | |
const ACTION_RESULT = '='; | |
class BaseStrategy { | |
constructor(delegate) { | |
this.delegate = delegate; | |
} | |
onNumber(number) {} | |
onOperator(operator) {} | |
onResult(operator) {} | |
onClear() { | |
this.delegate.reset(); | |
} | |
} | |
class LeftOperandStrategy extends BaseStrategy { | |
onNumber(number) { | |
this.delegate.addToAccumulator(number); | |
} | |
onOperator(operator) { | |
let dg = this.delegate; | |
dg.setOperator(operator); | |
dg.setLeftOperand(dg.getAccumulator()) | |
dg.transition(STATE_OPERATOR); | |
} | |
onResult(operator) {} | |
} | |
class RightOperandStrategy extends BaseStrategy { | |
onNumber(number) { | |
this.delegate.addToAccumulator(number); | |
} | |
onOperator(operator) { | |
let dg = this.delegate; | |
let result = 0; | |
dg.setRightOperand(dg.getAccumulator()); | |
result = dg.operation(); | |
dg.setAccumulator(result); | |
dg.setLeftOperand(dg.getAccumulator()); | |
dg.transition(STATE_OPERATOR); | |
} | |
onResult() { | |
let dg = this.delegate; | |
let result = 0; | |
let signed = 1; | |
let rightOperand = 0; | |
dg.setRightOperand(dg.getAccumulator()); | |
result = dg.operation(); | |
dg.setAccumulator(result); | |
rightOperand = dg.getRightOperand(); | |
if (dg.getOperator() === OPERATOR_SUBTRACTION) { | |
rightOperand = -1 * rightOperand; | |
dg.setOperator(OPERATOR_ADDITION); | |
} | |
if (dg.getOperator() === OPERATOR_DIVISION) { | |
rightOperand = 1 / rightOperand; | |
dg.setOperator(OPERATOR_MULTIPLICATION); | |
} | |
dg.setLeftOperand(rightOperand); | |
dg.transition(STATE_RESULT); | |
} | |
} | |
class OperatorStrategy extends BaseStrategy { | |
onNumber(number) { | |
let dg = this.delegate; | |
dg.clearAccumulator(); | |
dg.addToAccumulator(number); | |
dg.transition(STATE_RIGHT_OPERAND); | |
} | |
onOperator(operator) { | |
this.delegate.setOperator(operator); | |
} | |
onResult(operator) { | |
let dg = this.delegate; | |
dg.setRightOperand(dg.getAccumulator()); | |
dg.setAccumulator(dg.operation()); | |
} | |
} | |
class ResultStrategy extends BaseStrategy { | |
onNumber(number) { | |
let dg = this.delegate; | |
dg.setAccumulator(number); | |
dg.transition(STATE_OPERATOR); | |
} | |
onOperator(operator) { | |
let dg = this.delegate; | |
dg.setOperator(operator); | |
dg.setLeftOperand(dg.getAccumulator()); | |
dg.transition(STATE_OPERATOR); | |
} | |
onResult() { | |
let dg = this.delegate; | |
dg.setRightOperand(dg.getAccumulator()); | |
dg.setAccumulator(dg.operation()); | |
} | |
} | |
class Calculator { | |
constructor() { | |
this.init(); | |
} | |
init() { | |
this.acc = []; | |
this.operator = null; | |
this.leftOperand = 0; | |
this.rightOperand = 0; | |
this.state = STATE_LEFT_OPERAND; | |
this.strategy = null; | |
this.transition(STATE_LEFT_OPERAND); | |
} | |
transition (state) { | |
this.state = state; | |
switch (state) { | |
case STATE_LEFT_OPERAND: | |
this.strategy = new LeftOperandStrategy(this); | |
break; | |
case STATE_OPERATOR: | |
this.strategy = new OperatorStrategy(this); | |
break; | |
case STATE_RIGHT_OPERAND: | |
this.strategy = new RightOperandStrategy(this); | |
break; | |
case STATE_RESULT: | |
this.strategy = new ResultStrategy(this); | |
break; | |
} | |
} | |
input(type, value) { | |
console.log(type, value) | |
switch(type) { | |
case TYPE_ACTION: | |
if (value === ACTION_CLEAR) { | |
this.strategy.onClear(); | |
} | |
if (value === ACTION_RESULT) { | |
this.strategy.onResult(); | |
} | |
break; | |
case TYPE_OPERATOR: | |
this.strategy.onOperator(value); | |
break; | |
case TYPE_NUMBER: | |
this.strategy.onNumber(value); | |
break; | |
} | |
this.log(); | |
} | |
operation() { | |
let operator = this.operator; | |
let result = 0; | |
switch(operator) { | |
case OPERATOR_DIVISION: | |
result = this.leftOperand / this.rightOperand; | |
break; | |
case OPERATOR_MULTIPLICATION: | |
result = this.leftOperand * this.rightOperand; | |
break; | |
case OPERATOR_ADDITION: | |
result = this.leftOperand + this.rightOperand; | |
break; | |
case OPERATOR_SUBTRACTION: | |
result = this.leftOperand - this.rightOperand; | |
break; | |
} | |
return result; | |
} | |
setLeftOperand( value) { | |
this.leftOperand = value; | |
} | |
getRightOperand() { | |
return this.rightOperand; | |
} | |
setRightOperand(value) { | |
this.rightOperand = value; | |
} | |
getLeftOperand() { | |
return this.rightOperand; | |
} | |
setOperator(operator) { | |
this.operator = operator; | |
} | |
getOperator() { | |
return this.operator; | |
} | |
setAccumulator(value) { | |
this.acc = Array.from(String(value)); | |
} | |
addToAccumulator(number) { | |
this.acc.push(number); | |
} | |
getAccumulator() { | |
return parseFloat(this.acc.join('')); | |
} | |
clearAccumulator() { | |
this.acc = []; | |
} | |
output() { | |
let acc = 0; | |
if (this.acc.length > 0) { | |
acc = this.acc.join(''); | |
} | |
return acc; | |
} | |
log() { | |
let { | |
acc, | |
operator, | |
leftOperand, | |
rightOperand, | |
state | |
} = this; | |
console.log({ | |
'acc': acc, | |
'operator': operator, | |
'leftOperand': leftOperand, | |
'rightOperand': rightOperand, | |
'state': state | |
}); | |
} | |
reset() { | |
this.init(); | |
} | |
} | |
var calc = new Calculator(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment