-
Notifications
You must be signed in to change notification settings - Fork 21
Lab1 #43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Lab1 #43
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| package by.alexbiliba.quizer; | ||
|
|
||
| import by.alexbiliba.quizer.tasks.TextTask; | ||
| import by.alexbiliba.quizer.task_generators.GroupTaskGenerator; | ||
| import by.alexbiliba.quizer.task_generators.PoolTaskGenerator; | ||
| import by.alexbiliba.quizer.tasks.math_tasks.EquationTask; | ||
| import by.alexbiliba.quizer.tasks.math_tasks.ExpressionTask; | ||
| import by.alexbiliba.quizer.tasks.math_tasks.MathTask; | ||
|
|
||
| import java.util.*; | ||
| import java.util.concurrent.ThreadLocalRandom; | ||
|
|
||
| public class Main { | ||
| /** | ||
| * @return тесты в {@link Map}, где | ||
| * ключ - название теста {@link String} | ||
| * значение - сам тест {@link Quiz} | ||
| */ | ||
| static Map<String, Quiz> getQuizMap() { | ||
| Map<String, Quiz> quizzes = new HashMap<String, Quiz>(); | ||
|
|
||
| EnumSet<MathTask.Operation> enumSet1; | ||
| enumSet1 = EnumSet.of(MathTask.Operation.SUM, | ||
| MathTask.Operation.DIFFERENCE, | ||
| MathTask.Operation.MULTIPLICATION, | ||
| MathTask.Operation.DIVISION); | ||
| quizzes.put("Only expressions", new Quiz(new ExpressionTask.Generator(0, 1000, 3, enumSet1), 10)); | ||
|
|
||
| EnumSet<MathTask.Operation> enumSet2; | ||
| enumSet2 = EnumSet.of(MathTask.Operation.SUM, | ||
| MathTask.Operation.MULTIPLICATION, | ||
| MathTask.Operation.DIVISION); | ||
| quizzes.put("Only equations", new Quiz(new EquationTask.Generator(0, 2000, 2, enumSet2), 10)); | ||
|
|
||
| EnumSet<MathTask.Operation> enumSet3; | ||
| enumSet3 = EnumSet.of( | ||
| MathTask.Operation.MULTIPLICATION, | ||
| MathTask.Operation.DIVISION); | ||
| quizzes.put("Mixed math tasks", new Quiz(new GroupTaskGenerator(new ExpressionTask.Generator(0, 1000, 5, enumSet3), | ||
| new EquationTask.Generator(0, 1000, 6, enumSet3)), 10)); | ||
|
|
||
| // Заготовка текстовых заданий | ||
| TextTask task1 = new TextTask("Do you love Java?", "Yes"); | ||
| TextTask task2 = new TextTask("Do you love C++?", "Yes"); | ||
| TextTask task3 = new TextTask("Do you love Assembly?", "No....."); | ||
| TextTask task4 = new TextTask("Do you love Python?", "Maybe"); | ||
| TextTask task5 = new TextTask("Do you love WinAPI?", "No"); | ||
| PoolTaskGenerator textTaskGen = new PoolTaskGenerator(false, task1, task2, task3, task4, task5); | ||
|
|
||
| EnumSet<MathTask.Operation> enumSet4; | ||
| enumSet4 = EnumSet.of(MathTask.Operation.SUM, | ||
| MathTask.Operation.DIFFERENCE); | ||
| quizzes.put("Mixed math tasks", new Quiz(new GroupTaskGenerator(textTaskGen, | ||
| new ExpressionTask.Generator(0, 1000, 10, enumSet4), | ||
| new EquationTask.Generator(0, 1000, 11, enumSet4)), 10)); | ||
|
|
||
| quizzes.put("Only text", new Quiz(new PoolTaskGenerator(true, task1, task2, task3, task4, task5), 10)); | ||
|
|
||
| return quizzes; | ||
| } | ||
| public static void main(String[] args) { | ||
| Map<String, Quiz> quizzes = getQuizMap(); | ||
| Scanner input = new Scanner(System.in); | ||
| String quizName = null; | ||
| while (true) { | ||
| System.out.print("Enter the quiz name: "); | ||
| quizName = input.nextLine(); | ||
| if (quizzes.containsKey(quizName)) { | ||
| break; | ||
| } | ||
| System.out.println("There is no quiz with this name!"); | ||
| } | ||
| System.out.flush(); | ||
|
|
||
| Quiz mainQuiz = quizzes.get(quizName); | ||
| System.out.println("Quiz started!"); | ||
| int taskIndex = 1; | ||
| while (!mainQuiz.isFinished()) { | ||
| System.out.print(String.valueOf(taskIndex) + ") "); | ||
| Task currentTask = mainQuiz.nextTask(); | ||
| System.out.println(currentTask.getText()); | ||
| String userAnswer = input.nextLine(); | ||
| mainQuiz.provideAnswer(userAnswer); | ||
| taskIndex++; | ||
| } | ||
| System.out.println("Total:"); | ||
| System.out.println("Correct answers - " + String.valueOf(mainQuiz.AC_number)); | ||
| System.out.println("Wrong answers - " + String.valueOf(mainQuiz.WA_number)); | ||
| System.out.println("Incorrect input - " + String.valueOf(mainQuiz.II_number)); | ||
| System.out.println("Your score: " + mainQuiz.getMark() * 100. + "%"); | ||
| input.close(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| package by.alexbiliba.quizer; | ||
|
|
||
| import java.util.ArrayList; | ||
|
|
||
| /** | ||
| * Class, который описывает один тест | ||
| */ | ||
| class Quiz { | ||
|
|
||
| ArrayList<Task> tasks = new ArrayList<>(); | ||
| int current_task_index = -1; | ||
|
|
||
| int AC_number = 0; | ||
| int WA_number = 0; | ||
| int II_number = 0; | ||
|
|
||
| /** | ||
| * @param generator генератор заданий | ||
| * @param taskCount количество заданий в тесте | ||
| */ | ||
| Quiz(Task.Generator generator, int taskCount) { | ||
| while (taskCount > 0) { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Почему нельзя делать это лениво? |
||
| Task new_task = generator.generate(); | ||
| tasks.add(new_task); | ||
| taskCount--; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @return задание, повторный вызов вернет слелующее | ||
| * @see Task | ||
| */ | ||
| Task nextTask() { | ||
| current_task_index++; | ||
| Task current_task = tasks.get(current_task_index); | ||
| return current_task; | ||
| } | ||
|
|
||
| /** | ||
| * Предоставить ответ ученика. Если результат {@link Result#INCORRECT_INPUT}, то счетчик неправильных | ||
| * ответов не увеличивается, а {@link #nextTask()} в следующий раз вернет тот же самый объект {@link Task}. | ||
| */ | ||
| Result provideAnswer(String answer) { | ||
| Task current_task = tasks.get(current_task_index); | ||
| Result current_result = current_task.validate(answer); | ||
| if (current_result == Result.OK) { | ||
| AC_number++; | ||
| } else if (current_result == Result.WRONG) { | ||
| WA_number++; | ||
| } else { | ||
| II_number++; | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Вряд ли тут соблюдается контракт выше. |
||
| } | ||
| return current_result; | ||
| } | ||
|
|
||
| /** | ||
| * @return завершен ли тест | ||
| */ | ||
| boolean isFinished() { | ||
| return current_task_index >= tasks.size() - 1; | ||
| } | ||
|
|
||
| /** | ||
| * @return количество правильных ответов | ||
| */ | ||
| int getCorrectAnswerNumber() { | ||
| return AC_number; | ||
| } | ||
|
|
||
| /** | ||
| * @return количество неправильных ответов | ||
| */ | ||
| int getWrongAnswerNumber() { | ||
| return WA_number; | ||
| } | ||
|
|
||
| /** | ||
| * @return количество раз, когда был предоставлен неправильный ввод | ||
| */ | ||
| int getIncorrectInputNumber() { | ||
| return II_number; | ||
| } | ||
|
|
||
| /** | ||
| * @return оценка, которая является отношением количества правильных ответов к количеству всех вопросов. | ||
| * Оценка выставляется только в конце! | ||
| */ | ||
| double getMark() { | ||
| return ((double) AC_number) / ((double) tasks.size()); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package by.alexbiliba.quizer; | ||
|
|
||
| /** | ||
| * Enum, который описывает результат ответа на задание | ||
| */ | ||
| public enum Result { | ||
| OK, // Получен правильный ответ | ||
| WRONG, // Получен неправильный ответ | ||
| INCORRECT_INPUT // Некорректный ввод. Например, текст, когда ожидалось число | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package by.alexbiliba.quizer; | ||
|
|
||
| /** | ||
| * Interface, который описывает одно задание | ||
| */ | ||
| public interface Task { | ||
| public interface Generator { | ||
| /* | ||
| * Возвращает задание. При этом новый объект может не создаваться, если класс задания иммутабельный | ||
| * | ||
| * @return задание | ||
| * @see Task | ||
| */ | ||
| Task generate(); | ||
| } | ||
| /* | ||
| @return текст задания | ||
| */ | ||
| String getText(); | ||
| String getAnswer(); | ||
|
|
||
| /* | ||
| * Проверяет ответ на задание и возвращает результат | ||
| * | ||
| * @param answer ответ на задание | ||
| * @return результат ответа | ||
| * @see Result | ||
| */ | ||
| Result validate(String answer); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| package by.alexbiliba.quizer.task_generators; | ||
|
|
||
| import by.alexbiliba.quizer.*; | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Не думаю, что здесь все нужно. |
||
|
|
||
| import java.util.*; | ||
|
|
||
| import java.util.concurrent.ThreadLocalRandom; | ||
|
|
||
| public class GroupTaskGenerator implements Task.Generator { | ||
| Collection<Task.Generator> generators = null; | ||
|
|
||
| /** | ||
| * Конструктор с переменным числом аргументов | ||
| * | ||
| * @param generators генераторы, которые в конструктор передаются через запятую | ||
| */ | ||
| public GroupTaskGenerator(Task.Generator... generators) { | ||
| this.generators = new ArrayList<Task.Generator>(); | ||
| this.generators.addAll(Arrays.asList(generators)); | ||
| } | ||
|
|
||
| /** | ||
| * Конструктор, который принимает коллекцию генераторов | ||
| * | ||
| * @param generators генераторы, которые передаются в конструктор в Collection (например, {@link ArrayList}) | ||
| */ | ||
| GroupTaskGenerator(Collection<Task.Generator> generators) { | ||
| this.generators = generators; | ||
| } | ||
|
|
||
| /** | ||
| * @return результат метода generate() случайного генератора из списка. | ||
| * Если этот генератор выбросил исключение в методе generate(), выбирается другой. | ||
| * Если все генераторы выбрасывают исключение, то и тут выбрасывается исключение. | ||
| */ | ||
| public Task generate() { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Не соблюдается контракт выше. |
||
| int generatorIndex = ThreadLocalRandom.current().nextInt(0, generators.size()); | ||
| int currentGeneratorIndex = 0; | ||
| for (Task.Generator generator : generators) { | ||
| if (generatorIndex == currentGeneratorIndex) { | ||
| return generator.generate(); | ||
| } | ||
| currentGeneratorIndex++; | ||
| } | ||
| return null; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| package by.alexbiliba.quizer.task_generators; | ||
|
|
||
| import by.alexbiliba.quizer.*; | ||
| import java.util.*; | ||
| import java.util.concurrent.ThreadLocalRandom; | ||
|
|
||
| public class PoolTaskGenerator implements Task.Generator { | ||
| boolean allowDuplicate; | ||
| int tasksAllow; | ||
| Collection<Task> tasks = null; | ||
| ArrayList<Boolean> task_used = new ArrayList<>(); | ||
|
|
||
| /** | ||
| * Конструктор с переменным числом аргументов | ||
| * | ||
| * @param allowDuplicate разрешить повторения | ||
| * @param tasks задания, которые в конструктор передаются через запятую | ||
| */ | ||
| public PoolTaskGenerator( | ||
| boolean allowDuplicate, | ||
| Task... tasks | ||
| ) { | ||
| tasksAllow = tasks.length; | ||
| this.allowDuplicate = allowDuplicate; | ||
| this.tasks = new ArrayList<Task>(); | ||
| this.tasks.addAll(Arrays.asList(tasks)); | ||
| for (int i = 0; i < tasks.length; i++) { | ||
| task_used.add(false); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Конструктор, который принимает коллекцию заданий | ||
| * | ||
| * @param allowDuplicate разрешить повторения | ||
| * @param tasks задания, которые передаются в конструктор в Collection (например, {@link LinkedList}) | ||
| */ | ||
| PoolTaskGenerator( | ||
| boolean allowDuplicate, | ||
| Collection<Task> tasks | ||
| ) { | ||
| tasksAllow = tasks.size(); | ||
| this.allowDuplicate = allowDuplicate; | ||
| this.tasks = tasks; | ||
| for (int i = 0; i < tasks.size(); i++) { | ||
| task_used.add(false); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @return случайная задача из списка | ||
| */ | ||
| public Task generate() { | ||
| Task newTask = null; | ||
| int taskIndex = 0; | ||
| if (allowDuplicate) { | ||
| taskIndex = ThreadLocalRandom.current().nextInt(0, tasks.size()); | ||
| } else { | ||
| if (tasksAllow == 0) { | ||
| return null; | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Почему не исключение? |
||
| } | ||
| while (task_used.get(taskIndex)) { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Супер неэффективно. |
||
| taskIndex = ThreadLocalRandom.current().nextInt(0, tasks.size()); | ||
| } | ||
| tasksAllow--; | ||
| task_used.set(taskIndex, true); | ||
| } | ||
|
|
||
| int currentTaskIndex = 0; | ||
| for (Task task : tasks) { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Чтобы достать задачу по известному индексу нам точно надо O(n) дейсвтий? Мб стоит выбрать другую коллекцию? |
||
| if (taskIndex == currentTaskIndex) { | ||
| newTask = task; | ||
| break; | ||
| } | ||
| currentTaskIndex++; | ||
| } | ||
| return newTask; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Для этого предоставляют геттеры и сеттеры и делют их приватными.