Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

g #111

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open

g #111

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 127 additions & 79 deletions src/simplejavacalculator/Calculator.java
Original file line number Diff line number Diff line change
@@ -1,72 +1,145 @@
/**
* @name Simple Java Calculator
* @package ph.calculator
* @file Main.java
* @author SORIA Pierre-Henry
* @email [email protected]
* @link http://github.com/pH-7
* @copyright Copyright Pierre-Henry SORIA, All Rights Reserved.
* @license Apache (http://www.apache.org/licenses/LICENSE-2.0)
*/

package simplejavacalculator;

import static java.lang.Double.NaN;
import static java.lang.Math.log;
import static java.lang.Math.log10;
import static java.lang.Math.pow;
import static java.lang.Math.*;
import java.util.HashMap;
import java.util.Map;
import simplejavacalculator.behavioral.command.*;
import simplejavacalculator.behavioral.strategy.*;
import simplejavacalculator.creational.*;
import simplejavacalculator.structural.*;
import simplejavacalculator.structural.adapter.*;
import simplejavacalculator.structural.decorator.*;

public class Calculator {

public enum BiOperatorModes {
normal, add, minus, multiply, divide , xpowerofy
normal, add, minus, multiply, divide, xpowerofy
}

public enum MonoOperatorModes {
square, squareRoot, oneDividedBy, cos, sin, tan, log, rate, abs, ln,
square, squareRoot, oneDividedBy, cos, sin, tan, log, rate, abs, ln
}

private Double currentValue = 0.0;
private Double num1, num2;
private BiOperatorModes mode = BiOperatorModes.normal;
private final Map<String, CalculatorOperation> operations;
private final OperationFactory factory;
private final CalculatorBuilder builder;
private final CommandHistory history;
private CalculationStrategy strategy;

public Calculator() {
this.operations = new HashMap<>();
this.factory = new OperationFactory();
this.builder = new CalculatorBuilder();
this.history = new CommandHistory();
this.strategy = new BasicStrategy();
initializeOperations();
}

private Double calculateBiImpl() {
if (mode.equals(BiOperatorModes.normal)) {
return num2;
private void initializeOperations() {
// Basic operations with factory and logging decorator
Operation addOp = factory.createOperation("add");
Operation subOp = factory.createOperation("subtract");
Operation mulOp = factory.createOperation("multiply");
Operation divOp = factory.createOperation("divide");

operations.put("add", new LoggingDecorator(new CalculatorOperationAdapter(addOp)));
operations.put("subtract", new LoggingDecorator(new CalculatorOperationAdapter(subOp)));
operations.put("multiply", new LoggingDecorator(new CalculatorOperationAdapter(mulOp)));
operations.put("divide", new LoggingDecorator(new CalculatorOperationAdapter(divOp)));

// Scientific operations with adapter
operations.put("sin", new LoggingDecorator(
new ScientificAdapter(new TrigonometricOperation("sin"), "sin")
));
operations.put("cos", new LoggingDecorator(
new ScientificAdapter(new TrigonometricOperation("cos"), "cos")
));
operations.put("tan", new LoggingDecorator(
new ScientificAdapter(new TrigonometricOperation("tan"), "tan")
));
}

private class CalculatorOperationAdapter implements CalculatorOperation {
private final Operation operation;

public CalculatorOperationAdapter(Operation operation) {
this.operation = operation;
}
if (mode.equals(BiOperatorModes.add)) {
if (num2 != 0) {
return num1 + num2;
}

return num1;
@Override
public Double execute(Double... numbers) {
return operation.execute(numbers);
}
if (mode.equals(BiOperatorModes.minus)) {
return num1 - num2;

@Override
public String getDescription() {
return operation.getDescription();
}
if (mode.equals(BiOperatorModes.multiply)) {
return num1 * num2;
}

public void setStrategy(CalculationStrategy strategy) {
this.strategy = strategy;
}

public Double getCurrentValue() {
return currentValue;
}

public void setValue(Double value) {
this.currentValue = value;
}

public void executeCommand(CalculatorCommand command) {
history.executeCommand(command);
}

public void undo() {
history.undo();
}

public void redo() {
history.redo();
}

private Double calculateBiImpl() {
if (mode.equals(BiOperatorModes.normal)) {
return num2;
}
if (mode.equals(BiOperatorModes.divide)) {
return num1 / num2;

String operationType = null;
switch (mode) {
case add: operationType = "add"; break;
case minus: operationType = "subtract"; break;
case multiply: operationType = "multiply"; break;
case divide: operationType = "divide"; break;
case xpowerofy: return strategy.calculate(num1, num2);
}
if (mode.equals(BiOperatorModes.xpowerofy)) {
return pow(num1,num2);

if (operationType != null) {
CalculatorOperation operation = operations.get(operationType);
if (operation != null) {
return operation.execute(num1, num2);
}
}

// never reach
throw new Error();
throw new Error("Invalid operation");
}

public Double calculateBi(BiOperatorModes newMode, Double num) {
if (mode.equals(BiOperatorModes.normal)) {
num2 = 0.0;
num1 = num;
mode = newMode;
currentValue = num1;
return NaN;
} else {
num2 = num;
num1 = calculateBiImpl();
mode = newMode;
currentValue = num1;
return num1;
}
}
Expand All @@ -78,54 +151,29 @@ public Double calculateEqual(Double num) {
public Double reset() {
num2 = 0.0;
num1 = 0.0;
currentValue = 0.0;
mode = BiOperatorModes.normal;

return NaN;
}


public Double calculateMono(MonoOperatorModes newMode, Double num) {
if (newMode.equals(MonoOperatorModes.square)) {
return num * num;
}
if (newMode.equals(MonoOperatorModes.squareRoot)) {
return Math.sqrt(num);
}
if (newMode.equals(MonoOperatorModes.oneDividedBy)) {
return 1 / num;
}
if (newMode.equals(MonoOperatorModes.cos)) {
return Math.cos(Math.toRadians(num));
}
if (newMode.equals(MonoOperatorModes.sin)) {
return Math.sin(Math.toRadians(num));
}
if (newMode.equals(MonoOperatorModes.tan)) {
if (num == 0 || num % 180 == 0 ) {
return 0.0;
}
if (num % 90 == 0.0 && num % 180 != 0.0) {
return NaN;
Double result = switch (newMode) {
case square -> num * num;
case squareRoot -> Math.sqrt(num);
case oneDividedBy -> 1 / num;
case cos -> Math.cos(Math.toRadians(num));
case sin -> Math.sin(Math.toRadians(num));
case tan -> {
if (num == 0 || num % 180 == 0) yield 0.0;
if (num % 90 == 0.0 && num % 180 != 0.0) yield NaN;
yield Math.tan(Math.toRadians(num));
}

return Math.tan(Math.toRadians(num));
}
if (newMode.equals(MonoOperatorModes.log)) {
return log10(num);
}
if (newMode.equals(MonoOperatorModes.ln)) {
return log(num);
}
if (newMode.equals(MonoOperatorModes.rate) ) {
return num / 100;
}
if (newMode.equals(MonoOperatorModes.abs)){
return Math.abs(num);
}

// never reach
throw new Error();
case log -> log10(num);
case ln -> log(num);
case rate -> num / 100;
case abs -> Math.abs(num);
};
currentValue = result;
return result;
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package simplejavacalculator.behavioral.command;

public interface CalculatorCommand {
Double execute();
void undo();
}
30 changes: 30 additions & 0 deletions src/simplejavacalculator/behavioral/command/CommandHistory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package simplejavacalculator.behavioral.command;

import java.util.Stack;

public class CommandHistory {
private final Stack<CalculatorCommand> undoStack = new Stack<>();
private final Stack<CalculatorCommand> redoStack = new Stack<>();

public void executeCommand(CalculatorCommand command) {
command.execute();
undoStack.push(command);
redoStack.clear();
}

public void undo() {
if (!undoStack.isEmpty()) {
CalculatorCommand command = undoStack.pop();
command.undo();
redoStack.push(command);
}
}

public void redo() {
if (!redoStack.isEmpty()) {
CalculatorCommand command = redoStack.pop();
command.execute();
undoStack.push(command);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package simplejavacalculator.behavioral.command.commands;

import simplejavacalculator.behavioral.command.CalculatorCommand;
import simplejavacalculator.Calculator;

public class AddCommand implements CalculatorCommand {
private final Calculator calculator;
private final Double operand;
private Double previousResult;

public AddCommand(Calculator calculator, Double operand) {
this.calculator = calculator;
this.operand = operand;
}

@Override
public Double execute() {
previousResult = calculator.getCurrentValue();
return calculator.calculateBi(Calculator.BiOperatorModes.add, operand);
}

@Override
public void undo() {
calculator.setValue(previousResult);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package simplejavacalculator.behavioral.command.commands;

import simplejavacalculator.behavioral.command.CalculatorCommand;
import simplejavacalculator.Calculator;

public class SubtractCommand implements CalculatorCommand {
private final Calculator calculator;
private final Double operand;
private Double previousResult;

public SubtractCommand(Calculator calculator, Double operand) {
this.calculator = calculator;
this.operand = operand;
}

@Override
public Double execute() {
previousResult = calculator.getCurrentValue();
return calculator.calculateBi(Calculator.BiOperatorModes.minus, operand);
}

@Override
public void undo() {
calculator.setValue(previousResult);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package simplejavacalculator.behavioral.strategy;

public class BasicStrategy implements CalculationStrategy {
@Override
public Double calculate(Double a, Double b) {
return a + b;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package simplejavacalculator.behavioral.strategy;

public interface CalculationStrategy {
Double calculate(Double a, Double b);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package simplejavacalculator.behavioral.strategy;

public class ScientificStrategy implements CalculationStrategy {
@Override
public Double calculate(Double a, Double b) {
return Math.pow(a, b);
}
}
Loading