Skip to content

Commit

Permalink
#1 Stop counter thread and #2 Two counter threads and refactored #7 …
Browse files Browse the repository at this point in the history
…Calculator from Design-patterns
  • Loading branch information
Secchol committed Oct 31, 2023
1 parent a491778 commit a4e4aff
Show file tree
Hide file tree
Showing 20 changed files with 358 additions and 155 deletions.
Original file line number Diff line number Diff line change
@@ -1,46 +1,53 @@
package com.ontotext.javacourse.designpatterns.calculator;

import lombok.NoArgsConstructor;
import com.ontotext.javacourse.designpatterns.calculator.commands.*;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;

/**
* Defines a calculator that can perform addition,subtraction,multiplication,division and
* exponentiation and return the result.
* The Calculator class contains a method that takes a given reverse polish notation expression and
* returns its result.
*/
@NoArgsConstructor
public class Calculator {
private double result;
private double operand;
public final class Calculator {

public void setOperand(double operand) {
this.operand = operand;
private Calculator() throws IllegalAccessException {
throw new IllegalAccessException("Calculator class is not meant to be instantiated!");
}

public void add() {
result += operand;
}

public void subtract() {
result -= operand;
}

public void multiply() {
result *= operand;
}

/** Divides the result by the given operand if the divisor is not zero. */
public void divide() {
if (operand == 0) {
System.out.println("Division by zero!");
} else {
result /= operand;
/**
* Evaluates the given expression.
*
* @param reversePolishNotationExpression the reverse polish notation expression
* @return the result of the expression
*/
public static double evaluateExpression(List<String> reversePolishNotationExpression) {
Deque<Double> stack = new ArrayDeque<>();
double firstOperand;
double secondOperand;
Double result;
for (String item : reversePolishNotationExpression) {
if (RPNEvaluator.isNumeric(item)) {
stack.push(Double.parseDouble(item));
} else {
secondOperand = stack.pop();
firstOperand = stack.pop();
Command command = getCommand(item);
result = command.execute(firstOperand, secondOperand);
stack.push(result);
}
}
return stack.pop();
}

public void exponentiate() {
result = Math.pow(result, operand);
}

public double getResult() {
return this.result;
private static Command getCommand(String action) {
return switch (action) {
case "+" -> new AddCommand();
case "-" -> new SubtractCommand();
case "*" -> new MultiplyCommand();
case "/" -> new DivisionCommand();
case "^" -> new ExponentiateCommand();
default -> throw new IllegalArgumentException("Action is invalid!");
};
}
}
Original file line number Diff line number Diff line change
@@ -1,50 +1,28 @@
package com.ontotext.javacourse.designpatterns.calculator;

import com.ontotext.javacourse.designpatterns.calculator.commands.*;
import java.security.InvalidParameterException;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
* The CalculatorApp class contains a method that starts the calculator and begins to accept
* operation and executes them.
* The CalculatorApp class contains a method that starts the calculator and accepts an expression as
* input.
*/
public class CalculatorApp {
private final CalculatorView calculatorView;
private final Calculator calculator;
private final CalculatorInvoker calculatorInvoker;
private final Scanner scanner;

public CalculatorApp(Calculator calculator) {
calculatorView = new CalculatorView();
this.calculator = calculator;
calculatorInvoker = new CalculatorInvoker();
public CalculatorApp() {
scanner = new Scanner(System.in);
}

/** Starts accepting user input from the console. */
public void startCalculator() {
calculatorView.displayAvailableCommands();
double startingNumber = calculatorView.promptNumberInput();
calculatorInvoker.setCommand(new AddCommand(this.calculator, startingNumber));
calculatorInvoker.executeCommand();
int operationNumber = calculatorView.promptOperationNumber();
double operand = 0;
while (operationNumber != 6) {
operand = calculatorView.promptNumberInput();
Command command = getOperationCommand(operationNumber, operand);
calculatorInvoker.setCommand(command);
calculatorInvoker.executeCommand();
calculatorView.displayCurrentResult(calculator.getResult());
operationNumber = calculatorView.promptOperationNumber();
}
calculatorView.displayEndResult(calculator.getResult());
}

private Command getOperationCommand(int operationNumber, double operand) {
return switch (operationNumber) {
case 1 -> new AddCommand(this.calculator, operand);
case 2 -> new SubtractCommand(this.calculator, operand);
case 3 -> new MultiplyCommand(this.calculator, operand);
case 4 -> new DivisionCommand(this.calculator, operand);
case 5 -> new ExponentiateCommand(this.calculator, operand);
default -> throw new InvalidParameterException("Invalid operand number!");
};
System.out.println("Enter an expression with a space between each number and symbol:");
String input = scanner.nextLine();
List<String> expression = Arrays.stream(input.split(" ")).toList();
List<String> reversePolishNotationExpression =
RPNEvaluator.getReversePolishNotation(expression);
double result = Calculator.evaluateExpression(reversePolishNotationExpression);
System.out.printf("Result: %.2f%n", result);
}
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,83 @@
package com.ontotext.javacourse.designpatterns.calculator;public class RPNEvaluator {
package com.ontotext.javacourse.designpatterns.calculator;

import java.util.*;

/**
* The RPNEvaluator class contains methods that return the reverse polish notation of a given
* expression.
*/
public final class RPNEvaluator {
private RPNEvaluator() throws IllegalAccessException {
throw new IllegalAccessException("RPNEvaluator class is not meant to be instantiated!");
}

public static List<String> getReversePolishNotation(List<String> expression) {
return transformExpression(expression);
}

/**
* Determines whether the given item is a valid number.
*
* @param item the item which to check the type of
* @return whether the item is a valid number or not.
*/
public static boolean isNumeric(String item) {
try {
Double.parseDouble(item);
return true;
} catch (NumberFormatException exception) {
return false;
}
}

private static List<String> transformExpression(List<String> expression) {
if (expression.isEmpty()) {
throw new IllegalArgumentException("Empty input!");
}
Deque<String> stack = new ArrayDeque<>();
List<String> output = new ArrayList<>();
for (String item : expression) {
if (isNumeric(item)) {
output.add(item);
} else if (item.equals("(")) {
stack.push(item);
} else if (item.equals(")")) {
while (!stack.isEmpty() && !stack.peek().equals("(")) {
output.add(stack.pop());
}
stack.pop();
} else {
while (!stack.isEmpty()
&& getPrecedence(item) <= getPrecedence(stack.peek())
&& hasLeftAssociativity(item)) {
output.add(stack.pop());
}
stack.push(item);
}
}
emptyStack(stack, output);
return output;
}

private static int getPrecedence(String item) {
return switch (item) {
case "+", "-" -> 1;
case "*", "/" -> 2;
case "^" -> 3;
default -> -1;
};
}

private static boolean hasLeftAssociativity(String item) {
return item.equals("+") || item.equals("-") || item.equals("/") || item.equals("*");
}

private static void emptyStack(Deque<String> stack, List<String> output) {
while (!stack.isEmpty()) {
if (stack.peek().equals("(")) {
throw new IllegalArgumentException("This expression is invalid");
}
output.add(stack.pop());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package com.ontotext.javacourse.designpatterns.calculator.commands;

import com.ontotext.javacourse.designpatterns.calculator.Calculator;
import lombok.NoArgsConstructor;

/** The AddCommand class is a command that executes the addition operation. */
public class AddCommand extends BaseOperation {

public AddCommand(Calculator calculator, double operand) {
super(calculator, operand);
}
/** The AddCommand class is a command that adds two given operands. */
@NoArgsConstructor
public class AddCommand implements Command {

@Override
public void execute() {
super.getCalculator().add();
public Double execute(Double firstOperand, Double secondOperand) {
return firstOperand + secondOperand;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

/** Defines a command that can be executed. */
public interface Command {
public void execute();
Double execute(Double firstOperand, Double secondOperand);
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package com.ontotext.javacourse.designpatterns.calculator.commands;

import com.ontotext.javacourse.designpatterns.calculator.Calculator;
import lombok.NoArgsConstructor;

/** The DivisionCommand class is a command that executes the division operation. */
public class DivisionCommand extends BaseOperation {

public DivisionCommand(Calculator calculator, double operand) {
super(calculator, operand);
}
/** The DivisionCommand class is a command that divides two given operands. */
@NoArgsConstructor
public class DivisionCommand implements Command {

@Override
public void execute() {
super.getCalculator().divide();
public Double execute(Double firstOperand, Double secondOperand) {
if (secondOperand == 0) {
throw new IllegalArgumentException("Division by zero!");
}
return firstOperand / secondOperand;
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
package com.ontotext.javacourse.designpatterns.calculator.commands;

import com.ontotext.javacourse.designpatterns.calculator.Calculator;

/**
* The ExponentiateCommand class is a command that raises the current result to a given exponent.
*/
public class ExponentiateCommand extends BaseOperation {
public ExponentiateCommand(Calculator calculator, double operand) {
super(calculator, operand);
}
import lombok.NoArgsConstructor;

/** The ExponentiateCommand class is a command that exponentiates two given operands. */
@NoArgsConstructor
public class ExponentiateCommand implements Command {
@Override
public void execute() {
super.getCalculator().exponentiate();
public Double execute(Double firstOperand, Double secondOperand) {
return Math.pow(firstOperand, secondOperand);
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
package com.ontotext.javacourse.designpatterns.calculator.commands;

import com.ontotext.javacourse.designpatterns.calculator.Calculator;

/** The MultiplyCommand class is a command that executes the multiplication operation. */
public class MultiplyCommand extends BaseOperation {
public MultiplyCommand(Calculator calculator, double operand) {
super(calculator, operand);
}
import lombok.NoArgsConstructor;

/** The MultiplyCommand class is a command that multiplies two given operands. */
@NoArgsConstructor
public class MultiplyCommand implements Command {
@Override
public void execute() {
super.getCalculator().multiply();
public Double execute(Double firstOperand, Double secondOperand) {
return firstOperand * secondOperand;
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
package com.ontotext.javacourse.designpatterns.calculator.commands;

import com.ontotext.javacourse.designpatterns.calculator.Calculator;

/** The SubtractCommand class is a command that executes the subtraction operation. */
public class SubtractCommand extends BaseOperation {
public SubtractCommand(Calculator calculator, double operand) {
super(calculator, operand);
}
import lombok.NoArgsConstructor;

/** The SubtractCommand class is a command that subtracts two given operands. */
@NoArgsConstructor
public class SubtractCommand implements Command {
@Override
public void execute() {
super.getCalculator().subtract();
public Double execute(Double firstOperand, Double secondOperand) {
return firstOperand - secondOperand;
}
}
Loading

0 comments on commit a4e4aff

Please sign in to comment.