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);
+ }
+ }
+}