Skip to content
Open
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.idea/
out/
*.iml
72 changes: 44 additions & 28 deletions lab-01/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ interface Task {
### TaskGenerator

```java
import by.toharrius.quizer.tasks.Task;

/**
* Interface, который описывает один генератор заданий
*/
Expand All @@ -61,7 +63,10 @@ interface TaskGenerator {
```

### Quiz

```java
import by.toharrius.quizer.tasks.Task;

/**
* Class, который описывает один тест
*/
Expand All @@ -70,54 +75,54 @@ class Quiz {
* @param generator генератор заданий
* @param taskCount количество заданий в тесте
*/
Quiz(TaskGenerator generator, int taskCount) {
Quiz(TaskGenerator generator, int taskCount) {
// ...
}

/**
* @return задание, повторный вызов вернет слелующее
* @see Task
*/
Task nextTask() {
// ...
}

/**
* Предоставить ответ ученика. Если результат {@link Result#INCORRECT_INPUT}, то счетчик неправильных
* ответов не увеличивается, а {@link #nextTask()} в следующий раз вернет тот же самый объект {@link Task}.
*/
Result provideAnswer(String answer) {
// ...
}

/**
* @return завершен ли тест
*/
boolean isFinished() {
// ...
}

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

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

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

/**
* @return оценка, которая является отношением количества правильных ответов к количеству всех вопросов.
* Оценка выставляется только в конце!
Expand All @@ -137,11 +142,11 @@ class Quiz {
/**
* @return тесты в {@link Map}, где
* ключ - название теста {@link String}
* значение - сам тест {@link Quiz}
* значение - сам тест {@link by.toharrius.quizer.Quiz}
*/
static Map<String, Quiz> getQuizMap() {
// ...
}
static Map<String, Quiz> getQuizMap(){
// ...
}
```

### public static void main()
Expand Down Expand Up @@ -237,6 +242,8 @@ class EquationTaskGenerator implements TaskGenerator {
`TaskGenerator`, который позволяет объединить несколько других `TaskGenerator`.

```java
import by.toharrius.quizer.tasks.Task;

class GroupTaskGenerator implements TaskGenerator {
/**
* Конструктор с переменным числом аргументов
Expand Down Expand Up @@ -271,6 +278,8 @@ class GroupTaskGenerator implements TaskGenerator {
`TaskGenerator`, который отдает задания из заранее заготовленного набора.

```java
import by.toharrius.quizer.tasks.Task;

class PoolTaskGenerator implements TaskGenerator {
/**
* Конструктор с переменным числом аргументов
Expand All @@ -279,8 +288,8 @@ class PoolTaskGenerator implements TaskGenerator {
* @param tasks задания, которые в конструктор передаются через запятую
*/
PoolTaskGenerator(
boolean allowDuplicate,
Task... tasks
boolean allowDuplicate,
Task... tasks
) {
// ...
}
Expand All @@ -292,8 +301,8 @@ class PoolTaskGenerator implements TaskGenerator {
* @param tasks задания, которые передаются в конструктор в Collection (например, {@link LinkedList})
*/
PoolTaskGenerator(
boolean allowDuplicate,
Collection<Task> tasks
boolean allowDuplicate,
Collection<Task> tasks
) {
// ...
}
Expand All @@ -310,6 +319,8 @@ class PoolTaskGenerator implements TaskGenerator {
### TextTask

```java
import by.toharrius.quizer.tasks.Task;

/**
* Задание с заранее заготовленным текстом.
* Можно использовать {@link PoolTaskGenerator}, чтобы задавать задания такого типа.
Expand All @@ -320,12 +331,12 @@ class TextTask implements Task {
* @param answer ответ на задание
*/
TextTask(
String text,
String answer
String text,
String answer
) {
// ...
}

// ...
}
```
Expand Down Expand Up @@ -363,37 +374,42 @@ default int getDiffNumber();

## Generator как nested class в Task★

Сейчас вся иерархия `Task` дублируется и для `Generator` в отдельном пакете, это не очень хорошая практика, т. к. за таким кодом сложно следить. Давайте сделаем все `Generator`'ы внутреннеми классами в соответствующих `Task`. Например, вместо `ExpressionTaskGenerator` будет `ExpressionTask.Generator`. При этом `GroupTaskGenerator` и `PoolTaskGenerator` остануться в отдельном пакете, т.к. они не привязаны к конкретному типу задачи.
Сейчас вся иерархия `Task` дублируется и для `Generator` в отдельном пакете, это не очень хорошая практика, т. к. за таким кодом сложно следить. Давайте сделаем все `Generator`'ы внутреннеми классами в соответствующих `Task`. Например, вместо `ExpressionTaskGenerator` будет `ExpressionTask.Generator`. При этом `GroupTaskGenerator` и `PoolTaskGenerator` останутся в отдельном пакете, т.к. они не привязаны к конкретному типу задачи.

```java
interface Task {
interface Generator { /* ... */ }
interface Generator { /* ... */
}
// ...
}

interface MathTask extends Task {
interface Generator extends Task.Generator { /* ... */ }
interface MathTask extends by.toharrius.quizer.tasks.Task {
interface Generator extends by.toharrius.quizer.tasks.Task.Generator { /* ... */
}
// ...
}

abstract class AbstractMathTask implements Task {
static abstract class Generator implements MathTask.Generator { /* ... */ }
abstract class AbstractMathTask implements by.toharrius.quizer.tasks.Task {
static abstract class Generator implements MathTask.Generator { /* ... */
}
// ...
}

class ExpressionTask extends AbstractMathTask {
static class Generator extends AbstractMathTask.Generator { /* ... */ }
static class Generator extends AbstractMathTask.Generator { /* ... */
}
// ...
}

class EquationTask extends AbstractMathTask {
static class Generator extends AbstractMathTask.Generator { /* ... */ }
static class Generator extends AbstractMathTask.Generator { /* ... */
}
// ...
}
```

## ★ 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. генерируются только целые числа.

Expand Down
4 changes: 4 additions & 0 deletions lab-01/by/toharrius/quizer/CopyParameter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package by.toharrius.quizer;
public enum CopyParameter {
FLAG
}
131 changes: 131 additions & 0 deletions lab-01/by/toharrius/quizer/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package by.toharrius.quizer;

import by.toharrius.quizer.task_generators.GroupTaskGenerator;
import by.toharrius.quizer.task_generators.PoolTaskGenerator;
import by.toharrius.quizer.tasks.imminence_tasks.GenerousTask;
import by.toharrius.quizer.tasks.TextTask;
import by.toharrius.quizer.tasks.imminence_tasks.TrickyTask;
import by.toharrius.quizer.tasks.math_tasks.EquationTask;
import by.toharrius.quizer.tasks.math_tasks.ExpressionTask;
import by.toharrius.quizer.tasks.math_tasks.MathOperation;
import org.jetbrains.annotations.NotNull;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;

public class Main {
private static final String helpMessage = "list : view available quizes\n" +
"<test name> : run particular quiz\n" +
"help : view this message\n" +
"exit | quit | stop : terminate session";
private static Map<String, Quiz> quizes;
/**
* @return тесты в {@link Map}, где
* ключ - название теста {@link String}
* значение - сам тест {@link by.toharrius.quizer.Quiz}
*/
private static @NotNull Map<String, Quiz> getQuizMap() {
var quizes = new HashMap<String, Quiz>();
{
var gen = new PoolTaskGenerator(false,
new TextTask("Какая (по слухам) подработка у С*****ча?", "сборщик мусора"),
new TextTask("Как называется человек, убегающий от каннибала?", "фастфуд"),
new TextTask("Какой вид порно не могут снять бомжи?", "домашнее"),
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.

...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

сказали же захардкодить...

new TextTask("Как называется оглушающий удар татара?", "татарстан"));
quizes.put("stupid-questions", new Quiz(gen, 4));
}
{
var gen = new PoolTaskGenerator(true,
new GenerousTask("Каков правильный ответ?"),
new TrickyTask("Это утверждение ложно."));
quizes.put("know-your-luck", new Quiz(gen, 7));
}
{
var gen_eq_add = new EquationTask.Generator(2, 55,
EnumSet.of(MathOperation.ADD));
var gen_eq_42_all = new EquationTask.Generator(42, 42,
EnumSet.allOf(MathOperation.class));
var gen_ex_div = new ExpressionTask.Generator(17, 42,
EnumSet.of(MathOperation.DIVIDE));
var gen_ex_all = new ExpressionTask.Generator(41, 42,
EnumSet.allOf(MathOperation.class));
var gen_eq = new GroupTaskGenerator(gen_eq_42_all, gen_eq_add);
var gen_ex = new GroupTaskGenerator(new ExpressionTask.Generator[]{gen_ex_div, gen_ex_all});
var gen_group = new GroupTaskGenerator(gen_ex, gen_eq,
new EquationTask.Generator(gen_eq_42_all, CopyParameter.FLAG));
quizes.put("tricky-math", new Quiz(gen_group, 5));
}
return quizes;
}

private static String inputLineNormalized() throws IOException {
return consoleReader.readLine().toLowerCase().trim();
}

private static void tryLaunchQuiz(String query) throws IOException {
if (quizes.containsKey(query)) {
System.out.println("Starting quiz \"" + query + "\"!");
Quiz clone;
try {
clone = new Quiz(quizes.get(query));
} catch (Exception e) {
throw new RuntimeException("Unable to clone", e);
}
runProblemSet(clone);
} else {
System.out.println("Sorry, not found. Type \"list\" to see available");
}
}

private static void runProblemSet(Quiz quiz) throws IOException {
while (!quiz.isFinished()) {
var task = quiz.nextTask();
System.out.println("Task " + (quiz.getCurrentTaskIndex() + 1)
+ " out of " + quiz.getTaskCount()
+ ": " + task.getText());
var answer = inputLineNormalized();
System.out.println(switch (quiz.provideAnswer(answer)) {
case OK -> "Nice!";
case WRONG -> "Nope.";
case INCORRECT_INPUT -> "Bad input format. Please, try again.";
});
}
System.out.println("Quiz finished! Your statistics:");
System.out.println("Correct answers: " + quiz.getCorrectAnswerNumber());
System.out.println("Wrong answers: " + quiz.getWrongAnswerNumber());
System.out.println("Total tries: " + quiz.getTotalAnswerNumber());
System.out.println("Final mark: " + quiz.getMark());
}

public static void main(String[] args) throws IOException {
System.out.println(helpMessage);
quizes = getQuizMap();
consoleReader = new BufferedReader(new InputStreamReader(System.in));
boolean interactionFinished = false;
while (!interactionFinished) {
var query = inputLineNormalized();
switch (query) {
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.

Вот если бы у меня не было кода, я бы не узнал об этом никак. Про help & exit точно.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

фикс, выводится хелпа с самого начала

case "list" -> {
if (quizes.isEmpty()) {
System.out.println("There are no quizes now, coming soon ):");
} else {
System.out.println("The total of " + quizes.size() + " quizes are present");
quizes.forEach((name, q) -> System.out.println(name));
}
}
case "help" -> {
System.out.println(helpMessage);
}
case "exit", "quit", "stop", ":q" -> {
interactionFinished = true;
}
default -> tryLaunchQuiz(query);
}
}
}
private static BufferedReader consoleReader;
}
Loading