From 6e2c5e96431eb82949ff812303135df54db8c7a2 Mon Sep 17 00:00:00 2001 From: Zhang Dongjun Date: Wed, 16 Oct 2019 17:02:50 +0800 Subject: [PATCH 01/10] Implement on main structure of quiz result --- docs/UserGuide.adoc | 2 +- .../logic/commands/quiz/QuizCheckAnswer.java | 21 ++++++- .../java/seedu/address/model/AddressBook.java | 13 +++++ src/main/java/seedu/address/model/Model.java | 8 +++ .../seedu/address/model/ModelManager.java | 17 +++++- .../address/model/ReadOnlyAddressBook.java | 6 ++ .../seedu/address/model/quiz/QuizResult.java | 56 +++++++++++++++++++ .../address/model/quiz/QuizResultList.java | 32 +++++++++++ .../logic/commands/AddNoteCommandTest.java | 12 ++++ 9 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 src/main/java/seedu/address/model/quiz/QuizResult.java create mode 100644 src/main/java/seedu/address/model/quiz/QuizResultList.java diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index b6cb5e01311..81940330e6c 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -191,7 +191,7 @@ Format: `mark` ==== Exit test mode : `quit` -Exits from the test mode. + +Exits from the quiz mode. + Format: `quit` === Get statistics diff --git a/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java b/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java index 642f183ff07..182ffaf94b9 100644 --- a/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java +++ b/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java @@ -2,10 +2,16 @@ import static java.util.Objects.requireNonNull; +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.util.Date; + import seedu.address.logic.commands.Command; import seedu.address.logic.commands.CommandResult; import seedu.address.model.Model; import seedu.address.model.question.Answer; +import seedu.address.model.question.QuestionBody; +import seedu.address.model.quiz.QuizResult; /** * Checks the quiz answer input by users. @@ -18,7 +24,7 @@ public class QuizCheckAnswer extends Command { private final Answer answer; /** - * @param index of the question the answer is mapped to. + * @param index of the question the answer is mapped to. * @param answer of the question input by user. */ public QuizCheckAnswer(int index, Answer answer) { @@ -26,11 +32,22 @@ public QuizCheckAnswer(int index, Answer answer) { this.answer = answer; } + public String getQuizTime() { + Date now = new Date(); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + return simpleDateFormat.format(now); + } + @Override public CommandResult execute(Model model) { requireNonNull(model); - if (model.checkQuizAnswer(index, answer)) { + QuestionBody questionBody = model.getFilteredQuizQuestionList().get(index).getQuestionBody(); + boolean result = model.checkQuizAnswer(index, answer); + QuizResult quizResult = new QuizResult(answer, questionBody, getQuizTime(), result); + + + if (result) { return new CommandResult(ANSWER_CORRECT); } else { return new CommandResult(ANSWER_WRONG); diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java index a9b3d8db7db..b821baa3020 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/seedu/address/model/AddressBook.java @@ -15,6 +15,8 @@ import seedu.address.model.question.Subject; import seedu.address.model.question.UniqueQuestionList; import seedu.address.model.quiz.QuizQuestionList; +import seedu.address.model.quiz.QuizResult; +import seedu.address.model.quiz.QuizResultList; import seedu.address.model.task.Task; import seedu.address.model.task.TaskList; @@ -27,6 +29,7 @@ public class AddressBook implements ReadOnlyAddressBook { private final UniqueNoteList notes; private final UniqueQuestionList questions; private final QuizQuestionList quiz; + private final QuizResultList quizResults; private final TaskList tasks; /* @@ -41,6 +44,7 @@ public class AddressBook implements ReadOnlyAddressBook { notes = new UniqueNoteList(); questions = new UniqueQuestionList(); quiz = new QuizQuestionList(); + quizResults = new QuizResultList(); tasks = new TaskList(); } @@ -213,6 +217,10 @@ public void clearQuizQuestionList() { quiz.clearQuizQuestionList(); } + public void addQuizResult(QuizResult quizResult) { + quizResults.add(quizResult); + } + // util methods @Override @@ -236,6 +244,11 @@ public ObservableList getQuizQuestionList() { return quiz.asUnmodifiableObservableList(); } + @Override + public ObservableList getQuizResultList() { + return quizResults.asUnmodifiableObservableList(); + } + @Override public boolean equals(Object other) { return other == this // short circuit if same object diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 6baf8fcefa8..e3456b217b6 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -11,6 +11,7 @@ import seedu.address.model.question.Difficulty; import seedu.address.model.question.Question; import seedu.address.model.question.Subject; +import seedu.address.model.quiz.QuizResult; import seedu.address.model.task.Task; /** @@ -185,11 +186,18 @@ public interface Model { */ ObservableList getFilteredQuizQuestionList(); + /** + * Returns an unmodifiable view of the filtered quiz result list. + */ + ObservableList getFilteredQuizResultList(); + /** * Checks the an answer input by user and return the boolean value as the result. */ boolean checkQuizAnswer(int index, Answer answer); + void addQuizResult(QuizResult quizResult); + /** * Clears the quiz question list. */ diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 4fac26568f1..858ef06e53f 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -18,6 +18,7 @@ import seedu.address.model.question.Difficulty; import seedu.address.model.question.Question; import seedu.address.model.question.Subject; +import seedu.address.model.quiz.QuizResult; import seedu.address.model.statistics.StatisticsStub; import seedu.address.model.task.Task; @@ -32,6 +33,7 @@ public class ModelManager implements Model { private final FilteredList filteredNotes; private final FilteredList filteredQuestions; private final FilteredList filteredQuizQuestions; + private final FilteredList filteredQuizResults; private final FilteredList filteredTasks; private final StatisticsStub statisticsStub; @@ -49,6 +51,7 @@ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs filteredNotes = new FilteredList<>(this.addressBook.getNoteList()); filteredQuestions = new FilteredList<>(this.addressBook.getQuestionList()); filteredQuizQuestions = new FilteredList<>(this.addressBook.getQuizQuestionList()); + filteredQuizResults = new FilteredList<>(this.addressBook.getQuizResultList()); filteredTasks = new FilteredList<>(this.addressBook.getTaskList()); this.statisticsStub = new StatisticsStub(); } @@ -188,6 +191,13 @@ public boolean checkQuizAnswer(int index, Answer answer) { return addressBook.checkQuizAnswer(index, answer); } + @Override + public void addQuizResult(QuizResult quizResult) { + requireNonNull(quizResult); + + addressBook.addQuizResult(quizResult); + } + @Override public void clearQuizQuestionList() { addressBook.clearQuizQuestionList(); @@ -227,13 +237,18 @@ public void updateFilteredQuestionList(Predicate predicate) { filteredQuestions.setPredicate(predicate); } - //=========== Filtered Question List Accessors ========================================================= + //=========== Filtered Quiz Question List Accessors ========================================================= @Override public ObservableList getFilteredQuizQuestionList() { return filteredQuizQuestions; } + @Override + public ObservableList getFilteredQuizResultList() { + return filteredQuizResults; + } + //=========== Filtered Task List accessors ============================================================= @Override diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java index 908bf86dd76..8b1458d034c 100644 --- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java +++ b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java @@ -5,6 +5,7 @@ import javafx.collections.ObservableList; import seedu.address.model.note.Note; import seedu.address.model.question.Question; +import seedu.address.model.quiz.QuizResult; import seedu.address.model.task.Task; /** @@ -28,6 +29,11 @@ public interface ReadOnlyAddressBook { */ ObservableList getQuizQuestionList(); + /** + * Returns an unmodifiable view of the quiz result list. + */ + ObservableList getQuizResultList(); + /** * Returns an unmodifiable view of the task list. */ diff --git a/src/main/java/seedu/address/model/quiz/QuizResult.java b/src/main/java/seedu/address/model/quiz/QuizResult.java new file mode 100644 index 00000000000..53cbb9da640 --- /dev/null +++ b/src/main/java/seedu/address/model/quiz/QuizResult.java @@ -0,0 +1,56 @@ +package seedu.address.model.quiz; + +import java.time.LocalDateTime; +import java.util.Objects; + +import seedu.address.model.question.Answer; +import seedu.address.model.question.QuestionBody; + +public class QuizResult { + private final Answer answer; + private final QuestionBody questionBody; + private final String quizTime; + private final boolean result; + + public QuizResult(Answer answer, QuestionBody questionBody, String quizTime, boolean result) { + this.answer = answer; + this.questionBody = questionBody; + this.quizTime = quizTime; + this.result = result; + } + + public Answer getAnswer() { + return answer; + } + + public QuestionBody getQuestionBody() { + return questionBody; + } + + public String getQuizTime() { + return quizTime; + } + + public boolean getResult() { + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof QuizResult)) { + return false; + } + + QuizResult otherQuizResult = (QuizResult) other; + return otherQuizResult.getQuestionBody().equals(getQuestionBody()); + } + + @Override + public int hashCode() { + return Objects.hash(answer, questionBody, quizTime, result); + } +} diff --git a/src/main/java/seedu/address/model/quiz/QuizResultList.java b/src/main/java/seedu/address/model/quiz/QuizResultList.java new file mode 100644 index 00000000000..debb712c027 --- /dev/null +++ b/src/main/java/seedu/address/model/quiz/QuizResultList.java @@ -0,0 +1,32 @@ +package seedu.address.model.quiz; + +import static java.util.Objects.requireNonNull; + +import java.util.Iterator; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +public class QuizResultList implements Iterable { + private final ObservableList internalList = FXCollections.observableArrayList(); + private final ObservableList internalUnmodifiableList = + FXCollections.unmodifiableObservableList(internalList); + + public void add(QuizResult quizResult) { + requireNonNull(quizResult); + internalList.add(quizResult); + } + + public QuizResult get(int index) { + return internalList.get(index); + } + + public ObservableList asUnmodifiableObservableList() { + return internalUnmodifiableList; + } + + @Override + public Iterator iterator() { + return internalList.iterator(); + } +} diff --git a/src/test/java/seedu/address/logic/commands/AddNoteCommandTest.java b/src/test/java/seedu/address/logic/commands/AddNoteCommandTest.java index 63a314844e6..9a54c20999b 100644 --- a/src/test/java/seedu/address/logic/commands/AddNoteCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddNoteCommandTest.java @@ -26,6 +26,7 @@ import seedu.address.model.question.Difficulty; import seedu.address.model.question.Question; import seedu.address.model.question.Subject; +import seedu.address.model.quiz.QuizResult; import seedu.address.model.task.Task; import seedu.address.testutil.PersonBuilder; @@ -265,9 +266,20 @@ public ObservableList getFilteredQuizQuestionList() { throw new AssertionError("This method should not be called."); } + @Override public Answer showQuizAnswer(int index) { throw new AssertionError("This method should not be called."); } + + @Override + public void addQuizResult(QuizResult quizResult) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getFilteredQuizResultList() { + throw new AssertionError("This method should not be called."); + } } /** From 97d37bbed45ad6c3e0c3d10cb7020df86f93e865 Mon Sep 17 00:00:00 2001 From: Zhang Dongjun Date: Wed, 16 Oct 2019 22:26:34 +0800 Subject: [PATCH 02/10] Update the storage part of quiz result --- .../java/seedu/address/model/AddressBook.java | 4 ++ .../address/model/quiz/QuizResultList.java | 17 +++++ .../storage/JsonAdaptedQuizResult.java | 71 +++++++++++++++++++ .../storage/JsonSerializableAddressBook.java | 16 ++++- 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 src/main/java/seedu/address/storage/JsonAdaptedQuizResult.java diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java index b821baa3020..0d4315d84ce 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/seedu/address/model/AddressBook.java @@ -221,6 +221,10 @@ public void addQuizResult(QuizResult quizResult) { quizResults.add(quizResult); } + public boolean hasQuizResult(QuizResult quizResult) { + return quizResults.contains(quizResult); + } + // util methods @Override diff --git a/src/main/java/seedu/address/model/quiz/QuizResultList.java b/src/main/java/seedu/address/model/quiz/QuizResultList.java index debb712c027..c41dd6ecaa6 100644 --- a/src/main/java/seedu/address/model/quiz/QuizResultList.java +++ b/src/main/java/seedu/address/model/quiz/QuizResultList.java @@ -7,20 +7,37 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; +/** + * Represents a quiz result list. + */ public class QuizResultList implements Iterable { private final ObservableList internalList = FXCollections.observableArrayList(); private final ObservableList internalUnmodifiableList = FXCollections.unmodifiableObservableList(internalList); + /** + * Adds a quiz result to the result list. The result must be different from all existing ones. + */ public void add(QuizResult quizResult) { requireNonNull(quizResult); internalList.add(quizResult); } + /** + * Returns true if the list contains a quiz result which equals with the given argument. + */ + public boolean contains(QuizResult toCheck) { + requireNonNull(toCheck); + return internalList.stream().anyMatch(toCheck::equals); + } + public QuizResult get(int index) { return internalList.get(index); } + /** + * Returns the backing list as an unmodifiable {@code ObservableList}. + */ public ObservableList asUnmodifiableObservableList() { return internalUnmodifiableList; } diff --git a/src/main/java/seedu/address/storage/JsonAdaptedQuizResult.java b/src/main/java/seedu/address/storage/JsonAdaptedQuizResult.java new file mode 100644 index 00000000000..ffcee1c4b90 --- /dev/null +++ b/src/main/java/seedu/address/storage/JsonAdaptedQuizResult.java @@ -0,0 +1,71 @@ +package seedu.address.storage; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.model.question.Answer; +import seedu.address.model.question.QuestionBody; +import seedu.address.model.quiz.QuizResult; + +/** + * Jackson-friendly version of {@link QuizResult}. + */ +class JsonAdaptedQuizResult { + public static final String MISSING_FIELD_MESSAGE_FORMAT = "Quiz result's %s field is missing!"; + + private final String answer; + private final String questionBody; + private final String quizTime; + private final String result; + + /** + * Constructs a {@code JsonAdaptedQuizResult} with the given quiz results. + */ + @JsonCreator + public JsonAdaptedQuizResult(@JsonProperty("answer") String answer, @JsonProperty("questionBody") String questionBody, + @JsonProperty("quizTime") String quizTime, @JsonProperty("result") String result) { + this.answer = answer; + this.questionBody = questionBody; + this.quizTime = quizTime; + this.result = result; + } + + /** + * Converts a given {@code QuizResult} into this class for Jackson use. + */ + public JsonAdaptedQuizResult(QuizResult source) { + answer = source.getAnswer().toString(); + questionBody = source.getQuestionBody().toString(); + quizTime = source.getQuizTime(); + result = String.valueOf(source.getResult()); + } + + /** + * Converts this Jackson-friendly adapted quiz result object into the model's {@code QuizResult} object. + * + * @throws IllegalValueException if there were any data constraints violated in the adapted quiz result. + */ + public QuizResult toModelType() throws IllegalValueException { + if (answer == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Answer.class.getSimpleName())); + } + final Answer modelAnswer = new Answer(answer); + + if (questionBody == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, QuestionBody.class.getSimpleName())); + } + final QuestionBody modelQuestionBody = new QuestionBody(questionBody); + + if (quizTime == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, "quizTime")); + } + final String modelQuizTime = quizTime; + + if (result == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, "result")); + } + final boolean modelResult = Boolean.parseBoolean(result); + + return new QuizResult(modelAnswer, modelQuestionBody, modelQuizTime, modelResult); + } +} diff --git a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java index 80da2032d18..0e18230c960 100644 --- a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java +++ b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java @@ -12,6 +12,7 @@ import seedu.address.model.AddressBook; import seedu.address.model.ReadOnlyAddressBook; import seedu.address.model.note.Note; +import seedu.address.model.quiz.QuizResult; import seedu.address.model.task.Task; /** @@ -21,18 +22,22 @@ class JsonSerializableAddressBook { public static final String MESSAGE_DUPLICATE_TITLE = "Lecture note list contains duplicate titles."; public static final String MESSAGE_DUPLICATE_TASK = "Task list contains duplicate tasks."; + public static final String MESSAGE_DUPLICATE_RESULT = "Quiz result contains duplicate results."; private final List notes = new ArrayList<>(); private final List tasks = new ArrayList<>(); + private final List quizResults = new ArrayList<>(); /** * Constructs a {@code JsonSerializableAddressBook} with the given lecture notes. */ @JsonCreator public JsonSerializableAddressBook(@JsonProperty("notes") List notes, - @JsonProperty("tasks") List tasks) { + @JsonProperty("tasks") List tasks, + @JsonProperty("quizResults") List quizResults) { this.notes.addAll(notes); this.tasks.addAll(tasks); + this.quizResults.addAll(quizResults); } /** @@ -43,6 +48,7 @@ public JsonSerializableAddressBook(@JsonProperty("notes") List public JsonSerializableAddressBook(ReadOnlyAddressBook source) { notes.addAll(source.getNoteList().stream().map(JsonAdaptedNote::new).collect(Collectors.toList())); tasks.addAll(source.getTaskList().stream().map(JsonAdaptedTaskForNote::new).collect(Collectors.toList())); + quizResults.addAll(source.getQuizResultList().stream().map(JsonAdaptedQuizResult::new).collect(Collectors.toList())); } /** @@ -67,6 +73,14 @@ public AddressBook toModelType() throws IllegalValueException { } addressBook.addTask(task); } + + for (JsonAdaptedQuizResult jsonAdaptedQuizResult : quizResults) { + QuizResult quizResult = jsonAdaptedQuizResult.toModelType(); + if (addressBook.hasQuizResult(quizResult)) { + throw new IllegalValueException(MESSAGE_DUPLICATE_RESULT); + } + addressBook.addQuizResult(quizResult); + } return addressBook; } } From 35644d16276f4501d21b574770edeee4fcf9f81f Mon Sep 17 00:00:00 2001 From: Zhang Dongjun Date: Wed, 16 Oct 2019 23:15:57 +0800 Subject: [PATCH 03/10] Allow quiz to randomly select questions from question list --- docs/UserGuide.adoc | 2 +- .../logic/commands/quiz/QuizCheckAnswer.java | 4 +--- .../logic/parser/quiz/QuizAnswerParser.java | 2 +- .../java/seedu/address/model/AddressBook.java | 22 +++++++++++-------- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 81940330e6c..c57fe822d2a 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -155,7 +155,7 @@ Format: `quiz [n/NUMBER_OF_QUESTIONS] [d/DIFFICULTY] [s/SUBJECT]` ==== Answer the quiz question : `type answer` + Answers the specified question. + -Format: `INDEX : ANSWER` +Format: `INDEX:ANSWER` ==== Change the difficulty: : `change -dif` diff --git a/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java b/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java index 182ffaf94b9..35d27ccfb17 100644 --- a/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java +++ b/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java @@ -3,7 +3,6 @@ import static java.util.Objects.requireNonNull; import java.text.SimpleDateFormat; -import java.time.LocalDateTime; import java.util.Date; import seedu.address.logic.commands.Command; @@ -42,11 +41,10 @@ public String getQuizTime() { public CommandResult execute(Model model) { requireNonNull(model); - QuestionBody questionBody = model.getFilteredQuizQuestionList().get(index).getQuestionBody(); boolean result = model.checkQuizAnswer(index, answer); + QuestionBody questionBody = model.getFilteredQuizQuestionList().get(index).getQuestionBody(); QuizResult quizResult = new QuizResult(answer, questionBody, getQuizTime(), result); - if (result) { return new CommandResult(ANSWER_CORRECT); } else { diff --git a/src/main/java/seedu/address/logic/parser/quiz/QuizAnswerParser.java b/src/main/java/seedu/address/logic/parser/quiz/QuizAnswerParser.java index c3906eb4b45..a51514f5ce3 100644 --- a/src/main/java/seedu/address/logic/parser/quiz/QuizAnswerParser.java +++ b/src/main/java/seedu/address/logic/parser/quiz/QuizAnswerParser.java @@ -13,7 +13,7 @@ */ public class QuizAnswerParser implements Parser { private static final String ANSWER_INVALID_FORMAT = "Invalid answer format! \n%1$s"; - private static final String SHOW_ANSWER_FORMAT = "Format: INDEX : ANSWER\n" + "Example: 1 : abstraction"; + private static final String SHOW_ANSWER_FORMAT = "Format: INDEX:ANSWER\n" + "Example: 1:abstraction"; /** * Used for initial separation of question index and answer. diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java index 0d4315d84ce..2b36f88e5a8 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/seedu/address/model/AddressBook.java @@ -4,6 +4,8 @@ import java.util.List; import java.util.Objects; +import java.util.Random; +import java.util.stream.Collectors; import javafx.collections.FXCollections; import javafx.collections.ObservableList; @@ -176,15 +178,17 @@ public void removeQuestion(Question key) { */ public ObservableList getQuizQuestions(int numOfQuestions, Subject subject, Difficulty difficulty) { ObservableList quizQuestions = FXCollections.observableArrayList(); - - for (int i = 0; i < questions.getSize(); i++) { - Question question = questions.get(i); - if (question.getSubject().equals(subject) && question.getDifficulty().equals(difficulty)) { - quizQuestions.add(question); - } - if (quizQuestions.size() == numOfQuestions) { - break; - } + List filteredQuestions = getQuestionList() + .stream() + .filter(question -> subject.equals(question.getSubject()) && difficulty.equals(question.getDifficulty())) + .collect(Collectors.toList()); + + Random random = new Random(); + for (int i = 0; i < numOfQuestions; i++) { + int randomIndex = random.nextInt(filteredQuestions.size()); + Question question = filteredQuestions.get(randomIndex); + quizQuestions.add(question); + filteredQuestions.remove(randomIndex); } return quizQuestions; } From a7d74ae584e46463ca9f61e5b31ef6b59ec65117 Mon Sep 17 00:00:00 2001 From: Zhang Dongjun Date: Thu, 17 Oct 2019 00:11:30 +0800 Subject: [PATCH 04/10] Fix checkstyle --- src/main/java/seedu/address/model/AddressBook.java | 3 ++- src/main/java/seedu/address/model/quiz/QuizResult.java | 4 +++- .../java/seedu/address/storage/JsonAdaptedQuizResult.java | 7 +++++-- .../seedu/address/storage/JsonSerializableAddressBook.java | 4 +++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java index 2b36f88e5a8..687ba8e0966 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/seedu/address/model/AddressBook.java @@ -180,7 +180,8 @@ public ObservableList getQuizQuestions(int numOfQuestions, Subject sub ObservableList quizQuestions = FXCollections.observableArrayList(); List filteredQuestions = getQuestionList() .stream() - .filter(question -> subject.equals(question.getSubject()) && difficulty.equals(question.getDifficulty())) + .filter(question -> subject.equals(question.getSubject()) + && difficulty.equals(question.getDifficulty())) .collect(Collectors.toList()); Random random = new Random(); diff --git a/src/main/java/seedu/address/model/quiz/QuizResult.java b/src/main/java/seedu/address/model/quiz/QuizResult.java index 53cbb9da640..54ee7f4882f 100644 --- a/src/main/java/seedu/address/model/quiz/QuizResult.java +++ b/src/main/java/seedu/address/model/quiz/QuizResult.java @@ -1,11 +1,13 @@ package seedu.address.model.quiz; -import java.time.LocalDateTime; import java.util.Objects; import seedu.address.model.question.Answer; import seedu.address.model.question.QuestionBody; +/** + * Represents a question. Its answer, questionBody, quizTime and result are guaranteed non-null. + */ public class QuizResult { private final Answer answer; private final QuestionBody questionBody; diff --git a/src/main/java/seedu/address/storage/JsonAdaptedQuizResult.java b/src/main/java/seedu/address/storage/JsonAdaptedQuizResult.java index ffcee1c4b90..888eff09abf 100644 --- a/src/main/java/seedu/address/storage/JsonAdaptedQuizResult.java +++ b/src/main/java/seedu/address/storage/JsonAdaptedQuizResult.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; + import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.model.question.Answer; import seedu.address.model.question.QuestionBody; @@ -22,7 +23,8 @@ class JsonAdaptedQuizResult { * Constructs a {@code JsonAdaptedQuizResult} with the given quiz results. */ @JsonCreator - public JsonAdaptedQuizResult(@JsonProperty("answer") String answer, @JsonProperty("questionBody") String questionBody, + public JsonAdaptedQuizResult(@JsonProperty("answer") String answer, + @JsonProperty("questionBody") String questionBody, @JsonProperty("quizTime") String quizTime, @JsonProperty("result") String result) { this.answer = answer; this.questionBody = questionBody; @@ -52,7 +54,8 @@ public QuizResult toModelType() throws IllegalValueException { final Answer modelAnswer = new Answer(answer); if (questionBody == null) { - throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, QuestionBody.class.getSimpleName())); + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, + QuestionBody.class.getSimpleName())); } final QuestionBody modelQuestionBody = new QuestionBody(questionBody); diff --git a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java index 33c6c8b9258..e0134cc6a33 100644 --- a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java +++ b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRootName; + import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.model.AddressBook; import seedu.address.model.ReadOnlyAddressBook; @@ -53,7 +54,8 @@ public JsonSerializableAddressBook(ReadOnlyAddressBook source) { notes.addAll(source.getNoteList().stream().map(JsonAdaptedNote::new).collect(Collectors.toList())); tasks.addAll(source.getTaskList().stream().map(JsonAdaptedTaskForNote::new).collect(Collectors.toList())); questions.addAll(source.getQuestionList().stream().map(JsonAdaptedQuestion::new).collect(Collectors.toList())); - quizResults.addAll(source.getQuizResultList().stream().map(JsonAdaptedQuizResult::new).collect(Collectors.toList())); + quizResults.addAll(source.getQuizResultList().stream().map(JsonAdaptedQuizResult::new) + .collect(Collectors.toList())); } /** From 3ea4a3ee8652c16902c50fdd6541bfd869433a58 Mon Sep 17 00:00:00 2001 From: Zhang Dongjun Date: Thu, 17 Oct 2019 00:50:53 +0800 Subject: [PATCH 05/10] Add test cases --- .../duplicatePersonAddressBook.json | 7 +- .../invalidPersonAddressBook.json | 6 ++ .../typicalPersonsAddressBook.json | 6 ++ .../seedu/address/model/AddressBookTest.java | 17 ++++- .../address/testutil/QuizResultBuilder.java | 73 +++++++++++++++++++ .../address/testutil/TypicalPersons.java | 4 + 6 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 src/test/java/seedu/address/testutil/QuizResultBuilder.java diff --git a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json index 8fbe96e7993..fa90ddf3ddb 100644 --- a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json +++ b/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json @@ -29,6 +29,11 @@ "answer" : "123", "subject" : "456", "difficulty" : "y" + } ], + "quizResults" : [ { + "answer" : "abc", + "questionBody" : "def", + "quizTime" : "2019/10/10 12:00", + "result" : "true" } ] - } diff --git a/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json index e3ee3f42280..877a4c38bf8 100644 --- a/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json +++ b/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json @@ -21,5 +21,11 @@ "answer" : "abc", "subject" : "def", "difficulty" : "x" + } ], + "quizResults" : [ { + "answer" : "", + "questionBody" : "aaa", + "quizTime" : "", + "result" : "" } ] } diff --git a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json index 015f8ac5d7b..40fab59ea75 100644 --- a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json +++ b/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json @@ -34,5 +34,11 @@ "answer" : "Coupling", "subject" : "CS2103T", "difficulty" : "easy" + } ], + "quizResults" : [ { + "answer" : "Coupling", + "questionBody" : "( ) is a measure of the degree of dependence between components, classes, methods, etc.", + "quizTime" : "2019/10/10 12:00", + "result" : true } ] } diff --git a/src/test/java/seedu/address/model/AddressBookTest.java b/src/test/java/seedu/address/model/AddressBookTest.java index 9863c11a30a..4e732e5c52f 100644 --- a/src/test/java/seedu/address/model/AddressBookTest.java +++ b/src/test/java/seedu/address/model/AddressBookTest.java @@ -7,6 +7,7 @@ import static seedu.address.testutil.Assert.assertThrows; import static seedu.address.testutil.TypicalPersons.ALICE; import static seedu.address.testutil.TypicalPersons.ALICE_QUESTION; +import static seedu.address.testutil.TypicalPersons.ALICE_RESULT; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; import java.time.LocalDate; @@ -18,11 +19,13 @@ import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.annotation.JsonProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import seedu.address.model.note.Note; import seedu.address.model.note.exceptions.DuplicateTitleException; import seedu.address.model.question.Question; +import seedu.address.model.quiz.QuizResult; import seedu.address.model.task.Task; import seedu.address.model.task.TaskForNote; import seedu.address.testutil.PersonBuilder; @@ -60,7 +63,8 @@ public void resetData_withDuplicatePersons_throwsDuplicatePersonException() { List newTasks = Arrays.asList(task); List newQuestions = Arrays.asList(ALICE_QUESTION); - AddressBookStub newData = new AddressBookStub(newNotes, newTasks, newQuestions); + List newQuizResults = Arrays.asList(ALICE_RESULT); + AddressBookStub newData = new AddressBookStub(newNotes, newTasks, newQuestions, newQuizResults); assertThrows(DuplicateTitleException.class, () -> addressBook.resetData(newData)); } @@ -98,15 +102,17 @@ public void getPersonList_modifyList_throwsUnsupportedOperationException() { */ private static class AddressBookStub implements ReadOnlyAddressBook { private final ObservableList notes = FXCollections.observableArrayList(); - private final ObservableList questions = FXCollections.observableArrayList(); private final ObservableList quizQuestions = FXCollections.observableArrayList(); + private final ObservableList quizResults = FXCollections.observableArrayList(); private final ObservableList tasks = FXCollections.observableArrayList(); - AddressBookStub(Collection notes, Collection tasks, Collection questions) { + AddressBookStub(Collection notes, Collection tasks, Collection questions, + Collection quizResults) { this.notes.setAll(notes); this.tasks.setAll(tasks); this.questions.setAll(questions); + this.quizResults.setAll(quizResults); } @Override @@ -124,6 +130,11 @@ public ObservableList getQuizQuestionList() { return quizQuestions; } + @Override + public ObservableList getQuizResultList() { + return quizResults; + } + /** * Returns an unmodifiable view of the task list. */ diff --git a/src/test/java/seedu/address/testutil/QuizResultBuilder.java b/src/test/java/seedu/address/testutil/QuizResultBuilder.java new file mode 100644 index 00000000000..4f4abf49d13 --- /dev/null +++ b/src/test/java/seedu/address/testutil/QuizResultBuilder.java @@ -0,0 +1,73 @@ +package seedu.address.testutil; + +import seedu.address.model.question.Answer; +import seedu.address.model.question.QuestionBody; +import seedu.address.model.quiz.QuizResult; + +/** + * A utility class to help with building Quiz Result objects. + */ +public class QuizResultBuilder { + public static final String DEFAULT_ANSWER = "An answer"; + public static final String DEFAULT_QUESTION_BODY = "A question"; + public static final String DEFAULT_TIME = "2019/10/10 12:00"; + public static final String DEFAULT_RESULT = "true"; + + private Answer answer; + private QuestionBody questionBody; + private String quizTime; + private boolean result; + + public QuizResultBuilder() { + answer = new Answer(DEFAULT_ANSWER); + questionBody = new QuestionBody(DEFAULT_QUESTION_BODY); + quizTime = DEFAULT_TIME; + result = Boolean.parseBoolean(DEFAULT_RESULT); + } + + /** + * Initializes the QuizResultBuilder with the data of {@code quizResultToCopy}. + */ + public QuizResultBuilder(QuizResult quizResultToCopy) { + answer = quizResultToCopy.getAnswer(); + questionBody = quizResultToCopy.getQuestionBody(); + quizTime = quizResultToCopy.getQuizTime(); + result = quizResultToCopy.getResult(); + } + + /** + * Sets the {@code Answer} of the {@code QuizResult} that we are building. + */ + public QuizResultBuilder withAnswer(String answer) { + this.answer = new Answer(answer); + return this; + } + + /** + * Sets the {@code QuestionBody} of the {@code QuizResult} that we are building. + */ + public QuizResultBuilder withQuestionBody(String questionBody) { + this.questionBody = new QuestionBody(questionBody); + return this; + } + + /** + * Sets the {@code QuizTime} of the {@code QuizResult} that we are building. + */ + public QuizResultBuilder withQuizTime(String quizTime) { + this.quizTime = quizTime; + return this; + } + + /** + * Sets the {@code Result} of the {@code QuizResult} that we are building. + */ + public QuizResultBuilder withResult(String result) { + this.result = Boolean.parseBoolean(result); + return this; + } + + public QuizResult build() { + return new QuizResult(answer, questionBody, quizTime, result); + } +} diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java index 307c08289f9..dac840c9433 100644 --- a/src/test/java/seedu/address/testutil/TypicalPersons.java +++ b/src/test/java/seedu/address/testutil/TypicalPersons.java @@ -14,6 +14,7 @@ import seedu.address.model.AddressBook; import seedu.address.model.note.Note; import seedu.address.model.question.Question; +import seedu.address.model.quiz.QuizResult; import seedu.address.model.task.Task; import seedu.address.model.task.TaskForNote; @@ -45,6 +46,9 @@ public class TypicalPersons { + "degree of dependence between components, classes, methods, etc.").withAnswer("Coupling") .withSubject("CS2103T").withDifficulty("easy").build(); + public static final QuizResult ALICE_RESULT = new QuizResultBuilder().withAnswer("Coupling") + .withQuestionBody("( ) is a measure of the degree of dependence between components, classes, methods, " + + "etc.").withQuizTime("2019/10/10 12:00").withResult("true").build(); // Manually added public static final Note HOON = new PersonBuilder().withTitle("Hoon Meier") From 0f591b1b8c09272cd106c2f8d5f614d48e9dca90 Mon Sep 17 00:00:00 2001 From: Zhang Dongjun Date: Thu, 17 Oct 2019 00:56:36 +0800 Subject: [PATCH 06/10] Fix checkstyle --- src/test/java/seedu/address/model/AddressBookTest.java | 2 +- src/test/java/seedu/address/testutil/TypicalPersons.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/seedu/address/model/AddressBookTest.java b/src/test/java/seedu/address/model/AddressBookTest.java index 4e732e5c52f..dc867ea0f67 100644 --- a/src/test/java/seedu/address/model/AddressBookTest.java +++ b/src/test/java/seedu/address/model/AddressBookTest.java @@ -19,9 +19,9 @@ import org.junit.jupiter.api.Test; -import com.fasterxml.jackson.annotation.JsonProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; + import seedu.address.model.note.Note; import seedu.address.model.note.exceptions.DuplicateTitleException; import seedu.address.model.question.Question; diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java index dac840c9433..ca96cdba34a 100644 --- a/src/test/java/seedu/address/testutil/TypicalPersons.java +++ b/src/test/java/seedu/address/testutil/TypicalPersons.java @@ -47,8 +47,8 @@ public class TypicalPersons { .withSubject("CS2103T").withDifficulty("easy").build(); public static final QuizResult ALICE_RESULT = new QuizResultBuilder().withAnswer("Coupling") - .withQuestionBody("( ) is a measure of the degree of dependence between components, classes, methods, " + - "etc.").withQuizTime("2019/10/10 12:00").withResult("true").build(); + .withQuestionBody("( ) is a measure of the degree of dependence between components, classes, methods, " + + "etc.").withQuizTime("2019/10/10 12:00").withResult("true").build(); // Manually added public static final Note HOON = new PersonBuilder().withTitle("Hoon Meier") From c1e1522e630d8cb6f4c25e1449f3ce8d10a80197 Mon Sep 17 00:00:00 2001 From: Zhang Dongjun Date: Thu, 17 Oct 2019 01:22:19 +0800 Subject: [PATCH 07/10] Fix minor bugs --- src/main/java/seedu/address/logic/LogicManager.java | 6 ++++++ .../seedu/address/logic/commands/quiz/QuizCheckAnswer.java | 1 + .../seedu/address/logic/parser/quiz/QuizAnswerParser.java | 2 +- .../java/seedu/address/model/quiz/QuizQuestionList.java | 2 +- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java index 5d34fffc970..c50ad48c47d 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/seedu/address/logic/LogicManager.java @@ -64,6 +64,12 @@ public CommandResult execute(String commandText) throws CommandException, ParseE Command command = quizParser.parseCommand(commandText); commandResult = command.execute(model); + try { + storage.saveAddressBook(model.getAddressBook()); + } catch (IOException ioe) { + throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe); + } + return commandResult; } } diff --git a/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java b/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java index 35d27ccfb17..b641ae9dae7 100644 --- a/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java +++ b/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java @@ -44,6 +44,7 @@ public CommandResult execute(Model model) { boolean result = model.checkQuizAnswer(index, answer); QuestionBody questionBody = model.getFilteredQuizQuestionList().get(index).getQuestionBody(); QuizResult quizResult = new QuizResult(answer, questionBody, getQuizTime(), result); + model.addQuizResult(quizResult); if (result) { return new CommandResult(ANSWER_CORRECT); diff --git a/src/main/java/seedu/address/logic/parser/quiz/QuizAnswerParser.java b/src/main/java/seedu/address/logic/parser/quiz/QuizAnswerParser.java index a51514f5ce3..8fd8c1b1ea3 100644 --- a/src/main/java/seedu/address/logic/parser/quiz/QuizAnswerParser.java +++ b/src/main/java/seedu/address/logic/parser/quiz/QuizAnswerParser.java @@ -32,7 +32,7 @@ public QuizCheckAnswer parse(String userInput) throws ParseException { final String index = matcher.group("index"); final String stringAnswer = matcher.group("answer"); - final int intIndex = Integer.parseInt(index); + final int intIndex = Integer.parseInt(index) - 1; final Answer answer = new Answer(stringAnswer); return new QuizCheckAnswer(intIndex, answer); diff --git a/src/main/java/seedu/address/model/quiz/QuizQuestionList.java b/src/main/java/seedu/address/model/quiz/QuizQuestionList.java index 02b6ec5696b..f2a50bccae5 100644 --- a/src/main/java/seedu/address/model/quiz/QuizQuestionList.java +++ b/src/main/java/seedu/address/model/quiz/QuizQuestionList.java @@ -41,7 +41,7 @@ public Answer showAnswer(int index) { public boolean checkQuizAnswer(int index, Answer answer) { requireAllNonNull(answer); - return get(index - 1).getAnswer().equals(answer); + return get(index).getAnswer().equals(answer); } /** From b427fa2af12417ed1101e123cf26e2894c5d545a Mon Sep 17 00:00:00 2001 From: Zhang Dongjun Date: Thu, 17 Oct 2019 11:02:40 +0800 Subject: [PATCH 08/10] Fix minor bugs --- src/main/java/seedu/address/model/quiz/QuizResult.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/address/model/quiz/QuizResult.java b/src/main/java/seedu/address/model/quiz/QuizResult.java index 54ee7f4882f..d5223ac1e1d 100644 --- a/src/main/java/seedu/address/model/quiz/QuizResult.java +++ b/src/main/java/seedu/address/model/quiz/QuizResult.java @@ -48,7 +48,7 @@ public boolean equals(Object other) { } QuizResult otherQuizResult = (QuizResult) other; - return otherQuizResult.getQuestionBody().equals(getQuestionBody()); + return otherQuizResult.getQuizTime().equals(getQuizTime()); } @Override From b326d5ba4438b9b0c29848e67ac04b68a31b0aca Mon Sep 17 00:00:00 2001 From: Zhang Dongjun Date: Thu, 17 Oct 2019 14:18:46 +0800 Subject: [PATCH 09/10] Fix some bugs and deal with exception during quiz --- docs/UserGuide.adoc | 5 ---- .../seedu/address/commons/core/Messages.java | 1 + .../seedu/address/logic/LogicManager.java | 25 ++++++----------- .../logic/commands/quiz/QuizCheckAnswer.java | 11 +++++++- .../logic/commands/quiz/QuizModeCommand.java | 16 ++++++----- .../commands/quiz/QuizShowAnswerCommand.java | 12 +++++++-- .../parser/quiz/QuizModeCommandParser.java | 13 ++++++--- .../address/logic/parser/quiz/QuizParser.java | 2 +- .../parser/quiz/QuizShowAnswerParser.java | 27 +++++++++++++++++++ 9 files changed, 77 insertions(+), 35 deletions(-) create mode 100644 src/main/java/seedu/address/logic/parser/quiz/QuizShowAnswerParser.java diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 9f71f121b6b..d77c4072b52 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -175,11 +175,6 @@ Format: + Changes the subject of questions. + Format: `change -s SUBJECT [MORE_SUBJECTS]` -==== Skip a question : `skip` - -Skips current question and goto the next one. + -Format: `skip` - ==== Show an answer : `show` Shows an answer for a question with specific index. + diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java index fb893352f73..9a848038f03 100644 --- a/src/main/java/seedu/address/commons/core/Messages.java +++ b/src/main/java/seedu/address/commons/core/Messages.java @@ -10,5 +10,6 @@ public class Messages { public static final String MESSAGE_NOTES_LISTED_OVERVIEW = "%1$d notes listed!"; public static final String MESSAGE_INVALID_QUESTION_DISPLAYED_INDEX = "The question index provided is invalid"; public static final String MESSAGE_QUESTIONS_LISTED_OVERVIEW = "%1$d questions listed!"; + public static final String MESSAGE_INVALID_QUIZ_QUESTION_DISPLAYED_INDEX = "The question index provided is invalid"; public static final String MESSAGE_INVALID_TASK_DISPLAYED_INDEX = "The task index provided is invalid"; } diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java index c50ad48c47d..977523dde92 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/seedu/address/logic/LogicManager.java @@ -43,37 +43,28 @@ public LogicManager(Model model, Storage storage) { @Override public CommandResult execute(String commandText) throws CommandException, ParseException { + CommandResult commandResult; if (!isQuiz) { logger.info("----------------[USER COMMAND][" + commandText + "]"); - CommandResult commandResult; Command command = addressBookParser.parseCommand(commandText); commandResult = command.execute(model); - - try { - storage.saveAddressBook(model.getAddressBook()); - } catch (IOException ioe) { - throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe); - } - - return commandResult; } else { logger.info("----------------[USER INPUT][" + commandText + "]"); - CommandResult commandResult; Command command = quizParser.parseCommand(commandText); commandResult = command.execute(model); + } - try { - storage.saveAddressBook(model.getAddressBook()); - } catch (IOException ioe) { - throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe); - } - - return commandResult; + try { + storage.saveAddressBook(model.getAddressBook()); + } catch (IOException ioe) { + throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe); } + return commandResult; } + @Override public ReadOnlyAddressBook getAddressBook() { return model.getAddressBook(); diff --git a/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java b/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java index b641ae9dae7..e5cd5e43ca0 100644 --- a/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java +++ b/src/main/java/seedu/address/logic/commands/quiz/QuizCheckAnswer.java @@ -4,11 +4,15 @@ import java.text.SimpleDateFormat; import java.util.Date; +import java.util.List; +import seedu.address.commons.core.Messages; import seedu.address.logic.commands.Command; import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; import seedu.address.model.question.Answer; +import seedu.address.model.question.Question; import seedu.address.model.question.QuestionBody; import seedu.address.model.quiz.QuizResult; @@ -38,9 +42,14 @@ public String getQuizTime() { } @Override - public CommandResult execute(Model model) { + public CommandResult execute(Model model) throws CommandException { requireNonNull(model); + List listShownList = model.getFilteredQuizQuestionList(); + if (index >= listShownList.size()) { + throw new CommandException(Messages.MESSAGE_INVALID_QUIZ_QUESTION_DISPLAYED_INDEX); + } + boolean result = model.checkQuizAnswer(index, answer); QuestionBody questionBody = model.getFilteredQuizQuestionList().get(index).getQuestionBody(); QuizResult quizResult = new QuizResult(answer, questionBody, getQuizTime(), result); diff --git a/src/main/java/seedu/address/logic/commands/quiz/QuizModeCommand.java b/src/main/java/seedu/address/logic/commands/quiz/QuizModeCommand.java index cd60ae3b420..d0153e16a48 100644 --- a/src/main/java/seedu/address/logic/commands/quiz/QuizModeCommand.java +++ b/src/main/java/seedu/address/logic/commands/quiz/QuizModeCommand.java @@ -9,6 +9,7 @@ import seedu.address.logic.LogicManager; import seedu.address.logic.commands.Command; import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; import seedu.address.model.question.Difficulty; import seedu.address.model.question.Question; @@ -32,8 +33,7 @@ public class QuizModeCommand extends Command { + PREFIX_SUBJECT + "Maths "; public static final String MESSAGE_SUCCESS = "You have successfully entered quiz mode!"; - public static final String MESSAGE_NOT_ENOUGH_QUESTIONS = "There are not enough questions to do!"; - + public static final String INSUFFICIENT_QUESTION = "There are insufficient questions to do the quiz!"; private final int numOfQuestions; private final Subject subject; @@ -49,12 +49,16 @@ public QuizModeCommand(int numOfQuestions, Subject subject, Difficulty difficult } @Override - public CommandResult execute(Model model) { + public CommandResult execute(Model model) throws CommandException { requireNonNull(model); + try { + ObservableList quizQuestionList = model.getQuizQuestions(numOfQuestions, subject, difficulty); + model.setQuizQuestionList(quizQuestionList); + LogicManager.setIsQuiz(true); + } catch (IllegalArgumentException e) { + throw new CommandException(INSUFFICIENT_QUESTION); + } - ObservableList quizQuestionList = model.getQuizQuestions(numOfQuestions, subject, difficulty); - model.setQuizQuestionList(quizQuestionList); - LogicManager.setIsQuiz(true); return new CommandResult(MESSAGE_SUCCESS, false, false, true, false); } } diff --git a/src/main/java/seedu/address/logic/commands/quiz/QuizShowAnswerCommand.java b/src/main/java/seedu/address/logic/commands/quiz/QuizShowAnswerCommand.java index 7cb6fd62469..bc587cbdd80 100644 --- a/src/main/java/seedu/address/logic/commands/quiz/QuizShowAnswerCommand.java +++ b/src/main/java/seedu/address/logic/commands/quiz/QuizShowAnswerCommand.java @@ -4,6 +4,8 @@ import seedu.address.logic.commands.Command; import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.Model; import seedu.address.model.question.Answer; @@ -14,6 +16,7 @@ public class QuizShowAnswerCommand extends Command { public static final String COMMAND_WORD = "show"; public static final String MESSAGE_SUCCESS = "The answer is: %1$s"; + public static final String INDEX_EXCEED_RANGE = "The index input is out of the range of quiz questions!"; private final int index; @@ -22,10 +25,15 @@ public QuizShowAnswerCommand(int index) { } @Override - public CommandResult execute(Model model) { + public CommandResult execute(Model model) throws CommandException { requireNonNull(model); - Answer answer = model.showQuizAnswer(index); + Answer answer; + try { + answer = model.showQuizAnswer(index); + } catch (IndexOutOfBoundsException e) { + throw new CommandException(INDEX_EXCEED_RANGE); + } return new CommandResult(String.format(MESSAGE_SUCCESS, answer.toString())); } } diff --git a/src/main/java/seedu/address/logic/parser/quiz/QuizModeCommandParser.java b/src/main/java/seedu/address/logic/parser/quiz/QuizModeCommandParser.java index 0d7f68acce0..34aac6eea3d 100644 --- a/src/main/java/seedu/address/logic/parser/quiz/QuizModeCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/quiz/QuizModeCommandParser.java @@ -22,6 +22,7 @@ * Parses input arguments and creates a new QuizModeCommand object. */ public class QuizModeCommandParser implements Parser { + private static final String INVALID_NUMBER = "The number input should be a positive integer!"; /** * Parses the given {@code String} of arguments in the context of the QuizModeCommand @@ -35,15 +36,21 @@ public QuizModeCommand parse(String args) throws ParseException { ArgumentTokenizer.tokenize(args, PREFIX_NUMBER, PREFIX_DIFFICULTY, PREFIX_SUBJECT); int numOfQuestions; + Subject subject; + Difficulty difficulty; if (!arePrefixesPresent(argMultimap, PREFIX_DIFFICULTY, PREFIX_SUBJECT) || (!argMultimap.getPreamble().isEmpty())) { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, QuizModeCommand.MESSAGE_USAGE)); } - numOfQuestions = ParserUtil.parseNumber(argMultimap.getValue(PREFIX_NUMBER).get()); - Subject subject = ParserUtil.parseSubject(argMultimap.getValue(PREFIX_SUBJECT).get()); - Difficulty difficulty = ParserUtil.parseDifficulty(argMultimap.getValue(PREFIX_DIFFICULTY).get()); + try { + numOfQuestions = ParserUtil.parseNumber(argMultimap.getValue(PREFIX_NUMBER).get()); + subject = ParserUtil.parseSubject(argMultimap.getValue(PREFIX_SUBJECT).get()); + difficulty = ParserUtil.parseDifficulty(argMultimap.getValue(PREFIX_DIFFICULTY).get()); + } catch (NumberFormatException e) { + throw new ParseException(INVALID_NUMBER); + } return new QuizModeCommand(numOfQuestions, subject, difficulty); } diff --git a/src/main/java/seedu/address/logic/parser/quiz/QuizParser.java b/src/main/java/seedu/address/logic/parser/quiz/QuizParser.java index baa1578a4a8..b73b52d7792 100644 --- a/src/main/java/seedu/address/logic/parser/quiz/QuizParser.java +++ b/src/main/java/seedu/address/logic/parser/quiz/QuizParser.java @@ -41,7 +41,7 @@ public Command parseCommand(String userInput) throws ParseException { return new QuitQuizModeCommand(); case QuizShowAnswerCommand.COMMAND_WORD: - return new QuizShowAnswerCommand(Integer.parseInt(arguments)); + return new QuizShowAnswerParser().parse(arguments.trim()); default: return new QuizAnswerParser().parse(userInput); diff --git a/src/main/java/seedu/address/logic/parser/quiz/QuizShowAnswerParser.java b/src/main/java/seedu/address/logic/parser/quiz/QuizShowAnswerParser.java new file mode 100644 index 00000000000..6b3b300de2d --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/quiz/QuizShowAnswerParser.java @@ -0,0 +1,27 @@ +package seedu.address.logic.parser.quiz; + +import static java.util.Objects.requireNonNull; + +import seedu.address.logic.commands.quiz.QuizShowAnswerCommand; +import seedu.address.logic.parser.Parser; +import seedu.address.logic.parser.exceptions.ParseException; + +/** + * Parses input arguments and creates a new QuizShowAnswerCommand object. + */ +public class QuizShowAnswerParser implements Parser { + public static final String INVALID_INDEX = "The index input should be a positive integer!"; + + private int index; + + public QuizShowAnswerCommand parse(String args) throws ParseException { + requireNonNull(args); + + try { + index = Integer.parseInt(args) - 1; + } catch (NumberFormatException e) { + throw new ParseException(INVALID_INDEX); + } + return new QuizShowAnswerCommand(index); + } +} From 456ee946a6f9a246431211643a48e752aee5c01f Mon Sep 17 00:00:00 2001 From: Zhang Dongjun Date: Thu, 17 Oct 2019 14:24:03 +0800 Subject: [PATCH 10/10] Fix checkstyle --- .../address/logic/commands/quiz/QuizShowAnswerCommand.java | 1 - .../seedu/address/logic/parser/quiz/QuizShowAnswerParser.java | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/address/logic/commands/quiz/QuizShowAnswerCommand.java b/src/main/java/seedu/address/logic/commands/quiz/QuizShowAnswerCommand.java index bc587cbdd80..465dd18fe1a 100644 --- a/src/main/java/seedu/address/logic/commands/quiz/QuizShowAnswerCommand.java +++ b/src/main/java/seedu/address/logic/commands/quiz/QuizShowAnswerCommand.java @@ -5,7 +5,6 @@ import seedu.address.logic.commands.Command; import seedu.address.logic.commands.CommandResult; import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.Model; import seedu.address.model.question.Answer; diff --git a/src/main/java/seedu/address/logic/parser/quiz/QuizShowAnswerParser.java b/src/main/java/seedu/address/logic/parser/quiz/QuizShowAnswerParser.java index 6b3b300de2d..d16305cc8c8 100644 --- a/src/main/java/seedu/address/logic/parser/quiz/QuizShowAnswerParser.java +++ b/src/main/java/seedu/address/logic/parser/quiz/QuizShowAnswerParser.java @@ -14,6 +14,10 @@ public class QuizShowAnswerParser implements Parser { private int index; + /** + * Parses the given {@code String} of user input in the context of showing answer + * and returns an QuizShowAnswerCommand object for execution. + */ public QuizShowAnswerCommand parse(String args) throws ParseException { requireNonNull(args);