diff --git a/lab-01/.gitignore b/lab-01/.gitignore new file mode 100644 index 0000000..2a1491c --- /dev/null +++ b/lab-01/.gitignore @@ -0,0 +1,11 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# other +/out/ +/.idea/ \ No newline at end of file diff --git a/lab-01/lab-01.iml b/lab-01/lab-01.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/lab-01/lab-01.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/lab-01/src/Main.java b/lab-01/src/Main.java new file mode 100644 index 0000000..2eb46ff --- /dev/null +++ b/lab-01/src/Main.java @@ -0,0 +1,88 @@ +import by.parfen01.quiser.Quiz; +import by.parfen01.quiser.Result; +import by.parfen01.quiser.task_generators.GroupTaskGenerator; +import by.parfen01.quiser.task_generators.PoolTaskGenerator; +import by.parfen01.quiser.tasks.TextTask; +import by.parfen01.quiser.tasks.math_tasks.EquationTask; +import by.parfen01.quiser.tasks.math_tasks.ExpressionTask; +import by.parfen01.quiser.tasks.math_tasks.MathTask; +import java.util.EnumSet; +import java.util.Map; +import java.util.Scanner; +import java.util.TreeMap; +import java.util.Formatter; + +public class Main { + public static void main(String[] argv) { + Map givenQuizzes = getQuizMap(); + System.out.println("Enter test name..."); + Scanner scanner = new Scanner(System.in); + Quiz currentQuiz; + String nameOfQuiz = scanner.nextLine(); + while(true) { + if (!givenQuizzes.containsKey(nameOfQuiz)) { + System.out.println("Test not found. Please try another name..."); + nameOfQuiz = scanner.nextLine(); + } else { + currentQuiz = givenQuizzes.get(nameOfQuiz); + break; + } + } + while (!currentQuiz.isFinished()) { + System.out.println(currentQuiz.nextTask().getText()); + String answer = scanner.nextLine(); + Result result = currentQuiz.provideAnswer(answer); + if (result == Result.OK) { + System.out.println("Right"); + continue; + } + if (result == Result.WRONG) { + System.out.println("Wrong"); + continue; + } + if (result == Result.INCORRECT_INPUT) { + System.out.println("Incorrect input. Try once more"); + } + } + Formatter formatter = new Formatter(); + formatter.format("%.1f", currentQuiz.getMark()); + System.out.println("total correct answer number: " + currentQuiz.getCorrectAnswerNumber()); + System.out.println("total wrong answer number: " + currentQuiz.getWrongAnswerNumber()); + System.out.println("total incorrect input number: " + currentQuiz.getIncorrectInputNumber()); + System.out.println("your final mark is: " + formatter); + } + + /** + * @return тесты в {@link Map}, где + * ключ - название теста {@link String} + * значение - сам тест {@link Quiz} + */ + static Map getQuizMap() { + Map result = new TreeMap<>(); + ExpressionTask.Generator firstTaskGenerator = new ExpressionTask.Generator( + 1, 100, 2, EnumSet.allOf(MathTask.Operation.class)); + Quiz firstQuiz = new Quiz(firstTaskGenerator, 10); + result.put("Expression Test", firstQuiz); + EquationTask.Generator secondTaskGenerator = new EquationTask.Generator( + 1, 100, 3, EnumSet.allOf(MathTask.Operation.class), new int[]{0, 1}); + Quiz secondQuiz = new Quiz(secondTaskGenerator, 10); + result.put("Equation Test", secondQuiz); + TextTask firstTextTask = new TextTask("what the highest mountain in the world?", "Everest"); + TextTask secondTextTask = new TextTask("what the fastest mammal in the world?", "Cheetah"); + TextTask thirdTextTask = new TextTask("Лектор расписался в журнале." + + " Там было 3 н-ки." + " Сколько студентов было на паре?", "Один"); + TextTask fourthTextTask = new TextTask("what the fastest mammal in the world?", "Cheetah"); + PoolTaskGenerator thirdTaskGenerator = new PoolTaskGenerator(false, secondTextTask, + thirdTextTask, fourthTextTask, firstTextTask); + PoolTaskGenerator fourthTaskGenerator = new PoolTaskGenerator(true, secondTextTask, + thirdTextTask, fourthTextTask, firstTextTask); + Quiz thirdQuiz = new Quiz(thirdTaskGenerator, 3); + result.put("Text Test", thirdQuiz); + Quiz fourthQuiz = new Quiz(new GroupTaskGenerator(firstTaskGenerator, secondTaskGenerator, + thirdTaskGenerator.clone()), 10); + result.put("Mixed Test", fourthQuiz); + Quiz fifthQuiz = new Quiz(fourthTaskGenerator, 3); + result.put("Text Test With Repeat", fifthQuiz); + return result; + } +} \ No newline at end of file diff --git a/lab-01/src/by/parfen01/quiser/Quiz.java b/lab-01/src/by/parfen01/quiser/Quiz.java new file mode 100644 index 0000000..ae89f59 --- /dev/null +++ b/lab-01/src/by/parfen01/quiser/Quiz.java @@ -0,0 +1,105 @@ +package by.parfen01.quiser; + +/** + * Class, который описывает один тест + */ +public class Quiz { + private final Task.Generator generator; + private int taskCount; + private int correctAnswerNumber = 0; + private int wrongAnswerNumber = 0; + private int incorrectInputCount = 0; + Task currentTask; + Task nextTask; + boolean isLastInputIncorrect = false; + /** + * @param generator генератор заданий + * @param taskCount количество заданий в тесте + */ + public Quiz(Task.Generator generator, int taskCount) { + this.generator = generator; + this.taskCount = taskCount; + this.nextTask = null; + } + + /** + * @return задание, повторный вызов вернет слелующее + * @see Task + */ + public Task nextTask() { + if (isLastInputIncorrect) { + return currentTask; + } + if (nextTask == null) { + nextTask = generator.generate(); + } + Task result = nextTask; + currentTask = nextTask; + if (taskCount > 1) { + nextTask = generator.generate(); + } + return result; + } + + /** + * Предоставить ответ ученика. Если результат {@link Result#INCORRECT_INPUT}, то счетчик неправильных + * ответов не увеличивается, а {@link #nextTask()} в следующий раз вернет тот же самый объект {@link Task}. + */ + public Result provideAnswer(String answer) { + Result result = currentTask.validate(answer); + switch (result) { + case INCORRECT_INPUT -> { + isLastInputIncorrect = true; + ++incorrectInputCount; + } + case OK -> { + ++correctAnswerNumber; + --taskCount; + isLastInputIncorrect = false; + } + case WRONG -> { + ++wrongAnswerNumber; + --taskCount; + isLastInputIncorrect = false; + } + } + + return result; + } + + /** + * @return завершен ли тест + */ + public boolean isFinished() { + return taskCount == 0; + } + + /** + * @return количество правильных ответов + */ + public int getCorrectAnswerNumber() { + return this.correctAnswerNumber; + } + + /** + * @return количество неправильных ответов + */ + public int getWrongAnswerNumber() { + return this.wrongAnswerNumber; + } + + /** + * @return количество раз, когда был предоставлен неправильный ввод + */ + public int getIncorrectInputNumber() { + return this.incorrectInputCount; + } + + /** + * @return оценка, которая является отношением количества правильных ответов к количеству всех вопросов. + * Оценка выставляется только в конце! + */ + public double getMark() { + return (double)correctAnswerNumber / (correctAnswerNumber + wrongAnswerNumber) * 10; + } +} \ No newline at end of file diff --git a/lab-01/src/by/parfen01/quiser/Result.java b/lab-01/src/by/parfen01/quiser/Result.java new file mode 100644 index 0000000..ce06467 --- /dev/null +++ b/lab-01/src/by/parfen01/quiser/Result.java @@ -0,0 +1,10 @@ +package by.parfen01.quiser; + +/** + * Enum, который описывает результат ответа на задание + */ +public enum Result { + OK, // Получен правильный ответ + WRONG, // Получен неправильный ответ + INCORRECT_INPUT // Некорректный ввод. Например, текст, когда ожидалось число +} \ No newline at end of file diff --git a/lab-01/src/by/parfen01/quiser/Task.java b/lab-01/src/by/parfen01/quiser/Task.java new file mode 100644 index 0000000..afb214d --- /dev/null +++ b/lab-01/src/by/parfen01/quiser/Task.java @@ -0,0 +1,34 @@ +package by.parfen01.quiser; + +/** + * Interface, который описывает одно задание + */ +public interface Task { + /* + @return текст задания + */ + + String getText(); + + /* + * Проверяет ответ на задание и возвращает результат + * + * @param answer ответ на задание + * @return результат ответа + * @see Result + */ + Result validate(String answer); + + /** + * Interface, который описывает один генератор заданий + */ + interface Generator { + /* + * Возвращает задание. При этом новый объект может не создаваться, если класс задания иммутабельный + * + * @return задание + * @see Task + */ + Task generate(); + } +} diff --git a/lab-01/src/by/parfen01/quiser/task_generators/GroupTaskGenerator.java b/lab-01/src/by/parfen01/quiser/task_generators/GroupTaskGenerator.java new file mode 100644 index 0000000..a3b232a --- /dev/null +++ b/lab-01/src/by/parfen01/quiser/task_generators/GroupTaskGenerator.java @@ -0,0 +1,65 @@ +package by.parfen01.quiser.task_generators; + +import by.parfen01.quiser.Task; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +public class GroupTaskGenerator implements Task.Generator { + private final ArrayList generators = new ArrayList<>(); + /** + * Конструктор с переменным числом аргументов + * + * @param generators генераторы, которые в конструктор передаются через запятую + */ + public GroupTaskGenerator(Task.Generator... generators) { + if (generators == null) { + throw new NullPointerException(); + } + for (Task.Generator generator : generators) { + if (generator != null) { + this.generators.add(generator); + } + } + if (this.generators.isEmpty()) { + throw new IllegalArgumentException(); + } + } + + /** + * Конструктор, который принимает коллекцию генераторов + * + * @param generators генераторы, которые передаются в конструктор в Collection (например, {@link ArrayList}) + */ + GroupTaskGenerator(Collection generators) { + if (generators == null) { + throw new NullPointerException(); + } + for (Task.Generator generator : generators) { + if (generator != null) { + this.generators.add(generator); + } + } + if (this.generators.isEmpty()) { + throw new IllegalArgumentException(); + } + } + + /** + * @return результат метода generate() случайного генератора из списка. + * Если этот генератор выбросил исключение в методе generate(), выбирается другой. + * Если все генераторы выбрасывают исключение, то и тут выбрасывается исключение. + */ + public Task generate() { + Collections.shuffle(generators); + for (Task.Generator generator : generators) { + try { + return generator.generate(); + } catch (Exception ignored) { + + } + } + + throw new RuntimeException(); + } +} \ No newline at end of file diff --git a/lab-01/src/by/parfen01/quiser/task_generators/PoolTaskGenerator.java b/lab-01/src/by/parfen01/quiser/task_generators/PoolTaskGenerator.java new file mode 100644 index 0000000..5cd3c8d --- /dev/null +++ b/lab-01/src/by/parfen01/quiser/task_generators/PoolTaskGenerator.java @@ -0,0 +1,84 @@ +package by.parfen01.quiser.task_generators; + +import by.parfen01.quiser.Task; +import java.util.*; + +/** + * Генератор заданий инициализирующийся перечнем доступных заданий. + * Одноразовый. Если хотите использовать один и тот же генератор в разных + * квизах передавайте его копию + */ +public class PoolTaskGenerator implements Task.Generator { + private final LinkedHashSet tasks = new LinkedHashSet<>(); + private boolean isAllowedDuplicate; + + /** + * Конструктор с переменным числом аргументов + * + * @param allowDuplicate разрешить повторения + * @param tasks задания, которые в конструктор передаются через запятую + */ + public PoolTaskGenerator(boolean allowDuplicate, Task... tasks) { + if (tasks == null) { + throw new NullPointerException(); + } + LinkedHashSet uniqueTexts = new LinkedHashSet<>(); + for (Task task : tasks) { + if (task != null && !uniqueTexts.contains(task.getText())) { + this.tasks.add(task); + uniqueTexts.add(task.getText()); + } + } + if (this.tasks.isEmpty()) { + throw new IllegalArgumentException(); + } + isAllowedDuplicate = allowDuplicate; + } + + /** + * Конструктор, который принимает коллекцию заданий + * + * @param allowDuplicate разрешить повторения + * @param tasks задания, которые передаются в конструктор в Collection (например, {@link LinkedList}) + */ + public PoolTaskGenerator(boolean allowDuplicate, Collection tasks) { + if (tasks == null) { + return; + } + LinkedHashSet uniqueTexts = new LinkedHashSet<>(); + for (Task task : tasks) { + if (task != null && !uniqueTexts.contains(task.getText())) { + this.tasks.add(task); + uniqueTexts.add(task.getText()); + } + } + if (this.tasks.isEmpty()) { + throw new IllegalArgumentException(); + } + isAllowedDuplicate = allowDuplicate; + } + + /** + * @return случайная задача из списка + */ + @Override + public Task generate() { + if (isAllowedDuplicate) { + int numberOfTest = (int) (Math.random() * tasks.size()); + return tasks.stream().skip(numberOfTest).limit(1).findFirst().get(); + } + + if (tasks.isEmpty()) { + throw new EmptyStackException(); + } + int numberOfTest = (int) (Math.random() * tasks.size()); + Task result = tasks.stream().skip(numberOfTest).limit(1).findFirst().get(); + tasks.remove(result); + return result; + } + + @Override + public PoolTaskGenerator clone() { + return new PoolTaskGenerator(isAllowedDuplicate, tasks); + } +} diff --git a/lab-01/src/by/parfen01/quiser/tasks/TextTask.java b/lab-01/src/by/parfen01/quiser/tasks/TextTask.java new file mode 100644 index 0000000..d24375a --- /dev/null +++ b/lab-01/src/by/parfen01/quiser/tasks/TextTask.java @@ -0,0 +1,39 @@ +package by.parfen01.quiser.tasks; + +import by.parfen01.quiser.Result; +import by.parfen01.quiser.Task; +import by.parfen01.quiser.task_generators.PoolTaskGenerator; + + +/** + * Задание с заранее заготовленным текстом. + * Можно использовать {@link PoolTaskGenerator}, чтобы задавать задания такого типа. + */ +public class TextTask implements Task { + private final String text; + private final String answer; + /** + * @param text текст задания + * @param answer ответ на задание + */ + public TextTask(String text, String answer) { + this.text = text; + this.answer = answer; + } + + @Override + public String getText() { + return text; + } + + @Override + public Result validate(String answer) { + if (answer == null) { + throw new NullPointerException(); + } + if (answer.equalsIgnoreCase(this.answer)) { + return Result.OK; + } + return Result.WRONG; + } +} diff --git a/lab-01/src/by/parfen01/quiser/tasks/math_tasks/AbstractMathTask.java b/lab-01/src/by/parfen01/quiser/tasks/math_tasks/AbstractMathTask.java new file mode 100644 index 0000000..7d767e5 --- /dev/null +++ b/lab-01/src/by/parfen01/quiser/tasks/math_tasks/AbstractMathTask.java @@ -0,0 +1,95 @@ +package by.parfen01.quiser.tasks.math_tasks; + +import by.parfen01.quiser.Result; + +import java.security.InvalidParameterException; +import java.util.EnumSet; + +public abstract class AbstractMathTask implements MathTask { + protected final double firstNumber; + protected final double secondNumber; + protected final Operation operation; + protected final int precision; + + public AbstractMathTask(double firstNumber, double secondNumber, int precision, Operation operation) { + this.firstNumber = firstNumber; + this.secondNumber = secondNumber; + this.precision = precision; + this.operation = operation; + } + + public int getPrecision() { + return precision; + } + + public double getPrecisionAsDoubleValue() { + if (operation == Operation.ADDITION || operation == Operation.SUBTRACTION) { + return Math.pow(10, -getPrecision() - 1); + } else { + return Math.pow(10, -2 * getPrecision()); + } + } + + public boolean doubleEqual(double first, double second) { + return Math.abs(first - second) < getPrecisionAsDoubleValue(); + } + + public Result checkAnswer(String answer, String providedAnswer) { + if (answer.equals(providedAnswer)) { + return Result.OK; + } else { + double doubleAnswer = Double.parseDouble(answer); + double doubleProvidedAnswer = Double.parseDouble(providedAnswer); + if (doubleEqual(doubleAnswer, doubleProvidedAnswer)) { + return Result.OK; + } else { + return Result.WRONG; + } + } + } + + public abstract static class Generator implements MathTask.Generator { + protected final double minNumber; + protected final double maxNumber; + + protected final int precision; + protected final EnumSet operations; + + public Generator(double minNumber, double maxNumber, EnumSet operations) { + this(minNumber, maxNumber, 0, operations); + } + + public Generator(double minNumber, double maxNumber, int precision, EnumSet operations) { + this.precision = precision; + this.minNumber = minNumber; + this.maxNumber = maxNumber; + this.operations = operations.clone(); + if (operations.equals(EnumSet.noneOf(MathTask.Operation.class))) { + throw new InvalidParameterException(); + } + if (maxNumber < minNumber) { + throw new IllegalArgumentException(); + } + } + + @Override + public double getMaxNumber() { + return maxNumber; + } + + @Override + public double getMinNumber() { + return minNumber; + } + + @Override + public int getPrecision() { + return precision; + } + + @Override + public EnumSet getOperations() { + return operations; + } + } +} diff --git a/lab-01/src/by/parfen01/quiser/tasks/math_tasks/EquationTask.java b/lab-01/src/by/parfen01/quiser/tasks/math_tasks/EquationTask.java new file mode 100644 index 0000000..ce04c14 --- /dev/null +++ b/lab-01/src/by/parfen01/quiser/tasks/math_tasks/EquationTask.java @@ -0,0 +1,96 @@ +package by.parfen01.quiser.tasks.math_tasks; + +import by.parfen01.quiser.Result; + +import java.util.EnumSet; + +public class EquationTask extends AbstractMathTask { + private final String text; + private final String answer; + public EquationTask(double firstNumber, double secondNumber, int precision, int positionOfX, Operation operation) { + super(firstNumber, secondNumber, precision, operation); + if (positionOfX != 0 && positionOfX != 1) { + throw new IllegalArgumentException(); + } + if (positionOfX == 0) { + text = "The precision of answer must be no less then " + getPrecisionAsDoubleValue() + "\n" + + "X" + Operation.toChar(operation) + firstNumber + "=" + secondNumber; + if (doubleEqual(firstNumber, 0.0) && operation == Operation.DIVISION) { + answer = "invalid operation"; + return; + } + if (doubleEqual(firstNumber, 0.0) && + doubleEqual(secondNumber, 0.0) && + operation == Operation.MULTIPLICATION) { + answer = "no right answer"; + return; + } + answer = String.valueOf(calculate(secondNumber, firstNumber, Operation.getReverseOperation(operation))); + } else { + text = "The precision of answer must be no less then " + getPrecisionAsDoubleValue() + "\n" + + firstNumber + Operation.toChar(operation) + "X" + "=" + secondNumber; + if (doubleEqual(firstNumber, 0) && + doubleEqual(secondNumber, 0.0) && + (operation == Operation.MULTIPLICATION || operation == Operation.DIVISION)) { + answer = "no right answer"; + return; + } + if (operation == Operation.ADDITION || operation == Operation.MULTIPLICATION) { + answer = String.valueOf(calculate(secondNumber, firstNumber, Operation.getReverseOperation(operation))); + } else { + answer = String.valueOf(calculate(firstNumber, secondNumber, operation)); + } + } + } + + @Override + public String getText() { + return text; + } + + @Override + public Result validate(String answer) { + if (answer == null) { + throw new NullPointerException(); + } + if (!answer.matches("^-?[0-9]+(\\.[0-9]+)?$") && + !answer.equalsIgnoreCase("invalid operation") && + !answer.equalsIgnoreCase("no right answer")) { + return Result.INCORRECT_INPUT; + } + + return checkAnswer(this.answer, answer); + } + + public static class Generator extends AbstractMathTask.Generator { + private final int[] possiblePositionsOfX; + /** + * @param minNumber минимальное число + * @param maxNumber максимальное число + */ + + public Generator(double minNumber, + double maxNumber, + EnumSet operations, + int[] possiblePositionsOfX) { + this(minNumber, maxNumber, 0, operations, possiblePositionsOfX); + } + public Generator(double minNumber, + double maxNumber, + int precision, + EnumSet operations, + int[] possiblePositionsOfX) { + super(minNumber, maxNumber, precision, operations); + this.possiblePositionsOfX = possiblePositionsOfX.clone(); + } + + /** + * return задание типа {@link EquationTask} + */ + public EquationTask generate() { + int xPos = possiblePositionsOfX[(int)(Math.random() * possiblePositionsOfX.length)]; + return new EquationTask(getRandomNumberForTask(), getRandomNumberForTask(), + getPrecision(), xPos, getRandomOperationFromSet()); + } + } +} diff --git a/lab-01/src/by/parfen01/quiser/tasks/math_tasks/ExpressionTask.java b/lab-01/src/by/parfen01/quiser/tasks/math_tasks/ExpressionTask.java new file mode 100644 index 0000000..b547c78 --- /dev/null +++ b/lab-01/src/by/parfen01/quiser/tasks/math_tasks/ExpressionTask.java @@ -0,0 +1,64 @@ +package by.parfen01.quiser.tasks.math_tasks; + +import by.parfen01.quiser.Result; + +import java.util.EnumSet; + +public class ExpressionTask extends AbstractMathTask { + private final String text; + private final String answer; + + public ExpressionTask(double firstNumber, double secondNumber, int precision, Operation operation) { + super(firstNumber, secondNumber, precision, operation); + text = "The precision of answer must be no less then " + getPrecisionAsDoubleValue() + "\n" + + firstNumber + Operation.toChar(operation) + secondNumber + "=?"; + if (secondNumber == 0 && operation == Operation.DIVISION) { + answer = "invalid operation"; + return; + } + answer = String.valueOf(calculate(firstNumber, secondNumber, operation)); + } + + @Override + public String getText() { + return text; + } + + @Override + public Result validate(String answer) { + if (answer == null) { + throw new NullPointerException(); + } + if (!answer.matches("^-?[0-9]+(\\.[0-9]+)?$") && !answer.equalsIgnoreCase("invalid operation")) { + return Result.INCORRECT_INPUT; + } + return checkAnswer(answer, this.answer); + } + + public static class Generator extends AbstractMathTask.Generator { + /** + * @param minNumber минимальное число + * @param maxNumber максимальное число + */ + public Generator(double minNumber, + double maxNumber, + int precision, + EnumSet operations) { + super(minNumber, maxNumber, precision, operations); + } + + public Generator(double minNumber, + double maxNumber, + EnumSet operations) { + this(minNumber, maxNumber, 0, operations); + } + + /** + * return задание типа {@link ExpressionTask} + */ + public ExpressionTask generate() { + return new ExpressionTask(getRandomNumberForTask(), getRandomNumberForTask(), + getPrecision(), getRandomOperationFromSet()); + } + } +} diff --git a/lab-01/src/by/parfen01/quiser/tasks/math_tasks/MathTask.java b/lab-01/src/by/parfen01/quiser/tasks/math_tasks/MathTask.java new file mode 100644 index 0000000..83fd602 --- /dev/null +++ b/lab-01/src/by/parfen01/quiser/tasks/math_tasks/MathTask.java @@ -0,0 +1,102 @@ +package by.parfen01.quiser.tasks.math_tasks; + +import by.parfen01.quiser.Task; + +import java.security.InvalidParameterException; +import java.util.EnumSet; + +public interface MathTask extends Task { + enum Operation { + ADDITION, // Операция сложения(+) + SUBTRACTION, // Операция вычитания(-) + MULTIPLICATION, // Операция умножения(*) + DIVISION; // Операция деления(/) + + + static char toChar(Operation operation) { + switch (operation) { + case ADDITION -> { + return '+'; + } + case SUBTRACTION -> { + return '-'; + } + case MULTIPLICATION -> { + return '*'; + } + case DIVISION -> { + return '/'; + } + } + + throw new InvalidParameterException(); + } + + static Operation getReverseOperation(Operation operation) { + switch (operation) { + case ADDITION -> { + return Operation.SUBTRACTION; + } + case SUBTRACTION -> { + return Operation.ADDITION; + } + case MULTIPLICATION -> { + return Operation.DIVISION; + } + case DIVISION -> { + return Operation.MULTIPLICATION; + } + } + + throw new InvalidParameterException(); + } + } + + default double calculate(double firstValue, double secondValue, Operation operation) { + switch (operation) { + case ADDITION -> { + return firstValue + secondValue; + } + case SUBTRACTION -> { + return firstValue - secondValue; + } + case MULTIPLICATION -> { + return firstValue * secondValue; + } + case DIVISION -> { + return firstValue / secondValue; + } + } + + throw new InvalidParameterException(); + } + + interface Generator extends Task.Generator { + double getMinNumber(); // получить минимальное число + double getMaxNumber(); // получить максимальное число + int getPrecision(); + EnumSet getOperations(); + /** + * @return разница между максимальным и минимальным возможным числом + */ + default double getDiffNumber() { + return getMaxNumber() - getMinNumber(); + } + + default double getRandomNumberForTask() { + double result = Math.random() * getDiffNumber() + getMinNumber(); + result = (long)(result * Math.pow(10, getPrecision())) / Math.pow(10, getPrecision()); + return result; + } + + default MathTask.Operation getRandomOperationFromSet() { + int pos = (int)(Math.random() * getOperations().size()); + return getOperations() + .stream() + .skip(pos) + .limit(1) + .findFirst() + .orElse(Operation.ADDITION); + } + } +}