Skip to content
Open

Lab1 #46

Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 8 additions & 8 deletions lab-01/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ enum Result {
* Interface, который описывает одно задание
*/
interface Task {
/**
/*
@return текст задания
*/
String getText();

/**
/*
* Проверяет ответ на задание и возвращает результат
*
* @param answer ответ на задание
Expand All @@ -50,7 +50,7 @@ interface Task {
* Interface, который описывает один генератор заданий
*/
interface TaskGenerator {
/**
/*
* Возвращает задание. При этом новый объект может не создаваться, если класс задания иммутабельный
*
* @return задание
Expand Down Expand Up @@ -158,7 +158,7 @@ public static void main() {

Для начала, получите список всех тестов с помощью статической функции `getQuizMap()` и выведите пользователю сообщение _“Введите название теста...”_. Затем получите объект `Quiz` по этому названию, если он есть, иначе попросите повторить попытку.

Пока тест не завершен, опрашивайте ученика (пользуйтесь методами реализованного вами класса `Quiz`). В конце выведите ему его отметку.
Пока тест на завершен, опрашивайте ученика (пользуйтесь методами реализованного вами класса `Quiz`). В конце выведите ему его отметку.

## Реализация Task и TaskGenerator
>Реализации `Task` следует расположить в пакете `tasks`, а реализации `TaskGenerator` в пакете `task_generators`.
Expand Down Expand Up @@ -393,16 +393,16 @@ class EquationTask extends AbstractMathTask {
```

## ★ Real ExpressionTask и EquationTask
Сделайте, чтобы `ExpressionTaskGenerator` и `EquationTaskGenerator` работал с double вместо int. Также нужно изменить сигнатуру в методах `getMinNumber()`, `getMaxNumnber()`, `getDiffNumber` интерфейса `MathTask`, чтобы они возвращали double.
Сделайте, чтобы `ExpressionTaskGenerator` и `EquationTaskGenerator` работал с double вместо int. Так же нужно изменить сигнатуру в методах `getMinNumber()`, `getMaxNumnber()`, `getDiffNumber` интерфейса `MathTask`, чтобы они возвращали double.

Добавьте в `ExpressionTaskGenerator` и `EquationTaskGenerator` конструктор, который после `maxNumber` принимает еще `int precision` - количество знаков после запятой в генерируемых числах. В других конструкторах считается, что `precision = 0`, т.e. генерируются только целые числа.
Добавьте в `ExpressionTaskGenerator` и `EquationTaskGenerator` конструктор, который после `maxNumber` принимает еще `int accuracy` - количество знаков после запятой в генерируемых числах. В других конструкторах считается, что `accuracy = 0`, т.e. генерируются только целые числа.

>★★ Учитывайте precision еще и в ответе
>★★ Учитывайте accuracy еще и в ответе

## ★★ UML
В каком-нибудь онлайн UML-редакторе (если очень хочется, можно и в пеинте) сделайте схему с участием всех интерфейсов и классов. Это схему нужно приложить в AnyTask к ссылке на github.
## Добавляем исключения
Добавьте исключения везде, где это необходимо. Например, когда у `Quiz` вызывается метод `getMark()`, пока тест не завершен или в конструктор `*MathTask` `maxNumber` передается меньше, чем `minNumber`, в `precision` передается некорректное число и т.д. В случае некорректных `minNumber`, `maxNumber`, `precision` уместно использовать `IllegalArgumentException`, для раннего вызова `getMark()` стоит сделать свое исключение, назвать `QuizNotFinishedException`. Все свои исключения стоит создавать в пакете `exceptions`.
Добавьте исключения везде, где это необходимо. Например, когда у `Quiz` вызывается метод `getMark()`, пока тест на завершен или в конструктор `*MathTask` `maxNumber` передается меньше, чем `minNumber`, в `accuracy` передается некорректное число и т.д. В случае некорректных `minNumber`, `maxNumber`, `accuracy` уместно использовать `IllegalArgumentException`, для раннего вызова `getMark()` стоит сделать свое исключение, назвать `QuizNotFinishedException`. Все свои исключения стоит создавать в пакете `exceptions`.
## Добавляем тесты (Quiz) и проверяем

Теперь добавьте в метод `getQuizMap()` тестов (минимум 5) и тщательно протестируйте приложение. Обязательно используйте все созданные классы, постарайтесь придумать свои `TaskGenerator`. Например, который генерирует задания вида _"У **A** было X яблок, он(она) подарил(а) **B** Y яблок. Сколько яблок осталось у **A**?"_.
11 changes: 11 additions & 0 deletions lab-01/lab-01.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
91 changes: 91 additions & 0 deletions lab-01/src/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import by.kalllegar.quizer.Quiz;
import by.kalllegar.quizer.Result;
import by.kalllegar.quizer.task_generators.GroupTaskGenerator;
import by.kalllegar.quizer.task_generators.PoolTaskGenerator;
import by.kalllegar.quizer.tasks.TextTask;
import by.kalllegar.quizer.tasks.math_tasks.EquationTask;
import by.kalllegar.quizer.tasks.math_tasks.ExpressionTask;
import by.kalllegar.quizer.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<String, Quiz> givenQuizzes = getQuizMap();
System.out.println("enter the name of the test:");
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А как я его узнаю без кода?

Scanner scanner = new Scanner(System.in);
Quiz currentQuiz;
String nameOfQuiz = scanner.nextLine();
while(true) {
if (!givenQuizzes.containsKey(nameOfQuiz)) {
System.out.println("The test was 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 again");
}
}
Formatter formatter = new Formatter();
formatter.format("%.1f", currentQuiz.getMark());
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

почему 1 знака достаточно?

System.out.println("correct answers number: " + currentQuiz.getCorrectAnswerCount());
System.out.println("wrong answers number: " + currentQuiz.getWrongAnswerCount());
System.out.println("incorrect inputs number: " + currentQuiz.getIncorrectInputNumber());
System.out.println("mark: " + formatter);
}

/**
* @return тесты в {@link Map}, где
* ключ - название теста {@link String}
* значение - сам тест {@link Quiz}
*/
static Map<String, Quiz> getQuizMap() {
Map<String, Quiz> result = new TreeMap<>();
//ExpressionTest usage
ExpressionTask.Generator firstTaskGenerator = new ExpressionTask.Generator(
1, 100, 2, EnumSet.allOf(MathTask.Operation.class));
Quiz firstQuiz = new Quiz(firstTaskGenerator, 10);
result.put("ExpressionTest", firstQuiz);
//EquationTest usage
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("EquationTest", secondQuiz);
//TextTest usage
TextTask firstTextTask = new TextTask("what the best array sorting asymptotics?", "O(nlogn)");
TextTask secondTextTask = new TextTask("how many people are in our group?", "26");
TextTask thirdTextTask = new TextTask("the asymptotics with which the insertion into the map is performed?", "O(1)");
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А это точно правда?

TextTask fourthTextTask = new TextTask("what the best array sorting asymptotics?", "O(nlogn)");
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("TextTest", thirdQuiz);
//MixedTest usage
Quiz fourthQuiz = new Quiz(new GroupTaskGenerator(firstTaskGenerator, secondTaskGenerator,
thirdTaskGenerator.clone()), 10);
result.put("GroupTest", fourthQuiz);
Quiz fifthQuiz = new Quiz(fourthTaskGenerator, 3);
result.put("Text Test With Repetition", fifthQuiz);
return result;
}
}
108 changes: 108 additions & 0 deletions lab-01/src/by/kalllegar/quizer/Quiz.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package by.kalllegar.quizer;

import by.kalllegar.quizer.task_generators.TaskGenerator;

/**
* Class, который описывает один тест
*/
public class Quiz {
private final TaskGenerator generator;
private int taskCount;
private int correctAnswerCount = 0;
private int wrongAnswerCount = 0;
private int incorrectInputCount = 0;
Task currentTask;
Task nextTask;
boolean isInputIncorrect = false;

/**
* @param generator генератор заданий
* @param taskCount количество заданий в тесте
*/
public Quiz(TaskGenerator generator, int taskCount) {
this.generator = generator;
this.taskCount = taskCount;
this.nextTask = null;
}

/**
* @return задание, повторный вызов вернет слелующее
* @see Task
*/
public Task nextTask() {
if (isInputIncorrect) {
return currentTask;
}
if (nextTask == null) {
nextTask = generator.generate();
}
Task result = nextTask;
currentTask = nextTask;
if (taskCount > 1) {
nextTask = generator.generate();
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Почему нам необходимо хранить текущую и следующую таску?

}
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 -> {
isInputIncorrect = true;
incorrectInputCount++;
}
case OK -> {
correctAnswerCount++;
taskCount--;
isInputIncorrect = false;
}
case WRONG -> {
wrongAnswerCount++;
taskCount--;
isInputIncorrect = false;
}
}

return result;
}

/**
* @return завершен ли тест
*/
public boolean isFinished() {
return taskCount == 0;
}

/**
* @return количество правильных ответов
*/
public int getCorrectAnswerCount() {
return this.correctAnswerCount;
}

/**
* @return количество неправильных ответов
*/
public int getWrongAnswerCount() {
return this.wrongAnswerCount;
}

/**
* @return количество раз, когда был предоставлен неправильный ввод
*/
public int getIncorrectInputNumber() {
return this.incorrectInputCount;
}

/**
* @return оценка, которая является отношением количества правильных ответов к количеству всех вопросов.
* Оценка выставляется только в конце!
*/
public double getMark() {
return (double) correctAnswerCount / (correctAnswerCount + wrongAnswerCount) * 10;
}
}
10 changes: 10 additions & 0 deletions lab-01/src/by/kalllegar/quizer/Result.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package by.kalllegar.quizer;

/**
* Enum, который описывает результат ответа на задание
*/
public enum Result {
OK, // Получен правильный ответ
WRONG, // Получен неправильный ответ
INCORRECT_INPUT // Некорректный ввод. Например, текст, когда ожидалось число
}
21 changes: 21 additions & 0 deletions lab-01/src/by/kalllegar/quizer/Task.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package by.kalllegar.quizer;

/**
* Interface, который описывает одно задание
*/
public interface Task {
/*
@return текст задания
*/

String getText();

/*
* Проверяет ответ на задание и возвращает результат
*
* @param answer ответ на задание
* @return результат ответа
* @see Result
*/
Result validate(String answer);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package by.kalllegar.quizer.task_generators;

import by.kalllegar.quizer.Task;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;

public class GroupTaskGenerator implements TaskGenerator {
private final ArrayList<TaskGenerator> generators = new ArrayList<>();

/**
* Конструктор с переменным числом аргументов
*
* @param generators генераторы, которые в конструктор передаются через запятую
*/
public GroupTaskGenerator(TaskGenerator... generators) {
if (generators == null) {
throw new NullPointerException();
}
for (var generator : generators) {
if (generator != null) {
this.generators.add(generator);
}
}
if (this.generators.isEmpty()) {
throw new IllegalArgumentException();
}
}

/**
* Конструктор, который принимает коллекцию генераторов
*
* @param generators генераторы, которые передаются в конструктор в Collection (например, {@link ArrayList})
*/
GroupTaskGenerator(Collection<TaskGenerator> generators) {
if (generators == null) {
throw new NullPointerException();
}
this.generators.addAll(generators);
if (this.generators.isEmpty()) {
throw new IllegalArgumentException();
}
}

/**
* @return результат метода generate() случайного генератора из списка.
* Если этот генератор выбросил исключение в методе generate(), выбирается другой.
* Если все генераторы выбрасывают исключение, то и тут выбрасывается исключение.
*/
public Task generate() {
Collections.shuffle(generators);
for (var generator : generators) {
try {
return generator.generate();
} catch (Exception ignore) {
}
}
throw new RuntimeException();
}
}
Loading