diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md
index cd002a05b59..2c3de86181b 100644
--- a/docs/DeveloperGuide.md
+++ b/docs/DeveloperGuide.md
@@ -51,7 +51,7 @@ The bulk of the app's work is done by the following four components:
**How the architecture components interact with each other**
-The *Sequence Diagram* below shows how the components interact with each other for the scenario where the user issues the command `delete 1`.
+The *Sequence Diagram* below shows how the components interact with each other for the scenario where the user issues the command `delete S1234567X`.
@@ -91,7 +91,7 @@ Here's a (partial) class diagram of the `Logic` component:
-The sequence diagram below illustrates the interactions within the `Logic` component, taking `execute("delete 1")` API call as an example.
+The sequence diagram below illustrates the interactions within the `Logic` component, taking `execute("delete S1234567X")` API call as an example.

@@ -100,7 +100,7 @@ The sequence diagram below illustrates the interactions within the `Logic` compo
How the `Logic` component works:
-1. When `Logic` is called upon to execute a command, it is passed to an `AddressBookParser` object which in turn creates a parser that matches the command (e.g., `DeleteCommandParser`) and uses it to parse the command.
+1. When `Logic` is called upon to execute a command, it is passed to an `ImmuniMateParser` object which in turn creates a parser that matches the command (e.g., `DeleteCommandParser`) and uses it to parse the command.
2. This results in a `Command` object (more precisely, an object of one of its subclasses e.g., `DeleteCommand`) which is executed by the `LogicManager`.
3. The command can communicate with the `Model` when it is executed (e.g. to delete a person).
Note that although this is shown as a single step in the diagram above (for simplicity), in the code it can take several interactions (between the command object and the `Model`) to achieve.
@@ -111,8 +111,8 @@ Here are the other classes in `Logic` (omitted from the class diagram above) tha
How the parsing works:
-* When called upon to parse a user command, the `AddressBookParser` class creates an `XYZCommandParser` (`XYZ` is a placeholder for the specific command name e.g., `AddCommandParser`) which uses the other classes shown above to parse the user command and create a `XYZCommand` object (e.g., `AddCommand`) which the `AddressBookParser` returns back as a `Command` object.
-* All `XYZCommandParser` classes (e.g., `AddCommandParser`, `DeleteCommandParser`, ...) inherit from the `Parser` interface so that they can be treated similarly where possible e.g, during testing.
+* When called upon to parse a user command, the `ImmuniMateParser` class creates an `XYZCommandParser` (`XYZ` is a placeholder for the specific command name e.g., `CreateCommandParser`) which uses the other classes shown above to parse the user command and create a `XYZCommand` object (e.g., `CreateCommand`) which the `ImmuniMateParser` returns back as a `Command` object.
+* All `XYZCommandParser` classes (e.g., `CreateCommandParser`, `DeleteCommandParser`, ...) inherit from the `Parser` interface so that they can be treated similarly where possible e.g, during testing.
### Model component
**API** : [`Model.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/model/Model.java)
@@ -150,7 +150,7 @@ Classes used by multiple components are in the `seedu.addressbook.commons` packa
This section describes some noteworthy details on how certain features are implemented.
### List all patients
-#### Proposed Implementation
+#### Implementation
The `list` feature allows users to view all patients in the system through the `list` command. This patient data is then displayed in the system for the user to have an overview of all patients.
The `list` command is facilitated by `ListCommand` which extends the `Command` classes, listing all instances in the `Model`.
@@ -159,21 +159,24 @@ The `list` command is facilitated by `ListCommand` which extends the `Command` c
* `Model#updateFilteredPersonList()` is called to make the UI display all patients in the system.
Step 1. `ListCommand#execute` is called by the `LogicManager`. The `ListCommand` calls `model.updateFilteredPersonList()` to update the filtered list of patients in the system.
+
Step 2. `Model#updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS)` is called to update the filtered list such that it shows all patients in the system.
+
Step 3. The `ListCommand` returns the appropriate `CommandResult` to indicate the success of the operation.
### Help
-#### Proposed Implementation
+#### Implementation
The `help` feature allows users to view the link to User Guide. This command is facilitated by `HelpCommand` which extends the `Command` classes.
* `HelpCommand#execute` is responsible for executing the command and listing the link to the User Guide.
Step 1. Parser interprets the user's input and creates a new `HelpCommand` instance.
+
Step 2. `HelpCommand#execute` is called by the `LogicManager`. The `HelpCommand` returns the appropriate `CommandResult`, which signals the UI to display the help window .
### Create new patient
-#### Proposed Implementation
+#### Implementation
The `create` feature allows users to create a patient by providing input through a command with specific arguments. This patient data is then stored within the system for future reference.
The `create` command is facilitated by `CreateCommand` and `CreateCommandParser`. They extend the `Command` and `Parser` classes respectively, storing a new instance of `Person` in the `UniquePersonList`.
@@ -197,13 +200,14 @@ Step 2. The `CreateCommand#execute` is called by the `LogicManager`. The `Create
Step 3. If there is no duplicate, the patient is added to the system by calling `model.addPerson(person)`.
Step 4: After the patient is added, the `CreateCommand` returns the appropriate `CommandResult` to indicate the success of the operation.
-The following sequence diagram shows how a create operation goes through the Logic component:
+
+The following sequence diagram shows how a create operation goes through the `Logic` component:

-Similarly, the following sequence diagram shows how a create operation goes through the Model component:
+Similarly, the following sequence diagram shows how a create operation goes through the `Model` component:

### Delete patient
-#### Proposed Implementation
+#### Implementation
The `delete` feature allows users to delete a patient by providing NRIC through a command. This patient data is then removed from the system.
The `delete` command is facilitated by `DeleteCommand` and `DeleteCommandParser`. They extend the `Command` and `Parser` classes respectively, removing an instance of `Person` from the `UniquePersonList`.
@@ -217,16 +221,18 @@ The `delete` command is facilitated by `DeleteCommand` and `DeleteCommandParser`
* `ModelManager#hasPerson(Person)` is called to check if the patient already exists in the system. It calls `ImmuniMate.hasPerson(Person)` which calls `UniquePersonList#contains(Person)` to check if the patient already exists in the internal list of patients.
Step 1. `DeleteCommandParser` interprets the user's input for NRIC, and creates a new `DeleteCommand` instance.
+
Step 2. The `DeleteCommand#execute` is called by the `LogicManager`. The `DeleteCommand` checks if the patient exists in the system by calling `model.hasPerson(person)`.
+
Step 3. If the patient exists, the patient is removed from the system by calling `model.deletePerson(person)`.
+
Step 4: After the patient is removed, the `DeleteCommand` returns the appropriate `CommandResult` to indicate the success of the operation.
-The following sequence diagram shows how a delete operation goes through the Logic component:
+The following sequence diagram shows how a delete operation goes through the `Logic` and `Model` component:

-How a delete operation goes through the Model component is very similar to that of the create operation, therefore the sequence diagram is omitted.
### Delete patient information
-#### Proposed Implementation
+#### Implementation
The `deleteinfo` command allows users to delete a patient's particular field of information by providing NRIC and the field to be deleted through a command.
This `deleteinfo` command is facilitated by `DeleteInfoCommand` and `DeleteInfoCommandParser`. They extend the `Command` and `Parser` classes respectively, removing a particular field of information from the `Person` object.
@@ -239,18 +245,23 @@ This `deleteinfo` command is facilitated by `DeleteInfoCommand` and `DeleteInfoC
* `ModelManager#hasPerson(Person)` is called to check if the patient already exists in the system. It calls `ImmuniMate.hasPerson(Person)` which calls `UniquePersonList#contains(Person)` to check if the patient already exists in the internal list of patients.
Step 1. `DeleteInfoCommandParser` interprets the user's input for NRIC and the fields to be deleted, and creates a new `DeleteInfoCommand` instance.
+
Step 2. The `DeleteInfoCommand#execute` is called by the `LogicManager`. The `DeleteInfoCommand` checks if the patient exists in the system by calling `model.hasPerson(person)`.
+
Step 3. If the patient exists, the `DeleteInfoCommand` calls `model.setField` (where the field is the specified field to delete) to get the list of patients in the system.
+
Step 4. `DeleteInfoCommand#execute` check which fields are to be deleted, and remove the field of information using `Person#setField(null)`. Where `Field` is the field to be deleted.
+
Step 5: After the field of information is removed, the `DeleteInfoCommand` returns the appropriate `CommandResult` to indicate the success of the operation.
-The following sequence diagram shows how a deleteinfo operation goes through the Logic component:
+The following sequence diagram shows how a `deleteinfo` operation goes through the `Logic` component:

-The sequence diagram for how the deleteinfo operation goes through the Model Component is as the following:
+
+The sequence diagram for how the `deleteinfo` operation goes through the `Model` Component is as the following:

### Read a patient's information
-#### Proposed Implementation
+#### Implementation
The `read` feature allows users to read a patient profile by providing NRIC through a command. This patient data is then displayed.
The `read` command is facilitated by `ReadCommand` and `ReadCommandParser`. They extend the `Command` and `Parser` classes respectively, displaying patient profile from an instance of `Person` from the `UniquePersonList`.
@@ -261,22 +272,44 @@ The `read` command is facilitated by `ReadCommand` and `ReadCommandParser`. They
* `Model#updateFilteredPersonList(Predicate)` and is called to update the list to be of patient with specified NRIC in the system.
* `Model#getFilteredPersonList()` is called to get the list of patient with specified NRIC in the system.
* `Observablelist#get(int)` is called to obtain `Person` object of patient with speicified NRIC.
+
Step 1. `ReadCommandParser` interprets the user's input for NRIC, and creates a new `ReadCommand` instance.
+
Step 2. The `ReadCommand#execute` is called by the `LogicManager`. The `ReadCommand` checks if the patient exists in the system by calling `model.hasPerson(person)`.
+
Step 3. If the patient exists, the patient is obtained from the system by calling `model.updateFilteredPersonList(person)`, followed by calling `model.getFilteredPersonList()` and `Observablelist#get(int)`.
+
Step 4: After the patient is obtained, the `ReadCommand` formats the patient profile by calling `Messages.format(person)` and returns the appropriate `CommandResult` to indicate the success of the operation.
-The following sequence diagram shows how a delete operation goes through the Logic component:
+The following sequence diagram shows how a `read` operation goes through the `Logic` component:

-How a read operation goes through the Model component is shown below:
-
+How a `read` operation goes through the `Model` component is shown below:
+
### Find patient
-#### Proposed Implementation
+#### Implementation
+
+The `find` feature lets users find patients with certain values in various fields, namely `name`, `address` and `condition`.
+After a command with specific arguments as input, the patient list is filtered and the resultant list is shown.
+
+The `find` command is facilitated by `FindCommand` and `FindCommandParser`, extending the `Command` and `Parser` classes respectively.
+* `FindCommandParser#parse` is responsible for parsing the user input and creating a new `FindCommand` instance.
+* `FindCommand#execute` is responsible for executing the command, calling `ModelManager#updateFilteredPersonList(Predicate)` to find patients with the given keywords in the given field.
+
+Step 1. `FindCommandParser` interprets the user's input, determine which field the user wishes to find patients by, and creates a new `FindCommand` instance.
+
+Step 2. The `FindCommand#execute` is called by the `LogicManager`.
+
+Step 3. This in turn calls `model.updateFilteredPersonList(Predicate)`, which identifies patients having any of the keywords in `Predicate` in the given field.
+
+Step 4: The `FindCommand` returns the appropriate `CommandResult` to indicate the success of the operation.
+
+The following sequence diagram shows how a `find` operation goes through the `Logic` and `Model` components:
+
### Update patient fields
-#### Proposed Implementation
+#### Implementation
Given below is an example usage scenario and how the update mechanism behaves at each step.
Step 1. The user launches the application for the first time.
@@ -293,20 +326,51 @@ Step 6. `model.getFilteredPersonsList()` retrieves the list of `Person`s stored,
Step 7. `model.setPerson()` then replaces the retrieved `Person` object with the new `Person` object with fields updated, taking in both `Person` objects as arguments. The `model` is then saved into `storage`.
-#### Design considerations:
-
-* **Alternative 1 (current choice):** Identify patient by `Nric`.
- * Pros: More user convenience, as user just needs to type NRIC patients provide
+The following sequence diagram shows how an `update` operation goes through the `Logic` components:
+
-* **Alternative 2:** Identify patient by given `Index`.
- * Pros: Easier to implement.
- * Cons: Less user convenience, as user has to first know patient `Index` to find patient.
+How an `update` operation goes through the `Model` component is shown below:
+
### Record patient visit
-#### Proposed Implementation
+#### Implementation
+The `addvisit` feature allows users to add a patient visit by providing input through a command with specific arguments. This visit is then stored within the system for future reference.
+The `addvisit` command is facilitated by `AddVisitCommand` and `AddVisitCommandParser`. They extend the `Command` and `Parser` classes respectively, storing a new instance of `Visit` in the `UniqueVisitList`.
+* `AddVisitCommandParser#parse` is responsible for parsing the user input and creating a new `AddVisitCommand` instance.
+* `AddVisitCommand#execute` is responsible for executing the command and adding the new visit to the system.
+* `ImmuniMate#addVisit(Visit)` is called to add the visit to the internal list of visits.
+* `UniquePersonList#add(Visit)` is used to add the new visit to the system.
+ `ModelManager#addVisit(Visit)` is called to add the visit to the system. It calls `ImmuniMate.addVisit(Visit)` which calls `UniqueVisitList#add(Visit)` to add the visit to the internal list of visits.
+ The command checks if the patient exists in the system before adding the new visit of a patient.
+* `Person#equals(Object)` is overridden to check if two patients are the same person.
+* `UniquePersonList#contains(Person)` is used to check if the patient exists in the system's list of patients.
+* `ImmuniMate#hasPerson(Person)` is used to check if the patient exists in the system.
+ `ModelManager#hasPerson(Person)` is called to check if the patient exists in the system. It calls `ImmuniMate.hasPerson(Person)` which calls `UniquePersonList#contains(Person)` to check if the patient exists in the internal list of patients.
+ The command checks for duplicates in the system before adding the new visit.
+* `Visit#equals(Object)` is overridden to check if two visits are duplicates.
+* `UniquePersonList#contains(Visit)` is used to check if the visit already exists in the system's list of visits.
+* `ImmuniMate#hasVisit(Visit)` is used to check if the visit already exists in the system.
+ `ModelManager#hasVisit(Visit)` is called to check if the visit already exists in the system. It calls `ImmuniMate.hasVisit(Visit)` which calls `UniqueVisitList#contains(Visit)` to check if the visit already exists in the internal list of visits.
+
+The creation of `Visit` instance also rely on field classes`NRIC`, `Symptoms`,`Diagnosis`, `Status` and `DateOfVisit`.
+
+Step 1. `AddVisitCommandParser` interprets the user's input, creates instances of fields which matches the input, and creates a new `AddVisitCommand` instance.
+
+Step 2. The `AddVisitCommand#execute` is called by the `LogicManager`. The `AddVisitCommand` checks if the patient already exists in the system by calling `model.hasPerson(person)`.
+
+Step 3. If the patient exists, the `AddVisitCommand` checks if the visit already exists in the system by calling `model.hasVisit(visit)`.
+
+Step 4. If the visit does not exist, the visit is added to the system by calling `model.addVisit(visit)`.
+
+Step 4: After the visit is added, the `AddVisitCommand` returns the appropriate `CommandResult` to indicate the success of the operation.
+
+The following sequence diagram shows how a addvisit operation goes through the `Logic` component:
+
+Similarly, the following sequence diagram shows how a addvisit operation goes through the `Model` component:
+
### Check a patient's visit history
-#### Proposed Implementation
+#### Implementation
The `check` feature allows users to check the visit history of a patient by providing NRIC through a command. This patient visit history is then displayed.
The `check` command is facilitated by `CheckCommand` and `CheckCommandParser`. They extend the `Command` and `Parser` classes respectively, displaying patient visit history from list of `Visit` from the `UniqueVisitList`.
@@ -316,25 +380,49 @@ The `check` command is facilitated by `CheckCommand` and `CheckCommandParser`. T
* `ModelManager#hasPerson(Person)` is called to check if the patient exists in the system. It calls `ImmuniMate.hasPerson(Person)` which calls `UniquePersonList#contains(Person)` to check if the patient already exists in the internal list of patients.
* `Model#updateFilteredPersonList(Predicate)` is called to get the list of patient with specified NRIC in the system.
* `Model#updateFilteredVisitList(Predicate)` is called to get the list of visits with specified NRIC in the system.
- Step 1. `CheckCommandParser` interprets the user's input for NRIC, and creates a new `CheckCommand` instance.
- Step 2. The `CheckCommand#execute` is called by the `LogicManager`. The `CheckCommand` checks if the patient exists in the system by calling `model.hasPerson(person)`.
- Step 3. If the patient exists, the patient is obtained from the system by calling `model.updateFilteredPersonList(pred)`, followed by calling `model.getFilteredPersonList()` and `Observablelist#get(int)`.
- Step 4: Patient visit history is obtained from the system by calling `model.updateFilteredVisitList(pred)`, followed by `model.getFilteredVisitList()`.
- Step 5: After the patient visit history is obtained, the `CheckCommand` formats the patient visit history by calling `Messages.formatCheck(visit)` and returns the appropriate `CommandResult` to indicate the success of the operation.
+
+Step 1. `CheckCommandParser` interprets the user's input for NRIC, and creates a new `CheckCommand` instance.
+
+Step 2. The `CheckCommand#execute` is called by the `LogicManager`. The `CheckCommand` checks if the patient exists in the system by calling `model.hasPerson(person)`.
-The following sequence diagram shows how a delete operation goes through the Logic component:
+Step 3. If the patient exists, the patient is obtained from the system by calling `model.updateFilteredPersonList(pred)`, followed by calling `model.getFilteredPersonList()` and `Observablelist#get(int)`.
+
+Step 4: Patient visit history is obtained from the system by calling `model.updateFilteredVisitList(pred)`, followed by `model.getFilteredVisitList()`.
+
+Step 5: After the patient visit history is obtained, the `CheckCommand` formats the patient visit history by calling `Messages.formatCheck(visit)` and returns the appropriate `CommandResult` to indicate the success of the operation.
+
+The following sequence diagram shows how a delete operation goes through the `Logic` component:

-How a check operation goes through the Model component is shown below:
+How a check operation goes through the `Model` component is shown below:

-### Check for clusters
-#### Proposed Implementation
+### Cluster Identification
+#### Implementation
+
+The `cluster` feature tells users if a certain location has a certain number of patients unwell with an illness.
+Provided an integer, location and disease as inputs, it finds unwell patients having an address with the given location as a substring, and diagnosis with the given illness as a substring, and informs the user if the number of those patients is at least that integer.
+The `cluster` command is facilitated by `ClusterCommand` and `ClusterCommandParser`, extending the `Command` and `Parser` classes respectively, storing a new instance of `Person` in the `UniquePersonList`.
+
+* `ClusterCommandParser#parse` is responsible for parsing the user input and creating a new `ClusterCommand` instance.
+* `ClusterCommand#execute` is responsible for executing the command and separating the inputs into their categories (cluster size, address and illness). It calls `ModelManager#updateFilteredPersonList(Predicate)` to find patients which satisfy the given criteria.
+
+Step 1. `ClusterCommandParser` interprets the user's input, and separates it into its constituent categories, and creates a new `ClusterCommand` instance.
+
+Step 2. The `ClusterCommand#execute` is called by the `LogicManager`.
+
+Step 3. This in turn calls `model.updateFilteredPersonList(Predicate)`, takes the location and illness keywords in `Predicate`, and finds all the patients which have them as substrings in their addresses and diagnoses respectively.
+
+Step 4. This also calls `model.getFilteredPersonList().size()` to obtain the size of the patient group satisfying the given criteria.
+
+Step 5: The `ClusterCommand` returns the appropriate `CommandResult` to indicate the success of the operation.
+
+The following sequence diagram shows how a `cluster` operation goes through the `Logic` and `Model` components:
+
### Exit the app
-#### Proposed Implementation
+#### Implementation
-#### Design considerations:
--------------------------------------------------------------------------------------------------------------------
@@ -370,8 +458,8 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli
| 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 |
-| `* * *` | Healthcare Worker | create a new patient record | |
-| `* * *` | Healthcare Worker | delete a patient | remove wrong or obselete patient record from the database |
+| `* * *` | Healthcare Worker | create a new patient profile | |
+| `* * *` | Healthcare Worker | delete a patient | remove wrong or obselete patient profile from the database |
| `* * *` | Healthcare Worker | delete patient's information | remove patient information that is known to be incorrect |
| `* * *` | Healthcare Worker | read a patient's information by NRIC | locate details of persons without having to go through the entire list |
| `* * *` | Healthcare Worker | update a person's details | keep the details up to date |
@@ -390,20 +478,20 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli
| `*` | Healthcare Worker | see the close contacts of a patient | see the links between infected patients |
### 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 `ImmuniMate` and the **Actor** is the `user`, unless specified otherwise)
-**Use Case: UC01 - Create Patient Record**
+**Use Case: UC01 - Create patient profile**
- **Actor:** Healthcare Worker
-- **Description:** Healthcare worker creates a new patient record in the ImmuniMate Address Book System.
+- **Description:** Healthcare worker creates a new patient profile in the ImmuniMate Address Book System.
- **Preconditions:** Healthcare worker has logged into the system.
-- **Guarantees:** New patient record is successfully created in the ImmuniMate Address Book System.
+- **Guarantees:** New patient profile is successfully created in the ImmuniMate Address Book System.
- **MSS:**
- 1. Healthcare worker choose to create a new patient record.
- 2. IABS requests the necessary details for the new patient record (name, NRIC, date of birth, sex, phone number, address, email, country of nationality, date of admission, blood type, allergies).
+ 1. Healthcare worker choose to create a new patient profile.
+ 2. IABS requests the necessary details for the new patient profile (name, NRIC, date of birth, sex, phone number, address, email, country of nationality, date of admission, blood type, allergies).
3. Healthcare worker enters the patient's details.
4. IABS validates the entered data.
- 5. IABS adds the new patient record to the database.
+ 5. IABS adds the new patient profile to the database.
- **Extensions:**
3a. IABS detects a conflict in the entered data (user existing).
@@ -421,7 +509,7 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli
Steps 3b1-3b2 are repeated until the data entered are correct.
Use case resumes from step 4.
- *a. At any time, Healthcare Worker chooses to cancel creating the patient record.
+ *a. At any time, Healthcare Worker chooses to cancel creating the patient profile.
*a1. IABS requests confirmation to cancel.
*a2. Healthcare Worker confirms the cancellation.
@@ -470,7 +558,7 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli
---
-**Use Case: UC04 - Delete Patient Record**
+**Use Case: UC04 - Delete patient profile**
- **Actor:** Healthcare worker
- **Description:** Healthcare worker deletes a patient's record from the ImmuniMate Address Book System.
@@ -579,7 +667,7 @@ Quality requirements:
17. **Cluster**: A group of patients who are infected by the same disease.
18. **Patient Visit**: A record of a patient's one specific visit to the clinic, including the date of visit, symptoms, diagnosis, and status.
19. **Patient History**: A collection of all the visits by a patient.
-20. **Patient Record**: A collection of all the information about a patient, including the patient's name, NRIC, phone number, address, email, country.
+20. **patient profile**: A collection of all the information about a patient, including the patient's name, `Nric`, `Phone`, `Address`, `Email`, `Country`.
--------------------------------------------------------------------------------------------------------------------
@@ -704,6 +792,7 @@ testers are expected to do more *exploratory* testing.
1. The person with NRIC `S1234567A` exists in the system.
1. Test case: `deleteinfo S1234567A n/`
Expected: The person's name is not deleted. The result panel shows an error message, indicating that the name field cannot be deleted.
+
### Saving data
1. Dealing with missing/corrupted data files
@@ -714,5 +803,9 @@ testers are expected to do more *exploratory* testing.
## Planned enhancements
**Include FIN as accepted values for field `NRIC`**: The field `NRIC` should accept `F`, `M` and `G` as valid values, as they are valid first characters for foreigners' FIN (foreign identification number).
-**Make `email` case-insensitive**: The field `Email` should be case-insensitive, as emails are not case-sensitive in practice.
-**Limit `country` to a list of valid countries**: The field `country` should be limited to a list of countries, to prevent invalid entries.
+
+**Allow `Name` to take special characters**: The field `Name` should be able to accommodate names with special characters such as dashes, slashes, apostrophes etc.
+
+**Limit `Country` to a list of valid countries**: The field `Country` should be limited to a list of countries, to prevent invalid entries.
+
+**Make `Email` case-insensitive**: The field `Email` should be case-insensitive, as emails are not case-sensitive in practice.
diff --git a/docs/diagrams/AddVisitCommandLogic.puml b/docs/diagrams/AddVisitCommandLogic.puml
new file mode 100644
index 00000000000..9af3f3bf383
--- /dev/null
+++ b/docs/diagrams/AddVisitCommandLogic.puml
@@ -0,0 +1,80 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":ImmuniMateParser" as ImmuniMateParser LOGIC_COLOR
+participant ":AddVisitCommandParser" as AddVisitCommandParser LOGIC_COLOR
+participant "c:AddVisitCommand" as AddVisitCommand LOGIC_COLOR
+participant "r:CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant "m:Model" as Model MODEL_COLOR
+participant "v:Visit" as Visit MODEL_COLOR
+end box
+
+[-> LogicManager : execute("addvisit ...")
+activate LogicManager
+LogicManager -> ImmuniMateParser : parseCommand("addvisit ...")
+activate ImmuniMateParser
+
+create AddVisitCommandParser
+ImmuniMateParser -> AddVisitCommandParser
+activate AddVisitCommandParser
+AddVisitCommandParser --> ImmuniMateParser
+deactivate AddVisitCommandParser
+ImmuniMateParser -> AddVisitCommandParser : parse("...")
+activate AddVisitCommandParser
+
+create Visit
+AddVisitCommandParser -> Visit
+activate Visit
+Visit --> AddVisitCommandParser
+deactivate Visit
+
+create AddVisitCommand
+AddVisitCommandParser -> AddVisitCommand
+activate AddVisitCommand
+AddVisitCommand --> AddVisitCommandParser
+deactivate AddVisitCommand
+
+AddVisitCommandParser --> ImmuniMateParser : c
+deactivate AddVisitCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+AddVisitCommandParser -[hidden]-> ImmuniMateParser
+destroy AddVisitCommandParser
+ImmuniMateParser --> LogicManager : c
+deactivate ImmuniMateParser
+
+LogicManager -> AddVisitCommand : execute()
+activate AddVisitCommand
+AddVisitCommand -> Visit : getNric()
+activate Visit
+Visit --> AddVisitCommand : nric
+deactivate Visit
+AddVisitCommand -> Model : hasPerson(...)
+activate Model
+Model --> AddVisitCommand : false
+deactivate Model
+AddVisitCommand -> Model : hasVisit(...)
+activate Model
+Model --> AddVisitCommand : false
+deactivate Model
+AddVisitCommand -> Model : addVisit(v)
+activate Model
+Model --> AddVisitCommand : add visit in the model
+deactivate Model
+
+create CommandResult
+AddVisitCommand -> CommandResult
+activate CommandResult
+CommandResult --> AddVisitCommand
+deactivate
+AddVisitCommand --> LogicManager : r
+deactivate AddVisitCommand
+
+[<--LogicManager : r
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/AddVisitCommandModel.puml b/docs/diagrams/AddVisitCommandModel.puml
new file mode 100644
index 00000000000..07fbb2948d4
--- /dev/null
+++ b/docs/diagrams/AddVisitCommandModel.puml
@@ -0,0 +1,119 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+box Logic LOGIC_COLOR_T1
+participant "l:Logic" as Logic LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":ModelManager" as ModelManager MODEL_COLOR
+participant ":ImmuniMate" as ImmuniMate MODEL_COLOR
+participant ":UniqueVisitList" as UniqueVisitList MODEL_COLOR
+participant "internalList: ObservableList" as internalList MODEL_COLOR
+participant "p:Person" as p MODEL_COLOR
+participant "v:Visit" as Visit MODEL_COLOR
+end box
+
+[-> Logic : execute()
+activate Logic
+
+create p
+Logic -> p
+activate p
+p --> Logic
+deactivate p
+
+create Visit
+Logic -> Visit
+activate Visit
+Visit --> Logic
+deactivate Visit
+
+Logic -> ModelManager : hasPerson(p)
+activate ModelManager
+
+ModelManager -> ImmuniMate: hasPerson(p)
+activate ImmuniMate
+
+ImmuniMate -> UniqueVisitList : contains(p)
+activate UniqueVisitList
+
+UniqueVisitList -> internalList : stream().anyMatch(p::isSamePerson)
+activate internalList
+
+internalList -> p : isSamePerson()
+activate p
+
+p --> internalList
+deactivate p
+
+internalList --> UniqueVisitList
+deactivate internalList
+
+UniqueVisitList --> ImmuniMate
+deactivate UniqueVisitList
+
+ImmuniMate --> ModelManager
+deactivate ImmuniMate
+
+ModelManager --> Logic
+deactivate ModelManager
+
+Logic -> ModelManager : hasVisit(v)
+activate ModelManager
+
+ModelManager -> ImmuniMate: hasVisit(v)
+activate ImmuniMate
+
+ImmuniMate -> UniqueVisitList : contains(v)
+activate UniqueVisitList
+
+UniqueVisitList -> internalList : stream().anyMatch(v::isSameVisit)
+activate internalList
+
+internalList -> Visit : isSameVisit()
+activate Visit
+
+Visit --> internalList
+deactivate Visit
+
+internalList --> UniqueVisitList
+deactivate internalList
+
+UniqueVisitList --> ImmuniMate
+deactivate UniqueVisitList
+
+ImmuniMate --> ModelManager
+deactivate ImmuniMate
+
+ModelManager --> Logic
+deactivate ModelManager
+
+Logic -> ModelManager : addVisit(v)
+activate ModelManager
+
+ModelManager -> ImmuniMate: addVisit(v)
+activate ImmuniMate
+
+ImmuniMate -> UniqueVisitList : add(v)
+activate UniqueVisitList
+
+UniqueVisitList -> internalList : add(v)
+activate internalList
+
+internalList --> UniqueVisitList
+deactivate internalList
+
+UniqueVisitList --> ImmuniMate
+deactivate UniqueVisitList
+
+ImmuniMate --> ModelManager
+deactivate ImmuniMate
+
+ModelManager --> Logic
+deactivate ModelManager
+
+[<--Logic
+deactivate Logic
+
+@enduml
diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml
index 7a969d0da86..a1a42a2832f 100644
--- a/docs/diagrams/ArchitectureSequenceDiagram.puml
+++ b/docs/diagrams/ArchitectureSequenceDiagram.puml
@@ -11,7 +11,7 @@ Participant ":Storage" as storage STORAGE_COLOR
user -[USER_COLOR]> ui : "delete S1234567X"
activate ui UI_COLOR
-ui -[UI_COLOR]> logic : execute("delete X1234567X")
+ui -[UI_COLOR]> logic : execute("delete S1234567X")
activate logic LOGIC_COLOR
logic -[LOGIC_COLOR]> model : deletePerson(p)
diff --git a/docs/diagrams/ClusterLogicModelDiagram.puml b/docs/diagrams/ClusterLogicModelDiagram.puml
new file mode 100644
index 00000000000..9f20bfbcf13
--- /dev/null
+++ b/docs/diagrams/ClusterLogicModelDiagram.puml
@@ -0,0 +1,63 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":ImmuniMateParser" as ImmuniMateParser LOGIC_COLOR
+participant ":ClusterCommandParser" as ClusterCommandParser LOGIC_COLOR
+participant "c:ClusterCommand" as ClusterCommand LOGIC_COLOR
+participant "r:CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant "m:Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("cluster 50 ...")
+activate LogicManager
+LogicManager -> ImmuniMateParser : parseCommand("cluster 50 ...")
+activate ImmuniMateParser
+
+create ClusterCommandParser
+ImmuniMateParser -> ClusterCommandParser
+activate ClusterCommandParser
+ClusterCommandParser --> ImmuniMateParser
+deactivate ClusterCommandParser
+ImmuniMateParser -> ClusterCommandParser : parse("50 ...")
+activate ClusterCommandParser
+
+create ClusterCommand
+ClusterCommandParser -> ClusterCommand
+activate ClusterCommand
+ClusterCommand --> ClusterCommandParser
+deactivate ClusterCommand
+ClusterCommandParser --> ImmuniMateParser : c
+deactivate ClusterCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+ClusterCommandParser -[hidden]-> ImmuniMateParser
+destroy ClusterCommandParser
+ImmuniMateParser --> LogicManager : c
+deactivate ImmuniMateParser
+LogicManager -> ClusterCommand : execute(m)
+activate ClusterCommand
+ClusterCommand -> Model : updateFilteredPersonList(...)
+activate Model
+Model --> ClusterCommand
+deactivate Model
+ClusterCommand -> Model : getFilteredPersonList(...)
+activate Model
+Model --> ClusterCommand
+deactivate Model
+
+create CommandResult
+ClusterCommand -> CommandResult
+activate CommandResult
+CommandResult --> ClusterCommand
+deactivate
+ClusterCommand --> LogicManager : r
+deactivate ClusterCommand
+
+[<--LogicManager : r
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/DeleteInfoModelDiagram.puml b/docs/diagrams/DeleteInfoModelDiagram.puml
index c165349ab2c..8e5b84ceff1 100644
--- a/docs/diagrams/DeleteInfoModelDiagram.puml
+++ b/docs/diagrams/DeleteInfoModelDiagram.puml
@@ -17,6 +17,12 @@ end box
[-> CreateCommand : execute()
activate CreateCommand
+CreateCommand -> ModelManager : getFilteredPersonsList()
+activate ModelManager
+
+ModelManager --> CreateCommand : persons
+deactivate ModelManager
+
CreateCommand -> ModelManager : hasPerson(...)
activate ModelManager
@@ -32,19 +38,19 @@ activate internalList
internalList -> p1 : isSamePerson(p1)
activate p1
-p1 --> internalList
+p1 --> internalList : true
deactivate p1
-internalList --> UniquePersonList
+internalList --> UniquePersonList : true
deactivate internalList
-UniquePersonList --> ImmuniMate
+UniquePersonList --> ImmuniMate : true
deactivate UniquePersonList
-ImmuniMate --> ModelManager
+ImmuniMate --> ModelManager : true
deactivate ImmuniMate
-ModelManager --> CreateCommand
+ModelManager --> CreateCommand : true
deactivate ModelManager
CreateCommand -> ModelManager : getFilteredPersonList()
diff --git a/docs/diagrams/DeleteInfoSequenceDiagram.puml b/docs/diagrams/DeleteInfoSequenceDiagram.puml
index bac2584dcc4..d2dbd322ed0 100644
--- a/docs/diagrams/DeleteInfoSequenceDiagram.puml
+++ b/docs/diagrams/DeleteInfoSequenceDiagram.puml
@@ -50,9 +50,16 @@ deactivate ImmuniMateParser
LogicManager -> DeleteInfoCommand : execute(m)
activate DeleteInfoCommand
+DeleteInfoCommand -> Model : getFilteredPersonsList()
+activate Model
+
+Model --> DeleteInfoCommand : persons
+deactivate Model
+
DeleteInfoCommand -> Model : hasPerson(...)
activate Model
-Model --> DeleteInfoCommand : false
+
+Model --> DeleteInfoCommand : true
deactivate Model
DeleteInfoCommand -> Model : getFilteredPersonList().filtered().get(0)
diff --git a/docs/diagrams/FindLogicModelDiagram.puml b/docs/diagrams/FindLogicModelDiagram.puml
new file mode 100644
index 00000000000..b4a0b230803
--- /dev/null
+++ b/docs/diagrams/FindLogicModelDiagram.puml
@@ -0,0 +1,59 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":ImmuniMateParser" as ImmuniMateParser LOGIC_COLOR
+participant ":FindCommandParser" as FindCommandParser LOGIC_COLOR
+participant "f:FindCommand" as FindCommand LOGIC_COLOR
+participant "r:CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant "m:Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("find ...")
+activate LogicManager
+LogicManager -> ImmuniMateParser : parseCommand("find ...")
+activate ImmuniMateParser
+
+create FindCommandParser
+ImmuniMateParser -> FindCommandParser
+activate FindCommandParser
+FindCommandParser --> ImmuniMateParser
+deactivate FindCommandParser
+ImmuniMateParser -> FindCommandParser : parse("...")
+activate FindCommandParser
+
+create FindCommand
+FindCommandParser -> FindCommand
+activate FindCommand
+FindCommand --> FindCommandParser
+deactivate FindCommand
+FindCommandParser --> ImmuniMateParser : f
+deactivate FindCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+FindCommandParser -[hidden]-> ImmuniMateParser
+destroy FindCommandParser
+ImmuniMateParser --> LogicManager : f
+deactivate ImmuniMateParser
+LogicManager -> FindCommand : execute(m)
+activate FindCommand
+FindCommand -> Model : updateFilteredPersonList(...)
+activate Model
+Model --> FindCommand
+deactivate Model
+
+create CommandResult
+FindCommand -> CommandResult
+activate CommandResult
+CommandResult --> FindCommand
+deactivate
+FindCommand --> LogicManager : r
+deactivate FindCommand
+
+[<--LogicManager : r
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/ModelClassDiagram.puml b/docs/diagrams/ModelClassDiagram.puml
index 6a9bdac94b9..e65d736d024 100644
--- a/docs/diagrams/ModelClassDiagram.puml
+++ b/docs/diagrams/ModelClassDiagram.puml
@@ -5,14 +5,14 @@ skinparam arrowColor MODEL_COLOR
skinparam classBackgroundColor MODEL_COLOR
Package Model as ModelPackage <>{
-Class "<>\nReadOnlyAddressBook" as ReadOnlyAddressBook
+Class "<>\nReadOnlyImmuniMate" as ReadOnlyImmuniMate
Class "<>\nReadOnlyUserPrefs" as ReadOnlyUserPrefs
Class "<>\nModel" as Model
Class ImmuniMate
Class ModelManager
Class UserPrefs
-
Class UniquePersonList
+Class UniqueVisitList
Class Person
Class Address
Class Name
@@ -29,6 +29,8 @@ Class Condition
Class DateOfAdmission
Class Diagnosis
Class Symptom
+Class Visit
+Class DateOfVisit
Class I #FFFFFF
@@ -37,17 +39,19 @@ Class I #FFFFFF
Class HiddenOutside #FFFFFF
HiddenOutside ..> Model
-ImmuniMate .up.|> ReadOnlyAddressBook
+ImmuniMate .up.|> ReadOnlyImmuniMate
ModelManager .up.|> Model
Model .right.> ReadOnlyUserPrefs
-Model .left.> ReadOnlyAddressBook
+Model .left.> ReadOnlyImmuniMate
ModelManager -left-> "1" ImmuniMate
ModelManager -right-> "1" UserPrefs
UserPrefs .up.|> ReadOnlyUserPrefs
ImmuniMate *--> "1" UniquePersonList
+ImmuniMate *--> "1" UniqueVisitList
UniquePersonList --> "~* all" Person
+UniqueVisitList --> "~* all" Visit
Person *--> "1" Nric
Person *--> "1" Name
Person *--> "1" Phone
@@ -56,14 +60,20 @@ Person *--> "1" DateOfBirth
Person *--> "1" Sex
Person *--> "1" Status
-Person *--> "1" Email
-Person *--> "1" Country
-Person *--> "1" Allergies
-Person *--> "1" BloodType
-Person *--> "1" Condition
-Person *--> "1" DateOfAdmission
-Person *--> "1" Diagnosis
-Person *--> "1" Symptom
+Person *--> "0..1" Email
+Person *--> "0..1" Country
+Person *--> "0..1" Allergies
+Person *--> "0..1" BloodType
+Person *--> "0..1" Condition
+Person *--> "0..1" DateOfAdmission
+Person *--> "0..1" Diagnosis
+Person *--> "0..1" Symptom
+
+Visit *--> "1" DateOfVisit
+Visit *--> "1" Nric
+Visit *--> "1" Diagnosis
+Visit *--> "1" Symptom
+Visit *--> "1" Status
Person -[hidden]up--> I
@@ -77,5 +87,6 @@ DateOfBirth -[hidden]right-> Sex
Sex -[hidden]right-> Status
ModelManager --> "~* filtered" Person
+ModelManager --> "~* filtered" Visit
@enduml
diff --git a/docs/diagrams/ParserClasses.puml b/docs/diagrams/ParserClasses.puml
index ce4c5ce8c8d..2080e0b626f 100644
--- a/docs/diagrams/ParserClasses.puml
+++ b/docs/diagrams/ParserClasses.puml
@@ -9,7 +9,7 @@ Class XYZCommand
package "Parser classes"{
Class "<>\nParser" as Parser
-Class AddressBookParser
+Class ImmuniMateParser
Class XYZCommandParser
Class CliSyntax
Class ParserUtil
@@ -19,12 +19,12 @@ Class Prefix
}
Class HiddenOutside #FFFFFF
-HiddenOutside ..> AddressBookParser
+HiddenOutside ..> ImmuniMateParser
-AddressBookParser .down.> XYZCommandParser: <>
+ImmuniMateParser .down.> XYZCommandParser: <>
XYZCommandParser ..> XYZCommand : <>
-AddressBookParser ..> Command : <