I coded the 1000xxxxth calculator to test React.
Please check the code or the app and give me feedbacks, your way to do, everything.
code: https://github.com/blade-sensei/react-calculator/tree/master/src
app: https://calculator-1000.firebaseapp.com/
calculator service
import { operators } from '../constants';
class Calculator {
calculationExpression(calculExpression) {
let result = calculExpression.split('');
while (!this.isLastResult(result)) {
const terms = this.priorityOperationTerms(result)
let resultCalcul = this.calculation(terms.operands, terms.operator);
resultCalcul = resultCalcul.toString();
const deltaDeleteIndex = (terms.limitIndexes.end - terms.limitIndexes.start) + 1;
result.splice(terms.limitIndexes.start, deltaDeleteIndex, resultCalcul);
}
return Number(result[0]);
}
isLastResult(expression) {
return expression.length === 1;
}
calculation(operands, operator) {
const [firstOperand, secondOperand] = operands;
if (operator === operators.MULTIPLICATION) {
return this.multiplication(firstOperand, secondOperand);
} else if (operator === operators.DIVISION) {
return this.division(firstOperand, secondOperand);
} else if (operator === operators.ADDITION) {
return this.addition(firstOperand, secondOperand);
}
return this.subtraction(firstOperand, secondOperand);
}
//return limitIndexes to know where to replace in
//current string expressionn, priority operation by futur priority result
priorityOperationTerms(expression) {
let firstOperatorFound = false;
let indexPriorityOperator;
let operands = [];
for (let [index, term] of expression.entries()) {
if (this.isOperator(term)) {
if (this.isPriorityOperator(term)) {
indexPriorityOperator = index;
break;
} if (!firstOperatorFound) {
indexPriorityOperator = index;
firstOperatorFound = true;
}
}
}
const [operandLeft, operandLeftIndex ] = this.getLeftOperand(expression, indexPriorityOperator);
const [operandRight, operandRightIndex] = this.getRightOperand(expression, indexPriorityOperator);
operands = [operandLeft, operandRight];
const terms = {
operator: expression[indexPriorityOperator],
operands,
limitIndexes: {
start: operandLeftIndex,
end: operandRightIndex,
}
}
return terms;
}
getRightOperand(expression, index) {
let rightLimit = expression.length;
let leftLimit = index + 1;
for (let endIndex = leftLimit; endIndex < expression.length; endIndex++) {
const term = expression[endIndex];
if (this.isOperator(term)) {
rightLimit = endIndex;
break;
}
}
let number = expression.slice(leftLimit, rightLimit);
number = number.join('');
number = Number(number);
return [number, rightLimit - 1]
}
getLeftOperand(expression, index) {
let leftLimit = 0;
for (let endIndex = index - 1; endIndex >= 0; endIndex--) {
const term = expression[endIndex];
if (this.isOperator(term)) {
leftLimit = endIndex + 1;
break;
}
}
let number = expression.slice(leftLimit, index);
number = number.join('');
number = Number(number);
return [number, leftLimit]
}
isPriorityOperator(operator) {
return (
operator === operators.MULTIPLICATION ||
operator === operators.DIVISION
);
}
isOperator(term) {
return Object.values(operators).includes(term)
}
addition(first, second) {
return (first + second).toFixed(2);
}
subtraction(first, second) {
return (first - second).toFixed(2);
}
multiplication(first, second) {
return (first * second).toFixed(2);
}
division(first, second) {
return (first / second).toFixed(2);
}
}
export default Calculator;
It deals with string calcul expression (i wanted to try this way)
calculator component
import React from 'react';
import CalculatorButton from './CalculatorButton';
import CalculatorDisplayer from './CalculatorDisplayer';
import Calculator from '../services/calculator';
import './Calculator.css';
import { inputs, operators } from '../constants'
class CalculatorComponent extends React.Component {
constructor(props) {
super(props);
this.calculator = new Calculator();
this.state = {
calculationExpression: '0',
}
this.handleUserInput = this.handleUserInput.bind(this);
}
handleUserInput(userInput) {
const { type, value } = userInput;
const lastUserInput = this.lastUserInput();
switch(type) {
case inputs.NUMBER:
if (this.state.calculationExpression === '0') {
return this.setState({
calculationExpression: value,
});
}
this.append(value);
break;
case inputs.OPERATOR:
if (lastUserInput.type === inputs.NUMBER) {
this.append(value);
}
break;
case inputs.SEPARATOR:
if (lastUserInput.type === inputs.NUMBER) {
const lastNumber = this.getLastNumberInExpression();
if (!this.isFloat(lastNumber)) {
this.append(value);
}
}
break;
case inputs.CLEAR:
this.clearExpression(value);
break;
case inputs.RESULT:
if (this.lastUserInput().type === inputs.NUMBER ) {
const normalizedExpression = this.normalizeToCalculation(this.state.calculationExpression);
let result = this.calculator.calculationExpression(normalizedExpression);
result = result.toString();
result = this.normalizeToDisplay(result);
this.setState({ calculationExpression: result });
}
break;
default:
break;
}
}
append(input) {
this.setState({
calculationExpression: this.state.calculationExpression + input,
});
}
isFloat(stringNumber) {
return stringNumber.includes(',');
}
normalizeToCalculation(expression) {
let expressionNormalized = expression;
const regexMultiply = /x/gi;
const regexSeparator = /,/gi;
expressionNormalized = expressionNormalized.replace(regexMultiply, '*');
expressionNormalized = expressionNormalized.replace(regexSeparator, '.');
return expressionNormalized;
}
normalizeToDisplay(expression) {
let expressionNormalized = expression;
expressionNormalized = expressionNormalized.replace('.', ',');
return expressionNormalized;
}
getLastNumberInExpression() {
const expression = this.state.calculationExpression.split('');
const rightLimit = expression.length;
let leftLimit = 0;
for (let termIndex = rightLimit; termIndex >= 0; termIndex--) {
const term = expression[termIndex];
if (this.isOperator(term)) {
leftLimit = termIndex + 1;
break;
}
}
const number = expression.slice(leftLimit, rightLimit + 1);
return number.join('');
}
clearExpression(typeOfClear) {
if (typeOfClear === inputs.CLEAR_ALL) {
return this.resetExpression();
}
return this.removeLastUserInput();
}
removeLastUserInput() {
this.setState({
calculationExpression: this.state.calculationExpression.slice(0, -1)
})
}
resetExpression() {
this.setState({ calculationExpression: '0'});
}
isOperator(term) {
return Object.values(operators).includes(term)
}
lastUserInput() {
const lastInput = this.state.calculationExpression.slice(-1);
let type = '';
if (!lastInput) return { type, lastInput }
if (!isNaN(Number(lastInput))) {
type = inputs.NUMBER
} else if (lastInput === ',') {
type = inputs.SEPARATOR;
} else {
type = inputs.OPERATOR;
}
return {
type,
lastInput,
}
}
render() {
return (
<div className="calculator">
<div className="displayer-container">
<CalculatorDisplayer expression={this.state.calculationExpression} />
</div>
<div className="inputs-container">
<div className="row">
<CalculatorButton value='AC' type='clear' onUserInput={this.handleUserInput} />
<CalculatorButton value='' type='disabled' onUserInput={this.handleUserInput} />
<CalculatorButton value='C' type='clear' onUserInput={this.handleUserInput} />
<CalculatorButton value='/' type='operator' onUserInput={this.handleUserInput} />
</div>
<div className="row">
<CalculatorButton value='7' type='number' onUserInput={this.handleUserInput} />
<CalculatorButton value='8' type='number' onUserInput={this.handleUserInput} />
<CalculatorButton value='9' type='number' onUserInput={this.handleUserInput} />
<CalculatorButton value='x' type='operator' onUserInput={this.handleUserInput} />
</div>
<div className="row">
<CalculatorButton value='4' type='number' onUserInput={this.handleUserInput} />
<CalculatorButton value='5' type='number' onUserInput={this.handleUserInput} />
<CalculatorButton value='6' type='number' onUserInput={this.handleUserInput} />
<CalculatorButton value='-' type='operator' onUserInput={this.handleUserInput} />
</div>
<div className="row">
<CalculatorButton value='1' type='number' onUserInput={this.handleUserInput} />
<CalculatorButton value='2' type='number' onUserInput={this.handleUserInput} />
<CalculatorButton value='3' type='number' onUserInput={this.handleUserInput} />
<CalculatorButton value='+' type='operator' onUserInput={this.handleUserInput} />
</div>
<div className="row">
<CalculatorButton value='0' type='number' onUserInput={this.handleUserInput} />
<CalculatorButton value=',' type='separator' onUserInput={this.handleUserInput} />
<CalculatorButton value='=' type='result' onUserInput={this.handleUserInput}/>
</div>
</div>
</div>
)
}
}
export default CalculatorComponent;
Top comments (0)