diff --git a/LICENSE b/LICENSE
index 39b3478982c..3c55efcccd5 100644
--- a/LICENSE
+++ b/LICENSE
@@ -2,11 +2,11 @@ MIT License
Copyright (c) 2016 Software Engineering Education - FOSS Resources
-Permission is hereby granted, free of charge, to any person obtaining a copy
+Permission is hereby granted, free of charge, to any qAndA obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
+copies of the Software, and to permit qAndAs to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
diff --git a/README.md b/README.md
index 13f5c77403f..c5c65337c97 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,17 @@
-[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/se-edu/addressbook-level3/actions)
+[![CI Status](https://github.com/AY2021S1-CS2103T-W15-1/tp/workflows/Java%20CI/badge.svg)](https://github.com/AY2021S1-CS2103T-W15-1/tp/actions)
+
+# Medmoriser
![Ui](docs/images/Ui.png)
-* This is **a sample project for Software Engineering (SE) students**.
- Example usages:
- * as a starting point of a course project (as opposed to writing everything from scratch)
- * as a case study
-* The project simulates an ongoing software project for a desktop application (called _AddressBook_) used for managing contact details.
- * It is **written in OOP fashion**. It provides a **reasonably well-written** code base **bigger** (around 6 KLoC) than what students usually write in beginner-level SE modules, without being overwhelmingly big.
- * It comes with a **reasonable level of user and developer documentation**.
-* It is named `AddressBook Level 3` (`AB3` for short) because it was initially created as a part of a series of `AddressBook` projects (`Level 1`, `Level 2`, `Level 3` ...).
-* For the detailed documentation of this project, see the **[Address Book Product Website](https://se-education.org/addressbook-level3)**.
-* This project is a **part of the se-education.org** initiative. If you would like to contribute code to this project, see [se-education.org](https://se-education.org#https://se-education.org/#contributing) for more info.
+**Medmoriser** is a desktop app, optimized for the CLI, which helps medical students memorise and revise their content. It aids users in practising active recall to improve their retention of key information.
+
+## Site Map
+- [User Guide](https://ay2021s1-cs2103t-w15-1.github.io/tp/UserGuide.html)
+- [Developer Guide](https://ay2021s1-cs2103t-w15-1.github.io/tp/DeveloperGuide.html)
+- [About Us](https://ay2021s1-cs2103t-w15-1.github.io/tp/AboutUs.html)
+
+## Acknowledgements
+
+This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative](https://se-education.org).
+
diff --git a/build.gradle b/build.gradle
index be2d2905dde..8b42e42e91c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,7 +6,7 @@ plugins {
id 'jacoco'
}
-mainClassName = 'seedu.address.Main'
+mainClassName = 'seedu.medmoriser.Main'
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
@@ -25,6 +25,10 @@ test {
finalizedBy jacocoTestReport
}
+run {
+ enableAssertions = false
+}
+
task coverage(type: JacocoReport) {
sourceDirectories.from files(sourceSets.main.allSource.srcDirs)
classDirectories.from files(sourceSets.main.output)
@@ -66,7 +70,11 @@ dependencies {
}
shadowJar {
- archiveName = 'addressbook.jar'
+ archiveFileName = 'medmoriser.jar'
+}
+
+run {
+ enableAssertions = true
}
defaultTasks 'clean', 'test'
diff --git a/docs/AboutUs.md b/docs/AboutUs.md
index 1c9514e966a..600b9e0b4c4 100644
--- a/docs/AboutUs.md
+++ b/docs/AboutUs.md
@@ -5,55 +5,59 @@ title: About Us
We are a team based in the [School of Computing, National University of Singapore](http://www.comp.nus.edu.sg).
-You can reach us at the email `seer[at]comp.nus.edu.sg`
+You can find us on [Github](https://github.com/AY2021S1-CS2103T-W15-1)
## Project team
-### John Doe
+### Kim Hyeongcheol (Danny)
-
+
-[[homepage](http://www.comp.nus.edu.sg/~damithch)]
-[[github](https://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](https://github.com/bluesky0911)]
* Role: Project Advisor
-### Jane Doe
+### Yong Ming Yang
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](https://github.com/yongmingyang)]
* Role: Team Lead
-* Responsibilities: UI
+* Responsibilities: Deliverables & deadlines, Scheduling & tracking
-### Johnny Doe
+### Jonathan Foo Chee Yong
-
+
-[[github](http://github.com/johndoe)] [[portfolio](team/johndoe.md)]
+[[github](http://github.com/jonfoocy)]
* Role: Developer
-* Responsibilities: Data
+* Responsibilities: Integration
-### Jean Doe
+### Cheng Jiyuqing
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](https://github.com/ChengJiyuqing)]
* Role: Developer
-* Responsibilities: Dev Ops + Threading
+* Responsibilities: Testing
-### James Doe
+### Tan Rui En Joshua
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](https://github.com/joshruien)]
* Role: Developer
-* Responsibilities: UI
+* Responsibilities: Documentation
+
+### Teng Jian Ling
+
+
+
+[[github](https://github.com/tengjianling)]
+
+* Role: Developer
+* Responsibilities: Code Quality
diff --git a/docs/DevOps.md b/docs/DevOps.md
index 4414eea3344..aa42e5872cf 100644
--- a/docs/DevOps.md
+++ b/docs/DevOps.md
@@ -73,7 +73,7 @@ Any warnings or errors will be printed out to the console.
Here are the steps to create a new release.
-1. Update the version number in [`MainApp.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/MainApp.java).
+1. Update the version number in [`MainApp.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/answer/MainApp.java).
1. Generate a fat JAR file using Gradle (i.e., `gradlew shadow`).
1. Tag the repo with the version number. e.g. `v0.1`
1. [Create a new release using GitHub](https://help.github.com/articles/creating-releases/). Upload the JAR file you created.
diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md
index 4829fe43011..2d101185072 100644
--- a/docs/DeveloperGuide.md
+++ b/docs/DeveloperGuide.md
@@ -2,9 +2,9 @@
layout: page
title: Developer Guide
---
-* Table of Contents
+* Table of Contents:
{:toc}
-
+
--------------------------------------------------------------------------------------------------------------------
## **Setting up, getting started**
@@ -23,11 +23,11 @@ The ***Architecture Diagram*** given above explains the high-level design of the
-:bulb: **Tip:** The `.puml` files used to create diagrams in this document can be found in the [diagrams](https://github.com/se-edu/addressbook-level3/tree/master/docs/diagrams/) folder. Refer to the [_PlantUML Tutorial_ at se-edu/guides](https://se-education.org/guides/tutorials/plantUml.html) to learn how to create and edit diagrams.
+:bulb: **Tip:** The `.puml` files used to create diagrams in this document can be found in the [diagrams](https://github.com/AY2021S1-CS2103T-W15-1/tp/tree/master/docs/diagrams) folder. Refer to the [_PlantUML Tutorial_ at se-edu/guides](https://se-education.org/guides/tutorials/plantUml.html) to learn how to create and edit diagrams.
-**`Main`** has two classes called [`Main`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/Main.java) and [`MainApp`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/MainApp.java). It is responsible for,
+**`Main`** has two classes called [`Main`](https://github.com/AY2021S1-CS2103T-W15-1/tp/blob/master/src/main/java/seedu/medmoriser/Main.java) and [`MainApp`](https://github.com/AY2021S1-CS2103T-W15-1/tp/blob/master/src/main/java/seedu/medmoriser/MainApp.java). It is responsible for:
* At app launch: Initializes the components in the correct sequence, and connects them up with each other.
* At shut down: Shuts down the components and invokes cleanup methods where necessary.
@@ -62,11 +62,11 @@ The sections below give more details of each component.
![Structure of the UI Component](images/UiClassDiagram.png)
**API** :
-[`Ui.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/ui/Ui.java)
+[`Ui.java`](https://github.com/AY2021S1-CS2103T-W15-1/tp/blob/master/src/main/java/seedu/medmoriser/ui/Ui.java)
-The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `StatusBarFooter` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class.
+The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `QAndAListPanel`, `StatusBarFooter` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class.
-The `UI` component uses JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the [`MainWindow`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/ui/MainWindow.java) is specified in [`MainWindow.fxml`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/resources/view/MainWindow.fxml)
+The `UI` component uses JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the [`MainWindow`](https://github.com/AY2021S1-CS2103T-W15-1/tp/blob/master/src/main/java/seedu/medmoriser/ui/MainWindow.java) is specified in [`MainWindow.fxml`](https://github.com/AY2021S1-CS2103T-W15-1/tp/blob/master/src/main/resources/view/MainWindow.fxml)
The `UI` component,
@@ -78,11 +78,11 @@ The `UI` component,
![Structure of the Logic Component](images/LogicClassDiagram.png)
**API** :
-[`Logic.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/logic/Logic.java)
+[`Logic.java`](https://github.com/AY2021S1-CS2103T-W15-1/tp/blob/master/src/main/java/seedu/medmoriser/logic/Logic.java)
-1. `Logic` uses the `AddressBookParser` class to parse the user command.
+1. `Logic` uses the `MedmoriserParser` class to parse the user command.
1. This results in a `Command` object which is executed by the `LogicManager`.
-1. The command execution can affect the `Model` (e.g. adding a person).
+1. The command execution can affect the `Model` (e.g. adding a qAndA).
1. The result of the command execution is encapsulated as a `CommandResult` object which is passed back to the `Ui`.
1. In addition, the `CommandResult` object can also instruct the `Ui` to perform certain actions, such as displaying help to the user.
@@ -97,17 +97,17 @@ Given below is the Sequence Diagram for interactions within the `Logic` componen
![Structure of the Model Component](images/ModelClassDiagram.png)
-**API** : [`Model.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/model/Model.java)
+**API** : [`Model.java`](https://github.com/AY2021S1-CS2103T-W15-1/tp/blob/master/src/main/java/seedu/medmoriser/model/Model.java)
The `Model`,
* stores a `UserPref` object that represents the user’s preferences.
-* stores the address book data.
+* stores the answer book data.
* exposes an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.
* does not depend on any of the other three components.
-
:information_source: **Note:** An alternative (arguably, a more OOP) model is given below. It has a `Tag` list in the `AddressBook`, which `Person` references. This allows `AddressBook` to only require one `Tag` object per unique `Tag`, instead of each `Person` needing their own `Tag` object.
+
:information_source: **Note:** An alternative (arguably, a more OOP) model is given below. It has a `Tag` list in the `Medmoriser`, which `QAndA` references. This allows `Medmoriser` to only require one `Tag` object per unique `Tag`, instead of each `QAndA` needing their own `Tag` object.
![BetterModelClassDiagram](images/BetterModelClassDiagram.png)
@@ -117,15 +117,15 @@ The `Model`,
![Structure of the Storage Component](images/StorageClassDiagram.png)
-**API** : [`Storage.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/storage/Storage.java)
+**API** : [`Storage.java`](https://github.com/AY2021S1-CS2103T-W15-1/tp/blob/master/src/main/java/seedu/medmoriser/storage/Storage.java)
The `Storage` component,
* can save `UserPref` objects in json format and read it back.
-* can save the address book data in json format and read it back.
+* can save the answer book data in json format and read it back.
### Common classes
-Classes used by multiple components are in the `seedu.addressbook.commons` package.
+Classes used by multiple components are in the `seedu.medmoriser.commons` package.
--------------------------------------------------------------------------------------------------------------------
@@ -133,90 +133,136 @@ Classes used by multiple components are in the `seedu.addressbook.commons` packa
This section describes some noteworthy details on how certain features are implemented.
-### \[Proposed\] Undo/redo feature
+### Add Feature (Cheng Jiyuqing)
-#### Proposed Implementation
+#### Implementation
-The proposed undo/redo mechanism is facilitated by `VersionedAddressBook`. It extends `AddressBook` with an undo/redo history, stored internally as an `addressBookStateList` and `currentStatePointer`. Additionally, it implements the following operations:
+This portion describes the implementation of the add feature which allows the user to add new QAndAs with the question, answer and tags(optional).
-* `VersionedAddressBook#commit()` — Saves the current address book state in its history.
-* `VersionedAddressBook#undo()` — Restores the previous address book state from its history.
-* `VersionedAddressBook#redo()` — Restores a previously undone address book state from its history.
+Explanation of the diagrams:
-These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively.
+1. As the user parses the add command through the `UI`, the `MedmoriserParser` identifies this as a `AddCommand` and passes the user input to the `AddCommandParser`.
+2. The `AddCommandParser` ensures the input is of correct format and identifies the input for question, answer and tag(s).
+3. The `AddCommandParser` then creates a new QAndA object, and passes it to a new `AddCommand` object to handle the rest of the job.
+4. The `AddCommand` object will then add the new QAndA to model, and return a `CommandResult` containing a message to users indicating success in adding a new QAndA.
+5. `UI` will also be updated accordingly.
-Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
+The following sequence diagram (Fig 1.1) shows how the add operation works:
-Step 1. The user launches the application for the first time. The `VersionedAddressBook` will be initialized with the initial address book state, and the `currentStatePointer` pointing to that single address book state.
+(Figure 1.1: Add Command Sequence Diagram)
+![AddSequenceDiagram](images/AddSequenceDiagram.png)
-![UndoRedoState0](images/UndoRedoState0.png)
+### Find feature (Ming Yang)
-Step 2. The user executes `delete 5` command to delete the 5th person in the address book. The `delete` command calls `Model#commitAddressBook()`, causing the modified state of the address book after the `delete 5` command executes to be saved in the `addressBookStateList`, and the `currentStatePointer` is shifted to the newly inserted address book state.
+#### Implementation
-![UndoRedoState1](images/UndoRedoState1.png)
+This portion describes the implementation of the find feature which allows the user to find QAndA sets based on the question, answer or tags.
-Step 3. The user executes `add n/David …` to add a new person. The `add` command also calls `Model#commitAddressBook()`, causing another modified address book state to be saved into the `addressBookStateList`.
+Explanation of the diagrams:
+1. As the user parses the find command through the `UI`, the `MedmoriserParser` identifies this as a `FindCommand` and passes the user input to the `FindCommandParser`.
+2. The `FindCommandParser` identifies the type of find command, such as find tag/question/answer.
+3. A `FindCommand` with the respective predicate such as `TagContainsKeywordPredicate` is created and returned to the `LogicManager`.
+4. The filtered list of question will be displayed on the `UI`.
-![UndoRedoState2](images/UndoRedoState2.png)
+The following sequence diagram (Fig 1.2) shows how the find operation works:
-
:information_source: **Note:** If a command fails its execution, it will not call `Model#commitAddressBook()`, so the address book state will not be saved into the `addressBookStateList`.
+(Figure 1.2: Find Command Sequence Diagram)
+![UndoSequenceDiagram](images/FindSequenceDiagram.png)
-
+The activity diagram below (Fig 1.3) shows the activity flow of the find feature.
-Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing the `undo` command. The `undo` command will call `Model#undoAddressBook()`, which will shift the `currentStatePointer` once to the left, pointing it to the previous address book state, and restores the address book to that state.
+(Figure 1.3: Find Command Activity Diagram)
+![FindActivityDiagram](images/FindActivityDiagram.png)
-![UndoRedoState3](images/UndoRedoState3.png)
+### Quiz Feature (Joshua Tan)
-
:information_source: **Note:** If the `currentStatePointer` is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. The `undo` command uses `Model#canUndoAddressBook()` to check if this is the case. If so, it will return an error to the user rather
-than attempting to perform the undo.
+#### Implementation
-
+This feature allows the user to quiz himself/herself.
-The following sequence diagram shows how the undo operation works:
+The flow of the execution is as follows:
-![UndoSequenceDiagram](images/UndoSequenceDiagram.png)
+1. User enters the input for quiz (eg. `quiz t/Immune System`)
-
:information_source: **Note:** The lifeline for `UndoCommand` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
+2. The `LogicManager` executes the command, the command is then parsed by `MedmoriserParser` and the command is
+identified as a `QuizCommand`. The command is then parsed by `QuizCommandParser`.
-
+3. `QuizCommandParser` identifies the type of quiz command. (eg. quiz t/)
-The `redo` command does the opposite — it calls `Model#redoAddressBook()`, which shifts the `currentStatePointer` once to the right, pointing to the previously undone state, and restores the address book to that state.
+4. A `QuizCommand` with the respective predicate, in this case `TagContainsKeywordPredicate` is created and returned to `LogicManager`
-
:information_source: **Note:** If the `currentStatePointer` is at index `addressBookStateList.size() - 1`, pointing to the latest address book state, then there are no undone AddressBook states to restore. The `redo` command uses `Model#canRedoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
+5. The `QuizCard` will be displayed on the `UI`.
-
+The sequence diagram below (Fig 1.4) shows the interactions between the Logic and model components for the quiz command.
+
+(Figure 1.4: Quiz Command Sequence Diagram)
+![QuizSequenceDiagram](images/QuizSequenceDiagram.png)
+
+The diagram below (Fig 1.5) shows the activity diagram flow for the quiz command
+
+(Figure 1.5: Quiz Command Activity Diagram)
+![QuizActivityDiagram](images/QuizActivityDiagram.png)
+
+
+### Delete Feature (Jian Ling)
+
+#### Implementation
+
+This feature allows the user to delete a QAndA from the answer book. The flow of the execution of the delete command is shown below.
+
+1. User enters the input to delete a QAndA (eg. `delete 1`)
+
+2. The `LogicManager` executes this command, leading to the command being parsed by `MedmoriserParser` and `DeleteCommandParser`
+
+3. After successful parsing, `DeleteCommand#execute(Model model)` is called. This method checks for the following scenarios:
-Step 5. The user then decides to execute the command `list`. Commands that do not modify the address book, such as `list`, will usually not call `Model#commitAddressBook()`, `Model#undoAddressBook()` or `Model#redoAddressBook()`. Thus, the `addressBookStateList` remains unchanged.
+ - A quiz is currently in progress
+ - The index entered by the user is out of bounds
-![UndoRedoState4](images/UndoRedoState4.png)
+ If any of the scenarios above occur, a `CommandException` will be thrown with their respective error messages. Othewise, a new `CommandResult` is returned, along with a success message that the specified QAndA has been successfully deleted
-Step 6. The user executes `clear`, which calls `Model#commitAddressBook()`. Since the `currentStatePointer` is not pointing at the end of the `addressBookStateList`, all address book states after the `currentStatePointer` will be purged. Reason: It no longer makes sense to redo the `add n/David …` command. This is the behavior that most modern desktop applications follow.
+The sequence diagram (Fig. 1.6) below shows the flow of the delete feature.
-![UndoRedoState5](images/UndoRedoState5.png)
+(Figure 1.6: Delete Command Sequence Diagram)
-The following activity diagram summarizes what happens when a user executes a new command:
+![DeleteSequenceDiagram](images/DeleteSequenceDiagram.png)
-![CommitActivityDiagram](images/CommitActivityDiagram.png)
+The activity diagram (Fig 1.7) below further shows the flow of the delete feature.
-#### Design consideration:
+(Figure 1.7: Delete Command Activity Diagram)
-##### Aspect: How undo & redo executes
+![DeleteActivityDiagram](images/DeleteActivityDiagram.png)
-* **Alternative 1 (current choice):** Saves the entire address book.
- * Pros: Easy to implement.
- * Cons: May have performance issues in terms of memory usage.
-* **Alternative 2:** Individual command knows how to undo/redo by
- itself.
- * Pros: Will use less memory (e.g. for `delete`, just save the person being deleted).
- * Cons: We must ensure that the implementation of each individual command are correct.
+### List Feature (Jonathan Foo)
-_{more aspects and alternatives to be added}_
+#### Implementation
-### \[Proposed\] Data archiving
+This section elaborates on the implementation of the list feature.
-_{Explain here how the data archiving feature will be implemented}_
+1. The user enters input to list all QAndAs.
+2. The `Ui` component calls the `Logic` component to execute this. `MedmoriserParser` parses the command, resulting in a `ListCommand` object which is executed by the `LogicManager`.
+
+3. This updates the `Model` to show all QAndAs in the answer book.
+
+4. The result of this command execution is encapsulated as a `CommandResult` object which is passed back to the `Ui`.
+
+5. `Ui` checks the `CommandResult` object and modifies the visibility of the `Answer` label. In this case, the visibilty is set to `hidden`
+
+The sequence diagram below (Fig 1.8) shows the interactions between the Ui and Logic components for the list command.
+
+(Figure 1.8: List Command Sequence Diagram)
+![ListSequenceDiagram](images/ListSequenceDiagram.png)
+
+The following activity diagram (Fig 1.9) summarises what happens when a user executes the `list` command.
+
+(Figure 1.9: List Command Activity Diagram)
+![ListActivityDiagram](images/ListActivityDiagram.png)
+
+#### Design considerations:
+* The `Ui` component was selected to perform the showing/hiding of answers as it already had access to the various components in the GUI, hence preventing further coupling between the different components.
+* We decided to use `list` rather than `list all` to show all questions and answers as we wanted to maintain the original functionality of the `list` command.
--------------------------------------------------------------------------------------------------------------------
@@ -236,71 +282,195 @@ _{Explain here how the data archiving feature will be implemented}_
**Target user profile**:
-* has a need to manage a significant number of contacts
+* medical students with heavy content to memorise
+* has a need to manage and frequently revisit a significant number of questions and answers
+* has a need to refer to images and diagrams
* prefer desktop apps over other types
-* can type fast
+* finds typing with a keyboard faster than typing with smartphones or handwriting.
* prefers typing to mouse interactions
* is reasonably comfortable using CLI apps
-**Value proposition**: manage contacts faster than a typical mouse/GUI driven app
+**Value proposition**:
+* Aggregate and organises contents and much faster than traditional methods.
+* Allows students to memorise contents more efficiently by continuously testing them. This way they can practice active recall.
### User stories
Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*`
-| Priority | As a … | I want to … | So that I can… |
-| -------- | ------------------------------------------ | ------------------------------ | ---------------------------------------------------------------------- |
-| `* * *` | new user | see usage instructions | refer to instructions when I forget how to use the App |
-| `* * *` | user | add a new person | |
-| `* * *` | user | delete a person | remove entries that I no longer need |
-| `* * *` | user | find a person by name | locate details of persons without having to go through the entire list |
-| `* *` | user | hide private contact details | minimize chance of someone else seeing them by accident |
-| `*` | user with many persons in the address book | sort persons by name | locate a person easily |
-
-*{More to be added}*
+| Priority | As a … | I want to … | So that I can… |
+| -------- | ------------------------------------------ | ------------------------------ | -------------------------------------------------------------------------|
+| `* * *` | new user | see usage instructions | refer to instructions when I forget how to use the App |
+| `* * *` | user | key in questions and answers | revise on the questions I keyed in |
+| `* * *` | user | delete a Q&A | remove entries that I no longer need |
+| `* * *` | user | edit existing questions and answers | make changes to the questions and answers |
+| `* * *` | user | see all the questions | have an overview of all the Q&As I have |
+| `* *` | user | find questions by keywords | locate the Q&A without having to go through the entire list of questions |
+| `* * ` | user | tag questions to its topics | organise the questions properly by topic |
+| `*` | organised user | archive questions I no longer need | keep my question book organised and updated |
### Use cases
-(For all use cases below, the **System** is the `AddressBook` and the **Actor** is the `user`, unless specified otherwise)
+(For all use cases below, the **System** is the `Medmoriser` and the **Actor** is the `user`, unless specified otherwise. Q&A stands for a question and answer pair)
-**Use case: Delete a person**
+**Use case: UC01 - Add a Q&A**
**MSS**
-1. User requests to list persons
-2. AddressBook shows a list of persons
-3. User requests to delete a specific person in the list
-4. AddressBook deletes the person
+1. User adds a new QAndA into the database
+
+2. Medmoriser adds the new QAndA and displays a success message
+
+ Use case ends.
+
+**Extensions**
+
+- 1a. The entered data is invalid
+
+ - 1a1. Medmoriser displays an error message
Use case ends.
+
+
+**Use case: UC02 - View all QAndAs**
+
+**MSS**
+
+1. User requests to view all QAndAs
+
+2. Medmoriser shows a list of QAndAs in the database
+
+ Use case ends.
+
+
+
+**Use case: UC03 - Delete a QAndA**
+
+**MSS**
+
+1. User requests to view all QAndAs
+
+2. Medmoriser shows a list of QAndAs in the database
+
+3. User requests to delete a QAndA at a specific index in the list
+
+4. Medmoriser deletes the Q&A and displays success message
+
+ Use case ends
+
+**Extensions**
+
+- 2a. The list is empty.
+
+ Use case ends.
+
+- 3a. The given index is invalid.
+
+ - 3a1. Medmoriser shows an error message.
+
+ Use case resumes at step 2.
+
+**Use case: UC04 - Add a tag to a QAndA**
+
+**MSS**
+
+1. User requests to view all QAndAs
+
+2. Medmoriser shows a list of QAndAs in the database
+
+3. User requests to add a tag to a QAndA at a specific index in the list
+
+4. Medmoriser adds the specified tag to the QAndA and displays success message
+
+ Use case ends.
+
**Extensions**
-* 2a. The list is empty.
+- 2a. The list is empty.
Use case ends.
-* 3a. The given index is invalid.
+- 3a. The given index is invalid.
+
+ - 3a1. Medmoriser shows an error message.
+
+ Use case resumes at step 2.
+
+- 3b. The given tag is invalid.
+
+ - 3b1. Medmoriser shows an error message.
+
+ Use case resumes at step 2.
+
+**Use case: UC05 - Edit a QAndA**
+
+**MSS**
+
+1. User requests to view all QAndAs
+
+2. Medmoriser shows a list of QAndAs in the database
+
+3. User requests to edit a QAndA at a specific index in the list
+
+4. Medmoriser edits the QAndA at the specified index according to the user's new input and displays success message
+
+ Use case ends
+
+**Extensions**
+
+- 2a. The list is empty.
+
+ Use case ends.
+
+- 3a. The given index is invalid.
+
+ - 3a1. Medmoriser shows an error message.
+
+ Use case resumes at step 2.
+
+- 3b. The edit request is invalid
- * 3a1. AddressBook shows an error message.
+ - 3b1. Medmoriser shows an error message
- Use case resumes at step 2.
+ Use case resumes at step 2.
+
+**Use case: UC06 - Find a QAndA**
+
+**MSS**
+
+1. User searches for a key word or phrase
+
+2. Medmoriser shows a list of QAndAs with that specified word or phrase
+
+ Use case ends
+
+**Extensions**
+
+- 2a. There are no QAndAs that contain the specified word or phrase
+
+ - 2a1. Medmoriser displays message that no QAndAs found
+
+ Use case ends
*{More to be added}*
### Non-Functional Requirements
-1. Should work on any _mainstream OS_ as long as it has Java `11` or above installed.
-2. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage.
-3. A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
+1. Data bank should be able to hold large number (500+) pairs of QAndAs without any sluggish performance
+ for typical usage.
+2. Users should be able to retrieve answers to a question with a single command
+3. User should be able to add a QAndA easily and efficiently through a user-friendly GUI
+4. Have a clean user interface when it comes to reviewing questions and answers
*{More to be added}*
### Glossary
-* **Mainstream OS**: Windows, Linux, Unix, OS-X
-* **Private contact detail**: A contact detail that is not meant to be shared with others
+* **QAndA**: A set containing a question and answer
+* **Question**: A question belonging to a QAndA
+* **Answer**: An answer to a question, both of which belong to the same QAndA
--------------------------------------------------------------------------------------------------------------------
@@ -319,7 +489,7 @@ testers are expected to do more *exploratory* testing.
1. Download the jar file and copy into an empty folder
- 1. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
+ 1. Double-click the jar file Expected: Shows the GUI with a set of sample QAndAs. The window size may not be optimum.
1. Saving window preferences
@@ -328,29 +498,127 @@ testers are expected to do more *exploratory* testing.
1. Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-1. _{ more test cases … }_
+### Finding a QAndA
+
+1. Find QAndAs based on keywords in the question
+
+ 1. Prerequisites: QAndA(s) with the word `heart` in the question
+
+ 1. Test case: `find q/heart`
+ Expected: QAndA(s) with `heart` in the question are shown.
+
+1. Find QAndAs based on keywords in the answer
+
+ 1. Prerequisites: 2 different QAndAs, 1 with the word `blood` in the answer
+ and the other with `respiratory function` in the answer
+
+ 1. Test case: `find a/blood, respiratory function`
+ Expected: Both QAndAs with the corresponding keywords are shown.
+ (i.e. the QAndA with `blood` in the answer and the QAndA with `respiratory function` in the answer are both shown)
+
+1. Find QAndAs based on keywords in the tag
+
+ 1. Prerequisites: QAndA(s) with the tag `immune system`
+
+ 1. Test case: `find t/immune system`
+ Expected: QAndA(s) with the tag `immune system` are shown.
+
+### Quizzing
+
+1. Starting a quiz
+
+ 1. Prerequisites: QAndA(s) with the `heart` tag. **No** QAndA with the `missing` tag.
+
+ 1. Test case: `quiz t/heart`
+ Expected: A card showing a QAndA with the `heart` tag appears.
+
+ 1. Test case: `quiz t/missing`
+ Expected: No QAndA is shown. Error message shown in the result box.
+
+1. Attempting a quiz
+
+ 1. Prerequisites: QAndA(s) with the `immune system` tag. Start the quiz by following step 2 in the previous
+ test case (i.e. `quiz t/immune system`)
+
+ 1. Test case: `answer white blood cell`
+ Expected: The card displaying the quizzed QAndA now shows the correct answer to the question.
+ The input answer is displayed in the result box.
+
+ 1. End the quiz with `endquiz`. Repeat step 1. Test case: `white blood cell`
+ Expected: The card displaying the quizzed QAndA remains unchanged. Error message shown in result box.
+
+
:information_source:
+**Note:** Remember to `endquiz` and achieve the prerequisites when starting a new test case.
+
-### Deleting a person
+### Deleting a QAndA
-1. Deleting a person while all persons are being shown
+1. Deleting a QAndA while all QAndAs are being shown
- 1. Prerequisites: List all persons using the `list` command. Multiple persons in the list.
+ 1. Prerequisites: List all QAndAs using the `list` command. Multiple QAndAs in the list.
1. Test case: `delete 1`
- Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated.
+ Expected: First QAndA is deleted from the list. Details of the deleted QAndA shown in the result box.
1. Test case: `delete 0`
- Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.
+ Expected: No QAndA is deleted. Error details shown in the result box.
1. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
Expected: Similar to previous.
-1. _{ more test cases … }_
+1. Deleting QAndA while only certain QAndAs are being shown
+ 1. Prerequisites: Multiple QAndAs with the word `heart` in the question. Find all QAndAs with `heart` in the
+ question using the `find q/heart` command.
+
+ 1. Test case: `delete 2`
+ Expected: Second QAndA is deleted from the list. Details of the deleted QAndA shown in the result box.
+ The window continues to display the remaining QAndAs with `heart` in the question.
+
### Saving data
-1. Dealing with missing/corrupted data files
+1. Initial setup of data files
+
+ 1. Download the jar file and move it into an empty folder
+
+ 1. Double-click the jar file.
+ Expected: Shows the GUI with a set of sample QAndAs.
+
+ 1. Exit the app with the `exit` command.
+
+1. Simulating a missing data file
+
+ 1. Locate the `data` folder and delete the `medmoriser.json` file
+
+ 1. Re-launch the app by double-clicking the jar file.
+ Expected: The app shows the GUI with the same set of sample QAndAs. A new `medmoriser.json` file is created in
+ the `data` folder.
+
+1. Simulating a corrupted data file
+
+ 1. Locate the `data` folder and open the `medmoriser.json` file with an editor of your choice. Delete all the data
+ and replace it with random characters (e.g. `abcdef123456`), then save the file.
+
+ 1. Re-launch the app by double-clicking the jar file.
+ Expected: Shows the GUI with no QAndAs.
+
+ 1. Add a QAndA into the app. Exit the app with the `exit` command.
+ Expected: The random characters in `medmoriser.json` are replaced with the json data of the new QAndA.
+
+## Appendix: Effort
+
+This section explains the difficulty level, challenges faced, effort required, and achievements of Medmoriser.
+
+
:information_source:
+**Note:** The examples used below are explained in comparison to AB3.
+
+
+
+
+Making Medmoriser was particularly difficult as there were many challenges we faced along the way:
- 1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_
+1. There was a need to change a large portion of the AB3 code, as we had a completely different set of variables for Medmoriser. We had to do a lot of refactoring in the form of renaming class and attributes. The restrictions on fields in AB3 were also different from those in Medmoriser (eg. Person in AB3 cannot have special characters, but Question in Medmoriser can), and we had to edit those restrictions respectively.
+2. Implementing a quizzing feature required a deep understanding of the design of AB3. Merely manipulating variables in existing code was not sufficient here, and we had to create many new classes such as `QuizCommand`, `AnswerCommand`, `NextCommand`and `EndQuizCommand`. We also had to come up with ways to keep track of the state of the application, such as whether the user is in an ongoing quiz, whether the user has entered an answer for a quiz question, and whether a quiz question has been asked before when choosing the next question to show the user in a quiz. There was not a need for this in AB3.
+3. The numerous new classes created and enhancements to existing commands meant that a lot more effort was required to implement testing for Medmoriser. This is evident in our implementation of new test classes (eg. `QuizCommandTest`, `QuizCommandParserTest`, `AnswerCommandTest`, `EndQuizTest` , etc) and additional test cases in existing test classes (eg `FindCommandTest`, `ListCommandTest`, etc).
-1. _{ more test cases … }_
+Despite the difficulties mentioned above, we managed to overcome them and come up with a fully functional product that we are proud of.
diff --git a/docs/SettingUp.md b/docs/SettingUp.md
index b89b691fed9..0280883ed48 100644
--- a/docs/SettingUp.md
+++ b/docs/SettingUp.md
@@ -23,7 +23,7 @@ If you plan to use Intellij IDEA (highly recommended):
1. **Import the project as a Gradle project**: Follow the guide [_[se-edu/guides] IDEA: Importing a Gradle project_](https://se-education.org/guides/tutorials/intellijImportGradleProject.html) to import the project into IDEA.
:exclamation: Note: Importing a Gradle project is slightly different from importing a normal Java project.
1. **Verify the setup**:
- 1. Run the `seedu.address.Main` and try a few commands.
+ 1. Run the `seedu.medmoriser.Main` and try a few commands.
1. [Run the tests](Testing.md) to ensure they all pass.
--------------------------------------------------------------------------------------------------------------------
@@ -45,7 +45,7 @@ If you plan to use Intellij IDEA (highly recommended):
1. **Learn the design**
- When you are ready to start coding, we recommend that you get some sense of the overall design by reading about [AddressBook’s architecture](DeveloperGuide.md#architecture).
+ When you are ready to start coding, we recommend that you get some sense of the overall design by reading about [Medmoriser’s architecture](DeveloperGuide.md#architecture).
1. **Do the tutorials**
These tutorials will help you get acquainted with the codebase.
diff --git a/docs/Testing.md b/docs/Testing.md
index 8a99e82438a..31a4ee50cb2 100644
--- a/docs/Testing.md
+++ b/docs/Testing.md
@@ -29,8 +29,8 @@ There are two ways to run tests.
This project has three types of tests:
1. *Unit tests* targeting the lowest level methods/classes.
- e.g. `seedu.address.commons.StringUtilTest`
+ e.g. `seedu.medmoriser.commons.StringUtilTest`
1. *Integration tests* that are checking the integration of multiple code units (those code units are assumed to be working).
- e.g. `seedu.address.storage.StorageManagerTest`
+ e.g. `seedu.medmoriser.storage.StorageManagerTest`
1. Hybrids of unit and integration tests. These test are checking multiple code units as well as how the are connected together.
- e.g. `seedu.address.logic.LogicManagerTest`
+ e.g. `seedu.medmoriser.logic.LogicManagerTest`
diff --git a/docs/UserGuide.md b/docs/UserGuide.md
index b91c3bab04d..b3e093cc849 100644
--- a/docs/UserGuide.md
+++ b/docs/UserGuide.md
@@ -3,176 +3,354 @@ layout: page
title: User Guide
---
-AddressBook Level 3 (AB3) is a **desktop app for managing contacts, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB3 can get your contact management tasks done faster than traditional GUI apps.
+## Introduction
-* Table of Contents
+Hi Medical Student! Welcome to the User Guide for **Medmoriser**!
+
+**Medmoriser** is a desktop app to help medical students organise, memorise and revise their content.
+
+This guide aims to orientate you to the features of **Medmoriser**. If you're looking for a quiz
+management system, this guide will give you all the information you need to get started with **Medmoriser**.
+
+* Table of Contents:
{:toc}
--------------------------------------------------------------------------------------------------------------------
-## Quick start
+## How to use this guide
-1. Ensure you have Java `11` or above installed in your Computer.
+The explanation for each feature follows the template:
-1. Download the latest `addressbook.jar` from [here](https://github.com/se-edu/addressbook-level3/releases).
+> Introduction of feature
+>
+> Format of command
+>
+> * Details about behaviour of the command
+> * are in the bulletpoints
+>
+> Examples:
+>
+> * example of the command usage
-1. Copy the file to the folder you want to use as the _home folder_ for your AddressBook.
+
-1. Double-click the file to start the app. The GUI similar to the below should appear in a few seconds. Note how the app contains some sample data.
- ![Ui](images/Ui.png)
+**:information_source: Notes about the command format:**
-1. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
- Some example commands you can try:
+* Words in `UPPER_CASE` are the parameters to be supplied by the user.
+ e.g. in `add q/QUESTION`, `QUESTION` is a parameter which can be used as `add q/What is the heart responsible for?`.
- * **`list`** : Lists all contacts.
+* Items in square brackets are optional.
+ e.g. `q/QUESTION [t/TAG]` can be used as `q/What is the heart responsible for? t/cardiology` or as `q/What is the heart responsible for?`
- * **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : Adds a contact named `John Doe` to the Address Book.
+* Items with `…` after them can be used multiple times including zero times.
+ e.g. `[t/TAG]…` can be used as ` ` (i.e. 0 times), `t/heart`, `t/heart t/cardiology` etc.
- * **`delete`**`3` : Deletes the 3rd contact shown in the current list.
+* Parameters can be in any order.
+ e.g. if the command specifies `q/QUESTION a/ANSWER`, `a/ANSWER q/QUESTION` is also acceptable.
- * **`clear`** : Deletes all contacts.
+
- * **`exit`** : Exits the app.
+## Features
-1. Refer to the [Features](#features) below for details of each command.
+This section will bring you through various features of Medmoriser. After this section, you will know how to use most of the commands available.
---------------------------------------------------------------------------------------------------------------------
+You can follow the instructions one by one, or jump to your feature of interest. For a summary of all commands, please refer to the [Command Summary](#command-summary) section at the end of this guide.
-## Features
+### Viewing help: `help`
-
+If you need to view the help page, this command shows a message explaining how to access it.
-**:information_source: Notes about the command format:**
+Format: `help`
-* Words in `UPPER_CASE` are the parameters to be supplied by the user.
- e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`.
+### Adding a QAndA: `add` (by: Cheng Jiyuqing)
-* Items in square brackets are optional.
- e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`.
+You can add a QAndA to the database. You can tag this pair with tag(s) of your choice. It is also okay to not tag the question at all.
-* Items with `…` after them can be used multiple times including zero times.
- e.g. `[t/TAG]…` can be used as ` ` (i.e. 0 times), `t/friend`, `t/friend t/family` etc.
+Format: `add q/QUESTION a/ANSWER [t/TAG]…`
-* Parameters can be in any order.
- e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable.
+Examples:
+* `add q/what organ system is the lungs part of? a/respiratory system.`
+* `add q/what organ system is the lungs part of? a/respiratory system? t/Body systems t/Respiratory system.`
+* `add q/what is the function of the heart? a/It's the muscle at the centre of your circulation system, pumping blood around your body as your heart beats. This blood sends oxygen and nutrients to all parts of your body, and carries away unwanted carbon dioxide and waste products.`
-
+How it should look in the application:
-### Viewing help : `help`
+Add with tag:
-Shows a message explaning how to access the help page.
+![Add With Tag](images/AddCommandEg1.png)
-![help message](images/helpMessage.png)
+Expected result:
-Format: `help`
+![Add With Tag](images/AddCommandEg2.png)
+
+### Deleting a QAndA: `delete` (by: Teng Jian Ling)
+You can delete a specified QAndA from the database.
-### Adding a person: `add`
+Format: `delete INDEX`
-Adds a person to the address book.
+* This allows you to delete the QAndA at the specified `INDEX`.
+* The index refers to the index number shown in the displayed QAndA list.
-Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…`
+Examples:
+
+* `list` followed by `delete 2` deletes the 2nd QAndA in the list.
+* `find disease` followed by `delete 1` deletes the 1st QAndA in the results of the `find` command.
+
+
+**:information_source: Note about the delete command:**
+
+The index **must be a positive integer** (1, 2, 3, ...) within the range of the number of QAndAs in the displayed list.
-
:bulb: **Tip:**
-A person can have any number of tags (including 0)
+How it should look in the application:
+
+Entering the command:
+
+![DeleteContext](images/DeleteContext.png)
+
+Expected Result:
+
+![DeleteResult](images/DeleteResult.png)
+
+The `delete 4 ` command deletes the 4th QAndA in the database, as shown above.
+
+### Listing all QAndAs: `list` (by: Jonathan Foo)
+
+You can use this command to view all the QAndAs you have added.
+
+Format: `list [questions]`
+
+* Entering `list` will list all QAndAs, with both questions and answers displayed.
+* Adding the `questions` parameter will list all QAndAs, with only the questions displayed (i.e. hide the answers)
+
Examples:
-* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01`
-* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal`
+* `list` - show all questions and answers
+* `list questions` - show all questions
-### Listing all persons : `list`
+The expected behaviour of `list` is shown below:
-Shows a list of all persons in the address book.
+![ListCommand](images/ListCommand.png)
-Format: `list`
+The expected behaviour of `list questions` is shown below:
-### Editing a person : `edit`
+![ListQuestionsCommand](images/ListQuestionsCommand.png)
-Edits an existing person in the address book.
+### Editing a QAndA: `edit` (by: Teng Jian Ling)
-Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…`
+You can make changes to an existing QAndA with this command.
-* Edits the person at the specified `INDEX`. The index refers to the index number shown in the displayed person list. The index **must be a positive integer** 1, 2, 3, …
-* At least one of the optional fields must be provided.
+Format: `edit INDEX [q/QUESTION] [a/ANSWER] [t/TAG]…`
+
+* This allows you to edit the QAndA at the specified `INDEX`. The index refers to the index number shown in the displayed QAndA list.
* Existing values will be updated to the input values.
-* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative.
-* You can remove all the person’s tags by typing `t/` without
- specifying any tags after it.
Examples:
-* `edit 1 p/91234567 e/johndoe@example.com` Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively.
-* `edit 2 n/Betsy Crower t/` Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags.
-### Locating persons by name: `find`
+* `edit 1 a/To pump blood` - Edits the answer the 1st question to be `To pump blood`.
+* `edit 2 q/how many bones are there in an ADULT human skeleton? t/` - Edits the question of the 2nd QAndA to be `how many bones are there in an ADULT human skeleton?` and clears all existing tags.
+
+
+**:information_source: Notes about the edit command:**
+
+* When you edit the tags, the existing tags of the QAndA will be removed i.e adding of tags is not cumulative.
+* You must provide at least one of the optional fields.
+* The index **must be a positive integer** (1, 2, 3, ...) within the range of the number of QAndAs in the displayed list.
-Finds persons whose names contain any of the given keywords.
+
-Format: `find KEYWORD [MORE_KEYWORDS]`
+
-* The search is case-insensitive. e.g `hans` will match `Hans`
-* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans`
-* Only the name is searched.
-* Only full words will be matched e.g. `Han` will not match `Hans`
-* Persons matching at least one keyword will be returned (i.e. `OR` search).
- e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang`
+**:bulb: Tip:**
-Examples:
-* `find John` returns `john` and `John Doe`
-* `find alex david` returns `Alex Yeoh`, `David Li`
- ![result for 'find alex david'](images/findAlexDavidResult.png)
+You can remove all the QAndA's tags by typing `t/` without specifying any tags after it.
-### Deleting a person : `delete`
+
-Deletes the specified person from the address book.
+How it should look in the application:
-Format: `delete INDEX`
+Entering the edit command:
+
+![EditContext](images/EditContext.png)
+
+Expected Result:
+
+![EditResult](images/EditResult.png)
+
+The `edit 6 q/how many bones are there in an ADULT human skeleton? t/ ` input will edit the QAndA at index 6 and remove all tags as shown.
+
+### Finding QAndA by keywords: `find` (by: Yong Ming Yang)
+The `find` function allows you to find existing QAndA based on keywords and phrases.
+
+If you would like to search the database based on keywords or phrases, you can do so in a few ways by following the respective formats:
+
+1. Find QAndA with **questions** containing any of the given keywords.
+
+ Format: `find q/KEYWORD`, for 2 or more words: `find q/PHRASE 1, KEYWORD1`
-* Deletes the person at the specified `INDEX`.
-* The index refers to the index number shown in the displayed person list.
-* The index **must be a positive integer** 1, 2, 3, …
+2. Find QAndA with **answers** containing any of the given keywords.
+
+ Format: `find a/KEYWORD`, for 2 or more words: `find q/PHRASE 1, KEYWORD1`
+
+3. Find QAndA with **tags** containing any of the given keywords.
+ Keywords for tags can also have phrases, however this requires the text to have an exact match (case-insensitive).
+
+ Format: `find t/KEYWORD`, for 2 or more words: `find q/PHRASE1, KEYWORD1`
+
+4. Find QAndA with **questions or answers** containing any of the given keywords.
+
+ Format: `find KEYWORD`, for 2 or more words: `find PHRASE, KEYWORD1`
Examples:
-* `list` followed by `delete 2` deletes the 2nd person in the address book.
-* `find Betsy` followed by `delete 1` deletes the 1st person in the results of the `find` command.
+* `find q/system, disease` - finds questions containing the word "system" and/or "disease".
+* `find a/vessels, chronic disease` - finds answers containing the word vessels, and/or the phrase "chronic disease".
+* `find t/anatomy, Nervous System` - finds QAndAs tagged with the word "anatomy" and/or "Nervous System" (can be both), requires exact match of words (case-insensitive).
+* `find infection, nervous system` - finds question and/or answers containing the word "infection", and/or the phrase "nervous system"
+
+
+
+**:bulb: Tip:**
+`PHRASE` refers to words with spaces in between, for example: "nervous system"
+
+
+
+How it should look like in the application:
+
+![FindContext](images/FindContext.PNG)
+
+Expected Result:
+
+![FindResult](images/FindResult.PNG)
-### Clearing all entries : `clear`
+The input `find t/respiratory system, disease` will return the questions with the tag "respiratory system" and/or "disease" as shown.
-Clears all entries from the address book.
+### Clearing all entries: `clear`
+
+If you want to reset your question book, this command clears all existing entries.
Format: `clear`
-### Exiting the program : `exit`
+### Starting a quiz: `quiz` (by: Joshua Tan)
+
+You will be able to test yourself on your knowledge from the questions that you added into the application.
+Medmoriser will randomly select a question to quiz you based on the keywords you provide.
+
+There are 2 ways that you can quiz yourself. By question keywords or by tag keywords. If multiple keywords are given, you will be quizzed on a question that has any of the keywords, or all of the keywords.
+
+1. Quiz a QAndA with **questions** containing any of the given keywords.
+
+ Format: `quiz q/KEYWORD`, for 2 or more words: `quiz q/PHRASE 1, KEYWORD 1`
+
+2. Quiz a QAndA wih **tag** containing any of the given keywords.
+
+ Format: `quiz t/KEYWORD`, for 2 or more words: `quiz t/PHRASE 1, KEYWORD 1`
+
+Examples:
+* `quiz q/immunology` - randomly quizzes a question containing the word "immunology".
+* `quiz t/surgery, injuries` - randomly quizzes a question that was tagged with the word "surgery" and/or "injuries" (can be both), requires exact match of words (case-insensitive).
+
+
+
+**:bulb: Tip:**
+To run other commands other than `next` or `answer`, you have to first `endquiz`.
+
+
+
+How it should look like in the application:
+
+![QuizContext](images/QuizContext.png)
+
+Expected Result:
+
+![QuizResult](images/QuizResult.png)
+
+### Answering a quiz question: `answer` (by: Joshua Tan)
+You will be able to key in your answer for a quiz question. After your answer is submitted, Medmoriser will flash the correct answer to the question and you will be able to check your answer:
+
+Format: `answer YOUR_ANSWER`
+
+Example:
+* `answer This is my answer to the quiz question`
+
+### Moving to next quiz question: `next` (by: Teng Jian Ling)
+You will be able to continue testing yourself without ending the current quiz. Medmoriser will randomly select a different quiz question based on the same keywords you provided previously.
+
+Format: `next`
+
+Example:
+* `next` - will show you the next question in this quiz
+
+
+**:bulb: Tip:**
+If you want to skip the current quiz question, you can enter `next` without answering first.
+
+
+
+**:information_source: Notes about the edit command:**
+
+* You can only use the `next` command when you are in an ongoing quiz.
+* When there are no more questions with the specified keywords, you will not be able to use `next` to retrieve another quiz question.
+
+
+
+How it should look like in the application:
+
+![QuizContext](images/NextContext.png)
+
+Expected Result:
-Exits the program.
+![QuizResult](images/NextResult.png)
+
+Assuming the user is in a quiz for `t/respiratory system`, the input `next` will display a new randomly selected question with the tag `respiratory system`, as shown above.
+
+### Ending a quiz: `endquiz` (by: Joshua Tan)
+Once you are done with a quiz and have finished comparing your input answer with the answer in the question, you have to end the quiz to run other commands.
+If you want to run other commands in the midst of a quiz(ie. if you have not answered the question) you have to end the quiz first:
+
+Format: `endquiz`
+
+### Exiting the program: `exit`
+
+If you're done with your work, this command allows you to exit the program. You can also exit the application by closing its window like any normal program window.
Format: `exit`
### Saving the data
-AddressBook data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually.
+You don't need to worry about saving data manually, as Medmoriser data is automatically saved in the hard disk after any command that changes the data.
-### Archiving data files `[coming in v2.0]`
+### Archiving data files [Coming Soon]
-_{explain the feature here}_
+If you don't need certain questions anymore, you can archive them to declutter your workspace.
--------------------------------------------------------------------------------------------------------------------
## FAQ
+Commonly asked questions and answers.
**Q**: How do I transfer my data to another Computer?
-**A**: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous AddressBook home folder.
+**A**: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous Medmoriser home folder.
--------------------------------------------------------------------------------------------------------------------
+
## Command summary
+A brief summary of all the commands available. For details of when and how each command should be used, please refer to
+the [Features](#features) section.
Action | Format, Examples
--------|------------------
-**Add** | `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…` e.g., `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague`
+**Add** | `add q/QUESTION a/ANSWER [t/TAG]…` e.g. `add q/What does the heart do? a/Pump blood t/heart t/cardiology`
+**Delete** | `delete INDEX` e.g. `delete 3`
+**List** | `list [questions]`
+**Edit** | `edit INDEX [q/QUESTION] [a/ANSWER] [t/TAG]…` e.g. `edit 1 a/Maintain blood pressure t/cardiology`
+**Find** | `find KEYWORD or [q/QUESTION_KEYWORD] or [a/ANSWER_KEYWORD] or [t/TAG_KEYWORD]` e.g. `find system` or `find a/answer1, answer 2`
+**Quiz** | `quiz [q/QUESTION_KEYWORD] or [t/TAG_KEYWORD]` e.g. `quiz q/blood` or `quiz t/Immune System`
+**Answer** | `answer YOUR_ANSWER` e.g. `answer This is my answer`
+**Next** | `next`
+**End Quiz** | `endquiz`
**Clear** | `clear`
-**Delete** | `delete INDEX` e.g., `delete 3`
-**Edit** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…` e.g.,`edit 2 n/James Lee e/jameslee@example.com`
-**Find** | `find KEYWORD [MORE_KEYWORDS]` e.g., `find James Jake`
-**List** | `list`
**Help** | `help`
+**Exit** | `exit`
+
diff --git a/docs/_config.yml b/docs/_config.yml
index 6bd245d8f4e..20e9ac5848c 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -1,4 +1,4 @@
-title: "AB-3"
+title: "Medmoriser"
theme: minima
header_pages:
@@ -8,7 +8,7 @@ header_pages:
markdown: kramdown
-repository: "se-edu/addressbook-level3"
+repository: "AY2021S1-CS2103T-W15-1/tp"
github_icon: "images/github-icon.png"
plugins:
diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml
index ef81d18c337..354b292d73a 100644
--- a/docs/diagrams/ArchitectureSequenceDiagram.puml
+++ b/docs/diagrams/ArchitectureSequenceDiagram.puml
@@ -13,13 +13,13 @@ activate ui UI_COLOR
ui -[UI_COLOR]> logic : execute("delete 1")
activate logic LOGIC_COLOR
-logic -[LOGIC_COLOR]> model : deletePerson(p)
+logic -[LOGIC_COLOR]> model : deleteQAndA(qAndAToDelete)
activate model MODEL_COLOR
model -[MODEL_COLOR]-> logic
deactivate model
-logic -[LOGIC_COLOR]> storage : saveAddressBook(addressBook)
+logic -[LOGIC_COLOR]> storage : saveMedmoriser(model.getMedmoriser());
activate storage STORAGE_COLOR
storage -[STORAGE_COLOR]> storage : Save to file
diff --git a/docs/diagrams/BetterModelClassDiagram.puml b/docs/diagrams/BetterModelClassDiagram.puml
index 29076104af3..1d0e24d5c03 100644
--- a/docs/diagrams/BetterModelClassDiagram.puml
+++ b/docs/diagrams/BetterModelClassDiagram.puml
@@ -4,18 +4,16 @@ skinparam arrowThickness 1.1
skinparam arrowColor MODEL_COLOR
skinparam classBackgroundColor MODEL_COLOR
-AddressBook *-right-> "1" UniquePersonList
-AddressBook *-right-> "1" UniqueTagList
-UniqueTagList -[hidden]down- UniquePersonList
-UniqueTagList -[hidden]down- UniquePersonList
+Medmoriser *-right-> "1" UniqueQAndAList
+Medmoriser *-right-> "1" UniqueTagList
+UniqueTagList -[hidden]down- UniqueQAndAList
+UniqueTagList -[hidden]down- UniqueQAndAList
UniqueTagList *-right-> "*" Tag
-UniquePersonList o-right-> Person
+UniqueQAndAList o-right-> QAndA
-Person -up-> "*" Tag
+QAndA -up-> "*" Tag
-Person *--> Name
-Person *--> Phone
-Person *--> Email
-Person *--> Address
+QAndA *--> Question
+QAndA *--> Answer
@enduml
diff --git a/docs/diagrams/DeleteActivityDiagram.puml b/docs/diagrams/DeleteActivityDiagram.puml
new file mode 100644
index 00000000000..353b0974fb2
--- /dev/null
+++ b/docs/diagrams/DeleteActivityDiagram.puml
@@ -0,0 +1,15 @@
+@startuml
+
+start
+:User executes delete command;
+:Parse the delete command;
+if () then ([quiz is in progress or index out of bounds])
+ :Throw CommandException;
+else ([else])
+ :Delete the QAndA specified;
+ :Display success message;
+endif
+
+stop
+
+@enduml
diff --git a/docs/diagrams/DeleteSequenceDiagram.puml b/docs/diagrams/DeleteSequenceDiagram.puml
index 1dc2311b245..251f8e35e91 100644
--- a/docs/diagrams/DeleteSequenceDiagram.puml
+++ b/docs/diagrams/DeleteSequenceDiagram.puml
@@ -3,10 +3,10 @@
box Logic LOGIC_COLOR_T1
participant ":LogicManager" as LogicManager LOGIC_COLOR
-participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
-participant ":DeleteCommandParser" as DeleteCommandParser LOGIC_COLOR
-participant "d:DeleteCommand" as DeleteCommand LOGIC_COLOR
-participant ":CommandResult" as CommandResult LOGIC_COLOR
+participant ":MedmoriserParser" as MedmoriserParser MEDMORISER_PARSER_COLOR
+participant ":DeleteCommandParser" as DeleteCommandParser COMMAND_PARSER_COLOR
+participant "d:DeleteCommand" as DeleteCommand COMMAND_COLOR
+participant ":CommandResult" as CommandResult COMMAND_RESULT_COLOR
end box
box Model MODEL_COLOR_T1
@@ -16,17 +16,17 @@ end box
[-> LogicManager : execute("delete 1")
activate LogicManager
-LogicManager -> AddressBookParser : parseCommand("delete 1")
-activate AddressBookParser
+LogicManager -> MedmoriserParser : parseCommand("delete 1")
+activate MedmoriserParser
create DeleteCommandParser
-AddressBookParser -> DeleteCommandParser
+MedmoriserParser -> DeleteCommandParser
activate DeleteCommandParser
-DeleteCommandParser --> AddressBookParser
+DeleteCommandParser --> MedmoriserParser
deactivate DeleteCommandParser
-AddressBookParser -> DeleteCommandParser : parse("1")
+MedmoriserParser -> DeleteCommandParser : parse("1")
activate DeleteCommandParser
create DeleteCommand
@@ -36,19 +36,19 @@ activate DeleteCommand
DeleteCommand --> DeleteCommandParser : d
deactivate DeleteCommand
-DeleteCommandParser --> AddressBookParser : d
+DeleteCommandParser --> MedmoriserParser : d
deactivate DeleteCommandParser
'Hidden arrow to position the destroy marker below the end of the activation bar.
-DeleteCommandParser -[hidden]-> AddressBookParser
+DeleteCommandParser -[hidden]-> MedmoriserParser
destroy DeleteCommandParser
-AddressBookParser --> LogicManager : d
-deactivate AddressBookParser
+MedmoriserParser --> LogicManager : d
+deactivate MedmoriserParser
LogicManager -> DeleteCommand : execute()
activate DeleteCommand
-DeleteCommand -> Model : deletePerson(1)
+DeleteCommand -> Model : deleteQAndA(1)
activate Model
Model --> DeleteCommand
diff --git a/docs/diagrams/EditSequenceDiagram.puml b/docs/diagrams/EditSequenceDiagram.puml
new file mode 100644
index 00000000000..79e006d0fcb
--- /dev/null
+++ b/docs/diagrams/EditSequenceDiagram.puml
@@ -0,0 +1,75 @@
+@startuml
+!include style.puml
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":MedmoriserParser" as MedmoriserParser MEDMORISER_PARSER_COLOR
+participant ":EditCommandParser" as EditCommandParser COMMAND_PARSER_COLOR
+participant "e:EditCommand" as EditCommand COMMAND_COLOR
+participant ":CommandResult" as CommandResult COMMAND_RESULT_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("edit 1 q/what causes acne?")
+activate LogicManager
+
+LogicManager -> MedmoriserParser : parseCommand("edit 1 q/what causes acne?")
+activate MedmoriserParser
+
+create EditCommandParser
+MedmoriserParser -> EditCommandParser
+activate EditCommandParser
+
+EditCommandParser --> MedmoriserParser
+deactivate EditCommandParser
+
+MedmoriserParser -> EditCommandParser : parse("1 q/what causes acne?")
+activate EditCommandParser
+
+create EditCommand
+EditCommandParser -> EditCommand
+activate EditCommand
+
+EditCommand --> EditCommandParser : e
+deactivate EditCommand
+
+EditCommandParser --> MedmoriserParser : e
+deactivate EditCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+EditCommandParser -[hidden]-> MedmoriserParser
+destroy EditCommandParser
+
+MedmoriserParser --> LogicManager : e
+deactivate MedmoriserParser
+
+LogicManager -> EditCommand : execute()
+activate EditCommand
+
+EditCommand -> Model : setQAndA(qAndAToEdit, editedQAndA)
+activate Model
+
+Model --> EditCommand
+deactivate Model
+
+EditCommand -> Model : updateFilteredQAndAList(PREDICATE_SHOW_ALL_QANDA)
+activate Model
+
+Model --> EditCommand
+deactivate Model
+
+create CommandResult
+EditCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> EditCommand
+deactivate CommandResult
+
+EditCommand --> LogicManager : result
+deactivate EditCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/FindActivityDiagram.puml b/docs/diagrams/FindActivityDiagram.puml
new file mode 100644
index 00000000000..a43e64083cc
--- /dev/null
+++ b/docs/diagrams/FindActivityDiagram.puml
@@ -0,0 +1,25 @@
+@startuml
+!include style.puml
+
+start
+:"Find command is executed";
+:"Command is parsed";
+
+if (command is valid) then (valid)
+ :identify find command type;
+ if (find in tags) then (yes)
+ :retrieve tag predicate;
+ elseif (find in answers) then (yes)
+ :retrieve answer predicate;
+ elseif (find in questions) then
+ :retrieve question predicate;
+ else
+ :retrieve QAndA predicate;
+ endif
+ :retrieve list of questions;
+else (invalid)
+ :"Show invalid command message";
+endif
+:show on GUI;
+stop
+@enduml
diff --git a/docs/diagrams/FindSequenceDiagram.puml b/docs/diagrams/FindSequenceDiagram.puml
new file mode 100644
index 00000000000..ef35a851272
--- /dev/null
+++ b/docs/diagrams/FindSequenceDiagram.puml
@@ -0,0 +1,69 @@
+@startuml
+!include style.puml
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":MedmoriserParser" as MedmoriserParser MEDMORISER_PARSER_COLOR
+participant ":FindCommandParser" as FindCommandParser COMMAND_PARSER_COLOR
+participant "f:FindCommand" as FindCommand COMMAND_COLOR
+participant ":CommandResult" as CommandResult COMMAND_RESULT_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("find Immunology")
+activate LogicManager
+
+LogicManager -> MedmoriserParser : parseCommand("find Immunology")
+activate MedmoriserParser
+
+create FindCommandParser
+MedmoriserParser -> FindCommandParser
+activate FindCommandParser
+
+FindCommandParser --> MedmoriserParser
+deactivate FindCommandParser
+
+MedmoriserParser -> FindCommandParser : parse("Immunology")
+activate FindCommandParser
+
+create FindCommand
+FindCommandParser -> FindCommand
+activate FindCommand
+
+FindCommand --> FindCommandParser : f
+deactivate FindCommand
+
+FindCommandParser --> MedmoriserParser : f
+deactivate FindCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+FindCommandParser -[hidden]-> MedmoriserParser
+destroy FindCommandParser
+
+MedmoriserParser --> LogicManager : f
+deactivate MedmoriserParser
+
+LogicManager -> FindCommand : execute()
+activate FindCommand
+
+FindCommand -> Model : updateFilteredQAndAList(predicate)
+activate Model
+
+Model --> FindCommand
+deactivate Model
+
+create CommandResult
+FindCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> FindCommand
+deactivate CommandResult
+
+FindCommand --> LogicManager : result
+deactivate FindCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/ListActivityDiagram.puml b/docs/diagrams/ListActivityDiagram.puml
new file mode 100644
index 00000000000..1c1602a3425
--- /dev/null
+++ b/docs/diagrams/ListActivityDiagram.puml
@@ -0,0 +1,12 @@
+@startuml
+:User enters list command;
+:User input is parsed;
+:Update model to return all QAndAs;
+:Check if answers are to be displayed;
+if () then ([answersDisplayed])
+ :Set answers to be visible;
+else ([else])
+ :Set answers to be hidden;
+endif
+:Show all QAndAs on GUI;
+@enduml
diff --git a/docs/diagrams/ListSequenceDiagram.puml b/docs/diagrams/ListSequenceDiagram.puml
new file mode 100644
index 00000000000..a5fa5fb2e65
--- /dev/null
+++ b/docs/diagrams/ListSequenceDiagram.puml
@@ -0,0 +1,89 @@
+@startuml
+!include style.puml
+
+box Ui UI_COLOR_T1
+participant ":MainWindow" as MainWindow UI_COLOR
+end box
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":MedmoriserParser" as MedmoriserParser LOGIC_COLOR
+participant ":ListCommandParser" as ListCommandParser LOGIC_COLOR
+participant "l:ListCommand" as ListCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> MainWindow
+activate MainWindow
+MainWindow -> MainWindow : executeCommand("list questions")
+activate MainWindow #cecece
+
+MainWindow -> LogicManager : execute("list questions")
+activate LogicManager
+
+LogicManager -> MedmoriserParser : parseCommand("list questions")
+activate MedmoriserParser
+
+create ListCommandParser
+MedmoriserParser -> ListCommandParser
+activate ListCommandParser
+
+ListCommandParser --> MedmoriserParser
+deactivate ListCommandParser
+
+MedmoriserParser -> ListCommandParser : parse("questions")
+activate ListCommandParser
+
+create ListCommand
+ListCommandParser -> ListCommand
+activate ListCommand
+
+ListCommand --> ListCommandParser : l
+deactivate ListCommand
+
+ListCommandParser --> MedmoriserParser : l
+deactivate ListCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+ListCommandParser -[hidden]-> MedmoriserParser
+destroy ListCommandParser
+
+MedmoriserParser --> LogicManager : l
+deactivate MedmoriserParser
+
+LogicManager -> ListCommand : execute()
+activate ListCommand
+
+ListCommand -> Model : updateFilteredQAndAList(predicate)
+activate Model
+
+Model --> ListCommand
+deactivate Model
+
+create CommandResult
+ListCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> ListCommand
+deactivate CommandResult
+
+ListCommand --> LogicManager : result
+deactivate ListCommand
+
+MainWindow <--LogicManager : result
+deactivate LogicManager
+
+MainWindow -> MainWindow : handleList()
+activate MainWindow #949494
+
+MainWindow --> MainWindow
+deactivate MainWindow
+
+MainWindow --> MainWindow
+deactivate MainWindow
+[<--MainWindow
+
+@enduml
diff --git a/docs/diagrams/LogicClassDiagram.puml b/docs/diagrams/LogicClassDiagram.puml
index 016ef33e2e2..7f6708e37cb 100644
--- a/docs/diagrams/LogicClassDiagram.puml
+++ b/docs/diagrams/LogicClassDiagram.puml
@@ -8,7 +8,7 @@ package Logic {
package Parser {
Interface Parser <>
-Class AddressBookParser
+Class MedmoriserParser
Class XYZCommandParser
Class CliSyntax
Class ParserUtil
@@ -35,8 +35,8 @@ Class HiddenOutside #FFFFFF
HiddenOutside ..> Logic
LogicManager .up.|> Logic
-LogicManager -->"1" AddressBookParser
-AddressBookParser .left.> XYZCommandParser: creates >
+LogicManager -->"1" MedmoriserParser
+MedmoriserParser .left.> XYZCommandParser: creates >
XYZCommandParser ..> XYZCommand : creates >
XYZCommandParser ..|> Parser
diff --git a/docs/diagrams/ModelClassDiagram.puml b/docs/diagrams/ModelClassDiagram.puml
index e85a00d4107..b9f1832525b 100644
--- a/docs/diagrams/ModelClassDiagram.puml
+++ b/docs/diagrams/ModelClassDiagram.puml
@@ -5,23 +5,21 @@ skinparam arrowColor MODEL_COLOR
skinparam classBackgroundColor MODEL_COLOR
Package Model <>{
-Interface ReadOnlyAddressBook <>
+Interface ReadOnlyMedmoriser <>
Interface Model <>
Interface ObservableList <>
-Class AddressBook
-Class ReadOnlyAddressBook
+Class Medmoriser
+Class ReadOnlyMedmoriser
Class Model
Class ModelManager
Class UserPrefs
Class ReadOnlyUserPrefs
-Package Person {
-Class Person
-Class Address
-Class Email
-Class Name
-Class Phone
-Class UniquePersonList
+Package QAndA {
+Class QAndA
+Class Answer
+Class Question
+Class UniqueQAndAList
}
Package Tag {
@@ -32,25 +30,19 @@ Class Tag
Class HiddenOutside #FFFFFF
HiddenOutside ..> Model
-AddressBook .up.|> ReadOnlyAddressBook
+Medmoriser .up.|> ReadOnlyMedmoriser
ModelManager .up.|> Model
Model .right.> ObservableList
-ModelManager o--> "1" AddressBook
+ModelManager o--> "1" Medmoriser
ModelManager o-left-> "1" UserPrefs
UserPrefs .up.|> ReadOnlyUserPrefs
-AddressBook *--> "1" UniquePersonList
-UniquePersonList o--> "*" Person
-Person *--> Name
-Person *--> Phone
-Person *--> Email
-Person *--> Address
-Person *--> "*" Tag
+Medmoriser *--> "1" UniqueQAndAList
+UniqueQAndAList o--> "*" QAndA
+QAndA *--> Question
+QAndA *--> Answer
+QAndA *--> "*" Tag
-Name -[hidden]right-> Phone
-Phone -[hidden]right-> Address
-Address -[hidden]right-> Email
-
-ModelManager -->"1" Person : filtered list
+ModelManager -->"1" QAndA : filtered list
@enduml
diff --git a/docs/diagrams/QuizActivityDiagram.puml b/docs/diagrams/QuizActivityDiagram.puml
new file mode 100644
index 00000000000..2eb6a176549
--- /dev/null
+++ b/docs/diagrams/QuizActivityDiagram.puml
@@ -0,0 +1,20 @@
+@startuml
+start
+:Quiz command executed;
+:Parse the quiz command;
+
+if () then ([valid command])
+ : Identify command type;
+ if () then ([quiz by tags])
+ :retrieve tag predicate;
+ else ([quiz by questions])
+ :retrieve question predicate;
+ endif
+ :Randomly select a question based on predicate;
+
+else ([invalid command])
+ :Invalid Command;
+endif
+:show on GUI;
+stop
+@enduml
diff --git a/docs/diagrams/QuizSequenceDiagram.puml b/docs/diagrams/QuizSequenceDiagram.puml
new file mode 100644
index 00000000000..75a8eed267e
--- /dev/null
+++ b/docs/diagrams/QuizSequenceDiagram.puml
@@ -0,0 +1,73 @@
+@startuml
+!include style.puml
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":MedmoriserParser" as MedmoriserParser MEDMORISER_PARSER_COLOR
+participant ":QuizCommandParser" as QuizCommandParser COMMAND_PARSER_COLOR
+participant "f:QuizCommand" as QuizCommand COMMAND_COLOR
+participant ":CommandResult" as CommandResult COMMAND_RESULT_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("quiz t/Infections")
+activate LogicManager
+
+LogicManager -> MedmoriserParser : parseCommand("quiz t/Infections")
+activate MedmoriserParser
+
+create QuizCommandParser
+MedmoriserParser -> QuizCommandParser
+activate QuizCommandParser
+
+QuizCommandParser --> MedmoriserParser
+deactivate QuizCommandParser
+
+MedmoriserParser -> QuizCommandParser : parse("t/Infections")
+activate QuizCommandParser
+
+create QuizCommand
+QuizCommandParser -> QuizCommand
+activate QuizCommand
+
+QuizCommand --> QuizCommandParser : f
+deactivate QuizCommand
+
+QuizCommandParser --> MedmoriserParser : f
+deactivate QuizCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+QuizCommandParser -[hidden]-> MedmoriserParser
+destroy QuizCommandParser
+
+MedmoriserParser --> LogicManager : f
+deactivate MedmoriserParser
+
+LogicManager -> QuizCommand : execute()
+activate QuizCommand
+
+QuizCommand -> QuizCommand : getRandomQuestion(filteredList)
+
+QuizCommand -> Model : updateFilteredQAndAList(x -> x.equals(question))
+activate Model
+
+Model --> QuizCommand
+deactivate Model
+
+QuizCommand -> QuizCommand : setIsQuiz(true, model)
+
+create CommandResult
+QuizCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> QuizCommand
+deactivate CommandResult
+
+QuizCommand --> LogicManager : result
+deactivate QuizCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/StorageClassDiagram.puml b/docs/diagrams/StorageClassDiagram.puml
index 6adb2e156bf..bc4d2fa78a1 100644
--- a/docs/diagrams/StorageClassDiagram.puml
+++ b/docs/diagrams/StorageClassDiagram.puml
@@ -6,19 +6,19 @@ skinparam classBackgroundColor STORAGE_COLOR
Interface Storage <>
Interface UserPrefsStorage <>
-Interface AddressBookStorage <>
+Interface MedmoriserStorage <>
Class StorageManager
Class JsonUserPrefsStorage
-Class JsonAddressBookStorage
+Class JsonMedmoriserStorage
StorageManager .left.|> Storage
StorageManager o-right-> UserPrefsStorage
-StorageManager o--> AddressBookStorage
+StorageManager o--> MedmoriserStorage
JsonUserPrefsStorage .left.|> UserPrefsStorage
-JsonAddressBookStorage .left.|> AddressBookStorage
-JsonAddressBookStorage .down.> JsonSerializableAddressBookStorage
-JsonSerializableAddressBookStorage .right.> JsonSerializablePerson
-JsonSerializablePerson .right.> JsonAdaptedTag
+JsonMedmoriserStorage .left.|> MedmoriserStorage
+JsonMedmoriserStorage .down.> JsonSerializableMedmoriserStorage
+JsonSerializableMedmoriserStorage .right.> JsonAdaptedQAndA
+JsonAdaptedQAndA .right.> JsonAdaptedTag
@enduml
diff --git a/docs/diagrams/style.puml b/docs/diagrams/style.puml
index fad8b0adeaa..5fa3d42be63 100644
--- a/docs/diagrams/style.puml
+++ b/docs/diagrams/style.puml
@@ -7,60 +7,68 @@
'T1 through T4 are shades of the original color from lightest to darkest
-!define UI_COLOR #1D8900
-!define UI_COLOR_T1 #83E769
-!define UI_COLOR_T2 #3FC71B
+!define UI_COLOR #F28080
+!define UI_COLOR_T1 #D97373
+!define UI_COLOR_T2 #BF6565
!define UI_COLOR_T3 #166800
!define UI_COLOR_T4 #0E4100
-!define LOGIC_COLOR #3333C4
-!define LOGIC_COLOR_T1 #C8C8FA
+!define LOGIC_COLOR #A9EEE6
+!define LOGIC_COLOR_T1 #8BC4BE
!define LOGIC_COLOR_T2 #6A6ADC
!define LOGIC_COLOR_T3 #1616B0
!define LOGIC_COLOR_T4 #101086
-!define MODEL_COLOR #9D0012
-!define MODEL_COLOR_T1 #F97181
+!define MODEL_COLOR #C4AEE6
+!define MODEL_COLOR_T1 v
!define MODEL_COLOR_T2 #E41F36
!define MODEL_COLOR_T3 #7B000E
!define MODEL_COLOR_T4 #51000A
-!define STORAGE_COLOR #A38300
-!define STORAGE_COLOR_T1 #FFE374
+!define STORAGE_COLOR #B3BD84
+!define STORAGE_COLOR_T1 #E4F0A8
!define STORAGE_COLOR_T2 #EDC520
!define STORAGE_COLOR_T3 #806600
!define STORAGE_COLOR_T2 #544400
+!define MEDMORISER_PARSER_COLOR #EDC1C0
+!define COMMAND_PARSER_COLOR #EDC891
+
+!define COMMAND_COLOR #83A6DE
+
+!define COMMAND_RESULT_COLOR #C78FAB
+
!define USER_COLOR #000000
-skinparam BackgroundColor #FFFFFFF
+skinparam BackgroundColor #FEFAEC
skinparam Shadowing false
skinparam Class {
- FontColor #FFFFFF
+ FontColor #000000
BorderThickness 1
BorderColor #FFFFFF
StereotypeFontColor #FFFFFF
- FontName Arial
+ FontName Roboto Light
}
skinparam Actor {
BorderColor USER_COLOR
Color USER_COLOR
- FontName Arial
+ FontName Roboto Light
}
skinparam Sequence {
MessageAlign center
BoxFontSize 15
BoxPadding 0
- BoxFontColor #FFFFFF
- FontName Arial
+ BoxFontColor #000000
+ FontName Roboto Light
}
skinparam Participant {
- FontColor #FFFFFFF
+ FontColor #000000
+ FontName Roboto Light
Padding 20
}
diff --git a/docs/diagrams/tracing/LogicSequenceDiagram.puml b/docs/diagrams/tracing/LogicSequenceDiagram.puml
index fdcbe1c0ccc..5c881e25367 100644
--- a/docs/diagrams/tracing/LogicSequenceDiagram.puml
+++ b/docs/diagrams/tracing/LogicSequenceDiagram.puml
@@ -13,7 +13,7 @@ create ecp
abp -> ecp
abp -> ecp ++: parse(arguments)
create ec
-ecp -> ec ++: index, editPersonDescriptor
+ecp -> ec ++: index, editQAndADescriptor
ec --> ecp --
ecp --> abp --: command
abp --> logic --: command
diff --git a/docs/images/AddCommandEg1.png b/docs/images/AddCommandEg1.png
new file mode 100644
index 00000000000..12370acc855
Binary files /dev/null and b/docs/images/AddCommandEg1.png differ
diff --git a/docs/images/AddCommandEg2.png b/docs/images/AddCommandEg2.png
new file mode 100644
index 00000000000..722ca4bcf0b
Binary files /dev/null and b/docs/images/AddCommandEg2.png differ
diff --git a/docs/images/AddCommandEg3.png b/docs/images/AddCommandEg3.png
new file mode 100644
index 00000000000..19ae1ce4907
Binary files /dev/null and b/docs/images/AddCommandEg3.png differ
diff --git a/docs/images/AddCommandEg4.png b/docs/images/AddCommandEg4.png
new file mode 100644
index 00000000000..7ea8237e793
Binary files /dev/null and b/docs/images/AddCommandEg4.png differ
diff --git a/docs/images/AddSequenceDiagram.png b/docs/images/AddSequenceDiagram.png
new file mode 100644
index 00000000000..b3765daedbe
Binary files /dev/null and b/docs/images/AddSequenceDiagram.png differ
diff --git a/docs/images/ArchitectureDiagram.png b/docs/images/ArchitectureDiagram.png
index 5cdcf67e747..2fcfa1e8c72 100644
Binary files a/docs/images/ArchitectureDiagram.png and b/docs/images/ArchitectureDiagram.png differ
diff --git a/docs/images/ArchitectureSequenceDiagram.png b/docs/images/ArchitectureSequenceDiagram.png
index 2f1346869d0..225d190b810 100644
Binary files a/docs/images/ArchitectureSequenceDiagram.png and b/docs/images/ArchitectureSequenceDiagram.png differ
diff --git a/docs/images/BetterModelClassDiagram.png b/docs/images/BetterModelClassDiagram.png
index bc7ed18ae29..498a1e0e116 100644
Binary files a/docs/images/BetterModelClassDiagram.png and b/docs/images/BetterModelClassDiagram.png differ
diff --git a/docs/images/ChengJiyuqing.png b/docs/images/ChengJiyuqing.png
new file mode 100644
index 00000000000..56a948aea15
Binary files /dev/null and b/docs/images/ChengJiyuqing.png differ
diff --git a/docs/images/DeleteActivityDiagram.png b/docs/images/DeleteActivityDiagram.png
new file mode 100644
index 00000000000..1cd24469120
Binary files /dev/null and b/docs/images/DeleteActivityDiagram.png differ
diff --git a/docs/images/DeleteContext.png b/docs/images/DeleteContext.png
new file mode 100644
index 00000000000..58da814f813
Binary files /dev/null and b/docs/images/DeleteContext.png differ
diff --git a/docs/images/DeleteResult.png b/docs/images/DeleteResult.png
new file mode 100644
index 00000000000..09df4b09a77
Binary files /dev/null and b/docs/images/DeleteResult.png differ
diff --git a/docs/images/DeleteSequenceDiagram.png b/docs/images/DeleteSequenceDiagram.png
index fa327b39618..27f3a9c1ee8 100644
Binary files a/docs/images/DeleteSequenceDiagram.png and b/docs/images/DeleteSequenceDiagram.png differ
diff --git a/docs/images/EditContext.png b/docs/images/EditContext.png
new file mode 100644
index 00000000000..8fed3857a24
Binary files /dev/null and b/docs/images/EditContext.png differ
diff --git a/docs/images/EditResult.png b/docs/images/EditResult.png
new file mode 100644
index 00000000000..8e905992aa4
Binary files /dev/null and b/docs/images/EditResult.png differ
diff --git a/docs/images/FindActivityDiagram.png b/docs/images/FindActivityDiagram.png
new file mode 100644
index 00000000000..a8586eb08c4
Binary files /dev/null and b/docs/images/FindActivityDiagram.png differ
diff --git a/docs/images/FindContext.PNG b/docs/images/FindContext.PNG
new file mode 100644
index 00000000000..f114df90c3c
Binary files /dev/null and b/docs/images/FindContext.PNG differ
diff --git a/docs/images/FindResult.PNG b/docs/images/FindResult.PNG
new file mode 100644
index 00000000000..341997180bc
Binary files /dev/null and b/docs/images/FindResult.PNG differ
diff --git a/docs/images/FindSequenceDiagram.png b/docs/images/FindSequenceDiagram.png
new file mode 100644
index 00000000000..dbac0869010
Binary files /dev/null and b/docs/images/FindSequenceDiagram.png differ
diff --git a/docs/images/ListActivityDiagram.png b/docs/images/ListActivityDiagram.png
new file mode 100644
index 00000000000..06e96f8c322
Binary files /dev/null and b/docs/images/ListActivityDiagram.png differ
diff --git a/docs/images/ListCommand.png b/docs/images/ListCommand.png
new file mode 100644
index 00000000000..6c46dc1e123
Binary files /dev/null and b/docs/images/ListCommand.png differ
diff --git a/docs/images/ListQuestionsCommand.png b/docs/images/ListQuestionsCommand.png
new file mode 100644
index 00000000000..b1a457b926f
Binary files /dev/null and b/docs/images/ListQuestionsCommand.png differ
diff --git a/docs/images/ListSequenceDiagram.png b/docs/images/ListSequenceDiagram.png
new file mode 100644
index 00000000000..bc739007783
Binary files /dev/null and b/docs/images/ListSequenceDiagram.png differ
diff --git a/docs/images/LogicClassDiagram.png b/docs/images/LogicClassDiagram.png
index b9e853cef12..661e01ba574 100644
Binary files a/docs/images/LogicClassDiagram.png and b/docs/images/LogicClassDiagram.png differ
diff --git a/docs/images/ModelClassDiagram.png b/docs/images/ModelClassDiagram.png
index 280064118cf..332b016b92a 100644
Binary files a/docs/images/ModelClassDiagram.png and b/docs/images/ModelClassDiagram.png differ
diff --git a/docs/images/NextContext.png b/docs/images/NextContext.png
new file mode 100644
index 00000000000..8b8a8ae008f
Binary files /dev/null and b/docs/images/NextContext.png differ
diff --git a/docs/images/NextResult.png b/docs/images/NextResult.png
new file mode 100644
index 00000000000..ff75120a8d4
Binary files /dev/null and b/docs/images/NextResult.png differ
diff --git a/docs/images/QuizActivityDiagram.png b/docs/images/QuizActivityDiagram.png
new file mode 100644
index 00000000000..27a531313b8
Binary files /dev/null and b/docs/images/QuizActivityDiagram.png differ
diff --git a/docs/images/QuizContext.png b/docs/images/QuizContext.png
new file mode 100644
index 00000000000..94ec28def02
Binary files /dev/null and b/docs/images/QuizContext.png differ
diff --git a/docs/images/QuizResult.png b/docs/images/QuizResult.png
new file mode 100644
index 00000000000..da5f574c5f4
Binary files /dev/null and b/docs/images/QuizResult.png differ
diff --git a/docs/images/QuizSequenceDiagram.png b/docs/images/QuizSequenceDiagram.png
new file mode 100644
index 00000000000..7c146250e31
Binary files /dev/null and b/docs/images/QuizSequenceDiagram.png differ
diff --git a/docs/images/StorageClassDiagram.png b/docs/images/StorageClassDiagram.png
index d87c1216820..e3c26e677b7 100644
Binary files a/docs/images/StorageClassDiagram.png and b/docs/images/StorageClassDiagram.png differ
diff --git a/docs/images/Ui.png b/docs/images/Ui.png
index 5bd77847aa2..fa80209ce24 100644
Binary files a/docs/images/Ui.png and b/docs/images/Ui.png differ
diff --git a/docs/images/UiClassDiagram.png b/docs/images/UiClassDiagram.png
index 7b4b3dbea45..5923d07ed3c 100644
Binary files a/docs/images/UiClassDiagram.png and b/docs/images/UiClassDiagram.png differ
diff --git a/docs/images/bluesky0911.png b/docs/images/bluesky0911.png
new file mode 100644
index 00000000000..23e3045c34d
Binary files /dev/null and b/docs/images/bluesky0911.png differ
diff --git a/docs/images/chengjiyuqing.png b/docs/images/chengjiyuqing.png
new file mode 100644
index 00000000000..56a948aea15
Binary files /dev/null and b/docs/images/chengjiyuqing.png differ
diff --git a/docs/images/jonfoocy.png b/docs/images/jonfoocy.png
new file mode 100644
index 00000000000..5e060533734
Binary files /dev/null and b/docs/images/jonfoocy.png differ
diff --git a/docs/images/joshruien.png b/docs/images/joshruien.png
new file mode 100644
index 00000000000..86230afe9b0
Binary files /dev/null and b/docs/images/joshruien.png differ
diff --git a/docs/images/tengjianling.png b/docs/images/tengjianling.png
new file mode 100644
index 00000000000..76bc82fce72
Binary files /dev/null and b/docs/images/tengjianling.png differ
diff --git a/docs/images/yongmingyang.png b/docs/images/yongmingyang.png
new file mode 100644
index 00000000000..d30ed663eee
Binary files /dev/null and b/docs/images/yongmingyang.png differ
diff --git a/docs/index.md b/docs/index.md
index 7601dbaad0d..33ab3e1e3bc 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,6 +1,6 @@
---
layout: page
-title: AddressBook Level-3
+title: Medmoriser
---
[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/se-edu/addressbook-level3/actions)
@@ -8,12 +8,13 @@ title: AddressBook Level-3
![Ui](images/Ui.png)
-**AddressBook is a desktop application for managing your contact details.** While it has a GUI, most of the user interactions happen using a CLI (Command Line Interface).
+**Medmoriser** is a desktop app, optimized for the CLI, which helps medical students memorise and revise their content. It aids users in practising active recall to improve their retention of key information.
-* If you are interested in using AddressBook, head over to the [_Quick Start_ section of the **User Guide**](UserGuide.html#quick-start).
-* If you are interested about developing AddressBook, the [**Developer Guide**](DeveloperGuide.html) is a good place to start.
+* If you are interested in using Medmoriser, head over to the [**User Guide**](UserGuide.html) to get started.
+* If you are interested in helping to develop Medmoriser, the [**Developer Guide**](DeveloperGuide.html) is a good place to start.
**Acknowledgements**
* Libraries used: [JavaFX](https://openjfx.io/), [Jackson](https://github.com/FasterXML/jackson), [JUnit5](https://github.com/junit-team/junit5)
+* This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative](https://se-education.org).
diff --git a/docs/team/chengjiyuqing.md b/docs/team/chengjiyuqing.md
new file mode 100644
index 00000000000..7494b6c1ec8
--- /dev/null
+++ b/docs/team/chengjiyuqing.md
@@ -0,0 +1,41 @@
+---
+layout: page
+title: Cheng Jiyuqing's Project Portfolio Page
+---
+
+
+## Project: Medmoriser
+
+Medmoriser is a desktop app to help medical students organise, memorise and revise their content. The user interacts with it using a CLI, and it has a GUI created with JavaFX and is written in Java.
+
+Given below are my contributions to the project.
+
+
+* **Code contributed**: [RepoSense Link](https://nus-cs2103-ay2021s1.github.io/tp-dashboard/#breakdown=true&search=chengjiyuqing)
+
+* **Project management**:
+ * Managed releases `v1.2` - `v1.4` (3 releases) on GitHub
+
+* **Enhancements to existing features**:
+ * Created new GUI component QuizCard to acommodate Quiz command, Answer command, Endquiz command and Next command
+ (Pull request [\#77](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/77) [\#161](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/161))
+ This is very hard because I have to coordinate among various Logic commands and UI.
+ * Updated the GUI color scheme (Pull request [\#77](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/77))
+ * Changed cells in GUI to rounded corners (Pull request [\#77](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/77)[\#162](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/162))
+ * Moved CommandBox to the bottom (Pull request [\#162](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/162))
+ * Set Tag to wrap text, so that long tag text will not be cut off.[\#158](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/158)
+
+* **Documentation**:
+ * User Guide:
+ * Added introduction to each section [\#95](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/95)
+ * Added details and photos to `Add` feature. [\#158](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/158)
+ * Developer Guide:
+ * Addded architecture diagram [\#182](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/182)
+ * Added implementation details of the `Add` feature. [\#182](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/182)
+ * Added sequence diagram for `Add` Feature (Figure 1.1) [\#182](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/182)
+ * Added User Stories, Value Props and target audience. [\#33](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/33)
+
+
+* **Community**:
+ * Contributed to forum discussions (examples: [1](https://github.com/nus-cs2103-AY2021S1/forum/issues/36))
+ * Reported bugs and suggestions for other teams in the class (examples: [1](https://github.com/AY2021S1-CS2103T-W12-2/tp/issues/158), [2](https://github.com/AY2021S1-CS2103T-W12-2/tp/issues/157), [3](https://github.com/AY2021S1-CS2103T-W12-2/tp/issues/155))
diff --git a/docs/team/johndoe.md b/docs/team/johndoe.md
deleted file mode 100644
index 1f1e9e6f6db..00000000000
--- a/docs/team/johndoe.md
+++ /dev/null
@@ -1,46 +0,0 @@
----
-layout: page
-title: John Doe's Project Portfolio Page
----
-
-## Project: AddressBook Level 3
-
-AddressBook - Level 3 is a desktop address book application used for teaching Software Engineering principles. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC.
-
-Given below are my contributions to the project.
-
-* **New Feature**: Added the ability to undo/redo previous commands.
- * What it does: allows the user to undo all previous commands one at a time. Preceding undo commands can be reversed by using the redo command.
- * Justification: This feature improves the product significantly because a user can make mistakes in commands and the app should provide a convenient way to rectify them.
- * Highlights: This enhancement affects existing commands and commands to be added in future. It required an in-depth analysis of design alternatives. The implementation too was challenging as it required changes to existing commands.
- * Credits: *{mention here if you reused any code/ideas from elsewhere or if a third-party library is heavily used in the feature so that a reader can make a more accurate judgement of how much effort went into the feature}*
-
-* **New Feature**: Added a history command that allows the user to navigate to previous commands using up/down keys.
-
-* **Code contributed**: [RepoSense link]()
-
-* **Project management**:
- * Managed releases `v1.3` - `v1.5rc` (3 releases) on GitHub
-
-* **Enhancements to existing features**:
- * Updated the GUI color scheme (Pull requests [\#33](), [\#34]())
- * Wrote additional tests for existing features to increase coverage from 88% to 92% (Pull requests [\#36](), [\#38]())
-
-* **Documentation**:
- * User Guide:
- * Added documentation for the features `delete` and `find` [\#72]()
- * Did cosmetic tweaks to existing documentation of features `clear`, `exit`: [\#74]()
- * Developer Guide:
- * Added implementation details of the `delete` feature.
-
-* **Community**:
- * PRs reviewed (with non-trivial review comments): [\#12](), [\#32](), [\#19](), [\#42]()
- * Contributed to forum discussions (examples: [1](), [2](), [3](), [4]())
- * Reported bugs and suggestions for other teams in the class (examples: [1](), [2](), [3]())
- * Some parts of the history feature I added was adopted by several other class mates ([1](), [2]())
-
-* **Tools**:
- * Integrated a third party library (Natty) to the project ([\#42]())
- * Integrated a new Github plugin (CircleCI) to the team repo
-
-* _{you can add/remove categories in the list above}_
diff --git a/docs/team/jonfoocy.md b/docs/team/jonfoocy.md
new file mode 100644
index 00000000000..81f691d0823
--- /dev/null
+++ b/docs/team/jonfoocy.md
@@ -0,0 +1,44 @@
+---
+layout: page
+title: Jonathan Foo Chee Yong's Project Portfolio Page
+---
+
+## Project: Medmoriser
+
+Medmoriser is a desktop app to help medical students organise, memorise and revise their content. The user interacts with it using a CLI, and it has a GUI created with JavaFX and is written in Java.
+
+Given below are my contributions to the project.
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2021s1.github.io/tp-dashboard/#breakdown=true&search=jonfoocy)
+
+* **Project management**:
+ * Managed releases `v1.3` (1 release) on GitHub
+
+* **Enhancements to existing features**:
+ * Refactored AddressBook-Level3 code for v1.2
+ * Changed classes, variables and other instances of `Name` → `Question`, `AddressBook` → `Medmoriser` [\#38](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/38).
+
+ * Added the ability to hide answers from the main view [\#57](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/57), [\#136](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/136)
+ * What it does: Allows the user to hide the answer when browsing the list of QAndAs
+ 1. `list` which allows to user to view all QAndAs, with questions and answers all visible.
+ 2. `list questions` which allows the user to view all QAndAs, with questions visible and answers hidden.
+ * Justification: Gives the user the flexibility to choose the preferred mode of viewing,
+ and to prevent seeing the answer before quizzing.
+ * Added new test cases to ensure the new functionality worked in conjunction with existing features [\#60](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/60), [\#136](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/136)
+
+* **Documentation**:
+ * Project Website:
+ * Updated the website with project and team writeup [\#14](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/14), [\#30](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/30).
+
+ * User Guide:
+ * Updated/modified User Guide to ensure currency and formatting consistency: [\#72](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/72), [\#74](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/74), [\#170](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/170).
+ * Added the documentation for the `list` feature [\#91](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/91).
+
+ * Developer Guide:
+ * Added implementation details of the `list` feature [\#84](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/84).
+ * Updated Developer Guide to ensure consistency [\#167](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/167)
+
+* **Community**:
+ * PRs reviewed (with non-trivial review comments): [\#73](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/73),
+ [\#77](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/77).
+ * Discovered bugs and gave suggestions for other teams in the class: [\#200](https://github.com/AY2021S1-CS2103T-W10-1/tp/issues/200), [\#201](https://github.com/AY2021S1-CS2103T-W10-1/tp/issues/201), [\#202](https://github.com/AY2021S1-CS2103T-W10-1/tp/issues/202), [\#203](https://github.com/AY2021S1-CS2103T-W10-1/tp/issues/203), [\#204](https://github.com/AY2021S1-CS2103T-W10-1/tp/issues/204).
diff --git a/docs/team/joshruien.md b/docs/team/joshruien.md
new file mode 100644
index 00000000000..c6125dc5a17
--- /dev/null
+++ b/docs/team/joshruien.md
@@ -0,0 +1,58 @@
+---
+layout: page
+title: Joshua Tan's Project Portfolio Page
+---
+
+## Project: Medmoriser
+
+Medmoriser is a desktop app to help medical students organise, memorise and revise their content. The user interacts with it using a CLI, and it has a GUI created with JavaFX and is written in Java.
+
+Given below are my contributions to the project.
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2021s1.github.io/tp-dashboard/#breakdown=true&search=joshruien)
+
+* **New Feature**: Added a quiz feature for users to test themselves.
+ * What it does: Allows users to quiz themselves to test their memory on the answers to the questions. Medmoriser selects a random question based on the keywords that users input and quizzes them. After answering the question, the answer to the question will show up so that users can check their answers.
+ * Justification: This feature improves the product significantly because our app utilizes active recall to help users to memorise their content. Active recall is a proven study technique to help improve memory.
+ * Highlights:
+ * It required an in-depth analysis of design alternatives challenging as it was an entirely new feature on its own.
+ * It required commands to be created. Other commands created for this feature are `answer` and `endquiz`.
+ * New command classes and their parser classes had to be created.
+ * New test classes to test our features.
+ * This feature was rather challenging to implement. We had to keep track of the state, whether there was an ongoing quiz or not. Furthermore, we had to ensure a flow (ie. answer command comes after quiz command), whereas for the existing commands, they were one off commands. Hence it was challenging to implement the carrying over of the state across different commands.
+
+* **New Feature**: Added an answer feature for users to answer the quiz question.
+ * What it does: Allows users to answer the quiz question.
+ * Justification: This feature improves the product significantly as users are able to check their input answer against the answer that was keyed into Medmoriser for that particular question. This way they will know whether they could remember what they learnt.
+ * Highlights:
+ * It required a lot of error checking, to ensure that this command could only be called when there was an ongoing quiz and when the question has not yet been answered.
+
+* **New Feature**: Added an end quiz feature when users are done with the quiz.
+ * What it does: Allows users to end an ongoing quiz. When there is an ongoing quiz, users have to first end the quiz before being able to run other commands other than `answer` and `next`.
+
+* **Enhancements to existing features**:
+ * Updated the list command to show QAndAs (Pull requests [\#40](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/40))
+ * Updated the edit and add command examples (Pull requests [\#137](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/137))
+ * Redefined add and edit functions such that there can only be a limit of 1 prefix in the user input. (Pull requests [\#154](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/154))
+ * Wrote additional tests: `AddCommandParserTest`, `EditCommandParserTest` , `NextCommandTest`, `QuizCommandParserTest`. (Pull requests [\#154](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/154) ,[\#160](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/160), [\#171](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/171))
+ * Refactoring: Removed space between prefix and parameters for quiz and find command. (Pull Requests [#65](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/65))
+ * Refactoring: Removed AB3 phone and email instances. (Pull Requests [\#71](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/71))
+
+* **Documentation**:
+ * User Guide:
+ * Added documentation for the features `quiz` and `answer` and `endquiz`.
+ * Pull Requests: [\#85](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/85), [\#141](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/141), [\#155](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/155)
+ * Added documentation for the command summary.
+ * Pull Requests: [\#85](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/85), [\#141](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/141)
+ * Developer Guide:
+ * Added implementation details of the `quiz` feature.
+ * Pull Requests: [\#85](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/85), [\#94](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/94), [\#166](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/166)
+ * Added user stories.
+ * Pull Requests: [\#19](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/19)
+ * Edited the architecture diagrams to suit our application.
+ * Pull Requests: [\#176](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/176)
+
+* **Community**:
+ * PRs reviewed (with non-trivial review comments): [\#138](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/138)
+ * Reported bugs and suggestions for other teams in the class [1](https://github.com/AY2021S1-CS2103T-W13-1/tp/issues/174), [2](https://github.com/AY2021S1-CS2103T-W13-1/tp/issues/175), [3](https://github.com/AY2021S1-CS2103T-W13-1/tp/issues/176), [4](https://github.com/AY2021S1-CS2103T-W13-1/tp/issues/177), [5](https://github.com/AY2021S1-CS2103T-W13-1/tp/issues/178), [6](https://github.com/AY2021S1-CS2103T-W13-1/tp/issues/179), [7](https://github.com/AY2021S1-CS2103T-W13-1/tp/issues/180)
+
diff --git a/docs/team/tengjianling.md b/docs/team/tengjianling.md
new file mode 100644
index 00000000000..869cd063a59
--- /dev/null
+++ b/docs/team/tengjianling.md
@@ -0,0 +1,46 @@
+---
+layout: page
+title: Teng Jian Ling's Project Portfolio Page
+---
+
+### Project: Medmoriser
+
+Medmoriser is a desktop app to help medical students organise, memorise and revise their content. The user interacts with it using a CLI, and it has a GUI created with JavaFX and is written in Java.
+
+Given below are my contributions to the project.
+
+- **Code contributed:** [RepoSense Link](https://nus-cs2103-ay2021s1.github.io/tp-dashboard/#breakdown=true&search=tengjianling)
+
+- **New feature:** Added a `next` command for the user to move on to the next question in the quiz.
+ - What it does: allows the user to be tested on another question based on the same keywords provided for the current quiz session, without having to end the quiz first.
+ - Justification: This feature improves the product significantly because a user may want to test themselves on multiple questions with the same keywords specified, and the app should provide a convenient way for them to do this.
+ - Highlights: The implementation of this enchancement was challenging due to the following reasons:
+ - This enhancement required an in-depth analysis of design alternatives to find the best design choice.
+ - There was a need to make sure repeated questions are not shown
+ - There was a need to detect when there are no more questions with the keyword specified
+ - There was a need to check whether there is an ongoing quiz when this command is entered
+ - It required changes to existing commands such as `QuizCommand` and `AnswerCommand`
+
+- **Enhancements to Existing features:**
+ - Changed the usage message in the `edit` command to the context of questions and answers: [#41](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/41)
+ - Renamed all uses of `QuestionSet` and `questionSet` to `QAndA` and `qAndA` to avoid confusion between sets and lists: [#43](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/43), [#44](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/44), [#64](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/64)
+ - Changed restrictions on `question`, `answer`, and `tag` fields when adding a QAndA: [#66](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/66)
+ - Changed implementation of `QuizCommand` and `QuizCommandParser` to include ability to start a quiz based on multiple keywords or tags: [#73](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/73)
+ - Wrote the following additional tests: `QuizCommandTest`, `QuizCommandParserTest`, `ExitCommandTest`: [#73](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/73)
+ - increased code coverage by 2.96%
+ - Updated the GUI for quiz to be centralised and remove the question index number: [#83](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/83)
+ - Removed unnecessary 'F1' from the help menu: [#143](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/143)
+ - Wrote the following addtional tests: `AnswerCommandTest` and `AnswerCommandParserTest`: [#157](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/157)
+ - increased code coverage by 1.54%
+
+- **Documentation:**
+ - User Guide:
+ - Added documentation for the features `add` , `delete`, `edit` and `next`: [#18](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/18), [#83](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/83), [#92](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/92), [#153](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/153)
+ - Developer Guide:
+ - Added use cases for Medmoriser: [#18](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/18)
+ - Added implementation details of the `delete` feature, including a sequence diagram and an activity diagram: [#78](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/78)
+ - Added "Appendix: Effort" section: [#163](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/163)
+
+- **Community**:
+ - PRs reviewed with non-trivial review comments: [#71](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/71), [#168](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/168)
+ - Reported bugs and suggestions for other teams in the class (examples: [1](https://github.com/AY2021S1-CS2103T-W16-3/tp/issues/236), [2](https://github.com/AY2021S1-CS2103T-W16-3/tp/issues/237))
diff --git a/docs/team/yongmingyang.md b/docs/team/yongmingyang.md
new file mode 100644
index 00000000000..fee44de09cc
--- /dev/null
+++ b/docs/team/yongmingyang.md
@@ -0,0 +1,48 @@
+---
+layout: page
+title: Yong Ming Yang's Project Portfolio Page
+---
+
+## Project: Medmoriser
+
+Medmoriser is a desktop app to help medical students organise, memorise and revise their content. The user interacts with it using a CLI, and it has a GUI created with JavaFX and is written in Java.
+
+Given below are my contributions to the project.
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2021s1.github.io/tp-dashboard/#breakdown=true&search=yongmingyang)
+
+* **Enhancements to existing features**:
+ * Redefined the Find functionality:
+ * What it does: Allows the user to find based on 3 modes
+ 1. `find t/[tagname]` which allows the user to find QAndA based on the tagname(s).
+ 2. `find q/[keyword]` which allows the user to find QAndA which contains the specified keyword(s) in the question.
+ 3. `find [keyword]` which allows the user to find QAndA which contains the specified keyword(s) in the question or the answer.
+ * Justification: Gives the user more flexibility to find relevant QAndA sets.
+ * Added additional test cases to suit the redefined functionality, increased code coverage by 2.56%: [#58](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/58)
+ * Pull requests (inclusive of bug fixes):
+ 1. [#55](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/55)
+ 2. [#58](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/58)
+ 3. [#68](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/68)
+ 4. [#75](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/75)
+ 5. [#81](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/81)
+ 6. [#138](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/138)
+ 7. [#139](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/139)
+ * Credits: The find functionality makes use of code from the following links:
+ 1. https://stackoverflow.com/questions/36793397/check-if-string-contains-word-not-substring.
+ * Refactoring instances of `Address` to `Answer`, `UniquePersonList` to `UniqueQuestionSetList`, `AddressBook` to `Medmoriser` and `Person` to `QuestionSet` (later changed to QAndA by Jian Ling): [#36](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/36)
+ * Updated GUI, for quizing part in particular: [#46](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/46), [#165](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/165), [#172](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/172)
+
+* **Documentation**:
+ * User Guide:
+ * Minimal base documentation for start of project [#29](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/29)
+ * Add documentation for the `find` feature: [#68](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/68)
+ * Update documentation for improved `find` feature: [#79](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/79)
+ * Did cosmetic tweaks to `find` feature: [#93](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/93)
+ * Developer Guide:
+ * Added implementation details of the `find` feature: [#68](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/68)
+ * Restructured implementation details for all features: [#159](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/159)
+
+* **Community**:
+ * PRs reviewed (with non-trivial review comments): [#38](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/38), [#62](https://github.com/AY2021S1-CS2103T-W15-1/tp/pull/62)
+ * Contributed to forum discussions (examples: [#127](https://github.com/nus-cs2103-AY2021S1/forum/issues/127), [#128](https://github.com/nus-cs2103-AY2021S1/forum/issues/128), [#349](https://github.com/nus-cs2103-AY2021S1/forum/issues/349)
+ * Reported bugs for other teams: [#232](https://github.com/AY2021S1-CS2103T-T12-3/tp/issues/232), [#233](https://github.com/AY2021S1-CS2103T-T12-3/tp/issues/233), [#234](https://github.com/AY2021S1-CS2103T-T12-3/tp/issues/234), [#235](https://github.com/AY2021S1-CS2103T-T12-3/tp/issues/235), [#236](https://github.com/AY2021S1-CS2103T-T12-3/tp/issues/236), [#237](https://github.com/AY2021S1-CS2103T-T12-3/tp/issues/237)
diff --git a/docs/tutorials/AddRemark.md b/docs/tutorials/AddRemark.md
index 6907e29456c..1082c268422 100644
--- a/docs/tutorials/AddRemark.md
+++ b/docs/tutorials/AddRemark.md
@@ -5,7 +5,7 @@ title: "Tutorial: Adding a command"
Let's walk you through the implementation of a new command — `remark`.
-This command allows users of the AddressBook application to add optional remarks to people in their address book and edit it if required. The command should have the following format:
+This command allows users of the AddressBook application to add optional remarks to people in their answer book and edit it if required. The command should have the following format:
`remark INDEX r/REMARK` (e.g., `remark 2 r/Likes baseball`)
@@ -16,19 +16,19 @@ We’ll assume that you have already set up the development environment as outli
Looking in the `logic.command` package, you will notice that each existing command have their own class. All the commands inherit from the abstract class `Command` which means that they must override `execute()`. Each `Command` returns an instance of `CommandResult` upon success and `CommandResult#feedbackToUser` is printed to the `ResultDisplay`.
-Let’s start by creating a new `RemarkCommand` class in the `src/main/java/seedu/address/logic/command` directory.
+Let’s start by creating a new `RemarkCommand` class in the `src/main/java/seedu/answer/logic/command` directory.
For now, let’s keep `RemarkCommand` as simple as possible and print some output. We accomplish that by returning a `CommandResult` with an accompanying message.
**`RemarkCommand.java`:**
``` java
-package seedu.address.logic.commands;
+package seedu.medmoriser.logic.commands;
-import seedu.address.model.Model;
+import seedu.medmoriser.model.Model;
/**
- * Changes the remark of an existing person in the address book.
+ * Changes the remark of an existing qAndA in the answer book.
*/
public class RemarkCommand extends Command {
@@ -64,8 +64,8 @@ Following the convention in other commands, we add relevant messages as constant
**`RemarkCommand.java`:**
``` java
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the remark of the person identified "
- + "by the index number used in the last person listing. "
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the remark of the qAndA identified "
+ + "by the index number used in the last qAndA listing. "
+ "Existing remark will be overwritten by the input.\n"
+ "Parameters: INDEX (must be a positive integer) "
+ "r/ [REMARK]\n"
@@ -89,7 +89,7 @@ Let’s change `RemarkCommand` to parse input from the user.
We start by modifying the constructor of `RemarkCommand` to accept an `Index` and a `String`. While we are at it, let’s change the error message to echo the values. While this is not a replacement for tests, it is an obvious way to tell if our code is functioning as intended.
``` java
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.medmoriser.commons.util.CollectionUtil.requireAllNonNull;
//...
public class RemarkCommand extends Command {
//...
@@ -99,8 +99,8 @@ public class RemarkCommand extends Command {
private final String remark;
/**
- * @param index of the person in the filtered person list to edit the remark
- * @param remark of the person to be updated to
+ * @param index of the qAndA in the filtered qAndA list to edit the remark
+ * @param remark of the qAndA to be updated to
*/
public RemarkCommand(Index index, String remark) {
requireAllNonNull(index, remark);
@@ -139,7 +139,7 @@ Your code should look something like [this](https://github.com/se-edu/addressboo
Now let’s move on to writing a parser that will extract the index and remark from the input provided by the user.
-Create a `RemarkCommandParser` class in the `seedu.address.logic.parser` package. The class must extend the `Parser` interface.
+Create a `RemarkCommandParser` class in the `seedu.medmoriser.logic.parser` package. The class must extend the `Parser` interface.
![The relationship between Parser and RemarkCommandParser](../images/add-remark/ParserInterface.png)
@@ -222,11 +222,11 @@ If you are stuck, check out the sample
## Add `Remark` to the model
-Now that we have all the information that we need, let’s lay the groundwork for propagating the remarks added into the in-memory storage of person data. We achieve that by working with the `Person` model. Each field in a Person is implemented as a separate class (e.g. a `Name` object represents the person’s name). That means we should add a `Remark` class so that we can use a `Remark` object to represent a remark given to a person.
+Now that we have all the information that we need, let’s lay the groundwork for propagating the remarks added into the in-memory storage of qAndA data. We achieve that by working with the `Person` model. Each field in a Person is implemented as a separate class (e.g. a `Name` object represents the qAndA’s name). That means we should add a `Remark` class so that we can use a `Remark` object to represent a remark given to a qAndA.
### Add a new `Remark` class
-Create a new `Remark` in `seedu.address.model.person`. Since a `Remark` is a field that is similar to `Address`, we can reuse a significant bit of code.
+Create a new `Remark` in `seedu.medmoriser.model.qanda`. Since a `Remark` is a field that is similar to `Address`, we can reuse a significant bit of code.
A copy-paste and search-replace later, you should have something like [this](https://github.com/se-edu/addressbook-level3/commit/4516e099699baa9e2d51801bd26f016d812dedcc#diff-af2f075d24dfcd333876f0fbce321f25). Note how `Remark` has no constrains and thus does not require input
validation.
@@ -237,9 +237,9 @@ Let’s change `RemarkCommand` and `RemarkCommandParser` to use the new `Remark`
## Add a placeholder element for remark to the UI
-Without getting too deep into `fxml`, let’s go on a 5 minute adventure to get some placeholder text to show up for each person.
+Without getting too deep into `fxml`, let’s go on a 5 minute adventure to get some placeholder text to show up for each qAndA.
-Simply add the following to [`seedu.address.ui.PersonCard`](https://github.com/se-edu/addressbook-level3/commit/850b78879582f38accb05dd20c245963c65ea599#diff-0c6b6abcfac8c205e075294f25e851fe).
+Simply add the following to [`seedu.medmoriser.ui.QuestionSetCard`](https://github.com/se-edu/addressbook-level3/commit/850b78879582f38accb05dd20c245963c65ea599#diff-0c6b6abcfac8c205e075294f25e851fe).
**`PersonCard.java`:**
@@ -292,7 +292,7 @@ While the changes to code may be minimal, the test data will have to be updated
-:exclamation: You must delete AddressBook’s storage file located at `/data/addressbook.json` before running it! Not doing so will cause AddressBook to default to an empty address book!
+:exclamation: You must delete Medmoriser’s storage file located at `/data/medmoriser.json` before running it! Not doing so will cause Medmoriser to default to an empty question bank!
@@ -308,9 +308,9 @@ Just add [this one line of code!](https://github.com/se-edu/addressbook-level3/c
**`PersonCard.java`:**
``` java
-public PersonCard(Person person, int displayedIndex) {
+public PersonCard(Person qAndA, int displayedIndex) {
//...
- remark.setText(person.getRemark().value);
+ remark.setText(qAndA.getRemark().value);
}
```
@@ -340,23 +340,23 @@ save it with `Model#setPerson()`.
throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
}
- Person personToEdit = lastShownList.get(index.getZeroBased());
- Person editedPerson = new Person(personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(),
- personToEdit.getAddress(), remark, personToEdit.getTags());
+ Person qAndAToEdit = lastShownList.get(index.getZeroBased());
+ Person editedQAndA = new Person(qAndAToEdit.getName(), qAndAToEdit.getPhone(), qAndAToEdit.getEmail(),
+ qAndAToEdit.getAddress(), remark, qAndAToEdit.getTags());
- model.setPerson(personToEdit, editedPerson);
+ model.setPerson(qAndAToEdit, editedQAndA);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- return new CommandResult(generateSuccessMessage(editedPerson));
+ return new CommandResult(generateSuccessMessage(editedQAndA));
}
/**
* Generates a command execution success message based on whether the remark is added to or removed from
- * {@code personToEdit}.
+ * {@code qAndAToEdit}.
*/
- private String generateSuccessMessage(Person personToEdit) {
+ private String generateSuccessMessage(Person qAndAToEdit) {
String message = !remark.value.isEmpty() ? MESSAGE_ADD_REMARK_SUCCESS : MESSAGE_DELETE_REMARK_SUCCESS;
- return String.format(message, personToEdit);
+ return String.format(message, qAndAToEdit);
}
```
diff --git a/docs/tutorials/RemovingFields.md b/docs/tutorials/RemovingFields.md
index aa8e0baaad9..c6ffa5ca8bb 100644
--- a/docs/tutorials/RemovingFields.md
+++ b/docs/tutorials/RemovingFields.md
@@ -9,7 +9,7 @@ title: "Tutorial: Removing Fields"
When working on AddressBook, you will most likely find that some features and fields that are no longer necessary. In scenarios like this, you can consider refactoring the existing `Person` model to suit your use case.
-In this tutorial, we’ll do exactly just that and remove the `address` field from `Person`.
+In this tutorial, we’ll do exactly just that and remove the `answer` field from `Person`.
* Table of Contents
{:toc}
@@ -20,7 +20,7 @@ Fortunately, IntelliJ IDEA provides a robust refactoring tool that can identify
### Assisted refactoring
-The `address` field in `Person` is actually an instance of the `seedu.address.model.person.Address` class. Since removing the `Address` class will break the application, we start by identifying `Address`'s usages. This allows us to see code that depends on `Address` to function properly and edit them on a case-by-case basis. Right-click the `Address` class and select `Refactor` \> `Safe Delete` through the menu.
+The `answer` field in `Person` is actually an instance of the `seedu.medmoriser.model.qanda.Answer` class. Since removing the `Address` class will break the application, we start by identifying `Address`'s usages. This allows us to see code that depends on `Address` to function properly and edit them on a case-by-case basis. Right-click the `Address` class and select `Refactor` \> `Safe Delete` through the menu.
![Usages detected](../images/remove/UnsafeDelete.png)
@@ -32,18 +32,18 @@ Remove usages of `Address` by performing `Safe Delete`s on each entry. You will
Let’s try removing references to `Address` in `EditPersonDescriptor`.
-1. Safe delete the field `address` in `EditPersonDescriptor`.
+1. Safe delete the field `answer` in `EditPersonDescriptor`.
1. Select `Yes` when prompted to remove getters and setters.
1. Select `View Usages` again.
![UnsafeDeleteOnField](../images/remove/UnsafeDeleteOnField.png)
-1. Remove the usages of `address` and select `Do refactor` when you are done.
+1. Remove the usages of `answer` and select `Do refactor` when you are done.
- :bulb: **Tip:** Removing usages may result in errors. Exercise discretion and fix them. For example, removing the `address` field from the `Person` class will require you to modify its constructor.
+ :bulb: **Tip:** Removing usages may result in errors. Exercise discretion and fix them. For example, removing the `answer` field from the `Person` class will require you to modify its constructor.
1. Repeat the steps for the remaining usages of `Address`
@@ -52,11 +52,11 @@ After you are done, verify that the application still works by compiling and run
### Manual refactoring
-Unfortunately, there are usages of `Address` that IntelliJ IDEA cannot identify. You can find them by searching for instances of the word `address` in your code (`Edit` \> `Find` \> `Find in path`).
+Unfortunately, there are usages of `Address` that IntelliJ IDEA cannot identify. You can find them by searching for instances of the word `answer` in your code (`Edit` \> `Find` \> `Find in path`).
-Places of interest to look out for would be resources used by the application. `main/resources` contains images and `fxml` files used by the application and `test/resources` contains test data. For example, there is a `$address` in each `PersonCard` that has not been removed nor identified.
+Places of interest to look out for would be resources used by the application. `main/resources` contains images and `fxml` files used by the application and `test/resources` contains test data. For example, there is a `$answer` in each `PersonCard` that has not been removed nor identified.
-![$address](../images/remove/$address.png)
+![$answer](../images/remove/$answer.png)
A quick look at the `PersonCard` class and its `fxml` file quickly reveals why it slipped past the automated refactoring.
@@ -65,7 +65,7 @@ A quick look at the `PersonCard` class and its `fxml` file quickly reveals why i
``` java
...
@FXML
-private Label address;
+private Label answer;
...
```
@@ -74,7 +74,7 @@ private Label address;
``` xml
...
-
+
...
```
@@ -85,19 +85,19 @@ After removing the `Label`, we can proceed to formally test our code. If everyth
At this point, your application is working as intended and all your tests are passing. What’s left to do is to clean up references to `Address` in test data and documentation.
-In `src/test/data/`, data meant for testing purposes are stored. While keeping the `address` field in the json files does not cause the tests to fail, it is not good practice to let cruft from old features accumulate.
+In `src/test/data/`, data meant for testing purposes are stored. While keeping the `answer` field in the json files does not cause the tests to fail, it is not good practice to let cruft from old features accumulate.
**`invalidPersonAddressBook.json`:**
```json
{
- "persons": [ {
+ "qAndAs": [ {
"name": "Person with invalid name field: Ha!ns Mu@ster",
"phone": "9482424",
"email": "hans@example.com",
- "address": "4th street"
+ "answer": "4th street"
} ]
}
```
-You can go through each individual `json` file and manually remove the `address` field.
+You can go through each individual `json` file and manually remove the `answer` field.
diff --git a/docs/tutorials/TracingCode.md b/docs/tutorials/TracingCode.md
index bd34ed498cd..42c4c77818f 100644
--- a/docs/tutorials/TracingCode.md
+++ b/docs/tutorials/TracingCode.md
@@ -32,7 +32,7 @@ Before we proceed, ensure that you have done the following:
## Setting a break point
-As you know, the first step of debugging is to put in a breakpoint where you want the debugger to pause the execution. For example, if you are trying to understand how the App starts up, you would put a breakpoint in the first statement of the `main` method. In our case, we would want to begin the tracing at the very point where the App start processing user input (i.e., somewhere in the UI component), and then trace through how the execution proceeds through the UI component. However, the execution path through a GUI is often somewhat obscure due to various *event-driven mechanisms* used by GUI frameworks, which happens to be the case here too. Therefore, let us put the breakpoint where the UI transfers control to the Logic component. According to the sequence diagram, the UI component yields control to the Logic component through a method named `execute`. Searching through the code base for `execute()` yields a promising candidate in `seedu.address.ui.CommandBox.CommandExecutor`.
+As you know, the first step of debugging is to put in a breakpoint where you want the debugger to pause the execution. For example, if you are trying to understand how the App starts up, you would put a breakpoint in the first statement of the `main` method. In our case, we would want to begin the tracing at the very point where the App start processing user input (i.e., somewhere in the UI component), and then trace through how the execution proceeds through the UI component. However, the execution path through a GUI is often somewhat obscure due to various *event-driven mechanisms* used by GUI frameworks, which happens to be the case here too. Therefore, let us put the breakpoint where the UI transfers control to the Logic component. According to the sequence diagram, the UI component yields control to the Logic component through a method named `execute`. Searching through the code base for `execute()` yields a promising candidate in `seedu.medmoriser.ui.CommandBox.CommandExecutor`.
![Using the `Search for target by name` feature. `Navigate` \> `Symbol`.](../images/tracing/Execute.png)
@@ -152,14 +152,14 @@ Recall from the User Guide that the `edit` command has the format: `edit INDEX [
@Override
public CommandResult execute(Model model) throws CommandException {
...
- Person personToEdit = lastShownList.get(index.getZeroBased());
- Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor);
- if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) {
+ Person qAndAToEdit = lastShownList.get(index.getZeroBased());
+ Person editedQAndA = createEditedPerson(qAndAToEdit, editQAndADescriptor);
+ if (!qAndAToEdit.isSamePerson(editedQAndA) && model.hasPerson(editedQAndA)) {
throw new CommandException(MESSAGE_DUPLICATE_PERSON);
}
- model.setPerson(personToEdit, editedPerson);
+ model.setPerson(qAndAToEdit, editedQAndA);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson));
+ return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedQAndA));
}
```
@@ -180,7 +180,7 @@ Recall from the User Guide that the `edit` command has the format: `edit INDEX [
* {@code JsonSerializableAddressBook}.
*/
public JsonSerializableAddressBook(ReadOnlyAddressBook source) {
- persons.addAll(
+ qAndAs.addAll(
source.getPersonList()
.stream()
.map(JsonAdaptedPerson::new)
@@ -241,10 +241,10 @@ the given commands to find exactly what happens.
2. Allow `delete` to remove more than one index at a time
- 3. Save the address book in the CSV format instead
+ 3. Save the answer book in the CSV format instead
4. Add a new command
5. Add a new field to `Person`
- 6. Add a new entity to the address book
+ 6. Add a new entity to the answer book
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 44e7c4d1d7b..19d972169e0 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,6 @@
+#Sun Oct 25 15:00:53 SGT 2020
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/src/addressbook.log.0 b/src/addressbook.log.0
new file mode 100644
index 00000000000..d3224868fb4
--- /dev/null
+++ b/src/addressbook.log.0
@@ -0,0 +1,22 @@
+Sep 28, 2020 12:34:10 PM seedu.medmoriser.MainApp init
+INFO: =============================[ Initializing AddressBook ]===========================
+Sep 28, 2020 12:34:10 PM seedu.medmoriser.MainApp initConfig
+INFO: Using config file : config.json
+Sep 28, 2020 12:34:10 PM seedu.medmoriser.commons.util.JsonUtil readJsonFile
+INFO: Json file config.json not found
+Sep 28, 2020 12:34:10 PM seedu.medmoriser.MainApp initPrefs
+INFO: Using prefs file : preferences.json
+Sep 28, 2020 12:34:10 PM seedu.medmoriser.commons.util.JsonUtil readJsonFile
+INFO: Json file preferences.json not found
+Sep 28, 2020 12:34:10 PM seedu.medmoriser.commons.core.LogsCenter init
+INFO: currentLogLevel: INFO
+Sep 28, 2020 12:34:10 PM seedu.medmoriser.commons.util.JsonUtil readJsonFile
+INFO: Json file data/addressbook.json not found
+Sep 28, 2020 12:34:10 PM seedu.medmoriser.MainApp initModelManager
+INFO: Data file not found. Will be starting with a sample AddressBook
+Sep 28, 2020 12:34:11 PM seedu.medmoriser.MainApp start
+INFO: Starting AddressBook V0.6.0ea
+Sep 28, 2020 12:34:11 PM seedu.medmoriser.ui.UiManager start
+INFO: Starting UI...
+Sep 28, 2020 12:34:14 PM seedu.medmoriser.MainApp stop
+INFO: ============================ [ Stopping Address Book ] =============================
diff --git a/src/config.json b/src/config.json
new file mode 100644
index 00000000000..a0edc78a820
--- /dev/null
+++ b/src/config.json
@@ -0,0 +1,4 @@
+{
+ "logLevel" : "INFO",
+ "userPrefsFilePath" : "preferences.json"
+}
diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java
deleted file mode 100644
index 1deb3a1e469..00000000000
--- a/src/main/java/seedu/address/commons/core/Messages.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package seedu.address.commons.core;
-
-/**
- * Container for user visible messages.
- */
-public class Messages {
-
- public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command";
- public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s";
- public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The person index provided is invalid";
- public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
-
-}
diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java
deleted file mode 100644
index 71656d7c5c8..00000000000
--- a/src/main/java/seedu/address/logic/commands/AddCommand.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Person;
-
-/**
- * Adds a person to the address book.
- */
-public class AddCommand extends Command {
-
- public static final String COMMAND_WORD = "add";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book. "
- + "Parameters: "
- + PREFIX_NAME + "NAME "
- + PREFIX_PHONE + "PHONE "
- + PREFIX_EMAIL + "EMAIL "
- + PREFIX_ADDRESS + "ADDRESS "
- + "[" + PREFIX_TAG + "TAG]...\n"
- + "Example: " + COMMAND_WORD + " "
- + PREFIX_NAME + "John Doe "
- + PREFIX_PHONE + "98765432 "
- + PREFIX_EMAIL + "johnd@example.com "
- + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 "
- + PREFIX_TAG + "friends "
- + PREFIX_TAG + "owesMoney";
-
- public static final String MESSAGE_SUCCESS = "New person added: %1$s";
- public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book";
-
- private final Person toAdd;
-
- /**
- * Creates an AddCommand to add the specified {@code Person}
- */
- public AddCommand(Person person) {
- requireNonNull(person);
- toAdd = person;
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- requireNonNull(model);
-
- if (model.hasPerson(toAdd)) {
- throw new CommandException(MESSAGE_DUPLICATE_PERSON);
- }
-
- model.addPerson(toAdd);
- return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof AddCommand // instanceof handles nulls
- && toAdd.equals(((AddCommand) other).toAdd));
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java
deleted file mode 100644
index 9c86b1fa6e4..00000000000
--- a/src/main/java/seedu/address/logic/commands/ClearCommand.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-
-/**
- * Clears the address book.
- */
-public class ClearCommand extends Command {
-
- public static final String COMMAND_WORD = "clear";
- public static final String MESSAGE_SUCCESS = "Address book has been cleared!";
-
-
- @Override
- public CommandResult execute(Model model) {
- requireNonNull(model);
- model.setAddressBook(new AddressBook());
- return new CommandResult(MESSAGE_SUCCESS);
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java
deleted file mode 100644
index 02fd256acba..00000000000
--- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.List;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Person;
-
-/**
- * Deletes a person identified using it's displayed index from the address book.
- */
-public class DeleteCommand extends Command {
-
- public static final String COMMAND_WORD = "delete";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD
- + ": Deletes the person identified by the index number used in the displayed person list.\n"
- + "Parameters: INDEX (must be a positive integer)\n"
- + "Example: " + COMMAND_WORD + " 1";
-
- public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s";
-
- private final Index targetIndex;
-
- public DeleteCommand(Index targetIndex) {
- this.targetIndex = targetIndex;
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- requireNonNull(model);
- List lastShownList = model.getFilteredPersonList();
-
- if (targetIndex.getZeroBased() >= lastShownList.size()) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- Person personToDelete = lastShownList.get(targetIndex.getZeroBased());
- model.deletePerson(personToDelete);
- return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof DeleteCommand // instanceof handles nulls
- && targetIndex.equals(((DeleteCommand) other).targetIndex)); // state check
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java
deleted file mode 100644
index 7e36114902f..00000000000
--- a/src/main/java/seedu/address/logic/commands/EditCommand.java
+++ /dev/null
@@ -1,226 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.commons.util.CollectionUtil;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Edits the details of an existing person in the address book.
- */
-public class EditCommand extends Command {
-
- public static final String COMMAND_WORD = "edit";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the person identified "
- + "by the index number used in the displayed person list. "
- + "Existing values will be overwritten by the input values.\n"
- + "Parameters: INDEX (must be a positive integer) "
- + "[" + PREFIX_NAME + "NAME] "
- + "[" + PREFIX_PHONE + "PHONE] "
- + "[" + PREFIX_EMAIL + "EMAIL] "
- + "[" + PREFIX_ADDRESS + "ADDRESS] "
- + "[" + PREFIX_TAG + "TAG]...\n"
- + "Example: " + COMMAND_WORD + " 1 "
- + PREFIX_PHONE + "91234567 "
- + PREFIX_EMAIL + "johndoe@example.com";
-
- public static final String MESSAGE_EDIT_PERSON_SUCCESS = "Edited Person: %1$s";
- public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided.";
- public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book.";
-
- private final Index index;
- private final EditPersonDescriptor editPersonDescriptor;
-
- /**
- * @param index of the person in the filtered person list to edit
- * @param editPersonDescriptor details to edit the person with
- */
- public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) {
- requireNonNull(index);
- requireNonNull(editPersonDescriptor);
-
- this.index = index;
- this.editPersonDescriptor = new EditPersonDescriptor(editPersonDescriptor);
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- requireNonNull(model);
- List lastShownList = model.getFilteredPersonList();
-
- if (index.getZeroBased() >= lastShownList.size()) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- Person personToEdit = lastShownList.get(index.getZeroBased());
- Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor);
-
- if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) {
- throw new CommandException(MESSAGE_DUPLICATE_PERSON);
- }
-
- model.setPerson(personToEdit, editedPerson);
- model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson));
- }
-
- /**
- * Creates and returns a {@code Person} with the details of {@code personToEdit}
- * edited with {@code editPersonDescriptor}.
- */
- private static Person createEditedPerson(Person personToEdit, EditPersonDescriptor editPersonDescriptor) {
- assert personToEdit != null;
-
- Name updatedName = editPersonDescriptor.getName().orElse(personToEdit.getName());
- Phone updatedPhone = editPersonDescriptor.getPhone().orElse(personToEdit.getPhone());
- Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail());
- Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress());
- Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags());
-
- return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags);
- }
-
- @Override
- public boolean equals(Object other) {
- // short circuit if same object
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof EditCommand)) {
- return false;
- }
-
- // state check
- EditCommand e = (EditCommand) other;
- return index.equals(e.index)
- && editPersonDescriptor.equals(e.editPersonDescriptor);
- }
-
- /**
- * Stores the details to edit the person with. Each non-empty field value will replace the
- * corresponding field value of the person.
- */
- public static class EditPersonDescriptor {
- private Name name;
- private Phone phone;
- private Email email;
- private Address address;
- private Set tags;
-
- public EditPersonDescriptor() {}
-
- /**
- * Copy constructor.
- * A defensive copy of {@code tags} is used internally.
- */
- public EditPersonDescriptor(EditPersonDescriptor toCopy) {
- setName(toCopy.name);
- setPhone(toCopy.phone);
- setEmail(toCopy.email);
- setAddress(toCopy.address);
- setTags(toCopy.tags);
- }
-
- /**
- * Returns true if at least one field is edited.
- */
- public boolean isAnyFieldEdited() {
- return CollectionUtil.isAnyNonNull(name, phone, email, address, tags);
- }
-
- public void setName(Name name) {
- this.name = name;
- }
-
- public Optional getName() {
- return Optional.ofNullable(name);
- }
-
- public void setPhone(Phone phone) {
- this.phone = phone;
- }
-
- public Optional getPhone() {
- return Optional.ofNullable(phone);
- }
-
- public void setEmail(Email email) {
- this.email = email;
- }
-
- public Optional getEmail() {
- return Optional.ofNullable(email);
- }
-
- public void setAddress(Address address) {
- this.address = address;
- }
-
- public Optional getAddress() {
- return Optional.ofNullable(address);
- }
-
- /**
- * Sets {@code tags} to this object's {@code tags}.
- * A defensive copy of {@code tags} is used internally.
- */
- public void setTags(Set tags) {
- this.tags = (tags != null) ? new HashSet<>(tags) : null;
- }
-
- /**
- * Returns an unmodifiable tag set, which throws {@code UnsupportedOperationException}
- * if modification is attempted.
- * Returns {@code Optional#empty()} if {@code tags} is null.
- */
- public Optional> getTags() {
- return (tags != null) ? Optional.of(Collections.unmodifiableSet(tags)) : Optional.empty();
- }
-
- @Override
- public boolean equals(Object other) {
- // short circuit if same object
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof EditPersonDescriptor)) {
- return false;
- }
-
- // state check
- EditPersonDescriptor e = (EditPersonDescriptor) other;
-
- return getName().equals(e.getName())
- && getPhone().equals(e.getPhone())
- && getEmail().equals(e.getEmail())
- && getAddress().equals(e.getAddress())
- && getTags().equals(e.getTags());
- }
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java
deleted file mode 100644
index d6b19b0a0de..00000000000
--- a/src/main/java/seedu/address/logic/commands/FindCommand.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.model.Model;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-
-/**
- * Finds and lists all persons in address book whose name contains any of the argument keywords.
- * Keyword matching is case insensitive.
- */
-public class FindCommand extends Command {
-
- public static final String COMMAND_WORD = "find";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose names contain any of "
- + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n"
- + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
- + "Example: " + COMMAND_WORD + " alice bob charlie";
-
- private final NameContainsKeywordsPredicate predicate;
-
- public FindCommand(NameContainsKeywordsPredicate predicate) {
- this.predicate = predicate;
- }
-
- @Override
- public CommandResult execute(Model model) {
- requireNonNull(model);
- model.updateFilteredPersonList(predicate);
- return new CommandResult(
- String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size()));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof FindCommand // instanceof handles nulls
- && predicate.equals(((FindCommand) other).predicate)); // state check
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java
deleted file mode 100644
index 84be6ad2596..00000000000
--- a/src/main/java/seedu/address/logic/commands/ListCommand.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
-
-import seedu.address.model.Model;
-
-/**
- * Lists all persons in the address book to the user.
- */
-public class ListCommand extends Command {
-
- public static final String COMMAND_WORD = "list";
-
- public static final String MESSAGE_SUCCESS = "Listed all persons";
-
-
- @Override
- public CommandResult execute(Model model) {
- requireNonNull(model);
- model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- return new CommandResult(MESSAGE_SUCCESS);
- }
-}
diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java
deleted file mode 100644
index 3b8bfa035e8..00000000000
--- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import java.util.Set;
-import java.util.stream.Stream;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Parses input arguments and creates a new AddCommand object
- */
-public class AddCommandParser implements Parser {
-
- /**
- * Parses the given {@code String} of arguments in the context of the AddCommand
- * and returns an AddCommand object for execution.
- * @throws ParseException if the user input does not conform the expected format
- */
- public AddCommand parse(String args) throws ParseException {
- ArgumentMultimap argMultimap =
- ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
-
- if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL)
- || !argMultimap.getPreamble().isEmpty()) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
- }
-
- Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get());
- Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get());
- Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get());
- Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get());
- Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG));
-
- Person person = new Person(name, phone, email, address, tagList);
-
- return new AddCommand(person);
- }
-
- /**
- * Returns true if none of the prefixes contains empty {@code Optional} values in the given
- * {@code ArgumentMultimap}.
- */
- private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
- return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java
deleted file mode 100644
index 75b1a9bf119..00000000000
--- a/src/main/java/seedu/address/logic/parser/CliSyntax.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package seedu.address.logic.parser;
-
-/**
- * Contains Command Line Interface (CLI) syntax definitions common to multiple commands
- */
-public class CliSyntax {
-
- /* Prefix definitions */
- public static final Prefix PREFIX_NAME = new Prefix("n/");
- public static final Prefix PREFIX_PHONE = new Prefix("p/");
- public static final Prefix PREFIX_EMAIL = new Prefix("e/");
- public static final Prefix PREFIX_ADDRESS = new Prefix("a/");
- public static final Prefix PREFIX_TAG = new Prefix("t/");
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/EditCommandParser.java
deleted file mode 100644
index 845644b7dea..00000000000
--- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package seedu.address.logic.parser;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Optional;
-import java.util.Set;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.tag.Tag;
-
-/**
- * Parses input arguments and creates a new EditCommand object
- */
-public class EditCommandParser implements Parser {
-
- /**
- * Parses the given {@code String} of arguments in the context of the EditCommand
- * and returns an EditCommand object for execution.
- * @throws ParseException if the user input does not conform the expected format
- */
- public EditCommand parse(String args) throws ParseException {
- requireNonNull(args);
- ArgumentMultimap argMultimap =
- ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
-
- Index index;
-
- try {
- index = ParserUtil.parseIndex(argMultimap.getPreamble());
- } catch (ParseException pe) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE), pe);
- }
-
- EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor();
- if (argMultimap.getValue(PREFIX_NAME).isPresent()) {
- editPersonDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()));
- }
- if (argMultimap.getValue(PREFIX_PHONE).isPresent()) {
- editPersonDescriptor.setPhone(ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()));
- }
- if (argMultimap.getValue(PREFIX_EMAIL).isPresent()) {
- editPersonDescriptor.setEmail(ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()));
- }
- if (argMultimap.getValue(PREFIX_ADDRESS).isPresent()) {
- editPersonDescriptor.setAddress(ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get()));
- }
- parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags);
-
- if (!editPersonDescriptor.isAnyFieldEdited()) {
- throw new ParseException(EditCommand.MESSAGE_NOT_EDITED);
- }
-
- return new EditCommand(index, editPersonDescriptor);
- }
-
- /**
- * Parses {@code Collection tags} into a {@code Set} if {@code tags} is non-empty.
- * If {@code tags} contain only one element which is an empty string, it will be parsed into a
- * {@code Set} containing zero tags.
- */
- private Optional> parseTagsForEdit(Collection tags) throws ParseException {
- assert tags != null;
-
- if (tags.isEmpty()) {
- return Optional.empty();
- }
- Collection tagSet = tags.size() == 1 && tags.contains("") ? Collections.emptySet() : tags;
- return Optional.of(ParserUtil.parseTags(tagSet));
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java
deleted file mode 100644
index 4fb71f23103..00000000000
--- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-
-import java.util.Arrays;
-
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-
-/**
- * Parses input arguments and creates a new FindCommand object
- */
-public class FindCommandParser implements Parser {
-
- /**
- * Parses the given {@code String} of arguments in the context of the FindCommand
- * and returns a FindCommand object for execution.
- * @throws ParseException if the user input does not conform the expected format
- */
- public FindCommand parse(String args) throws ParseException {
- String trimmedArgs = args.trim();
- if (trimmedArgs.isEmpty()) {
- throw new ParseException(
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
- }
-
- String[] nameKeywords = trimmedArgs.split("\\s+");
-
- return new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(nameKeywords)));
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java
deleted file mode 100644
index b117acb9c55..00000000000
--- a/src/main/java/seedu/address/logic/parser/ParserUtil.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package seedu.address.logic.parser;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.commons.util.StringUtil;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Contains utility methods used for parsing strings in the various *Parser classes.
- */
-public class ParserUtil {
-
- public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer.";
-
- /**
- * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be
- * trimmed.
- * @throws ParseException if the specified index is invalid (not non-zero unsigned integer).
- */
- public static Index parseIndex(String oneBasedIndex) throws ParseException {
- String trimmedIndex = oneBasedIndex.trim();
- if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) {
- throw new ParseException(MESSAGE_INVALID_INDEX);
- }
- return Index.fromOneBased(Integer.parseInt(trimmedIndex));
- }
-
- /**
- * Parses a {@code String name} into a {@code Name}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code name} is invalid.
- */
- public static Name parseName(String name) throws ParseException {
- requireNonNull(name);
- String trimmedName = name.trim();
- if (!Name.isValidName(trimmedName)) {
- throw new ParseException(Name.MESSAGE_CONSTRAINTS);
- }
- return new Name(trimmedName);
- }
-
- /**
- * Parses a {@code String phone} into a {@code Phone}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code phone} is invalid.
- */
- public static Phone parsePhone(String phone) throws ParseException {
- requireNonNull(phone);
- String trimmedPhone = phone.trim();
- if (!Phone.isValidPhone(trimmedPhone)) {
- throw new ParseException(Phone.MESSAGE_CONSTRAINTS);
- }
- return new Phone(trimmedPhone);
- }
-
- /**
- * Parses a {@code String address} into an {@code Address}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code address} is invalid.
- */
- public static Address parseAddress(String address) throws ParseException {
- requireNonNull(address);
- String trimmedAddress = address.trim();
- if (!Address.isValidAddress(trimmedAddress)) {
- throw new ParseException(Address.MESSAGE_CONSTRAINTS);
- }
- return new Address(trimmedAddress);
- }
-
- /**
- * Parses a {@code String email} into an {@code Email}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code email} is invalid.
- */
- public static Email parseEmail(String email) throws ParseException {
- requireNonNull(email);
- String trimmedEmail = email.trim();
- if (!Email.isValidEmail(trimmedEmail)) {
- throw new ParseException(Email.MESSAGE_CONSTRAINTS);
- }
- return new Email(trimmedEmail);
- }
-
- /**
- * Parses a {@code String tag} into a {@code Tag}.
- * Leading and trailing whitespaces will be trimmed.
- *
- * @throws ParseException if the given {@code tag} is invalid.
- */
- public static Tag parseTag(String tag) throws ParseException {
- requireNonNull(tag);
- String trimmedTag = tag.trim();
- if (!Tag.isValidTagName(trimmedTag)) {
- throw new ParseException(Tag.MESSAGE_CONSTRAINTS);
- }
- return new Tag(trimmedTag);
- }
-
- /**
- * Parses {@code Collection tags} into a {@code Set}.
- */
- public static Set parseTags(Collection tags) throws ParseException {
- requireNonNull(tags);
- final Set tagSet = new HashSet<>();
- for (String tagName : tags) {
- tagSet.add(parseTag(tagName));
- }
- return tagSet;
- }
-}
diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java
deleted file mode 100644
index 1a943a0781a..00000000000
--- a/src/main/java/seedu/address/model/AddressBook.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package seedu.address.model;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.List;
-
-import javafx.collections.ObservableList;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.UniquePersonList;
-
-/**
- * Wraps all data at the address-book level
- * Duplicates are not allowed (by .isSamePerson comparison)
- */
-public class AddressBook implements ReadOnlyAddressBook {
-
- private final UniquePersonList persons;
-
- /*
- * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication
- * between constructors. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
- *
- * Note that non-static init blocks are not recommended to use. There are other ways to avoid duplication
- * among constructors.
- */
- {
- persons = new UniquePersonList();
- }
-
- public AddressBook() {}
-
- /**
- * Creates an AddressBook using the Persons in the {@code toBeCopied}
- */
- public AddressBook(ReadOnlyAddressBook toBeCopied) {
- this();
- resetData(toBeCopied);
- }
-
- //// list overwrite operations
-
- /**
- * Replaces the contents of the person list with {@code persons}.
- * {@code persons} must not contain duplicate persons.
- */
- public void setPersons(List persons) {
- this.persons.setPersons(persons);
- }
-
- /**
- * Resets the existing data of this {@code AddressBook} with {@code newData}.
- */
- public void resetData(ReadOnlyAddressBook newData) {
- requireNonNull(newData);
-
- setPersons(newData.getPersonList());
- }
-
- //// person-level operations
-
- /**
- * Returns true if a person with the same identity as {@code person} exists in the address book.
- */
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return persons.contains(person);
- }
-
- /**
- * Adds a person to the address book.
- * The person must not already exist in the address book.
- */
- public void addPerson(Person p) {
- persons.add(p);
- }
-
- /**
- * Replaces the given person {@code target} in the list with {@code editedPerson}.
- * {@code target} must exist in the address book.
- * The person identity of {@code editedPerson} must not be the same as another existing person in the address book.
- */
- public void setPerson(Person target, Person editedPerson) {
- requireNonNull(editedPerson);
-
- persons.setPerson(target, editedPerson);
- }
-
- /**
- * Removes {@code key} from this {@code AddressBook}.
- * {@code key} must exist in the address book.
- */
- public void removePerson(Person key) {
- persons.remove(key);
- }
-
- //// util methods
-
- @Override
- public String toString() {
- return persons.asUnmodifiableObservableList().size() + " persons";
- // TODO: refine later
- }
-
- @Override
- public ObservableList getPersonList() {
- return persons.asUnmodifiableObservableList();
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof AddressBook // instanceof handles nulls
- && persons.equals(((AddressBook) other).persons));
- }
-
- @Override
- public int hashCode() {
- return persons.hashCode();
- }
-}
diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java
deleted file mode 100644
index d54df471c1f..00000000000
--- a/src/main/java/seedu/address/model/Model.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package seedu.address.model;
-
-import java.nio.file.Path;
-import java.util.function.Predicate;
-
-import javafx.collections.ObservableList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.model.person.Person;
-
-/**
- * The API of the Model component.
- */
-public interface Model {
- /** {@code Predicate} that always evaluate to true */
- Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true;
-
- /**
- * Replaces user prefs data with the data in {@code userPrefs}.
- */
- void setUserPrefs(ReadOnlyUserPrefs userPrefs);
-
- /**
- * Returns the user prefs.
- */
- ReadOnlyUserPrefs getUserPrefs();
-
- /**
- * Returns the user prefs' GUI settings.
- */
- GuiSettings getGuiSettings();
-
- /**
- * Sets the user prefs' GUI settings.
- */
- void setGuiSettings(GuiSettings guiSettings);
-
- /**
- * Returns the user prefs' address book file path.
- */
- Path getAddressBookFilePath();
-
- /**
- * Sets the user prefs' address book file path.
- */
- void setAddressBookFilePath(Path addressBookFilePath);
-
- /**
- * Replaces address book data with the data in {@code addressBook}.
- */
- void setAddressBook(ReadOnlyAddressBook addressBook);
-
- /** Returns the AddressBook */
- ReadOnlyAddressBook getAddressBook();
-
- /**
- * Returns true if a person with the same identity as {@code person} exists in the address book.
- */
- boolean hasPerson(Person person);
-
- /**
- * Deletes the given person.
- * The person must exist in the address book.
- */
- void deletePerson(Person target);
-
- /**
- * Adds the given person.
- * {@code person} must not already exist in the address book.
- */
- void addPerson(Person person);
-
- /**
- * Replaces the given person {@code target} with {@code editedPerson}.
- * {@code target} must exist in the address book.
- * The person identity of {@code editedPerson} must not be the same as another existing person in the address book.
- */
- void setPerson(Person target, Person editedPerson);
-
- /** Returns an unmodifiable view of the filtered person list */
- ObservableList getFilteredPersonList();
-
- /**
- * Updates the filter of the filtered person list to filter by the given {@code predicate}.
- * @throws NullPointerException if {@code predicate} is null.
- */
- void updateFilteredPersonList(Predicate predicate);
-}
diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java
deleted file mode 100644
index 0650c954f5c..00000000000
--- a/src/main/java/seedu/address/model/ModelManager.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package seedu.address.model;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-
-import java.nio.file.Path;
-import java.util.function.Predicate;
-import java.util.logging.Logger;
-
-import javafx.collections.ObservableList;
-import javafx.collections.transformation.FilteredList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.model.person.Person;
-
-/**
- * Represents the in-memory model of the address book data.
- */
-public class ModelManager implements Model {
- private static final Logger logger = LogsCenter.getLogger(ModelManager.class);
-
- private final AddressBook addressBook;
- private final UserPrefs userPrefs;
- private final FilteredList filteredPersons;
-
- /**
- * Initializes a ModelManager with the given addressBook and userPrefs.
- */
- public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs) {
- super();
- requireAllNonNull(addressBook, userPrefs);
-
- logger.fine("Initializing with address book: " + addressBook + " and user prefs " + userPrefs);
-
- this.addressBook = new AddressBook(addressBook);
- this.userPrefs = new UserPrefs(userPrefs);
- filteredPersons = new FilteredList<>(this.addressBook.getPersonList());
- }
-
- public ModelManager() {
- this(new AddressBook(), new UserPrefs());
- }
-
- //=========== UserPrefs ==================================================================================
-
- @Override
- public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
- requireNonNull(userPrefs);
- this.userPrefs.resetData(userPrefs);
- }
-
- @Override
- public ReadOnlyUserPrefs getUserPrefs() {
- return userPrefs;
- }
-
- @Override
- public GuiSettings getGuiSettings() {
- return userPrefs.getGuiSettings();
- }
-
- @Override
- public void setGuiSettings(GuiSettings guiSettings) {
- requireNonNull(guiSettings);
- userPrefs.setGuiSettings(guiSettings);
- }
-
- @Override
- public Path getAddressBookFilePath() {
- return userPrefs.getAddressBookFilePath();
- }
-
- @Override
- public void setAddressBookFilePath(Path addressBookFilePath) {
- requireNonNull(addressBookFilePath);
- userPrefs.setAddressBookFilePath(addressBookFilePath);
- }
-
- //=========== AddressBook ================================================================================
-
- @Override
- public void setAddressBook(ReadOnlyAddressBook addressBook) {
- this.addressBook.resetData(addressBook);
- }
-
- @Override
- public ReadOnlyAddressBook getAddressBook() {
- return addressBook;
- }
-
- @Override
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return addressBook.hasPerson(person);
- }
-
- @Override
- public void deletePerson(Person target) {
- addressBook.removePerson(target);
- }
-
- @Override
- public void addPerson(Person person) {
- addressBook.addPerson(person);
- updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- }
-
- @Override
- public void setPerson(Person target, Person editedPerson) {
- requireAllNonNull(target, editedPerson);
-
- addressBook.setPerson(target, editedPerson);
- }
-
- //=========== Filtered Person List Accessors =============================================================
-
- /**
- * Returns an unmodifiable view of the list of {@code Person} backed by the internal list of
- * {@code versionedAddressBook}
- */
- @Override
- public ObservableList getFilteredPersonList() {
- return filteredPersons;
- }
-
- @Override
- public void updateFilteredPersonList(Predicate predicate) {
- requireNonNull(predicate);
- filteredPersons.setPredicate(predicate);
- }
-
- @Override
- public boolean equals(Object obj) {
- // short circuit if same object
- if (obj == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(obj instanceof ModelManager)) {
- return false;
- }
-
- // state check
- ModelManager other = (ModelManager) obj;
- return addressBook.equals(other.addressBook)
- && userPrefs.equals(other.userPrefs)
- && filteredPersons.equals(other.filteredPersons);
- }
-
-}
diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java
deleted file mode 100644
index 6ddc2cd9a29..00000000000
--- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package seedu.address.model;
-
-import javafx.collections.ObservableList;
-import seedu.address.model.person.Person;
-
-/**
- * Unmodifiable view of an address book
- */
-public interface ReadOnlyAddressBook {
-
- /**
- * Returns an unmodifiable view of the persons list.
- * This list will not contain any duplicate persons.
- */
- ObservableList getPersonList();
-
-}
diff --git a/src/main/java/seedu/address/model/person/Address.java b/src/main/java/seedu/address/model/person/Address.java
deleted file mode 100644
index 60472ca22a0..00000000000
--- a/src/main/java/seedu/address/model/person/Address.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package seedu.address.model.person;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
-
-/**
- * Represents a Person's address in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidAddress(String)}
- */
-public class Address {
-
- public static final String MESSAGE_CONSTRAINTS = "Addresses can take any values, and it should not be blank";
-
- /*
- * The first character of the address must not be a whitespace,
- * otherwise " " (a blank string) becomes a valid input.
- */
- public static final String VALIDATION_REGEX = "[^\\s].*";
-
- public final String value;
-
- /**
- * Constructs an {@code Address}.
- *
- * @param address A valid address.
- */
- public Address(String address) {
- requireNonNull(address);
- checkArgument(isValidAddress(address), MESSAGE_CONSTRAINTS);
- value = address;
- }
-
- /**
- * Returns true if a given string is a valid email.
- */
- public static boolean isValidAddress(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Address // instanceof handles nulls
- && value.equals(((Address) other).value)); // state check
- }
-
- @Override
- public int hashCode() {
- return value.hashCode();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/Email.java b/src/main/java/seedu/address/model/person/Email.java
deleted file mode 100644
index a5bbe0b6a5f..00000000000
--- a/src/main/java/seedu/address/model/person/Email.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package seedu.address.model.person;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
-
-/**
- * Represents a Person's email in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidEmail(String)}
- */
-public class Email {
-
- private static final String SPECIAL_CHARACTERS = "!#$%&'*+/=?`{|}~^.-";
- public static final String MESSAGE_CONSTRAINTS = "Emails should be of the format local-part@domain "
- + "and adhere to the following constraints:\n"
- + "1. The local-part should only contain alphanumeric characters and these special characters, excluding "
- + "the parentheses, (" + SPECIAL_CHARACTERS + ") .\n"
- + "2. This is followed by a '@' and then a domain name. "
- + "The domain name must:\n"
- + " - be at least 2 characters long\n"
- + " - start and end with alphanumeric characters\n"
- + " - consist of alphanumeric characters, a period or a hyphen for the characters in between, if any.";
- // alphanumeric and special characters
- private static final String LOCAL_PART_REGEX = "^[\\w" + SPECIAL_CHARACTERS + "]+";
- private static final String DOMAIN_FIRST_CHARACTER_REGEX = "[^\\W_]"; // alphanumeric characters except underscore
- private static final String DOMAIN_MIDDLE_REGEX = "[a-zA-Z0-9.-]*"; // alphanumeric, period and hyphen
- private static final String DOMAIN_LAST_CHARACTER_REGEX = "[^\\W_]$";
- public static final String VALIDATION_REGEX = LOCAL_PART_REGEX + "@"
- + DOMAIN_FIRST_CHARACTER_REGEX + DOMAIN_MIDDLE_REGEX + DOMAIN_LAST_CHARACTER_REGEX;
-
- public final String value;
-
- /**
- * Constructs an {@code Email}.
- *
- * @param email A valid email address.
- */
- public Email(String email) {
- requireNonNull(email);
- checkArgument(isValidEmail(email), MESSAGE_CONSTRAINTS);
- value = email;
- }
-
- /**
- * Returns if a given string is a valid email.
- */
- public static boolean isValidEmail(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Email // instanceof handles nulls
- && value.equals(((Email) other).value)); // state check
- }
-
- @Override
- public int hashCode() {
- return value.hashCode();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/Name.java b/src/main/java/seedu/address/model/person/Name.java
deleted file mode 100644
index 79244d71cf7..00000000000
--- a/src/main/java/seedu/address/model/person/Name.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package seedu.address.model.person;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
-
-/**
- * Represents a Person's name in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidName(String)}
- */
-public class Name {
-
- public static final String MESSAGE_CONSTRAINTS =
- "Names should only contain alphanumeric characters and spaces, and it should not be blank";
-
- /*
- * The first character of the address must not be a whitespace,
- * otherwise " " (a blank string) becomes a valid input.
- */
- public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*";
-
- public final String fullName;
-
- /**
- * Constructs a {@code Name}.
- *
- * @param name A valid name.
- */
- public Name(String name) {
- requireNonNull(name);
- checkArgument(isValidName(name), MESSAGE_CONSTRAINTS);
- fullName = name;
- }
-
- /**
- * Returns true if a given string is a valid name.
- */
- public static boolean isValidName(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
-
- @Override
- public String toString() {
- return fullName;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Name // instanceof handles nulls
- && fullName.equals(((Name) other).fullName)); // state check
- }
-
- @Override
- public int hashCode() {
- return fullName.hashCode();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
deleted file mode 100644
index c9b5868427c..00000000000
--- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package seedu.address.model.person;
-
-import java.util.List;
-import java.util.function.Predicate;
-
-import seedu.address.commons.util.StringUtil;
-
-/**
- * Tests that a {@code Person}'s {@code Name} matches any of the keywords given.
- */
-public class NameContainsKeywordsPredicate implements Predicate {
- private final List keywords;
-
- public NameContainsKeywordsPredicate(List keywords) {
- this.keywords = keywords;
- }
-
- @Override
- public boolean test(Person person) {
- return keywords.stream()
- .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getName().fullName, keyword));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof NameContainsKeywordsPredicate // instanceof handles nulls
- && keywords.equals(((NameContainsKeywordsPredicate) other).keywords)); // state check
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java
deleted file mode 100644
index 557a7a60cd5..00000000000
--- a/src/main/java/seedu/address/model/person/Person.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package seedu.address.model.person;
-
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-
-import seedu.address.model.tag.Tag;
-
-/**
- * Represents a Person in the address book.
- * Guarantees: details are present and not null, field values are validated, immutable.
- */
-public class Person {
-
- // Identity fields
- private final Name name;
- private final Phone phone;
- private final Email email;
-
- // Data fields
- private final Address address;
- private final Set tags = new HashSet<>();
-
- /**
- * Every field must be present and not null.
- */
- public Person(Name name, Phone phone, Email email, Address address, Set tags) {
- requireAllNonNull(name, phone, email, address, tags);
- this.name = name;
- this.phone = phone;
- this.email = email;
- this.address = address;
- this.tags.addAll(tags);
- }
-
- public Name getName() {
- return name;
- }
-
- public Phone getPhone() {
- return phone;
- }
-
- public Email getEmail() {
- return email;
- }
-
- public Address getAddress() {
- return address;
- }
-
- /**
- * Returns an immutable tag set, which throws {@code UnsupportedOperationException}
- * if modification is attempted.
- */
- public Set getTags() {
- return Collections.unmodifiableSet(tags);
- }
-
- /**
- * Returns true if both persons of the same name have at least one other identity field that is the same.
- * This defines a weaker notion of equality between two persons.
- */
- public boolean isSamePerson(Person otherPerson) {
- if (otherPerson == this) {
- return true;
- }
-
- return otherPerson != null
- && otherPerson.getName().equals(getName())
- && (otherPerson.getPhone().equals(getPhone()) || otherPerson.getEmail().equals(getEmail()));
- }
-
- /**
- * Returns true if both persons have the same identity and data fields.
- * This defines a stronger notion of equality between two persons.
- */
- @Override
- public boolean equals(Object other) {
- if (other == this) {
- return true;
- }
-
- if (!(other instanceof Person)) {
- return false;
- }
-
- Person otherPerson = (Person) other;
- return otherPerson.getName().equals(getName())
- && otherPerson.getPhone().equals(getPhone())
- && otherPerson.getEmail().equals(getEmail())
- && otherPerson.getAddress().equals(getAddress())
- && otherPerson.getTags().equals(getTags());
- }
-
- @Override
- public int hashCode() {
- // use this method for custom fields hashing instead of implementing your own
- return Objects.hash(name, phone, email, address, tags);
- }
-
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder();
- builder.append(getName())
- .append(" Phone: ")
- .append(getPhone())
- .append(" Email: ")
- .append(getEmail())
- .append(" Address: ")
- .append(getAddress())
- .append(" Tags: ");
- getTags().forEach(builder::append);
- return builder.toString();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/Phone.java b/src/main/java/seedu/address/model/person/Phone.java
deleted file mode 100644
index 872c76b382f..00000000000
--- a/src/main/java/seedu/address/model/person/Phone.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package seedu.address.model.person;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
-
-/**
- * Represents a Person's phone number in the address book.
- * Guarantees: immutable; is valid as declared in {@link #isValidPhone(String)}
- */
-public class Phone {
-
-
- public static final String MESSAGE_CONSTRAINTS =
- "Phone numbers should only contain numbers, and it should be at least 3 digits long";
- public static final String VALIDATION_REGEX = "\\d{3,}";
- public final String value;
-
- /**
- * Constructs a {@code Phone}.
- *
- * @param phone A valid phone number.
- */
- public Phone(String phone) {
- requireNonNull(phone);
- checkArgument(isValidPhone(phone), MESSAGE_CONSTRAINTS);
- value = phone;
- }
-
- /**
- * Returns true if a given string is a valid phone number.
- */
- public static boolean isValidPhone(String test) {
- return test.matches(VALIDATION_REGEX);
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof Phone // instanceof handles nulls
- && value.equals(((Phone) other).value)); // state check
- }
-
- @Override
- public int hashCode() {
- return value.hashCode();
- }
-
-}
diff --git a/src/main/java/seedu/address/model/person/UniquePersonList.java b/src/main/java/seedu/address/model/person/UniquePersonList.java
deleted file mode 100644
index 0fee4fe57e6..00000000000
--- a/src/main/java/seedu/address/model/person/UniquePersonList.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package seedu.address.model.person;
-
-import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-
-import java.util.Iterator;
-import java.util.List;
-
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
-import seedu.address.model.person.exceptions.DuplicatePersonException;
-import seedu.address.model.person.exceptions.PersonNotFoundException;
-
-/**
- * A list of persons that enforces uniqueness between its elements and does not allow nulls.
- * A person is considered unique by comparing using {@code Person#isSamePerson(Person)}. As such, adding and updating of
- * persons uses Person#isSamePerson(Person) for equality so as to ensure that the person being added or updated is
- * unique in terms of identity in the UniquePersonList. However, the removal of a person uses Person#equals(Object) so
- * as to ensure that the person with exactly the same fields will be removed.
- *
- * Supports a minimal set of list operations.
- *
- * @see Person#isSamePerson(Person)
- */
-public class UniquePersonList implements Iterable {
-
- private final ObservableList internalList = FXCollections.observableArrayList();
- private final ObservableList internalUnmodifiableList =
- FXCollections.unmodifiableObservableList(internalList);
-
- /**
- * Returns true if the list contains an equivalent person as the given argument.
- */
- public boolean contains(Person toCheck) {
- requireNonNull(toCheck);
- return internalList.stream().anyMatch(toCheck::isSamePerson);
- }
-
- /**
- * Adds a person to the list.
- * The person must not already exist in the list.
- */
- public void add(Person toAdd) {
- requireNonNull(toAdd);
- if (contains(toAdd)) {
- throw new DuplicatePersonException();
- }
- internalList.add(toAdd);
- }
-
- /**
- * Replaces the person {@code target} in the list with {@code editedPerson}.
- * {@code target} must exist in the list.
- * The person identity of {@code editedPerson} must not be the same as another existing person in the list.
- */
- public void setPerson(Person target, Person editedPerson) {
- requireAllNonNull(target, editedPerson);
-
- int index = internalList.indexOf(target);
- if (index == -1) {
- throw new PersonNotFoundException();
- }
-
- if (!target.isSamePerson(editedPerson) && contains(editedPerson)) {
- throw new DuplicatePersonException();
- }
-
- internalList.set(index, editedPerson);
- }
-
- /**
- * Removes the equivalent person from the list.
- * The person must exist in the list.
- */
- public void remove(Person toRemove) {
- requireNonNull(toRemove);
- if (!internalList.remove(toRemove)) {
- throw new PersonNotFoundException();
- }
- }
-
- public void setPersons(UniquePersonList replacement) {
- requireNonNull(replacement);
- internalList.setAll(replacement.internalList);
- }
-
- /**
- * Replaces the contents of this list with {@code persons}.
- * {@code persons} must not contain duplicate persons.
- */
- public void setPersons(List persons) {
- requireAllNonNull(persons);
- if (!personsAreUnique(persons)) {
- throw new DuplicatePersonException();
- }
-
- internalList.setAll(persons);
- }
-
- /**
- * Returns the backing list as an unmodifiable {@code ObservableList}.
- */
- public ObservableList asUnmodifiableObservableList() {
- return internalUnmodifiableList;
- }
-
- @Override
- public Iterator iterator() {
- return internalList.iterator();
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof UniquePersonList // instanceof handles nulls
- && internalList.equals(((UniquePersonList) other).internalList));
- }
-
- @Override
- public int hashCode() {
- return internalList.hashCode();
- }
-
- /**
- * Returns true if {@code persons} contains only unique persons.
- */
- private boolean personsAreUnique(List persons) {
- for (int i = 0; i < persons.size() - 1; i++) {
- for (int j = i + 1; j < persons.size(); j++) {
- if (persons.get(i).isSamePerson(persons.get(j))) {
- return false;
- }
- }
- }
- return true;
- }
-}
diff --git a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java b/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java
deleted file mode 100644
index d7290f59442..00000000000
--- a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package seedu.address.model.person.exceptions;
-
-/**
- * Signals that the operation will result in duplicate Persons (Persons are considered duplicates if they have the same
- * identity).
- */
-public class DuplicatePersonException extends RuntimeException {
- public DuplicatePersonException() {
- super("Operation would result in duplicate persons");
- }
-}
diff --git a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java b/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java
deleted file mode 100644
index fa764426ca7..00000000000
--- a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package seedu.address.model.person.exceptions;
-
-/**
- * Signals that the operation is unable to find the specified person.
- */
-public class PersonNotFoundException extends RuntimeException {}
diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java
deleted file mode 100644
index 1806da4facf..00000000000
--- a/src/main/java/seedu/address/model/util/SampleDataUtil.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package seedu.address.model.util;
-
-import java.util.Arrays;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Contains utility methods for populating {@code AddressBook} with sample data.
- */
-public class SampleDataUtil {
- public static Person[] getSamplePersons() {
- return new Person[] {
- new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"),
- new Address("Blk 30 Geylang Street 29, #06-40"),
- getTagSet("friends")),
- new Person(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"),
- new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"),
- getTagSet("colleagues", "friends")),
- new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"),
- new Address("Blk 11 Ang Mo Kio Street 74, #11-04"),
- getTagSet("neighbours")),
- new Person(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"),
- new Address("Blk 436 Serangoon Gardens Street 26, #16-43"),
- getTagSet("family")),
- new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"),
- new Address("Blk 47 Tampines Street 20, #17-35"),
- getTagSet("classmates")),
- new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"),
- new Address("Blk 45 Aljunied Street 85, #11-31"),
- getTagSet("colleagues"))
- };
- }
-
- public static ReadOnlyAddressBook getSampleAddressBook() {
- AddressBook sampleAb = new AddressBook();
- for (Person samplePerson : getSamplePersons()) {
- sampleAb.addPerson(samplePerson);
- }
- return sampleAb;
- }
-
- /**
- * Returns a tag set containing the list of strings given.
- */
- public static Set getTagSet(String... strings) {
- return Arrays.stream(strings)
- .map(Tag::new)
- .collect(Collectors.toSet());
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/AddressBookStorage.java b/src/main/java/seedu/address/storage/AddressBookStorage.java
deleted file mode 100644
index 4599182b3f9..00000000000
--- a/src/main/java/seedu/address/storage/AddressBookStorage.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package seedu.address.storage;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyAddressBook;
-
-/**
- * Represents a storage for {@link seedu.address.model.AddressBook}.
- */
-public interface AddressBookStorage {
-
- /**
- * Returns the file path of the data file.
- */
- Path getAddressBookFilePath();
-
- /**
- * Returns AddressBook data as a {@link ReadOnlyAddressBook}.
- * Returns {@code Optional.empty()} if storage file is not found.
- * @throws DataConversionException if the data in storage is not in the expected format.
- * @throws IOException if there was any problem when reading from the storage.
- */
- Optional readAddressBook() throws DataConversionException, IOException;
-
- /**
- * @see #getAddressBookFilePath()
- */
- Optional readAddressBook(Path filePath) throws DataConversionException, IOException;
-
- /**
- * Saves the given {@link ReadOnlyAddressBook} to the storage.
- * @param addressBook cannot be null.
- * @throws IOException if there was any problem writing to the file.
- */
- void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException;
-
- /**
- * @see #saveAddressBook(ReadOnlyAddressBook)
- */
- void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException;
-
-}
diff --git a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java
deleted file mode 100644
index a6321cec2ea..00000000000
--- a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package seedu.address.storage;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * Jackson-friendly version of {@link Person}.
- */
-class JsonAdaptedPerson {
-
- public static final String MISSING_FIELD_MESSAGE_FORMAT = "Person's %s field is missing!";
-
- private final String name;
- private final String phone;
- private final String email;
- private final String address;
- private final List tagged = new ArrayList<>();
-
- /**
- * Constructs a {@code JsonAdaptedPerson} with the given person details.
- */
- @JsonCreator
- public JsonAdaptedPerson(@JsonProperty("name") String name, @JsonProperty("phone") String phone,
- @JsonProperty("email") String email, @JsonProperty("address") String address,
- @JsonProperty("tagged") List tagged) {
- this.name = name;
- this.phone = phone;
- this.email = email;
- this.address = address;
- if (tagged != null) {
- this.tagged.addAll(tagged);
- }
- }
-
- /**
- * Converts a given {@code Person} into this class for Jackson use.
- */
- public JsonAdaptedPerson(Person source) {
- name = source.getName().fullName;
- phone = source.getPhone().value;
- email = source.getEmail().value;
- address = source.getAddress().value;
- tagged.addAll(source.getTags().stream()
- .map(JsonAdaptedTag::new)
- .collect(Collectors.toList()));
- }
-
- /**
- * Converts this Jackson-friendly adapted person object into the model's {@code Person} object.
- *
- * @throws IllegalValueException if there were any data constraints violated in the adapted person.
- */
- public Person toModelType() throws IllegalValueException {
- final List personTags = new ArrayList<>();
- for (JsonAdaptedTag tag : tagged) {
- personTags.add(tag.toModelType());
- }
-
- if (name == null) {
- throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName()));
- }
- if (!Name.isValidName(name)) {
- throw new IllegalValueException(Name.MESSAGE_CONSTRAINTS);
- }
- final Name modelName = new Name(name);
-
- if (phone == null) {
- throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName()));
- }
- if (!Phone.isValidPhone(phone)) {
- throw new IllegalValueException(Phone.MESSAGE_CONSTRAINTS);
- }
- final Phone modelPhone = new Phone(phone);
-
- if (email == null) {
- throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName()));
- }
- if (!Email.isValidEmail(email)) {
- throw new IllegalValueException(Email.MESSAGE_CONSTRAINTS);
- }
- final Email modelEmail = new Email(email);
-
- if (address == null) {
- throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName()));
- }
- if (!Address.isValidAddress(address)) {
- throw new IllegalValueException(Address.MESSAGE_CONSTRAINTS);
- }
- final Address modelAddress = new Address(address);
-
- final Set modelTags = new HashSet<>(personTags);
- return new Person(modelName, modelPhone, modelEmail, modelAddress, modelTags);
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java b/src/main/java/seedu/address/storage/JsonAddressBookStorage.java
deleted file mode 100644
index dfab9daaa0d..00000000000
--- a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package seedu.address.storage;
-
-import static java.util.Objects.requireNonNull;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-import java.util.logging.Logger;
-
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.commons.util.FileUtil;
-import seedu.address.commons.util.JsonUtil;
-import seedu.address.model.ReadOnlyAddressBook;
-
-/**
- * A class to access AddressBook data stored as a json file on the hard disk.
- */
-public class JsonAddressBookStorage implements AddressBookStorage {
-
- private static final Logger logger = LogsCenter.getLogger(JsonAddressBookStorage.class);
-
- private Path filePath;
-
- public JsonAddressBookStorage(Path filePath) {
- this.filePath = filePath;
- }
-
- public Path getAddressBookFilePath() {
- return filePath;
- }
-
- @Override
- public Optional readAddressBook() throws DataConversionException {
- return readAddressBook(filePath);
- }
-
- /**
- * Similar to {@link #readAddressBook()}.
- *
- * @param filePath location of the data. Cannot be null.
- * @throws DataConversionException if the file is not in the correct format.
- */
- public Optional readAddressBook(Path filePath) throws DataConversionException {
- requireNonNull(filePath);
-
- Optional jsonAddressBook = JsonUtil.readJsonFile(
- filePath, JsonSerializableAddressBook.class);
- if (!jsonAddressBook.isPresent()) {
- return Optional.empty();
- }
-
- try {
- return Optional.of(jsonAddressBook.get().toModelType());
- } catch (IllegalValueException ive) {
- logger.info("Illegal values found in " + filePath + ": " + ive.getMessage());
- throw new DataConversionException(ive);
- }
- }
-
- @Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException {
- saveAddressBook(addressBook, filePath);
- }
-
- /**
- * Similar to {@link #saveAddressBook(ReadOnlyAddressBook)}.
- *
- * @param filePath location of the data. Cannot be null.
- */
- public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException {
- requireNonNull(addressBook);
- requireNonNull(filePath);
-
- FileUtil.createIfMissing(filePath);
- JsonUtil.saveJsonFile(new JsonSerializableAddressBook(addressBook), filePath);
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java
deleted file mode 100644
index 5efd834091d..00000000000
--- a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package seedu.address.storage;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-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;
-import seedu.address.model.person.Person;
-
-/**
- * An Immutable AddressBook that is serializable to JSON format.
- */
-@JsonRootName(value = "addressbook")
-class JsonSerializableAddressBook {
-
- public static final String MESSAGE_DUPLICATE_PERSON = "Persons list contains duplicate person(s).";
-
- private final List persons = new ArrayList<>();
-
- /**
- * Constructs a {@code JsonSerializableAddressBook} with the given persons.
- */
- @JsonCreator
- public JsonSerializableAddressBook(@JsonProperty("persons") List persons) {
- this.persons.addAll(persons);
- }
-
- /**
- * Converts a given {@code ReadOnlyAddressBook} into this class for Jackson use.
- *
- * @param source future changes to this will not affect the created {@code JsonSerializableAddressBook}.
- */
- public JsonSerializableAddressBook(ReadOnlyAddressBook source) {
- persons.addAll(source.getPersonList().stream().map(JsonAdaptedPerson::new).collect(Collectors.toList()));
- }
-
- /**
- * Converts this address book into the model's {@code AddressBook} object.
- *
- * @throws IllegalValueException if there were any data constraints violated.
- */
- public AddressBook toModelType() throws IllegalValueException {
- AddressBook addressBook = new AddressBook();
- for (JsonAdaptedPerson jsonAdaptedPerson : persons) {
- Person person = jsonAdaptedPerson.toModelType();
- if (addressBook.hasPerson(person)) {
- throw new IllegalValueException(MESSAGE_DUPLICATE_PERSON);
- }
- addressBook.addPerson(person);
- }
- return addressBook;
- }
-
-}
diff --git a/src/main/java/seedu/address/storage/Storage.java b/src/main/java/seedu/address/storage/Storage.java
deleted file mode 100644
index beda8bd9f11..00000000000
--- a/src/main/java/seedu/address/storage/Storage.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package seedu.address.storage;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
-
-/**
- * API of the Storage component
- */
-public interface Storage extends AddressBookStorage, UserPrefsStorage {
-
- @Override
- Optional readUserPrefs() throws DataConversionException, IOException;
-
- @Override
- void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException;
-
- @Override
- Path getAddressBookFilePath();
-
- @Override
- Optional readAddressBook() throws DataConversionException, IOException;
-
- @Override
- void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException;
-
-}
diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/address/storage/StorageManager.java
deleted file mode 100644
index 79868290974..00000000000
--- a/src/main/java/seedu/address/storage/StorageManager.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package seedu.address.storage;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-import java.util.logging.Logger;
-
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
-
-/**
- * Manages storage of AddressBook data in local storage.
- */
-public class StorageManager implements Storage {
-
- private static final Logger logger = LogsCenter.getLogger(StorageManager.class);
- private AddressBookStorage addressBookStorage;
- private UserPrefsStorage userPrefsStorage;
-
- /**
- * Creates a {@code StorageManager} with the given {@code AddressBookStorage} and {@code UserPrefStorage}.
- */
- public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage) {
- super();
- this.addressBookStorage = addressBookStorage;
- this.userPrefsStorage = userPrefsStorage;
- }
-
- // ================ UserPrefs methods ==============================
-
- @Override
- public Path getUserPrefsFilePath() {
- return userPrefsStorage.getUserPrefsFilePath();
- }
-
- @Override
- public Optional readUserPrefs() throws DataConversionException, IOException {
- return userPrefsStorage.readUserPrefs();
- }
-
- @Override
- public void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException {
- userPrefsStorage.saveUserPrefs(userPrefs);
- }
-
-
- // ================ AddressBook methods ==============================
-
- @Override
- public Path getAddressBookFilePath() {
- return addressBookStorage.getAddressBookFilePath();
- }
-
- @Override
- public Optional readAddressBook() throws DataConversionException, IOException {
- return readAddressBook(addressBookStorage.getAddressBookFilePath());
- }
-
- @Override
- public Optional readAddressBook(Path filePath) throws DataConversionException, IOException {
- logger.fine("Attempting to read data from file: " + filePath);
- return addressBookStorage.readAddressBook(filePath);
- }
-
- @Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException {
- saveAddressBook(addressBook, addressBookStorage.getAddressBookFilePath());
- }
-
- @Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException {
- logger.fine("Attempting to write to data file: " + filePath);
- addressBookStorage.saveAddressBook(addressBook, filePath);
- }
-
-}
diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java
deleted file mode 100644
index 7fc927bc5d9..00000000000
--- a/src/main/java/seedu/address/ui/PersonCard.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package seedu.address.ui;
-
-import java.util.Comparator;
-
-import javafx.fxml.FXML;
-import javafx.scene.control.Label;
-import javafx.scene.layout.FlowPane;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.Region;
-import seedu.address.model.person.Person;
-
-/**
- * An UI component that displays information of a {@code Person}.
- */
-public class PersonCard extends UiPart {
-
- private static final String FXML = "PersonListCard.fxml";
-
- /**
- * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX.
- * As a consequence, UI elements' variable names cannot be set to such keywords
- * or an exception will be thrown by JavaFX during runtime.
- *
- * @see The issue on AddressBook level 4
- */
-
- public final Person person;
-
- @FXML
- private HBox cardPane;
- @FXML
- private Label name;
- @FXML
- private Label id;
- @FXML
- private Label phone;
- @FXML
- private Label address;
- @FXML
- private Label email;
- @FXML
- private FlowPane tags;
-
- /**
- * Creates a {@code PersonCode} with the given {@code Person} and index to display.
- */
- public PersonCard(Person person, int displayedIndex) {
- super(FXML);
- this.person = person;
- id.setText(displayedIndex + ". ");
- name.setText(person.getName().fullName);
- phone.setText(person.getPhone().value);
- address.setText(person.getAddress().value);
- email.setText(person.getEmail().value);
- person.getTags().stream()
- .sorted(Comparator.comparing(tag -> tag.tagName))
- .forEach(tag -> tags.getChildren().add(new Label(tag.tagName)));
- }
-
- @Override
- public boolean equals(Object other) {
- // short circuit if same object
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof PersonCard)) {
- return false;
- }
-
- // state check
- PersonCard card = (PersonCard) other;
- return id.getText().equals(card.id.getText())
- && person.equals(card.person);
- }
-}
diff --git a/src/main/java/seedu/address/ui/PersonListPanel.java b/src/main/java/seedu/address/ui/PersonListPanel.java
deleted file mode 100644
index f4c501a897b..00000000000
--- a/src/main/java/seedu/address/ui/PersonListPanel.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package seedu.address.ui;
-
-import java.util.logging.Logger;
-
-import javafx.collections.ObservableList;
-import javafx.fxml.FXML;
-import javafx.scene.control.ListCell;
-import javafx.scene.control.ListView;
-import javafx.scene.layout.Region;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.model.person.Person;
-
-/**
- * Panel containing the list of persons.
- */
-public class PersonListPanel extends UiPart {
- private static final String FXML = "PersonListPanel.fxml";
- private final Logger logger = LogsCenter.getLogger(PersonListPanel.class);
-
- @FXML
- private ListView personListView;
-
- /**
- * Creates a {@code PersonListPanel} with the given {@code ObservableList}.
- */
- public PersonListPanel(ObservableList personList) {
- super(FXML);
- personListView.setItems(personList);
- personListView.setCellFactory(listView -> new PersonListViewCell());
- }
-
- /**
- * Custom {@code ListCell} that displays the graphics of a {@code Person} using a {@code PersonCard}.
- */
- class PersonListViewCell extends ListCell {
- @Override
- protected void updateItem(Person person, boolean empty) {
- super.updateItem(person, empty);
-
- if (empty || person == null) {
- setGraphic(null);
- setText(null);
- } else {
- setGraphic(new PersonCard(person, getIndex() + 1).getRoot());
- }
- }
- }
-
-}
diff --git a/src/main/java/seedu/address/AppParameters.java b/src/main/java/seedu/medmoriser/AppParameters.java
similarity index 93%
rename from src/main/java/seedu/address/AppParameters.java
rename to src/main/java/seedu/medmoriser/AppParameters.java
index ab552c398f3..fe30589b836 100644
--- a/src/main/java/seedu/address/AppParameters.java
+++ b/src/main/java/seedu/medmoriser/AppParameters.java
@@ -1,4 +1,4 @@
-package seedu.address;
+package seedu.medmoriser;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -7,8 +7,8 @@
import java.util.logging.Logger;
import javafx.application.Application;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.util.FileUtil;
+import seedu.medmoriser.commons.core.LogsCenter;
+import seedu.medmoriser.commons.util.FileUtil;
/**
* Represents the parsed command-line parameters given to the application.
diff --git a/src/main/java/seedu/address/Main.java b/src/main/java/seedu/medmoriser/Main.java
similarity index 97%
rename from src/main/java/seedu/address/Main.java
rename to src/main/java/seedu/medmoriser/Main.java
index 052a5068631..d019911bfef 100644
--- a/src/main/java/seedu/address/Main.java
+++ b/src/main/java/seedu/medmoriser/Main.java
@@ -1,4 +1,4 @@
-package seedu.address;
+package seedu.medmoriser;
import javafx.application.Application;
diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/medmoriser/MainApp.java
similarity index 67%
rename from src/main/java/seedu/address/MainApp.java
rename to src/main/java/seedu/medmoriser/MainApp.java
index e5cfb161b73..c75d8f8fdd1 100644
--- a/src/main/java/seedu/address/MainApp.java
+++ b/src/main/java/seedu/medmoriser/MainApp.java
@@ -1,4 +1,4 @@
-package seedu.address;
+package seedu.medmoriser;
import java.io.IOException;
import java.nio.file.Path;
@@ -7,36 +7,36 @@
import javafx.application.Application;
import javafx.stage.Stage;
-import seedu.address.commons.core.Config;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.core.Version;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.commons.util.ConfigUtil;
-import seedu.address.commons.util.StringUtil;
-import seedu.address.logic.Logic;
-import seedu.address.logic.LogicManager;
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.util.SampleDataUtil;
-import seedu.address.storage.AddressBookStorage;
-import seedu.address.storage.JsonAddressBookStorage;
-import seedu.address.storage.JsonUserPrefsStorage;
-import seedu.address.storage.Storage;
-import seedu.address.storage.StorageManager;
-import seedu.address.storage.UserPrefsStorage;
-import seedu.address.ui.Ui;
-import seedu.address.ui.UiManager;
+import seedu.medmoriser.commons.core.Config;
+import seedu.medmoriser.commons.core.LogsCenter;
+import seedu.medmoriser.commons.core.Version;
+import seedu.medmoriser.commons.exceptions.DataConversionException;
+import seedu.medmoriser.commons.util.ConfigUtil;
+import seedu.medmoriser.commons.util.StringUtil;
+import seedu.medmoriser.logic.Logic;
+import seedu.medmoriser.logic.LogicManager;
+import seedu.medmoriser.model.Medmoriser;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ModelManager;
+import seedu.medmoriser.model.ReadOnlyMedmoriser;
+import seedu.medmoriser.model.ReadOnlyUserPrefs;
+import seedu.medmoriser.model.UserPrefs;
+import seedu.medmoriser.model.util.SampleDataUtil;
+import seedu.medmoriser.storage.JsonMedmoriserStorage;
+import seedu.medmoriser.storage.JsonUserPrefsStorage;
+import seedu.medmoriser.storage.MedmoriserStorage;
+import seedu.medmoriser.storage.Storage;
+import seedu.medmoriser.storage.StorageManager;
+import seedu.medmoriser.storage.UserPrefsStorage;
+import seedu.medmoriser.ui.Ui;
+import seedu.medmoriser.ui.UiManager;
/**
* Runs the application.
*/
public class MainApp extends Application {
- public static final Version VERSION = new Version(0, 6, 0, true);
+ public static final Version VERSION = new Version(1, 4, 0, true);
private static final Logger logger = LogsCenter.getLogger(MainApp.class);
@@ -48,7 +48,7 @@ public class MainApp extends Application {
@Override
public void init() throws Exception {
- logger.info("=============================[ Initializing AddressBook ]===========================");
+ logger.info("=============================[ Initializing Medmoriser ]===========================");
super.init();
AppParameters appParameters = AppParameters.parse(getParameters());
@@ -56,8 +56,8 @@ public void init() throws Exception {
UserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(config.getUserPrefsFilePath());
UserPrefs userPrefs = initPrefs(userPrefsStorage);
- AddressBookStorage addressBookStorage = new JsonAddressBookStorage(userPrefs.getAddressBookFilePath());
- storage = new StorageManager(addressBookStorage, userPrefsStorage);
+ MedmoriserStorage medmoriserStorage = new JsonMedmoriserStorage(userPrefs.getMedmoriserFilePath());
+ storage = new StorageManager(medmoriserStorage, userPrefsStorage);
initLogging(config);
@@ -69,25 +69,25 @@ public void init() throws Exception {
}
/**
- * Returns a {@code ModelManager} with the data from {@code storage}'s address book and {@code userPrefs}.
- * The data from the sample address book will be used instead if {@code storage}'s address book is not found,
- * or an empty address book will be used instead if errors occur when reading {@code storage}'s address book.
+ * Returns a {@code ModelManager} with the data from {@code storage}'s medmoriser and {@code userPrefs}.
+ * The data from the sample medmoriser will be used instead if {@code storage}'s medmoriser is not found,
+ * or an empty medmoriser will be used instead if errors occur when reading {@code storage}'s medmoriser.
*/
private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) {
- Optional addressBookOptional;
- ReadOnlyAddressBook initialData;
+ Optional medmoriserOptional;
+ ReadOnlyMedmoriser initialData;
try {
- addressBookOptional = storage.readAddressBook();
- if (!addressBookOptional.isPresent()) {
- logger.info("Data file not found. Will be starting with a sample AddressBook");
+ medmoriserOptional = storage.readMedmoriser();
+ if (!medmoriserOptional.isPresent()) {
+ logger.info("Data file not found. Will be starting with a sample Medmoriser");
}
- initialData = addressBookOptional.orElseGet(SampleDataUtil::getSampleAddressBook);
+ initialData = medmoriserOptional.orElseGet(SampleDataUtil::getSampleMedmoriser);
} catch (DataConversionException e) {
- logger.warning("Data file not in the correct format. Will be starting with an empty AddressBook");
- initialData = new AddressBook();
+ logger.warning("Data file not in the correct format. Will be starting with an empty Medmoriser");
+ initialData = new Medmoriser();
} catch (IOException e) {
- logger.warning("Problem while reading from the file. Will be starting with an empty AddressBook");
- initialData = new AddressBook();
+ logger.warning("Problem while reading from the file. Will be starting with an empty Medmoriser");
+ initialData = new Medmoriser();
}
return new ModelManager(initialData, userPrefs);
@@ -151,7 +151,7 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) {
+ "Using default user prefs");
initializedPrefs = new UserPrefs();
} catch (IOException e) {
- logger.warning("Problem while reading from the file. Will be starting with an empty AddressBook");
+ logger.warning("Problem while reading from the file. Will be starting with an empty Medmoriser");
initializedPrefs = new UserPrefs();
}
@@ -167,13 +167,13 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) {
@Override
public void start(Stage primaryStage) {
- logger.info("Starting AddressBook " + MainApp.VERSION);
+ logger.info("Starting Medmoriser " + MainApp.VERSION);
ui.start(primaryStage);
}
@Override
public void stop() {
- logger.info("============================ [ Stopping Address Book ] =============================");
+ logger.info("============================ [ Stopping Medmoriser ] =============================");
try {
storage.saveUserPrefs(model.getUserPrefs());
} catch (IOException e) {
diff --git a/src/main/java/seedu/address/commons/core/Config.java b/src/main/java/seedu/medmoriser/commons/core/Config.java
similarity index 97%
rename from src/main/java/seedu/address/commons/core/Config.java
rename to src/main/java/seedu/medmoriser/commons/core/Config.java
index 91145745521..77a497c4d04 100644
--- a/src/main/java/seedu/address/commons/core/Config.java
+++ b/src/main/java/seedu/medmoriser/commons/core/Config.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.medmoriser.commons.core;
import java.nio.file.Path;
import java.nio.file.Paths;
diff --git a/src/main/java/seedu/address/commons/core/GuiSettings.java b/src/main/java/seedu/medmoriser/commons/core/GuiSettings.java
similarity index 98%
rename from src/main/java/seedu/address/commons/core/GuiSettings.java
rename to src/main/java/seedu/medmoriser/commons/core/GuiSettings.java
index ba33653be67..efbb551fc33 100644
--- a/src/main/java/seedu/address/commons/core/GuiSettings.java
+++ b/src/main/java/seedu/medmoriser/commons/core/GuiSettings.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.medmoriser.commons.core;
import java.awt.Point;
import java.io.Serializable;
diff --git a/src/main/java/seedu/address/commons/core/LogsCenter.java b/src/main/java/seedu/medmoriser/commons/core/LogsCenter.java
similarity index 97%
rename from src/main/java/seedu/address/commons/core/LogsCenter.java
rename to src/main/java/seedu/medmoriser/commons/core/LogsCenter.java
index 431e7185e76..f9e8ad72f1e 100644
--- a/src/main/java/seedu/address/commons/core/LogsCenter.java
+++ b/src/main/java/seedu/medmoriser/commons/core/LogsCenter.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.medmoriser.commons.core;
import java.io.IOException;
import java.util.Arrays;
@@ -18,7 +18,7 @@
public class LogsCenter {
private static final int MAX_FILE_COUNT = 5;
private static final int MAX_FILE_SIZE_IN_BYTES = (int) (Math.pow(2, 20) * 5); // 5MB
- private static final String LOG_FILE = "addressbook.log";
+ private static final String LOG_FILE = "medmoriser.log";
private static Level currentLogLevel = Level.INFO;
private static final Logger logger = LogsCenter.getLogger(LogsCenter.class);
private static FileHandler fileHandler;
diff --git a/src/main/java/seedu/medmoriser/commons/core/Messages.java b/src/main/java/seedu/medmoriser/commons/core/Messages.java
new file mode 100644
index 00000000000..fa7934a3286
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/commons/core/Messages.java
@@ -0,0 +1,15 @@
+package seedu.medmoriser.commons.core;
+
+/**
+ * Container for user visible messages.
+ */
+public class Messages {
+
+ public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command";
+ public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s";
+ public static final String MESSAGE_INVALID_QANDA_DISPLAYED_INDEX = "The qAndA index "
+ + "provided is invalid";
+ public static final String MESSAGE_QANDA_LISTED_OVERVIEW = "%1$d qAndA listed!";
+ public static final String MESSAGE_ONGOING_QUIZ = "Please end the ongoing quiz first.";
+
+}
diff --git a/src/main/java/seedu/address/commons/core/Version.java b/src/main/java/seedu/medmoriser/commons/core/Version.java
similarity index 98%
rename from src/main/java/seedu/address/commons/core/Version.java
rename to src/main/java/seedu/medmoriser/commons/core/Version.java
index 12142ec1e32..0c423292478 100644
--- a/src/main/java/seedu/address/commons/core/Version.java
+++ b/src/main/java/seedu/medmoriser/commons/core/Version.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.medmoriser.commons.core;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
diff --git a/src/main/java/seedu/address/commons/core/index/Index.java b/src/main/java/seedu/medmoriser/commons/core/index/Index.java
similarity index 97%
rename from src/main/java/seedu/address/commons/core/index/Index.java
rename to src/main/java/seedu/medmoriser/commons/core/index/Index.java
index 19536439c09..1a98006d3ee 100644
--- a/src/main/java/seedu/address/commons/core/index/Index.java
+++ b/src/main/java/seedu/medmoriser/commons/core/index/Index.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core.index;
+package seedu.medmoriser.commons.core.index;
/**
* Represents a zero-based or one-based index.
diff --git a/src/main/java/seedu/address/commons/exceptions/DataConversionException.java b/src/main/java/seedu/medmoriser/commons/exceptions/DataConversionException.java
similarity index 83%
rename from src/main/java/seedu/address/commons/exceptions/DataConversionException.java
rename to src/main/java/seedu/medmoriser/commons/exceptions/DataConversionException.java
index 1f689bd8e3f..3912c0f9c7b 100644
--- a/src/main/java/seedu/address/commons/exceptions/DataConversionException.java
+++ b/src/main/java/seedu/medmoriser/commons/exceptions/DataConversionException.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.exceptions;
+package seedu.medmoriser.commons.exceptions;
/**
* Represents an error during conversion of data from one format to another
diff --git a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java b/src/main/java/seedu/medmoriser/commons/exceptions/IllegalValueException.java
similarity index 92%
rename from src/main/java/seedu/address/commons/exceptions/IllegalValueException.java
rename to src/main/java/seedu/medmoriser/commons/exceptions/IllegalValueException.java
index 19124db485c..17e49babb12 100644
--- a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java
+++ b/src/main/java/seedu/medmoriser/commons/exceptions/IllegalValueException.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.exceptions;
+package seedu.medmoriser.commons.exceptions;
/**
* Signals that some given data does not fulfill some constraints.
diff --git a/src/main/java/seedu/address/commons/util/AppUtil.java b/src/main/java/seedu/medmoriser/commons/util/AppUtil.java
similarity index 94%
rename from src/main/java/seedu/address/commons/util/AppUtil.java
rename to src/main/java/seedu/medmoriser/commons/util/AppUtil.java
index 87aa89c0326..70bbf9ec157 100644
--- a/src/main/java/seedu/address/commons/util/AppUtil.java
+++ b/src/main/java/seedu/medmoriser/commons/util/AppUtil.java
@@ -1,9 +1,9 @@
-package seedu.address.commons.util;
+package seedu.medmoriser.commons.util;
import static java.util.Objects.requireNonNull;
import javafx.scene.image.Image;
-import seedu.address.MainApp;
+import seedu.medmoriser.MainApp;
/**
* A container for App specific utility functions
diff --git a/src/main/java/seedu/address/commons/util/CollectionUtil.java b/src/main/java/seedu/medmoriser/commons/util/CollectionUtil.java
similarity index 96%
rename from src/main/java/seedu/address/commons/util/CollectionUtil.java
rename to src/main/java/seedu/medmoriser/commons/util/CollectionUtil.java
index eafe4dfd681..e8578ebb2ca 100644
--- a/src/main/java/seedu/address/commons/util/CollectionUtil.java
+++ b/src/main/java/seedu/medmoriser/commons/util/CollectionUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.medmoriser.commons.util;
import static java.util.Objects.requireNonNull;
diff --git a/src/main/java/seedu/address/commons/util/ConfigUtil.java b/src/main/java/seedu/medmoriser/commons/util/ConfigUtil.java
similarity index 76%
rename from src/main/java/seedu/address/commons/util/ConfigUtil.java
rename to src/main/java/seedu/medmoriser/commons/util/ConfigUtil.java
index f7f8a2bd44c..d9ed1a96d6f 100644
--- a/src/main/java/seedu/address/commons/util/ConfigUtil.java
+++ b/src/main/java/seedu/medmoriser/commons/util/ConfigUtil.java
@@ -1,11 +1,11 @@
-package seedu.address.commons.util;
+package seedu.medmoriser.commons.util;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
-import seedu.address.commons.core.Config;
-import seedu.address.commons.exceptions.DataConversionException;
+import seedu.medmoriser.commons.core.Config;
+import seedu.medmoriser.commons.exceptions.DataConversionException;
/**
* A class for accessing the Config File.
diff --git a/src/main/java/seedu/address/commons/util/FileUtil.java b/src/main/java/seedu/medmoriser/commons/util/FileUtil.java
similarity index 98%
rename from src/main/java/seedu/address/commons/util/FileUtil.java
rename to src/main/java/seedu/medmoriser/commons/util/FileUtil.java
index b1e2767cdd9..363a1484d46 100644
--- a/src/main/java/seedu/address/commons/util/FileUtil.java
+++ b/src/main/java/seedu/medmoriser/commons/util/FileUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.medmoriser.commons.util;
import java.io.IOException;
import java.nio.file.Files;
diff --git a/src/main/java/seedu/address/commons/util/JsonUtil.java b/src/main/java/seedu/medmoriser/commons/util/JsonUtil.java
similarity index 97%
rename from src/main/java/seedu/address/commons/util/JsonUtil.java
rename to src/main/java/seedu/medmoriser/commons/util/JsonUtil.java
index 8ef609f055d..07849d4aedf 100644
--- a/src/main/java/seedu/address/commons/util/JsonUtil.java
+++ b/src/main/java/seedu/medmoriser/commons/util/JsonUtil.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.medmoriser.commons.util;
import static java.util.Objects.requireNonNull;
@@ -20,8 +20,8 @@
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.exceptions.DataConversionException;
+import seedu.medmoriser.commons.core.LogsCenter;
+import seedu.medmoriser.commons.exceptions.DataConversionException;
/**
* Converts a Java object instance to JSON and vice versa
diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/seedu/medmoriser/commons/util/StringUtil.java
similarity index 95%
rename from src/main/java/seedu/address/commons/util/StringUtil.java
rename to src/main/java/seedu/medmoriser/commons/util/StringUtil.java
index 61cc8c9a1cb..073d5844b28 100644
--- a/src/main/java/seedu/address/commons/util/StringUtil.java
+++ b/src/main/java/seedu/medmoriser/commons/util/StringUtil.java
@@ -1,7 +1,7 @@
-package seedu.address.commons.util;
+package seedu.medmoriser.commons.util;
import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
+import static seedu.medmoriser.commons.util.AppUtil.checkArgument;
import java.io.PrintWriter;
import java.io.StringWriter;
diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/medmoriser/logic/Logic.java
similarity index 58%
rename from src/main/java/seedu/address/logic/Logic.java
rename to src/main/java/seedu/medmoriser/logic/Logic.java
index 92cd8fa605a..b7ad118265b 100644
--- a/src/main/java/seedu/address/logic/Logic.java
+++ b/src/main/java/seedu/medmoriser/logic/Logic.java
@@ -1,14 +1,14 @@
-package seedu.address.logic;
+package seedu.medmoriser.logic;
import java.nio.file.Path;
import javafx.collections.ObservableList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Person;
+import seedu.medmoriser.commons.core.GuiSettings;
+import seedu.medmoriser.logic.commands.CommandResult;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.model.ReadOnlyMedmoriser;
+import seedu.medmoriser.model.qanda.QAndA;
/**
* API of the Logic component
@@ -26,17 +26,17 @@ public interface Logic {
/**
* Returns the AddressBook.
*
- * @see seedu.address.model.Model#getAddressBook()
+ * @see seedu.medmoriser.model.Model#getMedmoriser()
*/
- ReadOnlyAddressBook getAddressBook();
+ ReadOnlyMedmoriser getMedmoriser();
- /** Returns an unmodifiable view of the filtered list of persons */
- ObservableList getFilteredPersonList();
+ /** Returns an unmodifiable view of the filtered list of qAndAs */
+ ObservableList getFilteredQAndAList();
/**
* Returns the user prefs' address book file path.
*/
- Path getAddressBookFilePath();
+ Path getMedmoriserFilePath();
/**
* Returns the user prefs' GUI settings.
diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/medmoriser/logic/LogicManager.java
similarity index 56%
rename from src/main/java/seedu/address/logic/LogicManager.java
rename to src/main/java/seedu/medmoriser/logic/LogicManager.java
index 9d9c6d15bdc..34d85249992 100644
--- a/src/main/java/seedu/address/logic/LogicManager.java
+++ b/src/main/java/seedu/medmoriser/logic/LogicManager.java
@@ -1,21 +1,21 @@
-package seedu.address.logic;
+package seedu.medmoriser.logic;
import java.io.IOException;
import java.nio.file.Path;
import java.util.logging.Logger;
import javafx.collections.ObservableList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.AddressBookParser;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.Model;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.person.Person;
-import seedu.address.storage.Storage;
+import seedu.medmoriser.commons.core.GuiSettings;
+import seedu.medmoriser.commons.core.LogsCenter;
+import seedu.medmoriser.logic.commands.Command;
+import seedu.medmoriser.logic.commands.CommandResult;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.logic.parser.MedmoriserParser;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ReadOnlyMedmoriser;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.storage.Storage;
/**
* The main LogicManager of the app.
@@ -26,7 +26,7 @@ public class LogicManager implements Logic {
private final Model model;
private final Storage storage;
- private final AddressBookParser addressBookParser;
+ private final MedmoriserParser medmoriserParser;
/**
* Constructs a {@code LogicManager} with the given {@code Model} and {@code Storage}.
@@ -34,19 +34,18 @@ public class LogicManager implements Logic {
public LogicManager(Model model, Storage storage) {
this.model = model;
this.storage = storage;
- addressBookParser = new AddressBookParser();
+ medmoriserParser = new MedmoriserParser();
}
@Override
public CommandResult execute(String commandText) throws CommandException, ParseException {
logger.info("----------------[USER COMMAND][" + commandText + "]");
-
CommandResult commandResult;
- Command command = addressBookParser.parseCommand(commandText);
+ Command command = medmoriserParser.parseCommand(commandText);
commandResult = command.execute(model);
try {
- storage.saveAddressBook(model.getAddressBook());
+ storage.saveMedmoriser(model.getMedmoriser());
} catch (IOException ioe) {
throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe);
}
@@ -55,18 +54,18 @@ public CommandResult execute(String commandText) throws CommandException, ParseE
}
@Override
- public ReadOnlyAddressBook getAddressBook() {
- return model.getAddressBook();
+ public ReadOnlyMedmoriser getMedmoriser() {
+ return model.getMedmoriser();
}
@Override
- public ObservableList getFilteredPersonList() {
- return model.getFilteredPersonList();
+ public ObservableList getFilteredQAndAList() {
+ return model.getFilteredQAndAList();
}
@Override
- public Path getAddressBookFilePath() {
- return model.getAddressBookFilePath();
+ public Path getMedmoriserFilePath() {
+ return model.getMedmoriserFilePath();
}
@Override
diff --git a/src/main/java/seedu/medmoriser/logic/commands/AddCommand.java b/src/main/java/seedu/medmoriser/logic/commands/AddCommand.java
new file mode 100644
index 00000000000..f73c16669d4
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/commands/AddCommand.java
@@ -0,0 +1,68 @@
+package seedu.medmoriser.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_ANSWER;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_QUESTION;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_TAG;
+
+import seedu.medmoriser.commons.core.Messages;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.qanda.QAndA;
+
+/**
+ * Adds a QuestionSet to the question bank.
+ */
+public class AddCommand extends Command {
+
+ public static final String COMMAND_WORD = "add";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a QAndA to the question bank "
+ + "Parameters: "
+ + PREFIX_QUESTION + "QUESTION "
+ + PREFIX_ANSWER + "ANSWER "
+ + "[" + PREFIX_TAG + "TAG]...\n"
+ + "Example: " + COMMAND_WORD + " "
+ + PREFIX_QUESTION + "How many taste buds does the average human have?" + " "
+ + PREFIX_ANSWER + "10,000" + " "
+ + PREFIX_TAG + "Human Anatomy";
+
+ public static final String MESSAGE_SUCCESS = "New QAndA added: %1$s";
+
+ public static final String MESSAGE_DUPLICATE_QANDA = "This QAndA already exists in the answer book";
+
+ public static final String MESSAGE_ONE_PREFIX = "There are multiple prefixes present. Ensure that q/ is before the"
+ + " question that you intend to add and a/ is before the answer to the question. There can only "
+ + "be one instance of q/ and a/ .";
+
+ private final QAndA toAdd;
+
+ /**
+ * Creates an AddCommand to add the specified {@code QuestionSet}
+ */
+ public AddCommand(QAndA qAndA) {
+ requireNonNull(qAndA);
+ toAdd = qAndA;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ if (model.hasQAndA(toAdd)) {
+ throw new CommandException(MESSAGE_DUPLICATE_QANDA);
+ } else if (QuizCommand.getIsQuiz()) {
+ throw new CommandException(Messages.MESSAGE_ONGOING_QUIZ);
+ } else {
+ model.addQAndA(toAdd);
+ return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd), true);
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof AddCommand // instanceof handles nulls
+ && toAdd.equals(((AddCommand) other).toAdd));
+ }
+}
diff --git a/src/main/java/seedu/medmoriser/logic/commands/AnswerCommand.java b/src/main/java/seedu/medmoriser/logic/commands/AnswerCommand.java
new file mode 100644
index 00000000000..93c9a3e2965
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/commands/AnswerCommand.java
@@ -0,0 +1,77 @@
+package seedu.medmoriser.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Model;
+
+/**
+ * Receives the user's answer for a quiz.
+ */
+public class AnswerCommand extends Command {
+
+ public static final String COMMAND_WORD = "answer";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": The answer that the user keys in for the quiz "
+ + "question. \n"
+ + "Example: " + COMMAND_WORD + " This is my answer";
+
+ public static final String MESSAGE_USER_ANSWER = "Your answer: ";
+
+ public static final String MESSAGE_NOT_QUIZ = "There is no ongoing quiz.";
+
+ public static final String MESSAGE_ALREADY_ANSWERED = "This quiz has already been answered";
+
+ private static boolean beenAnswered = false;
+
+ private static CommandResult currCommandResult;
+
+ private final String userAnswer;
+
+ /**
+ * Creates an AnswerCommand
+ * @param userAnswer The user's input answer.
+ */
+ public AnswerCommand(String userAnswer) {
+ this.userAnswer = userAnswer;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ if (!QuizCommand.getIsQuiz()) {
+ throw new CommandException(MESSAGE_NOT_QUIZ);
+ } else {
+ model.getFilteredQAndAList().get(0).setQuizAnswer();
+ if (beenAnswered) {
+ throw new CommandException(currCommandResult.getFeedbackToUser() + "\n" + MESSAGE_ALREADY_ANSWERED);
+ } else {
+ setBeenAnswered(true, model);
+ currCommandResult = new CommandResult(MESSAGE_USER_ANSWER + userAnswer);
+ return currCommandResult;
+ }
+ }
+ }
+
+ public static void setBeenAnswered(boolean hasBeenAnswered, Model model) {
+ beenAnswered = hasBeenAnswered;
+ if (!beenAnswered) {
+ for (int i = 0; i < model.getFilteredQAndAList().size(); i++) {
+ model.getFilteredQAndAList().get(i).setNotBeenAnswered();
+ }
+ } else {
+ model.getFilteredQAndAList().get(0).setBeenAnswered();
+ }
+ }
+
+ public static void setCurrCommandResult(String msg) {
+ currCommandResult = new CommandResult(msg);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof AnswerCommand // instanceof handles nulls
+ && userAnswer.equals(((AnswerCommand) other).userAnswer)); // state check
+ }
+}
diff --git a/src/main/java/seedu/medmoriser/logic/commands/ClearCommand.java b/src/main/java/seedu/medmoriser/logic/commands/ClearCommand.java
new file mode 100644
index 00000000000..9e44f7ef10b
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/commands/ClearCommand.java
@@ -0,0 +1,30 @@
+package seedu.medmoriser.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import seedu.medmoriser.commons.core.Messages;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Medmoriser;
+import seedu.medmoriser.model.Model;
+
+/**
+ * Clears the address book.
+ */
+public class ClearCommand extends Command {
+
+ public static final String COMMAND_WORD = "clear";
+ public static final String MESSAGE_SUCCESS = "Medmoriser has been cleared!";
+
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ if (QuizCommand.getIsQuiz()) {
+ throw new CommandException(Messages.MESSAGE_ONGOING_QUIZ);
+ } else {
+ model.setMedmoriser(new Medmoriser());
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/seedu/medmoriser/logic/commands/Command.java
similarity index 77%
rename from src/main/java/seedu/address/logic/commands/Command.java
rename to src/main/java/seedu/medmoriser/logic/commands/Command.java
index 64f18992160..c43a0da7000 100644
--- a/src/main/java/seedu/address/logic/commands/Command.java
+++ b/src/main/java/seedu/medmoriser/logic/commands/Command.java
@@ -1,7 +1,7 @@
-package seedu.address.logic.commands;
+package seedu.medmoriser.logic.commands;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Model;
/**
* Represents a command with hidden internal logic and the ability to be executed.
diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/seedu/medmoriser/logic/commands/CommandResult.java
similarity index 71%
rename from src/main/java/seedu/address/logic/commands/CommandResult.java
rename to src/main/java/seedu/medmoriser/logic/commands/CommandResult.java
index 92f900b7916..a0601c3daa5 100644
--- a/src/main/java/seedu/address/logic/commands/CommandResult.java
+++ b/src/main/java/seedu/medmoriser/logic/commands/CommandResult.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.commands;
+package seedu.medmoriser.logic.commands;
import static java.util.Objects.requireNonNull;
@@ -9,6 +9,9 @@
*/
public class CommandResult {
+ /** Answers should be shown. */
+ private static boolean isAnswerDisplayed = true;
+
private final String feedbackToUser;
/** Help information should be shown to the user. */
@@ -34,10 +37,23 @@ public CommandResult(String feedbackToUser) {
this(feedbackToUser, false, false);
}
+ /**
+ * Constructs a {@code CommandResult} with the specified {@code feedbackToUser}
+ * and hides/shows the answers, with other fields set to their default value.
+ */
+ public CommandResult(String feedbackToUser, boolean isAnswerDisplayed) {
+ this(feedbackToUser, false, false);
+ CommandResult.isAnswerDisplayed = isAnswerDisplayed;
+ }
+
public String getFeedbackToUser() {
return feedbackToUser;
}
+ public boolean isAnswerDisplayed() {
+ return isAnswerDisplayed;
+ }
+
public boolean isShowHelp() {
return showHelp;
}
@@ -46,6 +62,10 @@ public boolean isExit() {
return exit;
}
+ public void setIsAnswerDisplayed(boolean isAnswerDisplayed) {
+ this.isAnswerDisplayed = isAnswerDisplayed;
+ }
+
@Override
public boolean equals(Object other) {
if (other == this) {
diff --git a/src/main/java/seedu/medmoriser/logic/commands/DeleteCommand.java b/src/main/java/seedu/medmoriser/logic/commands/DeleteCommand.java
new file mode 100644
index 00000000000..6e386ad114f
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/commands/DeleteCommand.java
@@ -0,0 +1,58 @@
+package seedu.medmoriser.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.List;
+
+import seedu.medmoriser.commons.core.Messages;
+import seedu.medmoriser.commons.core.index.Index;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.qanda.QAndA;
+
+/**
+ * Deletes a qAndA identified using it's displayed index from the address book.
+ */
+public class DeleteCommand extends Command {
+
+ public static final String COMMAND_WORD = "delete";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Deletes the QAndA identified by the index number used in the displayed QAndA list.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_DELETE_QANDA_SUCCESS = "Deleted QAndA: %1$s";
+
+ private final Index targetIndex;
+
+ public DeleteCommand(Index targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredQAndAList();
+
+ if (QuizCommand.getIsQuiz()) {
+ throw new CommandException(Messages.MESSAGE_ONGOING_QUIZ);
+ } else {
+
+ if (targetIndex.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_QANDA_DISPLAYED_INDEX);
+ }
+
+ QAndA qAndAToDelete = lastShownList.get(targetIndex.getZeroBased());
+ model.deleteQAndA(qAndAToDelete);
+ return new CommandResult(String.format(MESSAGE_DELETE_QANDA_SUCCESS, qAndAToDelete));
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof DeleteCommand // instanceof handles nulls
+ && targetIndex.equals(((DeleteCommand) other).targetIndex)); // state check
+ }
+}
diff --git a/src/main/java/seedu/medmoriser/logic/commands/EditCommand.java b/src/main/java/seedu/medmoriser/logic/commands/EditCommand.java
new file mode 100644
index 00000000000..1a1a4767c6f
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/commands/EditCommand.java
@@ -0,0 +1,207 @@
+package seedu.medmoriser.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_ANSWER;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_QUESTION;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_TAG;
+import static seedu.medmoriser.model.Model.PREDICATE_SHOW_ALL_QANDA;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+import seedu.medmoriser.commons.core.Messages;
+import seedu.medmoriser.commons.core.index.Index;
+import seedu.medmoriser.commons.util.CollectionUtil;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.qanda.Answer;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.qanda.Question;
+import seedu.medmoriser.model.tag.Tag;
+
+/**
+ * Edits the details of an existing QAndA in the question bank.
+ */
+public class EditCommand extends Command {
+
+ public static final String COMMAND_WORD = "edit";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the QAndA identified "
+ + "by the index number used in the displayed QAndA list. "
+ + "Existing values will be overwritten by the input values.\n"
+ + "Parameters: INDEX (must be a positive integer) "
+ + "[" + PREFIX_QUESTION + "QUESTION] "
+ + "[" + PREFIX_ANSWER + "ANSWER] "
+ + "[" + PREFIX_TAG + "TAG]...\n"
+ + "Example: " + COMMAND_WORD + " 1 "
+ + PREFIX_QUESTION + "What causes pimples? "
+ + PREFIX_ANSWER + "triggered by androgen hormones and, in some cases, genetics";
+
+ public static final String MESSAGE_EDIT_QANDA_SUCCESS = "Edited QAndA: %1$s";
+
+ public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided.";
+
+ public static final String MESSAGE_DUPLICATE_QANDA = "This QAndA already exists in the question bank.";
+
+ public static final String MESSAGE_ONE_PREFIX = "There are multiple prefixes present. Ensure that q/ is before the"
+ + " question that you intend to add and a/ is before the answer to the question. There can only "
+ + "be maximum one instance of q/ and a/ .";
+
+ private final Index index;
+ private final EditQAndADescriptor editQAndADescriptor;
+
+ /**
+ * @param index of the qAndA in the filtered qAndA list to edit
+ * @param editQAndADescriptor details to edit the qAndA with
+ */
+ public EditCommand(Index index, EditQAndADescriptor editQAndADescriptor) {
+ requireNonNull(index);
+ requireNonNull(editQAndADescriptor);
+
+ this.index = index;
+ this.editQAndADescriptor = new EditQAndADescriptor(editQAndADescriptor);
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ if (QuizCommand.getIsQuiz()) {
+ throw new CommandException(Messages.MESSAGE_ONGOING_QUIZ);
+ } else {
+ List lastShownList = model.getFilteredQAndAList();
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_QANDA_DISPLAYED_INDEX);
+ }
+
+ QAndA qAndAToEdit = lastShownList.get(index.getZeroBased());
+ QAndA editedQAndA = createEditedQAndA(qAndAToEdit, editQAndADescriptor);
+
+ if (!qAndAToEdit.isSameQAndA(editedQAndA) && model.hasQAndA(editedQAndA)) {
+ throw new CommandException(MESSAGE_DUPLICATE_QANDA);
+ }
+
+ model.setQAndA(qAndAToEdit, editedQAndA);
+ model.updateFilteredQAndAList(PREDICATE_SHOW_ALL_QANDA);
+ return new CommandResult(String.format(MESSAGE_EDIT_QANDA_SUCCESS, editedQAndA), true);
+ }
+ }
+
+ /**
+ * Creates and returns a {@code QAndA} with the details of {@code qAndAToEdit}
+ * edited with {@code editQAndADescriptor}.
+ */
+ private static QAndA createEditedQAndA(QAndA qAndAToEdit,
+ EditQAndADescriptor editQAndADescriptor) {
+ assert qAndAToEdit != null;
+
+ Question updatedQuestion = editQAndADescriptor.getQuestion().orElse(qAndAToEdit.getQuestion());
+ Answer updatedAnswer = editQAndADescriptor.getAnswer().orElse(qAndAToEdit.getAnswer());
+ Set updatedTags = editQAndADescriptor.getTags().orElse(qAndAToEdit.getTags());
+
+ return new QAndA(updatedQuestion, updatedAnswer, updatedTags);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof EditCommand)) {
+ return false;
+ }
+
+ // state check
+ EditCommand e = (EditCommand) other;
+ return index.equals(e.index)
+ && editQAndADescriptor.equals(e.editQAndADescriptor);
+ }
+
+ /**
+ * Stores the details to edit the qAndA with. Each non-empty field value will replace the
+ * corresponding field value of the qAndA.
+ */
+ public static class EditQAndADescriptor {
+ private Question question;
+ private Answer answer;
+ private Set tags;
+
+ public EditQAndADescriptor() {}
+
+ /**
+ * Copy constructor.
+ * A defensive copy of {@code tags} is used internally.
+ */
+ public EditQAndADescriptor(EditQAndADescriptor toCopy) {
+ setQuestion(toCopy.question);
+ setAnswer(toCopy.answer);
+ setTags(toCopy.tags);
+ }
+
+ /**
+ * Returns true if at least one field is edited.
+ */
+ public boolean isAnyFieldEdited() {
+ return CollectionUtil.isAnyNonNull(question, answer, tags);
+ }
+
+ public void setQuestion(Question question) {
+ this.question = question;
+ }
+
+ public Optional getQuestion() {
+ return Optional.ofNullable(question);
+ }
+
+ public void setAnswer(Answer answer) {
+ this.answer = answer;
+ }
+
+ public Optional getAnswer() {
+ return Optional.ofNullable(answer);
+ }
+
+ /**
+ * Sets {@code tags} to this object's {@code tags}.
+ * A defensive copy of {@code tags} is used internally.
+ */
+ public void setTags(Set tags) {
+ this.tags = (tags != null) ? new HashSet<>(tags) : null;
+ }
+
+ /**
+ * Returns an unmodifiable tag set, which throws {@code UnsupportedOperationException}
+ * if modification is attempted.
+ * Returns {@code Optional#empty()} if {@code tags} is null.
+ */
+ public Optional> getTags() {
+ return (tags != null) ? Optional.of(Collections.unmodifiableSet(tags)) : Optional.empty();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof EditQAndADescriptor)) {
+ return false;
+ }
+
+ // state check
+ EditQAndADescriptor e = (EditQAndADescriptor) other;
+
+ return getQuestion().equals(e.getQuestion())
+ && getAnswer().equals(e.getAnswer())
+ && getTags().equals(e.getTags());
+ }
+ }
+}
diff --git a/src/main/java/seedu/medmoriser/logic/commands/EndQuizCommand.java b/src/main/java/seedu/medmoriser/logic/commands/EndQuizCommand.java
new file mode 100644
index 00000000000..f3f5ca94492
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/commands/EndQuizCommand.java
@@ -0,0 +1,35 @@
+package seedu.medmoriser.logic.commands;
+
+import static seedu.medmoriser.model.Model.PREDICATE_SHOW_ALL_QANDA;
+
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Model;
+
+/**
+ * Ends an ongoing quiz
+ */
+public class EndQuizCommand extends Command {
+
+ public static final String COMMAND_WORD = "endquiz";
+
+ public static final String MESSAGE_ENDQUIZ_ACKNOWLEDGEMENT = "Ending ongoing quiz as requested ...";
+
+ public static final String MESSAGE_NO_ONGOING_QUIZ = "There is no ongoing quiz.";
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ if (!QuizCommand.getIsQuiz()) {
+ throw new CommandException(MESSAGE_NO_ONGOING_QUIZ);
+ } else {
+ QuizCommand.setIsQuiz(false, model);
+ AnswerCommand.setBeenAnswered(false, model);
+ model.updateFilteredQAndAList(PREDICATE_SHOW_ALL_QANDA);
+ for (int i = 0; i < model.getFilteredQAndAList().size(); i++) {
+ model.getFilteredQAndAList().get(i).setNotQuiz();
+ }
+ return new CommandResult(MESSAGE_ENDQUIZ_ACKNOWLEDGEMENT);
+ }
+ }
+
+
+}
diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/seedu/medmoriser/logic/commands/ExitCommand.java
similarity index 83%
rename from src/main/java/seedu/address/logic/commands/ExitCommand.java
rename to src/main/java/seedu/medmoriser/logic/commands/ExitCommand.java
index 3dd85a8ba90..f7eaea50dd6 100644
--- a/src/main/java/seedu/address/logic/commands/ExitCommand.java
+++ b/src/main/java/seedu/medmoriser/logic/commands/ExitCommand.java
@@ -1,6 +1,6 @@
-package seedu.address.logic.commands;
+package seedu.medmoriser.logic.commands;
-import seedu.address.model.Model;
+import seedu.medmoriser.model.Model;
/**
* Terminates the program.
diff --git a/src/main/java/seedu/medmoriser/logic/commands/FindCommand.java b/src/main/java/seedu/medmoriser/logic/commands/FindCommand.java
new file mode 100644
index 00000000000..df03eafe94e
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/commands/FindCommand.java
@@ -0,0 +1,78 @@
+package seedu.medmoriser.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_ANSWER;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_QUESTION;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_TAG;
+
+import java.util.function.Predicate;
+
+import seedu.medmoriser.commons.core.Messages;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.qanda.AnswerContainsKeywordsPredicate;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.qanda.QAndAContainsKeywordsPredicate;
+import seedu.medmoriser.model.qanda.QuestionContainsKeywordsPredicate;
+import seedu.medmoriser.model.qanda.TagContainsKeywordsPredicate;
+
+/**
+ * Finds and lists all qAndAs in address book whose name contains any of the argument keywords.
+ * Keyword matching is case insensitive.
+ */
+public class FindCommand extends Command {
+
+ public static final String COMMAND_WORD = "find";
+
+ public static final String MESSAGE_ONE_PREFIX = "There are multiple prefixes present.\n"
+ + "Please ensure that q/ is before the question keyword or a/ is before the answer keyword "
+ + "or t/ is before the tag keyword";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all QAndAs whose names contain any of "
+ + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n"
+ + "Parameters (each keyword/phrase separated by a comma): "
+ + PREFIX_QUESTION + "KEYWORD [MORE_KEYWORDS]... OR "
+ + PREFIX_ANSWER + "KEYWORD [MORE_KEYWORDS]... OR "
+ + PREFIX_TAG + "KEYWORD [MORE_KEYWORDS]... OR "
+ + "KEYWORD [MORE_KEYWORDS]... \n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_TAG + "Human Anatomy";
+
+ private final Predicate predicate;
+
+ public FindCommand(QuestionContainsKeywordsPredicate predicate) {
+ this.predicate = predicate;
+ }
+
+ public FindCommand(AnswerContainsKeywordsPredicate predicate) {
+ this.predicate = predicate;
+ }
+
+ public FindCommand(TagContainsKeywordsPredicate predicate) {
+ this.predicate = predicate;
+ }
+
+ public FindCommand(QAndAContainsKeywordsPredicate predicate) {
+ this.predicate = predicate;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ if (QuizCommand.getIsQuiz()) {
+ throw new CommandException(Messages.MESSAGE_ONGOING_QUIZ);
+ } else {
+ model.updateFilteredQAndAList(predicate);
+ return new CommandResult(
+ String.format(Messages.MESSAGE_QANDA_LISTED_OVERVIEW,
+ model.getFilteredQAndAList().size()), true);
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof FindCommand // instanceof handles nulls
+ && predicate.equals(((FindCommand) other).predicate)); // state check
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/seedu/medmoriser/logic/commands/HelpCommand.java
similarity index 55%
rename from src/main/java/seedu/address/logic/commands/HelpCommand.java
rename to src/main/java/seedu/medmoriser/logic/commands/HelpCommand.java
index bf824f91bd0..49336b96baa 100644
--- a/src/main/java/seedu/address/logic/commands/HelpCommand.java
+++ b/src/main/java/seedu/medmoriser/logic/commands/HelpCommand.java
@@ -1,6 +1,8 @@
-package seedu.address.logic.commands;
+package seedu.medmoriser.logic.commands;
-import seedu.address.model.Model;
+import seedu.medmoriser.commons.core.Messages;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Model;
/**
* Format full help instructions for every command for display.
@@ -15,7 +17,11 @@ public class HelpCommand extends Command {
public static final String SHOWING_HELP_MESSAGE = "Opened help window.";
@Override
- public CommandResult execute(Model model) {
+ public CommandResult execute(Model model) throws CommandException {
+
+ if (QuizCommand.getIsQuiz()) {
+ throw new CommandException(Messages.MESSAGE_ONGOING_QUIZ);
+ }
return new CommandResult(SHOWING_HELP_MESSAGE, true, false);
}
}
diff --git a/src/main/java/seedu/medmoriser/logic/commands/ListCommand.java b/src/main/java/seedu/medmoriser/logic/commands/ListCommand.java
new file mode 100644
index 00000000000..467a4ba1fad
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/commands/ListCommand.java
@@ -0,0 +1,59 @@
+package seedu.medmoriser.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medmoriser.model.Model.PREDICATE_SHOW_ALL_QANDA;
+
+import seedu.medmoriser.commons.core.Messages;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Model;
+
+/**
+ * Lists all QAndAs in Medmoriser to the user.
+ */
+public class ListCommand extends Command {
+
+ public static final String COMMAND_WORD = "list";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Lists all Questions (and Answers) "
+ + "depending on the optional parameter passed.\n"
+ + "Parameters: [questions]\n"
+ + "Example: " + COMMAND_WORD + " questions";
+
+ public static final String MESSAGE_LIST_ALL_SUCCESS = "Listed all QAndAs";
+
+ public static final String MESSAGE_LIST_QUESTIONS_SUCCESS = "Listed all Questions";
+
+ private final boolean isAnswerDisplayed;
+
+ /**
+ * Lists all QAndAs.
+ * @param isAnswerDisplayed whether answers should be displayed
+ */
+ public ListCommand(boolean isAnswerDisplayed) {
+ super();
+ this.isAnswerDisplayed = isAnswerDisplayed;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ if (QuizCommand.getIsQuiz()) {
+ throw new CommandException(Messages.MESSAGE_ONGOING_QUIZ);
+ } else {
+ model.updateFilteredQAndAList(PREDICATE_SHOW_ALL_QANDA);
+ if (isAnswerDisplayed) {
+ return new CommandResult(MESSAGE_LIST_ALL_SUCCESS, true);
+ } else {
+ return new CommandResult(MESSAGE_LIST_QUESTIONS_SUCCESS, false);
+ }
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof ListCommand // instanceof handles nulls
+ && isAnswerDisplayed == (((ListCommand) other).isAnswerDisplayed)); // state check
+ }
+}
diff --git a/src/main/java/seedu/medmoriser/logic/commands/NextCommand.java b/src/main/java/seedu/medmoriser/logic/commands/NextCommand.java
new file mode 100644
index 00000000000..d4517723ecf
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/commands/NextCommand.java
@@ -0,0 +1,40 @@
+package seedu.medmoriser.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.qanda.QAndA;
+
+public class NextCommand extends Command {
+
+ public static final String COMMAND_WORD = "next";
+
+ public static final String MESSAGE_SUCCESS = "Here's the next question!";
+
+ public static final String MESSAGE_NO_MORE_QUESTIONS =
+ "There are no more question with this keyword! Enter `endquiz` to end the quiz.";
+
+ public static final String MESSAGE_NOT_QUIZ = "There is no ongoing quiz.";
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ if (QuizCommand.getIsQuiz()) {
+ if (QuizCommand.getCurrentList().size() > 0) {
+ AnswerCommand.setBeenAnswered(false, model);
+ QAndA qAndA = QuizCommand.getRandomQuestion(QuizCommand.getCurrentList());
+ model.updateFilteredQAndAList(x -> x.equals(qAndA));
+ QuizCommand.setIsQuiz(true, model);
+ QuizCommand.getCurrentList().remove(qAndA);
+ return new CommandResult(MESSAGE_SUCCESS);
+ } else {
+ throw new CommandException(MESSAGE_NO_MORE_QUESTIONS);
+ }
+ } else {
+ throw new CommandException(MESSAGE_NOT_QUIZ);
+ }
+
+ }
+}
diff --git a/src/main/java/seedu/medmoriser/logic/commands/QuizCommand.java b/src/main/java/seedu/medmoriser/logic/commands/QuizCommand.java
new file mode 100644
index 00000000000..36d213ab188
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/commands/QuizCommand.java
@@ -0,0 +1,114 @@
+package seedu.medmoriser.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_QUESTION;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_TAG;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.function.Predicate;
+
+import javafx.collections.ObservableList;
+import seedu.medmoriser.commons.core.Messages;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.qanda.QuestionContainsKeywordsPredicate;
+import seedu.medmoriser.model.qanda.TagContainsKeywordsPredicate;
+
+/**
+ * Starts a new Quiz for the user.
+ */
+public class QuizCommand extends Command {
+
+ public static final String COMMAND_WORD = "quiz";
+
+ public static final String MESSAGE_SUCCESS = "Quiz time! Here's a question...";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Quizzes the user on a question based on the keywords"
+ + " provided by the user. Quiz by tag or keyword in question. \n"
+ + "Parameters: "
+ + PREFIX_QUESTION + "QUESTION_KEYWORD [MORE_KEYWORDS]... " + "OR "
+ + PREFIX_TAG + "TAG [MORE_TAGS]... \n"
+ + "Example: " + COMMAND_WORD + " t/Human Anatomy, Nervous System";
+
+ public static final String MESSAGE_NO_QUESTION_WITH_KEYWORD = "No question with this tag/keyword";
+
+ public static final String MESSAGE_ONE_PREFIX = "There are multiple prefixes present. Ensure that q/ is before the"
+ + "question keyword or t/ is before the tag keyword";
+
+ private static boolean isQuiz = false;
+
+ private static List currentList = new ArrayList<>();
+
+ private final Predicate predicate;
+
+ public QuizCommand(TagContainsKeywordsPredicate predicate) {
+ this.predicate = predicate;
+ }
+
+ public QuizCommand(QuestionContainsKeywordsPredicate predicate) {
+ this.predicate = predicate;
+ }
+
+ public static QAndA getRandomQuestion(List list) {
+ Random rand = new Random();
+ return list.get(rand.nextInt(list.size()));
+ }
+
+ public static boolean getIsQuiz() {
+ return isQuiz;
+ }
+
+ public static void setIsQuiz(boolean ongoingQuiz, Model model) {
+ isQuiz = ongoingQuiz;
+ if (!isQuiz) {
+ for (int i = 0; i < model.getFilteredQAndAList().size(); i++) {
+ model.getFilteredQAndAList().get(i).setNotQuiz();
+ }
+ } else {
+ model.getFilteredQAndAList().get(0).setAsQuiz();
+ }
+ }
+
+ public static List getCurrentList() {
+ return currentList;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ if (getIsQuiz()) {
+ throw new CommandException(Messages.MESSAGE_ONGOING_QUIZ);
+ } else {
+ model.updateFilteredQAndAList(predicate);
+ ObservableList filteredList = model.getFilteredQAndAList();
+
+ for (QAndA q : filteredList) {
+ currentList.add(q);
+ }
+
+ if (filteredList.size() > 0) {
+ QAndA question = getRandomQuestion(currentList);
+
+ currentList.remove(question);
+
+ model.updateFilteredQAndAList(x -> x.equals(question));
+ setIsQuiz(true, model);
+
+ return new CommandResult(MESSAGE_SUCCESS);
+ } else {
+ throw new CommandException(MESSAGE_NO_QUESTION_WITH_KEYWORD);
+ }
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof QuizCommand // instanceof handles nulls
+ && predicate.equals(((QuizCommand) other).predicate)) // state check
+ && (isQuiz == ((QuizCommand) other).isQuiz);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java b/src/main/java/seedu/medmoriser/logic/commands/exceptions/CommandException.java
similarity index 89%
rename from src/main/java/seedu/address/logic/commands/exceptions/CommandException.java
rename to src/main/java/seedu/medmoriser/logic/commands/exceptions/CommandException.java
index a16bd14f2cd..bb82aa63848 100644
--- a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java
+++ b/src/main/java/seedu/medmoriser/logic/commands/exceptions/CommandException.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.commands.exceptions;
+package seedu.medmoriser.logic.commands.exceptions;
/**
* Represents an error which occurs during execution of a {@link Command}.
diff --git a/src/main/java/seedu/medmoriser/logic/parser/AddCommandParser.java b/src/main/java/seedu/medmoriser/logic/parser/AddCommandParser.java
new file mode 100644
index 00000000000..eaac5d3cbff
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/parser/AddCommandParser.java
@@ -0,0 +1,70 @@
+package seedu.medmoriser.logic.parser;
+
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_ANSWER;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_QUESTION;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_TAG;
+
+import java.util.Set;
+import java.util.stream.Stream;
+
+import seedu.medmoriser.logic.commands.AddCommand;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.model.qanda.Answer;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.qanda.Question;
+import seedu.medmoriser.model.tag.Tag;
+
+/**
+ * Parses input arguments and creates a new AddCommand object
+ */
+public class AddCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the AddCommand
+ * and returns an AddCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public AddCommand parse(String args) throws ParseException {
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_QUESTION,
+ PREFIX_ANSWER, PREFIX_TAG);
+
+ if (!arePrefixesPresent(argMultimap, PREFIX_QUESTION, PREFIX_ANSWER)
+ || !argMultimap.getPreamble().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
+ }
+
+ if (!containsOnce(args, PREFIX_ANSWER) || !containsOnce(args, PREFIX_QUESTION)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_ONE_PREFIX));
+ }
+
+ Question question = ParserUtil.parseQuestion(argMultimap.getValue(PREFIX_QUESTION).get());
+ Answer answer = ParserUtil.parseAnswer(argMultimap.getValue(PREFIX_ANSWER).get());
+ Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG));
+ QAndA qAndA;
+
+ qAndA = new QAndA(question, answer, tagList);
+ return new AddCommand(qAndA);
+ }
+
+ /**
+ * Returns true if none of the prefixes contains empty {@code Optional} values in the given
+ * {@code ArgumentMultimap}.
+ */
+ private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
+ }
+
+ /**
+ * Returns true if prefix only appears once in the string
+ * @param s The string to compare with.
+ * @param prefix The prefix to compare with.
+ * @return a boolean to indicate if prefix only appears in s once.
+ */
+ private boolean containsOnce(String s, Prefix prefix) {
+ String prefixString = prefix.toString();
+ int i = s.indexOf(prefixString);
+ return i == s.lastIndexOf(prefixString) && i != -1;
+ }
+
+}
diff --git a/src/main/java/seedu/medmoriser/logic/parser/AnswerCommandParser.java b/src/main/java/seedu/medmoriser/logic/parser/AnswerCommandParser.java
new file mode 100644
index 00000000000..b0bf328fb8f
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/parser/AnswerCommandParser.java
@@ -0,0 +1,25 @@
+package seedu.medmoriser.logic.parser;
+
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.medmoriser.logic.commands.AnswerCommand;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new AnswerCommand object
+ */
+public class AnswerCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the AnswerCommand
+ * and returns an AnswerCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public AnswerCommand parse(String args) throws ParseException {
+ if (args.equals("")) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, AnswerCommand.MESSAGE_USAGE));
+ }
+ return new AnswerCommand(args);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java b/src/main/java/seedu/medmoriser/logic/parser/ArgumentMultimap.java
similarity index 98%
rename from src/main/java/seedu/address/logic/parser/ArgumentMultimap.java
rename to src/main/java/seedu/medmoriser/logic/parser/ArgumentMultimap.java
index 954c8e18f8e..c9271e67789 100644
--- a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java
+++ b/src/main/java/seedu/medmoriser/logic/parser/ArgumentMultimap.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.medmoriser.logic.parser;
import java.util.ArrayList;
import java.util.HashMap;
diff --git a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java b/src/main/java/seedu/medmoriser/logic/parser/ArgumentTokenizer.java
similarity index 99%
rename from src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java
rename to src/main/java/seedu/medmoriser/logic/parser/ArgumentTokenizer.java
index 5c9aebfa488..f61753e96b9 100644
--- a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java
+++ b/src/main/java/seedu/medmoriser/logic/parser/ArgumentTokenizer.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.medmoriser.logic.parser;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/src/main/java/seedu/medmoriser/logic/parser/CliSyntax.java b/src/main/java/seedu/medmoriser/logic/parser/CliSyntax.java
new file mode 100644
index 00000000000..4e70808398d
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/parser/CliSyntax.java
@@ -0,0 +1,13 @@
+package seedu.medmoriser.logic.parser;
+
+/**
+ * Contains Command Line Interface (CLI) syntax definitions common to multiple commands
+ */
+public class CliSyntax {
+
+ /* Prefix definitions */
+ public static final Prefix PREFIX_QUESTION = new Prefix("q/");
+ public static final Prefix PREFIX_ANSWER = new Prefix("a/");
+ public static final Prefix PREFIX_TAG = new Prefix("t/");
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java b/src/main/java/seedu/medmoriser/logic/parser/DeleteCommandParser.java
similarity index 57%
rename from src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
rename to src/main/java/seedu/medmoriser/logic/parser/DeleteCommandParser.java
index 522b93081cc..6349194bf2e 100644
--- a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
+++ b/src/main/java/seedu/medmoriser/logic/parser/DeleteCommandParser.java
@@ -1,10 +1,11 @@
-package seedu.address.logic.parser;
+package seedu.medmoriser.logic.parser;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_QANDA_DISPLAYED_INDEX;
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.DeleteCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.commons.core.index.Index;
+import seedu.medmoriser.logic.commands.DeleteCommand;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
/**
* Parses input arguments and creates a new DeleteCommand object
@@ -21,6 +22,9 @@ public DeleteCommand parse(String args) throws ParseException {
Index index = ParserUtil.parseIndex(args);
return new DeleteCommand(index);
} catch (ParseException pe) {
+ if (pe.getMessage().equals(MESSAGE_INVALID_QANDA_DISPLAYED_INDEX)) {
+ throw new ParseException(MESSAGE_INVALID_QANDA_DISPLAYED_INDEX);
+ }
throw new ParseException(
String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE), pe);
}
diff --git a/src/main/java/seedu/medmoriser/logic/parser/EditCommandParser.java b/src/main/java/seedu/medmoriser/logic/parser/EditCommandParser.java
new file mode 100644
index 00000000000..b2d1a36951b
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/parser/EditCommandParser.java
@@ -0,0 +1,92 @@
+package seedu.medmoriser.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_ANSWER;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_QUESTION;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_TAG;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.Set;
+
+import seedu.medmoriser.commons.core.index.Index;
+import seedu.medmoriser.logic.commands.EditCommand;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.model.tag.Tag;
+
+/**
+ * Parses input arguments and creates a new EditCommand object
+ */
+public class EditCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the EditCommand
+ * and returns an EditCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public EditCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_QUESTION, PREFIX_ANSWER, PREFIX_TAG);
+
+ Index index;
+
+ if (!containsMaximumOnce(args, PREFIX_QUESTION)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_ONE_PREFIX));
+ }
+ if (!containsMaximumOnce(args, PREFIX_ANSWER)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_ONE_PREFIX));
+ }
+ try {
+ index = ParserUtil.parseIndex(argMultimap.getPreamble());
+ } catch (ParseException pe) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE), pe);
+ }
+
+ EditCommand.EditQAndADescriptor editQAndADescriptor = new EditCommand.EditQAndADescriptor();
+ if (argMultimap.getValue(PREFIX_QUESTION).isPresent()) {
+ editQAndADescriptor.setQuestion(ParserUtil.parseQuestion(argMultimap
+ .getValue(PREFIX_QUESTION).get()));
+ }
+ if (argMultimap.getValue(PREFIX_ANSWER).isPresent()) {
+ editQAndADescriptor.setAnswer(ParserUtil.parseAnswer(argMultimap.getValue(PREFIX_ANSWER).get()));
+ }
+ parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editQAndADescriptor::setTags);
+
+ if (!editQAndADescriptor.isAnyFieldEdited()) {
+ throw new ParseException(EditCommand.MESSAGE_NOT_EDITED);
+ }
+
+ return new EditCommand(index, editQAndADescriptor);
+ }
+
+ /**
+ * Parses {@code Collection tags} into a {@code Set} if {@code tags} is non-empty.
+ * If {@code tags} contain only one element which is an empty string, it will be parsed into a
+ * {@code Set} containing zero tags.
+ */
+ private Optional> parseTagsForEdit(Collection tags) throws ParseException {
+ assert tags != null;
+
+ if (tags.isEmpty()) {
+ return Optional.empty();
+ }
+ Collection tagSet = tags.size() == 1 && tags.contains("") ? Collections.emptySet() : tags;
+ return Optional.of(ParserUtil.parseTags(tagSet));
+ }
+
+ /**
+ * Returns true if prefix only appears once in the string
+ * @param s The string to compare with.
+ * @param prefix The prefix to compare with.
+ * @return a boolean to indicate if prefix only appears in s once.
+ */
+ private boolean containsMaximumOnce(String s, Prefix prefix) {
+ String prefixString = prefix.toString();
+ int i = s.indexOf(prefixString);
+ return i == s.lastIndexOf(prefixString);
+ }
+
+}
diff --git a/src/main/java/seedu/medmoriser/logic/parser/FindCommandParser.java b/src/main/java/seedu/medmoriser/logic/parser/FindCommandParser.java
new file mode 100644
index 00000000000..eb88240e702
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/parser/FindCommandParser.java
@@ -0,0 +1,100 @@
+package seedu.medmoriser.logic.parser;
+
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_ANSWER;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_QUESTION;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_TAG;
+
+import java.util.Arrays;
+
+import seedu.medmoriser.logic.commands.FindCommand;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.model.qanda.AnswerContainsKeywordsPredicate;
+import seedu.medmoriser.model.qanda.QAndAContainsKeywordsPredicate;
+import seedu.medmoriser.model.qanda.QuestionContainsKeywordsPredicate;
+import seedu.medmoriser.model.qanda.TagContainsKeywordsPredicate;
+
+/**
+ * Parses input arguments and creates a new FindCommand object
+ */
+public class FindCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the FindCommand
+ * and returns a FindCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public FindCommand parse(String args) throws ParseException {
+ assert args != null;
+ String trimmedArgs = args.trim();
+ if (trimmedArgs.isEmpty()) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
+ }
+
+ if (args.contains("q/") && args.contains("t/") && args.contains("a/")
+ || args.contains("q/") && args.contains("a/") || args.contains("q/") && args.contains("t/")
+ || args.contains("t/") && args.contains("a/")) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
+ }
+
+ if (!containsMaximumOnce(args, PREFIX_QUESTION)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_ONE_PREFIX));
+ }
+
+ if (!containsMaximumOnce(args, PREFIX_ANSWER)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_ONE_PREFIX));
+ }
+
+ if (!containsMaximumOnce(args, PREFIX_TAG)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_ONE_PREFIX));
+ }
+
+ String[] keywordsArray = trimmedArgs.split("/|, ");
+ String[] excludeType = keywordsArray;
+
+ //trim whitespaces
+ keywordsArray = trimArg(keywordsArray);
+
+ String findType = keywordsArray[0];
+ if (keywordsArray.length > 1) {
+ excludeType = Arrays.copyOfRange(keywordsArray, 1, keywordsArray.length);
+ }
+
+ if (!args.contains("q/") && !args.contains("a/") && !args.contains("t/")) {
+ return new FindCommand(new QAndAContainsKeywordsPredicate(Arrays.asList(keywordsArray)));
+ }
+
+ switch (findType) {
+ case "t":
+ return new FindCommand(new TagContainsKeywordsPredicate(Arrays.asList(excludeType)));
+ case "q":
+ return new FindCommand(new QuestionContainsKeywordsPredicate(Arrays.asList(excludeType)));
+ case "a":
+ return new FindCommand(new AnswerContainsKeywordsPredicate(Arrays.asList(excludeType)));
+ default:
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
+ }
+ }
+
+ private String[] trimArg(String[] args) {
+ String[] toReturn = new String[args.length];
+ for (int i = 0; i < args.length; i++) {
+ toReturn[i] = args[i].trim();
+ }
+ return toReturn;
+ }
+
+ /**
+ * Returns true if prefix only appears once in the string
+ * @param s The string to compare with.
+ * @param prefix The prefix to compare with.
+ * @return a boolean to indicate if prefix only appears in s once.
+ */
+ private boolean containsMaximumOnce(String s, Prefix prefix) {
+ String prefixString = prefix.toString();
+ int i = s.indexOf(prefixString);
+ return i == s.lastIndexOf(prefixString);
+ }
+}
diff --git a/src/main/java/seedu/medmoriser/logic/parser/ListCommandParser.java b/src/main/java/seedu/medmoriser/logic/parser/ListCommandParser.java
new file mode 100644
index 00000000000..8c9327865a8
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/parser/ListCommandParser.java
@@ -0,0 +1,41 @@
+package seedu.medmoriser.logic.parser;
+
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.medmoriser.logic.commands.ListCommand;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new ListCommand object
+ */
+public class ListCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the ListCommand
+ * and returns a ListCommand object for execution.
+ * @throws ParseException if the user input does not conform to the expected format
+ */
+ public ListCommand parse(String args) throws ParseException {
+ String trimmedArgs = args.trim();
+
+ String[] argArr = trimmedArgs.split("\\s+");
+ if (argArr.length > 1) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListCommand.MESSAGE_USAGE));
+ }
+
+ String listParam = argArr[0];
+ boolean isAnsDisplayed = true;
+ if (listParam.isEmpty()) {
+ isAnsDisplayed = true;
+ } else if (listParam.equals("questions")) {
+ isAnsDisplayed = false;
+ } else {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListCommand.MESSAGE_USAGE));
+ }
+
+ return new ListCommand(isAnsDisplayed);
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/medmoriser/logic/parser/MedmoriserParser.java
similarity index 56%
rename from src/main/java/seedu/address/logic/parser/AddressBookParser.java
rename to src/main/java/seedu/medmoriser/logic/parser/MedmoriserParser.java
index 1e466792b46..f9462679011 100644
--- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java
+++ b/src/main/java/seedu/medmoriser/logic/parser/MedmoriserParser.java
@@ -1,26 +1,30 @@
-package seedu.address.logic.parser;
+package seedu.medmoriser.logic.parser;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.commands.ClearCommand;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.commands.DeleteCommand;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.ExitCommand;
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.logic.commands.HelpCommand;
-import seedu.address.logic.commands.ListCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.logic.commands.AddCommand;
+import seedu.medmoriser.logic.commands.AnswerCommand;
+import seedu.medmoriser.logic.commands.ClearCommand;
+import seedu.medmoriser.logic.commands.Command;
+import seedu.medmoriser.logic.commands.DeleteCommand;
+import seedu.medmoriser.logic.commands.EditCommand;
+import seedu.medmoriser.logic.commands.EndQuizCommand;
+import seedu.medmoriser.logic.commands.ExitCommand;
+import seedu.medmoriser.logic.commands.FindCommand;
+import seedu.medmoriser.logic.commands.HelpCommand;
+import seedu.medmoriser.logic.commands.ListCommand;
+import seedu.medmoriser.logic.commands.NextCommand;
+import seedu.medmoriser.logic.commands.QuizCommand;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
/**
* Parses user input.
*/
-public class AddressBookParser {
+public class MedmoriserParser {
/**
* Used for initial separation of command word and args.
@@ -59,8 +63,20 @@ public Command parseCommand(String userInput) throws ParseException {
case FindCommand.COMMAND_WORD:
return new FindCommandParser().parse(arguments);
+ case QuizCommand.COMMAND_WORD:
+ return new QuizCommandParser().parse(arguments);
+
+ case AnswerCommand.COMMAND_WORD:
+ return new AnswerCommandParser().parse(arguments);
+
+ case EndQuizCommand.COMMAND_WORD:
+ return new EndQuizCommand();
+
+ case NextCommand.COMMAND_WORD:
+ return new NextCommand();
+
case ListCommand.COMMAND_WORD:
- return new ListCommand();
+ return new ListCommandParser().parse(arguments);
case ExitCommand.COMMAND_WORD:
return new ExitCommand();
diff --git a/src/main/java/seedu/address/logic/parser/Parser.java b/src/main/java/seedu/medmoriser/logic/parser/Parser.java
similarity index 71%
rename from src/main/java/seedu/address/logic/parser/Parser.java
rename to src/main/java/seedu/medmoriser/logic/parser/Parser.java
index d6551ad8e3f..434588f824a 100644
--- a/src/main/java/seedu/address/logic/parser/Parser.java
+++ b/src/main/java/seedu/medmoriser/logic/parser/Parser.java
@@ -1,7 +1,7 @@
-package seedu.address.logic.parser;
+package seedu.medmoriser.logic.parser;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.logic.commands.Command;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
/**
* Represents a Parser that is able to parse user input into a {@code Command} of type {@code T}.
diff --git a/src/main/java/seedu/medmoriser/logic/parser/ParserUtil.java b/src/main/java/seedu/medmoriser/logic/parser/ParserUtil.java
new file mode 100644
index 00000000000..d9f9b25d80c
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/parser/ParserUtil.java
@@ -0,0 +1,97 @@
+package seedu.medmoriser.logic.parser;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import seedu.medmoriser.commons.core.index.Index;
+import seedu.medmoriser.commons.util.StringUtil;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.model.qanda.Answer;
+import seedu.medmoriser.model.qanda.Question;
+import seedu.medmoriser.model.tag.Tag;
+
+/**
+ * Contains utility methods used for parsing strings in the various *Parser classes.
+ */
+public class ParserUtil {
+
+ public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer.";
+ public static final String MESSAGE_INVALID_QANDA_DISPLAYED_INDEX = "The qAndA index "
+ + "provided is invalid";
+
+ /**
+ * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be
+ * trimmed.
+ * @throws ParseException if the specified index is invalid (not non-zero unsigned integer).
+ */
+ public static Index parseIndex(String oneBasedIndex) throws ParseException {
+ String trimmedIndex = oneBasedIndex.trim();
+ if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) {
+ if (!trimmedIndex.matches("[a-zA-Z]+")) {
+ throw new ParseException(MESSAGE_INVALID_QANDA_DISPLAYED_INDEX);
+ }
+ throw new ParseException(MESSAGE_INVALID_INDEX);
+ }
+ return Index.fromOneBased(Integer.parseInt(trimmedIndex));
+ }
+
+ /**
+ * Parses a {@code String question} into a {@code Question}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code question} is invalid.
+ */
+ public static Question parseQuestion(String question) throws ParseException {
+ requireNonNull(question);
+ String trimmedName = question.trim();
+ if (!Question.isValidQuestion(trimmedName)) {
+ throw new ParseException(Question.MESSAGE_CONSTRAINTS);
+ }
+ return new Question(trimmedName);
+ }
+
+ /**
+ * Parses a {@code String answer} into an {@code answer}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code answer} is invalid.
+ */
+ public static Answer parseAnswer(String answer) throws ParseException {
+ requireNonNull(answer);
+ String trimmedAnswer = answer.trim();
+ if (!Answer.isValidAnswer(trimmedAnswer)) {
+ throw new ParseException(Answer.MESSAGE_CONSTRAINTS);
+ }
+ return new Answer(trimmedAnswer);
+ }
+
+ /**
+ * Parses a {@code String tag} into a {@code Tag}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code tag} is invalid.
+ */
+ public static Tag parseTag(String tag) throws ParseException {
+ requireNonNull(tag);
+ String trimmedTag = tag.trim();
+ if (!Tag.isValidTagName(trimmedTag)) {
+ throw new ParseException(Tag.MESSAGE_CONSTRAINTS);
+ }
+ return new Tag(trimmedTag);
+ }
+
+ /**
+ * Parses {@code Collection tags} into a {@code Set}.
+ */
+ public static Set parseTags(Collection tags) throws ParseException {
+ requireNonNull(tags);
+ final Set tagSet = new HashSet<>();
+ for (String tagName : tags) {
+ tagSet.add(parseTag(tagName));
+ }
+ return tagSet;
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/Prefix.java b/src/main/java/seedu/medmoriser/logic/parser/Prefix.java
similarity index 95%
rename from src/main/java/seedu/address/logic/parser/Prefix.java
rename to src/main/java/seedu/medmoriser/logic/parser/Prefix.java
index c859d5fa5db..6687664322b 100644
--- a/src/main/java/seedu/address/logic/parser/Prefix.java
+++ b/src/main/java/seedu/medmoriser/logic/parser/Prefix.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.medmoriser.logic.parser;
/**
* A prefix that marks the beginning of an argument in an arguments string.
diff --git a/src/main/java/seedu/medmoriser/logic/parser/QuizCommandParser.java b/src/main/java/seedu/medmoriser/logic/parser/QuizCommandParser.java
new file mode 100644
index 00000000000..c839fbb895c
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/logic/parser/QuizCommandParser.java
@@ -0,0 +1,94 @@
+package seedu.medmoriser.logic.parser;
+
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_QUESTION;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_TAG;
+
+import java.util.Arrays;
+
+import seedu.medmoriser.logic.commands.QuizCommand;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.model.qanda.QuestionContainsKeywordsPredicate;
+import seedu.medmoriser.model.qanda.TagContainsKeywordsPredicate;
+
+/**
+ * Parses input arguments and creates a new QuizCommand object
+ */
+public class QuizCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the QuizCommand
+ * and returns a QuizCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public QuizCommand parse(String args) throws ParseException {
+ assert args != null;
+ String trimmedArgs = args.trim();
+ if (trimmedArgs.isEmpty()) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, QuizCommand.MESSAGE_USAGE));
+ }
+
+ if (args.contains("q/") && args.contains("t/") && args.contains("a/")
+ || args.contains("q/") && args.contains("a/") || args.contains("q/") && args.contains("t/")
+ || args.contains("t/") && args.contains("a/")) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, QuizCommand.MESSAGE_USAGE));
+ }
+
+ if (!args.contains("q/")) {
+ if (!args.contains("t/")) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, QuizCommand.MESSAGE_USAGE));
+ }
+ }
+
+ if (!containsMaximumOnce(args, PREFIX_QUESTION)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, QuizCommand.MESSAGE_ONE_PREFIX));
+ }
+ if (!containsMaximumOnce(args, PREFIX_TAG)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, QuizCommand.MESSAGE_ONE_PREFIX));
+ }
+
+ String[] keywordsArray = trimmedArgs.split("/|, ");
+ String[] excludeType = keywordsArray;
+
+ //trim whitespaces
+ keywordsArray = trimArg(keywordsArray);
+
+ String findType = keywordsArray[0];
+ if (keywordsArray.length > 1) {
+ excludeType = Arrays.copyOfRange(keywordsArray, 1, keywordsArray.length);
+ }
+
+ switch (findType) {
+ case "t":
+ return new QuizCommand(new TagContainsKeywordsPredicate(Arrays.asList(excludeType)));
+ case "q":
+ return new QuizCommand(new QuestionContainsKeywordsPredicate(Arrays.asList(excludeType)));
+ default:
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, QuizCommand.MESSAGE_USAGE));
+ }
+ }
+
+ private String[] trimArg(String[] args) {
+ String[] toReturn = new String[args.length];
+ for (int i = 0; i < args.length; i++) {
+ toReturn[i] = args[i].trim();
+ }
+ return toReturn;
+ }
+
+ /**
+ * Returns true if prefix only appears once in the string
+ * @param s The string to compare with.
+ * @param prefix The prefix to compare with.
+ * @return a boolean to indicate if prefix only appears in s once.
+ */
+ private boolean containsMaximumOnce(String s, Prefix prefix) {
+ String prefixString = prefix.toString();
+ int i = s.indexOf(prefixString);
+ return i == s.lastIndexOf(prefixString);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/exceptions/ParseException.java b/src/main/java/seedu/medmoriser/logic/parser/exceptions/ParseException.java
similarity index 72%
rename from src/main/java/seedu/address/logic/parser/exceptions/ParseException.java
rename to src/main/java/seedu/medmoriser/logic/parser/exceptions/ParseException.java
index 158a1a54c1c..ff691480f6d 100644
--- a/src/main/java/seedu/address/logic/parser/exceptions/ParseException.java
+++ b/src/main/java/seedu/medmoriser/logic/parser/exceptions/ParseException.java
@@ -1,6 +1,6 @@
-package seedu.address.logic.parser.exceptions;
+package seedu.medmoriser.logic.parser.exceptions;
-import seedu.address.commons.exceptions.IllegalValueException;
+import seedu.medmoriser.commons.exceptions.IllegalValueException;
/**
* Represents a parse error encountered by a parser.
diff --git a/src/main/java/seedu/medmoriser/model/Medmoriser.java b/src/main/java/seedu/medmoriser/model/Medmoriser.java
new file mode 100644
index 00000000000..891261bbe88
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/model/Medmoriser.java
@@ -0,0 +1,121 @@
+package seedu.medmoriser.model;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.List;
+
+import javafx.collections.ObservableList;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.qanda.UniqueQAndAList;
+
+/**
+ * Wraps all data at the medmoriser level
+ * Duplicates are not allowed (by .isSameQAndA comparison)
+ */
+public class Medmoriser implements ReadOnlyMedmoriser {
+
+ private final UniqueQAndAList qAndAs;
+
+ /*
+ * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication
+ * between constructors. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
+ *
+ * Note that non-static init blocks are not recommended to use. There are other ways to avoid duplication
+ * among constructors.
+ */
+ {
+ qAndAs = new UniqueQAndAList();
+ }
+
+ public Medmoriser() {}
+
+ /**
+ * Creates a Medmoriser using the QAndAs in the {@code toBeCopied}
+ */
+ public Medmoriser(ReadOnlyMedmoriser toBeCopied) {
+ this();
+ resetData(toBeCopied);
+ }
+
+ //// list overwrite operations
+
+ /**
+ * Replaces the contents of the qAndA list with {@code qAndAs}.
+ * {@code qAndAs} must not contain duplicate qAndAs.
+ */
+ public void setqAndAs(List qAndAs) {
+ this.qAndAs.setQAndAs(qAndAs);
+ }
+
+ /**
+ * Resets the existing data of this {@code Medmoriser} with {@code newData}.
+ */
+ public void resetData(ReadOnlyMedmoriser newData) {
+ requireNonNull(newData);
+
+ setqAndAs(newData.getQAndAList());
+ }
+
+ //// qAndA-level operations
+
+ /**
+ * Returns true if a qAndA with the same identity as {@code qAndA} exists in the medmoriser.
+ */
+ public boolean hasQAndA(QAndA qAndA) {
+ requireNonNull(qAndA);
+ return qAndAs.contains(qAndA);
+ }
+
+ /**
+ * Adds a qAndA to the medmoriser.
+ * The qAndA must not already exist in the medmoriser.
+ */
+ public void addQAndA(QAndA p) {
+ qAndAs.add(p);
+ }
+
+ /**
+ * Replaces the given qAndA {@code target} in the list with {@code editedQAndA}.
+ * {@code target} must exist in the medmoriser.
+ * The qAndA identity of {@code editedQAndA} must
+ * not be the same as another existing qAndA in the medmoriser.
+ */
+ public void setQAndA(QAndA target, QAndA editedQAndA) {
+ requireNonNull(editedQAndA);
+
+ qAndAs.setQAndA(target, editedQAndA);
+ }
+
+ /**
+ * Removes {@code key} from this {@code Medmoriser}.
+ * {@code key} must exist in the medmoriser.
+ */
+ public void removeQAndA(QAndA key) {
+ qAndAs.remove(key);
+ }
+
+ //// util methods
+
+ @Override
+ public String toString() {
+ return qAndAs.asUnmodifiableObservableList().size() + " qAndAs";
+ // TODO: refine later
+ }
+
+ @Override
+ public ObservableList getQAndAList() {
+ return qAndAs.asUnmodifiableObservableList();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Medmoriser // instanceof handles nulls
+ && qAndAs.equals(((Medmoriser) other).qAndAs));
+ }
+
+ @Override
+ public int hashCode() {
+ return qAndAs.hashCode();
+ }
+}
diff --git a/src/main/java/seedu/medmoriser/model/Model.java b/src/main/java/seedu/medmoriser/model/Model.java
new file mode 100644
index 00000000000..59953c15c90
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/model/Model.java
@@ -0,0 +1,88 @@
+package seedu.medmoriser.model;
+
+import java.nio.file.Path;
+import java.util.function.Predicate;
+
+import javafx.collections.ObservableList;
+import seedu.medmoriser.commons.core.GuiSettings;
+import seedu.medmoriser.model.qanda.QAndA;
+
+/**
+ * The API of the Model component.
+ */
+public interface Model {
+ /** {@code Predicate} that always evaluate to true */
+ Predicate PREDICATE_SHOW_ALL_QANDA = unused -> true;
+
+ /**
+ * Replaces user prefs data with the data in {@code userPrefs}.
+ */
+ void setUserPrefs(ReadOnlyUserPrefs userPrefs);
+
+ /**
+ * Returns the user prefs.
+ */
+ ReadOnlyUserPrefs getUserPrefs();
+
+ /**
+ * Returns the user prefs' GUI settings.
+ */
+ GuiSettings getGuiSettings();
+
+ /**
+ * Sets the user prefs' GUI settings.
+ */
+ void setGuiSettings(GuiSettings guiSettings);
+
+ /**
+ * Returns the user prefs' medmoriser file path.
+ */
+ Path getMedmoriserFilePath();
+
+ /**
+ * Sets the user prefs' medmoriser file path.
+ */
+ void setMedmoriserFilePath(Path medmoriserFilePath);
+
+ /**
+ * Replaces Medmoriser data with the data in {@code Medmoriser}.
+ */
+ void setMedmoriser(ReadOnlyMedmoriser medmoriser);
+
+ /** Returns the Medmoriser */
+ ReadOnlyMedmoriser getMedmoriser();
+
+ /**
+ * Returns true if a qAndA with the same identity as {@code qAndA} exists in the medmoriser.
+ */
+ boolean hasQAndA(QAndA qAndA);
+
+ /**
+ * Deletes the given qAndA.
+ * The qAndA must exist in the medmoriser.
+ */
+ void deleteQAndA(QAndA target);
+
+ /**
+ * Adds the given qAndA.
+ * {@code qAndA} must not already exist in the medmoriser.
+ */
+ void addQAndA(QAndA qAndA);
+
+ /**
+ * Replaces the given qAndA {@code target} with {@code editedQAndA}.
+ * {@code target} must exist in the medmoriser.
+ * The qAndA identity of {@code editedQAndA} must not be the same as another
+ * existing qAndA in the medmoriser.
+ */
+ void setQAndA(QAndA target, QAndA editedQAndA);
+
+ /** Returns an unmodifiable view of the filtered qAndA list */
+ ObservableList getFilteredQAndAList();
+
+ /**
+ * Updates the filter of the filtered qAndA list to filter by the given {@code predicate}.
+ * @throws NullPointerException if {@code predicate} is null.
+ */
+ void updateFilteredQAndAList(Predicate predicate);
+}
diff --git a/src/main/java/seedu/medmoriser/model/ModelManager.java b/src/main/java/seedu/medmoriser/model/ModelManager.java
new file mode 100644
index 00000000000..db6ba7c07bc
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/model/ModelManager.java
@@ -0,0 +1,151 @@
+package seedu.medmoriser.model;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medmoriser.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.nio.file.Path;
+import java.util.function.Predicate;
+import java.util.logging.Logger;
+
+import javafx.collections.ObservableList;
+import javafx.collections.transformation.FilteredList;
+import seedu.medmoriser.commons.core.GuiSettings;
+import seedu.medmoriser.commons.core.LogsCenter;
+import seedu.medmoriser.model.qanda.QAndA;
+
+/**
+ * Represents the in-memory model of the medmoriser data.
+ */
+public class ModelManager implements Model {
+ private static final Logger logger = LogsCenter.getLogger(ModelManager.class);
+
+ private final Medmoriser medmoriser;
+ private final UserPrefs userPrefs;
+ private final FilteredList filteredQAndAS;
+
+ /**
+ * Initializes a ModelManager with the given medmoriser and userPrefs.
+ */
+ public ModelManager(ReadOnlyMedmoriser medmoriser, ReadOnlyUserPrefs userPrefs) {
+ super();
+ requireAllNonNull(medmoriser, userPrefs);
+
+ logger.fine("Initializing with medmoriser: " + medmoriser + " and user prefs " + userPrefs);
+
+ this.medmoriser = new Medmoriser(medmoriser);
+ this.userPrefs = new UserPrefs(userPrefs);
+ filteredQAndAS = new FilteredList<>(this.medmoriser.getQAndAList());
+ }
+
+ public ModelManager() {
+ this(new Medmoriser(), new UserPrefs());
+ }
+
+ //=========== UserPrefs ==================================================================================
+
+ @Override
+ public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
+ requireNonNull(userPrefs);
+ this.userPrefs.resetData(userPrefs);
+ }
+
+ @Override
+ public ReadOnlyUserPrefs getUserPrefs() {
+ return userPrefs;
+ }
+
+ @Override
+ public GuiSettings getGuiSettings() {
+ return userPrefs.getGuiSettings();
+ }
+
+ @Override
+ public void setGuiSettings(GuiSettings guiSettings) {
+ requireNonNull(guiSettings);
+ userPrefs.setGuiSettings(guiSettings);
+ }
+
+ @Override
+ public Path getMedmoriserFilePath() {
+ return userPrefs.getMedmoriserFilePath();
+ }
+
+ @Override
+ public void setMedmoriserFilePath(Path medmoriserFilePath) {
+ requireNonNull(medmoriserFilePath);
+ userPrefs.setMedmoriserFilePath(medmoriserFilePath);
+ }
+
+ //=========== medmoriser ================================================================================
+
+ @Override
+ public void setMedmoriser(ReadOnlyMedmoriser medmoriser) {
+ this.medmoriser.resetData(medmoriser);
+ }
+
+ @Override
+ public ReadOnlyMedmoriser getMedmoriser() {
+ return medmoriser;
+ }
+
+ @Override
+ public boolean hasQAndA(QAndA qAndA) {
+ requireNonNull(qAndA);
+ return medmoriser.hasQAndA(qAndA);
+ }
+
+ @Override
+ public void deleteQAndA(QAndA target) {
+ medmoriser.removeQAndA(target);
+ }
+
+ @Override
+ public void addQAndA(QAndA qAndA) {
+ medmoriser.addQAndA(qAndA);
+ updateFilteredQAndAList(PREDICATE_SHOW_ALL_QANDA);
+ }
+
+ @Override
+ public void setQAndA(QAndA target, QAndA editedQAndA) {
+ requireAllNonNull(target, editedQAndA);
+
+ medmoriser.setQAndA(target, editedQAndA);
+ }
+
+ //=========== Filtered QAndA List Accessors =============================================================
+
+ /**
+ * Returns an unmodifiable view of the list of {@code QAndA} backed by the internal list of
+ * {@code versionedMedmoriser}
+ */
+ @Override
+ public ObservableList getFilteredQAndAList() {
+ return filteredQAndAS;
+ }
+
+ @Override
+ public void updateFilteredQAndAList(Predicate predicate) {
+ requireNonNull(predicate);
+ filteredQAndAS.setPredicate(predicate);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ // short circuit if same object
+ if (obj == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(obj instanceof ModelManager)) {
+ return false;
+ }
+
+ // state check
+ ModelManager other = (ModelManager) obj;
+ return medmoriser.equals(other.medmoriser)
+ && userPrefs.equals(other.userPrefs)
+ && filteredQAndAS.equals(other.filteredQAndAS);
+ }
+
+}
diff --git a/src/main/java/seedu/medmoriser/model/ReadOnlyMedmoriser.java b/src/main/java/seedu/medmoriser/model/ReadOnlyMedmoriser.java
new file mode 100644
index 00000000000..4a00209e270
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/model/ReadOnlyMedmoriser.java
@@ -0,0 +1,17 @@
+package seedu.medmoriser.model;
+
+import javafx.collections.ObservableList;
+import seedu.medmoriser.model.qanda.QAndA;
+
+/**
+ * Unmodifiable view of a medmoriser
+ */
+public interface ReadOnlyMedmoriser {
+
+ /**
+ * Returns an unmodifiable view of the qAndAs list.
+ * This list will not contain any duplicate qAndAs.
+ */
+ ObservableList getQAndAList();
+
+}
diff --git a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java b/src/main/java/seedu/medmoriser/model/ReadOnlyUserPrefs.java
similarity index 56%
rename from src/main/java/seedu/address/model/ReadOnlyUserPrefs.java
rename to src/main/java/seedu/medmoriser/model/ReadOnlyUserPrefs.java
index befd58a4c73..377795808d0 100644
--- a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java
+++ b/src/main/java/seedu/medmoriser/model/ReadOnlyUserPrefs.java
@@ -1,8 +1,8 @@
-package seedu.address.model;
+package seedu.medmoriser.model;
import java.nio.file.Path;
-import seedu.address.commons.core.GuiSettings;
+import seedu.medmoriser.commons.core.GuiSettings;
/**
* Unmodifiable view of user prefs.
@@ -11,6 +11,6 @@ public interface ReadOnlyUserPrefs {
GuiSettings getGuiSettings();
- Path getAddressBookFilePath();
+ Path getMedmoriserFilePath();
}
diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/seedu/medmoriser/model/UserPrefs.java
similarity index 70%
rename from src/main/java/seedu/address/model/UserPrefs.java
rename to src/main/java/seedu/medmoriser/model/UserPrefs.java
index 25a5fd6eab9..e5544f9bd06 100644
--- a/src/main/java/seedu/address/model/UserPrefs.java
+++ b/src/main/java/seedu/medmoriser/model/UserPrefs.java
@@ -1,4 +1,4 @@
-package seedu.address.model;
+package seedu.medmoriser.model;
import static java.util.Objects.requireNonNull;
@@ -6,7 +6,7 @@
import java.nio.file.Paths;
import java.util.Objects;
-import seedu.address.commons.core.GuiSettings;
+import seedu.medmoriser.commons.core.GuiSettings;
/**
* Represents User's preferences.
@@ -14,7 +14,7 @@
public class UserPrefs implements ReadOnlyUserPrefs {
private GuiSettings guiSettings = new GuiSettings();
- private Path addressBookFilePath = Paths.get("data" , "addressbook.json");
+ private Path medmoriserFilePath = Paths.get("data" , "medmoriser.json");
/**
* Creates a {@code UserPrefs} with default values.
@@ -35,7 +35,7 @@ public UserPrefs(ReadOnlyUserPrefs userPrefs) {
public void resetData(ReadOnlyUserPrefs newUserPrefs) {
requireNonNull(newUserPrefs);
setGuiSettings(newUserPrefs.getGuiSettings());
- setAddressBookFilePath(newUserPrefs.getAddressBookFilePath());
+ setMedmoriserFilePath(newUserPrefs.getMedmoriserFilePath());
}
public GuiSettings getGuiSettings() {
@@ -47,13 +47,13 @@ public void setGuiSettings(GuiSettings guiSettings) {
this.guiSettings = guiSettings;
}
- public Path getAddressBookFilePath() {
- return addressBookFilePath;
+ public Path getMedmoriserFilePath() {
+ return medmoriserFilePath;
}
- public void setAddressBookFilePath(Path addressBookFilePath) {
- requireNonNull(addressBookFilePath);
- this.addressBookFilePath = addressBookFilePath;
+ public void setMedmoriserFilePath(Path medmoriserFilePath) {
+ requireNonNull(medmoriserFilePath);
+ this.medmoriserFilePath = medmoriserFilePath;
}
@Override
@@ -68,19 +68,19 @@ public boolean equals(Object other) {
UserPrefs o = (UserPrefs) other;
return guiSettings.equals(o.guiSettings)
- && addressBookFilePath.equals(o.addressBookFilePath);
+ && medmoriserFilePath.equals(o.medmoriserFilePath);
}
@Override
public int hashCode() {
- return Objects.hash(guiSettings, addressBookFilePath);
+ return Objects.hash(guiSettings, medmoriserFilePath);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Gui Settings : " + guiSettings);
- sb.append("\nLocal data file location : " + addressBookFilePath);
+ sb.append("\nLocal data file location : " + medmoriserFilePath);
return sb.toString();
}
diff --git a/src/main/java/seedu/medmoriser/model/qanda/Answer.java b/src/main/java/seedu/medmoriser/model/qanda/Answer.java
new file mode 100644
index 00000000000..8a887b11c89
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/model/qanda/Answer.java
@@ -0,0 +1,57 @@
+package seedu.medmoriser.model.qanda;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medmoriser.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents a qAndA's answer in the question bank.
+ * Guarantees: immutable; is valid as declared in {@link #isValidAnswer(String)}
+ */
+public class Answer {
+
+ public static final String MESSAGE_CONSTRAINTS = "Answer can take any values, and it should not be blank";
+
+ /*
+ * The first character of the answer must not be a whitespace,
+ * otherwise " " (a blank string) becomes a valid input.
+ */
+ public static final String VALIDATION_REGEX = "[^\\s].*";
+
+ public final String answer;
+
+ /**
+ * Constructs an {@code answer}.
+ *
+ * @param answer A valid answer.
+ */
+ public Answer(String answer) {
+ requireNonNull(answer);
+ checkArgument(isValidAnswer(answer), MESSAGE_CONSTRAINTS);
+ this.answer = answer;
+ }
+
+ /**
+ * Returns true if a given string is a valid email.
+ */
+ public static boolean isValidAnswer(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ @Override
+ public String toString() {
+ return answer;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Answer // instanceof handles nulls
+ && answer.equals(((Answer) other).answer)); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return answer.hashCode();
+ }
+
+}
diff --git a/src/main/java/seedu/medmoriser/model/qanda/AnswerContainsKeywordsPredicate.java b/src/main/java/seedu/medmoriser/model/qanda/AnswerContainsKeywordsPredicate.java
new file mode 100644
index 00000000000..885d130bd11
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/model/qanda/AnswerContainsKeywordsPredicate.java
@@ -0,0 +1,31 @@
+package seedu.medmoriser.model.qanda;
+
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+
+/**
+ * Tests that a {@code QAndA}'s {@code Answer} matches any of the keywords given.
+ */
+public class AnswerContainsKeywordsPredicate implements Predicate {
+ private final List keywords;
+
+ public AnswerContainsKeywordsPredicate(List keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public boolean test(QAndA qAndA) {
+ return keywords.stream()
+ .anyMatch(keyword -> qAndA.getAnswer().answer.toLowerCase()
+ .matches((".*\\b" + Pattern.quote(keyword.toLowerCase()) + "\\b.*")));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof AnswerContainsKeywordsPredicate // instanceof handles nulls
+ && keywords.equals(((AnswerContainsKeywordsPredicate) other).keywords)); // state check
+ }
+
+}
diff --git a/src/main/java/seedu/medmoriser/model/qanda/QAndA.java b/src/main/java/seedu/medmoriser/model/qanda/QAndA.java
new file mode 100644
index 00000000000..23b4bcc5d25
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/model/qanda/QAndA.java
@@ -0,0 +1,136 @@
+package seedu.medmoriser.model.qanda;
+
+import static seedu.medmoriser.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+import seedu.medmoriser.model.tag.Tag;
+
+/**
+ * Represents a QuestionSet in the Question bank.
+ * Guarantees: details are present and not null, field values are validated, immutable.
+ */
+public class QAndA {
+
+ // Identity fields
+ private final Question question;
+ private boolean isQuiz = false;
+ private boolean isQuizAnswer = false;
+ private boolean beenAnswered = false;
+
+ // Data fields
+ private final Answer answer;
+ private final Set tags = new HashSet<>();
+
+ /**
+ * If all fields are present:
+ * Every field must be present and not null.
+ */
+ public QAndA(Question question, Answer answer, Set tags) {
+ requireAllNonNull(question, answer, tags);
+ this.question = question;
+ this.answer = answer;
+ this.tags.addAll(tags);
+ }
+
+ public Question getQuestion() {
+ return question;
+ }
+
+ public Answer getAnswer() {
+ return answer;
+ }
+
+ public Boolean getIsQuiz() {
+ return this.isQuiz;
+ }
+
+ public Boolean getIsQuizAnswer() {
+ return this.isQuizAnswer;
+ }
+
+ public void setQuizAnswer() {
+ this.isQuizAnswer = true;
+ }
+
+ public void setAsQuiz() {
+ this.isQuiz = true;
+ }
+
+ public void setNotQuiz() {
+ this.isQuiz = false;
+ this.isQuizAnswer = false;
+ }
+
+ public void setBeenAnswered() {
+ beenAnswered = true;
+ }
+
+ public void setNotBeenAnswered() {
+ beenAnswered = false;
+ }
+
+ /**
+ * Returns an immutable tag set, which throws {@code UnsupportedOperationException}
+ * if modification is attempted.
+ */
+ public Set getTags() {
+ return Collections.unmodifiableSet(tags);
+ }
+
+ /**
+ * Returns true if both QuestionSets of the same name have at least one other identity field that is the same.
+ * This defines a weaker notion of equality between two QuestionSets.
+ */
+ public boolean isSameQAndA(QAndA otherQAndA) {
+ if (otherQAndA == this) {
+ return true;
+ }
+
+ return otherQAndA != null
+ && otherQAndA.getQuestion().equals(getQuestion());
+ }
+
+ /**
+ * Returns true if both QuestionSets have the same identity and data fields.
+ * This defines a stronger notion of equality between two QuestionSet.
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ if (!(other instanceof QAndA)) {
+ return false;
+ }
+
+ QAndA otherQAndA = (QAndA) other;
+ return otherQAndA.getQuestion().equals(getQuestion())
+ && otherQAndA.getAnswer().equals(getAnswer())
+ && otherQAndA.getTags().equals(getTags());
+ }
+
+ @Override
+ public int hashCode() {
+ // use this method for custom fields hashing instead of implementing your own
+ return Objects.hash(question, answer, tags);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(getQuestion())
+ .append(" Answer: ")
+ .append(getAnswer());
+ if (getTags().size() > 0) {
+ builder.append(" Tags: ");
+ getTags().forEach(builder::append);
+ }
+ return builder.toString();
+ }
+
+}
diff --git a/src/main/java/seedu/medmoriser/model/qanda/QAndAContainsKeywordsPredicate.java b/src/main/java/seedu/medmoriser/model/qanda/QAndAContainsKeywordsPredicate.java
new file mode 100644
index 00000000000..cb2dfd8115a
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/model/qanda/QAndAContainsKeywordsPredicate.java
@@ -0,0 +1,34 @@
+package seedu.medmoriser.model.qanda;
+
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+
+/**
+ * Tests that a {@code QandA}'s {@code Question or Answer} matches any of the keywords given.
+ */
+public class QAndAContainsKeywordsPredicate implements Predicate {
+ private final List keywords;
+
+ public QAndAContainsKeywordsPredicate(List keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public boolean test(QAndA qAndA) {
+ return keywords.stream()
+ .anyMatch(keyword -> qAndA.getQuestion().question.toLowerCase()
+ .matches((".*\\b" + Pattern.quote(keyword.toLowerCase()) + "\\b.*"))
+ || qAndA.getAnswer().answer.toLowerCase()
+ .matches((".*\\b" + Pattern.quote(keyword.toLowerCase()) + "\\b.*"))
+ );
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof QAndAContainsKeywordsPredicate // instanceof handles nulls
+ && keywords.equals(((QAndAContainsKeywordsPredicate) other).keywords)); // state check
+ }
+
+}
diff --git a/src/main/java/seedu/medmoriser/model/qanda/Question.java b/src/main/java/seedu/medmoriser/model/qanda/Question.java
new file mode 100644
index 00000000000..8f6820417eb
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/model/qanda/Question.java
@@ -0,0 +1,59 @@
+package seedu.medmoriser.model.qanda;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medmoriser.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents a QuestionSet's question in the question bank.
+ * Guarantees: immutable; is valid as declared in {@link #isValidQuestion(String)}
+ */
+public class Question {
+
+ public static final String MESSAGE_CONSTRAINTS =
+ "Questions can take any values, and it should not be blank";
+
+ /*
+ * The first character of the question must not be a whitespace,
+ * otherwise " " (a blank string) becomes a valid input.
+ */
+ public static final String VALIDATION_REGEX = "[^\\s].*";
+
+ public final String question;
+
+ /**
+ * Constructs a {@code Question}.
+ *
+ * @param question A valid question.
+ */
+ public Question(String question) {
+ requireNonNull(question);
+ checkArgument(isValidQuestion(question), MESSAGE_CONSTRAINTS);
+ this.question = question;
+ }
+
+ /**
+ * Returns true if a given string is a valid question.
+ */
+ public static boolean isValidQuestion(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+
+ @Override
+ public String toString() {
+ return question;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Question // instanceof handles nulls
+ && question.equals(((Question) other).question)); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return question.hashCode();
+ }
+
+}
diff --git a/src/main/java/seedu/medmoriser/model/qanda/QuestionContainsKeywordsPredicate.java b/src/main/java/seedu/medmoriser/model/qanda/QuestionContainsKeywordsPredicate.java
new file mode 100644
index 00000000000..9a767ecabd2
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/model/qanda/QuestionContainsKeywordsPredicate.java
@@ -0,0 +1,31 @@
+package seedu.medmoriser.model.qanda;
+
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+
+/**
+ * Tests that a {@code QAndA}'s {@code Question} matches any of the keywords given.
+ */
+public class QuestionContainsKeywordsPredicate implements Predicate {
+ private final List keywords;
+
+ public QuestionContainsKeywordsPredicate(List keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public boolean test(QAndA qAndA) {
+ return keywords.stream()
+ .anyMatch(keyword -> qAndA.getQuestion().question.toLowerCase()
+ .matches((".*\\b" + Pattern.quote(keyword.toLowerCase()) + "\\b.*")));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof QuestionContainsKeywordsPredicate // instanceof handles nulls
+ && keywords.equals(((QuestionContainsKeywordsPredicate) other).keywords)); // state check
+ }
+
+}
diff --git a/src/main/java/seedu/medmoriser/model/qanda/TagContainsKeywordsPredicate.java b/src/main/java/seedu/medmoriser/model/qanda/TagContainsKeywordsPredicate.java
new file mode 100644
index 00000000000..711fd492c39
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/model/qanda/TagContainsKeywordsPredicate.java
@@ -0,0 +1,46 @@
+package seedu.medmoriser.model.qanda;
+
+import java.util.List;
+import java.util.Set;
+import java.util.function.Predicate;
+
+import seedu.medmoriser.model.tag.Tag;
+
+/**
+ * Tests that a {@code QAndA}'s {@code Tag} matches any of the keywords given.
+ */
+public class TagContainsKeywordsPredicate implements Predicate {
+ private final List keywords;
+
+ public TagContainsKeywordsPredicate(List keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public boolean test(QAndA qAndA) {
+ if (keywords.size() == 0 || keywords.get(0).equals("t")) {
+ Set tags = qAndA.getTags();
+ return tags.isEmpty();
+ } else {
+ return keywords.stream()
+ .anyMatch(keyword -> {
+ Set tags = qAndA.getTags();
+ for (Tag tag : tags) {
+ String lowercase = tag.tagName.toLowerCase();
+ if (lowercase.equals(keyword.toLowerCase())) {
+ return true;
+ }
+ }
+ return false;
+ });
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof TagContainsKeywordsPredicate // instanceof handles nulls
+ && keywords.equals(((TagContainsKeywordsPredicate) other).keywords)); // state check
+ }
+
+}
diff --git a/src/main/java/seedu/medmoriser/model/qanda/UniqueQAndAList.java b/src/main/java/seedu/medmoriser/model/qanda/UniqueQAndAList.java
new file mode 100644
index 00000000000..1a4c797ef1e
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/model/qanda/UniqueQAndAList.java
@@ -0,0 +1,140 @@
+package seedu.medmoriser.model.qanda;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.medmoriser.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.medmoriser.model.qanda.exceptions.DuplicateQAndAException;
+import seedu.medmoriser.model.qanda.exceptions.QAndANotFoundException;
+
+/**
+ * A list of questionSets that enforces uniqueness between its elements and does not allow nulls.
+ * A questionSet is considered unique by comparing using {@code QuestionSet#isSameQAndA(QuestionSet)}.
+ * As such, adding and updating of questionSets uses QuestionSet#isSameQAndA(QuestionSet)
+ * for equality so as to ensure that the questionSet being added or updated is
+ * unique in terms of identity in the UniqueQuestionSetList. However, the removal
+ * of a questionSet uses QuestionSet#equals(Object) so as to ensure that the questionSet
+ * with exactly the same fields will be removed.
+ *
+ * Supports a minimal set of list operations.
+ *
+ * @see QAndA#isSameQAndA(QAndA)
+ */
+public class UniqueQAndAList implements Iterable {
+
+ private final ObservableList internalList = FXCollections.observableArrayList();
+ private final ObservableList internalUnmodifiableList =
+ FXCollections.unmodifiableObservableList(internalList);
+
+ /**
+ * Returns true if the list contains an equivalent qAndA as the given argument.
+ */
+ public boolean contains(QAndA toCheck) {
+ requireNonNull(toCheck);
+ return internalList.stream().anyMatch(toCheck::isSameQAndA);
+ }
+
+ /**
+ * Adds a qAndA to the list.
+ * The qAndA must not already exist in the list.
+ */
+ public void add(QAndA toAdd) {
+ requireNonNull(toAdd);
+ if (contains(toAdd)) {
+ throw new DuplicateQAndAException();
+ }
+ internalList.add(toAdd);
+ }
+
+ /**
+ * Replaces the qAndA {@code target} in the list with {@code editedQuestionSet}.
+ * {@code target} must exist in the list.
+ * The questionSet identity of {@code editedQuestionSet} must not be the same as another existing
+ * questionSet in the list.
+ */
+ public void setQAndA(QAndA target, QAndA editedQAndA) {
+ requireAllNonNull(target, editedQAndA);
+
+ int index = internalList.indexOf(target);
+ if (index == -1) {
+ throw new QAndANotFoundException();
+ }
+
+ if (!target.isSameQAndA(editedQAndA) && contains(editedQAndA)) {
+ throw new DuplicateQAndAException();
+ }
+
+ internalList.set(index, editedQAndA);
+ }
+
+ /**
+ * Removes the equivalent qAndA from the list.
+ * The qAndA must exist in the list.
+ */
+ public void remove(QAndA toRemove) {
+ requireNonNull(toRemove);
+ if (!internalList.remove(toRemove)) {
+ throw new QAndANotFoundException();
+ }
+ }
+
+ public void setQAndAs(UniqueQAndAList replacement) {
+ requireNonNull(replacement);
+ internalList.setAll(replacement.internalList);
+ }
+
+ /**
+ * Replaces the contents of this list with {@code qAndAs}.
+ * {@code qAndAs} must not contain duplicate qAndAs.
+ */
+ public void setQAndAs(List qAndAs) {
+ requireAllNonNull(qAndAs);
+ if (!questionSetsAreUnique(qAndAs)) {
+ throw new DuplicateQAndAException();
+ }
+
+ internalList.setAll(qAndAs);
+ }
+
+ /**
+ * Returns the backing list as an unmodifiable {@code ObservableList}.
+ */
+ public ObservableList asUnmodifiableObservableList() {
+ return internalUnmodifiableList;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return internalList.iterator();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof UniqueQAndAList // instanceof handles nulls
+ && internalList.equals(((UniqueQAndAList) other).internalList));
+ }
+
+ @Override
+ public int hashCode() {
+ return internalList.hashCode();
+ }
+
+ /**
+ * Returns true if {@code qAndAs} contains only unique qAndAs.
+ */
+ private boolean questionSetsAreUnique(List qAndAs) {
+ for (int i = 0; i < qAndAs.size() - 1; i++) {
+ for (int j = i + 1; j < qAndAs.size(); j++) {
+ if (qAndAs.get(i).isSameQAndA(qAndAs.get(j))) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/seedu/medmoriser/model/qanda/exceptions/DuplicateQAndAException.java b/src/main/java/seedu/medmoriser/model/qanda/exceptions/DuplicateQAndAException.java
new file mode 100644
index 00000000000..9ceda03a63c
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/model/qanda/exceptions/DuplicateQAndAException.java
@@ -0,0 +1,11 @@
+package seedu.medmoriser.model.qanda.exceptions;
+
+/**
+ * Signals that the operation will result in duplicate QAndAs (QAndAs are considered
+ * duplicates if they have the same identity).
+ */
+public class DuplicateQAndAException extends RuntimeException {
+ public DuplicateQAndAException() {
+ super("Operation would result in duplicate QAndAs");
+ }
+}
diff --git a/src/main/java/seedu/medmoriser/model/qanda/exceptions/QAndANotFoundException.java b/src/main/java/seedu/medmoriser/model/qanda/exceptions/QAndANotFoundException.java
new file mode 100644
index 00000000000..97f38c11266
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/model/qanda/exceptions/QAndANotFoundException.java
@@ -0,0 +1,6 @@
+package seedu.medmoriser.model.qanda.exceptions;
+
+/**
+ * Signals that the operation is unable to find the specified qAndA.
+ */
+public class QAndANotFoundException extends RuntimeException {}
diff --git a/src/main/java/seedu/address/model/tag/Tag.java b/src/main/java/seedu/medmoriser/model/tag/Tag.java
similarity index 78%
rename from src/main/java/seedu/address/model/tag/Tag.java
rename to src/main/java/seedu/medmoriser/model/tag/Tag.java
index b0ea7e7dad7..62aa0cf1c08 100644
--- a/src/main/java/seedu/address/model/tag/Tag.java
+++ b/src/main/java/seedu/medmoriser/model/tag/Tag.java
@@ -1,7 +1,7 @@
-package seedu.address.model.tag;
+package seedu.medmoriser.model.tag;
import static java.util.Objects.requireNonNull;
-import static seedu.address.commons.util.AppUtil.checkArgument;
+import static seedu.medmoriser.commons.util.AppUtil.checkArgument;
/**
* Represents a Tag in the address book.
@@ -9,8 +9,9 @@
*/
public class Tag {
- public static final String MESSAGE_CONSTRAINTS = "Tags names should be alphanumeric";
- public static final String VALIDATION_REGEX = "\\p{Alnum}+";
+ public static final String MESSAGE_CONSTRAINTS =
+ "Tags names should only contain alphanumeric characters and spaces";
+ public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*";
public final String tagName;
diff --git a/src/main/java/seedu/medmoriser/model/util/SampleDataUtil.java b/src/main/java/seedu/medmoriser/model/util/SampleDataUtil.java
new file mode 100644
index 00000000000..ba2db5e3cc6
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/model/util/SampleDataUtil.java
@@ -0,0 +1,52 @@
+package seedu.medmoriser.model.util;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import seedu.medmoriser.model.Medmoriser;
+import seedu.medmoriser.model.ReadOnlyMedmoriser;
+import seedu.medmoriser.model.qanda.Answer;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.qanda.Question;
+import seedu.medmoriser.model.tag.Tag;
+
+/**
+ * Contains utility methods for populating {@code Medmoriser} with sample data.
+ */
+public class SampleDataUtil {
+ public static QAndA[] getSampleQuestionSets() {
+ return new QAndA[] {
+ new QAndA(new Question("What is the largest organ in the human body?"), new Answer("Skin"),
+ getTagSet("anatomy")),
+ new QAndA(new Question("What is the largest bone in the body?"), new Answer("Femur"),
+ getTagSet("anatomy", "skeletal system")),
+ new QAndA(new Question("Which type of cell is found in the brain?"), new Answer("Neurons"),
+ getTagSet("neurology")),
+ new QAndA(new Question("People with diabetes are unable to produce or use ______ properly"),
+ new Answer("Insulin"), getTagSet("disease")),
+ new QAndA(new Question("_________ is a rare disorder in which the blood does not clot properly"),
+ new Answer("Hemophilia"), getTagSet("cardiology")),
+ new QAndA(new Question("Encephalitis refers to inflammation of which organ in the body?"),
+ new Answer("Brain"), getTagSet("neurology"))
+ };
+ }
+
+ public static ReadOnlyMedmoriser getSampleMedmoriser() {
+ Medmoriser sampleMedmoriser = new Medmoriser();
+ for (QAndA sampleQAndA : getSampleQuestionSets()) {
+ sampleMedmoriser.addQAndA(sampleQAndA);
+ }
+ return sampleMedmoriser;
+ }
+
+ /**
+ * Returns a tag set containing the list of strings given.
+ */
+ public static Set getTagSet(String... strings) {
+ return Arrays.stream(strings)
+ .map(Tag::new)
+ .collect(Collectors.toSet());
+ }
+
+}
diff --git a/src/main/java/seedu/medmoriser/storage/JsonAdaptedQAndA.java b/src/main/java/seedu/medmoriser/storage/JsonAdaptedQAndA.java
new file mode 100644
index 00000000000..63bf0b6522b
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/storage/JsonAdaptedQAndA.java
@@ -0,0 +1,85 @@
+package seedu.medmoriser.storage;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import seedu.medmoriser.commons.exceptions.IllegalValueException;
+import seedu.medmoriser.model.qanda.Answer;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.qanda.Question;
+import seedu.medmoriser.model.tag.Tag;
+
+/**
+ * Jackson-friendly version of {@link QAndA}.
+ */
+class JsonAdaptedQAndA {
+
+ public static final String MISSING_FIELD_MESSAGE_FORMAT = "QAndA's %s field is missing!";
+
+ private final String question;
+ private final String answer;
+ private final List tagged = new ArrayList<>();
+
+ /**
+ * Constructs a {@code JsonAdaptedQAndA} with the given qAndA details.
+ */
+ @JsonCreator
+ public JsonAdaptedQAndA(@JsonProperty("name") String question, @JsonProperty("answer") String answer,
+ @JsonProperty("tagged") List tagged) {
+ this.question = question;
+ this.answer = answer;
+ if (tagged != null) {
+ this.tagged.addAll(tagged);
+ }
+ }
+
+ /**
+ * Converts a given {@code QAndA} into this class for Jackson use.
+ */
+ public JsonAdaptedQAndA(QAndA source) {
+ question = source.getQuestion().question;
+ answer = source.getAnswer().answer;
+ tagged.addAll(source.getTags().stream()
+ .map(JsonAdaptedTag::new)
+ .collect(Collectors.toList()));
+ }
+
+ /**
+ * Converts this Jackson-friendly adapted qAndA object into the model's {@code QAndA} object.
+ *
+ * @throws IllegalValueException if there were any data constraints violated in the adapted qAndA.
+ */
+ public QAndA toModelType() throws IllegalValueException {
+ final List qAndATags = new ArrayList<>();
+ for (JsonAdaptedTag tag : tagged) {
+ qAndATags.add(tag.toModelType());
+ }
+
+ if (question == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT,
+ Question.class.getSimpleName()));
+ }
+ if (!Question.isValidQuestion(question)) {
+ throw new IllegalValueException(Question.MESSAGE_CONSTRAINTS);
+ }
+ final Question modelQuestion = new Question(question);
+
+ if (answer == null) {
+ throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Answer.class.getSimpleName()));
+ }
+ if (!Answer.isValidAnswer(answer)) {
+ throw new IllegalValueException(Answer.MESSAGE_CONSTRAINTS);
+ }
+ final Answer modelAnswer = new Answer(answer);
+
+ final Set modelTags = new HashSet<>(qAndATags);
+ return new QAndA(modelQuestion, modelAnswer, modelTags);
+ }
+
+}
diff --git a/src/main/java/seedu/address/storage/JsonAdaptedTag.java b/src/main/java/seedu/medmoriser/storage/JsonAdaptedTag.java
similarity index 88%
rename from src/main/java/seedu/address/storage/JsonAdaptedTag.java
rename to src/main/java/seedu/medmoriser/storage/JsonAdaptedTag.java
index 0df22bdb754..c4ea938cb9f 100644
--- a/src/main/java/seedu/address/storage/JsonAdaptedTag.java
+++ b/src/main/java/seedu/medmoriser/storage/JsonAdaptedTag.java
@@ -1,10 +1,10 @@
-package seedu.address.storage;
+package seedu.medmoriser.storage;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.tag.Tag;
+import seedu.medmoriser.commons.exceptions.IllegalValueException;
+import seedu.medmoriser.model.tag.Tag;
/**
* Jackson-friendly version of {@link Tag}.
diff --git a/src/main/java/seedu/medmoriser/storage/JsonMedmoriserStorage.java b/src/main/java/seedu/medmoriser/storage/JsonMedmoriserStorage.java
new file mode 100644
index 00000000000..7586a101b91
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/storage/JsonMedmoriserStorage.java
@@ -0,0 +1,80 @@
+package seedu.medmoriser.storage;
+
+import static java.util.Objects.requireNonNull;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import seedu.medmoriser.commons.core.LogsCenter;
+import seedu.medmoriser.commons.exceptions.DataConversionException;
+import seedu.medmoriser.commons.exceptions.IllegalValueException;
+import seedu.medmoriser.commons.util.FileUtil;
+import seedu.medmoriser.commons.util.JsonUtil;
+import seedu.medmoriser.model.ReadOnlyMedmoriser;
+
+/**
+ * A class to access Medmoriser data stored as a json file on the hard disk.
+ */
+public class JsonMedmoriserStorage implements MedmoriserStorage {
+
+ private static final Logger logger = LogsCenter.getLogger(JsonMedmoriserStorage.class);
+
+ private Path filePath;
+
+ public JsonMedmoriserStorage(Path filePath) {
+ this.filePath = filePath;
+ }
+
+ public Path getMedmoriserFilePath() {
+ return filePath;
+ }
+
+ @Override
+ public Optional readMedmoriser() throws DataConversionException {
+ return readMedmoriser(filePath);
+ }
+
+ /**
+ * Similar to {@link #readMedmoriser()}.
+ *
+ * @param filePath location of the data. Cannot be null.
+ * @throws DataConversionException if the file is not in the correct format.
+ */
+ public Optional readMedmoriser(Path filePath) throws DataConversionException {
+ requireNonNull(filePath);
+
+ Optional jsonMedmoriser = JsonUtil.readJsonFile(
+ filePath, JsonSerializableMedmoriser.class);
+ if (!jsonMedmoriser.isPresent()) {
+ return Optional.empty();
+ }
+
+ try {
+ return Optional.of(jsonMedmoriser.get().toModelType());
+ } catch (IllegalValueException ive) {
+ logger.info("Illegal values found in " + filePath + ": " + ive.getMessage());
+ throw new DataConversionException(ive);
+ }
+ }
+
+ @Override
+ public void saveMedmoriser(ReadOnlyMedmoriser medmoriser) throws IOException {
+ saveMedmoriser(medmoriser, filePath);
+ }
+
+ /**
+ * Similar to {@link #saveMedmoriser(ReadOnlyMedmoriser)}.
+ *
+ * @param filePath location of the data. Cannot be null.
+ */
+ public void saveMedmoriser(ReadOnlyMedmoriser medmoriser, Path filePath) throws IOException {
+ requireNonNull(medmoriser);
+ requireNonNull(filePath);
+
+ FileUtil.createIfMissing(filePath);
+ JsonUtil.saveJsonFile(new JsonSerializableMedmoriser(medmoriser), filePath);
+ }
+
+}
diff --git a/src/main/java/seedu/medmoriser/storage/JsonSerializableMedmoriser.java b/src/main/java/seedu/medmoriser/storage/JsonSerializableMedmoriser.java
new file mode 100644
index 00000000000..db7ff9e589e
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/storage/JsonSerializableMedmoriser.java
@@ -0,0 +1,61 @@
+package seedu.medmoriser.storage;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonRootName;
+
+import seedu.medmoriser.commons.exceptions.IllegalValueException;
+import seedu.medmoriser.model.Medmoriser;
+import seedu.medmoriser.model.ReadOnlyMedmoriser;
+import seedu.medmoriser.model.qanda.QAndA;
+
+/**
+ * An Immutable Medmoriser that is serializable to JSON format.
+ */
+@JsonRootName(value = "medmoriser")
+class JsonSerializableMedmoriser {
+
+ public static final String MESSAGE_DUPLICATE_QANDA = "QAndAs list contains duplicate qAndA(s).";
+
+ private final List qAndAs = new ArrayList<>();
+
+ /**
+ * Constructs a {@code JsonSerializableMedmoriser} with the given qAndAs.
+ */
+ @JsonCreator
+ public JsonSerializableMedmoriser(@JsonProperty("qAndAs") List qAndAs) {
+ this.qAndAs.addAll(qAndAs);
+ }
+
+ /**
+ * Converts a given {@code ReadOnlyMedmoriser} into this class for Jackson use.
+ *
+ * @param source future changes to this will not affect the created {@code JsonSerializableMedmoriser}.
+ */
+ public JsonSerializableMedmoriser(ReadOnlyMedmoriser source) {
+ qAndAs.addAll(source.getQAndAList().stream().map(JsonAdaptedQAndA::new)
+ .collect(Collectors.toList()));
+ }
+
+ /**
+ * Converts this medmoriser into the model's {@code Medmoriser} object.
+ *
+ * @throws IllegalValueException if there were any data constraints violated.
+ */
+ public Medmoriser toModelType() throws IllegalValueException {
+ Medmoriser medmoriser = new Medmoriser();
+ for (JsonAdaptedQAndA jsonAdaptedQAndA : qAndAs) {
+ QAndA qAndA = jsonAdaptedQAndA.toModelType();
+ if (medmoriser.hasQAndA(qAndA)) {
+ throw new IllegalValueException(MESSAGE_DUPLICATE_QANDA);
+ }
+ medmoriser.addQAndA(qAndA);
+ }
+ return medmoriser;
+ }
+
+}
diff --git a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java b/src/main/java/seedu/medmoriser/storage/JsonUserPrefsStorage.java
similarity index 82%
rename from src/main/java/seedu/address/storage/JsonUserPrefsStorage.java
rename to src/main/java/seedu/medmoriser/storage/JsonUserPrefsStorage.java
index bc2bbad84aa..4361366f1be 100644
--- a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java
+++ b/src/main/java/seedu/medmoriser/storage/JsonUserPrefsStorage.java
@@ -1,13 +1,13 @@
-package seedu.address.storage;
+package seedu.medmoriser.storage;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.commons.util.JsonUtil;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
+import seedu.medmoriser.commons.exceptions.DataConversionException;
+import seedu.medmoriser.commons.util.JsonUtil;
+import seedu.medmoriser.model.ReadOnlyUserPrefs;
+import seedu.medmoriser.model.UserPrefs;
/**
* A class to access UserPrefs stored in the hard disk as a json file
diff --git a/src/main/java/seedu/medmoriser/storage/MedmoriserStorage.java b/src/main/java/seedu/medmoriser/storage/MedmoriserStorage.java
new file mode 100644
index 00000000000..9e35ea65b7f
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/storage/MedmoriserStorage.java
@@ -0,0 +1,46 @@
+package seedu.medmoriser.storage;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+
+import seedu.medmoriser.commons.exceptions.DataConversionException;
+import seedu.medmoriser.model.Medmoriser;
+import seedu.medmoriser.model.ReadOnlyMedmoriser;
+
+/**
+ * Represents a storage for {@link Medmoriser}.
+ */
+public interface MedmoriserStorage {
+
+ /**
+ * Returns the file path of the data file.
+ */
+ Path getMedmoriserFilePath();
+
+ /**
+ * Returns Medmoriser data as a {@link ReadOnlyMedmoriser}.
+ * Returns {@code Optional.empty()} if storage file is not found.
+ * @throws DataConversionException if the data in storage is not in the expected format.
+ * @throws IOException if there was any problem when reading from the storage.
+ */
+ Optional readMedmoriser() throws DataConversionException, IOException;
+
+ /**
+ * @see #getMedmoriserFilePath()
+ */
+ Optional readMedmoriser(Path filePath) throws DataConversionException, IOException;
+
+ /**
+ * Saves the given {@link ReadOnlyMedmoriser} to the storage.
+ * @param medmoriser cannot be null.
+ * @throws IOException if there was any problem writing to the file.
+ */
+ void saveMedmoriser(ReadOnlyMedmoriser medmoriser) throws IOException;
+
+ /**
+ * @see #saveMedmoriser(ReadOnlyMedmoriser)
+ */
+ void saveMedmoriser(ReadOnlyMedmoriser medmoriser, Path filePath) throws IOException;
+
+}
diff --git a/src/main/java/seedu/medmoriser/storage/Storage.java b/src/main/java/seedu/medmoriser/storage/Storage.java
new file mode 100644
index 00000000000..c21570318b0
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/storage/Storage.java
@@ -0,0 +1,32 @@
+package seedu.medmoriser.storage;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+
+import seedu.medmoriser.commons.exceptions.DataConversionException;
+import seedu.medmoriser.model.ReadOnlyMedmoriser;
+import seedu.medmoriser.model.ReadOnlyUserPrefs;
+import seedu.medmoriser.model.UserPrefs;
+
+/**
+ * API of the Storage component
+ */
+public interface Storage extends MedmoriserStorage, UserPrefsStorage {
+
+ @Override
+ Optional readUserPrefs() throws DataConversionException, IOException;
+
+ @Override
+ void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException;
+
+ @Override
+ Path getMedmoriserFilePath();
+
+ @Override
+ Optional readMedmoriser() throws DataConversionException, IOException;
+
+ @Override
+ void saveMedmoriser(ReadOnlyMedmoriser medmoriser) throws IOException;
+
+}
diff --git a/src/main/java/seedu/medmoriser/storage/StorageManager.java b/src/main/java/seedu/medmoriser/storage/StorageManager.java
new file mode 100644
index 00000000000..8b634ad089b
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/storage/StorageManager.java
@@ -0,0 +1,79 @@
+package seedu.medmoriser.storage;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import seedu.medmoriser.commons.core.LogsCenter;
+import seedu.medmoriser.commons.exceptions.DataConversionException;
+import seedu.medmoriser.model.ReadOnlyMedmoriser;
+import seedu.medmoriser.model.ReadOnlyUserPrefs;
+import seedu.medmoriser.model.UserPrefs;
+
+/**
+ * Manages storage of AddressBook data in local storage.
+ */
+public class StorageManager implements Storage {
+
+ private static final Logger logger = LogsCenter.getLogger(StorageManager.class);
+ private MedmoriserStorage medmoriserStorage;
+ private UserPrefsStorage userPrefsStorage;
+
+ /**
+ * Creates a {@code StorageManager} with the given {@code AddressBookStorage} and {@code UserPrefStorage}.
+ */
+ public StorageManager(MedmoriserStorage medmoriserStorage, UserPrefsStorage userPrefsStorage) {
+ super();
+ this.medmoriserStorage = medmoriserStorage;
+ this.userPrefsStorage = userPrefsStorage;
+ }
+
+ // ================ UserPrefs methods ==============================
+
+ @Override
+ public Path getUserPrefsFilePath() {
+ return userPrefsStorage.getUserPrefsFilePath();
+ }
+
+ @Override
+ public Optional readUserPrefs() throws DataConversionException, IOException {
+ return userPrefsStorage.readUserPrefs();
+ }
+
+ @Override
+ public void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException {
+ userPrefsStorage.saveUserPrefs(userPrefs);
+ }
+
+
+ // ================ Medmoriser methods ==============================
+
+ @Override
+ public Path getMedmoriserFilePath() {
+ return medmoriserStorage.getMedmoriserFilePath();
+ }
+
+ @Override
+ public Optional readMedmoriser() throws DataConversionException, IOException {
+ return readMedmoriser(medmoriserStorage.getMedmoriserFilePath());
+ }
+
+ @Override
+ public Optional readMedmoriser(Path filePath) throws DataConversionException, IOException {
+ logger.fine("Attempting to read data from file: " + filePath);
+ return medmoriserStorage.readMedmoriser(filePath);
+ }
+
+ @Override
+ public void saveMedmoriser(ReadOnlyMedmoriser medmoriser) throws IOException {
+ saveMedmoriser(medmoriser, medmoriserStorage.getMedmoriserFilePath());
+ }
+
+ @Override
+ public void saveMedmoriser(ReadOnlyMedmoriser medmoriser, Path filePath) throws IOException {
+ logger.fine("Attempting to write to data file: " + filePath);
+ medmoriserStorage.saveMedmoriser(medmoriser, filePath);
+ }
+
+}
diff --git a/src/main/java/seedu/address/storage/UserPrefsStorage.java b/src/main/java/seedu/medmoriser/storage/UserPrefsStorage.java
similarity index 70%
rename from src/main/java/seedu/address/storage/UserPrefsStorage.java
rename to src/main/java/seedu/medmoriser/storage/UserPrefsStorage.java
index 29eef178dbc..111d2cd8134 100644
--- a/src/main/java/seedu/address/storage/UserPrefsStorage.java
+++ b/src/main/java/seedu/medmoriser/storage/UserPrefsStorage.java
@@ -1,15 +1,15 @@
-package seedu.address.storage;
+package seedu.medmoriser.storage;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.UserPrefs;
+import seedu.medmoriser.commons.exceptions.DataConversionException;
+import seedu.medmoriser.model.ReadOnlyUserPrefs;
+import seedu.medmoriser.model.UserPrefs;
/**
- * Represents a storage for {@link seedu.address.model.UserPrefs}.
+ * Represents a storage for {@link seedu.medmoriser.model.UserPrefs}.
*/
public interface UserPrefsStorage {
@@ -27,7 +27,7 @@ public interface UserPrefsStorage {
Optional readUserPrefs() throws DataConversionException, IOException;
/**
- * Saves the given {@link seedu.address.model.ReadOnlyUserPrefs} to the storage.
+ * Saves the given {@link seedu.medmoriser.model.ReadOnlyUserPrefs} to the storage.
* @param userPrefs cannot be null.
* @throws IOException if there was any problem writing to the file.
*/
diff --git a/src/main/java/seedu/address/ui/CommandBox.java b/src/main/java/seedu/medmoriser/ui/CommandBox.java
similarity index 88%
rename from src/main/java/seedu/address/ui/CommandBox.java
rename to src/main/java/seedu/medmoriser/ui/CommandBox.java
index 5cc21e47889..b00805c863a 100644
--- a/src/main/java/seedu/address/ui/CommandBox.java
+++ b/src/main/java/seedu/medmoriser/ui/CommandBox.java
@@ -1,12 +1,12 @@
-package seedu.address.ui;
+package seedu.medmoriser.ui;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import javafx.scene.layout.Region;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.logic.commands.CommandResult;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
/**
* The UI component that is responsible for receiving user command inputs.
@@ -72,7 +72,7 @@ public interface CommandExecutor {
/**
* Executes the command and returns the result.
*
- * @see seedu.address.logic.Logic#execute(String)
+ * @see seedu.medmoriser.logic.Logic#execute(String)
*/
CommandResult execute(String commandText) throws CommandException, ParseException;
}
diff --git a/src/main/java/seedu/address/ui/HelpWindow.java b/src/main/java/seedu/medmoriser/ui/HelpWindow.java
similarity index 92%
rename from src/main/java/seedu/address/ui/HelpWindow.java
rename to src/main/java/seedu/medmoriser/ui/HelpWindow.java
index 9a665915949..0e933813d9c 100644
--- a/src/main/java/seedu/address/ui/HelpWindow.java
+++ b/src/main/java/seedu/medmoriser/ui/HelpWindow.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.medmoriser.ui;
import java.util.logging.Logger;
@@ -8,14 +8,14 @@
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.stage.Stage;
-import seedu.address.commons.core.LogsCenter;
+import seedu.medmoriser.commons.core.LogsCenter;
/**
* Controller for a help page
*/
public class HelpWindow extends UiPart {
- public static final String USERGUIDE_URL = "https://se-education.org/addressbook-level3/UserGuide.html";
+ public static final String USERGUIDE_URL = "https://ay2021s1-cs2103t-w15-1.github.io/tp/UserGuide.html";
public static final String HELP_MESSAGE = "Refer to the user guide: " + USERGUIDE_URL;
private static final Logger logger = LogsCenter.getLogger(HelpWindow.class);
diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/medmoriser/ui/MainWindow.java
similarity index 83%
rename from src/main/java/seedu/address/ui/MainWindow.java
rename to src/main/java/seedu/medmoriser/ui/MainWindow.java
index 9106c3aa6e5..5e181a22c1c 100644
--- a/src/main/java/seedu/address/ui/MainWindow.java
+++ b/src/main/java/seedu/medmoriser/ui/MainWindow.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.medmoriser.ui;
import java.util.logging.Logger;
@@ -10,12 +10,12 @@
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.logic.Logic;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.commons.core.GuiSettings;
+import seedu.medmoriser.commons.core.LogsCenter;
+import seedu.medmoriser.logic.Logic;
+import seedu.medmoriser.logic.commands.CommandResult;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
/**
* The Main Window. Provides the basic application layout containing
@@ -31,7 +31,7 @@ public class MainWindow extends UiPart {
private Logic logic;
// Independent Ui parts residing in this Ui container
- private PersonListPanel personListPanel;
+ private QuestionSetListPanel questionSetListPanel;
private ResultDisplay resultDisplay;
private HelpWindow helpWindow;
@@ -42,7 +42,7 @@ public class MainWindow extends UiPart {
private MenuItem helpMenuItem;
@FXML
- private StackPane personListPanelPlaceholder;
+ private StackPane questionSetListPanelPlaceholder;
@FXML
private StackPane resultDisplayPlaceholder;
@@ -63,8 +63,6 @@ public MainWindow(Stage primaryStage, Logic logic) {
// Configure the UI
setWindowDefaultSize(logic.getGuiSettings());
- setAccelerators();
-
helpWindow = new HelpWindow();
}
@@ -72,9 +70,6 @@ public Stage getPrimaryStage() {
return primaryStage;
}
- private void setAccelerators() {
- setAccelerator(helpMenuItem, KeyCombination.valueOf("F1"));
- }
/**
* Sets the accelerator of a MenuItem.
@@ -110,15 +105,12 @@ private void setAccelerator(MenuItem menuItem, KeyCombination keyCombination) {
* Fills up all the placeholders of this window.
*/
void fillInnerParts() {
- personListPanel = new PersonListPanel(logic.getFilteredPersonList());
- personListPanelPlaceholder.getChildren().add(personListPanel.getRoot());
+ questionSetListPanel = new QuestionSetListPanel(logic.getFilteredQAndAList());
+ questionSetListPanelPlaceholder.getChildren().add(questionSetListPanel.getRoot());
resultDisplay = new ResultDisplay();
resultDisplayPlaceholder.getChildren().add(resultDisplay.getRoot());
- StatusBarFooter statusBarFooter = new StatusBarFooter(logic.getAddressBookFilePath());
- statusbarPlaceholder.getChildren().add(statusBarFooter.getRoot());
-
CommandBox commandBox = new CommandBox(this::executeCommand);
commandBoxPlaceholder.getChildren().add(commandBox.getRoot());
}
@@ -135,6 +127,14 @@ private void setWindowDefaultSize(GuiSettings guiSettings) {
}
}
+ /**
+ * Shows/hides the answers.
+ */
+ @FXML
+ public void handleList(boolean isAnswerDisplayed) {
+ questionSetListPanel.setAnswerView(isAnswerDisplayed);
+ }
+
/**
* Opens the help window or focuses on it if it's already opened.
*/
@@ -163,18 +163,19 @@ private void handleExit() {
primaryStage.hide();
}
- public PersonListPanel getPersonListPanel() {
- return personListPanel;
+ public QuestionSetListPanel getQuestionSetListPanel() {
+ return questionSetListPanel;
}
/**
* Executes the command and returns the result.
*
- * @see seedu.address.logic.Logic#execute(String)
+ * @see seedu.medmoriser.logic.Logic#execute(String)
*/
private CommandResult executeCommand(String commandText) throws CommandException, ParseException {
try {
CommandResult commandResult = logic.execute(commandText);
+ handleList(commandResult.isAnswerDisplayed());
logger.info("Result: " + commandResult.getFeedbackToUser());
resultDisplay.setFeedbackToUser(commandResult.getFeedbackToUser());
diff --git a/src/main/java/seedu/medmoriser/ui/QuestionSetCard.java b/src/main/java/seedu/medmoriser/ui/QuestionSetCard.java
new file mode 100644
index 00000000000..63ee2ada4a4
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/ui/QuestionSetCard.java
@@ -0,0 +1,85 @@
+package seedu.medmoriser.ui;
+
+import java.util.Comparator;
+
+import javafx.fxml.FXML;
+import javafx.scene.control.Label;
+import javafx.scene.layout.FlowPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Region;
+import seedu.medmoriser.model.qanda.QAndA;
+
+/**
+ * An UI component that displays information of a {@code QuestionSet}.
+ */
+public class QuestionSetCard extends UiPart {
+
+ private static final String FXML = "QuestionSetListCard.fxml";
+
+ /**
+ * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX.
+ * As a consequence, UI elements' variable names cannot be set to such keywords
+ * or an exception will be thrown by JavaFX during runtime.
+ *
+ * @see The issue on AddressBook level 4
+ */
+
+ public final QAndA qAndA;
+
+ @FXML
+ private HBox cardPane;
+ @FXML
+ private Label question;
+ @FXML
+ private Label id;
+ @FXML
+ private Label answer;
+ @FXML
+ private FlowPane tags;
+
+ /**
+ * Creates a {@code QuestionSetCode} with the given {@code QuestionSet} and index to display.
+ */
+ public QuestionSetCard(QAndA qAndA, int displayedIndex, boolean isAnswerDisplayed) {
+ super(FXML);
+ this.qAndA = qAndA;
+ id.setText(displayedIndex + ". ");
+ question.setText(qAndA.getQuestion().question);
+ answer.setText(qAndA.getAnswer().answer);
+ qAndA.getTags().stream()
+ .sorted(Comparator.comparing(tag -> tag.tagName))
+ .forEach(tag -> {
+ Label tagName = new Label(tag.tagName);
+ tagName.setMaxWidth(680);
+ tagName.setMaxHeight(Double.NEGATIVE_INFINITY);
+ tagName.setMinHeight(Double.NEGATIVE_INFINITY);
+ tagName.setWrapText(true);
+ tags.getChildren().add(tagName); }
+ );
+ if (!isAnswerDisplayed) {
+ hideAnswer();
+ }
+ }
+
+ public void hideAnswer() {
+ this.answer.setVisible(false);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof QuestionSetCard)) {
+ return false;
+ }
+
+ // state check
+ QuestionSetCard card = (QuestionSetCard) other;
+ return id.getText().equals(card.id.getText())
+ && qAndA.equals(card.qAndA);
+ }
+}
diff --git a/src/main/java/seedu/medmoriser/ui/QuestionSetListPanel.java b/src/main/java/seedu/medmoriser/ui/QuestionSetListPanel.java
new file mode 100644
index 00000000000..74c4836bc3e
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/ui/QuestionSetListPanel.java
@@ -0,0 +1,82 @@
+package seedu.medmoriser.ui;
+
+import java.util.logging.Logger;
+
+import javafx.collections.ObservableList;
+import javafx.fxml.FXML;
+import javafx.scene.control.ListCell;
+import javafx.scene.control.ListView;
+import javafx.scene.layout.Region;
+import seedu.medmoriser.commons.core.LogsCenter;
+import seedu.medmoriser.model.qanda.QAndA;
+
+/**
+ * Panel containing the list of questionSet.
+ */
+public class QuestionSetListPanel extends UiPart {
+ private static final String FXML = "QuestionSetListPanel.fxml";
+ private final Logger logger = LogsCenter.getLogger(QuestionSetListPanel.class);
+
+ @FXML
+ private ListView questionSetListView;
+
+ /**
+ * Creates a {@code QuestionSetListPanel} with the given {@code ObservableList}.
+ */
+ public QuestionSetListPanel(ObservableList qAndAList) {
+ super(FXML);
+ questionSetListView.setItems(qAndAList);
+ questionSetListView.setCellFactory(listView -> new QAndAListViewCell());
+ }
+
+ public void setAnswerView(boolean isAnswerDisplayed) {
+ assert questionSetListView != null;
+ questionSetListView.setCellFactory(listView -> {
+ QAndAListViewCell temp = new QAndAListViewCell();
+ temp.setAnswerDisplayed(isAnswerDisplayed);
+ return temp;
+ });
+ }
+
+ /**
+ * Custom {@code ListCell} that displays the graphics of a {@code QuestionSet} using a {@code QuestionSetCard}.
+ */
+ public class QAndAListViewCell extends ListCell {
+ private boolean isAnswerDisplayed;
+
+ /**
+ * Constructor
+ */
+ public QAndAListViewCell() {
+ super();
+ this.isAnswerDisplayed = true;
+ }
+
+ public void setAnswerDisplayed(boolean isAnswerDisplayed) {
+ this.isAnswerDisplayed = isAnswerDisplayed;
+ }
+
+ @Override
+ protected void updateItem(QAndA qAndA, boolean empty) {
+ super.updateItem(qAndA, empty);
+
+ if (empty || qAndA == null) {
+ setGraphic(null);
+ setText(null);
+ } else {
+ if (qAndA.getIsQuiz()) {
+ if (qAndA.getIsQuizAnswer()) {
+ setGraphic(new QuizCard(qAndA, getIndex() + 1, true).getRoot());
+ } else {
+ setGraphic(new QuizCard(qAndA, getIndex() + 1, false).getRoot());
+ }
+ } else if (isAnswerDisplayed) {
+ setGraphic(new QuestionSetCard(qAndA, getIndex() + 1, true).getRoot());
+ } else {
+ setGraphic(new QuestionSetCard(qAndA, getIndex() + 1, false).getRoot());
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/medmoriser/ui/QuizCard.java b/src/main/java/seedu/medmoriser/ui/QuizCard.java
new file mode 100644
index 00000000000..90c9350e21b
--- /dev/null
+++ b/src/main/java/seedu/medmoriser/ui/QuizCard.java
@@ -0,0 +1,85 @@
+package seedu.medmoriser.ui;
+
+import java.util.Comparator;
+
+import javafx.fxml.FXML;
+import javafx.scene.control.Label;
+import javafx.scene.layout.FlowPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Region;
+import seedu.medmoriser.model.qanda.QAndA;
+
+public class QuizCard extends UiPart {
+ private static final String FXML = "QuizCard.fxml";
+
+ /**
+ * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX.
+ * As a consequence, UI elements' variable names cannot be set to such keywords
+ * or an exception will be thrown by JavaFX during runtime.
+ *
+ * @see The issue on AddressBook level 4
+ */
+
+ public final QAndA qAndA;
+
+ @FXML
+ private HBox cardPane;
+ @FXML
+ private Label question;
+ @FXML
+ private Label id;
+ @FXML
+ private Label answer;
+ @FXML
+ private FlowPane tags;
+
+ /**
+ * Creates a {@code QuestionSetCode} with the given {@code QuestionSet} and index to display.
+ */
+ public QuizCard(QAndA qAndA, int displayedIndex, boolean isAnswerDisplayed) {
+ super(FXML);
+ this.qAndA = qAndA;
+ id.setText("");
+ question.setText(qAndA.getQuestion().question);
+ answer.setText(qAndA.getAnswer().answer);
+ qAndA.getTags().stream()
+ .sorted(Comparator.comparing(tag -> tag.tagName))
+ .forEach(tag -> {
+ Label tagName = new Label(tag.tagName);
+ tagName.setMaxWidth(680);
+ tagName.setMaxHeight(Double.NEGATIVE_INFINITY);
+ tagName.setMinHeight(Double.NEGATIVE_INFINITY);
+ tagName.setWrapText(true);
+ tags.getChildren().add(tagName); }
+ );
+ if (!isAnswerDisplayed) {
+ hideAnswer();
+ }
+ }
+
+ /***
+ * Hide answer for Quiz Card
+ */
+ public void hideAnswer() {
+ this.answer.setVisible(false);
+ answer.setPrefSize(0, 0);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof QuestionSetCard)) {
+ return false;
+ }
+
+ // state check
+ QuizCard card = (QuizCard) other;
+ return id.getText().equals(card.id.getText())
+ && qAndA.equals(card.qAndA);
+ }
+}
diff --git a/src/main/java/seedu/address/ui/ResultDisplay.java b/src/main/java/seedu/medmoriser/ui/ResultDisplay.java
similarity index 95%
rename from src/main/java/seedu/address/ui/ResultDisplay.java
rename to src/main/java/seedu/medmoriser/ui/ResultDisplay.java
index 7d98e84eedf..a73e8ce4d15 100644
--- a/src/main/java/seedu/address/ui/ResultDisplay.java
+++ b/src/main/java/seedu/medmoriser/ui/ResultDisplay.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.medmoriser.ui;
import static java.util.Objects.requireNonNull;
diff --git a/src/main/java/seedu/address/ui/StatusBarFooter.java b/src/main/java/seedu/medmoriser/ui/StatusBarFooter.java
similarity index 95%
rename from src/main/java/seedu/address/ui/StatusBarFooter.java
rename to src/main/java/seedu/medmoriser/ui/StatusBarFooter.java
index b577f829423..dfb0fb09d77 100644
--- a/src/main/java/seedu/address/ui/StatusBarFooter.java
+++ b/src/main/java/seedu/medmoriser/ui/StatusBarFooter.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.medmoriser.ui;
import java.nio.file.Path;
import java.nio.file.Paths;
diff --git a/src/main/java/seedu/address/ui/Ui.java b/src/main/java/seedu/medmoriser/ui/Ui.java
similarity index 84%
rename from src/main/java/seedu/address/ui/Ui.java
rename to src/main/java/seedu/medmoriser/ui/Ui.java
index 17aa0b494fe..a031fe76c63 100644
--- a/src/main/java/seedu/address/ui/Ui.java
+++ b/src/main/java/seedu/medmoriser/ui/Ui.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.medmoriser.ui;
import javafx.stage.Stage;
diff --git a/src/main/java/seedu/address/ui/UiManager.java b/src/main/java/seedu/medmoriser/ui/UiManager.java
similarity index 91%
rename from src/main/java/seedu/address/ui/UiManager.java
rename to src/main/java/seedu/medmoriser/ui/UiManager.java
index 882027e4537..640236ef07e 100644
--- a/src/main/java/seedu/address/ui/UiManager.java
+++ b/src/main/java/seedu/medmoriser/ui/UiManager.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.medmoriser.ui;
import java.util.logging.Logger;
@@ -7,10 +7,10 @@
import javafx.scene.control.Alert.AlertType;
import javafx.scene.image.Image;
import javafx.stage.Stage;
-import seedu.address.MainApp;
-import seedu.address.commons.core.LogsCenter;
-import seedu.address.commons.util.StringUtil;
-import seedu.address.logic.Logic;
+import seedu.medmoriser.MainApp;
+import seedu.medmoriser.commons.core.LogsCenter;
+import seedu.medmoriser.commons.util.StringUtil;
+import seedu.medmoriser.logic.Logic;
/**
* The manager of the UI component.
@@ -20,7 +20,7 @@ public class UiManager implements Ui {
public static final String ALERT_DIALOG_PANE_FIELD_ID = "alertDialogPane";
private static final Logger logger = LogsCenter.getLogger(UiManager.class);
- private static final String ICON_APPLICATION = "/images/address_book_32.png";
+ private static final String ICON_APPLICATION = "/images/healthemoticon.png";
private Logic logic;
private MainWindow mainWindow;
diff --git a/src/main/java/seedu/address/ui/UiPart.java b/src/main/java/seedu/medmoriser/ui/UiPart.java
similarity index 97%
rename from src/main/java/seedu/address/ui/UiPart.java
rename to src/main/java/seedu/medmoriser/ui/UiPart.java
index fc820e01a9c..da4f365e7d0 100644
--- a/src/main/java/seedu/address/ui/UiPart.java
+++ b/src/main/java/seedu/medmoriser/ui/UiPart.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.medmoriser.ui;
import static java.util.Objects.requireNonNull;
@@ -6,7 +6,7 @@
import java.net.URL;
import javafx.fxml.FXMLLoader;
-import seedu.address.MainApp;
+import seedu.medmoriser.MainApp;
/**
* Represents a distinct part of the UI. e.g. Windows, dialogs, panels, status bars, etc.
diff --git a/src/main/resources/images/healthemoticon.png b/src/main/resources/images/healthemoticon.png
new file mode 100644
index 00000000000..82187bc305f
Binary files /dev/null and b/src/main/resources/images/healthemoticon.png differ
diff --git a/src/main/resources/view/CommandBox.fxml b/src/main/resources/view/CommandBox.fxml
index 09f6d6fe9e4..125cb6cc992 100644
--- a/src/main/resources/view/CommandBox.fxml
+++ b/src/main/resources/view/CommandBox.fxml
@@ -1,9 +1,8 @@
-
-
+
+
-
-
+
+
-
diff --git a/src/main/resources/view/DarkTheme.css b/src/main/resources/view/DarkTheme.css
index 36e6b001cd8..0e2369b6e41 100644
--- a/src/main/resources/view/DarkTheme.css
+++ b/src/main/resources/view/DarkTheme.css
@@ -1,26 +1,26 @@
.background {
- -fx-background-color: derive(#1d1d1d, 20%);
- background-color: #383838; /* Used in the default.html file */
+ -fx-background-color: derive(#56575c, 20%);
+ background-color: #78797d; /* Used in the default.html file */
}
.label {
-fx-font-size: 11pt;
-fx-font-family: "Segoe UI Semibold";
- -fx-text-fill: #555555;
+ -fx-text-fill: black;
-fx-opacity: 0.9;
}
.label-bright {
-fx-font-size: 11pt;
-fx-font-family: "Segoe UI Semibold";
- -fx-text-fill: white;
+ -fx-text-fill: black;
-fx-opacity: 1;
}
.label-header {
-fx-font-size: 32pt;
-fx-font-family: "Segoe UI Light";
- -fx-text-fill: white;
+ -fx-text-fill: black;
-fx-opacity: 1;
}
@@ -40,22 +40,24 @@
}
.table-view {
- -fx-base: #1d1d1d;
- -fx-control-inner-background: #1d1d1d;
- -fx-background-color: #1d1d1d;
+ -fx-base: #56575c;
+ -fx-control-inner-background: #56575c;
+ -fx-background-color: #56575c;
+ -fx-background-radius: 0;
-fx-table-cell-border-color: transparent;
-fx-table-header-border-color: transparent;
-fx-padding: 5;
}
.table-view .column-header-background {
- -fx-background-color: transparent;
+ -fx-background-color: #78797d;
+ -fx-background-radius: 0;
}
.table-view .column-header, .table-view .filler {
-fx-size: 35;
-fx-border-width: 0 0 1 0;
- -fx-background-color: transparent;
+ -fx-background-color: #78797d;
-fx-border-color:
transparent
transparent
@@ -73,84 +75,105 @@
}
.table-view:focused .table-row-cell:filled:focused:selected {
- -fx-background-color: -fx-focus-color;
+ -fx-background-color: #78797d;
}
.split-pane:horizontal .split-pane-divider {
- -fx-background-color: derive(#1d1d1d, 20%);
+ -fx-background-color: derive(#78797d, 20%);
-fx-border-color: transparent transparent transparent #4d4d4d;
}
.split-pane {
-fx-border-radius: 1;
-fx-border-width: 1;
- -fx-background-color: derive(#1d1d1d, 20%);
+ -fx-background-color: derive(#78797d, 20%);
}
.list-view {
-fx-background-insets: 0;
-fx-padding: 0;
- -fx-background-color: derive(#1d1d1d, 20%);
+ -fx-background-color: derive(#78797d, 20%);
}
.list-cell {
-fx-label-padding: 0 0 0 0;
-fx-graphic-text-gap : 0;
-fx-padding: 0 0 0 0;
+ -fx-background-radius: 5;
}
.list-cell:filled:even {
- -fx-background-color: #3c3e3f;
+ -fx-background-color: #2c2d33;
}
.list-cell:filled:odd {
- -fx-background-color: #515658;
+ -fx-background-color: #56575c;
}
.list-cell:filled:selected {
- -fx-background-color: #424d5f;
+ -fx-background-color: black;
}
.list-cell:filled:selected #cardPane {
- -fx-border-color: #3e7b91;
+ -fx-border-color: #7bded3;
+ -fx-border-radius: 5;
-fx-border-width: 1;
}
.list-cell .label {
- -fx-text-fill: white;
}
.cell_big_label {
-fx-font-family: "Segoe UI Semibold";
-fx-font-size: 16px;
- -fx-text-fill: #010504;
+ -fx-text-fill: #bbbcbe;
}
.cell_small_label {
-fx-font-family: "Segoe UI";
-fx-font-size: 13px;
- -fx-text-fill: #010504;
+ -fx-text-fill: #bbbcbe;
+}
+
+.quiz_big_label {
+ -fx-font-family: "Segoe UI Semibold";
+ -fx-font-size: 30px;
+ -fx-text-fill: #bbbcbe;
+ -fx-translate-y: 5px;
+}
+
+.quiz_small_label {
+ -fx-font-family: "Segoe UI";
+ -fx-font-size: 25px;
+ -fx-text-fill: white;
+ -fx-padding: 10px;
+ -fx-background-color: #4B5F6B;
+ -fx-background-radius: 15px;
+ -fx-translate-y: 20px;
}
.stack-pane {
- -fx-background-color: derive(#1d1d1d, 20%);
+ -fx-background-color: derive(#56575c, 20%);
}
.pane-with-border {
- -fx-background-color: derive(#1d1d1d, 20%);
- -fx-border-color: derive(#1d1d1d, 10%);
- -fx-border-top-width: 1px;
+ -fx-background-color: #56575c;
+ -fx-border-color: derive(transparent, 10%);
+ -fx-border-top-width: 0px;
+ -fx-border-radius: 5px;
}
.status-bar {
- -fx-background-color: derive(#1d1d1d, 30%);
+ -fx-background-color: derive(#56575c, 30%);
}
.result-display {
- -fx-background-color: transparent;
+ -fx-background-color: #78797d;
-fx-font-family: "Segoe UI Light";
-fx-font-size: 13pt;
-fx-text-fill: white;
+ -fx-border-width: 0px;
+
}
.result-display .label {
@@ -166,26 +189,28 @@
.status-bar-with-border {
-fx-background-color: derive(#1d1d1d, 30%);
- -fx-border-color: derive(#1d1d1d, 25%);
- -fx-border-width: 1px;
+ -fx-border-color: derive(transparent, 25%);
+ -fx-border-width: 0px;
}
.status-bar-with-border .label {
- -fx-text-fill: white;
+ -fx-text-fill: black;
}
.grid-pane {
- -fx-background-color: derive(#1d1d1d, 30%);
- -fx-border-color: derive(#1d1d1d, 30%);
- -fx-border-width: 1px;
+ -fx-background-color: derive(#56575c, 30%);
+ -fx-border-color: derive(#56575c, 30%);
+ -fx-border-width: 0px;
}
.grid-pane .stack-pane {
- -fx-background-color: derive(#1d1d1d, 30%);
+ -fx-background-color: derive(#56575c, 30%);
+ -fx-border-width: 0px;
}
.context-menu {
- -fx-background-color: derive(#1d1d1d, 50%);
+ -fx-background-color: derive(#56575c, 50%);
+ -fx-border-width: 0px;
}
.context-menu .label {
@@ -193,7 +218,7 @@
}
.menu-bar {
- -fx-background-color: derive(#1d1d1d, 20%);
+ -fx-background-color: derive(#2c2d33, 20%);
}
.menu-bar .label {
@@ -204,7 +229,7 @@
}
.menu .left-container {
- -fx-background-color: black;
+ -fx-background-color: #56575c;
}
/*
@@ -216,7 +241,7 @@
-fx-padding: 5 22 5 22;
-fx-border-color: #e2e2e2;
-fx-border-width: 2;
- -fx-background-radius: 0;
+ -fx-background-radius: 5;
-fx-background-color: #1d1d1d;
-fx-font-family: "Segoe UI", Helvetica, Arial, sans-serif;
-fx-font-size: 11pt;
@@ -225,12 +250,12 @@
}
.button:hover {
- -fx-background-color: #3a3a3a;
+ -fx-background-color: #7bded3;
}
.button:pressed, .button:default:hover:pressed {
- -fx-background-color: white;
- -fx-text-fill: #1d1d1d;
+ -fx-background-color: #7bded3;
+ -fx-text-fill: #7bded3;
}
.button:focused {
@@ -258,20 +283,24 @@
.dialog-pane {
-fx-background-color: #1d1d1d;
+ -fx-border-width: 0px;
}
.dialog-pane > *.button-bar > *.container {
-fx-background-color: #1d1d1d;
+ -fx-border-width: 0px;
}
.dialog-pane > *.label.content {
-fx-font-size: 14px;
-fx-font-weight: bold;
-fx-text-fill: white;
+ -fx-border-width: 0px;
}
.dialog-pane:header *.header-panel {
-fx-background-color: derive(#1d1d1d, 25%);
+ -fx-border-width: 0px;
}
.dialog-pane:header *.header-panel *.label {
@@ -279,15 +308,17 @@
-fx-font-style: italic;
-fx-fill: white;
-fx-text-fill: white;
+ -fx-border-width: 0px;
}
.scroll-bar {
- -fx-background-color: derive(#1d1d1d, 20%);
+ -fx-background-color: derive(#d3d3d5, 20%);
}
.scroll-bar .thumb {
- -fx-background-color: derive(#1d1d1d, 50%);
+ -fx-background-color: derive(#56575c, 50%);
-fx-background-insets: 3;
+ -fx-background-radius: 15px
}
.scroll-bar .increment-button, .scroll-bar .decrement-button {
@@ -318,14 +349,15 @@
}
#commandTextField {
- -fx-background-color: transparent #383838 transparent #383838;
+ -fx-background-color: #28292b #28292b #28292b #28292b;
-fx-background-insets: 0;
- -fx-border-color: #383838 #383838 #ffffff #383838;
+ -fx-border-color: transparent, transparent, transparent, transparent;
+ -fx-background-radius: 5;
-fx-border-insets: 0;
- -fx-border-width: 1;
+ -fx-border-width: 0;
-fx-font-family: "Segoe UI Light";
-fx-font-size: 13pt;
- -fx-text-fill: white;
+ -fx-text-fill: #bbbcbe;
}
#filterField, #personListPanel, #personWebpage {
@@ -333,8 +365,8 @@
}
#resultDisplay .content {
- -fx-background-color: transparent, #383838, transparent, #383838;
- -fx-background-radius: 0;
+ -fx-background-color: #2c2d33;
+ -fx-border-color: #2c2d33;
}
#tags {
@@ -343,10 +375,13 @@
}
#tags .label {
- -fx-text-fill: white;
- -fx-background-color: #3e7b91;
+ -fx-text-fill: #2c2d33;
+ -fx-font-family: "Segoe UI Semibold";
+ -fx-background-color: #7bded3;
-fx-padding: 1 3 1 3;
- -fx-border-radius: 2;
- -fx-background-radius: 2;
- -fx-font-size: 11;
+ -fx-border-radius: 5;
+ -fx-background-radius: 6;
+ -fx-font-size: 13;
+ -fx-border-color: #7bded3;
+ -fx-border-width: 1px;
}
diff --git a/src/main/resources/view/Extensions.css b/src/main/resources/view/Extensions.css
index bfe82a85964..ddb05dd3d50 100644
--- a/src/main/resources/view/Extensions.css
+++ b/src/main/resources/view/Extensions.css
@@ -5,7 +5,8 @@
.list-cell:empty {
/* Empty cells will not have alternating colours */
- -fx-background: #383838;
+ -fx-background: #78797d;
+ -fx-background-radius: 0;
}
.tag-selector {
@@ -16,5 +17,5 @@
}
.tooltip-text {
- -fx-text-fill: white;
+ -fx-text-fill: black;
}
diff --git a/src/main/resources/view/HelpWindow.fxml b/src/main/resources/view/HelpWindow.fxml
index fa0fb54d9f4..dccba9ccabb 100644
--- a/src/main/resources/view/HelpWindow.fxml
+++ b/src/main/resources/view/HelpWindow.fxml
@@ -1,14 +1,13 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
-
+
diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml
index a431648f6c0..e49c69ee0d8 100644
--- a/src/main/resources/view/MainWindow.fxml
+++ b/src/main/resources/view/MainWindow.fxml
@@ -1,29 +1,25 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
-
+
-
+
-
+
-
+
-
-
+
-
+
diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/PersonListCard.fxml
deleted file mode 100644
index f08ea32ad55..00000000000
--- a/src/main/resources/view/PersonListCard.fxml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/main/resources/view/PersonListPanel.fxml b/src/main/resources/view/PersonListPanel.fxml
deleted file mode 100644
index 8836d323cc5..00000000000
--- a/src/main/resources/view/PersonListPanel.fxml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/src/main/resources/view/QuestionSetListCard.fxml b/src/main/resources/view/QuestionSetListCard.fxml
new file mode 100644
index 00000000000..44f3b4fd12f
--- /dev/null
+++ b/src/main/resources/view/QuestionSetListCard.fxml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/view/QuestionSetListPanel.fxml b/src/main/resources/view/QuestionSetListPanel.fxml
new file mode 100644
index 00000000000..294095025f9
--- /dev/null
+++ b/src/main/resources/view/QuestionSetListPanel.fxml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/view/QuizCard.fxml b/src/main/resources/view/QuizCard.fxml
new file mode 100644
index 00000000000..de8fbac7021
--- /dev/null
+++ b/src/main/resources/view/QuizCard.fxml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/view/ResultDisplay.fxml b/src/main/resources/view/ResultDisplay.fxml
index 58d5ad3dc56..4cf888d4e59 100644
--- a/src/main/resources/view/ResultDisplay.fxml
+++ b/src/main/resources/view/ResultDisplay.fxml
@@ -1,9 +1,8 @@
-
-
+
+
-
-
+
+
diff --git a/src/main/resources/view/StatusBarFooter.fxml b/src/main/resources/view/StatusBarFooter.fxml
index 149f62bd29c..2c47763cbd6 100644
--- a/src/main/resources/view/StatusBarFooter.fxml
+++ b/src/main/resources/view/StatusBarFooter.fxml
@@ -1,12 +1,14 @@
-
-
-
+
+
-
+
+
+
+
diff --git a/src/preferences.json b/src/preferences.json
new file mode 100644
index 00000000000..cd3cf0f878a
--- /dev/null
+++ b/src/preferences.json
@@ -0,0 +1,11 @@
+{
+ "guiSettings" : {
+ "windowWidth" : 740.0,
+ "windowHeight" : 600.0,
+ "windowCoordinates" : {
+ "x" : 270,
+ "y" : 82
+ }
+ },
+ "medmoriserFilePath" : "data/medmoriser.json"
+}
diff --git a/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json b/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json
deleted file mode 100644
index 6a4d2b7181c..00000000000
--- a/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "persons": [ {
- "name": "Valid Person",
- "phone": "9482424",
- "email": "hans@example.com",
- "address": "4th street"
- }, {
- "name": "Person With Invalid Phone Field",
- "phone": "948asdf2424",
- "email": "hans@example.com",
- "address": "4th street"
- } ]
-}
diff --git a/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json b/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json
deleted file mode 100644
index ccd21f7d1a9..00000000000
--- a/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "persons": [ {
- "name": "Person with invalid name field: Ha!ns Mu@ster",
- "phone": "9482424",
- "email": "hans@example.com",
- "address": "4th street"
- } ]
-}
diff --git a/src/test/data/JsonMedmoriserStorageTest/invalidAndValidQAndAMedmoriser.json b/src/test/data/JsonMedmoriserStorageTest/invalidAndValidQAndAMedmoriser.json
new file mode 100644
index 00000000000..00bcd9b8f23
--- /dev/null
+++ b/src/test/data/JsonMedmoriserStorageTest/invalidAndValidQAndAMedmoriser.json
@@ -0,0 +1,9 @@
+{
+ "qAndAs": [ {
+ "question": "Valid QuestionSet",
+ "answer": "Valid Answer"
+ }, {
+ "question": "QuestionSet With Invalid answer Field",
+ "answer": ""
+ } ]
+}
diff --git a/src/test/data/JsonMedmoriserStorageTest/invalidQAndAMedmoriser.json b/src/test/data/JsonMedmoriserStorageTest/invalidQAndAMedmoriser.json
new file mode 100644
index 00000000000..01550313377
--- /dev/null
+++ b/src/test/data/JsonMedmoriserStorageTest/invalidQAndAMedmoriser.json
@@ -0,0 +1,6 @@
+{
+ "qAndAs": [ {
+ "question": " ",
+ "answer": "pump blood"
+ } ]
+}
diff --git a/src/test/data/JsonAddressBookStorageTest/notJsonFormatAddressBook.json b/src/test/data/JsonMedmoriserStorageTest/notJsonFormatMedmoriser.json
similarity index 100%
rename from src/test/data/JsonAddressBookStorageTest/notJsonFormatAddressBook.json
rename to src/test/data/JsonMedmoriserStorageTest/notJsonFormatMedmoriser.json
diff --git a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json
deleted file mode 100644
index 48831cc7674..00000000000
--- a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "persons": [ {
- "name": "Alice Pauline",
- "phone": "94351253",
- "email": "alice@example.com",
- "address": "123, Jurong West Ave 6, #08-111",
- "tagged": [ "friends" ]
- }, {
- "name": "Alice Pauline",
- "phone": "94351253",
- "email": "pauline@example.com",
- "address": "4th street"
- } ]
-}
diff --git a/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json
deleted file mode 100644
index ad3f135ae42..00000000000
--- a/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "persons": [ {
- "name": "Hans Muster",
- "phone": "9482424",
- "email": "invalid@email!3e",
- "address": "4th street"
- } ]
-}
diff --git a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json
deleted file mode 100644
index f10eddee12e..00000000000
--- a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "_comment": "AddressBook save file which contains the same Person values as in TypicalPersons#getTypicalAddressBook()",
- "persons" : [ {
- "name" : "Alice Pauline",
- "phone" : "94351253",
- "email" : "alice@example.com",
- "address" : "123, Jurong West Ave 6, #08-111",
- "tagged" : [ "friends" ]
- }, {
- "name" : "Benson Meier",
- "phone" : "98765432",
- "email" : "johnd@example.com",
- "address" : "311, Clementi Ave 2, #02-25",
- "tagged" : [ "owesMoney", "friends" ]
- }, {
- "name" : "Carl Kurz",
- "phone" : "95352563",
- "email" : "heinz@example.com",
- "address" : "wall street",
- "tagged" : [ ]
- }, {
- "name" : "Daniel Meier",
- "phone" : "87652533",
- "email" : "cornelia@example.com",
- "address" : "10th street",
- "tagged" : [ "friends" ]
- }, {
- "name" : "Elle Meyer",
- "phone" : "9482224",
- "email" : "werner@example.com",
- "address" : "michegan ave",
- "tagged" : [ ]
- }, {
- "name" : "Fiona Kunz",
- "phone" : "9482427",
- "email" : "lydia@example.com",
- "address" : "little tokyo",
- "tagged" : [ ]
- }, {
- "name" : "George Best",
- "phone" : "9482442",
- "email" : "anna@example.com",
- "address" : "4th street",
- "tagged" : [ ]
- } ]
-}
diff --git a/src/test/data/JsonSerializableMedmoriserTest/duplicateQAndAMedmoriser.json b/src/test/data/JsonSerializableMedmoriserTest/duplicateQAndAMedmoriser.json
new file mode 100644
index 00000000000..4f7262671e3
--- /dev/null
+++ b/src/test/data/JsonSerializableMedmoriserTest/duplicateQAndAMedmoriser.json
@@ -0,0 +1,10 @@
+{
+ "qAndAs": [ {
+ "question": "Question 1",
+ "answer": "Answer 1",
+ "tagged": [ "disease" ]
+ }, {
+ "question": "Question 1",
+ "answer": "Answer 1"
+ } ]
+}
diff --git a/src/test/data/JsonSerializableMedmoriserTest/invalidQAndAMedmoriser.json b/src/test/data/JsonSerializableMedmoriserTest/invalidQAndAMedmoriser.json
new file mode 100644
index 00000000000..717c01040bd
--- /dev/null
+++ b/src/test/data/JsonSerializableMedmoriserTest/invalidQAndAMedmoriser.json
@@ -0,0 +1,6 @@
+{
+ "qAndAs": [ {
+ "question": "",
+ "answer": "Answer"
+ } ]
+}
diff --git a/src/test/data/JsonSerializableMedmoriserTest/typicalQAndAsMedmoriser.json b/src/test/data/JsonSerializableMedmoriserTest/typicalQAndAsMedmoriser.json
new file mode 100644
index 00000000000..c7409bc525c
--- /dev/null
+++ b/src/test/data/JsonSerializableMedmoriserTest/typicalQAndAsMedmoriser.json
@@ -0,0 +1,32 @@
+{
+ "_comment": "AddressBook save file which contains the same QuestionSet values as in TypicalQuestionSets#getTypicalAddressBook()",
+ "qAndAs" : [ {
+ "question" : "Question One",
+ "answer" : "Answer 1",
+ "tagged" : [ "DNA" ]
+ }, {
+ "question" : "Question Two",
+ "answer" : "Answer 2",
+ "tagged" : [ "ImmuneSystem" ]
+ }, {
+ "question" : "Question Three",
+ "answer" : "Answer 3",
+ "tagged" : [ ]
+ }, {
+ "question" : "Question Four",
+ "answer" : "Answer 4",
+ "tagged" : [ ]
+ }, {
+ "question" : "Question Five",
+ "answer" : "Answer 5",
+ "tagged" : [ ]
+ }, {
+ "question" : "Question Six",
+ "answer" : "Answer 6",
+ "tagged" : [ ]
+ }, {
+ "question" : "Question Seven",
+ "answer" : "Answer 7",
+ "tagged" : [ ]
+ } ]
+}
diff --git a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java
deleted file mode 100644
index cb8714bb055..00000000000
--- a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package seedu.address.logic.commands;
-
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.person.Person;
-import seedu.address.testutil.PersonBuilder;
-
-/**
- * Contains integration tests (interaction with the Model) for {@code AddCommand}.
- */
-public class AddCommandIntegrationTest {
-
- private Model model;
-
- @BeforeEach
- public void setUp() {
- model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- }
-
- @Test
- public void execute_newPerson_success() {
- Person validPerson = new PersonBuilder().build();
-
- Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- expectedModel.addPerson(validPerson);
-
- assertCommandSuccess(new AddCommand(validPerson), model,
- String.format(AddCommand.MESSAGE_SUCCESS, validPerson), expectedModel);
- }
-
- @Test
- public void execute_duplicatePerson_throwsCommandException() {
- Person personInList = model.getAddressBook().getPersonList().get(0);
- assertCommandFailure(new AddCommand(personInList), model, AddCommand.MESSAGE_DUPLICATE_PERSON);
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java
deleted file mode 100644
index 5865713d5dd..00000000000
--- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java
+++ /dev/null
@@ -1,194 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.function.Predicate;
-
-import org.junit.jupiter.api.Test;
-
-import javafx.collections.ObservableList;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.ReadOnlyUserPrefs;
-import seedu.address.model.person.Person;
-import seedu.address.testutil.PersonBuilder;
-
-public class AddCommandTest {
-
- @Test
- public void constructor_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> new AddCommand(null));
- }
-
- @Test
- public void execute_personAcceptedByModel_addSuccessful() throws Exception {
- ModelStubAcceptingPersonAdded modelStub = new ModelStubAcceptingPersonAdded();
- Person validPerson = new PersonBuilder().build();
-
- CommandResult commandResult = new AddCommand(validPerson).execute(modelStub);
-
- assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, validPerson), commandResult.getFeedbackToUser());
- assertEquals(Arrays.asList(validPerson), modelStub.personsAdded);
- }
-
- @Test
- public void execute_duplicatePerson_throwsCommandException() {
- Person validPerson = new PersonBuilder().build();
- AddCommand addCommand = new AddCommand(validPerson);
- ModelStub modelStub = new ModelStubWithPerson(validPerson);
-
- assertThrows(CommandException.class, AddCommand.MESSAGE_DUPLICATE_PERSON, () -> addCommand.execute(modelStub));
- }
-
- @Test
- public void equals() {
- Person alice = new PersonBuilder().withName("Alice").build();
- Person bob = new PersonBuilder().withName("Bob").build();
- AddCommand addAliceCommand = new AddCommand(alice);
- AddCommand addBobCommand = new AddCommand(bob);
-
- // same object -> returns true
- assertTrue(addAliceCommand.equals(addAliceCommand));
-
- // same values -> returns true
- AddCommand addAliceCommandCopy = new AddCommand(alice);
- assertTrue(addAliceCommand.equals(addAliceCommandCopy));
-
- // different types -> returns false
- assertFalse(addAliceCommand.equals(1));
-
- // null -> returns false
- assertFalse(addAliceCommand.equals(null));
-
- // different person -> returns false
- assertFalse(addAliceCommand.equals(addBobCommand));
- }
-
- /**
- * A default model stub that have all of the methods failing.
- */
- private class ModelStub implements Model {
- @Override
- public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public ReadOnlyUserPrefs getUserPrefs() {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public GuiSettings getGuiSettings() {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public void setGuiSettings(GuiSettings guiSettings) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public Path getAddressBookFilePath() {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public void setAddressBookFilePath(Path addressBookFilePath) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public void addPerson(Person person) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public void setAddressBook(ReadOnlyAddressBook newData) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public ReadOnlyAddressBook getAddressBook() {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public boolean hasPerson(Person person) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public void deletePerson(Person target) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public void setPerson(Person target, Person editedPerson) {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public ObservableList getFilteredPersonList() {
- throw new AssertionError("This method should not be called.");
- }
-
- @Override
- public void updateFilteredPersonList(Predicate predicate) {
- throw new AssertionError("This method should not be called.");
- }
- }
-
- /**
- * A Model stub that contains a single person.
- */
- private class ModelStubWithPerson extends ModelStub {
- private final Person person;
-
- ModelStubWithPerson(Person person) {
- requireNonNull(person);
- this.person = person;
- }
-
- @Override
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return this.person.isSamePerson(person);
- }
- }
-
- /**
- * A Model stub that always accept the person being added.
- */
- private class ModelStubAcceptingPersonAdded extends ModelStub {
- final ArrayList personsAdded = new ArrayList<>();
-
- @Override
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return personsAdded.stream().anyMatch(person::isSamePerson);
- }
-
- @Override
- public void addPerson(Person person) {
- requireNonNull(person);
- personsAdded.add(person);
- }
-
- @Override
- public ReadOnlyAddressBook getAddressBook() {
- return new AddressBook();
- }
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java b/src/test/java/seedu/address/logic/commands/ClearCommandTest.java
deleted file mode 100644
index 80d9110c03a..00000000000
--- a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package seedu.address.logic.commands;
-
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-
-public class ClearCommandTest {
-
- @Test
- public void execute_emptyAddressBook_success() {
- Model model = new ModelManager();
- Model expectedModel = new ModelManager();
-
- assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel);
- }
-
- @Test
- public void execute_nonEmptyAddressBook_success() {
- Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- expectedModel.setAddressBook(new AddressBook());
-
- assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel);
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
deleted file mode 100644
index 643a1d08069..00000000000
--- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package seedu.address.logic.commands;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-import seedu.address.model.person.Person;
-import seedu.address.testutil.EditPersonDescriptorBuilder;
-
-/**
- * Contains helper methods for testing commands.
- */
-public class CommandTestUtil {
-
- public static final String VALID_NAME_AMY = "Amy Bee";
- public static final String VALID_NAME_BOB = "Bob Choo";
- public static final String VALID_PHONE_AMY = "11111111";
- public static final String VALID_PHONE_BOB = "22222222";
- public static final String VALID_EMAIL_AMY = "amy@example.com";
- public static final String VALID_EMAIL_BOB = "bob@example.com";
- public static final String VALID_ADDRESS_AMY = "Block 312, Amy Street 1";
- public static final String VALID_ADDRESS_BOB = "Block 123, Bobby Street 3";
- public static final String VALID_TAG_HUSBAND = "husband";
- public static final String VALID_TAG_FRIEND = "friend";
-
- public static final String NAME_DESC_AMY = " " + PREFIX_NAME + VALID_NAME_AMY;
- public static final String NAME_DESC_BOB = " " + PREFIX_NAME + VALID_NAME_BOB;
- public static final String PHONE_DESC_AMY = " " + PREFIX_PHONE + VALID_PHONE_AMY;
- public static final String PHONE_DESC_BOB = " " + PREFIX_PHONE + VALID_PHONE_BOB;
- public static final String EMAIL_DESC_AMY = " " + PREFIX_EMAIL + VALID_EMAIL_AMY;
- public static final String EMAIL_DESC_BOB = " " + PREFIX_EMAIL + VALID_EMAIL_BOB;
- public static final String ADDRESS_DESC_AMY = " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY;
- public static final String ADDRESS_DESC_BOB = " " + PREFIX_ADDRESS + VALID_ADDRESS_BOB;
- public static final String TAG_DESC_FRIEND = " " + PREFIX_TAG + VALID_TAG_FRIEND;
- public static final String TAG_DESC_HUSBAND = " " + PREFIX_TAG + VALID_TAG_HUSBAND;
-
- public static final String INVALID_NAME_DESC = " " + PREFIX_NAME + "James&"; // '&' not allowed in names
- public static final String INVALID_PHONE_DESC = " " + PREFIX_PHONE + "911a"; // 'a' not allowed in phones
- public static final String INVALID_EMAIL_DESC = " " + PREFIX_EMAIL + "bob!yahoo"; // missing '@' symbol
- public static final String INVALID_ADDRESS_DESC = " " + PREFIX_ADDRESS; // empty string not allowed for addresses
- public static final String INVALID_TAG_DESC = " " + PREFIX_TAG + "hubby*"; // '*' not allowed in tags
-
- public static final String PREAMBLE_WHITESPACE = "\t \r \n";
- public static final String PREAMBLE_NON_EMPTY = "NonEmptyPreamble";
-
- public static final EditCommand.EditPersonDescriptor DESC_AMY;
- public static final EditCommand.EditPersonDescriptor DESC_BOB;
-
- static {
- DESC_AMY = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY)
- .withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY)
- .withTags(VALID_TAG_FRIEND).build();
- DESC_BOB = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB)
- .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB)
- .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build();
- }
-
- /**
- * Executes the given {@code command}, confirms that
- * - the returned {@link CommandResult} matches {@code expectedCommandResult}
- * - the {@code actualModel} matches {@code expectedModel}
- */
- public static void assertCommandSuccess(Command command, Model actualModel, CommandResult expectedCommandResult,
- Model expectedModel) {
- try {
- CommandResult result = command.execute(actualModel);
- assertEquals(expectedCommandResult, result);
- assertEquals(expectedModel, actualModel);
- } catch (CommandException ce) {
- throw new AssertionError("Execution of command should not fail.", ce);
- }
- }
-
- /**
- * Convenience wrapper to {@link #assertCommandSuccess(Command, Model, CommandResult, Model)}
- * that takes a string {@code expectedMessage}.
- */
- public static void assertCommandSuccess(Command command, Model actualModel, String expectedMessage,
- Model expectedModel) {
- CommandResult expectedCommandResult = new CommandResult(expectedMessage);
- assertCommandSuccess(command, actualModel, expectedCommandResult, expectedModel);
- }
-
- /**
- * Executes the given {@code command}, confirms that
- * - a {@code CommandException} is thrown
- * - the CommandException message matches {@code expectedMessage}
- * - the address book, filtered person list and selected person in {@code actualModel} remain unchanged
- */
- public static void assertCommandFailure(Command command, Model actualModel, String expectedMessage) {
- // we are unable to defensively copy the model for comparison later, so we can
- // only do so by copying its components.
- AddressBook expectedAddressBook = new AddressBook(actualModel.getAddressBook());
- List expectedFilteredList = new ArrayList<>(actualModel.getFilteredPersonList());
-
- assertThrows(CommandException.class, expectedMessage, () -> command.execute(actualModel));
- assertEquals(expectedAddressBook, actualModel.getAddressBook());
- assertEquals(expectedFilteredList, actualModel.getFilteredPersonList());
- }
- /**
- * Updates {@code model}'s filtered list to show only the person at the given {@code targetIndex} in the
- * {@code model}'s address book.
- */
- public static void showPersonAtIndex(Model model, Index targetIndex) {
- assertTrue(targetIndex.getZeroBased() < model.getFilteredPersonList().size());
-
- Person person = model.getFilteredPersonList().get(targetIndex.getZeroBased());
- final String[] splitName = person.getName().fullName.split("\\s+");
- model.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(splitName[0])));
-
- assertEquals(1, model.getFilteredPersonList().size());
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java
deleted file mode 100644
index 1c27530fa99..00000000000
--- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java
+++ /dev/null
@@ -1,173 +0,0 @@
-package seedu.address.logic.commands;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.person.Person;
-import seedu.address.testutil.EditPersonDescriptorBuilder;
-import seedu.address.testutil.PersonBuilder;
-
-/**
- * Contains integration tests (interaction with the Model, UndoCommand and RedoCommand) and unit tests for EditCommand.
- */
-public class EditCommandTest {
-
- private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
-
- @Test
- public void execute_allFieldsSpecifiedUnfilteredList_success() {
- Person editedPerson = new PersonBuilder().build();
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build();
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, descriptor);
-
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
-
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson);
-
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_someFieldsSpecifiedUnfilteredList_success() {
- Index indexLastPerson = Index.fromOneBased(model.getFilteredPersonList().size());
- Person lastPerson = model.getFilteredPersonList().get(indexLastPerson.getZeroBased());
-
- PersonBuilder personInList = new PersonBuilder(lastPerson);
- Person editedPerson = personInList.withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
- .withTags(VALID_TAG_HUSBAND).build();
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB)
- .withPhone(VALID_PHONE_BOB).withTags(VALID_TAG_HUSBAND).build();
- EditCommand editCommand = new EditCommand(indexLastPerson, descriptor);
-
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
-
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setPerson(lastPerson, editedPerson);
-
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_noFieldSpecifiedUnfilteredList_success() {
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, new EditPersonDescriptor());
- Person editedPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
-
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
-
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
-
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_filteredList_success() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
-
- Person personInFilteredList = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
- Person editedPerson = new PersonBuilder(personInFilteredList).withName(VALID_NAME_BOB).build();
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON,
- new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build());
-
- String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson);
-
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson);
-
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }
-
- @Test
- public void execute_duplicatePersonUnfilteredList_failure() {
- Person firstPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(firstPerson).build();
- EditCommand editCommand = new EditCommand(INDEX_SECOND_PERSON, descriptor);
-
- assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON);
- }
-
- @Test
- public void execute_duplicatePersonFilteredList_failure() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
-
- // edit person in filtered list into a duplicate in address book
- Person personInList = model.getAddressBook().getPersonList().get(INDEX_SECOND_PERSON.getZeroBased());
- EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON,
- new EditPersonDescriptorBuilder(personInList).build());
-
- assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON);
- }
-
- @Test
- public void execute_invalidPersonIndexUnfilteredList_failure() {
- Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1);
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build();
- EditCommand editCommand = new EditCommand(outOfBoundIndex, descriptor);
-
- assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- /**
- * Edit filtered list where index is larger than size of filtered list,
- * but smaller than size of address book
- */
- @Test
- public void execute_invalidPersonIndexFilteredList_failure() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
- Index outOfBoundIndex = INDEX_SECOND_PERSON;
- // ensures that outOfBoundIndex is still in bounds of address book list
- assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size());
-
- EditCommand editCommand = new EditCommand(outOfBoundIndex,
- new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build());
-
- assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- @Test
- public void equals() {
- final EditCommand standardCommand = new EditCommand(INDEX_FIRST_PERSON, DESC_AMY);
-
- // same values -> returns true
- EditPersonDescriptor copyDescriptor = new EditPersonDescriptor(DESC_AMY);
- EditCommand commandWithSameValues = new EditCommand(INDEX_FIRST_PERSON, copyDescriptor);
- assertTrue(standardCommand.equals(commandWithSameValues));
-
- // same object -> returns true
- assertTrue(standardCommand.equals(standardCommand));
-
- // null -> returns false
- assertFalse(standardCommand.equals(null));
-
- // different types -> returns false
- assertFalse(standardCommand.equals(new ClearCommand()));
-
- // different index -> returns false
- assertFalse(standardCommand.equals(new EditCommand(INDEX_SECOND_PERSON, DESC_AMY)));
-
- // different descriptor -> returns false
- assertFalse(standardCommand.equals(new EditCommand(INDEX_FIRST_PERSON, DESC_BOB)));
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java b/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java
deleted file mode 100644
index e0288792e72..00000000000
--- a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package seedu.address.logic.commands;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.testutil.EditPersonDescriptorBuilder;
-
-public class EditPersonDescriptorTest {
-
- @Test
- public void equals() {
- // same values -> returns true
- EditPersonDescriptor descriptorWithSameValues = new EditPersonDescriptor(DESC_AMY);
- assertTrue(DESC_AMY.equals(descriptorWithSameValues));
-
- // same object -> returns true
- assertTrue(DESC_AMY.equals(DESC_AMY));
-
- // null -> returns false
- assertFalse(DESC_AMY.equals(null));
-
- // different types -> returns false
- assertFalse(DESC_AMY.equals(5));
-
- // different values -> returns false
- assertFalse(DESC_AMY.equals(DESC_BOB));
-
- // different name -> returns false
- EditPersonDescriptor editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withName(VALID_NAME_BOB).build();
- assertFalse(DESC_AMY.equals(editedAmy));
-
- // different phone -> returns false
- editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withPhone(VALID_PHONE_BOB).build();
- assertFalse(DESC_AMY.equals(editedAmy));
-
- // different email -> returns false
- editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withEmail(VALID_EMAIL_BOB).build();
- assertFalse(DESC_AMY.equals(editedAmy));
-
- // different address -> returns false
- editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withAddress(VALID_ADDRESS_BOB).build();
- assertFalse(DESC_AMY.equals(editedAmy));
-
- // different tags -> returns false
- editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withTags(VALID_TAG_HUSBAND).build();
- assertFalse(DESC_AMY.equals(editedAmy));
- }
-}
diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindCommandTest.java
deleted file mode 100644
index 9b15db28bbb..00000000000
--- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package seedu.address.logic.commands;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.commons.core.Messages.MESSAGE_PERSONS_LISTED_OVERVIEW;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.testutil.TypicalPersons.CARL;
-import static seedu.address.testutil.TypicalPersons.ELLE;
-import static seedu.address.testutil.TypicalPersons.FIONA;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import java.util.Arrays;
-import java.util.Collections;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-
-/**
- * Contains integration tests (interaction with the Model) for {@code FindCommand}.
- */
-public class FindCommandTest {
- private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs());
-
- @Test
- public void equals() {
- NameContainsKeywordsPredicate firstPredicate =
- new NameContainsKeywordsPredicate(Collections.singletonList("first"));
- NameContainsKeywordsPredicate secondPredicate =
- new NameContainsKeywordsPredicate(Collections.singletonList("second"));
-
- FindCommand findFirstCommand = new FindCommand(firstPredicate);
- FindCommand findSecondCommand = new FindCommand(secondPredicate);
-
- // same object -> returns true
- assertTrue(findFirstCommand.equals(findFirstCommand));
-
- // same values -> returns true
- FindCommand findFirstCommandCopy = new FindCommand(firstPredicate);
- assertTrue(findFirstCommand.equals(findFirstCommandCopy));
-
- // different types -> returns false
- assertFalse(findFirstCommand.equals(1));
-
- // null -> returns false
- assertFalse(findFirstCommand.equals(null));
-
- // different person -> returns false
- assertFalse(findFirstCommand.equals(findSecondCommand));
- }
-
- @Test
- public void execute_zeroKeywords_noPersonFound() {
- String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 0);
- NameContainsKeywordsPredicate predicate = preparePredicate(" ");
- FindCommand command = new FindCommand(predicate);
- expectedModel.updateFilteredPersonList(predicate);
- assertCommandSuccess(command, model, expectedMessage, expectedModel);
- assertEquals(Collections.emptyList(), model.getFilteredPersonList());
- }
-
- @Test
- public void execute_multipleKeywords_multiplePersonsFound() {
- String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 3);
- NameContainsKeywordsPredicate predicate = preparePredicate("Kurz Elle Kunz");
- FindCommand command = new FindCommand(predicate);
- expectedModel.updateFilteredPersonList(predicate);
- assertCommandSuccess(command, model, expectedMessage, expectedModel);
- assertEquals(Arrays.asList(CARL, ELLE, FIONA), model.getFilteredPersonList());
- }
-
- /**
- * Parses {@code userInput} into a {@code NameContainsKeywordsPredicate}.
- */
- private NameContainsKeywordsPredicate preparePredicate(String userInput) {
- return new NameContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")));
- }
-}
diff --git a/src/test/java/seedu/address/logic/commands/ListCommandTest.java b/src/test/java/seedu/address/logic/commands/ListCommandTest.java
deleted file mode 100644
index 435ff1f7275..00000000000
--- a/src/test/java/seedu/address/logic/commands/ListCommandTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package seedu.address.logic.commands;
-
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-
-/**
- * Contains integration tests (interaction with the Model) and unit tests for ListCommand.
- */
-public class ListCommandTest {
-
- private Model model;
- private Model expectedModel;
-
- @BeforeEach
- public void setUp() {
- model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- }
-
- @Test
- public void execute_listIsNotFiltered_showsSameList() {
- assertCommandSuccess(new ListCommand(), model, ListCommand.MESSAGE_SUCCESS, expectedModel);
- }
-
- @Test
- public void execute_listIsFiltered_showsEverything() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
- assertCommandSuccess(new ListCommand(), model, ListCommand.MESSAGE_SUCCESS, expectedModel);
- }
-}
diff --git a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java
deleted file mode 100644
index 5cf487d7ebb..00000000000
--- a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.PREAMBLE_NON_EMPTY;
-import static seedu.address.logic.commands.CommandTestUtil.PREAMBLE_WHITESPACE;
-import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_HUSBAND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
-import static seedu.address.testutil.TypicalPersons.AMY;
-import static seedu.address.testutil.TypicalPersons.BOB;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-import seedu.address.testutil.PersonBuilder;
-
-public class AddCommandParserTest {
- private AddCommandParser parser = new AddCommandParser();
-
- @Test
- public void parse_allFieldsPresent_success() {
- Person expectedPerson = new PersonBuilder(BOB).withTags(VALID_TAG_FRIEND).build();
-
- // whitespace only preamble
- assertParseSuccess(parser, PREAMBLE_WHITESPACE + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
-
- // multiple names - last name accepted
- assertParseSuccess(parser, NAME_DESC_AMY + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
-
- // multiple phones - last phone accepted
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_AMY + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
-
- // multiple emails - last email accepted
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_AMY + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
-
- // multiple addresses - last address accepted
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_AMY
- + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson));
-
- // multiple tags - all accepted
- Person expectedPersonMultipleTags = new PersonBuilder(BOB).withTags(VALID_TAG_FRIEND, VALID_TAG_HUSBAND)
- .build();
- assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, new AddCommand(expectedPersonMultipleTags));
- }
-
- @Test
- public void parse_optionalFieldsMissing_success() {
- // zero tags
- Person expectedPerson = new PersonBuilder(AMY).withTags().build();
- assertParseSuccess(parser, NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY,
- new AddCommand(expectedPerson));
- }
-
- @Test
- public void parse_compulsoryFieldMissing_failure() {
- String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE);
-
- // missing name prefix
- assertParseFailure(parser, VALID_NAME_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB,
- expectedMessage);
-
- // missing phone prefix
- assertParseFailure(parser, NAME_DESC_BOB + VALID_PHONE_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB,
- expectedMessage);
-
- // missing email prefix
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + VALID_EMAIL_BOB + ADDRESS_DESC_BOB,
- expectedMessage);
-
- // missing address prefix
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + VALID_ADDRESS_BOB,
- expectedMessage);
-
- // all prefixes missing
- assertParseFailure(parser, VALID_NAME_BOB + VALID_PHONE_BOB + VALID_EMAIL_BOB + VALID_ADDRESS_BOB,
- expectedMessage);
- }
-
- @Test
- public void parse_invalidValue_failure() {
- // invalid name
- assertParseFailure(parser, INVALID_NAME_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Name.MESSAGE_CONSTRAINTS);
-
- // invalid phone
- assertParseFailure(parser, NAME_DESC_BOB + INVALID_PHONE_DESC + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Phone.MESSAGE_CONSTRAINTS);
-
- // invalid email
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + INVALID_EMAIL_DESC + ADDRESS_DESC_BOB
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Email.MESSAGE_CONSTRAINTS);
-
- // invalid address
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC
- + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Address.MESSAGE_CONSTRAINTS);
-
- // invalid tag
- assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB
- + INVALID_TAG_DESC + VALID_TAG_FRIEND, Tag.MESSAGE_CONSTRAINTS);
-
- // two invalid values, only first invalid value reported
- assertParseFailure(parser, INVALID_NAME_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC,
- Name.MESSAGE_CONSTRAINTS);
-
- // non-empty preamble
- assertParseFailure(parser, PREAMBLE_NON_EMPTY + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB
- + ADDRESS_DESC_BOB + TAG_DESC_HUSBAND + TAG_DESC_FRIEND,
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
- }
-}
diff --git a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java
deleted file mode 100644
index 2ff31522486..00000000000
--- a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java
+++ /dev/null
@@ -1,211 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC;
-import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_HUSBAND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
-import static seedu.address.testutil.TypicalIndexes.INDEX_THIRD_PERSON;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-import seedu.address.testutil.EditPersonDescriptorBuilder;
-
-public class EditCommandParserTest {
-
- private static final String TAG_EMPTY = " " + PREFIX_TAG;
-
- private static final String MESSAGE_INVALID_FORMAT =
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE);
-
- private EditCommandParser parser = new EditCommandParser();
-
- @Test
- public void parse_missingParts_failure() {
- // no index specified
- assertParseFailure(parser, VALID_NAME_AMY, MESSAGE_INVALID_FORMAT);
-
- // no field specified
- assertParseFailure(parser, "1", EditCommand.MESSAGE_NOT_EDITED);
-
- // no index and no field specified
- assertParseFailure(parser, "", MESSAGE_INVALID_FORMAT);
- }
-
- @Test
- public void parse_invalidPreamble_failure() {
- // negative index
- assertParseFailure(parser, "-5" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT);
-
- // zero index
- assertParseFailure(parser, "0" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT);
-
- // invalid arguments being parsed as preamble
- assertParseFailure(parser, "1 some random string", MESSAGE_INVALID_FORMAT);
-
- // invalid prefix being parsed as preamble
- assertParseFailure(parser, "1 i/ string", MESSAGE_INVALID_FORMAT);
- }
-
- @Test
- public void parse_invalidValue_failure() {
- assertParseFailure(parser, "1" + INVALID_NAME_DESC, Name.MESSAGE_CONSTRAINTS); // invalid name
- assertParseFailure(parser, "1" + INVALID_PHONE_DESC, Phone.MESSAGE_CONSTRAINTS); // invalid phone
- assertParseFailure(parser, "1" + INVALID_EMAIL_DESC, Email.MESSAGE_CONSTRAINTS); // invalid email
- assertParseFailure(parser, "1" + INVALID_ADDRESS_DESC, Address.MESSAGE_CONSTRAINTS); // invalid address
- assertParseFailure(parser, "1" + INVALID_TAG_DESC, Tag.MESSAGE_CONSTRAINTS); // invalid tag
-
- // invalid phone followed by valid email
- assertParseFailure(parser, "1" + INVALID_PHONE_DESC + EMAIL_DESC_AMY, Phone.MESSAGE_CONSTRAINTS);
-
- // valid phone followed by invalid phone. The test case for invalid phone followed by valid phone
- // is tested at {@code parse_invalidValueFollowedByValidValue_success()}
- assertParseFailure(parser, "1" + PHONE_DESC_BOB + INVALID_PHONE_DESC, Phone.MESSAGE_CONSTRAINTS);
-
- // while parsing {@code PREFIX_TAG} alone will reset the tags of the {@code Person} being edited,
- // parsing it together with a valid tag results in error
- assertParseFailure(parser, "1" + TAG_DESC_FRIEND + TAG_DESC_HUSBAND + TAG_EMPTY, Tag.MESSAGE_CONSTRAINTS);
- assertParseFailure(parser, "1" + TAG_DESC_FRIEND + TAG_EMPTY + TAG_DESC_HUSBAND, Tag.MESSAGE_CONSTRAINTS);
- assertParseFailure(parser, "1" + TAG_EMPTY + TAG_DESC_FRIEND + TAG_DESC_HUSBAND, Tag.MESSAGE_CONSTRAINTS);
-
- // multiple invalid values, but only the first invalid value is captured
- assertParseFailure(parser, "1" + INVALID_NAME_DESC + INVALID_EMAIL_DESC + VALID_ADDRESS_AMY + VALID_PHONE_AMY,
- Name.MESSAGE_CONSTRAINTS);
- }
-
- @Test
- public void parse_allFieldsSpecified_success() {
- Index targetIndex = INDEX_SECOND_PERSON;
- String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + TAG_DESC_HUSBAND
- + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + NAME_DESC_AMY + TAG_DESC_FRIEND;
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY)
- .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY)
- .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
-
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-
- @Test
- public void parse_someFieldsSpecified_success() {
- Index targetIndex = INDEX_FIRST_PERSON;
- String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + EMAIL_DESC_AMY;
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB)
- .withEmail(VALID_EMAIL_AMY).build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
-
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-
- @Test
- public void parse_oneFieldSpecified_success() {
- // name
- Index targetIndex = INDEX_THIRD_PERSON;
- String userInput = targetIndex.getOneBased() + NAME_DESC_AMY;
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY).build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // phone
- userInput = targetIndex.getOneBased() + PHONE_DESC_AMY;
- descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_AMY).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // email
- userInput = targetIndex.getOneBased() + EMAIL_DESC_AMY;
- descriptor = new EditPersonDescriptorBuilder().withEmail(VALID_EMAIL_AMY).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // address
- userInput = targetIndex.getOneBased() + ADDRESS_DESC_AMY;
- descriptor = new EditPersonDescriptorBuilder().withAddress(VALID_ADDRESS_AMY).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // tags
- userInput = targetIndex.getOneBased() + TAG_DESC_FRIEND;
- descriptor = new EditPersonDescriptorBuilder().withTags(VALID_TAG_FRIEND).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-
- @Test
- public void parse_multipleRepeatedFields_acceptsLast() {
- Index targetIndex = INDEX_FIRST_PERSON;
- String userInput = targetIndex.getOneBased() + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY
- + TAG_DESC_FRIEND + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY + TAG_DESC_FRIEND
- + PHONE_DESC_BOB + ADDRESS_DESC_BOB + EMAIL_DESC_BOB + TAG_DESC_HUSBAND;
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB)
- .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_FRIEND, VALID_TAG_HUSBAND)
- .build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
-
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-
- @Test
- public void parse_invalidValueFollowedByValidValue_success() {
- // no other valid values specified
- Index targetIndex = INDEX_FIRST_PERSON;
- String userInput = targetIndex.getOneBased() + INVALID_PHONE_DESC + PHONE_DESC_BOB;
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB).build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
-
- // other valid values specified
- userInput = targetIndex.getOneBased() + EMAIL_DESC_BOB + INVALID_PHONE_DESC + ADDRESS_DESC_BOB
- + PHONE_DESC_BOB;
- descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB)
- .withAddress(VALID_ADDRESS_BOB).build();
- expectedCommand = new EditCommand(targetIndex, descriptor);
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-
- @Test
- public void parse_resetTags_success() {
- Index targetIndex = INDEX_THIRD_PERSON;
- String userInput = targetIndex.getOneBased() + TAG_EMPTY;
-
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withTags().build();
- EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
-
- assertParseSuccess(parser, userInput, expectedCommand);
- }
-}
diff --git a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java
deleted file mode 100644
index 70f4f0e79c4..00000000000
--- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
-
-import java.util.Arrays;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-
-public class FindCommandParserTest {
-
- private FindCommandParser parser = new FindCommandParser();
-
- @Test
- public void parse_emptyArg_throwsParseException() {
- assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
- }
-
- @Test
- public void parse_validArgs_returnsFindCommand() {
- // no leading and trailing whitespaces
- FindCommand expectedFindCommand =
- new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob")));
- assertParseSuccess(parser, "Alice Bob", expectedFindCommand);
-
- // multiple whitespaces between keywords
- assertParseSuccess(parser, " \n Alice \n \t Bob \t", expectedFindCommand);
- }
-
-}
diff --git a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java
deleted file mode 100644
index 4256788b1a7..00000000000
--- a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-package seedu.address.logic.parser;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.parser.ParserUtil.MESSAGE_INVALID_INDEX;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-public class ParserUtilTest {
- private static final String INVALID_NAME = "R@chel";
- private static final String INVALID_PHONE = "+651234";
- private static final String INVALID_ADDRESS = " ";
- private static final String INVALID_EMAIL = "example.com";
- private static final String INVALID_TAG = "#friend";
-
- private static final String VALID_NAME = "Rachel Walker";
- private static final String VALID_PHONE = "123456";
- private static final String VALID_ADDRESS = "123 Main Street #0505";
- private static final String VALID_EMAIL = "rachel@example.com";
- private static final String VALID_TAG_1 = "friend";
- private static final String VALID_TAG_2 = "neighbour";
-
- private static final String WHITESPACE = " \t\r\n";
-
- @Test
- public void parseIndex_invalidInput_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseIndex("10 a"));
- }
-
- @Test
- public void parseIndex_outOfRangeInput_throwsParseException() {
- assertThrows(ParseException.class, MESSAGE_INVALID_INDEX, ()
- -> ParserUtil.parseIndex(Long.toString(Integer.MAX_VALUE + 1)));
- }
-
- @Test
- public void parseIndex_validInput_success() throws Exception {
- // No whitespaces
- assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex("1"));
-
- // Leading and trailing whitespaces
- assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex(" 1 "));
- }
-
- @Test
- public void parseName_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseName((String) null));
- }
-
- @Test
- public void parseName_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseName(INVALID_NAME));
- }
-
- @Test
- public void parseName_validValueWithoutWhitespace_returnsName() throws Exception {
- Name expectedName = new Name(VALID_NAME);
- assertEquals(expectedName, ParserUtil.parseName(VALID_NAME));
- }
-
- @Test
- public void parseName_validValueWithWhitespace_returnsTrimmedName() throws Exception {
- String nameWithWhitespace = WHITESPACE + VALID_NAME + WHITESPACE;
- Name expectedName = new Name(VALID_NAME);
- assertEquals(expectedName, ParserUtil.parseName(nameWithWhitespace));
- }
-
- @Test
- public void parsePhone_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parsePhone((String) null));
- }
-
- @Test
- public void parsePhone_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parsePhone(INVALID_PHONE));
- }
-
- @Test
- public void parsePhone_validValueWithoutWhitespace_returnsPhone() throws Exception {
- Phone expectedPhone = new Phone(VALID_PHONE);
- assertEquals(expectedPhone, ParserUtil.parsePhone(VALID_PHONE));
- }
-
- @Test
- public void parsePhone_validValueWithWhitespace_returnsTrimmedPhone() throws Exception {
- String phoneWithWhitespace = WHITESPACE + VALID_PHONE + WHITESPACE;
- Phone expectedPhone = new Phone(VALID_PHONE);
- assertEquals(expectedPhone, ParserUtil.parsePhone(phoneWithWhitespace));
- }
-
- @Test
- public void parseAddress_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseAddress((String) null));
- }
-
- @Test
- public void parseAddress_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseAddress(INVALID_ADDRESS));
- }
-
- @Test
- public void parseAddress_validValueWithoutWhitespace_returnsAddress() throws Exception {
- Address expectedAddress = new Address(VALID_ADDRESS);
- assertEquals(expectedAddress, ParserUtil.parseAddress(VALID_ADDRESS));
- }
-
- @Test
- public void parseAddress_validValueWithWhitespace_returnsTrimmedAddress() throws Exception {
- String addressWithWhitespace = WHITESPACE + VALID_ADDRESS + WHITESPACE;
- Address expectedAddress = new Address(VALID_ADDRESS);
- assertEquals(expectedAddress, ParserUtil.parseAddress(addressWithWhitespace));
- }
-
- @Test
- public void parseEmail_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseEmail((String) null));
- }
-
- @Test
- public void parseEmail_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseEmail(INVALID_EMAIL));
- }
-
- @Test
- public void parseEmail_validValueWithoutWhitespace_returnsEmail() throws Exception {
- Email expectedEmail = new Email(VALID_EMAIL);
- assertEquals(expectedEmail, ParserUtil.parseEmail(VALID_EMAIL));
- }
-
- @Test
- public void parseEmail_validValueWithWhitespace_returnsTrimmedEmail() throws Exception {
- String emailWithWhitespace = WHITESPACE + VALID_EMAIL + WHITESPACE;
- Email expectedEmail = new Email(VALID_EMAIL);
- assertEquals(expectedEmail, ParserUtil.parseEmail(emailWithWhitespace));
- }
-
- @Test
- public void parseTag_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseTag(null));
- }
-
- @Test
- public void parseTag_invalidValue_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseTag(INVALID_TAG));
- }
-
- @Test
- public void parseTag_validValueWithoutWhitespace_returnsTag() throws Exception {
- Tag expectedTag = new Tag(VALID_TAG_1);
- assertEquals(expectedTag, ParserUtil.parseTag(VALID_TAG_1));
- }
-
- @Test
- public void parseTag_validValueWithWhitespace_returnsTrimmedTag() throws Exception {
- String tagWithWhitespace = WHITESPACE + VALID_TAG_1 + WHITESPACE;
- Tag expectedTag = new Tag(VALID_TAG_1);
- assertEquals(expectedTag, ParserUtil.parseTag(tagWithWhitespace));
- }
-
- @Test
- public void parseTags_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> ParserUtil.parseTags(null));
- }
-
- @Test
- public void parseTags_collectionWithInvalidTags_throwsParseException() {
- assertThrows(ParseException.class, () -> ParserUtil.parseTags(Arrays.asList(VALID_TAG_1, INVALID_TAG)));
- }
-
- @Test
- public void parseTags_emptyCollection_returnsEmptySet() throws Exception {
- assertTrue(ParserUtil.parseTags(Collections.emptyList()).isEmpty());
- }
-
- @Test
- public void parseTags_collectionWithValidTags_returnsTagSet() throws Exception {
- Set actualTagSet = ParserUtil.parseTags(Arrays.asList(VALID_TAG_1, VALID_TAG_2));
- Set expectedTagSet = new HashSet(Arrays.asList(new Tag(VALID_TAG_1), new Tag(VALID_TAG_2)));
-
- assertEquals(expectedTagSet, actualTagSet);
- }
-}
diff --git a/src/test/java/seedu/address/model/AddressBookTest.java b/src/test/java/seedu/address/model/AddressBookTest.java
deleted file mode 100644
index 87782528ecd..00000000000
--- a/src/test/java/seedu/address/model/AddressBookTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package seedu.address.model;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.ALICE;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.junit.jupiter.api.Test;
-
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.exceptions.DuplicatePersonException;
-import seedu.address.testutil.PersonBuilder;
-
-public class AddressBookTest {
-
- private final AddressBook addressBook = new AddressBook();
-
- @Test
- public void constructor() {
- assertEquals(Collections.emptyList(), addressBook.getPersonList());
- }
-
- @Test
- public void resetData_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> addressBook.resetData(null));
- }
-
- @Test
- public void resetData_withValidReadOnlyAddressBook_replacesData() {
- AddressBook newData = getTypicalAddressBook();
- addressBook.resetData(newData);
- assertEquals(newData, addressBook);
- }
-
- @Test
- public void resetData_withDuplicatePersons_throwsDuplicatePersonException() {
- // Two persons with the same identity fields
- Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND)
- .build();
- List newPersons = Arrays.asList(ALICE, editedAlice);
- AddressBookStub newData = new AddressBookStub(newPersons);
-
- assertThrows(DuplicatePersonException.class, () -> addressBook.resetData(newData));
- }
-
- @Test
- public void hasPerson_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> addressBook.hasPerson(null));
- }
-
- @Test
- public void hasPerson_personNotInAddressBook_returnsFalse() {
- assertFalse(addressBook.hasPerson(ALICE));
- }
-
- @Test
- public void hasPerson_personInAddressBook_returnsTrue() {
- addressBook.addPerson(ALICE);
- assertTrue(addressBook.hasPerson(ALICE));
- }
-
- @Test
- public void hasPerson_personWithSameIdentityFieldsInAddressBook_returnsTrue() {
- addressBook.addPerson(ALICE);
- Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND)
- .build();
- assertTrue(addressBook.hasPerson(editedAlice));
- }
-
- @Test
- public void getPersonList_modifyList_throwsUnsupportedOperationException() {
- assertThrows(UnsupportedOperationException.class, () -> addressBook.getPersonList().remove(0));
- }
-
- /**
- * A stub ReadOnlyAddressBook whose persons list can violate interface constraints.
- */
- private static class AddressBookStub implements ReadOnlyAddressBook {
- private final ObservableList persons = FXCollections.observableArrayList();
-
- AddressBookStub(Collection persons) {
- this.persons.setAll(persons);
- }
-
- @Override
- public ObservableList getPersonList() {
- return persons;
- }
- }
-
-}
diff --git a/src/test/java/seedu/address/model/person/AddressTest.java b/src/test/java/seedu/address/model/person/AddressTest.java
deleted file mode 100644
index dcd3be87b3a..00000000000
--- a/src/test/java/seedu/address/model/person/AddressTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package seedu.address.model.person;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import org.junit.jupiter.api.Test;
-
-public class AddressTest {
-
- @Test
- public void constructor_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> new Address(null));
- }
-
- @Test
- public void constructor_invalidAddress_throwsIllegalArgumentException() {
- String invalidAddress = "";
- assertThrows(IllegalArgumentException.class, () -> new Address(invalidAddress));
- }
-
- @Test
- public void isValidAddress() {
- // null address
- assertThrows(NullPointerException.class, () -> Address.isValidAddress(null));
-
- // invalid addresses
- assertFalse(Address.isValidAddress("")); // empty string
- assertFalse(Address.isValidAddress(" ")); // spaces only
-
- // valid addresses
- assertTrue(Address.isValidAddress("Blk 456, Den Road, #01-355"));
- assertTrue(Address.isValidAddress("-")); // one character
- assertTrue(Address.isValidAddress("Leng Inc; 1234 Market St; San Francisco CA 2349879; USA")); // long address
- }
-}
diff --git a/src/test/java/seedu/address/model/person/EmailTest.java b/src/test/java/seedu/address/model/person/EmailTest.java
deleted file mode 100644
index 7fa726ceb18..00000000000
--- a/src/test/java/seedu/address/model/person/EmailTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package seedu.address.model.person;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import org.junit.jupiter.api.Test;
-
-public class EmailTest {
-
- @Test
- public void constructor_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> new Email(null));
- }
-
- @Test
- public void constructor_invalidEmail_throwsIllegalArgumentException() {
- String invalidEmail = "";
- assertThrows(IllegalArgumentException.class, () -> new Email(invalidEmail));
- }
-
- @Test
- public void isValidEmail() {
- // null email
- assertThrows(NullPointerException.class, () -> Email.isValidEmail(null));
-
- // blank email
- assertFalse(Email.isValidEmail("")); // empty string
- assertFalse(Email.isValidEmail(" ")); // spaces only
-
- // missing parts
- assertFalse(Email.isValidEmail("@example.com")); // missing local part
- assertFalse(Email.isValidEmail("peterjackexample.com")); // missing '@' symbol
- assertFalse(Email.isValidEmail("peterjack@")); // missing domain name
-
- // invalid parts
- assertFalse(Email.isValidEmail("peterjack@-")); // invalid domain name
- assertFalse(Email.isValidEmail("peterjack@exam_ple.com")); // underscore in domain name
- assertFalse(Email.isValidEmail("peter jack@example.com")); // spaces in local part
- assertFalse(Email.isValidEmail("peterjack@exam ple.com")); // spaces in domain name
- assertFalse(Email.isValidEmail(" peterjack@example.com")); // leading space
- assertFalse(Email.isValidEmail("peterjack@example.com ")); // trailing space
- assertFalse(Email.isValidEmail("peterjack@@example.com")); // double '@' symbol
- assertFalse(Email.isValidEmail("peter@jack@example.com")); // '@' symbol in local part
- assertFalse(Email.isValidEmail("peterjack@example@com")); // '@' symbol in domain name
- assertFalse(Email.isValidEmail("peterjack@.example.com")); // domain name starts with a period
- assertFalse(Email.isValidEmail("peterjack@example.com.")); // domain name ends with a period
- assertFalse(Email.isValidEmail("peterjack@-example.com")); // domain name starts with a hyphen
- assertFalse(Email.isValidEmail("peterjack@example.com-")); // domain name ends with a hyphen
-
- // valid email
- assertTrue(Email.isValidEmail("PeterJack_1190@example.com"));
- assertTrue(Email.isValidEmail("a@bc")); // minimal
- assertTrue(Email.isValidEmail("test@localhost")); // alphabets only
- assertTrue(Email.isValidEmail("!#$%&'*+/=?`{|}~^.-@example.org")); // special characters local part
- assertTrue(Email.isValidEmail("123@145")); // numeric local part and domain name
- assertTrue(Email.isValidEmail("a1+be!@example1.com")); // mixture of alphanumeric and special characters
- assertTrue(Email.isValidEmail("peter_jack@very-very-very-long-example.com")); // long domain name
- assertTrue(Email.isValidEmail("if.you.dream.it_you.can.do.it@example.com")); // long local part
- }
-}
diff --git a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java
deleted file mode 100644
index f136664e017..00000000000
--- a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package seedu.address.model.person;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.testutil.PersonBuilder;
-
-public class NameContainsKeywordsPredicateTest {
-
- @Test
- public void equals() {
- List firstPredicateKeywordList = Collections.singletonList("first");
- List secondPredicateKeywordList = Arrays.asList("first", "second");
-
- NameContainsKeywordsPredicate firstPredicate = new NameContainsKeywordsPredicate(firstPredicateKeywordList);
- NameContainsKeywordsPredicate secondPredicate = new NameContainsKeywordsPredicate(secondPredicateKeywordList);
-
- // same object -> returns true
- assertTrue(firstPredicate.equals(firstPredicate));
-
- // same values -> returns true
- NameContainsKeywordsPredicate firstPredicateCopy = new NameContainsKeywordsPredicate(firstPredicateKeywordList);
- assertTrue(firstPredicate.equals(firstPredicateCopy));
-
- // different types -> returns false
- assertFalse(firstPredicate.equals(1));
-
- // null -> returns false
- assertFalse(firstPredicate.equals(null));
-
- // different person -> returns false
- assertFalse(firstPredicate.equals(secondPredicate));
- }
-
- @Test
- public void test_nameContainsKeywords_returnsTrue() {
- // One keyword
- NameContainsKeywordsPredicate predicate = new NameContainsKeywordsPredicate(Collections.singletonList("Alice"));
- assertTrue(predicate.test(new PersonBuilder().withName("Alice Bob").build()));
-
- // Multiple keywords
- predicate = new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob"));
- assertTrue(predicate.test(new PersonBuilder().withName("Alice Bob").build()));
-
- // Only one matching keyword
- predicate = new NameContainsKeywordsPredicate(Arrays.asList("Bob", "Carol"));
- assertTrue(predicate.test(new PersonBuilder().withName("Alice Carol").build()));
-
- // Mixed-case keywords
- predicate = new NameContainsKeywordsPredicate(Arrays.asList("aLIce", "bOB"));
- assertTrue(predicate.test(new PersonBuilder().withName("Alice Bob").build()));
- }
-
- @Test
- public void test_nameDoesNotContainKeywords_returnsFalse() {
- // Zero keywords
- NameContainsKeywordsPredicate predicate = new NameContainsKeywordsPredicate(Collections.emptyList());
- assertFalse(predicate.test(new PersonBuilder().withName("Alice").build()));
-
- // Non-matching keyword
- predicate = new NameContainsKeywordsPredicate(Arrays.asList("Carol"));
- assertFalse(predicate.test(new PersonBuilder().withName("Alice Bob").build()));
-
- // Keywords match phone, email and address, but does not match name
- predicate = new NameContainsKeywordsPredicate(Arrays.asList("12345", "alice@email.com", "Main", "Street"));
- assertFalse(predicate.test(new PersonBuilder().withName("Alice").withPhone("12345")
- .withEmail("alice@email.com").withAddress("Main Street").build()));
- }
-}
diff --git a/src/test/java/seedu/address/model/person/NameTest.java b/src/test/java/seedu/address/model/person/NameTest.java
deleted file mode 100644
index c9801392874..00000000000
--- a/src/test/java/seedu/address/model/person/NameTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package seedu.address.model.person;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import org.junit.jupiter.api.Test;
-
-public class NameTest {
-
- @Test
- public void constructor_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> new Name(null));
- }
-
- @Test
- public void constructor_invalidName_throwsIllegalArgumentException() {
- String invalidName = "";
- assertThrows(IllegalArgumentException.class, () -> new Name(invalidName));
- }
-
- @Test
- public void isValidName() {
- // null name
- assertThrows(NullPointerException.class, () -> Name.isValidName(null));
-
- // invalid name
- assertFalse(Name.isValidName("")); // empty string
- assertFalse(Name.isValidName(" ")); // spaces only
- assertFalse(Name.isValidName("^")); // only non-alphanumeric characters
- assertFalse(Name.isValidName("peter*")); // contains non-alphanumeric characters
-
- // valid name
- assertTrue(Name.isValidName("peter jack")); // alphabets only
- assertTrue(Name.isValidName("12345")); // numbers only
- assertTrue(Name.isValidName("peter the 2nd")); // alphanumeric characters
- assertTrue(Name.isValidName("Capital Tan")); // with capital letters
- assertTrue(Name.isValidName("David Roger Jackson Ray Jr 2nd")); // long names
- }
-}
diff --git a/src/test/java/seedu/address/model/person/PersonTest.java b/src/test/java/seedu/address/model/person/PersonTest.java
deleted file mode 100644
index 7c1058d8635..00000000000
--- a/src/test/java/seedu/address/model/person/PersonTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package seedu.address.model.person;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.ALICE;
-import static seedu.address.testutil.TypicalPersons.BOB;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.testutil.PersonBuilder;
-
-public class PersonTest {
-
- @Test
- public void asObservableList_modifyList_throwsUnsupportedOperationException() {
- Person person = new PersonBuilder().build();
- assertThrows(UnsupportedOperationException.class, () -> person.getTags().remove(0));
- }
-
- @Test
- public void isSamePerson() {
- // same object -> returns true
- assertTrue(ALICE.isSamePerson(ALICE));
-
- // null -> returns false
- assertFalse(ALICE.isSamePerson(null));
-
- // different phone and email -> returns false
- Person editedAlice = new PersonBuilder(ALICE).withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).build();
- assertFalse(ALICE.isSamePerson(editedAlice));
-
- // different name -> returns false
- editedAlice = new PersonBuilder(ALICE).withName(VALID_NAME_BOB).build();
- assertFalse(ALICE.isSamePerson(editedAlice));
-
- // same name, same phone, different attributes -> returns true
- editedAlice = new PersonBuilder(ALICE).withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB)
- .withTags(VALID_TAG_HUSBAND).build();
- assertTrue(ALICE.isSamePerson(editedAlice));
-
- // same name, same email, different attributes -> returns true
- editedAlice = new PersonBuilder(ALICE).withPhone(VALID_PHONE_BOB).withAddress(VALID_ADDRESS_BOB)
- .withTags(VALID_TAG_HUSBAND).build();
- assertTrue(ALICE.isSamePerson(editedAlice));
-
- // same name, same phone, same email, different attributes -> returns true
- editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND).build();
- assertTrue(ALICE.isSamePerson(editedAlice));
- }
-
- @Test
- public void equals() {
- // same values -> returns true
- Person aliceCopy = new PersonBuilder(ALICE).build();
- assertTrue(ALICE.equals(aliceCopy));
-
- // same object -> returns true
- assertTrue(ALICE.equals(ALICE));
-
- // null -> returns false
- assertFalse(ALICE.equals(null));
-
- // different type -> returns false
- assertFalse(ALICE.equals(5));
-
- // different person -> returns false
- assertFalse(ALICE.equals(BOB));
-
- // different name -> returns false
- Person editedAlice = new PersonBuilder(ALICE).withName(VALID_NAME_BOB).build();
- assertFalse(ALICE.equals(editedAlice));
-
- // different phone -> returns false
- editedAlice = new PersonBuilder(ALICE).withPhone(VALID_PHONE_BOB).build();
- assertFalse(ALICE.equals(editedAlice));
-
- // different email -> returns false
- editedAlice = new PersonBuilder(ALICE).withEmail(VALID_EMAIL_BOB).build();
- assertFalse(ALICE.equals(editedAlice));
-
- // different address -> returns false
- editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).build();
- assertFalse(ALICE.equals(editedAlice));
-
- // different tags -> returns false
- editedAlice = new PersonBuilder(ALICE).withTags(VALID_TAG_HUSBAND).build();
- assertFalse(ALICE.equals(editedAlice));
- }
-}
diff --git a/src/test/java/seedu/address/model/person/PhoneTest.java b/src/test/java/seedu/address/model/person/PhoneTest.java
deleted file mode 100644
index 8dd52766a5f..00000000000
--- a/src/test/java/seedu/address/model/person/PhoneTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package seedu.address.model.person;
-
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import org.junit.jupiter.api.Test;
-
-public class PhoneTest {
-
- @Test
- public void constructor_null_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> new Phone(null));
- }
-
- @Test
- public void constructor_invalidPhone_throwsIllegalArgumentException() {
- String invalidPhone = "";
- assertThrows(IllegalArgumentException.class, () -> new Phone(invalidPhone));
- }
-
- @Test
- public void isValidPhone() {
- // null phone number
- assertThrows(NullPointerException.class, () -> Phone.isValidPhone(null));
-
- // invalid phone numbers
- assertFalse(Phone.isValidPhone("")); // empty string
- assertFalse(Phone.isValidPhone(" ")); // spaces only
- assertFalse(Phone.isValidPhone("91")); // less than 3 numbers
- assertFalse(Phone.isValidPhone("phone")); // non-numeric
- assertFalse(Phone.isValidPhone("9011p041")); // alphabets within digits
- assertFalse(Phone.isValidPhone("9312 1534")); // spaces within digits
-
- // valid phone numbers
- assertTrue(Phone.isValidPhone("911")); // exactly 3 numbers
- assertTrue(Phone.isValidPhone("93121534"));
- assertTrue(Phone.isValidPhone("124293842033123")); // long phone numbers
- }
-}
diff --git a/src/test/java/seedu/address/model/person/UniquePersonListTest.java b/src/test/java/seedu/address/model/person/UniquePersonListTest.java
deleted file mode 100644
index 1cc5fe9e0fe..00000000000
--- a/src/test/java/seedu/address/model/person/UniquePersonListTest.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package seedu.address.model.person;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.ALICE;
-import static seedu.address.testutil.TypicalPersons.BOB;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.model.person.exceptions.DuplicatePersonException;
-import seedu.address.model.person.exceptions.PersonNotFoundException;
-import seedu.address.testutil.PersonBuilder;
-
-public class UniquePersonListTest {
-
- private final UniquePersonList uniquePersonList = new UniquePersonList();
-
- @Test
- public void contains_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> uniquePersonList.contains(null));
- }
-
- @Test
- public void contains_personNotInList_returnsFalse() {
- assertFalse(uniquePersonList.contains(ALICE));
- }
-
- @Test
- public void contains_personInList_returnsTrue() {
- uniquePersonList.add(ALICE);
- assertTrue(uniquePersonList.contains(ALICE));
- }
-
- @Test
- public void contains_personWithSameIdentityFieldsInList_returnsTrue() {
- uniquePersonList.add(ALICE);
- Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND)
- .build();
- assertTrue(uniquePersonList.contains(editedAlice));
- }
-
- @Test
- public void add_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> uniquePersonList.add(null));
- }
-
- @Test
- public void add_duplicatePerson_throwsDuplicatePersonException() {
- uniquePersonList.add(ALICE);
- assertThrows(DuplicatePersonException.class, () -> uniquePersonList.add(ALICE));
- }
-
- @Test
- public void setPerson_nullTargetPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> uniquePersonList.setPerson(null, ALICE));
- }
-
- @Test
- public void setPerson_nullEditedPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> uniquePersonList.setPerson(ALICE, null));
- }
-
- @Test
- public void setPerson_targetPersonNotInList_throwsPersonNotFoundException() {
- assertThrows(PersonNotFoundException.class, () -> uniquePersonList.setPerson(ALICE, ALICE));
- }
-
- @Test
- public void setPerson_editedPersonIsSamePerson_success() {
- uniquePersonList.add(ALICE);
- uniquePersonList.setPerson(ALICE, ALICE);
- UniquePersonList expectedUniquePersonList = new UniquePersonList();
- expectedUniquePersonList.add(ALICE);
- assertEquals(expectedUniquePersonList, uniquePersonList);
- }
-
- @Test
- public void setPerson_editedPersonHasSameIdentity_success() {
- uniquePersonList.add(ALICE);
- Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND)
- .build();
- uniquePersonList.setPerson(ALICE, editedAlice);
- UniquePersonList expectedUniquePersonList = new UniquePersonList();
- expectedUniquePersonList.add(editedAlice);
- assertEquals(expectedUniquePersonList, uniquePersonList);
- }
-
- @Test
- public void setPerson_editedPersonHasDifferentIdentity_success() {
- uniquePersonList.add(ALICE);
- uniquePersonList.setPerson(ALICE, BOB);
- UniquePersonList expectedUniquePersonList = new UniquePersonList();
- expectedUniquePersonList.add(BOB);
- assertEquals(expectedUniquePersonList, uniquePersonList);
- }
-
- @Test
- public void setPerson_editedPersonHasNonUniqueIdentity_throwsDuplicatePersonException() {
- uniquePersonList.add(ALICE);
- uniquePersonList.add(BOB);
- assertThrows(DuplicatePersonException.class, () -> uniquePersonList.setPerson(ALICE, BOB));
- }
-
- @Test
- public void remove_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> uniquePersonList.remove(null));
- }
-
- @Test
- public void remove_personDoesNotExist_throwsPersonNotFoundException() {
- assertThrows(PersonNotFoundException.class, () -> uniquePersonList.remove(ALICE));
- }
-
- @Test
- public void remove_existingPerson_removesPerson() {
- uniquePersonList.add(ALICE);
- uniquePersonList.remove(ALICE);
- UniquePersonList expectedUniquePersonList = new UniquePersonList();
- assertEquals(expectedUniquePersonList, uniquePersonList);
- }
-
- @Test
- public void setPersons_nullUniquePersonList_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> uniquePersonList.setPersons((UniquePersonList) null));
- }
-
- @Test
- public void setPersons_uniquePersonList_replacesOwnListWithProvidedUniquePersonList() {
- uniquePersonList.add(ALICE);
- UniquePersonList expectedUniquePersonList = new UniquePersonList();
- expectedUniquePersonList.add(BOB);
- uniquePersonList.setPersons(expectedUniquePersonList);
- assertEquals(expectedUniquePersonList, uniquePersonList);
- }
-
- @Test
- public void setPersons_nullList_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> uniquePersonList.setPersons((List) null));
- }
-
- @Test
- public void setPersons_list_replacesOwnListWithProvidedList() {
- uniquePersonList.add(ALICE);
- List personList = Collections.singletonList(BOB);
- uniquePersonList.setPersons(personList);
- UniquePersonList expectedUniquePersonList = new UniquePersonList();
- expectedUniquePersonList.add(BOB);
- assertEquals(expectedUniquePersonList, uniquePersonList);
- }
-
- @Test
- public void setPersons_listWithDuplicatePersons_throwsDuplicatePersonException() {
- List listWithDuplicatePersons = Arrays.asList(ALICE, ALICE);
- assertThrows(DuplicatePersonException.class, () -> uniquePersonList.setPersons(listWithDuplicatePersons));
- }
-
- @Test
- public void asUnmodifiableObservableList_modifyList_throwsUnsupportedOperationException() {
- assertThrows(UnsupportedOperationException.class, ()
- -> uniquePersonList.asUnmodifiableObservableList().remove(0));
- }
-}
diff --git a/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java b/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java
deleted file mode 100644
index 83b11331cdb..00000000000
--- a/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package seedu.address.storage;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static seedu.address.storage.JsonAdaptedPerson.MISSING_FIELD_MESSAGE_FORMAT;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.BENSON;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Phone;
-
-public class JsonAdaptedPersonTest {
- private static final String INVALID_NAME = "R@chel";
- private static final String INVALID_PHONE = "+651234";
- private static final String INVALID_ADDRESS = " ";
- private static final String INVALID_EMAIL = "example.com";
- private static final String INVALID_TAG = "#friend";
-
- private static final String VALID_NAME = BENSON.getName().toString();
- private static final String VALID_PHONE = BENSON.getPhone().toString();
- private static final String VALID_EMAIL = BENSON.getEmail().toString();
- private static final String VALID_ADDRESS = BENSON.getAddress().toString();
- private static final List VALID_TAGS = BENSON.getTags().stream()
- .map(JsonAdaptedTag::new)
- .collect(Collectors.toList());
-
- @Test
- public void toModelType_validPersonDetails_returnsPerson() throws Exception {
- JsonAdaptedPerson person = new JsonAdaptedPerson(BENSON);
- assertEquals(BENSON, person.toModelType());
- }
-
- @Test
- public void toModelType_invalidName_throwsIllegalValueException() {
- JsonAdaptedPerson person =
- new JsonAdaptedPerson(INVALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
- String expectedMessage = Name.MESSAGE_CONSTRAINTS;
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_nullName_throwsIllegalValueException() {
- JsonAdaptedPerson person = new JsonAdaptedPerson(null, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
- String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName());
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_invalidPhone_throwsIllegalValueException() {
- JsonAdaptedPerson person =
- new JsonAdaptedPerson(VALID_NAME, INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
- String expectedMessage = Phone.MESSAGE_CONSTRAINTS;
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_nullPhone_throwsIllegalValueException() {
- JsonAdaptedPerson person = new JsonAdaptedPerson(VALID_NAME, null, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
- String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName());
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_invalidEmail_throwsIllegalValueException() {
- JsonAdaptedPerson person =
- new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, INVALID_EMAIL, VALID_ADDRESS, VALID_TAGS);
- String expectedMessage = Email.MESSAGE_CONSTRAINTS;
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_nullEmail_throwsIllegalValueException() {
- JsonAdaptedPerson person = new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, null, VALID_ADDRESS, VALID_TAGS);
- String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName());
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_invalidAddress_throwsIllegalValueException() {
- JsonAdaptedPerson person =
- new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, INVALID_ADDRESS, VALID_TAGS);
- String expectedMessage = Address.MESSAGE_CONSTRAINTS;
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_nullAddress_throwsIllegalValueException() {
- JsonAdaptedPerson person = new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, null, VALID_TAGS);
- String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName());
- assertThrows(IllegalValueException.class, expectedMessage, person::toModelType);
- }
-
- @Test
- public void toModelType_invalidTags_throwsIllegalValueException() {
- List invalidTags = new ArrayList<>(VALID_TAGS);
- invalidTags.add(new JsonAdaptedTag(INVALID_TAG));
- JsonAdaptedPerson person =
- new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, invalidTags);
- assertThrows(IllegalValueException.class, person::toModelType);
- }
-
-}
diff --git a/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java b/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java
deleted file mode 100644
index ac3c3af9566..00000000000
--- a/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package seedu.address.storage;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.ALICE;
-import static seedu.address.testutil.TypicalPersons.HOON;
-import static seedu.address.testutil.TypicalPersons.IDA;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.AddressBook;
-import seedu.address.model.ReadOnlyAddressBook;
-
-public class JsonAddressBookStorageTest {
- private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonAddressBookStorageTest");
-
- @TempDir
- public Path testFolder;
-
- @Test
- public void readAddressBook_nullFilePath_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> readAddressBook(null));
- }
-
- private java.util.Optional readAddressBook(String filePath) throws Exception {
- return new JsonAddressBookStorage(Paths.get(filePath)).readAddressBook(addToTestDataPathIfNotNull(filePath));
- }
-
- private Path addToTestDataPathIfNotNull(String prefsFileInTestDataFolder) {
- return prefsFileInTestDataFolder != null
- ? TEST_DATA_FOLDER.resolve(prefsFileInTestDataFolder)
- : null;
- }
-
- @Test
- public void read_missingFile_emptyResult() throws Exception {
- assertFalse(readAddressBook("NonExistentFile.json").isPresent());
- }
-
- @Test
- public void read_notJsonFormat_exceptionThrown() {
- assertThrows(DataConversionException.class, () -> readAddressBook("notJsonFormatAddressBook.json"));
- }
-
- @Test
- public void readAddressBook_invalidPersonAddressBook_throwDataConversionException() {
- assertThrows(DataConversionException.class, () -> readAddressBook("invalidPersonAddressBook.json"));
- }
-
- @Test
- public void readAddressBook_invalidAndValidPersonAddressBook_throwDataConversionException() {
- assertThrows(DataConversionException.class, () -> readAddressBook("invalidAndValidPersonAddressBook.json"));
- }
-
- @Test
- public void readAndSaveAddressBook_allInOrder_success() throws Exception {
- Path filePath = testFolder.resolve("TempAddressBook.json");
- AddressBook original = getTypicalAddressBook();
- JsonAddressBookStorage jsonAddressBookStorage = new JsonAddressBookStorage(filePath);
-
- // Save in new file and read back
- jsonAddressBookStorage.saveAddressBook(original, filePath);
- ReadOnlyAddressBook readBack = jsonAddressBookStorage.readAddressBook(filePath).get();
- assertEquals(original, new AddressBook(readBack));
-
- // Modify data, overwrite exiting file, and read back
- original.addPerson(HOON);
- original.removePerson(ALICE);
- jsonAddressBookStorage.saveAddressBook(original, filePath);
- readBack = jsonAddressBookStorage.readAddressBook(filePath).get();
- assertEquals(original, new AddressBook(readBack));
-
- // Save and read without specifying file path
- original.addPerson(IDA);
- jsonAddressBookStorage.saveAddressBook(original); // file path not specified
- readBack = jsonAddressBookStorage.readAddressBook().get(); // file path not specified
- assertEquals(original, new AddressBook(readBack));
-
- }
-
- @Test
- public void saveAddressBook_nullAddressBook_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> saveAddressBook(null, "SomeFile.json"));
- }
-
- /**
- * Saves {@code addressBook} at the specified {@code filePath}.
- */
- private void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) {
- try {
- new JsonAddressBookStorage(Paths.get(filePath))
- .saveAddressBook(addressBook, addToTestDataPathIfNotNull(filePath));
- } catch (IOException ioe) {
- throw new AssertionError("There should not be an error writing to the file.", ioe);
- }
- }
-
- @Test
- public void saveAddressBook_nullFilePath_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> saveAddressBook(new AddressBook(), null));
- }
-}
diff --git a/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java b/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java
deleted file mode 100644
index 188c9058d20..00000000000
--- a/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package seedu.address.storage;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static seedu.address.testutil.Assert.assertThrows;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import org.junit.jupiter.api.Test;
-
-import seedu.address.commons.exceptions.IllegalValueException;
-import seedu.address.commons.util.JsonUtil;
-import seedu.address.model.AddressBook;
-import seedu.address.testutil.TypicalPersons;
-
-public class JsonSerializableAddressBookTest {
-
- private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonSerializableAddressBookTest");
- private static final Path TYPICAL_PERSONS_FILE = TEST_DATA_FOLDER.resolve("typicalPersonsAddressBook.json");
- private static final Path INVALID_PERSON_FILE = TEST_DATA_FOLDER.resolve("invalidPersonAddressBook.json");
- private static final Path DUPLICATE_PERSON_FILE = TEST_DATA_FOLDER.resolve("duplicatePersonAddressBook.json");
-
- @Test
- public void toModelType_typicalPersonsFile_success() throws Exception {
- JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(TYPICAL_PERSONS_FILE,
- JsonSerializableAddressBook.class).get();
- AddressBook addressBookFromFile = dataFromFile.toModelType();
- AddressBook typicalPersonsAddressBook = TypicalPersons.getTypicalAddressBook();
- assertEquals(addressBookFromFile, typicalPersonsAddressBook);
- }
-
- @Test
- public void toModelType_invalidPersonFile_throwsIllegalValueException() throws Exception {
- JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(INVALID_PERSON_FILE,
- JsonSerializableAddressBook.class).get();
- assertThrows(IllegalValueException.class, dataFromFile::toModelType);
- }
-
- @Test
- public void toModelType_duplicatePersons_throwsIllegalValueException() throws Exception {
- JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(DUPLICATE_PERSON_FILE,
- JsonSerializableAddressBook.class).get();
- assertThrows(IllegalValueException.class, JsonSerializableAddressBook.MESSAGE_DUPLICATE_PERSON,
- dataFromFile::toModelType);
- }
-
-}
diff --git a/src/test/java/seedu/address/testutil/AddressBookBuilder.java b/src/test/java/seedu/address/testutil/AddressBookBuilder.java
deleted file mode 100644
index d53799fd110..00000000000
--- a/src/test/java/seedu/address/testutil/AddressBookBuilder.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package seedu.address.testutil;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.person.Person;
-
-/**
- * A utility class to help with building Addressbook objects.
- * Example usage:
- * {@code AddressBook ab = new AddressBookBuilder().withPerson("John", "Doe").build();}
- */
-public class AddressBookBuilder {
-
- private AddressBook addressBook;
-
- public AddressBookBuilder() {
- addressBook = new AddressBook();
- }
-
- public AddressBookBuilder(AddressBook addressBook) {
- this.addressBook = addressBook;
- }
-
- /**
- * Adds a new {@code Person} to the {@code AddressBook} that we are building.
- */
- public AddressBookBuilder withPerson(Person person) {
- addressBook.addPerson(person);
- return this;
- }
-
- public AddressBook build() {
- return addressBook;
- }
-}
diff --git a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java b/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java
deleted file mode 100644
index 4584bd5044e..00000000000
--- a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package seedu.address.testutil;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-
-/**
- * A utility class to help with building EditPersonDescriptor objects.
- */
-public class EditPersonDescriptorBuilder {
-
- private EditPersonDescriptor descriptor;
-
- public EditPersonDescriptorBuilder() {
- descriptor = new EditPersonDescriptor();
- }
-
- public EditPersonDescriptorBuilder(EditPersonDescriptor descriptor) {
- this.descriptor = new EditPersonDescriptor(descriptor);
- }
-
- /**
- * Returns an {@code EditPersonDescriptor} with fields containing {@code person}'s details
- */
- public EditPersonDescriptorBuilder(Person person) {
- descriptor = new EditPersonDescriptor();
- descriptor.setName(person.getName());
- descriptor.setPhone(person.getPhone());
- descriptor.setEmail(person.getEmail());
- descriptor.setAddress(person.getAddress());
- descriptor.setTags(person.getTags());
- }
-
- /**
- * Sets the {@code Name} of the {@code EditPersonDescriptor} that we are building.
- */
- public EditPersonDescriptorBuilder withName(String name) {
- descriptor.setName(new Name(name));
- return this;
- }
-
- /**
- * Sets the {@code Phone} of the {@code EditPersonDescriptor} that we are building.
- */
- public EditPersonDescriptorBuilder withPhone(String phone) {
- descriptor.setPhone(new Phone(phone));
- return this;
- }
-
- /**
- * Sets the {@code Email} of the {@code EditPersonDescriptor} that we are building.
- */
- public EditPersonDescriptorBuilder withEmail(String email) {
- descriptor.setEmail(new Email(email));
- return this;
- }
-
- /**
- * Sets the {@code Address} of the {@code EditPersonDescriptor} that we are building.
- */
- public EditPersonDescriptorBuilder withAddress(String address) {
- descriptor.setAddress(new Address(address));
- return this;
- }
-
- /**
- * Parses the {@code tags} into a {@code Set} and set it to the {@code EditPersonDescriptor}
- * that we are building.
- */
- public EditPersonDescriptorBuilder withTags(String... tags) {
- Set tagSet = Stream.of(tags).map(Tag::new).collect(Collectors.toSet());
- descriptor.setTags(tagSet);
- return this;
- }
-
- public EditPersonDescriptor build() {
- return descriptor;
- }
-}
diff --git a/src/test/java/seedu/address/testutil/PersonBuilder.java b/src/test/java/seedu/address/testutil/PersonBuilder.java
deleted file mode 100644
index efe744cd12c..00000000000
--- a/src/test/java/seedu/address/testutil/PersonBuilder.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package seedu.address.testutil;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import seedu.address.model.person.Address;
-import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
-import seedu.address.model.person.Person;
-import seedu.address.model.person.Phone;
-import seedu.address.model.tag.Tag;
-import seedu.address.model.util.SampleDataUtil;
-
-/**
- * A utility class to help with building Person objects.
- */
-public class PersonBuilder {
-
- public static final String DEFAULT_NAME = "Alice Pauline";
- public static final String DEFAULT_PHONE = "85355255";
- public static final String DEFAULT_EMAIL = "alice@gmail.com";
- public static final String DEFAULT_ADDRESS = "123, Jurong West Ave 6, #08-111";
-
- private Name name;
- private Phone phone;
- private Email email;
- private Address address;
- private Set tags;
-
- /**
- * Creates a {@code PersonBuilder} with the default details.
- */
- public PersonBuilder() {
- name = new Name(DEFAULT_NAME);
- phone = new Phone(DEFAULT_PHONE);
- email = new Email(DEFAULT_EMAIL);
- address = new Address(DEFAULT_ADDRESS);
- tags = new HashSet<>();
- }
-
- /**
- * Initializes the PersonBuilder with the data of {@code personToCopy}.
- */
- public PersonBuilder(Person personToCopy) {
- name = personToCopy.getName();
- phone = personToCopy.getPhone();
- email = personToCopy.getEmail();
- address = personToCopy.getAddress();
- tags = new HashSet<>(personToCopy.getTags());
- }
-
- /**
- * Sets the {@code Name} of the {@code Person} that we are building.
- */
- public PersonBuilder withName(String name) {
- this.name = new Name(name);
- return this;
- }
-
- /**
- * Parses the {@code tags} into a {@code Set} and set it to the {@code Person} that we are building.
- */
- public PersonBuilder withTags(String ... tags) {
- this.tags = SampleDataUtil.getTagSet(tags);
- return this;
- }
-
- /**
- * Sets the {@code Address} of the {@code Person} that we are building.
- */
- public PersonBuilder withAddress(String address) {
- this.address = new Address(address);
- return this;
- }
-
- /**
- * Sets the {@code Phone} of the {@code Person} that we are building.
- */
- public PersonBuilder withPhone(String phone) {
- this.phone = new Phone(phone);
- return this;
- }
-
- /**
- * Sets the {@code Email} of the {@code Person} that we are building.
- */
- public PersonBuilder withEmail(String email) {
- this.email = new Email(email);
- return this;
- }
-
- public Person build() {
- return new Person(name, phone, email, address, tags);
- }
-
-}
diff --git a/src/test/java/seedu/address/testutil/PersonUtil.java b/src/test/java/seedu/address/testutil/PersonUtil.java
deleted file mode 100644
index 90849945183..00000000000
--- a/src/test/java/seedu/address/testutil/PersonUtil.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package seedu.address.testutil;
-
-import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
-import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-
-import java.util.Set;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.model.person.Person;
-import seedu.address.model.tag.Tag;
-
-/**
- * A utility class for Person.
- */
-public class PersonUtil {
-
- /**
- * Returns an add command string for adding the {@code person}.
- */
- public static String getAddCommand(Person person) {
- return AddCommand.COMMAND_WORD + " " + getPersonDetails(person);
- }
-
- /**
- * Returns the part of command string for the given {@code person}'s details.
- */
- public static String getPersonDetails(Person person) {
- StringBuilder sb = new StringBuilder();
- sb.append(PREFIX_NAME + person.getName().fullName + " ");
- sb.append(PREFIX_PHONE + person.getPhone().value + " ");
- sb.append(PREFIX_EMAIL + person.getEmail().value + " ");
- sb.append(PREFIX_ADDRESS + person.getAddress().value + " ");
- person.getTags().stream().forEach(
- s -> sb.append(PREFIX_TAG + s.tagName + " ")
- );
- return sb.toString();
- }
-
- /**
- * Returns the part of command string for the given {@code EditPersonDescriptor}'s details.
- */
- public static String getEditPersonDescriptorDetails(EditPersonDescriptor descriptor) {
- StringBuilder sb = new StringBuilder();
- descriptor.getName().ifPresent(name -> sb.append(PREFIX_NAME).append(name.fullName).append(" "));
- descriptor.getPhone().ifPresent(phone -> sb.append(PREFIX_PHONE).append(phone.value).append(" "));
- descriptor.getEmail().ifPresent(email -> sb.append(PREFIX_EMAIL).append(email.value).append(" "));
- descriptor.getAddress().ifPresent(address -> sb.append(PREFIX_ADDRESS).append(address.value).append(" "));
- if (descriptor.getTags().isPresent()) {
- Set tags = descriptor.getTags().get();
- if (tags.isEmpty()) {
- sb.append(PREFIX_TAG);
- } else {
- tags.forEach(s -> sb.append(PREFIX_TAG).append(s.tagName).append(" "));
- }
- }
- return sb.toString();
- }
-}
diff --git a/src/test/java/seedu/address/testutil/TypicalIndexes.java b/src/test/java/seedu/address/testutil/TypicalIndexes.java
deleted file mode 100644
index 1e613937657..00000000000
--- a/src/test/java/seedu/address/testutil/TypicalIndexes.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package seedu.address.testutil;
-
-import seedu.address.commons.core.index.Index;
-
-/**
- * A utility class containing a list of {@code Index} objects to be used in tests.
- */
-public class TypicalIndexes {
- public static final Index INDEX_FIRST_PERSON = Index.fromOneBased(1);
- public static final Index INDEX_SECOND_PERSON = Index.fromOneBased(2);
- public static final Index INDEX_THIRD_PERSON = Index.fromOneBased(3);
-}
diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java
deleted file mode 100644
index fec76fb7129..00000000000
--- a/src/test/java/seedu/address/testutil/TypicalPersons.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package seedu.address.testutil;
-
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND;
-import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.person.Person;
-
-/**
- * A utility class containing a list of {@code Person} objects to be used in tests.
- */
-public class TypicalPersons {
-
- public static final Person ALICE = new PersonBuilder().withName("Alice Pauline")
- .withAddress("123, Jurong West Ave 6, #08-111").withEmail("alice@example.com")
- .withPhone("94351253")
- .withTags("friends").build();
- public static final Person BENSON = new PersonBuilder().withName("Benson Meier")
- .withAddress("311, Clementi Ave 2, #02-25")
- .withEmail("johnd@example.com").withPhone("98765432")
- .withTags("owesMoney", "friends").build();
- public static final Person CARL = new PersonBuilder().withName("Carl Kurz").withPhone("95352563")
- .withEmail("heinz@example.com").withAddress("wall street").build();
- public static final Person DANIEL = new PersonBuilder().withName("Daniel Meier").withPhone("87652533")
- .withEmail("cornelia@example.com").withAddress("10th street").withTags("friends").build();
- public static final Person ELLE = new PersonBuilder().withName("Elle Meyer").withPhone("9482224")
- .withEmail("werner@example.com").withAddress("michegan ave").build();
- public static final Person FIONA = new PersonBuilder().withName("Fiona Kunz").withPhone("9482427")
- .withEmail("lydia@example.com").withAddress("little tokyo").build();
- public static final Person GEORGE = new PersonBuilder().withName("George Best").withPhone("9482442")
- .withEmail("anna@example.com").withAddress("4th street").build();
-
- // Manually added
- public static final Person HOON = new PersonBuilder().withName("Hoon Meier").withPhone("8482424")
- .withEmail("stefan@example.com").withAddress("little india").build();
- public static final Person IDA = new PersonBuilder().withName("Ida Mueller").withPhone("8482131")
- .withEmail("hans@example.com").withAddress("chicago ave").build();
-
- // Manually added - Person's details found in {@code CommandTestUtil}
- public static final Person AMY = new PersonBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY)
- .withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY).withTags(VALID_TAG_FRIEND).build();
- public static final Person BOB = new PersonBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
- .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND)
- .build();
-
- public static final String KEYWORD_MATCHING_MEIER = "Meier"; // A keyword that matches MEIER
-
- private TypicalPersons() {} // prevents instantiation
-
- /**
- * Returns an {@code AddressBook} with all the typical persons.
- */
- public static AddressBook getTypicalAddressBook() {
- AddressBook ab = new AddressBook();
- for (Person person : getTypicalPersons()) {
- ab.addPerson(person);
- }
- return ab;
- }
-
- public static List getTypicalPersons() {
- return new ArrayList<>(Arrays.asList(ALICE, BENSON, CARL, DANIEL, ELLE, FIONA, GEORGE));
- }
-}
diff --git a/src/test/java/seedu/address/AppParametersTest.java b/src/test/java/seedu/medmoriser/AppParametersTest.java
similarity index 98%
rename from src/test/java/seedu/address/AppParametersTest.java
rename to src/test/java/seedu/medmoriser/AppParametersTest.java
index 61326b2d31a..2e9e14ca097 100644
--- a/src/test/java/seedu/address/AppParametersTest.java
+++ b/src/test/java/seedu/medmoriser/AppParametersTest.java
@@ -1,4 +1,4 @@
-package seedu.address;
+package seedu.medmoriser;
import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/src/test/java/seedu/address/commons/core/ConfigTest.java b/src/test/java/seedu/medmoriser/commons/core/ConfigTest.java
similarity index 94%
rename from src/test/java/seedu/address/commons/core/ConfigTest.java
rename to src/test/java/seedu/medmoriser/commons/core/ConfigTest.java
index 07cd7f73d53..a4a5f389598 100644
--- a/src/test/java/seedu/address/commons/core/ConfigTest.java
+++ b/src/test/java/seedu/medmoriser/commons/core/ConfigTest.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.core;
+package seedu.medmoriser.commons.core;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
diff --git a/src/test/java/seedu/address/commons/core/VersionTest.java b/src/test/java/seedu/medmoriser/commons/core/VersionTest.java
similarity index 97%
rename from src/test/java/seedu/address/commons/core/VersionTest.java
rename to src/test/java/seedu/medmoriser/commons/core/VersionTest.java
index 495cd231554..8eb3ebd38fb 100644
--- a/src/test/java/seedu/address/commons/core/VersionTest.java
+++ b/src/test/java/seedu/medmoriser/commons/core/VersionTest.java
@@ -1,8 +1,8 @@
-package seedu.address.commons.core;
+package seedu.medmoriser.commons.core;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/seedu/address/commons/core/index/IndexTest.java b/src/test/java/seedu/medmoriser/commons/core/index/IndexTest.java
similarity index 72%
rename from src/test/java/seedu/address/commons/core/index/IndexTest.java
rename to src/test/java/seedu/medmoriser/commons/core/index/IndexTest.java
index a3ec6f8e747..5591cf87600 100644
--- a/src/test/java/seedu/address/commons/core/index/IndexTest.java
+++ b/src/test/java/seedu/medmoriser/commons/core/index/IndexTest.java
@@ -1,9 +1,9 @@
-package seedu.address.commons.core.index;
+package seedu.medmoriser.commons.core.index;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
import org.junit.jupiter.api.Test;
@@ -39,22 +39,22 @@ public void createZeroBasedIndex() {
@Test
public void equals() {
- final Index fifthPersonIndex = Index.fromOneBased(5);
+ final Index fifthQuestionSetIndex = Index.fromOneBased(5);
// same values -> returns true
- assertTrue(fifthPersonIndex.equals(Index.fromOneBased(5)));
- assertTrue(fifthPersonIndex.equals(Index.fromZeroBased(4)));
+ assertTrue(fifthQuestionSetIndex.equals(Index.fromOneBased(5)));
+ assertTrue(fifthQuestionSetIndex.equals(Index.fromZeroBased(4)));
// same object -> returns true
- assertTrue(fifthPersonIndex.equals(fifthPersonIndex));
+ assertTrue(fifthQuestionSetIndex.equals(fifthQuestionSetIndex));
// null -> returns false
- assertFalse(fifthPersonIndex.equals(null));
+ assertFalse(fifthQuestionSetIndex.equals(null));
// different types -> returns false
- assertFalse(fifthPersonIndex.equals(5.0f));
+ assertFalse(fifthQuestionSetIndex.equals(5.0f));
// different index -> returns false
- assertFalse(fifthPersonIndex.equals(Index.fromOneBased(1)));
+ assertFalse(fifthQuestionSetIndex.equals(Index.fromOneBased(1)));
}
}
diff --git a/src/test/java/seedu/address/commons/util/AppUtilTest.java b/src/test/java/seedu/medmoriser/commons/util/AppUtilTest.java
similarity index 91%
rename from src/test/java/seedu/address/commons/util/AppUtilTest.java
rename to src/test/java/seedu/medmoriser/commons/util/AppUtilTest.java
index 594de1e6365..a5d86f55518 100644
--- a/src/test/java/seedu/address/commons/util/AppUtilTest.java
+++ b/src/test/java/seedu/medmoriser/commons/util/AppUtilTest.java
@@ -1,7 +1,7 @@
-package seedu.address.commons.util;
+package seedu.medmoriser.commons.util;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/seedu/address/commons/util/CollectionUtilTest.java b/src/test/java/seedu/medmoriser/commons/util/CollectionUtilTest.java
similarity index 96%
rename from src/test/java/seedu/address/commons/util/CollectionUtilTest.java
rename to src/test/java/seedu/medmoriser/commons/util/CollectionUtilTest.java
index b467a3dc025..f48b91ab2da 100644
--- a/src/test/java/seedu/address/commons/util/CollectionUtilTest.java
+++ b/src/test/java/seedu/medmoriser/commons/util/CollectionUtilTest.java
@@ -1,9 +1,9 @@
-package seedu.address.commons.util;
+package seedu.medmoriser.commons.util;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medmoriser.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
import java.util.Arrays;
import java.util.Collection;
diff --git a/src/test/java/seedu/address/commons/util/ConfigUtilTest.java b/src/test/java/seedu/medmoriser/commons/util/ConfigUtilTest.java
similarity index 94%
rename from src/test/java/seedu/address/commons/util/ConfigUtilTest.java
rename to src/test/java/seedu/medmoriser/commons/util/ConfigUtilTest.java
index d2ab2839a52..88d054a8ceb 100644
--- a/src/test/java/seedu/address/commons/util/ConfigUtilTest.java
+++ b/src/test/java/seedu/medmoriser/commons/util/ConfigUtilTest.java
@@ -1,8 +1,8 @@
-package seedu.address.commons.util;
+package seedu.medmoriser.commons.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
import java.io.IOException;
import java.nio.file.Path;
@@ -13,8 +13,8 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
-import seedu.address.commons.core.Config;
-import seedu.address.commons.exceptions.DataConversionException;
+import seedu.medmoriser.commons.core.Config;
+import seedu.medmoriser.commons.exceptions.DataConversionException;
public class ConfigUtilTest {
diff --git a/src/test/java/seedu/address/commons/util/FileUtilTest.java b/src/test/java/seedu/medmoriser/commons/util/FileUtilTest.java
similarity index 84%
rename from src/test/java/seedu/address/commons/util/FileUtilTest.java
rename to src/test/java/seedu/medmoriser/commons/util/FileUtilTest.java
index 1fe5478c756..cd6884eb727 100644
--- a/src/test/java/seedu/address/commons/util/FileUtilTest.java
+++ b/src/test/java/seedu/medmoriser/commons/util/FileUtilTest.java
@@ -1,8 +1,8 @@
-package seedu.address.commons.util;
+package seedu.medmoriser.commons.util;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/seedu/address/commons/util/JsonUtilTest.java b/src/test/java/seedu/medmoriser/commons/util/JsonUtilTest.java
similarity index 92%
rename from src/test/java/seedu/address/commons/util/JsonUtilTest.java
rename to src/test/java/seedu/medmoriser/commons/util/JsonUtilTest.java
index d4907539dee..95b345cb7c3 100644
--- a/src/test/java/seedu/address/commons/util/JsonUtilTest.java
+++ b/src/test/java/seedu/medmoriser/commons/util/JsonUtilTest.java
@@ -1,4 +1,4 @@
-package seedu.address.commons.util;
+package seedu.medmoriser.commons.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -7,8 +7,8 @@
import org.junit.jupiter.api.Test;
-import seedu.address.testutil.SerializableTestClass;
-import seedu.address.testutil.TestUtil;
+import seedu.medmoriser.testutil.SerializableTestClass;
+import seedu.medmoriser.testutil.TestUtil;
/**
* Tests JSON Read and Write
diff --git a/src/test/java/seedu/address/commons/util/StringUtilTest.java b/src/test/java/seedu/medmoriser/commons/util/StringUtilTest.java
similarity index 98%
rename from src/test/java/seedu/address/commons/util/StringUtilTest.java
rename to src/test/java/seedu/medmoriser/commons/util/StringUtilTest.java
index c56d407bf3f..3811f02a821 100644
--- a/src/test/java/seedu/address/commons/util/StringUtilTest.java
+++ b/src/test/java/seedu/medmoriser/commons/util/StringUtilTest.java
@@ -1,8 +1,8 @@
-package seedu.address.commons.util;
+package seedu.medmoriser.commons.util;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
import java.io.FileNotFoundException;
diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/seedu/medmoriser/logic/LogicManagerTest.java
similarity index 63%
rename from src/test/java/seedu/address/logic/LogicManagerTest.java
rename to src/test/java/seedu/medmoriser/logic/LogicManagerTest.java
index ad923ac249a..dfd5045732d 100644
--- a/src/test/java/seedu/address/logic/LogicManagerTest.java
+++ b/src/test/java/seedu/medmoriser/logic/LogicManagerTest.java
@@ -1,14 +1,12 @@
-package seedu.address.logic;
+package seedu.medmoriser.logic;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX;
-import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
-import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY;
-import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.AMY;
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_QANDA_DISPLAYED_INDEX;
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.ANSWER_DESC_A;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.QUESTION_DESC_A;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTIONA;
import java.io.IOException;
import java.nio.file.Path;
@@ -17,20 +15,20 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.commands.CommandResult;
-import seedu.address.logic.commands.ListCommand;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.person.Person;
-import seedu.address.storage.JsonAddressBookStorage;
-import seedu.address.storage.JsonUserPrefsStorage;
-import seedu.address.storage.StorageManager;
-import seedu.address.testutil.PersonBuilder;
+import seedu.medmoriser.logic.commands.AddCommand;
+import seedu.medmoriser.logic.commands.CommandResult;
+import seedu.medmoriser.logic.commands.ListCommand;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ModelManager;
+import seedu.medmoriser.model.ReadOnlyMedmoriser;
+import seedu.medmoriser.model.UserPrefs;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.storage.JsonMedmoriserStorage;
+import seedu.medmoriser.storage.JsonUserPrefsStorage;
+import seedu.medmoriser.storage.StorageManager;
+import seedu.medmoriser.testutil.QAndABuilder;
public class LogicManagerTest {
private static final IOException DUMMY_IO_EXCEPTION = new IOException("dummy exception");
@@ -43,10 +41,10 @@ public class LogicManagerTest {
@BeforeEach
public void setUp() {
- JsonAddressBookStorage addressBookStorage =
- new JsonAddressBookStorage(temporaryFolder.resolve("addressBook.json"));
+ JsonMedmoriserStorage medmoriserStorage =
+ new JsonMedmoriserStorage(temporaryFolder.resolve("medmoriser.json"));
JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(temporaryFolder.resolve("userPrefs.json"));
- StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage);
+ StorageManager storage = new StorageManager(medmoriserStorage, userPrefsStorage);
logic = new LogicManager(model, storage);
}
@@ -59,38 +57,37 @@ public void execute_invalidCommandFormat_throwsParseException() {
@Test
public void execute_commandExecutionError_throwsCommandException() {
String deleteCommand = "delete 9";
- assertCommandException(deleteCommand, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ assertCommandException(deleteCommand, MESSAGE_INVALID_QANDA_DISPLAYED_INDEX);
}
@Test
public void execute_validCommand_success() throws Exception {
String listCommand = ListCommand.COMMAND_WORD;
- assertCommandSuccess(listCommand, ListCommand.MESSAGE_SUCCESS, model);
+ assertCommandSuccess(listCommand, ListCommand.MESSAGE_LIST_ALL_SUCCESS, model);
}
@Test
public void execute_storageThrowsIoException_throwsCommandException() {
// Setup LogicManager with JsonAddressBookIoExceptionThrowingStub
- JsonAddressBookStorage addressBookStorage =
- new JsonAddressBookIoExceptionThrowingStub(temporaryFolder.resolve("ioExceptionAddressBook.json"));
+ JsonMedmoriserStorage medmoriserStorage =
+ new JsonMedmoriserIoExceptionThrowingStub(temporaryFolder.resolve("ioExceptionMedmoriser.json"));
JsonUserPrefsStorage userPrefsStorage =
new JsonUserPrefsStorage(temporaryFolder.resolve("ioExceptionUserPrefs.json"));
- StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage);
+ StorageManager storage = new StorageManager(medmoriserStorage, userPrefsStorage);
logic = new LogicManager(model, storage);
// Execute add command
- String addCommand = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY
- + ADDRESS_DESC_AMY;
- Person expectedPerson = new PersonBuilder(AMY).withTags().build();
+ String addCommand = AddCommand.COMMAND_WORD + QUESTION_DESC_A + ANSWER_DESC_A;
+ QAndA expectedQAndA = new QAndABuilder(QUESTIONA).withTags().build();
ModelManager expectedModel = new ModelManager();
- expectedModel.addPerson(expectedPerson);
+ expectedModel.addQAndA(expectedQAndA);
String expectedMessage = LogicManager.FILE_OPS_ERROR_MESSAGE + DUMMY_IO_EXCEPTION;
assertCommandFailure(addCommand, CommandException.class, expectedMessage, expectedModel);
}
@Test
- public void getFilteredPersonList_modifyList_throwsUnsupportedOperationException() {
- assertThrows(UnsupportedOperationException.class, () -> logic.getFilteredPersonList().remove(0));
+ public void getFilteredQAndAList_modifyList_throwsUnsupportedOperationException() {
+ assertThrows(UnsupportedOperationException.class, () -> logic.getFilteredQAndAList().remove(0));
}
/**
@@ -129,7 +126,7 @@ private void assertCommandException(String inputCommand, String expectedMessage)
*/
private void assertCommandFailure(String inputCommand, Class extends Throwable> expectedException,
String expectedMessage) {
- Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ Model expectedModel = new ModelManager(model.getMedmoriser(), new UserPrefs());
assertCommandFailure(inputCommand, expectedException, expectedMessage, expectedModel);
}
@@ -149,13 +146,13 @@ private void assertCommandFailure(String inputCommand, Class extends Throwable
/**
* A stub class to throw an {@code IOException} when the save method is called.
*/
- private static class JsonAddressBookIoExceptionThrowingStub extends JsonAddressBookStorage {
- private JsonAddressBookIoExceptionThrowingStub(Path filePath) {
+ private static class JsonMedmoriserIoExceptionThrowingStub extends JsonMedmoriserStorage {
+ private JsonMedmoriserIoExceptionThrowingStub(Path filePath) {
super(filePath);
}
@Override
- public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException {
+ public void saveMedmoriser(ReadOnlyMedmoriser medmoriser, Path filePath) throws IOException {
throw DUMMY_IO_EXCEPTION;
}
}
diff --git a/src/test/java/seedu/medmoriser/logic/commands/AddCommandIntegrationTest.java b/src/test/java/seedu/medmoriser/logic/commands/AddCommandIntegrationTest.java
new file mode 100644
index 00000000000..4d875bd7962
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/commands/AddCommandIntegrationTest.java
@@ -0,0 +1,45 @@
+package seedu.medmoriser.logic.commands;
+
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.medmoriser.testutil.TypicalQAndA.getTypicalMedmoriser;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ModelManager;
+import seedu.medmoriser.model.UserPrefs;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.testutil.QAndABuilder;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code AddCommand}.
+ */
+public class AddCommandIntegrationTest {
+
+ private Model model;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager(getTypicalMedmoriser(), new UserPrefs());
+ }
+
+ @Test
+ public void execute_newQAndA_success() {
+ QAndA validQAndA = new QAndABuilder().build();
+
+ Model expectedModel = new ModelManager(model.getMedmoriser(), new UserPrefs());
+ expectedModel.addQAndA(validQAndA);
+
+ assertCommandSuccess(new AddCommand(validQAndA), model,
+ String.format(AddCommand.MESSAGE_SUCCESS, validQAndA), expectedModel);
+ }
+
+ @Test
+ public void execute_duplicateQAndA_throwsCommandException() {
+ QAndA qAndAInList = model.getMedmoriser().getQAndAList().get(0);
+ assertCommandFailure(new AddCommand(qAndAInList), model, AddCommand.MESSAGE_DUPLICATE_QANDA);
+ }
+
+}
diff --git a/src/test/java/seedu/medmoriser/logic/commands/AddCommandTest.java b/src/test/java/seedu/medmoriser/logic/commands/AddCommandTest.java
new file mode 100644
index 00000000000..9f9ab27b49e
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/commands/AddCommandTest.java
@@ -0,0 +1,210 @@
+package seedu.medmoriser.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.function.Predicate;
+
+import org.junit.jupiter.api.Test;
+
+import javafx.collections.ObservableList;
+import seedu.medmoriser.commons.core.GuiSettings;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Medmoriser;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ReadOnlyMedmoriser;
+import seedu.medmoriser.model.ReadOnlyUserPrefs;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.testutil.QAndABuilder;
+
+public class AddCommandTest {
+
+ @Test
+ public void constructor_nullQAndA_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> new AddCommand(null));
+ }
+
+ @Test
+ public void execute_qAndAAcceptedByModel_addSuccessful() throws Exception {
+ ModelStubAcceptingQAndAAdded modelStub = new ModelStubAcceptingQAndAAdded();
+ QAndA validQAndA = new QAndABuilder().build();
+
+ CommandResult commandResult = new AddCommand(validQAndA).execute(modelStub);
+
+ assertEquals(String.format(AddCommand.MESSAGE_SUCCESS, validQAndA), commandResult.getFeedbackToUser());
+ assertEquals(Arrays.asList(validQAndA), modelStub.qAndAsAdded);
+ }
+
+ @Test
+ public void execute_duplicateQAndA_throwsCommandException() {
+ QAndA validQAndA = new QAndABuilder().build();
+ AddCommand addCommand = new AddCommand(validQAndA);
+ ModelStub modelStub = new ModelStubWithQAndA(validQAndA);
+
+ assertThrows(CommandException.class, AddCommand.MESSAGE_DUPLICATE_QANDA, () ->
+ addCommand.execute(modelStub)
+ );
+ }
+
+ @Test
+ public void execute_answersHidden_successAndShowsAnswers() throws Exception {
+ ListCommand listCommand = new ListCommand(false);
+ ModelStubAcceptingQAndAAdded modelStub = new ModelStubAcceptingQAndAAdded();
+ QAndA validQAndA = new QAndABuilder().build();
+
+ CommandResult commandResult = new AddCommand(validQAndA).execute(modelStub);
+ assertTrue(commandResult.isAnswerDisplayed());
+ }
+
+ @Test
+ public void equals() {
+ QAndA alice = new QAndABuilder().withQuestion("Alice").build();
+ QAndA bob = new QAndABuilder().withQuestion("Bob").build();
+ AddCommand addAliceCommand = new AddCommand(alice);
+ AddCommand addBobCommand = new AddCommand(bob);
+
+ // same object -> returns true
+ assertTrue(addAliceCommand.equals(addAliceCommand));
+
+ // same values -> returns true
+ AddCommand addAliceCommandCopy = new AddCommand(alice);
+ assertTrue(addAliceCommand.equals(addAliceCommandCopy));
+
+ // different types -> returns false
+ assertFalse(addAliceCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(addAliceCommand.equals(null));
+
+ // different qAndA -> returns false
+ assertFalse(addAliceCommand.equals(addBobCommand));
+ }
+
+ /**
+ * A default model stub that have all of the methods failing.
+ */
+ private class ModelStub implements Model {
+ @Override
+ public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyUserPrefs getUserPrefs() {
+ throw new AssertionError("This method"
+ + " should not be called.");
+ }
+
+ @Override
+ public GuiSettings getGuiSettings() {
+ throw new AssertionError("This method "
+ + "should not be called.");
+ }
+
+ @Override
+ public void setGuiSettings(GuiSettings guiSettings) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public Path getMedmoriserFilePath() {
+ throw new AssertionError("This method "
+ + "should not be called.");
+ }
+
+ @Override
+ public void setMedmoriserFilePath(Path medmoriserFilePath) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void addQAndA(QAndA qAndA) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setMedmoriser(ReadOnlyMedmoriser medmoriser) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyMedmoriser getMedmoriser() {
+ throw new AssertionError("This method should"
+ + " not be called.");
+ }
+
+ @Override
+ public boolean hasQAndA(QAndA qAndA) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void deleteQAndA(QAndA target) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setQAndA(QAndA target, QAndA editedQAndA) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ObservableList getFilteredQAndAList() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void updateFilteredQAndAList(Predicate predicate) {
+ throw new AssertionError("This method should not be called.");
+ }
+ }
+
+ /**
+ * A Model stub that contains a single qAndA.
+ */
+ private class ModelStubWithQAndA extends ModelStub {
+ private final QAndA qAndA;
+
+ ModelStubWithQAndA(QAndA qAndA) {
+ requireNonNull(qAndA);
+ this.qAndA = qAndA;
+ }
+
+ @Override
+ public boolean hasQAndA(QAndA qAndA) {
+ requireNonNull(qAndA);
+ return this.qAndA.isSameQAndA(qAndA);
+ }
+ }
+
+ /**
+ * A Model stub that always accept the qAndA being added.
+ */
+ private class ModelStubAcceptingQAndAAdded extends ModelStub {
+ final ArrayList qAndAsAdded = new ArrayList<>();
+
+ @Override
+ public boolean hasQAndA(QAndA qAndA) {
+ requireNonNull(qAndA);
+ return qAndAsAdded.stream().anyMatch(qAndA::isSameQAndA);
+ }
+
+ @Override
+ public void addQAndA(QAndA qAndA) {
+ requireNonNull(qAndA);
+ qAndAsAdded.add(qAndA);
+ }
+
+ @Override
+ public ReadOnlyMedmoriser getMedmoriser() {
+ return new Medmoriser();
+ }
+ }
+
+}
diff --git a/src/test/java/seedu/medmoriser/logic/commands/AnswerCommandTest.java b/src/test/java/seedu/medmoriser/logic/commands/AnswerCommandTest.java
new file mode 100644
index 00000000000..b6b6fac6f33
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/commands/AnswerCommandTest.java
@@ -0,0 +1,66 @@
+package seedu.medmoriser.logic.commands;
+
+import static seedu.medmoriser.logic.commands.AnswerCommand.MESSAGE_ALREADY_ANSWERED;
+import static seedu.medmoriser.logic.commands.AnswerCommand.MESSAGE_NOT_QUIZ;
+import static seedu.medmoriser.logic.commands.AnswerCommand.MESSAGE_USER_ANSWER;
+import static seedu.medmoriser.logic.commands.AnswerCommand.setCurrCommandResult;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.medmoriser.testutil.TypicalQAndA.getTypicalMedmoriser;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ModelManager;
+import seedu.medmoriser.model.UserPrefs;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.testutil.TypicalQAndA;
+
+public class AnswerCommandTest {
+
+ public static final String USER_ANSWER_1 = "Some answer";
+ public static final String USER_ANSWER_2 = "Another answer";
+
+ private Model model = new ModelManager(getTypicalMedmoriser(), new UserPrefs());
+
+ @Test
+ public void execute_answerNoOngoingQuiz_failure() {
+ QuizCommand.setIsQuiz(false, model);
+
+ // because model not supposed to change after answer command execution
+ Model expectedModel = model;
+
+ AnswerCommand answerCommand = new AnswerCommand(USER_ANSWER_1);
+ assertCommandFailure(answerCommand, model, MESSAGE_NOT_QUIZ);
+ }
+
+ @Test
+ public void execute_answerOngoingQuizHasBeenAnswered_failure() {
+ QuizCommand.setIsQuiz(true, model);
+ setCurrCommandResult(USER_ANSWER_2);
+ AnswerCommand answerCommand = new AnswerCommand(USER_ANSWER_1);
+
+ AnswerCommand.setBeenAnswered(true, model);
+ model.getFilteredQAndAList().get(0).setQuizAnswer();
+
+ String repeatedAnswerMessage = USER_ANSWER_2 + "\n" + MESSAGE_ALREADY_ANSWERED;
+ assertCommandFailure(answerCommand, model, repeatedAnswerMessage);
+ }
+
+ @Test
+ public void execute_answerOngoingQuizNotBeenAnswered_success() {
+ QuizCommand.setIsQuiz(true, model);
+ AnswerCommand.setBeenAnswered(false, model);
+ QAndA qAndA = TypicalQAndA.QUESTION1;
+ model.updateFilteredQAndAList(x -> x.equals(qAndA));
+
+ // because model not supposed to change after answer command execution
+ Model expectedModel = model;
+
+ AnswerCommand answerCommand = new AnswerCommand(USER_ANSWER_1);
+ assertCommandSuccess(answerCommand, model, MESSAGE_USER_ANSWER + USER_ANSWER_1, expectedModel);
+
+ // end the quiz
+ QuizCommand.setIsQuiz(false, model);
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/logic/commands/ClearCommandTest.java b/src/test/java/seedu/medmoriser/logic/commands/ClearCommandTest.java
new file mode 100644
index 00000000000..2f2b68df173
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/commands/ClearCommandTest.java
@@ -0,0 +1,32 @@
+package seedu.medmoriser.logic.commands;
+
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.medmoriser.testutil.TypicalQAndA.getTypicalMedmoriser;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.model.Medmoriser;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ModelManager;
+import seedu.medmoriser.model.UserPrefs;
+
+public class ClearCommandTest {
+
+ @Test
+ public void execute_emptyMedmoriser_success() {
+ Model model = new ModelManager();
+ Model expectedModel = new ModelManager();
+
+ assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel);
+ }
+
+ @Test
+ public void execute_nonEmptyMedmoriser_success() {
+ Model model = new ModelManager(getTypicalMedmoriser(), new UserPrefs());
+ Model expectedModel = new ModelManager(getTypicalMedmoriser(), new UserPrefs());
+ expectedModel.setMedmoriser(new Medmoriser());
+
+ assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel);
+ }
+
+}
diff --git a/src/test/java/seedu/address/logic/commands/CommandResultTest.java b/src/test/java/seedu/medmoriser/logic/commands/CommandResultTest.java
similarity index 98%
rename from src/test/java/seedu/address/logic/commands/CommandResultTest.java
rename to src/test/java/seedu/medmoriser/logic/commands/CommandResultTest.java
index 4f3eb46e9ef..cbd2192091f 100644
--- a/src/test/java/seedu/address/logic/commands/CommandResultTest.java
+++ b/src/test/java/seedu/medmoriser/logic/commands/CommandResultTest.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.commands;
+package seedu.medmoriser.logic.commands;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
diff --git a/src/test/java/seedu/medmoriser/logic/commands/CommandTestUtil.java b/src/test/java/seedu/medmoriser/logic/commands/CommandTestUtil.java
new file mode 100644
index 00000000000..fa65dcd73ff
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/commands/CommandTestUtil.java
@@ -0,0 +1,117 @@
+package seedu.medmoriser.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_ANSWER;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_QUESTION;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_TAG;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import seedu.medmoriser.commons.core.index.Index;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Medmoriser;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.qanda.QuestionContainsKeywordsPredicate;
+import seedu.medmoriser.testutil.EditQAndADescriptorBuilder;
+
+/**
+ * Contains helper methods for testing commands.
+ */
+public class CommandTestUtil {
+
+ public static final String VALID_QUESTION_A = "Question A";
+ public static final String VALID_QUESTION_B = "Question B";
+ public static final String VALID_ANSWER_A = "Answer A";
+ public static final String VALID_ANSWER_B = "Answer B";
+ public static final String VALID_TAG_TAG1 = "tag1";
+ public static final String VALID_TAG_TAG2 = "tag2";
+
+ public static final String QUESTION_DESC_A = " " + PREFIX_QUESTION + VALID_QUESTION_A;
+ public static final String QUESTION_DESC_B = " " + PREFIX_QUESTION + VALID_QUESTION_B;
+ public static final String ANSWER_DESC_A = " " + PREFIX_ANSWER + VALID_ANSWER_A;
+ public static final String ANSWER_DESC_B = " " + PREFIX_ANSWER + VALID_ANSWER_B;
+ public static final String TAG_DESC_TAG1 = " " + PREFIX_TAG + VALID_TAG_TAG1;
+ public static final String TAG_DESC_TAG2 = " " + PREFIX_TAG + VALID_TAG_TAG2;
+
+ public static final String INVALID_QUESTION_DESC = " "
+ + PREFIX_QUESTION + " "; // empty string not allowed in questions
+ public static final String INVALID_ANSWER_DESC = " " + PREFIX_ANSWER; // empty string not allowed for answers
+ public static final String INVALID_TAG_DESC = " " + PREFIX_TAG + "tag*"; // '*' not allowed in tags
+
+ public static final String PREAMBLE_WHITESPACE = "\t \r \n";
+ public static final String PREAMBLE_NON_EMPTY = "NonEmptyPreamble";
+
+ public static final EditCommand.EditQAndADescriptor DESC_A;
+ public static final EditCommand.EditQAndADescriptor DESC_B;
+
+ static {
+ DESC_A = new EditQAndADescriptorBuilder().withQuestion(VALID_QUESTION_A)
+ .withAnswer(VALID_ANSWER_A)
+ .withTags(VALID_TAG_TAG1).build();
+ DESC_B = new EditQAndADescriptorBuilder().withQuestion(VALID_QUESTION_B)
+ .withAnswer(VALID_ANSWER_B)
+ .withTags(VALID_TAG_TAG2, VALID_TAG_TAG1).build();
+ }
+
+ /**
+ * Executes the given {@code command}, confirms that
+ * - the returned {@link CommandResult} matches {@code expectedCommandResult}
+ * - the {@code actualModel} matches {@code expectedModel}
+ */
+ public static void assertCommandSuccess(Command command, Model actualModel, CommandResult expectedCommandResult,
+ Model expectedModel) {
+ try {
+ CommandResult result = command.execute(actualModel);
+ assertEquals(expectedCommandResult, result);
+ assertEquals(expectedModel, actualModel);
+ } catch (CommandException ce) {
+ throw new AssertionError("Execution of command should not fail.", ce);
+ }
+ }
+
+ /**
+ * Convenience wrapper to {@link #assertCommandSuccess(Command, Model, CommandResult, Model)}
+ * that takes a string {@code expectedMessage}.
+ */
+ public static void assertCommandSuccess(Command command, Model actualModel, String expectedMessage,
+ Model expectedModel) {
+ CommandResult expectedCommandResult = new CommandResult(expectedMessage);
+ assertCommandSuccess(command, actualModel, expectedCommandResult, expectedModel);
+ }
+
+ /**
+ * Executes the given {@code command}, confirms that
+ * - a {@code CommandException} is thrown
+ * - the CommandException message matches {@code expectedMessage}
+ * - the question book, filtered qAndA list and selected qAndA in {@code actualModel} remain unchanged
+ */
+ public static void assertCommandFailure(Command command, Model actualModel, String expectedMessage) {
+ // we are unable to defensively copy the model for comparison later, so we can
+ // only do so by copying its components.
+ Medmoriser expectedMedmoriser = new Medmoriser(actualModel.getMedmoriser());
+ List expectedFilteredList = new ArrayList<>(actualModel.getFilteredQAndAList());
+
+ assertThrows(CommandException.class, expectedMessage, () -> command.execute(actualModel));
+ assertEquals(expectedMedmoriser, actualModel.getMedmoriser());
+ assertEquals(expectedFilteredList, actualModel.getFilteredQAndAList());
+ }
+ /**
+ * Updates {@code model}'s filtered list to show only the qAndA at the given {@code targetIndex} in the
+ * {@code model}'s question book.
+ */
+ public static void showQAndAAtIndex(Model model, Index targetIndex) {
+ assertTrue(targetIndex.getZeroBased() < model.getFilteredQAndAList().size());
+
+ QAndA qAndA = model.getFilteredQAndAList().get(targetIndex.getZeroBased());
+ final String[] splitName = qAndA.getQuestion().question.split("\\s+");
+ model.updateFilteredQAndAList(new QuestionContainsKeywordsPredicate(Arrays.asList(splitName[1])));
+
+ assertEquals(1, model.getFilteredQAndAList().size());
+ }
+
+}
diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/medmoriser/logic/commands/DeleteCommandTest.java
similarity index 52%
rename from src/test/java/seedu/address/logic/commands/DeleteCommandTest.java
rename to src/test/java/seedu/medmoriser/logic/commands/DeleteCommandTest.java
index 0f77d8295f6..b1b25c0c17a 100644
--- a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java
+++ b/src/test/java/seedu/medmoriser/logic/commands/DeleteCommandTest.java
@@ -1,22 +1,22 @@
-package seedu.address.logic.commands;
+package seedu.medmoriser.logic.commands;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
-import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.showQAndAAtIndex;
+import static seedu.medmoriser.testutil.TypicalIndexes.INDEX_FIRST_QANDA;
+import static seedu.medmoriser.testutil.TypicalIndexes.INDEX_SECOND_QANDA;
+import static seedu.medmoriser.testutil.TypicalQAndA.getTypicalMedmoriser;
import org.junit.jupiter.api.Test;
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
-import seedu.address.model.UserPrefs;
-import seedu.address.model.person.Person;
+import seedu.medmoriser.commons.core.Messages;
+import seedu.medmoriser.commons.core.index.Index;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ModelManager;
+import seedu.medmoriser.model.UserPrefs;
+import seedu.medmoriser.model.qanda.QAndA;
/**
* Contains integration tests (interaction with the Model, UndoCommand and RedoCommand) and unit tests for
@@ -24,68 +24,70 @@
*/
public class DeleteCommandTest {
- private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private Model model = new ModelManager(getTypicalMedmoriser(), new UserPrefs());
@Test
public void execute_validIndexUnfilteredList_success() {
- Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
- DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON);
+ QAndA qAndAToDelete = model.getFilteredQAndAList()
+ .get(INDEX_FIRST_QANDA.getZeroBased());
+ DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_QANDA);
- String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete);
+ String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_QANDA_SUCCESS, qAndAToDelete);
- ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- expectedModel.deletePerson(personToDelete);
+ ModelManager expectedModel = new ModelManager(model.getMedmoriser(), new UserPrefs());
+ expectedModel.deleteQAndA(qAndAToDelete);
assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
}
@Test
public void execute_invalidIndexUnfilteredList_throwsCommandException() {
- Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1);
+ Index outOfBoundIndex = Index.fromOneBased(model.getFilteredQAndAList().size() + 1);
DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex);
- assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_QANDA_DISPLAYED_INDEX);
}
@Test
public void execute_validIndexFilteredList_success() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
+ showQAndAAtIndex(model, INDEX_FIRST_QANDA);
- Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
- DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON);
+ QAndA qAndAToDelete = model.getFilteredQAndAList()
+ .get(INDEX_FIRST_QANDA.getZeroBased());
+ DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_QANDA);
- String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete);
+ String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_QANDA_SUCCESS, qAndAToDelete);
- Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- expectedModel.deletePerson(personToDelete);
- showNoPerson(expectedModel);
+ Model expectedModel = new ModelManager(model.getMedmoriser(), new UserPrefs());
+ expectedModel.deleteQAndA(qAndAToDelete);
+ showNoQAndA(expectedModel);
assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
}
@Test
public void execute_invalidIndexFilteredList_throwsCommandException() {
- showPersonAtIndex(model, INDEX_FIRST_PERSON);
+ showQAndAAtIndex(model, INDEX_FIRST_QANDA);
- Index outOfBoundIndex = INDEX_SECOND_PERSON;
+ Index outOfBoundIndex = INDEX_SECOND_QANDA;
// ensures that outOfBoundIndex is still in bounds of address book list
- assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size());
+ assertTrue(outOfBoundIndex.getZeroBased() < model.getMedmoriser().getQAndAList().size());
DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex);
- assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_QANDA_DISPLAYED_INDEX);
}
@Test
public void equals() {
- DeleteCommand deleteFirstCommand = new DeleteCommand(INDEX_FIRST_PERSON);
- DeleteCommand deleteSecondCommand = new DeleteCommand(INDEX_SECOND_PERSON);
+ DeleteCommand deleteFirstCommand = new DeleteCommand(INDEX_FIRST_QANDA);
+ DeleteCommand deleteSecondCommand = new DeleteCommand(INDEX_SECOND_QANDA);
// same object -> returns true
assertTrue(deleteFirstCommand.equals(deleteFirstCommand));
// same values -> returns true
- DeleteCommand deleteFirstCommandCopy = new DeleteCommand(INDEX_FIRST_PERSON);
+ DeleteCommand deleteFirstCommandCopy = new DeleteCommand(INDEX_FIRST_QANDA);
assertTrue(deleteFirstCommand.equals(deleteFirstCommandCopy));
// different types -> returns false
@@ -94,16 +96,16 @@ public void equals() {
// null -> returns false
assertFalse(deleteFirstCommand.equals(null));
- // different person -> returns false
+ // different qAndA -> returns false
assertFalse(deleteFirstCommand.equals(deleteSecondCommand));
}
/**
* Updates {@code model}'s filtered list to show no one.
*/
- private void showNoPerson(Model model) {
- model.updateFilteredPersonList(p -> false);
+ private void showNoQAndA(Model model) {
+ model.updateFilteredQAndAList(p -> false);
- assertTrue(model.getFilteredPersonList().isEmpty());
+ assertTrue(model.getFilteredQAndAList().isEmpty());
}
}
diff --git a/src/test/java/seedu/medmoriser/logic/commands/EditCommandTest.java b/src/test/java/seedu/medmoriser/logic/commands/EditCommandTest.java
new file mode 100644
index 00000000000..bd8820f0be6
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/commands/EditCommandTest.java
@@ -0,0 +1,193 @@
+package seedu.medmoriser.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.DESC_A;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.DESC_B;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_QUESTION_B;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_TAG_TAG2;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.showQAndAAtIndex;
+import static seedu.medmoriser.testutil.TypicalIndexes.INDEX_FIRST_QANDA;
+import static seedu.medmoriser.testutil.TypicalIndexes.INDEX_SECOND_QANDA;
+import static seedu.medmoriser.testutil.TypicalQAndA.getTypicalMedmoriser;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.commons.core.Messages;
+import seedu.medmoriser.commons.core.index.Index;
+import seedu.medmoriser.logic.commands.EditCommand.EditQAndADescriptor;
+import seedu.medmoriser.model.Medmoriser;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ModelManager;
+import seedu.medmoriser.model.UserPrefs;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.testutil.EditQAndADescriptorBuilder;
+import seedu.medmoriser.testutil.QAndABuilder;
+
+/**
+ * Contains integration tests (interaction with the Model, UndoCommand and RedoCommand) and unit tests for EditCommand.
+ */
+public class EditCommandTest {
+
+ private Model model = new ModelManager(getTypicalMedmoriser(), new UserPrefs());
+
+ @Test
+ public void execute_allFieldsSpecifiedUnfilteredList_success() {
+ QAndA editedQAndA = new QAndABuilder().build();
+ EditQAndADescriptor descriptor = new EditQAndADescriptorBuilder(editedQAndA).build();
+ EditCommand editCommand = new EditCommand(INDEX_FIRST_QANDA, descriptor);
+
+ String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_QANDA_SUCCESS, editedQAndA);
+
+ Model expectedModel = new ModelManager(new Medmoriser(model.getMedmoriser()), new UserPrefs());
+ expectedModel.setQAndA(model.getFilteredQAndAList().get(0), editedQAndA);
+
+ assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_someFieldsSpecifiedUnfilteredList_success() {
+ Index indexLastQAndA = Index.fromOneBased(model.getFilteredQAndAList().size());
+ QAndA lastQAndA = model.getFilteredQAndAList().get(indexLastQAndA.getZeroBased());
+
+ QAndABuilder qAndAInList = new QAndABuilder(lastQAndA);
+ QAndA editedQAndA = qAndAInList.withQuestion(VALID_QUESTION_B).withTags(VALID_TAG_TAG2).build();
+
+ EditCommand.EditQAndADescriptor descriptor = new EditQAndADescriptorBuilder()
+ .withQuestion(VALID_QUESTION_B).withTags(VALID_TAG_TAG2).build();
+ EditCommand editCommand = new EditCommand(indexLastQAndA, descriptor);
+
+ String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_QANDA_SUCCESS, editedQAndA);
+
+ Model expectedModel = new ModelManager(new Medmoriser(model.getMedmoriser()), new UserPrefs());
+ expectedModel.setQAndA(lastQAndA, editedQAndA);
+
+ assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_noFieldSpecifiedUnfilteredList_success() {
+ EditCommand editCommand = new EditCommand(INDEX_FIRST_QANDA, new EditCommand.EditQAndADescriptor());
+ QAndA editedQAndA = model.getFilteredQAndAList().get(INDEX_FIRST_QANDA.getZeroBased());
+
+ String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_QANDA_SUCCESS, editedQAndA);
+
+ Model expectedModel = new ModelManager(new Medmoriser(model.getMedmoriser()), new UserPrefs());
+
+ assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_filteredList_success() {
+ showQAndAAtIndex(model, INDEX_FIRST_QANDA);
+
+ QAndA qAndAInFilteredList = model.getFilteredQAndAList()
+ .get(INDEX_FIRST_QANDA.getZeroBased());
+ QAndA editedQAndA = new QAndABuilder(qAndAInFilteredList)
+ .withQuestion(VALID_QUESTION_B).build();
+ EditCommand editCommand = new EditCommand(INDEX_FIRST_QANDA,
+ new EditQAndADescriptorBuilder().withQuestion(VALID_QUESTION_B).build());
+
+ String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_QANDA_SUCCESS, editedQAndA);
+
+ Model expectedModel = new ModelManager(new Medmoriser(model.getMedmoriser()), new UserPrefs());
+ expectedModel.setQAndA(model.getFilteredQAndAList().get(0), editedQAndA);
+
+ assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_duplicateQAndAUnfilteredList_failure() {
+ QAndA firstQAndA = model.getFilteredQAndAList().get(INDEX_FIRST_QANDA.getZeroBased());
+ EditQAndADescriptor descriptor = new EditQAndADescriptorBuilder(firstQAndA).build();
+ EditCommand editCommand = new EditCommand(INDEX_SECOND_QANDA, descriptor);
+
+ assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_QANDA);
+ }
+
+ @Test
+ public void execute_duplicateQAndAFilteredList_failure() {
+ showQAndAAtIndex(model, INDEX_FIRST_QANDA);
+
+ // edit qAndA in filtered list into a duplicate in medmoriser
+ QAndA qAndAInList = model.getMedmoriser().getQAndAList()
+ .get(INDEX_SECOND_QANDA.getZeroBased());
+ EditCommand editCommand = new EditCommand(INDEX_FIRST_QANDA,
+ new EditQAndADescriptorBuilder(qAndAInList).build());
+
+ assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_QANDA);
+ }
+
+ @Test
+ public void execute_invalidQAndAIndexUnfilteredList_failure() {
+ Index outOfBoundIndex = Index.fromOneBased(model.getFilteredQAndAList().size() + 1);
+ EditQAndADescriptor descriptor =
+ new EditQAndADescriptorBuilder().withQuestion(VALID_QUESTION_B).build();
+ EditCommand editCommand = new EditCommand(outOfBoundIndex, descriptor);
+
+ assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_QANDA_DISPLAYED_INDEX);
+ }
+
+ /**
+ * Edit filtered list where index is larger than size of filtered list,
+ * but smaller than size of medmoriser
+ */
+ @Test
+ public void execute_invalidQAndAIndexFilteredList_failure() {
+ showQAndAAtIndex(model, INDEX_FIRST_QANDA);
+ Index outOfBoundIndex = INDEX_SECOND_QANDA;
+ // ensures that outOfBoundIndex is still in bounds of medmoriser list
+ assertTrue(outOfBoundIndex.getZeroBased() < model.getMedmoriser().getQAndAList().size());
+
+ EditCommand editCommand = new EditCommand(outOfBoundIndex,
+ new EditQAndADescriptorBuilder().withQuestion(VALID_QUESTION_B).build());
+
+ assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_QANDA_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void execute_answersHidden_successAndShowsAnswers() throws Exception {
+ ListCommand listCommand = new ListCommand(false);
+
+ QAndA editedQAndA = new QAndABuilder().build();
+ EditQAndADescriptor descriptor = new EditQAndADescriptorBuilder(editedQAndA).build();
+ EditCommand editCommand = new EditCommand(INDEX_FIRST_QANDA, descriptor);
+ CommandResult commandResult = editCommand.execute(model);
+
+ String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_QANDA_SUCCESS, editedQAndA);
+ Model expectedModel = new ModelManager(new Medmoriser(model.getMedmoriser()), new UserPrefs());
+ expectedModel.setQAndA(model.getFilteredQAndAList().get(0), editedQAndA);
+ assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
+
+ assertTrue(commandResult.isAnswerDisplayed());
+ }
+
+ @Test
+ public void equals() {
+ final EditCommand standardCommand = new EditCommand(INDEX_FIRST_QANDA, DESC_A);
+
+ // same values -> returns true
+ EditQAndADescriptor copyDescriptor = new EditQAndADescriptor(DESC_A);
+
+ EditCommand commandWithSameValues = new EditCommand(INDEX_FIRST_QANDA, copyDescriptor);
+ assertTrue(standardCommand.equals(commandWithSameValues));
+
+ // same object -> returns true
+ assertTrue(standardCommand.equals(standardCommand));
+
+ // null -> returns false
+ assertFalse(standardCommand.equals(null));
+
+ // different types -> returns false
+ assertFalse(standardCommand.equals(new ClearCommand()));
+
+ // different index -> returns false
+ assertFalse(standardCommand.equals(new EditCommand(INDEX_SECOND_QANDA, DESC_A)));
+
+ // different descriptor -> returns false
+ assertFalse(standardCommand.equals(new EditCommand(INDEX_FIRST_QANDA, DESC_B)));
+ }
+
+}
diff --git a/src/test/java/seedu/medmoriser/logic/commands/EditQAndADescriptorTest.java b/src/test/java/seedu/medmoriser/logic/commands/EditQAndADescriptorTest.java
new file mode 100644
index 00000000000..6b1175c200f
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/commands/EditQAndADescriptorTest.java
@@ -0,0 +1,49 @@
+package seedu.medmoriser.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.DESC_A;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.DESC_B;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_ANSWER_B;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_QUESTION_B;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_TAG_TAG2;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.testutil.EditQAndADescriptorBuilder;
+
+public class EditQAndADescriptorTest {
+
+ @Test
+ public void equals() {
+ // same values -> returns true
+ EditCommand.EditQAndADescriptor descriptorWithSameValues = new EditCommand
+ .EditQAndADescriptor(DESC_A);
+ assertTrue(DESC_A.equals(descriptorWithSameValues));
+
+ // same object -> returns true
+ assertTrue(DESC_A.equals(DESC_A));
+
+ // null -> returns false
+ assertFalse(DESC_A.equals(null));
+
+ // different types -> returns false
+ assertFalse(DESC_A.equals(5));
+
+ // different values -> returns false
+ assertFalse(DESC_A.equals(DESC_B));
+
+ // different question -> returns false
+ EditCommand.EditQAndADescriptor editedAmy = new EditQAndADescriptorBuilder(DESC_A)
+ .withQuestion(VALID_QUESTION_B).build();
+ assertFalse(DESC_A.equals(editedAmy));
+
+ // different answer -> returns false
+ editedAmy = new EditQAndADescriptorBuilder(DESC_A).withAnswer(VALID_ANSWER_B).build();
+ assertFalse(DESC_A.equals(editedAmy));
+
+ // different tags -> returns false
+ editedAmy = new EditQAndADescriptorBuilder(DESC_A).withTags(VALID_TAG_TAG2).build();
+ assertFalse(DESC_A.equals(editedAmy));
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/logic/commands/EndQuizCommandTest.java b/src/test/java/seedu/medmoriser/logic/commands/EndQuizCommandTest.java
new file mode 100644
index 00000000000..061558034fc
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/commands/EndQuizCommandTest.java
@@ -0,0 +1,50 @@
+package seedu.medmoriser.logic.commands;
+
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.medmoriser.testutil.TypicalQAndA.getTypicalMedmoriser;
+
+import java.util.Arrays;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ModelManager;
+import seedu.medmoriser.model.UserPrefs;
+import seedu.medmoriser.model.qanda.QuestionContainsKeywordsPredicate;
+
+public class EndQuizCommandTest {
+ private Model model = new ModelManager(getTypicalMedmoriser(), new UserPrefs());
+ private Model expectedModel = new ModelManager(getTypicalMedmoriser(), new UserPrefs());
+
+ @Test
+ public void execute_endOngoingQuiz_success() {
+ QuestionContainsKeywordsPredicate predicate = preparePredicate("three");
+ QuizCommand quizCommand = new QuizCommand(predicate);
+ CommandResult expectedCommandResult = new CommandResult(EndQuizCommand.MESSAGE_ENDQUIZ_ACKNOWLEDGEMENT,
+ false, false);
+
+ try {
+ quizCommand.execute(model);
+ } catch (CommandException ce) {
+ throw new AssertionError("Execution of command should not fail.", ce);
+ }
+
+ assertCommandSuccess(new EndQuizCommand(), model, expectedCommandResult, expectedModel);
+ }
+
+ @Test
+ public void execute_noOngoingQuizEndQuiz_throwsCommandException() {
+ String expectedMessage = EndQuizCommand.MESSAGE_NO_ONGOING_QUIZ;
+ EndQuizCommand command = new EndQuizCommand();
+ assertCommandFailure(command, model, expectedMessage);
+ }
+
+ /**
+ * Parses {@code userInput} into a {@code NameContainsKeywordsPredicate}.
+ */
+ private QuestionContainsKeywordsPredicate preparePredicate(String userInput) {
+ return new QuestionContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java b/src/test/java/seedu/medmoriser/logic/commands/ExitCommandTest.java
similarity index 59%
rename from src/test/java/seedu/address/logic/commands/ExitCommandTest.java
rename to src/test/java/seedu/medmoriser/logic/commands/ExitCommandTest.java
index 9533c473875..ce46cc84e54 100644
--- a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java
+++ b/src/test/java/seedu/medmoriser/logic/commands/ExitCommandTest.java
@@ -1,12 +1,12 @@
-package seedu.address.logic.commands;
+package seedu.medmoriser.logic.commands;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.logic.commands.ExitCommand.MESSAGE_EXIT_ACKNOWLEDGEMENT;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.medmoriser.logic.commands.ExitCommand.MESSAGE_EXIT_ACKNOWLEDGEMENT;
import org.junit.jupiter.api.Test;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ModelManager;
public class ExitCommandTest {
private Model model = new ModelManager();
diff --git a/src/test/java/seedu/medmoriser/logic/commands/FindCommandTest.java b/src/test/java/seedu/medmoriser/logic/commands/FindCommandTest.java
new file mode 100644
index 00000000000..479aa3ba184
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/commands/FindCommandTest.java
@@ -0,0 +1,111 @@
+package seedu.medmoriser.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_QANDA_LISTED_OVERVIEW;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTION3;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTION5;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTION6;
+import static seedu.medmoriser.testutil.TypicalQAndA.getTypicalMedmoriser;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ModelManager;
+import seedu.medmoriser.model.UserPrefs;
+import seedu.medmoriser.model.qanda.AnswerContainsKeywordsPredicate;
+import seedu.medmoriser.model.qanda.QuestionContainsKeywordsPredicate;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code FindCommand}.
+ */
+public class FindCommandTest {
+ private Model model = new ModelManager(getTypicalMedmoriser(), new UserPrefs());
+ private Model expectedModel = new ModelManager(getTypicalMedmoriser(), new UserPrefs());
+
+ @Test
+ public void equals() {
+ QuestionContainsKeywordsPredicate firstPredicate =
+ new QuestionContainsKeywordsPredicate(Collections.singletonList("first"));
+ QuestionContainsKeywordsPredicate secondPredicate =
+ new QuestionContainsKeywordsPredicate(Collections.singletonList("second"));
+
+ AnswerContainsKeywordsPredicate thirdPredicate =
+ new AnswerContainsKeywordsPredicate(Collections.singletonList("first"));
+ AnswerContainsKeywordsPredicate fourthPredicate =
+ new AnswerContainsKeywordsPredicate(Collections.singletonList("second"));
+
+ FindCommand findFirstCommand = new FindCommand(firstPredicate);
+ FindCommand findSecondCommand = new FindCommand(secondPredicate);
+
+ FindCommand findThirdCommand = new FindCommand(thirdPredicate);
+ FindCommand findFourthCommand = new FindCommand(fourthPredicate);
+
+ // same object -> returns true
+ assertTrue(findFirstCommand.equals(findFirstCommand));
+ assertTrue(findThirdCommand.equals(findThirdCommand));
+
+ // same values -> returns true
+ FindCommand findFirstCommandCopy = new FindCommand(firstPredicate);
+ assertTrue(findFirstCommand.equals(findFirstCommandCopy));
+ FindCommand findThirdCommandCopy = new FindCommand(thirdPredicate);
+ assertTrue(findThirdCommand.equals(findThirdCommandCopy));
+
+ // different types -> returns false
+ assertFalse(findFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(findFirstCommand.equals(null));
+
+ // different qAndA -> returns false
+ assertFalse(findFirstCommand.equals(findSecondCommand));
+ assertFalse(findThirdCommand.equals(findFourthCommand));
+ }
+
+ @Test
+ public void execute_zeroKeywords_noQAndAFound() {
+ String expectedMessage = String.format(MESSAGE_QANDA_LISTED_OVERVIEW, 0);
+ QuestionContainsKeywordsPredicate predicate = preparePredicate(" ");
+ FindCommand command = new FindCommand(predicate);
+ expectedModel.updateFilteredQAndAList(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredQAndAList());
+ }
+
+ @Test
+ public void execute_multipleKeywords_multipleQAndAsFound() {
+ String expectedMessage = String.format(MESSAGE_QANDA_LISTED_OVERVIEW, 3);
+ QuestionContainsKeywordsPredicate predicate = preparePredicate("Three Five Six");
+ FindCommand command = new FindCommand(predicate);
+ expectedModel.updateFilteredQAndAList(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(QUESTION3, QUESTION5, QUESTION6), model.getFilteredQAndAList());
+ }
+
+ @Test
+ public void execute_answersHidden_successAndShowsAnswers() throws Exception {
+ ListCommand listCommand = new ListCommand(false);
+
+ String expectedMessage = String.format(MESSAGE_QANDA_LISTED_OVERVIEW, 3);
+ QuestionContainsKeywordsPredicate predicate = preparePredicate("Three Five Six");
+ FindCommand command = new FindCommand(predicate);
+ expectedModel.updateFilteredQAndAList(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(QUESTION3, QUESTION5, QUESTION6), model.getFilteredQAndAList());
+
+ CommandResult commandResult = command.execute(model);
+ assertTrue(commandResult.isAnswerDisplayed());
+ }
+
+ /**
+ * Parses {@code userInput} into a {@code NameContainsKeywordsPredicate}.
+ */
+ private QuestionContainsKeywordsPredicate preparePredicate(String userInput) {
+ return new QuestionContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java b/src/test/java/seedu/medmoriser/logic/commands/HelpCommandTest.java
similarity index 59%
rename from src/test/java/seedu/address/logic/commands/HelpCommandTest.java
rename to src/test/java/seedu/medmoriser/logic/commands/HelpCommandTest.java
index 4904fc4352e..22083c6aacf 100644
--- a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java
+++ b/src/test/java/seedu/medmoriser/logic/commands/HelpCommandTest.java
@@ -1,12 +1,12 @@
-package seedu.address.logic.commands;
+package seedu.medmoriser.logic.commands;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
-import static seedu.address.logic.commands.HelpCommand.SHOWING_HELP_MESSAGE;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.medmoriser.logic.commands.HelpCommand.SHOWING_HELP_MESSAGE;
import org.junit.jupiter.api.Test;
-import seedu.address.model.Model;
-import seedu.address.model.ModelManager;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ModelManager;
public class HelpCommandTest {
private Model model = new ModelManager();
diff --git a/src/test/java/seedu/medmoriser/logic/commands/ListCommandTest.java b/src/test/java/seedu/medmoriser/logic/commands/ListCommandTest.java
new file mode 100644
index 00000000000..b2bab3caa66
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/commands/ListCommandTest.java
@@ -0,0 +1,69 @@
+package seedu.medmoriser.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.showQAndAAtIndex;
+import static seedu.medmoriser.testutil.TypicalIndexes.INDEX_FIRST_QANDA;
+import static seedu.medmoriser.testutil.TypicalQAndA.getTypicalMedmoriser;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ModelManager;
+import seedu.medmoriser.model.UserPrefs;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for ListCommand.
+ */
+public class ListCommandTest {
+
+ private Model model;
+ private Model expectedModel;
+
+ @BeforeEach
+ public void setUpModels() {
+ model = new ModelManager(getTypicalMedmoriser(), new UserPrefs());
+ expectedModel = new ModelManager(model.getMedmoriser(), new UserPrefs());
+ }
+
+ @Test
+ public void equals() {
+
+ ListCommand listAllCommand = new ListCommand(true);
+ ListCommand listQuestionsCommand = new ListCommand(false);
+
+ // same object -> returns true
+ assertTrue(listAllCommand.equals(listAllCommand));
+
+ // same values -> returns true
+ ListCommand listAllCommandCopy = new ListCommand(true);
+ assertTrue(listAllCommand.equals(listAllCommandCopy));
+
+ // different types -> returns false
+ assertFalse(listAllCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(listAllCommand.equals(null));
+
+ // different value for isAnswerDisplayed -> returns false
+ assertFalse(listAllCommand.equals(listQuestionsCommand));
+ }
+
+ @Test
+ public void execute_listIsNotFiltered_showsSameList() {
+ // questions and answers both shown
+ assertCommandSuccess(new ListCommand(true), model, ListCommand.MESSAGE_LIST_ALL_SUCCESS, expectedModel);
+
+ // questions shown, answers hidden
+ assertCommandSuccess(new ListCommand(false), model, ListCommand.MESSAGE_LIST_QUESTIONS_SUCCESS, expectedModel);
+ }
+
+ @Test
+ public void execute_listIsFiltered_showsEverything() {
+ showQAndAAtIndex(model, INDEX_FIRST_QANDA);
+ assertCommandSuccess(new ListCommand(true), model, ListCommand.MESSAGE_LIST_ALL_SUCCESS, expectedModel);
+ }
+
+}
diff --git a/src/test/java/seedu/medmoriser/logic/commands/NextCommandTest.java b/src/test/java/seedu/medmoriser/logic/commands/NextCommandTest.java
new file mode 100644
index 00000000000..da2cd20e069
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/commands/NextCommandTest.java
@@ -0,0 +1,129 @@
+package seedu.medmoriser.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.medmoriser.logic.commands.NextCommand.MESSAGE_NOT_QUIZ;
+import static seedu.medmoriser.logic.commands.NextCommand.MESSAGE_NO_MORE_QUESTIONS;
+import static seedu.medmoriser.logic.commands.NextCommand.MESSAGE_SUCCESS;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTION3;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTION5;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTION6;
+import static seedu.medmoriser.testutil.TypicalQAndA.getTypicalMedmoriser;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.junit.jupiter.api.Test;
+
+import javafx.collections.ObservableList;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Medmoriser;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ModelManager;
+import seedu.medmoriser.model.UserPrefs;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.qanda.QuestionContainsKeywordsPredicate;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for NextCommand.
+ */
+public class NextCommandTest {
+ private Model model = new ModelManager(getTypicalMedmoriser(), new UserPrefs());
+ private Model expectedModel = new ModelManager(new Medmoriser(model.getMedmoriser()), new UserPrefs());
+
+ @Test
+ public void equals() {
+ NextCommand nextCommand = new NextCommand();
+
+ // same object
+ assertTrue(nextCommand.equals(nextCommand));
+
+ // different types -> returns false
+ assertFalse(nextCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(nextCommand.equals(null));
+
+ }
+
+ @Test
+ public void execute_noOngoingQuiz_failure() {
+ String expectedMessage = MESSAGE_NOT_QUIZ;
+ NextCommand command = new NextCommand();
+
+ assertCommandFailure(command, model, expectedMessage);
+ }
+
+ @Test
+ public void execute_noNextQuestion_failure() {
+ String expectedMessage = MESSAGE_NO_MORE_QUESTIONS;
+ NextCommand nextCommand = new NextCommand();
+
+ QuestionContainsKeywordsPredicate predicate =
+ new QuestionContainsKeywordsPredicate(Collections.singletonList("Three"));
+ QuizCommand command = new QuizCommand(predicate);
+ expectedModel.updateFilteredQAndAList(predicate);
+
+ ObservableList filteredList = expectedModel.getFilteredQAndAList();
+
+ assertTrue(filteredList.size() == 1);
+ assertEquals(Arrays.asList(QUESTION3), expectedModel.getFilteredQAndAList());
+
+ CommandResult expectedCommandResult = new CommandResult(expectedMessage);
+
+ try {
+ command.execute(model);
+ nextCommand.execute(model);
+ } catch (CommandException e) {
+ CommandResult result = new CommandResult(e.getMessage());
+ assertEquals(expectedCommandResult, result);
+ }
+ QuizCommand.setIsQuiz(false, model);
+ }
+
+ @Test
+ public void execute_nextQuestion_success() {
+ String expectedMessage = MESSAGE_SUCCESS;
+ NextCommand nextCommand = new NextCommand();
+
+ QuestionContainsKeywordsPredicate predicate = preparePredicate("three five six");
+ String expectedQuizMessage = QuizCommand.MESSAGE_SUCCESS;
+ QuizCommand quizCommand = new QuizCommand(predicate);
+ expectedModel.updateFilteredQAndAList(predicate);
+
+ ObservableList filteredList = expectedModel.getFilteredQAndAList();
+
+ assertTrue(filteredList.size() == 3);
+ assertEquals(Arrays.asList(QUESTION3, QUESTION5, QUESTION6), expectedModel.getFilteredQAndAList());
+
+ EndQuizCommand endQuizCommand = new EndQuizCommand();
+ String expectedEndQuizMessage = EndQuizCommand.MESSAGE_ENDQUIZ_ACKNOWLEDGEMENT;
+
+ CommandResult expectedCommandResult = new CommandResult(expectedMessage);
+ CommandResult expectedQuizCommandResult = new CommandResult(expectedQuizMessage);
+ CommandResult expectedEndQuizCommandResult = new CommandResult(expectedEndQuizMessage);
+ try {
+ CommandResult result = quizCommand.execute(model);
+ CommandResult resultNext = nextCommand.execute(model);
+ CommandResult resultNextQuestion = nextCommand.execute(model);
+ CommandResult endQuizResult = endQuizCommand.execute(model);
+
+ assertEquals(expectedQuizCommandResult, result);
+ assertEquals(expectedCommandResult, resultNext);
+ assertEquals(expectedCommandResult, resultNextQuestion);
+ assertEquals(expectedEndQuizCommandResult, endQuizResult);
+
+ } catch (CommandException e) {
+ throw new AssertionError("Command should not fail", e);
+ }
+ }
+
+ /**
+ * Parses {@code userInput} into a {@code NameContainsKeywordsPredicate}.
+ */
+ private QuestionContainsKeywordsPredicate preparePredicate(String userInput) {
+ return new QuestionContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")));
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/logic/commands/QuizCommandTest.java b/src/test/java/seedu/medmoriser/logic/commands/QuizCommandTest.java
new file mode 100644
index 00000000000..b3835287d7e
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/commands/QuizCommandTest.java
@@ -0,0 +1,110 @@
+package seedu.medmoriser.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.medmoriser.logic.commands.QuizCommand.MESSAGE_NO_QUESTION_WITH_KEYWORD;
+import static seedu.medmoriser.logic.commands.QuizCommand.MESSAGE_SUCCESS;
+import static seedu.medmoriser.testutil.TypicalQAndA.getTypicalMedmoriser;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.junit.jupiter.api.Test;
+
+import javafx.collections.ObservableList;
+import seedu.medmoriser.logic.commands.exceptions.CommandException;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.ModelManager;
+import seedu.medmoriser.model.UserPrefs;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.qanda.QuestionContainsKeywordsPredicate;
+import seedu.medmoriser.model.qanda.TagContainsKeywordsPredicate;
+
+public class QuizCommandTest {
+ private Model model = new ModelManager(getTypicalMedmoriser(), new UserPrefs());
+ private Model expectedModel = new ModelManager(getTypicalMedmoriser(), new UserPrefs());
+
+ @Test
+ public void equals() {
+ QuestionContainsKeywordsPredicate firstPredicate =
+ new QuestionContainsKeywordsPredicate(Collections.singletonList("first"));
+ QuestionContainsKeywordsPredicate secondPredicate =
+ new QuestionContainsKeywordsPredicate(Collections.singletonList("second"));
+
+ TagContainsKeywordsPredicate thirdPredicate =
+ new TagContainsKeywordsPredicate(Collections.singletonList("first"));
+ TagContainsKeywordsPredicate fourthPredicate =
+ new TagContainsKeywordsPredicate(Collections.singletonList("second"));
+
+
+ QuizCommand quizFirstCommand = new QuizCommand(firstPredicate);
+ QuizCommand quizSecondCommand = new QuizCommand(secondPredicate);
+ QuizCommand quizThirdCommand = new QuizCommand(thirdPredicate);
+ QuizCommand quizFourthCommand = new QuizCommand(fourthPredicate);
+
+ // same object -> returns true
+ assertTrue(quizFirstCommand.equals(quizFirstCommand));
+ assertTrue(quizThirdCommand.equals(quizThirdCommand));
+
+ // same values -> returns true
+ QuizCommand quizFirstCommandCopy = new QuizCommand(firstPredicate);
+ assertTrue(quizFirstCommand.equals(quizFirstCommandCopy));
+ QuizCommand quizThirdCommandCopy = new QuizCommand(thirdPredicate);
+ assertTrue(quizThirdCommand.equals(quizThirdCommandCopy));
+
+ // different types -> returns false
+ assertFalse(quizFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(quizFirstCommand.equals(null));
+
+ // different qAndA -> returns false
+ assertFalse(quizFirstCommand.equals(quizSecondCommand));
+ assertFalse(quizThirdCommand.equals(quizFourthCommand));
+ }
+
+ @Test
+ public void execute_zeroKeywords_throwsCommandException() {
+ String expectedMessage = MESSAGE_NO_QUESTION_WITH_KEYWORD;
+ QuestionContainsKeywordsPredicate predicate = preparePredicate(" ");
+ QuizCommand command = new QuizCommand(predicate);
+ model.updateFilteredQAndAList(predicate);
+ assertCommandFailure(command, model, expectedMessage);
+ }
+
+ @Test
+ public void execute_multipleKeywords_multipleQAndAsFound() {
+ String expectedMessage = String.format(MESSAGE_SUCCESS, 3);
+ QuestionContainsKeywordsPredicate predicate = preparePredicate("three five six");
+ QuizCommand command = new QuizCommand(predicate);
+ expectedModel.updateFilteredQAndAList(predicate);
+
+ ObservableList filteredList = expectedModel.getFilteredQAndAList();
+ QAndA filteredQAndA = filteredList.get(0);
+ String filteredQuestionString = filteredQAndA.getQuestion().question;
+ filteredQuestionString = filteredQuestionString.toLowerCase();
+
+ assertTrue(filteredQuestionString.contains("three")
+ || filteredQuestionString.contains("five")
+ || filteredQuestionString.contains("six"));
+
+ CommandResult expectedCommandResult = new CommandResult(expectedMessage);
+ try {
+ CommandResult result = command.execute(model);
+ EndQuizCommand endQuizCommand = new EndQuizCommand();
+ endQuizCommand.execute(model);
+ assertEquals(expectedCommandResult, result);
+ } catch (CommandException ce) {
+ throw new AssertionError("Execution of command should not fail.", ce);
+ }
+ }
+
+ /**
+ * Parses {@code userInput} into a {@code NameContainsKeywordsPredicate}.
+ */
+ private QuestionContainsKeywordsPredicate preparePredicate(String userInput) {
+ return new QuestionContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")));
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/logic/parser/AddCommandParserTest.java b/src/test/java/seedu/medmoriser/logic/parser/AddCommandParserTest.java
new file mode 100644
index 00000000000..24f8f9057b9
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/parser/AddCommandParserTest.java
@@ -0,0 +1,140 @@
+package seedu.medmoriser.logic.parser;
+
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.ANSWER_DESC_A;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.ANSWER_DESC_B;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.INVALID_ANSWER_DESC;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.INVALID_QUESTION_DESC;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.INVALID_TAG_DESC;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.PREAMBLE_NON_EMPTY;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.PREAMBLE_WHITESPACE;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.QUESTION_DESC_A;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.QUESTION_DESC_B;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.TAG_DESC_TAG1;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.TAG_DESC_TAG2;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_ANSWER_B;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_QUESTION_B;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_TAG_TAG1;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_TAG_TAG2;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_ANSWER;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_QUESTION;
+import static seedu.medmoriser.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.medmoriser.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTIONA;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTIONB;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.logic.commands.AddCommand;
+import seedu.medmoriser.model.qanda.Answer;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.qanda.Question;
+import seedu.medmoriser.model.tag.Tag;
+import seedu.medmoriser.testutil.QAndABuilder;
+
+public class AddCommandParserTest {
+
+ private static final String INVALID_ANSWER_MULTIPLE_PREFIX = " " + PREFIX_ANSWER + "This is an invalid "
+ + PREFIX_ANSWER + "answer " + PREFIX_ANSWER;
+
+ private static final String INVALID_QUESTION_MULTIPLE_PREFIX = " " + PREFIX_QUESTION + "This is an invalid "
+ + PREFIX_QUESTION + "question " + PREFIX_QUESTION;
+
+ private AddCommandParser parser = new AddCommandParser();
+
+ @Test
+ public void parse_allFieldsPresent_success() {
+ QAndA expectedQAndA = new QAndABuilder(QUESTIONB).withTags(VALID_TAG_TAG1).build();
+
+ // whitespace only preamble
+ assertParseSuccess(parser, PREAMBLE_WHITESPACE + QUESTION_DESC_B
+ + ANSWER_DESC_B + TAG_DESC_TAG1, new AddCommand(expectedQAndA));
+
+ // multiple tags - all accepted
+ QAndA expectedQAndAMultipleTags = new QAndABuilder(QUESTIONB).withTags(VALID_TAG_TAG1,
+ VALID_TAG_TAG2)
+ .build();
+ assertParseSuccess(parser, QUESTION_DESC_B + ANSWER_DESC_B
+ + TAG_DESC_TAG1 + TAG_DESC_TAG2, new AddCommand(expectedQAndAMultipleTags));
+ }
+
+ @Test
+ public void parse_optionalFieldsMissing_success() {
+ // zero tags
+ QAndA expectedQAndA = new QAndABuilder(QUESTIONA).withTags().build();
+ assertParseSuccess(parser, QUESTION_DESC_A + ANSWER_DESC_A,
+ new AddCommand(expectedQAndA));
+ }
+
+ @Test
+ public void parse_compulsoryFieldMissing_failure() {
+ String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE);
+
+ // missing question prefix
+ assertParseFailure(parser, VALID_QUESTION_B + ANSWER_DESC_B, expectedMessage);
+
+ // missing answer prefix
+ assertParseFailure(parser, QUESTION_DESC_B + VALID_ANSWER_B, expectedMessage);
+
+ // all prefixes missing
+ assertParseFailure(parser, VALID_QUESTION_B + VALID_ANSWER_B, expectedMessage);
+ }
+
+ @Test
+ public void parse_invalidValue_failure() {
+ // invalid question
+ assertParseFailure(parser, INVALID_QUESTION_DESC + ANSWER_DESC_B
+ + TAG_DESC_TAG1 + TAG_DESC_TAG2, Question.MESSAGE_CONSTRAINTS);
+
+ // invalid answer
+ assertParseFailure(parser, QUESTION_DESC_B + INVALID_ANSWER_DESC
+ + TAG_DESC_TAG1 + TAG_DESC_TAG2, Answer.MESSAGE_CONSTRAINTS);
+
+ // invalid tag
+ assertParseFailure(parser, QUESTION_DESC_B + ANSWER_DESC_B
+ + INVALID_TAG_DESC + VALID_TAG_TAG1, Tag.MESSAGE_CONSTRAINTS);
+
+ // two invalid values, only first invalid value reported
+ assertParseFailure(parser, INVALID_QUESTION_DESC + INVALID_ANSWER_DESC,
+ Question.MESSAGE_CONSTRAINTS);
+
+ // non-empty preamble
+ assertParseFailure(parser, PREAMBLE_NON_EMPTY + QUESTION_DESC_B
+ + ANSWER_DESC_B + TAG_DESC_TAG1 + TAG_DESC_TAG2,
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_moreThanOneQuestionPrefix_throwsParseException() {
+ String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_ONE_PREFIX);
+
+ // without tags
+ assertParseFailure(parser, INVALID_QUESTION_MULTIPLE_PREFIX + ANSWER_DESC_A, expectedMessage);
+
+ // with tags
+ assertParseFailure(parser, INVALID_QUESTION_MULTIPLE_PREFIX + ANSWER_DESC_A + TAG_DESC_TAG1,
+ expectedMessage);
+
+ //with multiple tags
+ assertParseFailure(parser, INVALID_QUESTION_MULTIPLE_PREFIX + ANSWER_DESC_A + TAG_DESC_TAG1
+ + TAG_DESC_TAG2, expectedMessage);
+ }
+
+ @Test
+ public void parse_moreThanOneAnswerPrefix_throwsParseException() {
+ String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_ONE_PREFIX);
+
+ // without tags
+ assertParseFailure(parser, QUESTION_DESC_A + INVALID_ANSWER_MULTIPLE_PREFIX, expectedMessage);
+
+ // with tags
+ assertParseFailure(parser, QUESTION_DESC_A + INVALID_ANSWER_MULTIPLE_PREFIX + TAG_DESC_TAG1,
+ expectedMessage);
+
+ // with multiple tags
+ assertParseFailure(parser, QUESTION_DESC_A + INVALID_ANSWER_MULTIPLE_PREFIX + TAG_DESC_TAG1
+ + TAG_DESC_TAG2, expectedMessage);
+
+ }
+
+}
diff --git a/src/test/java/seedu/medmoriser/logic/parser/AnswerCommandParserTest.java b/src/test/java/seedu/medmoriser/logic/parser/AnswerCommandParserTest.java
new file mode 100644
index 00000000000..6df5f46cee0
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/parser/AnswerCommandParserTest.java
@@ -0,0 +1,28 @@
+package seedu.medmoriser.logic.parser;
+
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medmoriser.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.medmoriser.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.logic.commands.AnswerCommand;
+
+public class AnswerCommandParserTest {
+
+ private static final String USER_INPUT_1 = "Some answer";
+ private static final String EMPTY_USER_INPUT = "";
+
+ private AnswerCommandParser parser = new AnswerCommandParser();
+
+ @Test
+ public void parse_validArgs_returnsAnswerCommand() {
+ assertParseSuccess(parser, USER_INPUT_1, new AnswerCommand(USER_INPUT_1));
+ }
+
+ @Test
+ public void parse_emptyAnswer_throwsParseException() {
+ assertParseFailure(parser, EMPTY_USER_INPUT,
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, AnswerCommand.MESSAGE_USAGE));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/ArgumentTokenizerTest.java b/src/test/java/seedu/medmoriser/logic/parser/ArgumentTokenizerTest.java
similarity index 99%
rename from src/test/java/seedu/address/logic/parser/ArgumentTokenizerTest.java
rename to src/test/java/seedu/medmoriser/logic/parser/ArgumentTokenizerTest.java
index c97308935f5..a0d50a86035 100644
--- a/src/test/java/seedu/address/logic/parser/ArgumentTokenizerTest.java
+++ b/src/test/java/seedu/medmoriser/logic/parser/ArgumentTokenizerTest.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.medmoriser.logic.parser;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
diff --git a/src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java b/src/test/java/seedu/medmoriser/logic/parser/CommandParserTestUtil.java
similarity index 88%
rename from src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java
rename to src/test/java/seedu/medmoriser/logic/parser/CommandParserTestUtil.java
index e4c33515768..30307bf5403 100644
--- a/src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java
+++ b/src/test/java/seedu/medmoriser/logic/parser/CommandParserTestUtil.java
@@ -1,9 +1,9 @@
-package seedu.address.logic.parser;
+package seedu.medmoriser.logic.parser;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.logic.commands.Command;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
/**
* Contains helper methods for testing command parsers.
diff --git a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java b/src/test/java/seedu/medmoriser/logic/parser/DeleteCommandParserTest.java
similarity index 66%
rename from src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java
rename to src/test/java/seedu/medmoriser/logic/parser/DeleteCommandParserTest.java
index 27eaec84450..689c998fc55 100644
--- a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java
+++ b/src/test/java/seedu/medmoriser/logic/parser/DeleteCommandParserTest.java
@@ -1,13 +1,13 @@
-package seedu.address.logic.parser;
+package seedu.medmoriser.logic.parser;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
-import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medmoriser.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.medmoriser.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.medmoriser.testutil.TypicalIndexes.INDEX_FIRST_QANDA;
import org.junit.jupiter.api.Test;
-import seedu.address.logic.commands.DeleteCommand;
+import seedu.medmoriser.logic.commands.DeleteCommand;
/**
* As we are only doing white-box testing, our test cases do not cover path variations
@@ -22,7 +22,7 @@ public class DeleteCommandParserTest {
@Test
public void parse_validArgs_returnsDeleteCommand() {
- assertParseSuccess(parser, "1", new DeleteCommand(INDEX_FIRST_PERSON));
+ assertParseSuccess(parser, "1", new DeleteCommand(INDEX_FIRST_QANDA));
}
@Test
diff --git a/src/test/java/seedu/medmoriser/logic/parser/EditCommandParserTest.java b/src/test/java/seedu/medmoriser/logic/parser/EditCommandParserTest.java
new file mode 100644
index 00000000000..c971d66139c
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/parser/EditCommandParserTest.java
@@ -0,0 +1,173 @@
+package seedu.medmoriser.logic.parser;
+
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.ANSWER_DESC_A;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.ANSWER_DESC_B;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.INVALID_ANSWER_DESC;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.INVALID_QUESTION_DESC;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.INVALID_TAG_DESC;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.QUESTION_DESC_A;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.TAG_DESC_TAG1;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.TAG_DESC_TAG2;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_ANSWER_A;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_QUESTION_A;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_TAG_TAG1;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_TAG_TAG2;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_ANSWER;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_QUESTION;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_TAG;
+import static seedu.medmoriser.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.medmoriser.logic.parser.CommandParserTestUtil.assertParseSuccess;
+import static seedu.medmoriser.testutil.TypicalIndexes.INDEX_FIRST_QANDA;
+import static seedu.medmoriser.testutil.TypicalIndexes.INDEX_SECOND_QANDA;
+import static seedu.medmoriser.testutil.TypicalIndexes.INDEX_THIRD_QANDA;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.commons.core.index.Index;
+import seedu.medmoriser.logic.commands.EditCommand;
+import seedu.medmoriser.model.qanda.Answer;
+import seedu.medmoriser.model.qanda.Question;
+import seedu.medmoriser.model.tag.Tag;
+import seedu.medmoriser.testutil.EditQAndADescriptorBuilder;
+
+public class EditCommandParserTest {
+
+ private static final String TAG_EMPTY = " " + PREFIX_TAG;
+
+ private static final String MESSAGE_INVALID_FORMAT =
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE);
+
+ private static final String INVALID_ANSWER_MULTIPLE_PREFIX = " " + PREFIX_ANSWER + "This is an invalid"
+ + PREFIX_ANSWER + "answer " + PREFIX_ANSWER;
+
+ private static final String INVALID_QUESTION_MULTIPLE_PREFIX = " " + PREFIX_QUESTION + "This is an invalid "
+ + PREFIX_QUESTION + "question " + PREFIX_QUESTION;
+
+ private EditCommandParser parser = new EditCommandParser();
+
+ @Test
+ public void parse_missingParts_failure() {
+ // no index specified
+ assertParseFailure(parser, VALID_QUESTION_A, MESSAGE_INVALID_FORMAT);
+
+ // no field specified
+ assertParseFailure(parser, "1", EditCommand.MESSAGE_NOT_EDITED);
+
+ // no index and no field specified
+ assertParseFailure(parser, "", MESSAGE_INVALID_FORMAT);
+ }
+
+ @Test
+ public void parse_invalidPreamble_failure() {
+ // negative index
+ assertParseFailure(parser, "-5" + QUESTION_DESC_A, MESSAGE_INVALID_FORMAT);
+
+ // zero index
+ assertParseFailure(parser, "0" + QUESTION_DESC_A, MESSAGE_INVALID_FORMAT);
+
+ // invalid arguments being parsed as preamble
+ assertParseFailure(parser, "1 some random string", MESSAGE_INVALID_FORMAT);
+
+ // invalid prefix being parsed as preamble
+ assertParseFailure(parser, "1 i/ string", MESSAGE_INVALID_FORMAT);
+ }
+
+ @Test
+ public void parse_invalidValue_failure() {
+ assertParseFailure(parser, "1" + INVALID_QUESTION_DESC, Question.MESSAGE_CONSTRAINTS); // invalid name
+ assertParseFailure(parser, "1" + INVALID_ANSWER_DESC, Answer.MESSAGE_CONSTRAINTS); // invalid ANSWER
+ assertParseFailure(parser, "1" + INVALID_TAG_DESC, Tag.MESSAGE_CONSTRAINTS); // invalid tag
+
+ // while parsing {@code PREFIX_TAG} alone will reset the tags of the {@code QAndA} being edited,
+ // parsing it together with a valid tag results in error
+ assertParseFailure(parser, "1" + TAG_DESC_TAG1 + TAG_DESC_TAG2 + TAG_EMPTY,
+ Tag.MESSAGE_CONSTRAINTS);
+ assertParseFailure(parser, "1" + TAG_DESC_TAG1 + TAG_EMPTY + TAG_DESC_TAG2,
+ Tag.MESSAGE_CONSTRAINTS);
+ assertParseFailure(parser, "1" + TAG_EMPTY + TAG_DESC_TAG1 + TAG_DESC_TAG2,
+ Tag.MESSAGE_CONSTRAINTS);
+
+ // multiple invalid values, but only the first invalid value is captured
+ assertParseFailure(parser, "1" + INVALID_QUESTION_DESC + INVALID_ANSWER_DESC,
+ Question.MESSAGE_CONSTRAINTS);
+ }
+
+ @Test
+ public void parse_allFieldsSpecified_success() {
+ Index targetIndex = INDEX_SECOND_QANDA;
+ String userInput = targetIndex.getOneBased() + TAG_DESC_TAG2 + ANSWER_DESC_A + QUESTION_DESC_A
+ + TAG_DESC_TAG1;
+
+ EditCommand.EditQAndADescriptor descriptor = new EditQAndADescriptorBuilder().withQuestion(VALID_QUESTION_A)
+ .withAnswer(VALID_ANSWER_A).withTags(VALID_TAG_TAG2, VALID_TAG_TAG1).build();
+ EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
+
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_oneFieldSpecified_success() {
+ // name
+ Index targetIndex = INDEX_THIRD_QANDA;
+ String userInput = targetIndex.getOneBased() + QUESTION_DESC_A;
+ EditCommand.EditQAndADescriptor descriptor =
+ new EditQAndADescriptorBuilder().withQuestion(VALID_QUESTION_A).build();
+ EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+
+ // answer
+ userInput = targetIndex.getOneBased() + ANSWER_DESC_A;
+ descriptor = new EditQAndADescriptorBuilder().withAnswer(VALID_ANSWER_A).build();
+ expectedCommand = new EditCommand(targetIndex, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+
+ // tags
+ userInput = targetIndex.getOneBased() + TAG_DESC_TAG1;
+ descriptor = new EditQAndADescriptorBuilder().withTags(VALID_TAG_TAG1).build();
+ expectedCommand = new EditCommand(targetIndex, descriptor);
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_resetTags_success() {
+ Index targetIndex = INDEX_THIRD_QANDA;
+ String userInput = targetIndex.getOneBased() + TAG_EMPTY;
+
+ EditCommand.EditQAndADescriptor descriptor = new EditQAndADescriptorBuilder().withTags().build();
+ EditCommand expectedCommand = new EditCommand(targetIndex, descriptor);
+
+ assertParseSuccess(parser, userInput, expectedCommand);
+ }
+
+ @Test
+ public void parse_multipleQuestionPrefix_failure() {
+ Index targetIndex = INDEX_FIRST_QANDA;
+ String userInput = targetIndex.getOneBased() + INVALID_QUESTION_MULTIPLE_PREFIX;
+ String userInput1 = targetIndex.getOneBased() + INVALID_QUESTION_MULTIPLE_PREFIX + ANSWER_DESC_B;
+
+ String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_ONE_PREFIX);
+
+ // edit question only
+ assertParseFailure(parser, userInput, expectedMessage);
+
+ // edit question and answer
+ assertParseFailure(parser, userInput1, expectedMessage);
+
+ }
+
+ @Test
+ public void parse_multipleAnswerPrefix_failure() {
+ Index targetIndex = INDEX_FIRST_QANDA;
+ String userInput = targetIndex.getOneBased() + INVALID_ANSWER_MULTIPLE_PREFIX;
+ String userInput1 = targetIndex.getOneBased() + QUESTION_DESC_A + INVALID_ANSWER_MULTIPLE_PREFIX;
+
+ String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_ONE_PREFIX);
+
+ // edit answer only
+ assertParseFailure(parser, userInput, expectedMessage);
+
+ // edit question and answer
+ assertParseFailure(parser, userInput1, expectedMessage);
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/medmoriser/logic/parser/FindCommandParserTest.java
new file mode 100644
index 00000000000..b2ebaeb1a62
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/parser/FindCommandParserTest.java
@@ -0,0 +1,102 @@
+package seedu.medmoriser.logic.parser;
+
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medmoriser.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.medmoriser.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import java.util.Arrays;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.logic.commands.FindCommand;
+import seedu.medmoriser.model.qanda.AnswerContainsKeywordsPredicate;
+import seedu.medmoriser.model.qanda.QAndAContainsKeywordsPredicate;
+import seedu.medmoriser.model.qanda.QuestionContainsKeywordsPredicate;
+import seedu.medmoriser.model.qanda.TagContainsKeywordsPredicate;
+
+public class FindCommandParserTest {
+
+ private FindCommandParser parser = new FindCommandParser();
+
+ @Test
+ public void parse_emptyArg_throwsParseException() {
+ assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_validArgsQAndAContainsKeywordsPredicate_returnsFindCommand() {
+ // no leading and trailing whitespaces
+ FindCommand expectedFindCommand =
+ new FindCommand(new QAndAContainsKeywordsPredicate(Arrays.asList("Alice", "Bob")));
+ assertParseSuccess(parser, "Alice, Bob", expectedFindCommand);
+
+ // multiple whitespaces between keywords
+ assertParseSuccess(parser, " \n Alice, \n Bob ", expectedFindCommand);
+ }
+
+ @Test
+ public void parse_validArgsAnswerContainsKeywordsPredicate_returnsFindCommand() {
+ // no leading and trailing whitespaces
+ FindCommand expectedFindCommand =
+ new FindCommand(new AnswerContainsKeywordsPredicate(Arrays.asList("Chronic Diseases", "Immune")));
+ assertParseSuccess(parser, "a/Chronic Diseases, Immune", expectedFindCommand);
+
+ // multiple whitespaces between keywords
+ assertParseSuccess(parser, "a/ \n Chronic Diseases, \n \t Immune \t", expectedFindCommand);
+ }
+
+ @Test
+ public void parse_validArgsQuestionContainsKeywordsPredicate_returnsFindCommand() {
+ // no leading and trailing whitespaces
+ FindCommand expectedFindCommand =
+ new FindCommand(new QuestionContainsKeywordsPredicate(Arrays.asList("Diabetic Condition",
+ "glucose level")));
+ assertParseSuccess(parser, "q/Diabetic Condition, glucose level", expectedFindCommand);
+
+ // multiple whitespaces between keywords
+ assertParseSuccess(parser, "q/ Diabetic Condition , glucose level ", expectedFindCommand);
+ }
+
+ @Test
+ public void parse_validArgsTagContainsKeywordsPredicate_returnsFindCommand() {
+ // no leading and trailing whitespaces
+ FindCommand expectedFindCommand =
+ new FindCommand(new TagContainsKeywordsPredicate(Arrays.asList("Immunology", "Chronic Diseases")));
+ assertParseSuccess(parser, "t/Immunology, Chronic Diseases", expectedFindCommand);
+
+ // multiple whitespaces between keywords
+ assertParseSuccess(parser, "t/ \n Immunology, \n \t Chronic Diseases \t", expectedFindCommand);
+ }
+
+ @Test
+ public void parse_emptyArgsTagContainsKeywordsPredicate_returnsFindCommand() {
+ // no leading and trailing whitespaces
+ FindCommand expectedFindCommand =
+ new FindCommand(new TagContainsKeywordsPredicate(Arrays.asList("t")));
+ assertParseSuccess(parser, "t/", expectedFindCommand);
+
+ // multiple whitespaces after t/
+ assertParseSuccess(parser, "t/ ", expectedFindCommand);
+ }
+
+ @Test
+ public void parse_multipleDifferentArgs_throwsParseException() {
+ assertParseFailure(parser, "q/heart a/blood t/body",
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_multipleSameArgs_throwsParseException() {
+ // multiple q/
+ assertParseFailure(parser, "q/heart q/blood",
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_ONE_PREFIX));
+
+ // multiple a/
+ assertParseFailure(parser, "a/pump blood a/breathe",
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_ONE_PREFIX));
+
+ // multiple t/
+ assertParseFailure(parser, "t/immune system t/cardiovascular t/skeleton",
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_ONE_PREFIX));
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/logic/parser/ListCommandParserTest.java b/src/test/java/seedu/medmoriser/logic/parser/ListCommandParserTest.java
new file mode 100644
index 00000000000..c570f462577
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/parser/ListCommandParserTest.java
@@ -0,0 +1,46 @@
+package seedu.medmoriser.logic.parser;
+
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medmoriser.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.medmoriser.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.logic.commands.ListCommand;
+
+public class ListCommandParserTest {
+
+ private ListCommandParser parser = new ListCommandParser();
+
+ @Test
+ public void parse_emptyArg_returnsListCommand() {
+ ListCommand expectedListCommand = new ListCommand(true);
+
+ // no trailing whitespace
+ assertParseSuccess(parser, "", expectedListCommand);
+
+ // trailing whitespace
+ assertParseSuccess(parser, " \t \n", expectedListCommand);
+ }
+
+ @Test
+ public void parse_validArg_returnsListCommand() {
+ // no leading and trailing whitespaces
+ ListCommand expectedListCommand = new ListCommand(false);
+ assertParseSuccess(parser, "questions", expectedListCommand);
+
+ // leading and trailing whitespace
+ assertParseSuccess(parser, "\n questions \t", expectedListCommand);
+ }
+
+ @Test
+ public void parse_invalidArgs_throwsParseException() {
+ // missing 's' from parameter
+ assertParseFailure(parser, "question",
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListCommand.MESSAGE_USAGE));
+
+ // >1 parameter
+ assertParseFailure(parser, "all questions",
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListCommand.MESSAGE_USAGE));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/medmoriser/logic/parser/MedmoriserParserTest.java
similarity index 51%
rename from src/test/java/seedu/address/logic/parser/AddressBookParserTest.java
rename to src/test/java/seedu/medmoriser/logic/parser/MedmoriserParserTest.java
index d9659205b57..0e69e0f9095 100644
--- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java
+++ b/src/test/java/seedu/medmoriser/logic/parser/MedmoriserParserTest.java
@@ -1,11 +1,11 @@
-package seedu.address.logic.parser;
+package seedu.medmoriser.logic.parser;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.TypicalIndexes.INDEX_FIRST_QANDA;
import java.util.Arrays;
import java.util.List;
@@ -13,31 +13,31 @@
import org.junit.jupiter.api.Test;
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.commands.ClearCommand;
-import seedu.address.logic.commands.DeleteCommand;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
-import seedu.address.logic.commands.ExitCommand;
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.logic.commands.HelpCommand;
-import seedu.address.logic.commands.ListCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-import seedu.address.model.person.Person;
-import seedu.address.testutil.EditPersonDescriptorBuilder;
-import seedu.address.testutil.PersonBuilder;
-import seedu.address.testutil.PersonUtil;
-
-public class AddressBookParserTest {
-
- private final AddressBookParser parser = new AddressBookParser();
+import seedu.medmoriser.logic.commands.AddCommand;
+import seedu.medmoriser.logic.commands.ClearCommand;
+import seedu.medmoriser.logic.commands.DeleteCommand;
+import seedu.medmoriser.logic.commands.EditCommand;
+import seedu.medmoriser.logic.commands.ExitCommand;
+import seedu.medmoriser.logic.commands.FindCommand;
+import seedu.medmoriser.logic.commands.HelpCommand;
+import seedu.medmoriser.logic.commands.ListCommand;
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.qanda.QAndAContainsKeywordsPredicate;
+//import seedu.medmoriser.model.qanda.QuestionContainsKeywordsPredicate;
+import seedu.medmoriser.testutil.EditQAndADescriptorBuilder;
+import seedu.medmoriser.testutil.QAndABuilder;
+import seedu.medmoriser.testutil.QAndAUtil;
+
+public class MedmoriserParserTest {
+
+ private final MedmoriserParser parser = new MedmoriserParser();
@Test
public void parseCommand_add() throws Exception {
- Person person = new PersonBuilder().build();
- AddCommand command = (AddCommand) parser.parseCommand(PersonUtil.getAddCommand(person));
- assertEquals(new AddCommand(person), command);
+ QAndA qAndA = new QAndABuilder().build();
+ AddCommand command = (AddCommand) parser.parseCommand(QAndAUtil.getAddCommand(qAndA));
+ assertEquals(new AddCommand(qAndA), command);
}
@Test
@@ -49,17 +49,18 @@ public void parseCommand_clear() throws Exception {
@Test
public void parseCommand_delete() throws Exception {
DeleteCommand command = (DeleteCommand) parser.parseCommand(
- DeleteCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased());
- assertEquals(new DeleteCommand(INDEX_FIRST_PERSON), command);
+ DeleteCommand.COMMAND_WORD + " " + INDEX_FIRST_QANDA.getOneBased());
+ assertEquals(new DeleteCommand(INDEX_FIRST_QANDA), command);
}
@Test
public void parseCommand_edit() throws Exception {
- Person person = new PersonBuilder().build();
- EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(person).build();
+ QAndA qAndA = new QAndABuilder().build();
+ EditCommand.EditQAndADescriptor descriptor = new EditQAndADescriptorBuilder(qAndA).build();
EditCommand command = (EditCommand) parser.parseCommand(EditCommand.COMMAND_WORD + " "
- + INDEX_FIRST_PERSON.getOneBased() + " " + PersonUtil.getEditPersonDescriptorDetails(descriptor));
- assertEquals(new EditCommand(INDEX_FIRST_PERSON, descriptor), command);
+ + INDEX_FIRST_QANDA.getOneBased() + " "
+ + QAndAUtil.getEditQAndADescriptorDetails(descriptor));
+ assertEquals(new EditCommand(INDEX_FIRST_QANDA, descriptor), command);
}
@Test
@@ -72,8 +73,8 @@ public void parseCommand_exit() throws Exception {
public void parseCommand_find() throws Exception {
List keywords = Arrays.asList("foo", "bar", "baz");
FindCommand command = (FindCommand) parser.parseCommand(
- FindCommand.COMMAND_WORD + " " + keywords.stream().collect(Collectors.joining(" ")));
- assertEquals(new FindCommand(new NameContainsKeywordsPredicate(keywords)), command);
+ FindCommand.COMMAND_WORD + " " + keywords.stream().collect(Collectors.joining(", ")));
+ assertEquals(new FindCommand(new QAndAContainsKeywordsPredicate(keywords)), command);
}
@Test
@@ -85,7 +86,7 @@ public void parseCommand_help() throws Exception {
@Test
public void parseCommand_list() throws Exception {
assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD) instanceof ListCommand);
- assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD + " 3") instanceof ListCommand);
+ assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD + " questions") instanceof ListCommand);
}
@Test
@@ -96,6 +97,7 @@ public void parseCommand_unrecognisedInput_throwsParseException() {
@Test
public void parseCommand_unknownCommand_throwsParseException() {
- assertThrows(ParseException.class, MESSAGE_UNKNOWN_COMMAND, () -> parser.parseCommand("unknownCommand"));
+ assertThrows(ParseException.class, MESSAGE_UNKNOWN_COMMAND, () ->
+ parser.parseCommand("unknownCommand"));
}
}
diff --git a/src/test/java/seedu/medmoriser/logic/parser/ParserUtilTest.java b/src/test/java/seedu/medmoriser/logic/parser/ParserUtilTest.java
new file mode 100644
index 00000000000..645ae6e0e47
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/parser/ParserUtilTest.java
@@ -0,0 +1,147 @@
+package seedu.medmoriser.logic.parser;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medmoriser.logic.parser.ParserUtil.MESSAGE_INVALID_QANDA_DISPLAYED_INDEX;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.TypicalIndexes.INDEX_FIRST_QANDA;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.logic.parser.exceptions.ParseException;
+import seedu.medmoriser.model.qanda.Answer;
+import seedu.medmoriser.model.qanda.Question;
+import seedu.medmoriser.model.tag.Tag;
+
+public class ParserUtilTest {
+ private static final String INVALID_QUESTION = " ";
+ private static final String INVALID_ANSWER = " ";
+ private static final String INVALID_TAG = "#tag";
+
+ private static final String VALID_QUESTION = "Valid Question";
+ private static final String VALID_ANSWER = "Valid answer";
+ private static final String VALID_TAG_1 = "tag1";
+ private static final String VALID_TAG_2 = "tag2";
+
+ private static final String WHITESPACE = " \t\r\n";
+
+ @Test
+ public void parseIndex_invalidInput_throwsParseException() {
+ assertThrows(ParseException.class, MESSAGE_INVALID_QANDA_DISPLAYED_INDEX, () ->
+ ParserUtil.parseIndex("10 a")
+ );
+ }
+
+ @Test
+ public void parseIndex_outOfRangeInput_throwsParseException() {
+ assertThrows(ParseException.class, MESSAGE_INVALID_QANDA_DISPLAYED_INDEX, () ->
+ ParserUtil.parseIndex(Long.toString(Integer.MAX_VALUE + 1))
+ );
+ }
+
+ @Test
+ public void parseIndex_validInput_success() throws Exception {
+ // No whitespaces
+ assertEquals(INDEX_FIRST_QANDA, ParserUtil.parseIndex("1"));
+
+ // Leading and trailing whitespaces
+ assertEquals(INDEX_FIRST_QANDA, ParserUtil.parseIndex(" 1 "));
+ }
+
+ @Test
+ public void parseQuestion_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parseQuestion((String) null));
+ }
+
+ @Test
+ public void parseQuestion_invalidValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseQuestion(INVALID_QUESTION));
+ }
+
+ @Test
+ public void parseQuestion_validValueWithoutWhitespace_returnsQuestion() throws Exception {
+ Question expectedQuestion = new Question(VALID_QUESTION);
+ assertEquals(expectedQuestion, ParserUtil.parseQuestion(VALID_QUESTION));
+ }
+
+ @Test
+ public void parseQuestion_validValueWithWhitespace_returnsTrimmedQuestion() throws Exception {
+ String questionWithWhitespace = WHITESPACE + VALID_QUESTION + WHITESPACE;
+ Question expectedQuestion = new Question(VALID_QUESTION);
+ assertEquals(expectedQuestion, ParserUtil.parseQuestion(questionWithWhitespace));
+ }
+
+ @Test
+ public void parseAnswer_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parseAnswer((String) null));
+ }
+
+ @Test
+ public void parseAnswer_invalidValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseAnswer(INVALID_ANSWER));
+ }
+
+ @Test
+ public void parseAnswer_validValueWithoutWhitespace_returnsAnswer() throws Exception {
+ Answer expectedAnswer = new Answer(VALID_ANSWER);
+ assertEquals(expectedAnswer, ParserUtil.parseAnswer(VALID_ANSWER));
+ }
+
+ @Test
+ public void parseAnswer_validValueWithWhitespace_returnsTrimmedAnswer() throws Exception {
+ String answerWithWhitespace = WHITESPACE + VALID_ANSWER + WHITESPACE;
+ Answer expectedAnswer = new Answer(VALID_ANSWER);
+ assertEquals(expectedAnswer, ParserUtil.parseAnswer(answerWithWhitespace));
+ }
+
+ @Test
+ public void parseTag_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parseTag(null));
+ }
+
+ @Test
+ public void parseTag_invalidValue_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseTag(INVALID_TAG));
+ }
+
+ @Test
+ public void parseTag_validValueWithoutWhitespace_returnsTag() throws Exception {
+ Tag expectedTag = new Tag(VALID_TAG_1);
+ assertEquals(expectedTag, ParserUtil.parseTag(VALID_TAG_1));
+ }
+
+ @Test
+ public void parseTag_validValueWithWhitespace_returnsTrimmedTag() throws Exception {
+ String tagWithWhitespace = WHITESPACE + VALID_TAG_1 + WHITESPACE;
+ Tag expectedTag = new Tag(VALID_TAG_1);
+ assertEquals(expectedTag, ParserUtil.parseTag(tagWithWhitespace));
+ }
+
+ @Test
+ public void parseTags_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> ParserUtil.parseTags(null));
+ }
+
+ @Test
+ public void parseTags_collectionWithInvalidTags_throwsParseException() {
+ assertThrows(ParseException.class, () -> ParserUtil.parseTags(Arrays.asList(VALID_TAG_1, INVALID_TAG)));
+ }
+
+ @Test
+ public void parseTags_emptyCollection_returnsEmptySet() throws Exception {
+ assertTrue(ParserUtil.parseTags(Collections.emptyList()).isEmpty());
+ }
+
+ @Test
+ public void parseTags_collectionWithValidTags_returnsTagSet() throws Exception {
+ Set actualTagSet = ParserUtil.parseTags(Arrays.asList(VALID_TAG_1, VALID_TAG_2));
+ Set expectedTagSet = new HashSet(Arrays.asList(new Tag(VALID_TAG_1), new Tag(VALID_TAG_2)));
+
+ assertEquals(expectedTagSet, actualTagSet);
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/logic/parser/QuizCommandParserTest.java b/src/test/java/seedu/medmoriser/logic/parser/QuizCommandParserTest.java
new file mode 100644
index 00000000000..119a83f5979
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/logic/parser/QuizCommandParserTest.java
@@ -0,0 +1,60 @@
+package seedu.medmoriser.logic.parser;
+
+import static seedu.medmoriser.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.medmoriser.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.medmoriser.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import java.util.Arrays;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.logic.commands.QuizCommand;
+import seedu.medmoriser.model.qanda.QuestionContainsKeywordsPredicate;
+import seedu.medmoriser.model.qanda.TagContainsKeywordsPredicate;
+
+public class QuizCommandParserTest {
+
+ private QuizCommandParser parser = new QuizCommandParser();
+
+ @Test
+ public void parse_emptyArg_throwsParseException() {
+ assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ QuizCommand.MESSAGE_USAGE));
+ }
+
+ @Test
+ public void parse_validArgsQuestionContainsKeywordsPredicate_returnsQuizCommand() {
+ // no leading and trailing whitespaces
+ QuizCommand expectedQuizCommand =
+ new QuizCommand(new QuestionContainsKeywordsPredicate(Arrays.asList("digestive system",
+ "skeletal system")));
+ assertParseSuccess(parser, "q/digestive system, skeletal system", expectedQuizCommand);
+
+ // multiple whitespaces between keywords
+ assertParseSuccess(parser, "q/ digestive system, skeletal system ", expectedQuizCommand);
+ }
+
+ @Test
+ public void parse_validArgsTagContainsKeywordsPredicate_returnsQuizCommand() {
+ // no leading and trailing whitespaces
+ QuizCommand expectedQuizCommand =
+ new QuizCommand(new TagContainsKeywordsPredicate(Arrays.asList("digestive system",
+ "skeletal system")));
+ assertParseSuccess(parser, "t/digestive system, skeletal system", expectedQuizCommand);
+
+ // multiple whitespaces between keywords
+ assertParseSuccess(parser, "t/ \n digestive system, \n \t skeletal system \t", expectedQuizCommand);
+ }
+
+ @Test
+ public void parse_invalidArgsMultiplePrefixes_throwsParseException() {
+ String userInput = "q/digestive system t/Human Anatomy";
+ String userInput2 = "q/digestive system t/Human Anatomy a/answer";
+
+ assertParseFailure(parser, userInput, String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ QuizCommand.MESSAGE_USAGE));
+
+ assertParseFailure(parser, userInput2, String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ QuizCommand.MESSAGE_USAGE));
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/model/MedmoriserTest.java b/src/test/java/seedu/medmoriser/model/MedmoriserTest.java
new file mode 100644
index 00000000000..7d2446ea145
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/model/MedmoriserTest.java
@@ -0,0 +1,102 @@
+package seedu.medmoriser.model;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_TAG_TAG2;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTION1;
+import static seedu.medmoriser.testutil.TypicalQAndA.getTypicalMedmoriser;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.qanda.exceptions.DuplicateQAndAException;
+import seedu.medmoriser.testutil.QAndABuilder;
+
+public class MedmoriserTest {
+
+ private final Medmoriser medmoriser = new Medmoriser();
+
+ @Test
+ public void constructor() {
+ assertEquals(Collections.emptyList(), medmoriser.getQAndAList());
+ }
+
+ @Test
+ public void resetData_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> medmoriser.resetData(null));
+ }
+
+ @Test
+ public void resetData_withValidReadOnlyMedmoriser_replacesData() {
+ Medmoriser newData = getTypicalMedmoriser();
+ medmoriser.resetData(newData);
+ assertEquals(newData, medmoriser);
+ }
+
+ @Test
+ public void resetData_withDuplicateQAndA_throwsDuplicateQAndAException() {
+ // Two QAndAs with the same identity fields
+ QAndA editedQuestion1 = new QAndABuilder(QUESTION1).withTags(VALID_TAG_TAG2)
+ .build();
+ List newQAndAs = Arrays.asList(QUESTION1, editedQuestion1);
+ MedmoriserStub newData = new MedmoriserStub(newQAndAs);
+
+ assertThrows(DuplicateQAndAException.class, () -> medmoriser.resetData(newData));
+ }
+
+ @Test
+ public void hasQAndA_nullQAndA_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> medmoriser.hasQAndA(null));
+ }
+
+ @Test
+ public void hasQAndA_qAndANotInMedmoriser_returnsFalse() {
+ assertFalse(medmoriser.hasQAndA(QUESTION1));
+ }
+
+ @Test
+ public void hasQAndA_qAndAInMedmoriser_returnsTrue() {
+ medmoriser.addQAndA(QUESTION1);
+ assertTrue(medmoriser.hasQAndA(QUESTION1));
+ }
+
+ @Test
+ public void hasQAndA_qAndAWithSameIdentityFieldsInMedmoriser_returnsTrue() {
+ medmoriser.addQAndA(QUESTION1);
+ QAndA editedQuestion1 = new QAndABuilder(QUESTION1).withTags(VALID_TAG_TAG2)
+ .build();
+ assertTrue(medmoriser.hasQAndA(editedQuestion1));
+ }
+
+ @Test
+ public void getQAndAList_modifyList_throwsUnsupportedOperationException() {
+ assertThrows(UnsupportedOperationException.class, () -> medmoriser.getQAndAList().remove(0));
+ }
+
+
+ /**
+ * A stub ReadOnlyAddressBook whose qAndAs list can violate interface constraints.
+ */
+ private static class MedmoriserStub implements ReadOnlyMedmoriser {
+ private final ObservableList qAndAs = FXCollections.observableArrayList();
+
+ MedmoriserStub(Collection qAndAs) {
+ this.qAndAs.setAll(qAndAs);
+ }
+
+ @Override
+ public ObservableList getQAndAList() {
+ return qAndAs;
+ }
+ }
+
+}
diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/seedu/medmoriser/model/ModelManagerTest.java
similarity index 54%
rename from src/test/java/seedu/address/model/ModelManagerTest.java
rename to src/test/java/seedu/medmoriser/model/ModelManagerTest.java
index 2cf1418d116..76554b923bd 100644
--- a/src/test/java/seedu/address/model/ModelManagerTest.java
+++ b/src/test/java/seedu/medmoriser/model/ModelManagerTest.java
@@ -1,12 +1,12 @@
-package seedu.address.model;
+package seedu.medmoriser.model;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
-import static seedu.address.testutil.Assert.assertThrows;
-import static seedu.address.testutil.TypicalPersons.ALICE;
-import static seedu.address.testutil.TypicalPersons.BENSON;
+import static seedu.medmoriser.model.Model.PREDICATE_SHOW_ALL_QANDA;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTION1;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTION2;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -14,9 +14,9 @@
import org.junit.jupiter.api.Test;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-import seedu.address.testutil.AddressBookBuilder;
+import seedu.medmoriser.commons.core.GuiSettings;
+import seedu.medmoriser.model.qanda.QuestionContainsKeywordsPredicate;
+import seedu.medmoriser.testutil.MedmoriserBuilder;
public class ModelManagerTest {
@@ -26,7 +26,7 @@ public class ModelManagerTest {
public void constructor() {
assertEquals(new UserPrefs(), modelManager.getUserPrefs());
assertEquals(new GuiSettings(), modelManager.getGuiSettings());
- assertEquals(new AddressBook(), new AddressBook(modelManager.getAddressBook()));
+ assertEquals(new Medmoriser(), new Medmoriser(modelManager.getMedmoriser()));
}
@Test
@@ -37,14 +37,14 @@ public void setUserPrefs_nullUserPrefs_throwsNullPointerException() {
@Test
public void setUserPrefs_validUserPrefs_copiesUserPrefs() {
UserPrefs userPrefs = new UserPrefs();
- userPrefs.setAddressBookFilePath(Paths.get("address/book/file/path"));
+ userPrefs.setMedmoriserFilePath(Paths.get("address/book/file/path"));
userPrefs.setGuiSettings(new GuiSettings(1, 2, 3, 4));
modelManager.setUserPrefs(userPrefs);
assertEquals(userPrefs, modelManager.getUserPrefs());
// Modifying userPrefs should not modify modelManager's userPrefs
UserPrefs oldUserPrefs = new UserPrefs(userPrefs);
- userPrefs.setAddressBookFilePath(Paths.get("new/address/book/file/path"));
+ userPrefs.setMedmoriserFilePath(Paths.get("new/address/book/file/path"));
assertEquals(oldUserPrefs, modelManager.getUserPrefs());
}
@@ -61,47 +61,47 @@ public void setGuiSettings_validGuiSettings_setsGuiSettings() {
}
@Test
- public void setAddressBookFilePath_nullPath_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> modelManager.setAddressBookFilePath(null));
+ public void setMedmoriserFilePath_nullPath_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> modelManager.setMedmoriserFilePath(null));
}
@Test
- public void setAddressBookFilePath_validPath_setsAddressBookFilePath() {
+ public void setMedmoriserFilePath_validPath_setsMedmoriserFilePath() {
Path path = Paths.get("address/book/file/path");
- modelManager.setAddressBookFilePath(path);
- assertEquals(path, modelManager.getAddressBookFilePath());
+ modelManager.setMedmoriserFilePath(path);
+ assertEquals(path, modelManager.getMedmoriserFilePath());
}
@Test
- public void hasPerson_nullPerson_throwsNullPointerException() {
- assertThrows(NullPointerException.class, () -> modelManager.hasPerson(null));
+ public void hasQAndA_nullQAndA_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> modelManager.hasQAndA(null));
}
@Test
- public void hasPerson_personNotInAddressBook_returnsFalse() {
- assertFalse(modelManager.hasPerson(ALICE));
+ public void hasQAndA_qAndANotInMedmoriser_returnsFalse() {
+ assertFalse(modelManager.hasQAndA(QUESTION1));
}
@Test
- public void hasPerson_personInAddressBook_returnsTrue() {
- modelManager.addPerson(ALICE);
- assertTrue(modelManager.hasPerson(ALICE));
+ public void hasQAndA_qAndAInMedmoriser_returnsTrue() {
+ modelManager.addQAndA(QUESTION1);
+ assertTrue(modelManager.hasQAndA(QUESTION1));
}
@Test
- public void getFilteredPersonList_modifyList_throwsUnsupportedOperationException() {
- assertThrows(UnsupportedOperationException.class, () -> modelManager.getFilteredPersonList().remove(0));
+ public void getFilteredQAndAList_modifyList_throwsUnsupportedOperationException() {
+ assertThrows(UnsupportedOperationException.class, () -> modelManager.getFilteredQAndAList().remove(0));
}
@Test
public void equals() {
- AddressBook addressBook = new AddressBookBuilder().withPerson(ALICE).withPerson(BENSON).build();
- AddressBook differentAddressBook = new AddressBook();
+ Medmoriser medmoriser = new MedmoriserBuilder().withQAndA(QUESTION1).withQAndA(QUESTION2).build();
+ Medmoriser differentMedmoriser = new Medmoriser();
UserPrefs userPrefs = new UserPrefs();
// same values -> returns true
- modelManager = new ModelManager(addressBook, userPrefs);
- ModelManager modelManagerCopy = new ModelManager(addressBook, userPrefs);
+ modelManager = new ModelManager(medmoriser, userPrefs);
+ ModelManager modelManagerCopy = new ModelManager(medmoriser, userPrefs);
assertTrue(modelManager.equals(modelManagerCopy));
// same object -> returns true
@@ -114,19 +114,19 @@ public void equals() {
assertFalse(modelManager.equals(5));
// different addressBook -> returns false
- assertFalse(modelManager.equals(new ModelManager(differentAddressBook, userPrefs)));
+ assertFalse(modelManager.equals(new ModelManager(differentMedmoriser, userPrefs)));
// different filteredList -> returns false
- String[] keywords = ALICE.getName().fullName.split("\\s+");
- modelManager.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(keywords)));
- assertFalse(modelManager.equals(new ModelManager(addressBook, userPrefs)));
+ String[] keywords = QUESTION1.getQuestion().question.split("\\s+");
+ modelManager.updateFilteredQAndAList(new QuestionContainsKeywordsPredicate(Arrays.asList(keywords[1])));
+ assertFalse(modelManager.equals(new ModelManager(medmoriser, userPrefs)));
// resets modelManager to initial state for upcoming tests
- modelManager.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+ modelManager.updateFilteredQAndAList(PREDICATE_SHOW_ALL_QANDA);
// different userPrefs -> returns false
UserPrefs differentUserPrefs = new UserPrefs();
- differentUserPrefs.setAddressBookFilePath(Paths.get("differentFilePath"));
- assertFalse(modelManager.equals(new ModelManager(addressBook, differentUserPrefs)));
+ differentUserPrefs.setMedmoriserFilePath(Paths.get("differentFilePath"));
+ assertFalse(modelManager.equals(new ModelManager(medmoriser, differentUserPrefs)));
}
}
diff --git a/src/test/java/seedu/address/model/UserPrefsTest.java b/src/test/java/seedu/medmoriser/model/UserPrefsTest.java
similarity index 67%
rename from src/test/java/seedu/address/model/UserPrefsTest.java
rename to src/test/java/seedu/medmoriser/model/UserPrefsTest.java
index b1307a70d52..4171e5ba49c 100644
--- a/src/test/java/seedu/address/model/UserPrefsTest.java
+++ b/src/test/java/seedu/medmoriser/model/UserPrefsTest.java
@@ -1,6 +1,6 @@
-package seedu.address.model;
+package seedu.medmoriser.model;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
import org.junit.jupiter.api.Test;
@@ -13,9 +13,9 @@ public void setGuiSettings_nullGuiSettings_throwsNullPointerException() {
}
@Test
- public void setAddressBookFilePath_nullPath_throwsNullPointerException() {
+ public void setMedmoriserFilePath_nullPath_throwsNullPointerException() {
UserPrefs userPrefs = new UserPrefs();
- assertThrows(NullPointerException.class, () -> userPrefs.setAddressBookFilePath(null));
+ assertThrows(NullPointerException.class, () -> userPrefs.setMedmoriserFilePath(null));
}
}
diff --git a/src/test/java/seedu/medmoriser/model/qanda/AnswerContainsKeywordPredicateTest.java b/src/test/java/seedu/medmoriser/model/qanda/AnswerContainsKeywordPredicateTest.java
new file mode 100644
index 00000000000..9b36f03ec4a
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/model/qanda/AnswerContainsKeywordPredicateTest.java
@@ -0,0 +1,78 @@
+package seedu.medmoriser.model.qanda;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.testutil.QAndABuilder;
+
+public class AnswerContainsKeywordPredicateTest {
+ @Test
+ public void equals() {
+ List firstPredicateKeywordList = Collections.singletonList("first");
+ List secondPredicateKeywordList = Arrays.asList("first", "second");
+
+ AnswerContainsKeywordsPredicate firstPredicate =
+ new AnswerContainsKeywordsPredicate(firstPredicateKeywordList);
+ AnswerContainsKeywordsPredicate secondPredicate =
+ new AnswerContainsKeywordsPredicate(secondPredicateKeywordList);
+
+ // same object -> returns true
+ assertTrue(firstPredicate.equals(firstPredicate));
+
+ // same values -> returns true
+ AnswerContainsKeywordsPredicate firstPredicateCopy =
+ new AnswerContainsKeywordsPredicate(firstPredicateKeywordList);
+ assertTrue(firstPredicate.equals(firstPredicateCopy));
+
+ // different types -> returns false
+ assertFalse(firstPredicate.equals(1));
+
+ // null -> returns false
+ assertFalse(firstPredicate.equals(null));
+
+ // different qAndA -> returns false
+ assertFalse(firstPredicate.equals(secondPredicate));
+ }
+
+ @Test
+ public void test_answerContainsKeywords_returnsTrue() {
+ // One keyword
+ AnswerContainsKeywordsPredicate predicate =
+ new AnswerContainsKeywordsPredicate(Collections.singletonList("Alice"));
+ assertTrue(predicate.test(new QAndABuilder().withAnswer("Alice Bob").build()));
+
+ // Multiple keywords
+ predicate = new AnswerContainsKeywordsPredicate(Arrays.asList("Alice", "Bob"));
+ assertTrue(predicate.test(new QAndABuilder().withAnswer("Alice Bob").build()));
+
+ // Only one matching keyword
+ predicate = new AnswerContainsKeywordsPredicate(Arrays.asList("Bob", "Carol"));
+ assertTrue(predicate.test(new QAndABuilder().withAnswer("Alice Carol").build()));
+
+ // Mixed-case keywords
+ predicate = new AnswerContainsKeywordsPredicate(Arrays.asList("aLIce", "bOB"));
+ assertTrue(predicate.test(new QAndABuilder().withAnswer("Alice Bob").build()));
+ }
+
+ @Test
+ public void test_answerDoesNotContainKeywords_returnsFalse() {
+ // Zero keywords
+ AnswerContainsKeywordsPredicate predicate = new AnswerContainsKeywordsPredicate(Collections.emptyList());
+ assertFalse(predicate.test(new QAndABuilder().withAnswer("Alice").build()));
+
+ // Non-matching keyword
+ predicate = new AnswerContainsKeywordsPredicate(Arrays.asList("Carol"));
+ assertFalse(predicate.test(new QAndABuilder().withAnswer("Alice Bob").build()));
+
+ // Keywords match question, tag, but does not match answer
+ predicate = new AnswerContainsKeywordsPredicate(Arrays.asList("12345", "fakeTag", "Ma1n", "Stre3t"));
+ assertFalse(predicate.test(new QAndABuilder().withQuestion("Alice")
+ .withTags("fakeTag").withAnswer("Main Street").build()));
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/model/qanda/AnswerTest.java b/src/test/java/seedu/medmoriser/model/qanda/AnswerTest.java
new file mode 100644
index 00000000000..8bc9ca26197
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/model/qanda/AnswerTest.java
@@ -0,0 +1,36 @@
+package seedu.medmoriser.model.qanda;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+public class AnswerTest {
+
+ @Test
+ public void constructor_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> new Answer(null));
+ }
+
+ @Test
+ public void constructor_inValidAnswer_throwsIllegalArgumentException() {
+ String inValidAnswer = "";
+ assertThrows(IllegalArgumentException.class, () -> new Answer(inValidAnswer));
+ }
+
+ @Test
+ public void isValidAnswer() {
+ // null answer
+ assertThrows(NullPointerException.class, () -> Answer.isValidAnswer(null));
+
+ // invalid answeres
+ assertFalse(Answer.isValidAnswer("")); // empty string
+ assertFalse(Answer.isValidAnswer(" ")); // spaces only
+
+ // valid answeres
+ assertTrue(Answer.isValidAnswer("Blk 456, Den Road, #01-355"));
+ assertTrue(Answer.isValidAnswer("-")); // one character
+ assertTrue(Answer.isValidAnswer("Leng Inc; 1234 Market St; San Francisco CA 2349879; USA")); // long answer
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/model/qanda/QAndAContainsKeywordPredicateTest.java b/src/test/java/seedu/medmoriser/model/qanda/QAndAContainsKeywordPredicateTest.java
new file mode 100644
index 00000000000..02f9e745ed8
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/model/qanda/QAndAContainsKeywordPredicateTest.java
@@ -0,0 +1,78 @@
+package seedu.medmoriser.model.qanda;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.testutil.QAndABuilder;
+
+public class QAndAContainsKeywordPredicateTest {
+ @Test
+ public void equals() {
+ List firstPredicateKeywordList = Collections.singletonList("first");
+ List secondPredicateKeywordList = Arrays.asList("first", "second");
+
+ QAndAContainsKeywordsPredicate firstPredicate =
+ new QAndAContainsKeywordsPredicate(firstPredicateKeywordList);
+ QAndAContainsKeywordsPredicate secondPredicate =
+ new QAndAContainsKeywordsPredicate(secondPredicateKeywordList);
+
+ // same object -> returns true
+ assertTrue(firstPredicate.equals(firstPredicate));
+
+ // same values -> returns true
+ QAndAContainsKeywordsPredicate firstPredicateCopy =
+ new QAndAContainsKeywordsPredicate(firstPredicateKeywordList);
+ assertTrue(firstPredicate.equals(firstPredicateCopy));
+
+ // different types -> returns false
+ assertFalse(firstPredicate.equals(1));
+
+ // null -> returns false
+ assertFalse(firstPredicate.equals(null));
+
+ // different qAndA -> returns false
+ assertFalse(firstPredicate.equals(secondPredicate));
+ }
+
+ @Test
+ public void test_qAndAContainsKeywords_returnsTrue() {
+ // One keyword
+ QAndAContainsKeywordsPredicate predicate =
+ new QAndAContainsKeywordsPredicate(Collections.singletonList("Alice"));
+ assertTrue(predicate.test(new QAndABuilder().withQuestion("Charlie").withAnswer("Alice Bob").build()));
+
+ // Multiple keywords
+ predicate = new QAndAContainsKeywordsPredicate(Arrays.asList("Alice", "Bob"));
+ assertTrue(predicate.test(new QAndABuilder().withQuestion("Bob").withAnswer("Alice").build()));
+
+ // Only one matching keyword
+ predicate = new QAndAContainsKeywordsPredicate(Arrays.asList("Bob", "Carol"));
+ assertTrue(predicate.test(new QAndABuilder().withQuestion("Tom").withAnswer("Alice Carol").build()));
+
+ // Mixed-case keywords
+ predicate = new QAndAContainsKeywordsPredicate(Arrays.asList("aLIce", "bOB"));
+ assertTrue(predicate.test(new QAndABuilder().withQuestion("Bob").withAnswer("Alice").build()));
+ }
+
+ @Test
+ public void test_qAndADoesNotContainKeywords_returnsFalse() {
+ // Zero keywords
+ QAndAContainsKeywordsPredicate predicate = new QAndAContainsKeywordsPredicate(Collections.emptyList());
+ assertFalse(predicate.test(new QAndABuilder().withQuestion("Bob").withAnswer("Alice").build()));
+
+ // Non-matching keyword
+ predicate = new QAndAContainsKeywordsPredicate(Arrays.asList("Carol"));
+ assertFalse(predicate.test(new QAndABuilder().withQuestion("Tom").withAnswer("Alice Bob").build()));
+
+ // Keywords match tag, but does not match Question or Answer
+ predicate = new QAndAContainsKeywordsPredicate(Arrays.asList("12345", "fakeTag", "Ma1n", "Stre3t"));
+ assertFalse(predicate.test(new QAndABuilder().withQuestion("Alice")
+ .withTags("fakeTag").withAnswer("Main Street").build()));
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/model/qanda/QAndATest.java b/src/test/java/seedu/medmoriser/model/qanda/QAndATest.java
new file mode 100644
index 00000000000..e3989995e7a
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/model/qanda/QAndATest.java
@@ -0,0 +1,78 @@
+package seedu.medmoriser.model.qanda;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_ANSWER_B;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_QUESTION_B;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_TAG_TAG2;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTION1;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTIONB;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.testutil.QAndABuilder;
+
+public class QAndATest {
+
+ @Test
+ public void asObservableList_modifyList_throwsUnsupportedOperationException() {
+ QAndA qAndA = new QAndABuilder().build();
+ assertThrows(UnsupportedOperationException.class, () -> qAndA.getTags().remove(0));
+ }
+
+ @Test
+ public void isSameQAndA() {
+ // same object -> returns true
+ assertTrue(QUESTION1.isSameQAndA(QUESTION1));
+
+ // null -> returns false
+ assertFalse(QUESTION1.isSameQAndA(null));
+
+ QAndA editedQuestion1;
+
+ // different question -> returns false
+ editedQuestion1 = new QAndABuilder(QUESTION1).withQuestion(VALID_QUESTION_B).build();
+ assertFalse(QUESTION1.isSameQAndA(editedQuestion1));
+
+ // same question, different answer -> returns true
+ editedQuestion1 = new QAndABuilder(QUESTION1).withAnswer(VALID_ANSWER_B)
+ .withTags(VALID_TAG_TAG2).build();
+ assertTrue(QUESTION1.isSameQAndA(editedQuestion1));
+
+ // same question, same answer, different tag -> returns true
+ editedQuestion1 = new QAndABuilder(QUESTION1).withTags(VALID_TAG_TAG2).build();
+ assertTrue(QUESTION1.isSameQAndA(editedQuestion1));
+ }
+
+ @Test
+ public void equals() {
+ // same values -> returns true
+ QAndA question1Copy = new QAndABuilder(QUESTION1).build();
+ assertTrue(QUESTION1.equals(question1Copy));
+
+ // same object -> returns true
+ assertTrue(QUESTION1.equals(QUESTION1));
+
+ // null -> returns false
+ assertFalse(QUESTION1.equals(null));
+
+ // different type -> returns false
+ assertFalse(QUESTION1.equals(5));
+
+ // different questionSet -> returns false
+ assertFalse(QUESTION1.equals(QUESTIONB));
+
+ // different question -> returns false
+ QAndA editedQuestion1 = new QAndABuilder(QUESTION1).withQuestion(VALID_QUESTION_B).build();
+ assertFalse(QUESTION1.equals(editedQuestion1));
+
+ // different answer -> returns false
+ editedQuestion1 = new QAndABuilder(QUESTION1).withAnswer(VALID_ANSWER_B).build();
+ assertFalse(QUESTION1.equals(editedQuestion1));
+
+ // different tags -> returns false
+ editedQuestion1 = new QAndABuilder(QUESTION1).withTags(VALID_TAG_TAG2).build();
+ assertFalse(QUESTION1.equals(editedQuestion1));
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/model/qanda/QuestionContainsKeywordsPredicateTest.java b/src/test/java/seedu/medmoriser/model/qanda/QuestionContainsKeywordsPredicateTest.java
new file mode 100644
index 00000000000..2f2d59449c3
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/model/qanda/QuestionContainsKeywordsPredicateTest.java
@@ -0,0 +1,79 @@
+package seedu.medmoriser.model.qanda;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.testutil.QAndABuilder;
+
+public class QuestionContainsKeywordsPredicateTest {
+
+ @Test
+ public void equals() {
+ List firstPredicateKeywordList = Collections.singletonList("first");
+ List secondPredicateKeywordList = Arrays.asList("first", "second");
+
+ QuestionContainsKeywordsPredicate firstPredicate =
+ new QuestionContainsKeywordsPredicate(firstPredicateKeywordList);
+ QuestionContainsKeywordsPredicate secondPredicate =
+ new QuestionContainsKeywordsPredicate(secondPredicateKeywordList);
+
+ // same object -> returns true
+ assertTrue(firstPredicate.equals(firstPredicate));
+
+ // same values -> returns true
+ QuestionContainsKeywordsPredicate firstPredicateCopy =
+ new QuestionContainsKeywordsPredicate(firstPredicateKeywordList);
+ assertTrue(firstPredicate.equals(firstPredicateCopy));
+
+ // different types -> returns false
+ assertFalse(firstPredicate.equals(1));
+
+ // null -> returns false
+ assertFalse(firstPredicate.equals(null));
+
+ // different qAndA -> returns false
+ assertFalse(firstPredicate.equals(secondPredicate));
+ }
+
+ @Test
+ public void test_questionContainsKeywords_returnsTrue() {
+ // One keyword
+ QuestionContainsKeywordsPredicate predicate =
+ new QuestionContainsKeywordsPredicate(Collections.singletonList("Alice"));
+ assertTrue(predicate.test(new QAndABuilder().withQuestion("Alice Bob").build()));
+
+ // Multiple keywords
+ predicate = new QuestionContainsKeywordsPredicate(Arrays.asList("Alice", "Bob"));
+ assertTrue(predicate.test(new QAndABuilder().withQuestion("Alice Bob").build()));
+
+ // Only one matching keyword
+ predicate = new QuestionContainsKeywordsPredicate(Arrays.asList("Bob", "Carol"));
+ assertTrue(predicate.test(new QAndABuilder().withQuestion("Alice Carol").build()));
+
+ // Mixed-case keywords
+ predicate = new QuestionContainsKeywordsPredicate(Arrays.asList("aLIce", "bOB"));
+ assertTrue(predicate.test(new QAndABuilder().withQuestion("Alice Bob").build()));
+ }
+
+ @Test
+ public void test_questionDoesNotContainKeywords_returnsFalse() {
+ // Zero keywords
+ QuestionContainsKeywordsPredicate predicate = new QuestionContainsKeywordsPredicate(Collections.emptyList());
+ assertFalse(predicate.test(new QAndABuilder().withQuestion("Alice").build()));
+
+ // Non-matching keyword
+ predicate = new QuestionContainsKeywordsPredicate(Arrays.asList("Carol"));
+ assertFalse(predicate.test(new QAndABuilder().withQuestion("Alice Bob").build()));
+
+ // Keywords match tag and answer, but does not match question
+ predicate = new QuestionContainsKeywordsPredicate(Arrays.asList("12345", "fakeTag", "Main", "Street"));
+ assertFalse(predicate.test(new QAndABuilder().withQuestion("Alice")
+ .withTags("fakeTag").withAnswer("Main Street").build()));
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/model/qanda/QuestionTest.java b/src/test/java/seedu/medmoriser/model/qanda/QuestionTest.java
new file mode 100644
index 00000000000..d27fecce18f
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/model/qanda/QuestionTest.java
@@ -0,0 +1,38 @@
+package seedu.medmoriser.model.qanda;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+public class QuestionTest {
+
+ @Test
+ public void constructor_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> new Question(null));
+ }
+
+ @Test
+ public void constructor_invalidQuestion_throwsIllegalArgumentException() {
+ String invalidQuestion = "";
+ assertThrows(IllegalArgumentException.class, () -> new Question(invalidQuestion));
+ }
+
+ @Test
+ public void isValidQuestion() {
+ // null question
+ assertThrows(NullPointerException.class, () -> Question.isValidQuestion(null));
+
+ // invalid question
+ assertFalse(Question.isValidQuestion("")); // empty string
+ assertFalse(Question.isValidQuestion(" ")); // spaces only
+
+ // valid question
+ assertTrue(Question.isValidQuestion("peter jack")); // alphabets only
+ assertTrue(Question.isValidQuestion("12345")); // numbers only
+ assertTrue(Question.isValidQuestion("peter the 2nd")); // alphanumeric characters
+ assertTrue(Question.isValidQuestion("Capital Tan")); // with capital letters
+ assertTrue(Question.isValidQuestion("David Roger Jackson Ray Jr 2nd")); // long question
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/model/qanda/TagContainsKeywordPredicateTest.java b/src/test/java/seedu/medmoriser/model/qanda/TagContainsKeywordPredicateTest.java
new file mode 100644
index 00000000000..17135d9306f
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/model/qanda/TagContainsKeywordPredicateTest.java
@@ -0,0 +1,86 @@
+package seedu.medmoriser.model.qanda;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.testutil.QAndABuilder;
+
+public class TagContainsKeywordPredicateTest {
+ @Test
+ public void equals() {
+ List firstPredicateKeywordList = Collections.singletonList("first");
+ List secondPredicateKeywordList = Arrays.asList("first", "second");
+
+ TagContainsKeywordsPredicate firstPredicate =
+ new TagContainsKeywordsPredicate(firstPredicateKeywordList);
+ TagContainsKeywordsPredicate secondPredicate =
+ new TagContainsKeywordsPredicate(secondPredicateKeywordList);
+
+ // same object -> returns true
+ assertTrue(firstPredicate.equals(firstPredicate));
+
+ // same values -> returns true
+ TagContainsKeywordsPredicate firstPredicateCopy =
+ new TagContainsKeywordsPredicate(firstPredicateKeywordList);
+ assertTrue(firstPredicate.equals(firstPredicateCopy));
+
+ // different types -> returns false
+ assertFalse(firstPredicate.equals(1));
+
+ // null -> returns false
+ assertFalse(firstPredicate.equals(null));
+
+ // different qAndA -> returns false
+ assertFalse(firstPredicate.equals(secondPredicate));
+ }
+
+ @Test
+ public void test_tagContainsKeywords_returnsTrue() {
+ // One keyword
+ TagContainsKeywordsPredicate predicate =
+ new TagContainsKeywordsPredicate(Collections.singletonList("Alice"));
+ assertTrue(predicate.test(new QAndABuilder().withTags("Alice", "Bob").build()));
+
+ // Multiple keywords
+ predicate = new TagContainsKeywordsPredicate(Arrays.asList("Alice", "Bob"));
+ assertTrue(predicate.test(new QAndABuilder().withTags("Alice", "Bob").build()));
+
+ // Only one matching keyword
+ predicate = new TagContainsKeywordsPredicate(Arrays.asList("Bob", "Carol"));
+ assertTrue(predicate.test(new QAndABuilder().withTags("Alice", "Carol").build()));
+
+ // Mixed-case keywords
+ predicate = new TagContainsKeywordsPredicate(Arrays.asList("aLIce", "bOB"));
+ assertTrue(predicate.test(new QAndABuilder().withTags("Alice", "Bob").build()));
+
+ // Words with spacing
+ predicate = new TagContainsKeywordsPredicate(Arrays.asList("Nervous System", "Cardiology"));
+ assertTrue(predicate.test(new QAndABuilder().withTags("nervous System", "Hematology").build()));
+ }
+
+ @Test
+ public void test_tagDoesNotContainKeywords_returnsFalse() {
+ // Zero keywords (should not be possible for user to end up in this test case)
+ TagContainsKeywordsPredicate predicate = new TagContainsKeywordsPredicate(Collections.emptyList());
+ assertFalse(predicate.test(new QAndABuilder().withTags("Alice").build()));
+
+ // Zero keywords entered
+ predicate = new TagContainsKeywordsPredicate(Arrays.asList("t"));
+ assertFalse(predicate.test(new QAndABuilder().withTags("Alice").build()));
+
+ // Non-matching keyword
+ predicate = new TagContainsKeywordsPredicate(Arrays.asList("Carol"));
+ assertFalse(predicate.test(new QAndABuilder().withTags("Alice", "Bob").build()));
+
+ // Keywords match question and answer, but does not match tag
+ predicate = new TagContainsKeywordsPredicate(Arrays.asList("12345", "alice@email.com", "Main", "Street"));
+ assertFalse(predicate.test(new QAndABuilder().withQuestion("Alice").withAnswer("Main Street")
+ .withTags("Immunology").build()));
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/model/qanda/UniqueQAndAListTest.java b/src/test/java/seedu/medmoriser/model/qanda/UniqueQAndAListTest.java
new file mode 100644
index 00000000000..622f0c94293
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/model/qanda/UniqueQAndAListTest.java
@@ -0,0 +1,176 @@
+package seedu.medmoriser.model.qanda;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_ANSWER_B;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_TAG_TAG2;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTION1;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTIONB;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.model.qanda.exceptions.DuplicateQAndAException;
+import seedu.medmoriser.model.qanda.exceptions.QAndANotFoundException;
+import seedu.medmoriser.testutil.QAndABuilder;
+
+public class UniqueQAndAListTest {
+
+ private final UniqueQAndAList uniqueQAndAList = new UniqueQAndAList();
+
+ @Test
+ public void contains_nullQAndA_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> uniqueQAndAList.contains(null));
+ }
+
+ @Test
+ public void contains_qAndANotInList_returnsFalse() {
+ assertFalse(uniqueQAndAList.contains(QUESTION1));
+ }
+
+ @Test
+ public void contains_qAndAInList_returnsTrue() {
+ uniqueQAndAList.add(QUESTION1);
+ assertTrue(uniqueQAndAList.contains(QUESTION1));
+ }
+
+ @Test
+ public void contains_qAndAWithSameIdentityFieldsInList_returnsTrue() {
+ uniqueQAndAList.add(QUESTION1);
+ QAndA editedQuestion1 = new QAndABuilder(QUESTION1).withTags(VALID_TAG_TAG2)
+ .build();
+ assertTrue(uniqueQAndAList.contains(editedQuestion1));
+ }
+
+ @Test
+ public void add_nullQAndA_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> uniqueQAndAList.add(null));
+ }
+
+ @Test
+ public void add_duplicateQAndA_throwsDuplicateQAndAException() {
+ uniqueQAndAList.add(QUESTION1);
+ assertThrows(DuplicateQAndAException.class, () -> uniqueQAndAList.add(QUESTION1));
+ }
+
+ @Test
+ public void setQAndA_nullTargetQAndA_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> uniqueQAndAList.setQAndA(null, QUESTION1));
+ }
+
+ @Test
+ public void setQAndA_nullEditedQAndA_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () ->
+ uniqueQAndAList.setQAndA(QUESTION1, null));
+ }
+
+ @Test
+ public void setQAndA_targetQAndANotInList_throwsQAndANotFoundException() {
+ assertThrows(QAndANotFoundException.class, () -> uniqueQAndAList.setQAndA(QUESTION1, QUESTION1));
+ }
+
+ @Test
+ public void setQAndA_editedQAndAIsSameQAndA_success() {
+ uniqueQAndAList.add(QUESTION1);
+ uniqueQAndAList.setQAndA(QUESTION1, QUESTION1);
+ UniqueQAndAList expectedUniqueQAndAList = new UniqueQAndAList();
+ expectedUniqueQAndAList.add(QUESTION1);
+ assertEquals(expectedUniqueQAndAList, uniqueQAndAList);
+ }
+
+ @Test
+ public void setQAndA_editedQAndAHasSameIdentity_success() {
+ uniqueQAndAList.add(QUESTION1);
+ QAndA editedQuestion1 = new QAndABuilder(QUESTION1).withAnswer(VALID_ANSWER_B)
+ .withTags(VALID_TAG_TAG2)
+ .build();
+ uniqueQAndAList.setQAndA(QUESTION1, editedQuestion1);
+ UniqueQAndAList expectedUniqueQAndAList = new UniqueQAndAList();
+ expectedUniqueQAndAList.add(editedQuestion1);
+ assertEquals(expectedUniqueQAndAList, uniqueQAndAList);
+ }
+
+ @Test
+ public void setQAndA_editedQAndAHasDifferentIdentity_success() {
+ uniqueQAndAList.add(QUESTION1);
+ uniqueQAndAList.setQAndA(QUESTION1, QUESTIONB);
+ UniqueQAndAList expectedUniqueQAndAList = new UniqueQAndAList();
+ expectedUniqueQAndAList.add(QUESTIONB);
+ assertEquals(expectedUniqueQAndAList, uniqueQAndAList);
+ }
+
+ @Test
+ public void setQAndA_editedQAndAHasNonUniqueIdentity_throwsDuplicateQAndAException() {
+ uniqueQAndAList.add(QUESTION1);
+ uniqueQAndAList.add(QUESTIONB);
+ assertThrows(DuplicateQAndAException.class, () -> uniqueQAndAList.setQAndA(QUESTION1, QUESTIONB));
+ }
+
+ @Test
+ public void remove_nullQAndA_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> uniqueQAndAList.remove(null));
+ }
+
+ @Test
+
+ public void remove_qAndADoesNotExist_throwsQAndANotFoundException() {
+ assertThrows(QAndANotFoundException.class, () -> uniqueQAndAList.remove(QUESTION1));
+ }
+
+ @Test
+ public void remove_existingQAndA_removesQAndA() {
+ uniqueQAndAList.add(QUESTION1);
+ uniqueQAndAList.remove(QUESTION1);
+ UniqueQAndAList expectedUniqueQAndAList = new UniqueQAndAList();
+ assertEquals(expectedUniqueQAndAList, uniqueQAndAList);
+ }
+
+ @Test
+ public void setQAndAs_nullUniqueQAndAList_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () ->
+ uniqueQAndAList.setQAndAs((UniqueQAndAList) null));
+ }
+
+ @Test
+ public void setQAndAs_uniqueQAndAList_replacesOwnListWithProvidedUniqueQAndAsList() {
+ uniqueQAndAList.add(QUESTION1);
+ UniqueQAndAList expectedUniqueQAndAList = new UniqueQAndAList();
+ expectedUniqueQAndAList.add(QUESTIONB);
+ uniqueQAndAList.setQAndAs(expectedUniqueQAndAList);
+ assertEquals(expectedUniqueQAndAList, uniqueQAndAList);
+ }
+
+ @Test
+ public void setQAndAs_nullList_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () ->
+ uniqueQAndAList.setQAndAs((List) null));
+ }
+
+ @Test
+ public void setQAndAs_list_replacesOwnListWithProvidedList() {
+ uniqueQAndAList.add(QUESTION1);
+ List qAndAList = Collections.singletonList(QUESTIONB);
+ uniqueQAndAList.setQAndAs(qAndAList);
+ UniqueQAndAList expectedUniqueQAndAList = new UniqueQAndAList();
+ expectedUniqueQAndAList.add(QUESTIONB);
+ assertEquals(expectedUniqueQAndAList, uniqueQAndAList);
+ }
+
+ @Test
+ public void setQAndAs_listWithDuplicateQuestions_throwsDuplicateQAndAException() {
+ List listWithDuplicateQAndAs = Arrays.asList(QUESTION1, QUESTION1);
+ assertThrows(DuplicateQAndAException.class, () ->
+ uniqueQAndAList.setQAndAs(listWithDuplicateQAndAs));
+ }
+
+ @Test
+ public void asUnmodifiableObservableList_modifyList_throwsUnsupportedOperationException() {
+ assertThrows(UnsupportedOperationException.class, () ->
+ uniqueQAndAList.asUnmodifiableObservableList().remove(0));
+ }
+}
diff --git a/src/test/java/seedu/address/model/tag/TagTest.java b/src/test/java/seedu/medmoriser/model/tag/TagTest.java
similarity index 85%
rename from src/test/java/seedu/address/model/tag/TagTest.java
rename to src/test/java/seedu/medmoriser/model/tag/TagTest.java
index 64d07d79ee2..2bac221598b 100644
--- a/src/test/java/seedu/address/model/tag/TagTest.java
+++ b/src/test/java/seedu/medmoriser/model/tag/TagTest.java
@@ -1,6 +1,6 @@
-package seedu.address.model.tag;
+package seedu.medmoriser.model.tag;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/seedu/medmoriser/storage/JsonAdaptedQAndATest.java b/src/test/java/seedu/medmoriser/storage/JsonAdaptedQAndATest.java
new file mode 100644
index 00000000000..0381e356677
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/storage/JsonAdaptedQAndATest.java
@@ -0,0 +1,74 @@
+package seedu.medmoriser.storage;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static seedu.medmoriser.storage.JsonAdaptedQAndA.MISSING_FIELD_MESSAGE_FORMAT;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTION2;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.commons.exceptions.IllegalValueException;
+import seedu.medmoriser.model.qanda.Answer;
+import seedu.medmoriser.model.qanda.Question;
+
+public class JsonAdaptedQAndATest {
+ private static final String INVALID_QUESTION = " ";
+ private static final String INVALID_ANSWER = " ";
+ private static final String INVALID_TAG = "#friend";
+
+ private static final String VALID_QUESTION = QUESTION2.getQuestion().toString();
+ private static final String VALID_ANSWER = QUESTION2.getAnswer().toString();
+ private static final List VALID_TAGS = QUESTION2.getTags().stream()
+ .map(JsonAdaptedTag::new)
+ .collect(Collectors.toList());
+
+ @Test
+ public void toModelType_validQAndADetails_returnsQAndA() throws Exception {
+ JsonAdaptedQAndA qAndA = new JsonAdaptedQAndA(QUESTION2);
+ assertEquals(QUESTION2, qAndA.toModelType());
+ }
+
+ @Test
+ public void toModelType_invalidQuestion_throwsIllegalValueException() {
+ JsonAdaptedQAndA qAndA =
+ new JsonAdaptedQAndA(INVALID_QUESTION, VALID_ANSWER, VALID_TAGS);
+ String expectedMessage = Question.MESSAGE_CONSTRAINTS;
+ assertThrows(IllegalValueException.class, expectedMessage, qAndA::toModelType);
+ }
+
+ @Test
+ public void toModelType_nullQuestion_throwsIllegalValueException() {
+ JsonAdaptedQAndA qAndA = new JsonAdaptedQAndA(null, VALID_ANSWER, VALID_TAGS);
+ String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Question.class.getSimpleName());
+ assertThrows(IllegalValueException.class, expectedMessage, qAndA::toModelType);
+ }
+
+ @Test
+ public void toModelType_invalidAnswer_throwsIllegalValueException() {
+ JsonAdaptedQAndA questionSize =
+ new JsonAdaptedQAndA(VALID_QUESTION, INVALID_ANSWER, VALID_TAGS);
+ String expectedMessage = Answer.MESSAGE_CONSTRAINTS;
+ assertThrows(IllegalValueException.class, expectedMessage, questionSize::toModelType);
+ }
+
+ @Test
+ public void toModelType_nullAnswer_throwsIllegalValueException() {
+ JsonAdaptedQAndA questionSize = new JsonAdaptedQAndA(VALID_QUESTION, null, VALID_TAGS);
+ String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Answer.class.getSimpleName());
+ assertThrows(IllegalValueException.class, expectedMessage, questionSize::toModelType);
+ }
+
+ @Test
+ public void toModelType_invalidTags_throwsIllegalValueException() {
+ List invalidTags = new ArrayList<>(VALID_TAGS);
+ invalidTags.add(new JsonAdaptedTag(INVALID_TAG));
+ JsonAdaptedQAndA qAndA =
+ new JsonAdaptedQAndA(VALID_QUESTION, VALID_ANSWER, invalidTags);
+ assertThrows(IllegalValueException.class, qAndA::toModelType);
+ }
+
+}
diff --git a/src/test/java/seedu/medmoriser/storage/JsonMedmoriserStorageTest.java b/src/test/java/seedu/medmoriser/storage/JsonMedmoriserStorageTest.java
new file mode 100644
index 00000000000..cd5e134360d
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/storage/JsonMedmoriserStorageTest.java
@@ -0,0 +1,111 @@
+package seedu.medmoriser.storage;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTION1;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTION8;
+import static seedu.medmoriser.testutil.TypicalQAndA.QUESTION9;
+import static seedu.medmoriser.testutil.TypicalQAndA.getTypicalMedmoriser;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import seedu.medmoriser.commons.exceptions.DataConversionException;
+import seedu.medmoriser.model.Medmoriser;
+import seedu.medmoriser.model.ReadOnlyMedmoriser;
+
+public class JsonMedmoriserStorageTest {
+ private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonMedmoriserStorageTest");
+
+ @TempDir
+ public Path testFolder;
+
+ @Test
+ public void readMedmoriser_nullFilePath_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> readMedmoriser(null));
+ }
+
+ private java.util.Optional readMedmoriser(String filePath) throws Exception {
+ return new JsonMedmoriserStorage(Paths.get(filePath)).readMedmoriser(addToTestDataPathIfNotNull(filePath));
+ }
+
+ private Path addToTestDataPathIfNotNull(String prefsFileInTestDataFolder) {
+ return prefsFileInTestDataFolder != null
+ ? TEST_DATA_FOLDER.resolve(prefsFileInTestDataFolder)
+ : null;
+ }
+
+ @Test
+ public void read_missingFile_emptyResult() throws Exception {
+ assertFalse(readMedmoriser("NonExistentFile.json").isPresent());
+ }
+
+ @Test
+ public void read_notJsonFormat_exceptionThrown() {
+ assertThrows(DataConversionException.class, () -> readMedmoriser("notJsonFormatMedmoriser.json"));
+ }
+
+ @Test
+ public void readMedmoriser_invalidQAndAMedmoriser_throwDataConversionException() {
+ assertThrows(DataConversionException.class, () -> readMedmoriser("invalidQAndAMedmoriser.json"));
+ }
+
+ @Test
+ public void readMedmoriser_invalidAndValidQAndAMedmoriser_throwDataConversionException() {
+ assertThrows(DataConversionException.class, () ->
+ readMedmoriser("invalidAndValidQAndAMedmoriser.json"));
+ }
+
+ @Test
+ public void readAndSaveMedmoriser_allInOrder_success() throws Exception {
+ Path filePath = testFolder.resolve("TempAddressBook.json");
+ Medmoriser original = getTypicalMedmoriser();
+ JsonMedmoriserStorage jsonMedmoriserStorage = new JsonMedmoriserStorage(filePath);
+
+ // Save in new file and read back
+ jsonMedmoriserStorage.saveMedmoriser(original, filePath);
+ ReadOnlyMedmoriser readBack = jsonMedmoriserStorage.readMedmoriser(filePath).get();
+ assertEquals(original, new Medmoriser(readBack));
+
+ // Modify data, overwrite exiting file, and read back
+ original.addQAndA(QUESTION8);
+ original.removeQAndA(QUESTION1);
+ jsonMedmoriserStorage.saveMedmoriser(original, filePath);
+ readBack = jsonMedmoriserStorage.readMedmoriser(filePath).get();
+ assertEquals(original, new Medmoriser(readBack));
+
+ // Save and read without specifying file path
+ original.addQAndA(QUESTION9);
+ jsonMedmoriserStorage.saveMedmoriser(original); // file path not specified
+ readBack = jsonMedmoriserStorage.readMedmoriser().get(); // file path not specified
+ assertEquals(original, new Medmoriser(readBack));
+
+ }
+
+ @Test
+ public void saveMedmoriser_nullMedmoriser_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> saveMedmoriser(null, "SomeFile.json"));
+ }
+
+ /**
+ * Saves {@code medmoriser} at the specified {@code filePath}.
+ */
+ private void saveMedmoriser(ReadOnlyMedmoriser medmoriser, String filePath) {
+ try {
+ new JsonMedmoriserStorage(Paths.get(filePath))
+ .saveMedmoriser(medmoriser, addToTestDataPathIfNotNull(filePath));
+ } catch (IOException ioe) {
+ throw new AssertionError("There should not be an error writing to the file.", ioe);
+ }
+ }
+
+ @Test
+ public void saveMedmoriser_nullFilePath_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> saveMedmoriser(new Medmoriser(), null));
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/storage/JsonSerializableMedmoriserTest.java b/src/test/java/seedu/medmoriser/storage/JsonSerializableMedmoriserTest.java
new file mode 100644
index 00000000000..cc94f1598b5
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/storage/JsonSerializableMedmoriserTest.java
@@ -0,0 +1,51 @@
+package seedu.medmoriser.storage;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.medmoriser.commons.exceptions.IllegalValueException;
+import seedu.medmoriser.commons.util.JsonUtil;
+import seedu.medmoriser.model.Medmoriser;
+import seedu.medmoriser.testutil.TypicalQAndA;
+
+public class JsonSerializableMedmoriserTest {
+
+ private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data",
+ "JsonSerializableMedmoriserTest");
+ private static final Path TYPICAL_QANDAS_FILE = TEST_DATA_FOLDER
+ .resolve("typicalQAndAsMedmoriser.json");
+ private static final Path INVALID_QANDA_FILE = TEST_DATA_FOLDER
+ .resolve("invalidQAndAMedmoriser.json");
+ private static final Path DUPLICATE_QANDA_FILE = TEST_DATA_FOLDER
+ .resolve("duplicateQAndAMedmoriser.json");
+
+ @Test
+ public void toModelType_typicalQAndAsFile_success() throws Exception {
+ JsonSerializableMedmoriser dataFromFile = JsonUtil.readJsonFile(TYPICAL_QANDAS_FILE,
+ JsonSerializableMedmoriser.class).get();
+ Medmoriser medmoriserFromFile = dataFromFile.toModelType();
+ Medmoriser typicalQAndAsMedmoriser = TypicalQAndA.getTypicalMedmoriser();
+ assertEquals(medmoriserFromFile, typicalQAndAsMedmoriser);
+ }
+
+ @Test
+ public void toModelType_invalidQAndAFile_throwsIllegalValueException() throws Exception {
+ JsonSerializableMedmoriser dataFromFile = JsonUtil.readJsonFile(INVALID_QANDA_FILE,
+ JsonSerializableMedmoriser.class).get();
+ assertThrows(IllegalValueException.class, dataFromFile::toModelType);
+ }
+
+ @Test
+ public void toModelType_duplicateQAndAs_throwsIllegalValueException() throws Exception {
+ JsonSerializableMedmoriser dataFromFile = JsonUtil.readJsonFile(DUPLICATE_QANDA_FILE,
+ JsonSerializableMedmoriser.class).get();
+ assertThrows(IllegalValueException.class, JsonSerializableMedmoriser.MESSAGE_DUPLICATE_QANDA,
+ dataFromFile::toModelType);
+ }
+
+}
diff --git a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java b/src/test/java/seedu/medmoriser/storage/JsonUserPrefsStorageTest.java
similarity index 92%
rename from src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java
rename to src/test/java/seedu/medmoriser/storage/JsonUserPrefsStorageTest.java
index 16f33f4a6bb..f766562708a 100644
--- a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java
+++ b/src/test/java/seedu/medmoriser/storage/JsonUserPrefsStorageTest.java
@@ -1,8 +1,8 @@
-package seedu.address.storage;
+package seedu.medmoriser.storage;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
import java.io.IOException;
import java.nio.file.Path;
@@ -12,9 +12,9 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.commons.exceptions.DataConversionException;
-import seedu.address.model.UserPrefs;
+import seedu.medmoriser.commons.core.GuiSettings;
+import seedu.medmoriser.commons.exceptions.DataConversionException;
+import seedu.medmoriser.model.UserPrefs;
public class JsonUserPrefsStorageTest {
@@ -73,7 +73,7 @@ public void readUserPrefs_extraValuesInFile_extraValuesIgnored() throws DataConv
private UserPrefs getTypicalUserPrefs() {
UserPrefs userPrefs = new UserPrefs();
userPrefs.setGuiSettings(new GuiSettings(1000, 500, 300, 100));
- userPrefs.setAddressBookFilePath(Paths.get("addressbook.json"));
+ userPrefs.setMedmoriserFilePath(Paths.get("data/medmoriser.json"));
return userPrefs;
}
diff --git a/src/test/java/seedu/address/storage/StorageManagerTest.java b/src/test/java/seedu/medmoriser/storage/StorageManagerTest.java
similarity index 67%
rename from src/test/java/seedu/address/storage/StorageManagerTest.java
rename to src/test/java/seedu/medmoriser/storage/StorageManagerTest.java
index 99a16548970..619a03dda88 100644
--- a/src/test/java/seedu/address/storage/StorageManagerTest.java
+++ b/src/test/java/seedu/medmoriser/storage/StorageManagerTest.java
@@ -1,8 +1,8 @@
-package seedu.address.storage;
+package seedu.medmoriser.storage;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
+import static seedu.medmoriser.testutil.TypicalQAndA.getTypicalMedmoriser;
import java.nio.file.Path;
@@ -10,10 +10,10 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
-import seedu.address.commons.core.GuiSettings;
-import seedu.address.model.AddressBook;
-import seedu.address.model.ReadOnlyAddressBook;
-import seedu.address.model.UserPrefs;
+import seedu.medmoriser.commons.core.GuiSettings;
+import seedu.medmoriser.model.Medmoriser;
+import seedu.medmoriser.model.ReadOnlyMedmoriser;
+import seedu.medmoriser.model.UserPrefs;
public class StorageManagerTest {
@@ -24,7 +24,7 @@ public class StorageManagerTest {
@BeforeEach
public void setUp() {
- JsonAddressBookStorage addressBookStorage = new JsonAddressBookStorage(getTempFilePath("ab"));
+ JsonMedmoriserStorage addressBookStorage = new JsonMedmoriserStorage(getTempFilePath("ab"));
JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(getTempFilePath("prefs"));
storageManager = new StorageManager(addressBookStorage, userPrefsStorage);
}
@@ -48,21 +48,21 @@ public void prefsReadSave() throws Exception {
}
@Test
- public void addressBookReadSave() throws Exception {
+ public void medmoriserReadSave() throws Exception {
/*
* Note: This is an integration test that verifies the StorageManager is properly wired to the
* {@link JsonAddressBookStorage} class.
* More extensive testing of UserPref saving/reading is done in {@link JsonAddressBookStorageTest} class.
*/
- AddressBook original = getTypicalAddressBook();
- storageManager.saveAddressBook(original);
- ReadOnlyAddressBook retrieved = storageManager.readAddressBook().get();
- assertEquals(original, new AddressBook(retrieved));
+ Medmoriser original = getTypicalMedmoriser();
+ storageManager.saveMedmoriser(original);
+ ReadOnlyMedmoriser retrieved = storageManager.readMedmoriser().get();
+ assertEquals(original, new Medmoriser(retrieved));
}
@Test
- public void getAddressBookFilePath() {
- assertNotNull(storageManager.getAddressBookFilePath());
+ public void getMedmoriserFilePath() {
+ assertNotNull(storageManager.getMedmoriserFilePath());
}
}
diff --git a/src/test/java/seedu/address/testutil/Assert.java b/src/test/java/seedu/medmoriser/testutil/Assert.java
similarity index 97%
rename from src/test/java/seedu/address/testutil/Assert.java
rename to src/test/java/seedu/medmoriser/testutil/Assert.java
index 9863093bd6e..90d96bf862f 100644
--- a/src/test/java/seedu/address/testutil/Assert.java
+++ b/src/test/java/seedu/medmoriser/testutil/Assert.java
@@ -1,4 +1,4 @@
-package seedu.address.testutil;
+package seedu.medmoriser.testutil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.function.Executable;
diff --git a/src/test/java/seedu/medmoriser/testutil/EditQAndADescriptorBuilder.java b/src/test/java/seedu/medmoriser/testutil/EditQAndADescriptorBuilder.java
new file mode 100644
index 00000000000..6ae2a8161be
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/testutil/EditQAndADescriptorBuilder.java
@@ -0,0 +1,68 @@
+package seedu.medmoriser.testutil;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import seedu.medmoriser.logic.commands.EditCommand;
+import seedu.medmoriser.logic.commands.EditCommand.EditQAndADescriptor;
+import seedu.medmoriser.model.qanda.Answer;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.qanda.Question;
+import seedu.medmoriser.model.tag.Tag;
+
+/**
+ * A utility class to help with building EditQAndADescriptor objects.
+ */
+public class EditQAndADescriptorBuilder {
+
+ private EditQAndADescriptor descriptor;
+
+ public EditQAndADescriptorBuilder() {
+ descriptor = new EditQAndADescriptor();
+ }
+
+ public EditQAndADescriptorBuilder(EditCommand.EditQAndADescriptor descriptor) {
+ this.descriptor = new EditQAndADescriptor(descriptor);
+ }
+
+ /**
+ * Returns an {@code EditQAndADescriptor} with fields containing {@code qAndA}'s details
+ */
+ public EditQAndADescriptorBuilder(QAndA qAndA) {
+ descriptor = new EditCommand.EditQAndADescriptor();
+ descriptor.setQuestion(qAndA.getQuestion());
+ descriptor.setAnswer(qAndA.getAnswer());
+ descriptor.setTags(qAndA.getTags());
+ }
+
+ /**
+ * Sets the {@code Name} of the {@code EditQAndADescriptor} that we are building.
+ */
+ public EditQAndADescriptorBuilder withQuestion(String question) {
+ descriptor.setQuestion(new Question(question));
+ return this;
+ }
+
+ /**
+ * Sets the {@code answer} of the {@code EditQAndADescriptor} that we are building.
+ */
+ public EditQAndADescriptorBuilder withAnswer(String answer) {
+ descriptor.setAnswer(new Answer(answer));
+ return this;
+ }
+
+ /**
+ * Parses the {@code tags} into a {@code Set} and set it to the {@code EditQAndADescriptor}
+ * that we are building.
+ */
+ public EditQAndADescriptorBuilder withTags(String... tags) {
+ Set tagSet = Stream.of(tags).map(Tag::new).collect(Collectors.toSet());
+ descriptor.setTags(tagSet);
+ return this;
+ }
+
+ public EditQAndADescriptor build() {
+ return descriptor;
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/testutil/MedmoriserBuilder.java b/src/test/java/seedu/medmoriser/testutil/MedmoriserBuilder.java
new file mode 100644
index 00000000000..0193c3fddd8
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/testutil/MedmoriserBuilder.java
@@ -0,0 +1,34 @@
+package seedu.medmoriser.testutil;
+
+import seedu.medmoriser.model.Medmoriser;
+import seedu.medmoriser.model.qanda.QAndA;
+
+/**
+ * A utility class to help with building Medmoriser objects.
+ * Example usage:
+ * {@code Medmoriser md = new MedmoriserBuilder().withQAndA("John", "Doe").build();}
+ */
+public class MedmoriserBuilder {
+
+ private Medmoriser medmoriser;
+
+ public MedmoriserBuilder() {
+ medmoriser = new Medmoriser();
+ }
+
+ public MedmoriserBuilder(Medmoriser medmoriser) {
+ this.medmoriser = medmoriser;
+ }
+
+ /**
+ * Adds a new {@code QAndA} to the {@code Medmoriser} that we are building.
+ */
+ public MedmoriserBuilder withQAndA(QAndA qAndA) {
+ medmoriser.addQAndA(qAndA);
+ return this;
+ }
+
+ public Medmoriser build() {
+ return medmoriser;
+ }
+}
diff --git a/src/test/java/seedu/medmoriser/testutil/QAndABuilder.java b/src/test/java/seedu/medmoriser/testutil/QAndABuilder.java
new file mode 100644
index 00000000000..76dae74c847
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/testutil/QAndABuilder.java
@@ -0,0 +1,70 @@
+package seedu.medmoriser.testutil;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import seedu.medmoriser.model.qanda.Answer;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.qanda.Question;
+import seedu.medmoriser.model.tag.Tag;
+import seedu.medmoriser.model.util.SampleDataUtil;
+
+/**
+ * A utility class to help with building QAndA objects.
+ */
+public class QAndABuilder {
+
+ public static final String DEFAULT_QUESTION = "This is a question";
+ public static final String DEFAULT_ANSWER = "This is the answer";
+
+ private Question question;
+ private Answer answer;
+ private Set tags;
+
+ /**
+ * Creates a {@code QAndABuilder} with the default details.
+ */
+ public QAndABuilder() {
+ question = new Question(DEFAULT_QUESTION);
+ answer = new Answer(DEFAULT_ANSWER);
+ tags = new HashSet<>();
+ }
+
+ /**
+ * Initializes the QAndABuilder with the data of {@code qAndAToCopy}.
+ */
+ public QAndABuilder(QAndA qAndAToCopy) {
+ question = qAndAToCopy.getQuestion();
+ answer = qAndAToCopy.getAnswer();
+ tags = new HashSet<>(qAndAToCopy.getTags());
+ }
+
+ /**
+ * Sets the {@code Name} of the {@code QAndA} that we are building.
+ */
+ public QAndABuilder withQuestion(String question) {
+ this.question = new Question(question);
+ return this;
+ }
+
+ /**
+ * Parses the {@code tags} into a {@code Set} and set it to the {@code QAndA} that we are building.
+ */
+ public QAndABuilder withTags(String ... tags) {
+ this.tags = SampleDataUtil.getTagSet(tags);
+ return this;
+ }
+
+ /**
+ * Sets the {@code Answer} of the {@code QAndA} that we are building.
+ */
+ public QAndABuilder withAnswer(String answer) {
+ this.answer = new Answer(answer);
+ return this;
+ }
+
+ public QAndA build() {
+ return new QAndA(question, answer, tags);
+ }
+
+}
diff --git a/src/test/java/seedu/medmoriser/testutil/QAndAUtil.java b/src/test/java/seedu/medmoriser/testutil/QAndAUtil.java
new file mode 100644
index 00000000000..1ae38b6a649
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/testutil/QAndAUtil.java
@@ -0,0 +1,57 @@
+package seedu.medmoriser.testutil;
+
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_ANSWER;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_QUESTION;
+import static seedu.medmoriser.logic.parser.CliSyntax.PREFIX_TAG;
+
+import java.util.Set;
+
+import seedu.medmoriser.logic.commands.AddCommand;
+import seedu.medmoriser.logic.commands.EditCommand;
+import seedu.medmoriser.model.qanda.QAndA;
+import seedu.medmoriser.model.tag.Tag;
+
+/**
+ * A utility class for QAndA.
+ */
+public class QAndAUtil {
+
+ /**
+ * Returns an add command string for adding the {@code qAndA}.
+ */
+ public static String getAddCommand(QAndA qAndA) {
+ return AddCommand.COMMAND_WORD + " " + getQAndADetails(qAndA);
+ }
+
+ /**
+ * Returns the part of command string for the given {@code qAndA}'s details.
+ */
+ public static String getQAndADetails(QAndA qAndA) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(PREFIX_QUESTION + qAndA.getQuestion().question + " ");
+
+ sb.append(PREFIX_ANSWER + qAndA.getAnswer().answer + " ");
+ qAndA.getTags().stream().forEach(
+ s -> sb.append(PREFIX_TAG + s.tagName + " ")
+ );
+ return sb.toString();
+ }
+
+ /**
+ * Returns the part of command string for the given {@code EditQAndADescriptor}'s details.
+ */
+ public static String getEditQAndADescriptorDetails(EditCommand.EditQAndADescriptor descriptor) {
+ StringBuilder sb = new StringBuilder();
+ descriptor.getQuestion().ifPresent(name -> sb.append(PREFIX_QUESTION).append(name.question).append(" "));
+ descriptor.getAnswer().ifPresent(address -> sb.append(PREFIX_ANSWER).append(address.answer).append(" "));
+ if (descriptor.getTags().isPresent()) {
+ Set tags = descriptor.getTags().get();
+ if (tags.isEmpty()) {
+ sb.append(PREFIX_TAG);
+ } else {
+ tags.forEach(s -> sb.append(PREFIX_TAG).append(s.tagName).append(" "));
+ }
+ }
+ return sb.toString();
+ }
+}
diff --git a/src/test/java/seedu/address/testutil/SerializableTestClass.java b/src/test/java/seedu/medmoriser/testutil/SerializableTestClass.java
similarity index 98%
rename from src/test/java/seedu/address/testutil/SerializableTestClass.java
rename to src/test/java/seedu/medmoriser/testutil/SerializableTestClass.java
index f5a66340489..5d528e326dc 100644
--- a/src/test/java/seedu/address/testutil/SerializableTestClass.java
+++ b/src/test/java/seedu/medmoriser/testutil/SerializableTestClass.java
@@ -1,4 +1,4 @@
-package seedu.address.testutil;
+package seedu.medmoriser.testutil;
import java.time.LocalDateTime;
import java.util.ArrayList;
diff --git a/src/test/java/seedu/address/testutil/TestUtil.java b/src/test/java/seedu/medmoriser/testutil/TestUtil.java
similarity index 58%
rename from src/test/java/seedu/address/testutil/TestUtil.java
rename to src/test/java/seedu/medmoriser/testutil/TestUtil.java
index 896d103eb0b..14196d88780 100644
--- a/src/test/java/seedu/address/testutil/TestUtil.java
+++ b/src/test/java/seedu/medmoriser/testutil/TestUtil.java
@@ -1,13 +1,13 @@
-package seedu.address.testutil;
+package seedu.medmoriser.testutil;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import seedu.address.commons.core.index.Index;
-import seedu.address.model.Model;
-import seedu.address.model.person.Person;
+import seedu.medmoriser.commons.core.index.Index;
+import seedu.medmoriser.model.Model;
+import seedu.medmoriser.model.qanda.QAndA;
/**
* A utility class for test cases.
@@ -33,23 +33,23 @@ public static Path getFilePathInSandboxFolder(String fileName) {
}
/**
- * Returns the middle index of the person in the {@code model}'s person list.
+ * Returns the middle index of the qAndA in the {@code model}'s qAndA list.
*/
public static Index getMidIndex(Model model) {
- return Index.fromOneBased(model.getFilteredPersonList().size() / 2);
+ return Index.fromOneBased(model.getFilteredQAndAList().size() / 2);
}
/**
- * Returns the last index of the person in the {@code model}'s person list.
+ * Returns the last index of the qAndA in the {@code model}'s qAndA list.
*/
public static Index getLastIndex(Model model) {
- return Index.fromOneBased(model.getFilteredPersonList().size());
+ return Index.fromOneBased(model.getFilteredQAndAList().size());
}
/**
- * Returns the person in the {@code model}'s person list at {@code index}.
+ * Returns the qAndA in the {@code model}'s qAndA list at {@code index}.
*/
- public static Person getPerson(Model model, Index index) {
- return model.getFilteredPersonList().get(index.getZeroBased());
+ public static QAndA getQAndA(Model model, Index index) {
+ return model.getFilteredQAndAList().get(index.getZeroBased());
}
}
diff --git a/src/test/java/seedu/medmoriser/testutil/TypicalIndexes.java b/src/test/java/seedu/medmoriser/testutil/TypicalIndexes.java
new file mode 100644
index 00000000000..4d9e6973625
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/testutil/TypicalIndexes.java
@@ -0,0 +1,12 @@
+package seedu.medmoriser.testutil;
+
+import seedu.medmoriser.commons.core.index.Index;
+
+/**
+ * A utility class containing a list of {@code Index} objects to be used in tests.
+ */
+public class TypicalIndexes {
+ public static final Index INDEX_FIRST_QANDA = Index.fromOneBased(1);
+ public static final Index INDEX_SECOND_QANDA = Index.fromOneBased(2);
+ public static final Index INDEX_THIRD_QANDA = Index.fromOneBased(3);
+}
diff --git a/src/test/java/seedu/medmoriser/testutil/TypicalQAndA.java b/src/test/java/seedu/medmoriser/testutil/TypicalQAndA.java
new file mode 100644
index 00000000000..0dbf23fd496
--- /dev/null
+++ b/src/test/java/seedu/medmoriser/testutil/TypicalQAndA.java
@@ -0,0 +1,73 @@
+package seedu.medmoriser.testutil;
+
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_ANSWER_A;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_ANSWER_B;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_QUESTION_A;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_QUESTION_B;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_TAG_TAG1;
+import static seedu.medmoriser.logic.commands.CommandTestUtil.VALID_TAG_TAG2;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import seedu.medmoriser.model.Medmoriser;
+import seedu.medmoriser.model.qanda.QAndA;
+
+/**
+ * A utility class containing a list of {@code QAndA} objects to be used in tests.
+ */
+public class TypicalQAndA {
+
+ public static final QAndA QUESTION1 = new QAndABuilder().withQuestion("Question One")
+ .withAnswer("Answer 1")
+ .withTags("DNA").build();
+ public static final QAndA QUESTION2 = new QAndABuilder().withQuestion("Question Two")
+ .withAnswer("Answer 2")
+ .withTags("ImmuneSystem").build();
+ public static final QAndA QUESTION3 = new QAndABuilder().withQuestion("Question Three")
+ .withAnswer("Answer 3").build();
+ public static final QAndA QUESTION4 = new QAndABuilder().withQuestion("Question Four")
+ .withAnswer("Answer 4").build();
+ public static final QAndA QUESTION5 = new QAndABuilder().withQuestion("Question Five")
+ .withAnswer("Answer 5").build();
+ public static final QAndA QUESTION6 = new QAndABuilder().withQuestion("Question Six")
+ .withAnswer("Answer 6")
+ .build();
+ public static final QAndA QUESTION7 = new QAndABuilder().withQuestion("Question Seven")
+ .withAnswer("Answer 7")
+ .build();
+
+ // Manually added
+ public static final QAndA QUESTION8 = new QAndABuilder().withQuestion("Question Eight")
+ .withAnswer("Answer 8").build();
+ public static final QAndA QUESTION9 = new QAndABuilder().withQuestion("Question Nine")
+ .withAnswer("Answer 9").build();
+
+ // Manually added - QuestionSet's details found in {@code CommandTestUtil}
+ public static final QAndA QUESTIONA = new QAndABuilder().withQuestion(VALID_QUESTION_A)
+ .withAnswer(VALID_ANSWER_A).withTags(VALID_TAG_TAG1).build();
+ public static final QAndA QUESTIONB = new QAndABuilder().withQuestion(VALID_QUESTION_B)
+ .withAnswer(VALID_ANSWER_B).withTags(VALID_TAG_TAG2, VALID_TAG_TAG1).build();
+
+ public static final String KEYWORD_MATCHING_MEIER = "Meier"; // A keyword that matches MEIER
+
+ private TypicalQAndA() {} // prevents instantiation
+
+ /**
+ * Returns a {@code Medmoriser} with all the typical qAndAs.
+ */
+ public static Medmoriser getTypicalMedmoriser() {
+ Medmoriser ab = new Medmoriser();
+ for (QAndA qAndA : getTypicalQAndAs()) {
+ ab.addQAndA(qAndA);
+ }
+ return ab;
+ }
+
+ public static List getTypicalQAndAs() {
+ return new ArrayList<>(Arrays.asList(QUESTION1, QUESTION2, QUESTION3, QUESTION4, QUESTION5, QUESTION6,
+ QUESTION7));
+
+ }
+}
diff --git a/src/test/java/seedu/address/ui/TestFxmlObject.java b/src/test/java/seedu/medmoriser/ui/TestFxmlObject.java
similarity index 96%
rename from src/test/java/seedu/address/ui/TestFxmlObject.java
rename to src/test/java/seedu/medmoriser/ui/TestFxmlObject.java
index 5ecd82656f2..658f96c1356 100644
--- a/src/test/java/seedu/address/ui/TestFxmlObject.java
+++ b/src/test/java/seedu/medmoriser/ui/TestFxmlObject.java
@@ -1,4 +1,4 @@
-package seedu.address.ui;
+package seedu.medmoriser.ui;
import javafx.beans.DefaultProperty;
diff --git a/src/test/java/seedu/address/ui/UiPartTest.java b/src/test/java/seedu/medmoriser/ui/UiPartTest.java
similarity index 97%
rename from src/test/java/seedu/address/ui/UiPartTest.java
rename to src/test/java/seedu/medmoriser/ui/UiPartTest.java
index 33d82d911b8..def331191cb 100644
--- a/src/test/java/seedu/address/ui/UiPartTest.java
+++ b/src/test/java/seedu/medmoriser/ui/UiPartTest.java
@@ -1,8 +1,8 @@
-package seedu.address.ui;
+package seedu.medmoriser.ui;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.medmoriser.testutil.Assert.assertThrows;
import java.net.URL;
import java.nio.file.Path;
@@ -11,7 +11,7 @@
import org.junit.jupiter.api.io.TempDir;
import javafx.fxml.FXML;
-import seedu.address.MainApp;
+import seedu.medmoriser.MainApp;
public class UiPartTest {
diff --git a/src/test/resources/view/UiPartTest/validFile.fxml b/src/test/resources/view/UiPartTest/validFile.fxml
index bab836af0db..10ed8da55f9 100644
--- a/src/test/resources/view/UiPartTest/validFile.fxml
+++ b/src/test/resources/view/UiPartTest/validFile.fxml
@@ -1,4 +1,4 @@
-
+
Hello World!
diff --git a/src/test/resources/view/UiPartTest/validFileWithFxRoot.fxml b/src/test/resources/view/UiPartTest/validFileWithFxRoot.fxml
index 151e09ce926..29b614ac5d0 100644
--- a/src/test/resources/view/UiPartTest/validFileWithFxRoot.fxml
+++ b/src/test/resources/view/UiPartTest/validFileWithFxRoot.fxml
@@ -1,6 +1,6 @@
-
+Hello World!