: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.
-
+Below is a class diagram for `ModelManager`.
+
+
+
+ Figure 7. Class Diagram for Model Component
+
+
+**API** : [`Model.java`](https://github.com/AY2021S1-CS2103T-W12-1/tp/blob/master/src/main/java/seedu/address/model/Model.java)
+
+The breakdown for each type of data in `ModelManager`, which include `PatientRecords`, `RoomList` and `RoomTaskRecords`, can be found below.
+
+The `PatientRecords` class is in charge of maintaining the data of the patients and in ensuring the uniqueness of patients according to their names. Below is a class diagram for `PatientRecords`.
+
+
+
+
+ Figure 8. Class Diagram for PatientRecords
+
+
+
:information_source: **Note:** The `PatientRecords` class implements the interface ReadOnlyList<Patient> but due to a limitation of PlantUML, the interface is reflected as simply `ReadOnlyList`.
+
+The `RoomList` class is in charge of maintaining the data in the rooms and in ensuring the uniqueness of rooms according to the room numbers. As each room stores the data of the patient who resides in the room and the tasks meant for the room, it incorporates data from both `Patient` and `RoomTasks`. `RoomTasks` class is in charge of maintaining the data of the tasks in a room. The full details of `Patient` can be found in the previous class diagram for `PatientRecords` so it is no longer reflected in the class diagram for `RoomList`. The class diagram for `RoomList` is shown below.
+
+
+
+ Figure 9. Class Diagram for RoomList
+
-### Storage component
+
:information_source: **Note:** The `RoomList` class implements the interface ReadOnlyList <Room> and the `RoomTasks` class implements the interface ReadOnlyList<Task>. However, due to a limitation of PlantUML, the interface is reflected as simply `ReadOnlyList`.
+
+
-
+The `RoomTaskRecords` class is in charge of maintaining the data regarding the association of a task in a room. The `RoomTaskAssociation` class acts as an association class that ties `Task` and `Room` together so that the `Task` object does not need to know of the details of `Room` and we are still able to identify the room number that `Task` belongs to and its index in `Room`. The class diagram for `RoomTaskRecords` is shown below.
-**API** : [`Storage.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/storage/Storage.java)
+
+
+
+ Figure 10. Class Diagram for RoomTaskRecords
+
-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.
+
:information_source: **Note:** The `RoomTaskRecords` class implements the interface ReadOnlyList <RoomTaskAssociation>. However, due to a limitation of PlantUML, the interface is reflected as simply `ReadOnlyList`.
+
+
-### Common classes
+ _Written by: Yun Qing_
+
+
+### 3.5 Storage Component
+
+
+
+
+ Figure 11. Structure of the Storage Component
+
+
+**API** : [`Storage.java`](https://github.com/AY2021S1-CS2103T-W12-1/tp/blob/master/src/main/java/seedu/address/storage/Storage.java)
+
+The `Storage` API handles the reading and writing of data in Json format, enabling Covigent to remember information stored by user even when the application is closed. The Storage API behaves like a façade by handling the storage classes and interfaces.
+
+The `Storage` interface class diagram is shown below, and as it can be seen it inherits from specific storage interfaces.
+
+The `Storage` component,
+ * Saves `UserPref` objects in Json format
+ * Reads `UserPred` objects in Json format
+ * Saves `RoomRecords` and `PatientRecords` data in json format
+ * Reads `RoomRecords` and `PatientRecords` data in json format
+
+The information of the `Patient` and `Room` feature of Covigent is stored locally in the Json format. This is done by adapting the Patient and Room feature into JsonSerializablePatientRecords and JsonSerializableRoomRecords respectively.
+
+The class diagram for StorageManager is shown below
+
+
+
+ Figure 12. Structure of the StorageManager Component
+
+
+The information of the `Patient` and `Room` feature of Covigent is stored locally in the Json format. This is done by adapting the Patient and Room feature into JsonSerializablePatientRecords and JsonSerializableRoomRecords respectively.
+
+The class diagrams for the above stated adapted classes are shown below
+
+
+
+ Figure 13. Structure of the JsonSerializableRoomRecords
+
+
+
+
+
+ Figure 14. Structure of the JsonSerializablePatientRecords
+
+
+ _Written by: Noorul Azlina_
+
+
+### 3.6 Commons Component
Classes used by multiple components are in the `seedu.addressbook.commons` package.
+
--------------------------------------------------------------------------------------------------------------------
-## **Implementation**
+## 4. Implementation
-This section describes some noteworthy details on how certain features are implemented.
+This section describes some noteworthy details on how [Patient](#41-patient-feature), [Room](#42-room-feature) and [Task](#43-task-feature) features are implemented.
-### \[Proposed\] Undo/redo feature
+### 4.1 Patient Feature
-#### Proposed Implementation
+#### 4.1.1 Overview
-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:
+The patient feature in Covigent allows hotel staff to store important information about the individuals that are quarantined in the hotels. Some of these important dynamic information include temperature and comment regarding the patient. To fully understand the patient feature, it is important to learn about the [implementation](#412-implementation) and [design considerations](#413-design-considerations) of the patient object before looking at the possible [commands](#414-create-read-update-delete) that can operate on the patient object. A patient is meant to be allocated to a room in the facility, hence tying the patient feature with the room feature together.
-* `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.
+#### 4.1.2 Implementation
+A `Patient` object in Covigent contains the following attributes, which is also reflected in Figure 15:
+1. Name
+1. Temperature
+1. PeriodOfStay
+1. Age
+1. Phone
+1. Comment
-These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively.
+Each of the attribute is a stand-alone class on its own.
-Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
+
+
+
+ Figure 15. Class Diagram for Patient
+
-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.
+#### 4.1.3 Design Considerations
+**Aspect: Encapsulation of fields for `Patient` object**
-
+* Option 1: Using primitive data types for `Temperature`, `Age` and `Comment` classes
-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.
+Classes like `Temperature`, `Age` and `Comment` can be easily treated as primitive data types including double and string. However, this option goes against the spirit of OOP. Furthermore, it does not align to the original design of AddressBook3, which Covigent was morphed from, in which `Name` and `Phone` attributes were abstracted out as separate classes.
-
+* Option 2: Encapsulate constituent patient attributes in their own classes
-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`.
+This option increases OOP and is aligned to the original design of AddressBook3. In addition, this design has proven itself to be extensible in the long run and allows for adjustments to `Patient` attributes easily. For example, when setting the valid temperature range as input for `Temperature`, only the `Temperature` class needs to change, which demonstrates the essence of the single responsibility principle. This allows for better understanding and maintenance of our code base in the future.
-
+**Aspect: Decision on the uniqueness of `Patient` object**
-
: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`.
+* Option 1: Uniqueness is identified by name, age and phone
-
+Originally, we intended to define two `Patient` to be equals if they have the same `Name`, `Age` and `Phone`. However, such a design will make it difficult for users of Covigent as they will have to key in all these fields when executing `EditPatientCommand` and `DeletePatientCommand` in order for Covigent to uniquely identify the `Patient` to manipulate.
-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.
+* Option 2: Uniqueness is identified by name
-
+Keeping in mind the ease of usage of Covigent for users, we chose to identify `Patient` uniquely by `Name` only. As such, when users need to manipulate the data of a `Patient`, all they need to input is the `Name`. Furthermore, we believes that since Covigent is used by small hotels, there is a very low chance of two patients having the same names.
-
: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.
+##### Features related to Patient
+Having looked at the design of `Patient`, we can now explore the possible features related to `Patient`. In particular, our commands support [create, read, update, delete](#414-create-read-update-delete) and [search](#415-search).
-
+The features comprise of five commands namely,
+* `AddPatientCommand` - Adding patients
+* `ListPatientCommand` - Listing all the patients
+* `EditPatientCommand` - Editing patients
+* `DeletePatientCommand` - Deleting patients
+* `SearchPatientCommand`- Searching for patients
-The following sequence diagram shows how the undo operation works:
+_Written by Yun Qing_
-
+#### 4.1.4 Create, Read, Update, Delete
+In this section, we will cover the implementation of the manipulation of the `Patient` data. The commands that allow creating, reading, updating and deleting of `Patient` include `AddPatientCommand`, `ListPatientCommand`, `EditPatientCommand` and `DeletePatientCommand`.
-
: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.
+As the `Patient` data are stored in `UniquePatientList`, which ensures the uniqueness of `Patient`, the actual manipulation of the `Patient` data is made in `UniquePatientList` class.
-
+Some of the significant methods within `UniquePatientList` class that allows the manipulation of the `Patient` data are shown below:
+* `UniquePatientList#add(Patient toAdd)` - Adds a `Patient` to `UniquePatientList`.
+* `UniquePatientList#setPatient(Patient target, Patient editedPatient)` - Edits the attributes of `Patient`.
+* `UniquePatientList#remove(Patient toRemove)` - Deletes a `Patient` from `UniquePatientList`.
+* `UniquePatientList#asUnmodifiableObservableList()` - Returns an observable list of `Patient`
+* `UniquePatientList#getPatientWithName(Name name)` - Returns the `Patient` with the given `Name` if the `Patient` object exists in `UniquePatientList`. Since `Name` is an identifier of a `Patient`, this method is used in `EditPatientCommand` and `DeletePatientCommand` to modify the `Patient` or check if the `Patient` to be deleted exists.
+
+These methods in `UniquePatientList` class support the corresponding methods in the facade classes `PatientRecords` and `ModelManager`. In particular, the `Model` interface exposes the methods `Model#addPatient(Patient patient)`, `Model#setPatient(Patient target, Patient editedPatient)`, `Model#deletePatient(Patient target)`, `Model#getPatientWithName(Name name)` and `Model#getFilteredPatientList()`.
+
+For brevity's sake, we will only illustrate the implementation of 2 specific commands - `AddPatientCommand` and `EditPatientCommand`.
+
+**Implementation of AddPatientCommand**
-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.
+The following is a detailed explanation of the operations that `AddPatientCommand` performs.
-
: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.
+**Step 1.** The user executes `addpatient [input all attributes of Patient]` command to add a patient to Covigent. An `AddPatientCommandParser` object is created and the `AddPatientCommandParser#parse(String args)` method is called, which helps to parse the different attributes of `Patient`. The parse method returns a new `AddPatientCommand` object and the `AddPatientCommand` object stores the `Patient` to be added.
+**Step 2.** The `Patient` to be added is then searched through `UniquePatientList#internalList`using the `Model#hasPatient(Patient patient)` method to check if the patient already exists. If the patient already exists, a `CommandException` object will be thrown with an error message.
+
+**Step 3.** Through `Model#addPatient(Patient toAdd)`, the `Patient` will be added to `UniquePatientList`.
+
+**Step 4.** A success message with the new patient details will be appended with the `AddPatientCommand#MESSAGE_SUCCESS` constant. A new `CommandResult` will be returned with the message.
+
+The sequence diagram for a successful execution of `AddPatientCommand` can be found below.
+
+
+
+
+ Figure 16. Sequence Diagram for AddPatientCommand
+
+
+
:information_source: **Note:** Due to space limitation in PlantUML diagram, the addpatient command example given in the sequence diagram only consists of two patient attributes, name and age.
+
+
+_Written by Yun Qing_
+
+**Implementation of EditPatientCommand**
+The following is a detailed explanation of the operations that `EditPatientCommand` performs.
+
+**Step 1.** The `EditPatientCommand#execute(Model model)` method is executed and it checks if the `Name` defined when instantiating
+`EditPatientCommand(Name patientToBeEdited, EditPatientDescriptor editPatientDescriptor)` is valid. The `EditPatientDescriptor` holds
+the edited information of the `Patient`.
+
+**Step 2.** A new `Patient` with the updated values will be created and the patient is then searched through `UniquePatientList#internalList`
+using the `Model#hasPatient(Patient patient)` method to check if the patient already exists. If the patient already exists,
+`CommandException` will be thrown with an error message.
+
+**Step 3.** The newly created `Patient` will replace the existing patient object through the `Model#setPatient(Patient target, Patient editedPatient)`
+method.
+
+**Step 4.** A success message with the edited patient will be appended with the `EditPatientCommand#MESSAGE_EDIT_PATIENT_SUCCESS` constant. A
+new `CommandResult` will be returned with the message.
+
+_Written by Ming De_
+
+
+#### 4.1.5 Search
+
+The following is a detailed explanation of the operations that `SearchPatientCommand` performs.
+
+**Step 1.** The `SearchPatientCommand#execute(Model model)` method is executed and checks the `criteriaToSearch` via `confirmCriteria(SearchPatientDescriptor searchPatientDescriptor)`.
+The `SearchPatientDescriptor` holds the `name` or `temperatureRange` of the Command.
+
+**Step 2.** If the `criteriaToSearch` is `SearchCriteria.CRITERIA_NOT_FOUND`, `CommandException` will be thrown with an error message.
+
+**Step 3.** If the `criteriaToSearch` is `SearchCriteria.CRITERIA_IS_NAME`, we update the `Model`'s `FilteredPatientList` Predicate via `updateNamePredicate(Model model, SearchPatientDescriptor searchPatientDescriptor)`
+Then `findPatientWithName(SearchPatientDescriptor searchPatientDescriptor, List
patientList)` will go through `Model`'s `FilteredPatientList`, if no patient is found, `CommandException` will be thrown with an error message. If there is at least one patient found, a new `CommandResult` will be returned with the message.
+
+**Step 4.** If the `criteriaToSearch` is `CRITERIA_IS_TEMPERATURE`, we update the `Model`'s `FilteredPatientList` Predicate via `updateTemperaturePredicate(Model model, SearchPatientDescriptor searchPatientDescriptor)`
+Then `findPatientWithTemperature(SearchPatientDescriptor searchPatientDescriptor, List patientList)` will go through `Model`'s `FilteredPatientList`, if no patient is found, `CommandException` will be thrown with an error message. If there is at least one patient found, a new `CommandResult` will be returned with the message.
+
+**Step 5.** If the `criteriaToSearch` is `TOO_MANY_CRITERIA` A new `CommandResult` will be returned with the message.
+method.
+
+_Written by Wai Lok_
+
+### 4.2 Room Feature
+
+#### 4.2.1 Overview
+The application is able to track the room details. It keep tracks of the whether a room is occupied and the patient inside the room if it is occupied.
+It also keeps track of the tasks assigned to a specific room. Hence, there is a need to represent the Room List as a list of Rooms on which the application can perform read and update operations.
+
+#### 4.2.2 Implementation
+
+The class diagram for RoomList is shown below.
+
+
+
+ Figure 17. Class diagram for RoomList
+
+
+From the diagram above, the `RoomList` contains of one `UniqueRoomList`. This `UniqueRoomList` is a wrapper class around the `RoomList`
+which contains an ObservableList of `Patient` and PriorityQueue of `Patient`. The `RoomList` can contain from about 1 to 500 rooms.
+
+Each Room contains the following member attributes, all of which are non-nullable attributes:
+1. **roomNumber**
+This gives the room number of the Room object
+2. **isOccupied**
+This gives the information of whether the Room is occupied or not. If there is a `Patient` inside the `Room`, then the isOccupied is true, else false
+3. **patient**
+This gives the patient details and it is stored as an Optional object. If there is no `Patient`, then the Optional.empty() is assigned.
+4. **tasks**
+This gives all the tasks that are assigned to a specific room. The number of tasks assigned can be zero.
+
+The proposed room feature is facilitated by `RoomList`. It extends `ReadOnlyRoomList` which reads the Room information Json file, stored internally as an `addressBookStateList` and `currentStatePointer`. Additionally, it implements the following operations:
+* `RoomList#addRooms(int num)` — adds the number of which are said to add together and retains infromation previously stored in each room
+* `RoomList#containsRoom(Room toCehck)` - checks whether the given room exists
+* `RoomList#clearRoom(Name patientName)` - removes patient from the room
+* `RoomList#setSingleRoom(Room target, Room editedRoom)` - sets the editedRoom to the target room
+
+These operations are exposed in the `Model` interface as `Model#addRooms(int num)`, `Model#hasroom(Room room)`, `Model#clearRoom(Name patientName)` and `Model#setSingleRoom(Room target, Room editedRoom)` respectivley.
+
+_Written by Noorul Azlina_
+
+The GUI for room feature is based on a `ListView` that updates whenever the `RoomList` is updated and a `scroll pane` that
+displays the details of the room. To ensure that the information displayed in the `scroll pane` is updated dynamically,
+we employ the use of `Listeners` that listens for changes and notify the `scroll pane` to update.
+
+_Written by: Ming De_
+
+
+#### 4.2.3 Design Considerations
+**Aspect: Decision on allowing `editRoomCommand` that allows changing of room number to remain**
+
+* Option 1: Do not change the `editRoomCommand`
+Allowing the users to change room numbers will give the user more power in customising the rooms. However, this option introduced a bug into the system
+that could not be easily resolved unless we changed our entire implementation of `InitRoomCommand`.
+
+* Option 2: Remove `editRoomCommand` ability to change room number and rename it to `AllocateRoomCommand`
+Removing the `editRoomCommand` to change room number is much more time-efficient compared to changing the entire implementation of `InitRoomCommand`. We
+also decided that there should be no reason that a user would need to change the room number. Renaming the method to `AllocateRoomCommand` would provide
+more clarity for the method.
+
+Ultimately, we decided on Option 2. This is because keeping `editRoomCommand` would lead to a large consumption of time to redesign the system. In order
+to not stray from our schedule, we have to remove `editRoomCommand` to ensure that we can develop the other features on time.
+Furthermore, to solve the bug that was introduced, we would have to store the count of the number of times `InitRoomCommand` was called. This would
+cause us to store information in another `.json` file which is unnecessary. Therefore, we decided that the forgoing a
+small function like this would be a better choice.
+
+_Written by Ming De_
+
+##### Feature related to Room
+
+The features comprise of five commands namely,
+* `InitRoomCommand` - Initializes the number of rooms in Covigent app.
+* `ListRoomCommand` - Lists all the rooms in Covigent app.
+* `AllocateRoomCommand` - Allocates a patient to a room.
+* `SearchRoomCommand` - Searches for the room with the specified room number.
+* `FindEmptyRoomCommand` - Finds an empty room with the lowest room number.
+
+We will illustrate the progress of two of the above commands for simplicity.
+
+
+#### 4.2.4 Create, Read, Update
+
+**Implementation of InitRoomCommand**
+
+The following is a detailed explanation of the operations that `InitRoomCommand` performs.
+
+**Step 1.** The `InitRoomCommand#execute(Model model)` method is executed and it check if the `Integer`defined when instantiating
+If it is a positive integer and the number of rooms is more than or equal to the existing number of occupied rooms, InitRoomCommand is valid.
+The checking of the number of rooms is done by `Model#hasSpaceForRooms()`. If this is true then `Integer` is valid, else it is invalid.
+
+**Step 2.** The stated number of rooms is then set to `Integer`, if `Integer` is greater than the existing number of rooms then excess rooms are added to the back of the
+UniqueRoomList. If the number of rooms is less than the `Integer` and there are occupied rooms the information of patients in that room is transferred to an empty room
+in the reduced number of rooms
+
+**Step 4.** A success message with the `Intger` appended with the `InitRoomCommand#MESSAGE_SUCCESS` constant is displayed on the UI. A new `CommandResult`
+returns this message.
+
+The activity diagram below illustrates the `initRoom`.
+
+
+
+ Figure 18. Activity diagram for initRoom
+
+
+The Sequence Diagram for `initRooms` is shown below.
+
+
+
+ Figure 19. Sequence diagram for initRoom
+
+
+ _Written By: Noorul Azlina_
+
+**Implementation of AllocateRoomCommand**
+
+The following is a detailed explanation of the operations that `AllocateRoomCommand` performs.
+
+**Step 1.** The `AllocateRoomCommand#execute(Model model)` method is executed and it checks if the `Integer` defined when instantiating
+`AllocateRoomCommand(Integer roomNumberToAllocate, AllocateRoomDescriptor AllocateRoomDescriptor)` is valid. This is done using the `Model#getRoomWithRoomNumber` method
+ where it is used to get an `Optional`. If `Optional` is empty, the `Integer` is not valid.
+ The `AllocateRoomDescriptor` holds the information of the `Room` with the patient allocated.
+
+**Step 2.** A new `Room` with the allocated patient will be created and the room is then searched through `RoomList#internalList`
+using the `Model#hasRoom(Room room)` method to check if a room with the same room number exists. If it already exists,
+`CommandException` will be thrown with an error message.
+
+**Step 3.** The newly created `Room` will replace the existing room object through the `Model#setSingleRoom(Room target, Room editedRoom)`
+method.
+
+**Step 4.** A success message with the allocated room will be appended with the `AllocateRoomCommand#MESSAGE_ALLOCATE_ROOM_SUCCESS ` constant. A
+new `CommandResult` will be returned with the message.
+
+The activity diagram below illustrates `allocateRoomCommand`.
+
+
+
+ Figure 20. Activity Diagram for AllocateRoomCommand
+
+
+The sequence diagram for `AllocateRoomCommand` is shown below.
+
+
+
+ Figure 21. Sequence Diagram for AllocateRoomCommand
+
+
+_Written by Mingde_
+
+
+### 4.3 Task Feature
+
+#### 4.3.1 Overview
+The task feature in Covigent allows hotel staff to manage and organize time-critical work related to a room in a quarantine facility.
+Every room can be allocated any number of tasks, with each task keeping track of the description of the work and a due date by which
+it should be completed.
+
+It is important to note that Covigent handles tasks on a per-room basis. Tasks not specific to any room (e.g. tasks related to the operations
+of the quarantine facility) are out of scope.
+
+The task feature in Covigent includes the following:
+
+* Adding a task to a room
+* Displaying all tasks in the user interface
+* Editing the description and due date of a task
+* Removing a task from a room
+* Filtering tasks based on a criterion and displays the filtered tasks in the user interface (currently on supports filtering by due date)
+
+#### 4.3.2 Implementation
+At a higher level, tasks share a composition type relationship with rooms. That is, if a room is deleted, all tasks in that room are similarly deleted.
+We have implemented the task feature based on the class diagram in Figure 22.
+
+
+
+ Figure 22. Class Diagram for Task
+
+
+Each `Room` contains a `RoomTasks` class, which is a wrapper around `TaskList`.
+
+Task-related operations that alter the tasks in a `Room` must be performed through that `Room`.
+The API calls for these operations first proceed to `Room`, which redirects them to `RoomTasks`. To enforce this constraint, `RoomTasks` is not publicly exposed in the API for `Room`
+(i.e. there is no getter for `RoomTasks` in `Room`).
+
+`TaskList` emulates the other `List` classes in Covigent such as `UniquePatientList` and `UniqueRoomList`, exposing only an unmodifiable `ObservableList`.
+This `ObservableList` is subsequently returned by `RoomTasks` in the `getReadOnlyList()` method to fulfill its contract with the `ReadOnlyList` interface.
+
+#### 4.3.3 Design Considerations
+
+**Aspect: Retrieving list of tasks from `Room`**
+
+* Option 1: Supplying a getter for `RoomTasks` in `Room`
+
+Having a `getRoomTasks()` method to retrieve all the tasks in `Room` greatly enhances convenience, especially when copying the information from one `Room` to another.
+This is because we can use the constructor of `Room` in this manner: `Room copyOfRoom = new Room(..., originalRoom.getRoomTasks()))` (`...` refers to other attributes of `Room` that need to be passed into constructor).
+It is a quick way to transfer tasks between `Room`.
+
+However, this option is not optimal from a defensive programming perspective. Because a client can retrieve `RoomTasks` from `Room`, there is potential for abuse.
+The `RoomTasks` object may be passed to some other classes that are not `Room`. Consequently, there is no guarantee that a client will not circumvent `Room` and call an operation that changes its tasks such as `addTask(Task)` directly from `RoomTasks`.
+This destroys the abstraction barrier of `Room` as clients can modify the tasks in it via external means.
+
+* Option 2: Add a `getReadOnlyTasks()` method in `Room` to retrieve an unmodifiable list of tasks from `RoomTasks`
+
+We chose option 2 for Covigent as we thought it was the safer option. Since `RoomTasks` implements `ReadOnlyList`, `Room` can retrieve and expose it via a `getReadOnlyTasks()` method for clients to access the tasks.
+This is more secure from a defensive programming perspective and respects the abstraction barrier. Without the getter for `RoomTasks`, clients are only allowed to change the tasks in `Room` via its API.
+It ensures that the tasks in a `Room` are not modified without knowledge of `Room`, while providing the flexibility for clients to access the information in them.
+An additional benefit of this option is that it obscures the fact that `Room` depends on `RoomTasks` for its task-related operations, thus strengthening the composition type relationship between tasks and rooms.
+
+With option 2, the operation for copying tasks from one `Room` to another can be performed as such: `Room copyOfRoom = new Room(..., new RoomTasks(originalRoom.getReadOnlyTasks()))`.
+It is probably better for the constructor of `Room` to take in `List` instead of `RoomTasks` to completely hide the existence of `RoomTasks` from clients.
+This can be considered as part of the improvements to be made to Covigent in the future.
+
+A downside of this option is that the implementor (future programmers of Covigent) must be aware of this design decision and avoid exposing `RoomTasks` through the public API of `Room`.
+Moreover, there is a slight increase in complexity now that `RoomTasks` has to implement `ReadOnlyList`.
+
+**Aspect: Storing a list of tasks in `Room`**
+
+* Option 1: Using `List` in `Room`
+
+This option is simple as it does not require any additional classes. However, `Room` has to handle all task-related operations, which violates the single-responsibility principle.
+Conceptually, we consider `Room` to be a container for a patient and tasks. It should not contain implementations of methods related to patients and tasks.
+
+* Option 2: Using `TaskList` in `Room`
+
+While entirely possible to use `TaskList` to store the tasks in `Room` (see Figure 23), we cannot be certain that `TaskList` will not be used elsewhere in `Covigent` in the future.
+
+
+
+ Figure 23. Class Diagram for Task using TaskList
+
+
+For instance, suppose we want to support a list of tasks for specific patients (instead of rooms). It may not make much sense to use `TaskList` for both patients and rooms as they can have different behaviors.
+Perhaps a maximum of 5 tasks can be assigned to each patient, while there is no limit to the number of tasks that can be assigned to each room.
+Taking that into consideration, we decided to add a wrapper class.
+
+* Option 3: Using an extra class in addition to `TaskList`
+
+We chose option 3 and added a new class `RoomTasks` to `Room`. `RoomTasks` is a wrapper around `TaskList` to support room-specific behavior associated with tasks.
+A simple example is how we can set a maximum number of tasks each `Room` can hold through `RoomTasks` without modifying `TaskList`. In that sense, option 3 respects the open-closed principle.
+
+An alternative is to use a new class that extends from `TaskList`. This would improve polymorphism as methods that work with `TaskList` will also work with the new class.
+However, Liskov substitution principle might be a concern. For instance, if `TaskList` allows an unlimited number of tasks to be stored but `RoomTasks` only allows 500, it would be a violation of Liskov substitution principle.
+As such, we did not choose this alternative.
+
+The disadvantage of using another class is the added complexity as API calls for task-related operations need to be routed from the new class to `TaskList`.
+
+#### 4.3.4 Create, Read, Update, Delete
+In this section, we will cover the implementation of the manipulation of `Task` data. The commands that allow the task-related operations of creating, reading, updating, and deleting of `Task` are `AddTaskCommand`, `ListTaskCommand`, `EditTaskCommand`, and `DeleteTaskCommand` respectively.
+
+The actual manipulation of `Task` data is performed in the `TaskList` class. Some significant methods within `TaskList` that allows the manipulation of `Task` data are shown below:
+
+* `TaskList#add(Task toAdd)` - Adds a `Task` to `TaskList`.
+* `TaskList#setTask(Task target, Task editedTask)` - Replaces a `Task` in `TaskList` with the edited `Task`.
+* `TaskList#remove(Task toRemove)` - Removes a `Task` from `TaskList`.
+* `TaskList#asUnmodifiableObservableList()` - Returns a read-only list containing all `Task` in `TaskList`.
+* `RoomTasks#getTaskWithTaskIndex(Index index)` - Returns the `Task` with the `Index` in the `TaskList`. This method is currently in `RoomTasks` but can be safely refactored into `TaskList`.
+
+These methods in `TaskList` class support the corresponding methods in `RoomTasks`. For clients to perform these operations, `Room` exposes `addTask(Task task)`, `setTask(Task task, Task editedTask)`, and `deleteTask(Task task)` in its public API.
+Calls to these APIs are redirected to `RoomTasks` and eventually `TaskList`.
-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.
+Since the commands do not directly interact with `Room` but rather the `Model`, the `Model` interface has to expose `addTaskToRoom(Task task, Room room)`, `deleteTaskFromRoom(Task task, Room room)` and `setTaskToRoom(Task task, Task editedTask, Room room)`.
-
+For brevity's sake, we will only illustrate the implementation of the most complex command, `EditTaskCommand`.
-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.
+**Implementation of EditTaskCommand**
-
+The following is an explanation of the operations that `EditTaskCommand` performs, with the higher level details (`LogicManager` and `CovigentAppParser`) omitted for simplicity.
-The following activity diagram summarizes what happens when a user executes a new command:
+**Step 1.** The user executes `edittask [room number] [task index] [other attributes to edit]` command to edit the description of a `Task` in a `Room`. An `EditTaskCommandParser` object is created and the `EditTaskCommandParser#parse(String args)` method is called, which helps to parse the different attributes of `Task`. The parse method returns a new `EditTaskCommand` object with the room number, task index, and a descriptor containing the updated values to replace the original.
-
+**Step 2.** The `Room` is retrieved from the list of rooms in Covigent using the `Model#getRoomWithRoomNumber(int roomNumber)` method. If no such `Room` exists, a `CommandException` object will be thrown with an error message.
-#### Design consideration:
+**Step 3.** The `Task` is retrieved from `RoomTasks` of `Room` using the `Model#getTaskFromRoomWithTaskIndex(Index taskIndex, Room room)` method. If no such `Task` exists, a `CommandException` object will be thrown with an error message.
-##### Aspect: How undo & redo executes
+**Step 4.** The `Task` is edited in `EditTaskCommand` and replaces the original `Task` the room with `Model#setTaskToRoom(Task target, Task editedTask, Room room)`.
-* **Alternative 1 (current choice):** Saves the entire address book.
- * Pros: Easy to implement.
- * Cons: May have performance issues in terms of memory usage.
+**Step 5.** A success message with the new task details will be appended with the `EditTaskCommand#MESSAGE_SUCCESS` constant. A new `CommandResult` will be returned with the message.
-* **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.
+The sequence diagram for `EditTaskCommand` can be found below.
+
+
+
+ Figure 24. Sequence Diagram for EditTaskCommand
+
+
+_Written by Yee Hong_
-_{more aspects and alternatives to be added}_
+#### 4.3.5 Search
-### \[Proposed\] Data archiving
+The following is a detailed explanation of the operations that `SearchTaskCommand` performs.
-_{Explain here how the data archiving feature will be implemented}_
+**Step 1.** The `SearchTaskCommand#execute(Model model)` method is executed and it gets information of `task` from each `room` in the `roomList`.
+
+**Step 2.** If the `task` has a `duedate` before the `duedate` from user command, it is stored in `taskListWithDesirableResult`.
+
+**Step 3.** If no `task` is found, `CommandException` will be thrown with an error message.
+
+**Step 4.** If there is at least one task found, the `model`'s `filteredRoomTaskRecords` is updated with a `dueDatePredicate` using `updateTasksInFilteredRoomTaskRecords`.
+
+**Step 5.** a new `CommandResult` will be returned with the message.
+
+_Written by Wai Lok_
+
+### 4.4 Logging Feature
+
+We are using `java.util.logging` package for logging. The `LogsCenter` class is used to manage the logging levels and logging destinations.
+
+* The logging level can be controlled using the `logLevel` setting in the configuration file (See [Section 4.5, "Configuration Features"](#45-configuration-feature))
+* The `Logger` for a class can be obtained using `LogsCenter.getLogger(Class)` which will log messages according to the specified logging level
+* Log messages are output through: `Console` and to a `.log` file
+
+**Logging Levels**:
+* `SEVERE` : Critical problem detected which may possibly cause the termination of the application
+* `WARNING` : Can continue, but with caution
+* `INFO` : Information showing the noteworthy actions by the App
+* `FINE` : Details that is not usually noteworthy but may be useful in debugging e.g. print the actual list instead of just its size
+
+_Written by Ming De_
+
+### 4.5 Configuration Feature
+
+Certain properties of the application can be controlled (e.g user prefs file location, logging level) through the configuration file (default: `config.json`).
+
+
+--------------------------------------------------------------------------------------------------------------------
+
+## 5. Planned Features
+
+This section describes the features planned for the next iteration of Covigent.
+
+### 5.1 Single Command to Create and Allocate Patient to Room
+
+When the user wants to assign a patient to a room, she must run 2 commands: `addpatient` and `allocateroom`. The former creates a new `Patient` object in Covigent and the latter assigns that `Patient` to an empty room.
+To improve the user's productivity, we can allow the user to specify a room number when executing `addpatient`. If the room and patient are valid, the patient is added to Covigent and assigned to the room in a single command.
+
+Since these changes will add another layer of complexity, we plan to complete this feature in Covigent v1.5.
+
+### 5.2 Search for Task by Description
+
+The `searchtask` command allows searching for tasks only by due dates. A user with many tasks would most likely want to search for tasks by description.
+
+In addition to modifying `SearchTaskCommand` and `SearchTaskCommandParser`, a new class `DescriptionPredicate` might have to be introduced to filter the tasks by description.
+Considering these additional changes, we plan to complete this feature in Covigent v1.5.
+
+### 5.3 Scroll to Modified Task in User Interface
+
+Whenever a user adds or edits a `Patient` or `Room`, the Patients and Rooms tabs in the user interface scrolls to the entry corresponding to the most recent change.
+This is useful as the user can immediately review the latest modification on the user interface. To accomplish this, `PatientListPanel` and `RoomListPanel` attach a listener to `ListView` and `ListView` respectively to update the user interface when changes are detected.
+
+Currently, when the user modifies a `Task`, the user interface does not scroll to the latest change. The reason is that the current implementation of the Tasks tab retrieves the room and task details from a `ListView`, as seen in `RoomTaskListPanel`.
+The underlying list for `ListView`, found in `RoomTaskRecords` is altered each time there are changes to a room, including not only the tasks but also the room itself and the patient in it.
+Hence, the list is unable to distinguish between modifications to tasks, to rooms, or to patients in rooms. Since we do not want the user interface for `Task` to scroll when there are changes to `Room` or `Patient`, we have disabled the listener for `ListView`.
+
+Fixing this issue likely requires a significant overhaul of the implementation of the Tasks tab. We plan to complete this feature in Covigent v2.0.
+
+_Written by Yee Hong_
--------------------------------------------------------------------------------------------------------------------
-## **Documentation, logging, testing, configuration, dev-ops**
+## 6. Documentation
* [Documentation guide](Documentation.md)
* [Testing guide](Testing.md)
@@ -230,81 +823,327 @@ _{Explain here how the data archiving feature will be implemented}_
--------------------------------------------------------------------------------------------------------------------
-## **Appendix: Requirements**
+## 7. Appendix
-### Product scope
+### A1. Product scope
**Target user profile**:
+* Needs to manage a significant number of patients and their tasks
+* Needs to manage a significant number of rooms
+* Wants to keep track of patients and their tasks efficiently
+* Wants to look up patients, rooms and tasks details quickly
+* Prefers desktop apps over other types
+* Prefers typing to mouse interactions
+* Prefers all information to be available at one place
+* Can type fast
+* Is reasonably comfortable using Command Line Interface (CLI) apps
-* has a need to manage a significant number of contacts
-* prefer desktop apps over other types
-* can type fast
-* 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**:
+* Covigent is a handy tool for quarantine facility managers to manage the rooms and patients in the quarantine facility with increased productivity.
+* Covigent stores and retrieves information faster than a typical mouse/GUI driven app.
-### User stories
+### A2. 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 |
+| `* * *` | staff of a quarantine facility | key in new patient information | keep track of the information of new patients in the facility |
+| `* * *` | staff of a quarantine facility | edit patient information | update his/her health status |
+| `* * *` | staff of a quarantine facility | delete the records of patients who no longer resides in the facility | focus on information of existing patients residing in the facility|
+| `* * *` | staff of a quarantine facility | view which rooms are empty | allocate patients to them |
+| `* * *` | staff of a quarantine facility | allocate patients to room |keep track of which room they are living in|
+| `* * *` | staff of a quarantine facility | quickly find the room that a patient is staying in | locate the patient in the facility easily |
+| `* * *` | staff of a quarantine facility | key in new task information | keep track of the details of the tasks that I must complete |
+| `* *` | staff of a quarantine facility | quickly find the room details of a given room number | track the patient and tasks in that room easily |
+| `* *` | staff of the quarantine facility | indicate that I have completed the task in the room | let other staff know that they no longer have to handle them|
+| `* *` | staff of a quarantine facility | find out all the outstanding tasks left in each room | serve the quarantined individuals better |
+| `* *` | staff of a quarantine facility | quickly search through patient information | find the patients that match my criteria|
+| `* *` | staff of a quarantine facility | look at all the rooms| find out which rooms are occupied and which are not |
+| `* *`| staff of a quarantine facility | initialise the number of rooms many times with previous information retained | define correct number of rooms if mistake is made I can correct it without having to tediously key in information again|
+|`* * `| staff of a quarantine facility | find out an empty room | to allocate patient to that empty room easily without having to search through the rooms for an empty room |
+| `* * `| careless staff of a quarantine facility | edit a task | to allow for me to easily change a mistake that I made while adding tasks |
+| `* * `| forgetful staff of a quarantine facility | search a task | to allow for me to easily search for a task that end before a certain due date |
+
+### A3. Use cases
+
+(For all use cases below, the **System** is `Covigent` and the **Actor** is `Hotel Staff`, unless specified otherwise. In addition, due to limitation in Github markdown, for use cases which include another use case, there will be no underlining of text.)
+
+**Use case: UC01 Add a patient**
-*{More to be added}*
+**MSS**
-### Use cases
+1. Hotel Staff requests to add a patient into Covigent.
+2. Covigent adds the patient.
+3. Covigent shows the details of the newly added patient.
-(For all use cases below, the **System** is the `AddressBook` and the **Actor** is the `user`, unless specified otherwise)
+Use case ends.
-**Use case: Delete a person**
+**Extensions**
+* 2a. Covigent realises that the patient name already exists.
+ * 2a1. Covigent displays an error message.
+
+Use case ends.
+
+* 2b. Covigent realises that the patient information being entered does not conform to the system format.
+ * 2b1. Covigent displays an error message.
+
+Use case ends.
+
+**Use case: UC02 Delete a patient**
**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. Hotel Staff requests to delete a patient from Covigent.
+2. Covigent deletes the patient and removes the patient from the room he/she is residing in.
+3. Covigent shows the details of the deleted patient.
- Use case ends.
+Use case ends.
**Extensions**
+* 2a. Covigent realizes the patient does not exist.
+ * 2a1. Covigent displays an error message.
+
+Use case ends.
-* 2a. The list is empty.
+**Use case: UC03 Edit a patient**
- Use case ends.
+**MSS**
-* 3a. The given index is invalid.
+1. Hotel Staff inputs the new information about the patient.
+2. Covigent edits the patient information to the new information.
+3. Covigent shows the details of the edited patient.
- * 3a1. AddressBook shows an error message.
+Use case ends.
- Use case resumes at step 2.
+**Extensions**
+* 1a. Covigent realizes that no optional fields are input.
+ * 1a1. Covigent displays an error message.
+
+Use case ends.
-*{More to be added}*
+**Use case: UC04 Search for a patient**
-### Non-Functional Requirements
+**MSS**
-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. Hotel Staff requests to search patients with a criterion.
+2. Covigent searches the patients with the input criteria.
+3. Covigent shows the search results.
-*{More to be added}*
+Use case ends.
-### Glossary
+**Extensions**
+* 2a. Covigent realizes that no such patient is recorded
+ * 2a1. Covigent displays an error message.
+
+Use case ends.
-* **Mainstream OS**: Windows, Linux, Unix, OS-X
-* **Private contact detail**: A contact detail that is not meant to be shared with others
+**Use case: UC05 Allocate a patient to a room**
+
+**MSS**
+
+1. Hotel Staff adds a patient to Covigent (UC01).
+2. Hotel Staff requests to allocate the patient to a specified room.
+3. Covigent adds the patient to the specified room.
+
+Use case ends.
+
+**Extensions**
+* 2a. Covigent realizes that the specified room does not exist.
+ * 2a1. Covigent displays an error message.
+
+Use case ends.
+
+* 2b. Covigent realizes that the specified room is not empty.
+ * 2b1. Covigent displays an error message.
+
+Use case ends.
+
+
+**Use case: UC06 List all rooms**
+
+**MSS**
+
+1. Hotel Staff requests to list all the rooms in quarantine facility.
+2. Covigent lists all the rooms in the hotel and whether they are occupied or unoccupied.
+
+Use case ends.
+
+**Extensions**
+* 1a. Covgient realizes that there are no rooms existing.
+ * 1a1. Covigent displays an error message.
+
+Use case ends.
+
+**Use case: UC07 Find empty room**
+
+**MSS**
+
+1. Hotel Staff requests to search for an empty room to accommodate patient.
+2. Covigent finds an empty room.
+3. Covigent shows the room to Hotel Staff.
+
+Use case ends.
+
+**Extensions**
+* 1a. Covigent realizes that there are no rooms.
+ * 1a1. Covigent displays an error message.
+
+Use case ends.
+
+* 1b. Covigent realizes that there are no empty rooms.
+ * 1b1. Covigent displays an error message.
+
+Use case ends.
+
+**Use case: UC08 Initialize rooms**
+
+**MSS**
+
+1. Hotel Staff requests to change number of rooms.
+2. Hotel Staff inputs the number of rooms to change into.
+3. Covigent changes the number of rooms in the system.
+4. Covigent displays all the current rooms.
+
+Use case ends.
+
+**Extensions**
+* 2a. Covigent realizes that the Hotel Staff inputs an invalid number.
+ * 2a1. Covigent displays an error message.
+
+Use case ends.
+
+* 2b. Covigent realizes that the number of rooms input is less than number of occupied room
+ * 2b1. Covigent displays an error message.
+
+Use case ends.
+
+**Use case: UC09 Search for a room**
+
+**MSS**
+
+1. Hotel Staff requests to search for a room with the given patient.
+2. Hotel Staff inputs the name of the patient to find the corresponding room.
+3. Covigent displays the room details that the patient resides in.
+
+Use case ends.
+
+**Extensions**
+* 2a. Covigent realizes that the patient does not exists in the system.
+ * 2a1. Covigent displays an error message.
+
+Use case ends.
+
+* 2b. Covigent realizes that the patient is not allocated to any room.
+ * 2b1. Covigent displays an error message.
+
+Use case ends.
+
+**Use case: UC10 Add a task to a room**
+
+**MSS**
+
+1. Hotel Staff requests to add a task to a room.
+2. Covigent adds the task to the room.
+
+Use case ends.
+
+**Extensions**
+* 1a. Covigent realizes that the specified room does not exist.
+ * 1a1. Covigent displays an error message.
+
+Use case ends.
+
+**Use case: UC11 Delete a task from a room**
+
+**MSS**
+
+1. Hotel Staff requests to delete a task from a room.
+2. Covigent deletes the task from the room.
+
+Use case ends.
+
+**Extensions**
+* 1a. Covigent realizes that the specified room does not exist.
+ * 1a1. Covigent displays an error message.
+
+ Use case ends.
+
+ * 1b. Covigent realizes that the specified task does not exist.
+ * 1b1. Covigent displays an error message.
+
+ Use case ends.
---------------------------------------------------------------------------------------------------------------------
-## **Appendix: Instructions for manual testing**
+**Use case: UC12 Edit a task in a room**
+
+**MSS**
+
+1. Hotel Staff inputs the new information about the task.
+2. Covigent edits the task information to the new information.
+3. Covigent shows the details of the edited task.
+
+Use case ends.
+
+**Extensions**
+* 1a. Covigent realizes that no optional fields are input.
+ * 1a1. Covigent displays an error message.
+
+ Use case ends.
+
+ * 1b. Covigent realizes that the specified room does not exist.
+ * 1b1. Covigent displays an error message.
+
+ Use case ends.
+
+ * 1c. Covigent realizes that the specified task does not exist.
+ * 1c1. Covigent displays an error message.
+
+ Use case ends.
+
+ * 1d. Covigent realizes that the new information for the task is the same as the original.
+ * 1d1. Covigent displays an error message.
+
+ Use case ends.
+
+**Use case: UC13 Search Task**
+
+**MSS**
+
+1. Hotel Staff requests to search for a task before a specific date.
+2. Hotel Staff inputs the specific date.
+3. Covigent searches for tasks before the specific date.
+4. Covigent displays the tasks before the specific date and success message.
+
+Use case ends.
+
+**Extensions**
+* 2a. Covigent realizes that the format of the date is incorrect.
+ * 2a1. Covigent displays an error message.
+
+Use case ends.
+
+* 3a. Covigent realizes that there is no task matching the criteria.
+ * 3a1. Covigent displays an error message.
+
+Use case ends.
+
+### A4. Non-Functional Requirements
+
+1. Should work on any _mainstream OS_ as long as it has Java `11` or above installed.
+1. Should be able to hold up to 100 patients without a noticeable sluggishness in performance for typical usage.
+1. 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. Should work even without internet connection.
+1. Should respond to commands within 3 seconds.
+
+### A5. Glossary
+
+* **Mainstream OS**: Windows, Linux, Unix, OS-X
+* **Patient**: An individual residing in the quarantine facility
+* **Task**: Task is to be completed by staff of the quarantine facility
+
+## A6. Instructions for manual testing
Given below are instructions to test the app manually.
@@ -315,42 +1154,70 @@ testers are expected to do more *exploratory* testing.
### Launch and shutdown
-1. Initial launch
+1. **Initial Launch**
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. Saving window preferences
+ 1. Double-click the jar file
+ **Expected**: Shows the GUI with a set of sample patients.
+1. **Saving Window Preferences**
+
1. Resize the window to an optimum size. Move the window to a different location. Close the window.
+
+ 1. Re-launch the app by double-clicking the jar file.
+ **Expected**: The most recent window size and location is retained.
+
+1. **Storage**
+
+ 1. Launch the application and make a change that changes the state of the program, such as `addpatient` or `initroom`. Close the window.
+
+ 1. Re-launch the app by double-clicking the jar file.
+ **Expected**: The app should re-launch into the same state as when it was closed.
- 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 … }_
-
-### Deleting a person
+### Adding a patient
-1. Deleting a person while all persons are being shown
+1. **Adding a patient to Covigent**
- 1. Prerequisites: List all persons using the `list` command. Multiple persons in the list.
+ 1. Prerequisites: User is viewing the patient tab.
- 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.
+ 1. Test case: `addpatient n/John Doe t/37.0 d/20200101-20200114 p/91234567 a/22`
+ **Expected**: Patient John Doe is added to the list. Details of the newly added patient is shown in the result box and the details panel.
- 1. Test case: `delete 0`
- Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.
-
- 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. Test case: `addpatient n/John Doe`
+ **Expected**: No patient is added. Error details shown in the result box.
+ 1. Other incorrect add patient commands to try: `addpatient n/John Doe t/37.0 d/20200101-20190114 p/91234567 a/22`
+ **Expected**: Similar to previous.
+
### Saving data
-1. Dealing with missing/corrupted data files
-
- 1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_
+1. **Dealing with missing data files**
+
+ 1. Run the app once and play around with the application. Once a change is made, the program will generate a data files in `./data/`.
+
+ 1. In `./data/`, delete `covigentapp.json` and `roomInformation.json`.
+
+ 1. Re-launch the app.
+ **Expected**: Default Patient information should now be present in the Patient tab. No Rooms present in Room tab.
+
+1. **Corrupted data files**
+
+ 1. Run the app once and play around with the application. Once a change is made, the program will generate a data files in `./data/`.
+
+ 1. In `./data/`, open `covigentapp.json`. On line 2, delete the `[`:
+ ```
+ 1 {
+ 2 "patients" : [ {
+ 3 ...
+ ```
+ should become
+
+ ```
+ 1 {
+ 2 "patients" : {
+ 3 ...
+ ```
+ 1. Re-launch the app.
+ **Expected**: Go to the Patient tab and the tab should not have any data. `covigentapp.json` still exists.
-1. _{ more test cases … }_
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 00000000000..899901192e2
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,10 @@
+### Covigent
+
+[](https://github.com/AY2021S1-CS2103T-W12-1/tp/actions)
+
+
+Covigent is a desktop app for managing information of quarantined individuals and the tasks to be done by staff of the quarantine facilities. It is optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). If you type fast, Covigent can improve your efficiency in managing your patients and tasks instead of using traditional GUI apps.
+
+Check out our [User Guide](https://ay2021s1-cs2103t-w12-1.github.io/tp/UserGuide.html) to get started.
+
+This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative](https://se-education.org).
diff --git a/docs/SettingUp.md b/docs/SettingUp.md
index b89b691fed9..392f994ee0a 100644
--- a/docs/SettingUp.md
+++ b/docs/SettingUp.md
@@ -45,11 +45,4 @@ 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).
-
-1. **Do the tutorials**
- These tutorials will help you get acquainted with the codebase.
-
- * [Tracing code](tutorials/TracingCode.md)
- * [Removing fields](tutorials/RemovingFields.md)
- * [Adding a new command](tutorials/AddRemark.md)
+ When you are ready to start coding, we recommend that you get some sense of the overall design by reading about [Covigent’s architecture](DeveloperGuide.md#architecture).
diff --git a/docs/UserGuide.md b/docs/UserGuide.md
index b91c3bab04d..f83773f7a2e 100644
--- a/docs/UserGuide.md
+++ b/docs/UserGuide.md
@@ -1,178 +1,1202 @@
---
layout: page
-title: User Guide
+title: Covigent - 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.
+1. [Introduction](#1-introduction)
+1. [About this Guide](#2-about-this-guide)
+ 2.1. [What's in Covigent](#21-what-is-in-covigent)
+ 2.2. [Formatting in the Guide](#22-formatting-in-the-guide)
+1. [Getting Started](#3-getting-started)
+ 3.1. [Setting Up](#31-setting-up)
+ 3.2. [Parts of the Graphical User Interface](#32-parts-of-the-graphical-user-interface)
+ 3.2.1. [Patients Tab](#321-patients-tab)
+ 3.2.2. [Rooms Tab](#322-rooms-tab)
+ 3.2.3. [Tasks Tab](#323-tasks-tab)
+ 3.3. [Tutorial on How to Use Covigent](#33-tutorial-on-how-to-use-covigent)
+1. [Glossary](#4-glossary)
+1. [Features](#5-features)
+ 5.1. [Command Format](#51-command-format)
+ 5.2. [Patient](#52-patient)
+ 5.2.1. [Add a Patient: `addpatient`](#521-add-a-patient-addpatient)
+ 5.2.2 [Delete a Patient: `deletepatient`](#522-delete-a-patient-deletepatient)
+ 5.2.3 [Edit Patient Details: `editpatient`](#523-edit-patient-details-editpatient)
+ 5.2.4 [Search Patients by Information: `searchpatient`](#524-search-patients-by-information-searchpatient)
+ 5.2.5 [List all Patients: `listpatient`](#525-list-all-patients-listpatient)
+ 5.3. [Room](#53-room)
+ 5.3.1 [Initialise Rooms in Hotel: `initroom`](#531-initialise-rooms-in-hotel-initroom)
+ 5.3.2 [Allocate Patient to Room: `allocateroom`](#532-allocate-patient-to-room-allocateroom)
+ 5.3.3 [Search by Room Number: `searchroom`](#533-search-by-room-number-searchroom)
+ 5.3.4 [Search for Room with Patient: `searchroom`](#534-search-for-room-with-patient-searchroom)
+ 5.3.5 [List the Current Rooms: `listroom`](#535-list-the-current-rooms-listroom)
+ 5.3.6 [Find the first free room: `findemptyroom`](#536-find-the-first-free-room-findemptyroom)
+ 5.4 [Task](#54-task)
+ 5.4.1 [Add a Task to a Room: `addtask`](#541-add-a-task-to-a-room-addtask)
+ 5.4.2 [Delete a Task from a Room: `deletetask`](#542-delete-a-task-from-a-room-deletetask)
+ 5.4.3 [Edit Task Description or Due Date: `edittask`](#543-edit-task-description-or-due-date-edittask)
+ 5.4.4 [Remove Due Date from a Task: `edittask`](#544-remove-due-date-from-a-task-edittask)
+ 5.4.5 [Search all Tasks before the Given Date: `searchtask`](#545-search-tasks-before-a-given-date-searchtask)
+ 5.4.6 [List all Tasks: `listtask`](#546-list-all-tasks-listtask)
+ 5.5 [View Help: `help`](#55-view-help-help)
+ 5.6 [Exit Covigent: `exit`](#56-exit-covigent-exit)
+ 5.7 [Autosave](#57-autosave)
+1. [Command Summary](#6-command-summary)
+ 6.1 [Patient](#61-patient)
+ 6.2 [Room](#62-room)
+ 6.3 [Task](#63-task)
+ 6.4 [General](#64-general)
+1. [FAQ](#7-faq)
-* Table of Contents
-{:toc}
--------------------------------------------------------------------------------------------------------------------
-## Quick start
+## 1. Introduction
-1. Ensure you have Java `11` or above installed in your Computer.
+Welcome to User Guide for our application, Covigent! Has Covid-19 hit your boutique hotel hard and left you scrambling to search for an application
+that can ease your transition from a boutique hotel to a quarantine facility? Your search ends here!
-1. Download the latest `addressbook.jar` from [here](https://github.com/se-edu/addressbook-level3/releases).
+Covigent is a desktop management application to ease boutique hotels' transitions into quarantine facilities. Covigent aims to help boutique hotel managers
+keep track of the information of quarantined individuals (i.e. patients) and the tasks to be done by their staff. The main features include:
-1. Copy the file to the folder you want to use as the _home folder_ for your AddressBook.
+ 1. Managing patient information - Period of Stay, temperature, phone number etc.
+ 2. Managing the rooms of the quarantine facility - Allocate patients to rooms, search for a room, etc.
+ 3. Managing the tasks to be done by each room - Add a task to a room, editing a task to the room, etc.
-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.
- 
+As an application optimized for use with a keyboard rather than the mouse, you operate Covigent mainly by
+typing commands into a Command Box. If you can type quickly, Covigent can improve your efficiency in managing your patients and tasks instead of using traditional apps.
+But wait! Don't forget our beautiful Graphical User Interface (GUI) too!
+With our easy to navigate GUI, it has served it's purpose well as an interface that facilitates interaction with our application
+through graphical icons.
-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:
+Getting interested? Jump to [Section 3, "Getting Started"](#3-getting-started) to get started.
- * **`list`** : Lists all contacts.
+This is what Covigent looks like:
- * **`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.
+
+
+
+ Figure 1. The Graphical User Interface for Covigent
+
- * **`delete`**`3` : Deletes the 3rd contact shown in the current list.
+_Written by: Ming De_
- * **`clear`** : Deletes all contacts.
- * **`exit`** : Exits the app.
+--------------------------------------------------------------------------------------------------------------------
+
+## 2. About this Guide
+
+This guide gives you an overview of the features in Covigent and shows you how to get started using Covigent.
+Choose a link in the [Feature](#5-features) section to get a step-by-step instruction, and understand how to use Covigent.
+
+### 2.1 What is in Covigent
+
+In our patient features, you can [add](#521-add-a-patient-addpatient), [delete](#522-delete-a-patient-deletepatient),
+[edit](#523-edit-patient-details-editpatient), [search](#524-search-patients-by-information-searchpatient) for a patient,
+or you can [list](#525-list-all-patients-listpatient) out all the patients in Covigent.
+
+Moving on to our room features, you can [initialise](#531-initialise-rooms-in-hotel-initroom), [allocate](#532-allocate-patient-to-room-allocateroom),
+[search](#533-search-by-room-number-searchroom) and [find](#536-find-the-first-free-room-findemptyroom) the rooms which you need.
+If you want an overview of the rooms, you can [list](#535-list-the-current-rooms-listroom) out all the rooms in Covigent.
+
+Next, for our task features, you can [add](#541-add-a-task-to-a-room-addtask), [delete](#542-delete-a-task-from-a-room-deletetask),
+[edit](#543-edit-task-description-or-due-date-edittask) and [search](#545-search-tasks-before-a-given-date-searchtask) for a task
+and see it be displayed on our amazing GUI. If you want to see all the tasks, you can [list](#546-list-all-tasks-listtask) out all the tasks in Covigent.
+
+Lastly, our miscellaneous features will ensure that you can seek [help](#55-view-help-help) if you are lost, or
+[exit](#56-exit-covigent-exit) the program when you are done with it. Our app also has an [autosave](#57-autosave) feature that allows you to save the data without manual command.
+
+
+### 2.2 Formatting in the Guide
+
+Note the following formatting used in this document:
+* 
+This symbol indicates important information.
+
+* 
+A grey highlight (called a mark-up) indicates a keyword. It denotes either i) a field or command that can be typed into the Command Box and executed by Covigent; or ii) the name of a file.
+
+* 
+Italicised words indicate text that is displayed on the Graphical User Interface.
+
+* 
+A light blue font color indicates that this is a Hyperlink that you can click on
+and be transferred to the corresponding section in Covigent.
+
+_Written by: Wai Lok_
-1. Refer to the [Features](#features) below for details of each command.
--------------------------------------------------------------------------------------------------------------------
-## Features
+## 3. Getting Started
-
+If you are tired of lengthy and problematic installation processes, Covigent is perfect for you.
+The setup is minimal and can be completed in 4 simple steps. Follow the instructions below to try it out!
-**:information_source: Notes about the command format:**
+### 3.1 Setting Up
-* 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`.
+The following steps to set up Covigent are applicable to Windows, Mac OS X, and Linux.
-* 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`.
+1. Install Java 11 or a later version. The latest version of Java can be found [here](https://java.com/en/download/).
-* 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.
+1. Download the latest version of Covigent from [here](https://github.com/AY2021S1-CS2103T-W12-1/tp/releases). To do so, look for the file `covigent.jar` and click on it.
+ Please refer to Figure 2 if you require assistance with locating the file. Figure 2 shows how to download version 1.3 of Covigent. `covigent.jar` has been highlighted in red for your convenience.
+
+
+
+ Figure 2. How to Download Covigent
+
-* 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.
+1. You may move `covigent.jar` to any other folder. Your save data and preferences for Covigent will be saved to the same folder.
-
+1. Double-click on `covigent.jar` to start Covigent. Here is what you will see if everything goes right:
+
+
+
+ Figure 3. Covigent after Starting Up
+
-### Viewing help : `help`
+In case there are any problems during setup, please refer to [Section 7, "FAQ"](#7-faq) for instructions to resolve them.
-Shows a message explaning how to access the help page.
+### 3.2 Parts of the Graphical User Interface
-
+The user interface of Covigent comprises 3 main tabs: Patients, Rooms, and Tasks. The tabs respectively display information on the
+patients, the rooms in the quarantine facility, and the tasks assigned to the rooms. A tab turns a deeper shade of pink
+when you click on it to indicate that you are currently in the tab. For example, Figure 4 shows how the Tasks tab changes colours when you click on it.
+
+
+
+ Figure 4. User Interface of Covigent when a Tab is Clicked
+
-Format: `help`
+#### 3.2.1 Patients Tab
+The main purpose of the Patients tab is to display information about the patients.
-### Adding a person: `add`
+When you first start Covigent, you will find yourself in the Patients tab. You may notice that there is already some sample data for quarantined
+individuals. There is no need to worry! The data can be edited or deleted to suit your needs later. If you urgently need to change the data,
+please proceed to [Section 5.2.3, "Edit Patient Details"](#523-edit-patient-details-editpatient) for the relevant instructions.
-Adds a person to the address book.
+Using the Patients tab is easy. Click on any of the patients. This will highlight that individual and display her information.
+Figure 5 illustrates what happens when you click on a patient _David Li_. Observe that his details appear on the right of the
+user interface, in the Details Panel.
-Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…`
+
+
+
+ Figure 5. Highlighted Individual in Patients Tab
+
-:bulb: **Tip:**
-A person can have any number of tags (including 0)
-
+#### 3.2.2 Rooms Tab
-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`
+The main purpose of the Rooms tab is to display information about the rooms in the quarantine facility. Each room contains 1 quarantined
+individual and multiple tasks.
-### Listing all persons : `list`
+When you first start Covigent and click into the Rooms tab, it will be empty. Rest assured that this is normal. Once you learn how to add rooms
+to Covigent, the Rooms tab will be populated in no time. You may refer to [Section 3.3, "Tutorial on How to Use Covigent"](#33-tutorial-on-how-to-use-covigent)
+for step-by-step guidance or [Section 5.3.1, "Initialise Rooms in Hotel"](#531-initialise-rooms-in-hotel-initroom) if you prefer a more hands-on approach.
-Shows a list of all persons in the address book.
+Using the Rooms tab is easy. Click on any of the rooms. This will highlight that room and display the patient and tasks allocated
+to the room. Figure 6 shows what happens when you click on _Room #2_. The details of the patient _Alex Yeoh_ and task _Sanitise the room_
+are displayed on the right of the user interface, in the Details Panel.
-Format: `list`
+
+
+
+ Figure 6. Highlighted Room in Rooms Tab
+
-### Editing a person : `edit`
+#### 3.2.3 Tasks Tab
-Edits an existing person in the address book.
+The main purpose of the Tasks tab is to display information about the tasks assigned to the rooms. When you have too many tasks, it is common
+to forget which room you have allocated a certain task to. The Tasks tab provides a quick overview of all the tasks in Covigent such that you do not
+have to look through each room to find a specific task.
-Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…`
+When you first start Covigent and click into the Tasks tab, it will be empty. Do not panic! This is the default behaviour. As you add more tasks to the rooms,
+those tasks will start to appear in the Tasks tab. You may refer to [Section 3.3, "Tutorial on How to Use Covigent"](#33-tutorial-on-how-to-use-covigent)
+for step-by-step guidance or [Section 5.4.1, "Add a Task to a Room"](#541-add-a-task-to-a-room-addtask) if you prefer a more hands-on approach.
-* 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.
-* 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.
+Using the Tasks tab is easy. Simply read the description and due date of the tasks directly from the user interface. For tasks with very long
+descriptions, the user interface is unable to fully display them. In those cases, you may highlight the descriptions with your cursor and drag right to scroll through them.
+Alternatively, you may triple-click on the descriptions, followed by a right click to copy them. Refer to Figure 7 for an example of the latter method.
+
+
+
+
+ Figure 7. Copying a Long Description in Tasks Tab
+
-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.
+### 3.3 Tutorial on How to Use Covigent
-### Locating persons by name: `find`
+Covigent has numerous features, including adding patients, creating rooms, assigning tasks to rooms, and more.
+Every feature has a corresponding command. Using a feature is as simple as typing a command in the Command Box (see Figure 8) and pressing Enter to execute it.
-Finds persons whose names contain any of the given keywords.
+
+
+
+ Figure 8. Command Box of Covigent
+
-Format: `find KEYWORD [MORE_KEYWORDS]`
+You have heard so much about the potential of Covigent. Excited? Without further ado, let's give these features a try! We will role-play the
+following scenario to get you acquainted with a few common commands: your hotel has 10 rooms; a guest is arriving today and will quarantine with
+your hotel for 14 days; and you must not forget to sanitise the room the day after he leaves.
-* 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`
+You may copy-and-paste the following commands (bold and in grey highlights) into the Command Box. Do not forget to press Enter, or the command will not execute!
-Examples:
-* `find John` returns `john` and `John Doe`
-* `find alex david` returns `Alex Yeoh`, `David Li`
- 
+1. **`initroom 10`** : Let's set up the hotel room first. This command creates _10_ rooms in Covigent. If you proceed to the Rooms tab, you will see that 10 rooms
+ have been created (see Figure 9).
-### Deleting a person : `delete`
+
+
+
+ Figure 9. Creating Hotel Rooms in Covigent
+
-Deletes the specified person from the address book.
+2. **`addpatient n/John Doe t/37.4 d/20200910-20200924 p/98765432 a/35 c/Vegan`** : The guest has arrived. You have taken his temperature and need to enter his details into Covigent.
+ This command adds a new patient named _John Doe_ with age _35_, phone number _98765432_, period of stay _10 Sep 2020 to 24 Sep 2020_, temperature _37.4_, and a comment that he is _Vegan_.
+ If you proceed to the Patients tab, you will see that _John Doe's_ entry has been added.
-Format: `delete INDEX`
+
+
+
+ Figure 10. Adding a Patient to Covigent
+
-* 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, …
+3. **`findemptyroom`** : You would like to assign _John Doe_ a room but are unsure which rooms are empty. This command will search for an empty room.
+ Proceed to the Rooms tab. The result can be seen in Figure 11.
-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.
+
+
+
+ Figure 11. Finding an Empty Room in Covigent
+
-### Clearing all entries : `clear`
+4. **`allocateroom 1 n/John Doe`** : Now that you know _Room #1_ is empty, let's assign _Room #1_ to _John Doe_. This command will do exactly that.
+ Notice that _Room #1_ is now occupied and _John Doe's_ details are reflected in the Details Panel on the right of the user interface.
-Clears all entries from the address book.
+
+
+
+ Figure 12. Allocating a Room to a Patient in Covigent
+
-Format: `clear`
+5. **`addtask r/1 d/Sanitise the room dd/20200925 1800`** : Finally, we would like a reminder to sanitise the room after _John Doe_ leaves.
+ This command adds a task to _Room #1_ with description _Sanitise the room_ and due date _25 Sep 2020 1800_. Notice that the Details Panel
+ reflects the task now (see Figure 12). You may also click on the Tasks tab to view the newly added task.
-### Exiting the program : `exit`
+
+
+
+ Figure 13. Adding a Task to Covigent
+
-Exits the program.
+If you are curious about what other features are available in Covigent, please visit [Section 5, Features](#5-features).
-Format: `exit`
+_Written by: Yee Hong_
+
+
+--------------------------------------------------------------------------------------------------------------------
-### Saving the data
+## 4. Glossary
-AddressBook data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually.
+* **Graphical User Interface**: A form of user interface that allows users to interact with electronic devices through graphical icons.
+* **Patient**: An individual who resides in the quarantine facility.
+* **Task**: A task to be completed by staff of the quarantine facility.
-### Archiving data files `[coming in v2.0]`
+_Written by: Yun Qing_
-_{explain the feature here}_
--------------------------------------------------------------------------------------------------------------------
-## FAQ
+## 5. Features
+
+This section covers all the commands that you can type into the Command Box of Covigent. The commands are categorised into [patient features](#52-patient), [room features](#53-room) and [task features](#54-task). If it is the first time that you are using the command, we recommend that you refer to [Command Format](#51-command-format) to find out how to interpret the format of the commands.
+
+_Written by: Yun Qing_
+
+### 5.1 Command Format
+
+**:information_source: Notes about the command format:**
+* Words in `UPPER_CASE` are the fields to be supplied by the user.
+ e.g. in `addpatient n/NAME`, `NAME` is a field which can be used as `addpatient n/John Doe`.
+
+* Fields in square brackets are optional.
+ e.g `n/NAME [c/COMMENT]` can be used as `n/John Doe c/Is vegan` or as `n/John Doe`.
+
+* Fields can be in any order.
+ e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable.
+
+* If the same field is provided multiple times, only the last input for that field will be processed.
+ e.g. if you input `n/John Doe n/Mary Doe`, Covigent will only process `n/Mary Doe` and ignore `n/John Doe`. Similarly, if you input `n/John Doe t/37.4 n/Mary Doe t/36.5`, Covigent will interpret the fields provided as simply `n/Mary Doe t/36.5`.
+
+
+### 5.2 Patient
+
+This section contains all the commands related to patients. You can [add](#521-add-a-patient-addpatient), [delete](#522-delete-a-patient-deletepatient),
+[edit](#523-edit-patient-details-editpatient), [search](#524-search-patients-by-information-searchpatient) for a patient, or you can [list](#525-list-all-patients-listpatient) out all the patients in Covigent. If you are unsure of how to interpret the command format, head back to [Command Format](#51-command-format) before executing the commands!
+
+#### 5.2.1 Add a Patient: `addpatient`
+
+You can use this command to add a patient with the following details: name, temperature, period of stay, phone number, age and comment.
+
+**Format:** `addpatient n/NAME t/TEMPERATURE d/PERIOD_OF_STAY p/PHONE_NUMBER a/AGE [c/COMMENT]`
+
+Field | Description
+------------ | -------------
+`NAME` | The name of the patient. It should preferably be the full name of the patient. The maximum number of characters allowed is 150.
+`TEMPERATURE` | The temperature of the patient. It must be keyed in to 1 decimal place (e.g. 37.0 instead of 37) and must be within the range 32.0 to 41.0 degree celsius, both inclusive.
+`PERIOD_OF_STAY` | The period of stay of the patient in the facility. It must be in the format YYYYMMDD-YYYYMMDD. Both dates must be valid and the start date must be before or equals to the end date.
+`PHONE_NUMBER` | The phone number of the patient that the patient wishes to be contacted by. The maximum number of digits allowed is 20.
+`AGE` | The age of the patient, which is between 0 (inclusive) and 120 (exclusive).
+`COMMENT` | An optional field that is used to indicate any special details of the patient such as dietary preferences or health conditions.
+
+**:information_source: Important Information:**
+* Duplicate names are not allowed. If an entry of name _John Doe_ is recorded in Covigent, you should not add a patient of the name _John Doe_ again.
+
+
+**Example(s):**
+1. `addpatient n/Betsy Crowe t/36.5 d/20201001-20201014 p/91234567 a/19 c/Is asthmatic` A patient named _Betsy Crowe_ with temperature _36.5_, period of stay from _1 October 2020 to 14 October 2020_, phone number _91234567_, age _19_ and comment _Is asthmatic_ is added to Covigent.
+
+
+**Step By Step Usage:**
+1. Navigate to the Patients tab under the navigation bar as shown in Figure 14.
+
+
+
+ Figure 14. Navigation to Patients Tab
+
+1. Using the first example, key in the command into the Command Box as shown below.
+
+
+
+ Figure 15. addpatient Command in Command Box
+
+1. Press Enter to run the command.
+1. The Result Box displays the sucess message shown in Figure 16. The Details Panel now reflects the information of the newly added patient and the patient is selected in the Patient List.
+
+
+
+ Figure 16. A Successful Execution of addpatient Command
+
+1. If you do not see the success message as shown in Figure 16, please repeat step 2 onwards.
+
+_Written by: Yun Qing_
+
+#### 5.2.2 Delete a Patient: `deletepatient`
+
+You can use this command to delete the details of the existing patient identified by his/her name from Covigent.
+
+**Format:** `deletepatient NAME`
+
+Field | Description
+------------ | -------------
+`NAME` | The name of the patient to be deleted. It is case-insensitive and must match exactly with the name of the patient that was input into Covigent previously.
+
+**:information_source: Important Information:**
+* If the patient to be deleted was allocated a room previously, the room will be updated to unoccupied in Covigent but the tasks (if any) in that room will remain unchanged.
+
+
+**Example(s):**
+1. `deletepatient Mary Doe` The patient details of Mary Doe will be deleted from Covigent.
+
+
+**Step By Step Usage:**
+1. Navigate to the Patients tab under the navigation bar as shown in Figure 17.
+
+
+
+ Figure 17. Navigation to Patients Tab
+
+1. Using the first example, key in the command into the Command Box as shown below.
+
+
+
+ Figure 18. deletepatient Command in Command Box
+
+1. Press Enter to run the command.
+1. The Result Box displays the success message shown in Figure 19 and the deleted patient can no longer be found in the list of patients in Covigent. The Patient List now hovers back to the first patient in the list and the Details Panel displays the information of the first patient.
+
+
+
+ Figure 19. A Successful Execution of deletepatient
+
+1. If you do not see the success message as shown in Figure 19, please repeat step 2 onwards.
+
+_Written by: Yun Qing_
+
+#### 5.2.3 Edit Patient Details: `editpatient`
+
+You can use this command to edit an existing patient's details in Covigent.
+
+**Format**: `editpatient ORIGINAL_NAME [n/NEW_NAME] [t/TEMPERATURE] [d/PERIOD_OF_STAY] [p/PHONE_NUMBER] [a/AGE] [c/COMMENT]`
+
+Field | Description
+------------ | -------------
+`ORIGINAL_NAME` | The name of the patient whom details are to be edited. It must match exactly with the name of the patient that was input into Covigent previously. It is case-insensitive.
+`NEW_NAME` | The new name of the patient. The new name must not already exist within Covigent and the maximum number of characters allowed is 150.
+`TEMPERATURE` | The new temperature of the patient. It must be keyed in to 1 decimal place (e.g. 37.0 instead of 37) and must be within the range 32.0 to 41.0 degree Celsius, both inclusive.
+`PERIOD_OF_STAY` | The new period of stay of the patient. It must be in the format YYYYMMDD-YYYYMMDD. Both dates must be valid and the start date must be before or equals to the end date.
+`PHONE_NUMBER` | The new phone number of the patient. The maximum number of digits allowed is 20.
+`AGE` | The new age of the patient. Age should be between 0 (inclusive) and 120 (exclusive).
+`COMMENT` | The new comments about the patient.
+
+**:information_source: Important Information:**
+* At least one of the optional fields must be provided.
+* Existing values will be updated to the input values.
+
+
+**Example(s):**
+1. `editpatient john doe p/91234567` The phone number of the patient named John Doe will be updated to _91234567_.
+1. `editpatient alex t/36.7 a/21 d/20200303-20200315` The temperature, age and period of stay of the patient named Alex will be updated to _36.7_, _21_ and _20200303-20200315_ respectively.
+
+**Step By Step Usage:**
+1. Navigate to the Patients tab under the navigation bar as shown in Figure 20.
+
+
+
+ Figure 20. Navigation to Patients Tab
+
+1. Using the first example, key in the command into the Command Box as shown below.
+
+
+
+ Figure 21. editpatient Command in Command Box
+
+1. Press Enter to run the command.
+1. The Result Box displays the success message shown in Figure 22 and the patient has been edited in Covigent.
+1. The details of the newly edited patient will be shown in the Details Panel.
+
+
+
+ Figure 22. A Successful Execution of editpatient Command
+
+1. If you do not see the success message as shown in Figure 11, please repeat step 2 onwards.
+
+_Written by: Ming De_
+
+#### 5.2.4 Search Patients by Information: `searchpatient`
+
+You can use this command to search patients that match the given criteria(name or a range of temperature) in Covigent.
+
+**Format**: `searchpatient [n/NAME] [tr/TEMPERATURE_RANGE]`
+
+Field | Description
+------------ | -------------
+`NAME` | The full name or the sub-name of the patient you want to look for. If the patient's name is "Alex Joe", then you must enter "Alex", "Joe" or "Alex Joe" to find him. You input is case-insensitive.
+`TEMPERATURE_RANGE` | The temperature range that you want to look for. It is made up of two valid temperatures. A temperature must be keyed in to 1 decimal place (e.g. 37.0 instead of 37). The two temperature are linked using a dash "-". The `TEMPERATURE_RANGE` is inclusive of start and end temperatures. `tr/35.5-36.0` means a temperature range of 35.5-36.0 degree, celsius, both inclusive.
+
+**:information_source: Important Information:**
+* Only one of the fields can be provided. If the field `n/name` is entered, you should not enter the field `tr/TEMPERATURE_RANGE`.
+* The two temperature you enter for field `tr/TEMPERATURE_RANGE` must both be valid, if one of the temperature is invalid, the search function will fail.
+
+
+**Example(s):**
+1. `searchpatient n/john` Searches patients with names containing _john_.
+1. `searchpatient tr/36.5-36.7` Searches patients within temperature range _36.5 to 36.7_ degree celsius, both inclusive.
+
+**Step By Step Usage:**
+
+1. Navigate to the Patients tab under the navigation bar as shown in Figure 23.
+
+
+
+ Figure 23. Navigation to Patients Tab
+
+1. Before the search, this is what you see in the list of patient.
+
+
+
+ Figure 24. Patient List before searchpatient Command
+
+1. Using the second example, key in the command into the Command Box as shown below.
+
+
+
+ Figure 25. searchpatient Command in Command Box
+
+1. Press Enter to run the command.
+1. The Result Box displays the success message shown in Figure 26 and you can find the patients with temperatures in the inputted temperature range in Covigent.
+
+
+
+ Figure 26. A Successful Execution of searchpatient
+
+
+_Written by: Wai Lok_
+
+#### 5.2.5 List all Patients: `listpatient`
+
+You can use this command to look at the list of all patients in the patient tab.
+
+**Format**: `listpatient`
+
+**Example(s)**:
+1. `listpatient` Lists all patients that are present in Covigent.
+
+**Step By Step Usage:**
+
+1. Navigate to the Patients tab under the navigation bar as shown in Figure 27.
+
+
+
+ Figure 27. Navigation to Patients Tab
+
+1. Key in the command into the Command Box as shown below.
+
+
+
+ Figure 28. listpatient Command in Command Box
+
+1. Press Enter to run the command.
+1. The Result Box displays the sucess message shown in Figure 29 and you can find the full list of patient in Covigent.
+
+
+
+ Figure 29. A Successful Execution of listpatient
+
+
+_Written by: Wai Lok_
+
+### 5.3 Room
+
+This section contains all the commands related to rooms. You can [initialise](#531-initialise-rooms-in-hotel-initroom), [allocate](#532-allocate-patient-to-room-allocateroom), [search](#533-search-by-room-number-searchroom) and [find](#536-find-the-first-free-room-findemptyroom) the rooms which you need.
+If you want an overview of the rooms, you can [list](#535-list-the-current-rooms-listroom) out all the rooms in Covigent. If you are unsure of how to interpret the command format, head back to [Command Format](#51-command-format) before executing the commands!
+
+
+#### 5.3.1 Initialise Rooms in Hotel: `initroom`
+
+You can use this command to initialise a number of rooms in the quarantine facility to the app, if there was data given previously, they would
+be stored.
+
+Format: `initroom NUMBER_OF_ROOMS`
+
+Field | Description
+----------|-------------
+`NUMBER_OF_ROOMS` | The number of rooms you wish to have in hotel
+
+**:information_source: Important Information:**
+* The maximum number of rooms that can be defined is 500 as most boutique hotels have a maximum of 500 rooms.
+* If suppose you `initroom x` and x is already the number of rooms, no error would be seen to improve user experience.
+* If the number of rooms is less than the number of patients error is thrown when decreasing the number of existing rooms.
+* Adds `NUMBER_OF_ROOMS` rooms into the hotel system, if there were previously added information that information for respective rooms will still be there.
+
+
+**Example(s):**
+1. `initroom 123`. 123 rooms are initialised in Covigent.
+1. `initroom 400`. 400 rooms are initialised in Covigent.
+
+**Step By Step Usage:**
+1. Navigate to the Rooms tab under the navigation bar as shown in Figure 30.
+
+
+
+ Figure 30. Navigation to Rooms Tab
+
+1. Using the first example, key in the command into the Command Box as shown below.
+
+
+
+ Figure 31. Navigation to Rooms Tab
+
+1. Press Enter to run the command.
+1. The Result Box shows a success message "Initialise the number of rooms to 400 rooms in the application.".
+
+
+
+ Figure 32. A Successful Execution of initroom
+
+
+_Written by: Noorul Azlina_
+
+#### 5.3.2 Allocate Patient to Room: `allocateroom`
+
+You can use this command to allocate a patient to a room.
+
+**Format**: `allocateroom ROOM_NUMBER n/PATIENT_NAME`
+
+Field | Description
+----------|-------------
+`ROOM_NUMBER` | The room number of the room of which the patient is to be allocated to. A room with the `ROOM_NUMBER` must already exist within Covigent.
+`PATIENT_NAME` | The name of the patient to be allocated to the room. It is case-sensitive but must match exactly with the name of the patient that was input into Covigent previously.
+
+**:information_source: Important Information:**
+* To remove a patient from the room, input the patient name as "-". Refer to the example below for more clarity.
+
+
+**Example(s):**
+1. `allocateroom 1 n/john doe`. The patient named _John Doe_ will be allocated to _Room #1_.
+1. `allocateroom 1 n/-`. The previous patient will be removed from _Room #1_.
+
+**Step By Step Usage:**
+1. Navigate to the Rooms tab under the navigation bar as shown in Figure 33.
+
+
+
+ Figure 33. Navigation to Rooms Tab
+
+1. Using the first example, key in the command into the Command Box as shown below.
+
+
+
+ Figure 34. allocateroom Command in Command Box
+
+1. Press Enter to run the command.
+1. The Result Box displays the sucess message shown in Figure 35 and the patient is allocated to the room.
+The room with the newly allocated patient is shown in the room Details Panel.
+
+
+
+ Figure 35. A Successful Execution of allocateroom for Room Number
+
+1. If you do not see the success message as shown in Figure 35, please repeat step 2 onwards.
+
+_Written by: Ming De_
+
+#### 5.3.3 Search by Room Number: `searchroom`
+
+You can use this command to search for the room details with the specified room number.
+
+**Format:** `searchroom r/ROOM_NUMBER`
+
+Field | Description
+----------|-------------
+`ROOM_NUMBER` | The room number of the room to be searched for, which is a positive integer. The room number should be present in the list of rooms in Covigent.
+
+**Example(s):**
+1. `searchroom r/6` The room details of room number 6 will be searched.
+
+**Step By Step Usage:**
+1. Navigate to the Rooms tab under the navigation bar as shown in Figure 36.
+
+
+
+ Figure 36. Navigation to Rooms Tab
+
+1. Using the first example, key in the command into the Command Box as shown below.
+
+
+
+ Figure 37. searchroom Command in Command Box
+
+1. Press Enter to run the command.
+1. The Result Box displays the success message shown in Figure 38 and the room with the specified room number is shown in the room Details Panel.
+
+
+
+ Figure 38. A Successful Execution of searchroom for Room Number
+
+1. If you do not see the success message as shown in Figure 38, please repeat step 2 onwards.
+
+_Written by: Yun Qing_
+
+#### 5.3.4 Search for Room with Patient: `searchroom`
+
+You can use this command to search for the room that the specified patient is residing in.
+
+**Format:** `searchroom n/NAME`
+
+Field | Description
+----------|-------------
+`NAME` | The name of the patient whose room you are looking for. It is case-insensitive and must match exactly with the name of the patient that was input into Covigent previously.
+
+**Example(s):**
+1. `searchroom n/Mary Doe` The room details of the room that Mary Doe resides in will be searched.
+
+**Step By Step Usage:**
+1. Navigate to the Rooms tab under the navigation bar as shown in Figure 39.
+
+
+
+ Figure 39. Navigation to Rooms Tab
+
+1. Using the first example, key in the command into the Command Box as shown below.
+
+
+
+ Figure 40. searchroom Command in Command Box
+
+1. Press Enter to run the command.
+1. The Result Box displays the success message shown in Figure 41 and the room that the specified patient resides in is shown in the room Details Panel.
+
+
+
+ Figure 41. A Successful Execution of searchroom for Patient
+
+1. If you do not see the success message as shown in Figure 41, please repeat step 2 onwards.
+
+_Written by: Yun Qing_
+
+#### 5.3.5 List the Current Rooms: `listroom`
+
+You can use this command to list all the rooms in the hotel together with information of whether the room is occupied or not, provided there is at least one room defined
+
+Format: `listroom` All the rooms in Covigent.
+
+**Example(s):**
+1. `listroom` all the rooms will be listed
+2. `listroom abdcfbhfr` all rooms will be listed
+3. `listroom 21232198` all rooms will be listed
+4. `listroom 123ebhbh11` all rooms will be listed
+
+**:information_source: Important Information:**
+* If there are no rooms, then no rooms will be mentioned and informs user to initialize rooms using the `initroom` command.
+* You need at least one room for this command to work.
+
+
+**Step By Step Usage:**
+1. Navigate to Rooms tab under the navigation bar as shown in Figure 42
+
+
+
+ Figure 42. Navigation to Rooms Tab
+
+1. Next, type the command `listroom` in the Command Box as shown below
+
+
+
+ Figure 43. listroom Command in Command Box
+
+1. Press Enter to run the command
+1. The Result Box shows a success message "All rooms are listed."
+
+
+
+ Figure 44. A Successful Execution of listroom
+
+
+_Written by: Noorul Azlina_
+
+#### 5.3.6 Find the First Free Room: `findemptyroom`
+
+You can use this command to find the room with the lowest room number that is free for use.
+
+Format: `findemptyroom` The unoccupied room in Covigent with the lowest room number will be displayed on UI.
+
+**Example(s)**:
+1. `findemptyroom` gives room with the lowest room number
+2. `findemptyroom 238405` gives room with the lowest room number
+3. `findemptyroom ahfbhrf` gives room with the lowest room number
+4. `findemptyroom hsbf835dfj` gives room with the lowest room number
+
+**:information_source: Important Information:**
+* If there are no empty rooms then an error message informing hotel staff is mentioned.
+
+
+**Step By Step Usage:**
+
+1. Navigate to Rooms tab under the navigation bar as shown in Figure 45.
+
+
+
+ Figure 45. Navigation to Rooms Tab
+
+1. Next, type the command `findemptyroom` in the Command Box as shown below
+
+
+
+ Figure 46. findemptyroom Command in Command Box
+
+1. Press Enter to run the command
+1. The Result Box shows a success message that "Room Number 4 is empty"
+
+
+
+ Figure 47. A Successful Execution of findemptyroom
+
+
+_Written by: Noorul Azlina_
+
+### 5.4 Task
+
+This section contains all the commands related to tasks. You can [add](#541-add-a-task-to-a-room-addtask), [delete](#542-delete-a-task-from-a-room-deletetask),
+[edit](#543-edit-task-description-or-due-date-edittask) and [search](#545-search-tasks-before-a-given-date-searchtask) for a task in a room.
+If you want to see all the tasks, you can [list](#546-list-all-tasks-listtask) out all the tasks in Covigent. If you are unsure of how to interpret the command format, head back to [Command Format](#51-command-format) before executing the commands!
+
+#### 5.4.1 Add a Task to a Room: `addtask`
+
+You can use this command to add a task to a room. The task has the following details: description and due date.
+
+Format: `addtask r/ROOM_NUMBER d/DESCRIPTION [dd/DUE_DATE]`
+
+Field | Description
+------------ | -------------
+`ROOM_NUMBER` | The room number of the room to which you want to add the task. It refers to the number displayed beside each room under the list of rooms. An example of the room number highlighted in red:
+`DESCRIPTION` | The description of the task. It must be between 1 and 4000 characters long. Note that empty inputs such as multiple spaces are considered 0 characters and are not allowed. The description can be related to the patient in the room, e.g. _Call the patient_; or related to the room, e.g. _Restock the supplies in this room_.
+`DUE_DATE` | An optional field that is used to indicate by what date and time should the task be completed. It can in any of the following formats:
i) YYYYMMDD, e.g. `20210131`
ii) YYYYMMDD HHmm, e.g. `20210131 2359`
iii) D/M/YYYY, e.g. `31/1/2021` or `31/01/2021`
iv) D/M/YYYY HHmm, e.g. `31/1/2021 2359` or `31/01/2021 2359`
+
+**:information_source: Important Information:**
+* After you add a task successfully, the task will appear in both the room you have added it to, and also in the Tasks tab.
+* `DUE_DATE` defaults to `-` if you leave out the field, i.e. the task has no due date.
+* If you do not provide the time for a `DUE_DATE`, it defaults to 0000 (12am).
+
+
+**Example(s):**
+1. `addtask r/5 d/Running low on masks and needs to be restocked. dd/12/1/2021` A task with description _Running low on masks and needs to be restocked._ and due date _12 Jan 2021 0000_ is added to _Room #5_.
+1. `addtask r/1 d/Remind patient to change bedsheets.` A task with description _Remind patient to change bedsheets._ and no due date is added to _Room #1_.
+
+**Step By Step Usage:**
+1. Navigate to the Rooms tab under the navigation bar as shown in Figure 48.
+
+
+
+ Figure 48. Navigation to Rooms Tab
+
+1. For this example, the task will be added to _Room #5_. Please ensure there at least 5 rooms in Covigent, i.e. you can find _Room #5_ in the Rooms tab.
+ If you cannot find _Room #5_, do not worry. That means that the room has not been created yet. To create the rooms, please key in `initroom 5` into the Command Box.
+ For more details on creating room, refer to [Section 5.3.1, "Initialise Rooms in Hotel"](#531-initialise-rooms-in-hotel-initroom).
+1. Key the command into the Command Box as shown below.
+
+
+
+ Figure 49. addtask Command in Command Box
+
+1. Press Enter to run the command.
+1. The Result Box displays a success message. Click on _Room #5_ to view the newly added task. Refer to Figure 50 for the success message and to confirm that details of the task are displayed in the Details Panel.
+
+
+
+ Figure 50. A Successful Execution of addtask Command
+
+1. If you do not see the success message as shown in Figure 50, please check that there are at least 5 rooms in Covigent as per step 2, and that you have keyed in the command correctly as in step 3.
+
+_Written by: Yee Hong_
+
+#### 5.4.2 Delete a Task from a Room: `deletetask`
+
+You can use this command to delete an existing task from a room.
+
+Format: `deletetask r/ROOM_NUMBER t/TASK_NUMBER`
+
+Field | Description
+------------ | -------------
+`ROOM_NUMBER` | The room number of the room from which you want to delete the task. It refers to the number displayed beside each room under the list of rooms. An example of the room number highlighted in red:
+`TASK_NUMBER` | The task number of the task to be deleted. It refers to the number displayed beside each task in the Details Panel for rooms. An example of the task number highlighted in red:

Alternatively, you may find the task number in the Tasks tab. Here is the task number of the same task, but found in the Tasks tab:
+
+**:information_source: Important Information:**
+* After you delete a task successfully, the task will not only disappear from room it was in, but also from the Tasks tab.
+* Once you delete a task, the `TASK_NUMBER` of the remaining tasks changes accordingly. Figure 51 illustrates how _Task 3_ is updated to _Task 2_ after the original Task 2 is deleted.
+
+
+
+ Figure 51. Task Number Changing after deletetask
+
+
+
+**Example(s):**
+1. `deletetask r/5 t/1` The first task (_Task 1_) of _Room #5_ is deleted.
+
+**Step By Step Usage:**
+1. Navigate to the Rooms tab under the navigation bar as shown in Figure 52.
+
+
+
+ Figure 52. Navigation to Rooms Tab
+
+1. For this example, _Task 1_ of _Room #5_ is deleted. Please replace the `5` with the `ROOM_NUMBER` of the room containing the task and the `1` with the `TASK_NUMBER` of the task that you want to delete.
+1. Key the command into the Command Box as shown below, replacing `ROOM_NUMBER` and `TASK_NUMBER` as necessary.
+
+
+
+ Figure 53. deletetask Command in Command Box
+
+1. Press Enter to run the command.
+1. The Result Box displays a success message. You have successfully deleted _Task 1_ of _Room #5_ (see Figure 54).
+
+
+
+ Figure 54. A Successful Execution of deletetask Command
+
+1. If you do not see a success message similar to Figure 54, please check that you have entered the correct `ROOM_NUMBER` and `TASK_NUMBER`.
+
+_Written by: Yee Hong_
+
+#### 5.4.3 Edit Task Description or Due Date: `edittask`
+
+You can use this command to edit the description or due date of an existing task in a room.
+
+Format: `edittask r/ROOM_NUMBER t/TASK_NUMBER [d/DESCRIPTION] [dd/DUE_DATE]`
+
+Field | Description
+------------ | -------------
+`ROOM_NUMBER` | The room number of the room from which you want to edit the task. It refers to the number displayed beside each room under the list of rooms. An example of the room number highlighted in red:
+`TASK_NUMBER` | The task number of the task to be edited. It refers to the number displayed beside each task in the Details Panel for rooms. An example of the task number highlighted in red:

Alternatively, you may find the task number in the Tasks tab. Here is the task number of the same task, but found in the Tasks tab:
+`DESCRIPTION` | The description of the task. It must be between 1 and 4000 characters long. Note that empty inputs such as multiple spaces are considered 0 characters and are not allowed. The description can be related to the patient in the room, e.g. _Call the patient_; or related to the room, e.g. _Restock the supplies in this room_.
+`DUE_DATE` | An optional field that is used to indicate by what date and time should the task be completed. It can in any of the following formats:
i) YYYYMMDD, e.g. `20210131`
ii) YYYYMMDD HHmm, e.g. `20210131 2359`
iii) D/M/YYYY, e.g. `31/1/2021` or `31/01/2021`
iv) D/M/YYYY HHmm, e.g. `31/1/2021 2359` or `31/01/2021 2359`
+
+**:information_source: Important Information:**
+* At least one of the optional fields must be provided.
+* Existing values will be updated to the input values.
+* A task will not be edited if there are no changes to its description or due date.
+* If you do not provide the time for a `DUE_DATE`, it defaults to _0000_ (12am).
+
+
+**Example(s):**
+1. `edittask r/5 t/1 d/Return a call to the patient. dd/12/1/2021 1500` The description and due date of the first task (_Task 1_) in _Room #5_ are updated to _Return a call to the patient._ and _12 Jan 2021 1500_ respectively.
+1. `edittask r/2 t/2 dd/12/1/2021` The due date for the second task (_Task 2_) of _Room #2_ is updated to _12 Jan 2021 0000_. The description remains unchanged.
+
+**Step By Step Usage:**
+1. Navigate to the Rooms tab under the navigation bar as shown in Figure 55.
+
+
+
+ Figure 55. Navigation to Rooms Tab
+
+1. For this example, _Task 1_ of _Room #5_ is edited. Please replace the `5` with the `ROOM_NUMBER` of the room containing the task and the `1` with the `TASK_NUMBER` of the task that you want to edit.
+1. Key the command into the Command Box as shown below, replacing `ROOM_NUMBER`, `TASK_NUMBER`, `DESCRIPTION`, and `DUE_DATE` as necessary.
+
+
+
+ Figure 56. edittask Command to Edit Description and Due Date in Command Box
+
+1. Press Enter to run the command.
+1. The Result Box displays a success message. Click on _Room #5_ to view the edited task. Refer to Figure 57 for the success message and to confirm that details of the edited task are displayed in the Details Panel.
+
+
+
+ Figure 57. A Successful Execution of edittask Command to Edit Description and Due Date
+
+1. If you do not see a success message similar to Figure 57, please check that you have entered the correct `ROOM_NUMBER` and `TASK_NUMBER`, and at least one of the optional fields.
+
+_Written by: Yee Hong_
+
+#### 5.4.4 Remove Due Date from a Task: `edittask`
+
+You can use this command to remove a due date from a task in a room.
+
+Format: `edittask r/ROOM_NUMBER t/TASK_NUMBER dd/-`
+
+Field | Description
+------------ | -------------
+`ROOM_NUMBER` | The room number of the room from which you want to edit the task. It refers to the number displayed beside each room under the list of rooms. An example of the room number highlighted in red:
+`TASK_NUMBER` | The task number of the task to be edited. It refers to the number displayed beside each task in the Details Panel for rooms. An example of the task number highlighted in red:

Alternatively, you may find the task number in the Tasks tab. Here is the task number of the same task, but found in the Tasks tab:
+`-` | A `-` indicates the removal of a due date.
+
+**:information_source: Important Information:**
+* Existing values will be updated to the input values.
+* The due date of a task cannot be removed if it does not originally have a due date.
+* This is only one feature of the `edittask` command. Refer to the full command [here](#543-edit-task-description-or-due-date-edittask).
+
+
+**Example(s):**
+1. `edittask r/5 t/1 dd/-` The due date of the first task (_Task 1_) in Room #5 is removed, i.e. set to `-`.
+
+**Step By Step Usage:**
+1. Navigate to the Rooms tab under the navigation bar as shown in Figure 58.
+
+
+
+ Figure 58. Navigation to Rooms Tab
+
+1. For this example, the due date of _Task 1_ of _Room #5_ is removed. Please replace the `5` with the `ROOM_NUMBER` of the room containing the task and the `1` with the `TASK_NUMBER` of the task from which you want to remove the due date.
+1. Key the command into the Command Box as shown below, replacing `ROOM_NUMBER`, `TASK_NUMBER` as necessary.
+
+
+
+ Figure 59. edittask Command to Remove Due Date in Command Box
+
+1. Press Enter to run the command.
+1. The Result Box displays a success message. Click on _Room #5_ to view the edited task. Refer to Figure 57 for the success message and to confirm that details of the edited task are displayed in the Details Panel.
+
+
+
+ Figure 60. A Successful Execution of edittask Command to Remove Due Date
+
+1. If you do not see a success message similar to Figure 60, please check that you have entered the correct `ROOM_NUMBER` and `TASK_NUMBER`, and that the task you want to edit has a due date.
+
+_Written by: Yee Hong_
+
+#### 5.4.5 Search Tasks before a Given Date: `searchtask`
+
+You can use this command to search all tasks before a date in Covigent.
+
+**Format**: `searchtask dd/DUE_DATE`
+
+Field | Description
+----------|-------------
+`DUE_DATE` | The due date you are looking for. It can in any of the following formats:
i) YYYYMMDD, e.g. `20210131`
ii) YYYYMMDD HHmm, e.g. `20210131 2359`
iii) D/M/YYYY, e.g. `31/1/2021` or `31/01/2021`
iv) D/M/YYYY HHmm, e.g. `31/1/2021 2359` or `31/01/2021 2359`
+
+**:information_source: Important Information:**
+* If you do not provide the time for a `DUE_DATE`, it defaults to _0000_ (12am).
+
+
+**Example(s)**:
+1. `searchtask dd/12/1/2021` Search all tasks before and including 12 January 2021 0000.
+
+**Step By Step Usage:**
+1. Navigate to the Tasks tab under the navigation bar as shown in Figure 61.
+
+
+
+ Figure 61. Navigation to Tasks Tab
+
+1. Using the example, key in the command into the Command Box as shown below.
+
+
+
+ Figure 62. searchtask Command in Command Box
+
+1. Press Enter to run the command.
+1. With reference to Figure 63, the Result Box displays the message, "Tasks before the due date found.".
+1. Now you can find tasks before and including _12 Jan 2021 0000_ can now be found in the list of tasks in Covigent.
+
+
+
+ Figure 63. A Successful Execution of searchtask
+
+
+_Written by: Wai Lok_
+
+#### 5.4.6 List all Tasks: `listtask`
+
+You can use this command to look at the list of all tasks in the task tab.
+
+**Format**: `listtask`
+
+**Example(s)**:
+1. `listtask` Lists all tasks that are present in Covigent.
+
+**Step By Step Usage:**
+
+1. Navigate to the Tasks tab under the navigation bar as shown in Figure 64.
+
+
+
+ Figure 64. Navigation to Tasks tab
+
+1. Key in the command into the Command Box as shown below.
+
+
+
+ Figure 65. listtask Command in Command Box
+
+1. Press Enter to run the command.
+1. Now you can find the full list of patient in Covigent.
+
+
+
+ Figure 66. A Successful Execution of listtask
+
+
+_Written by: Wai Lok_
+
+### 5.5 View help: `help`
+
+If you encounter any issues using Covigent and need to access this user guide again, simply key in `help` into the Command Box.
+
+**Format:** `help`
+
+**Step By Step Usage:**
+
+1. Key in the command into the Command Box as shown below.
+
+
+
+ Figure 67. help Command in Command Box
+
+1. Press Enter to run the command.
+1. The Result Box displays the message as shown in Figure 68.
+
+
+
+ Figure 68. Result Display Box
+
+1. A new help window appears.
+
+
+
+ Figure 69. Help Window
+
+
+_Written by Yun Qing_
+
+### 5.6 Exit Covigent: `exit`
+
+You can use this command to exit from Covigent.
+
+**Format:** `exit`
+
+**Step By Step Usage:**
+1. Key in the command into the Command Box as shown below.
+
+
+
+ Figure 70. exit Command in Command Box
+
+1. Press Enter to run the command.
+1. Covigent exits and closes.
+
+_Written by: MingDe_
+
+### 5.7 Autosave
+
+Covigent data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually.
-**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.
--------------------------------------------------------------------------------------------------------------------
-## Command summary
+## 6. Command Summary
+
+This section provides a quick summary of the commands for [Patient](#61-patient), [Room](#62-room), [Task](#63-task) and [General](#64-general). For the detailed explanation of the usage of each command, head on to the [Features](#5-features) section to find out more.
+
+### 6.1 Patient
+
+Action | Format, Examples
+--------|------------------
+**Add Patient** | `addpatient n/NAME t/TEMPERATURE d/PERIOD_OF_STAY p/PHONE_NUMBER a/AGE [c/COMMENT]`
e.g., addpatient n/Betsy Crowe t/36.5 d/20201001-20201014 p/91234567 a/19 c/Is asthmatic
+**Delete Patient** | `deletepatient NAME`
e.g., deletepatient Mary Doe
+**Edit Patient** | `editpatient NAME [n/NAME] [t/TEMPERATURE] [d/PERIOD_OF_STAY] [p/PHONE_NUMBER] [a/AGE] [c/COMMENT]`
e.g., editpatient James Lee t/36.5
+**Search Patient** | `searchpatient [n/NAME] [tr/TEMPERATURE_RANGE]`
e.g., searchpatient tr/36.5-36.7
+**List Patients** | `listpatient`
+
+### 6.2 Room
+
+Action | Format, Examples
+--------|------------------
+**Initialise Room** | `initroom NUMBER_OF_ROOMS`
e.g., initroom 123
+**Allocate Patient to Room** | `allocateroom ROOM_NUMBER n/NAME`
e.g., allocateroom 5 n/David Li
+**Search by Room Number** | `searchroom r/ROOM_NUMBER`
e.g., searchroom r/15
+**Search for Room with Patient** | `searchroom n/NAME`
e.g., searchroom n/Jane Doe
+**List Rooms** | `listroom`
+**Find Empty Room** | `findemptyroom`
+
+### 6.3 Task
+
+Action | Format, Examples
+--------|------------------
+**Add Task to Room** | `addtask r/ROOM_NUMBER d/DESCRIPTION [dd/DUE_DATE]`
e.g., addtask d/Running low on masks and needs to be restocked. r/5 dd/12/1/2021
+**Delete Task from Room** | `deletetask r/ROOM_NUMBER t/TASK_NUMBER`
e.g., deletetask r/5 t/1
+**Edit Task Description or Due Date** | `edittask r/ROOM_NUMBER t/TASK_NUMBER [d/DESCRIPTION] [dd/DUE_DATE]`
e.g., edittask r/5 t/1 dd/12/1/2021 1500
+**Remove Due Date from a Task** | `edittask r/ROOM_NUMBER t/TASK_NUMBER dd/-`
e.g., edittask r/5 t/1 dd/-
+**Search Task** | `searchtask dd/DUE_DATE`
e.g., searchtask dd/12/1/2021
+**List Tasks** | `listtask`
+
+### 6.4 General
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`
-**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`
+
+_Written by: Yun Qing_
+
+--------------------------------------------------------------------------------------------------------------------
+
+## 7. FAQ
+
+**Q**: Why does the output sometimes appear red and sometimes black?
+**A**: If the command input is given in the wrong format, then the output is given in red. Also the correct format for the particular command is given.
+
+ Example:
+ Invalid command format!
+ Please give the number of digits in numbers
+ Example: addRooms 200
+
+**Q**: Will data be stored in the system after closing the app?
+**A**: The data is stored in the hard disk and therefore would not be deleted even if you close the app
+
+**Q**: How do I look at all the rooms and patient when only one is being displayed after commands such as `findroom`?
+**A**: Use the command `listroom` for rooms and `listpatient` for patients.
+
+**Q**: What should I do if nothing happens when I double click the Jar file?
+**A**: Open Terminal(Mac)/Command Prompt(Windows) . Type `cd [PATH TO DIRECTORY CONTAINING .JAR FILE]` . Type java `-jar covigent.jar` to run the application.
+
+_Written by: Noorul Azlina_
diff --git a/docs/_config.yml b/docs/_config.yml
index 6bd245d8f4e..c4a25e8a3a9 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -1,4 +1,4 @@
-title: "AB-3"
+title: "Covigent"
theme: minima
header_pages:
@@ -8,7 +8,7 @@ header_pages:
markdown: kramdown
-repository: "se-edu/addressbook-level3"
+repository: "AY2021S1-CS2103T-W12-1/tp"
github_icon: "images/github-icon.png"
plugins:
diff --git a/docs/diagrams/DeleteSequenceDiagram.puml b/docs/diagrams/DeleteSequenceDiagram.puml
deleted file mode 100644
index 1dc2311b245..00000000000
--- a/docs/diagrams/DeleteSequenceDiagram.puml
+++ /dev/null
@@ -1,69 +0,0 @@
-@startuml
-!include style.puml
-
-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
-end box
-
-box Model MODEL_COLOR_T1
-participant ":Model" as Model MODEL_COLOR
-end box
-
-[-> LogicManager : execute("delete 1")
-activate LogicManager
-
-LogicManager -> AddressBookParser : parseCommand("delete 1")
-activate AddressBookParser
-
-create DeleteCommandParser
-AddressBookParser -> DeleteCommandParser
-activate DeleteCommandParser
-
-DeleteCommandParser --> AddressBookParser
-deactivate DeleteCommandParser
-
-AddressBookParser -> DeleteCommandParser : parse("1")
-activate DeleteCommandParser
-
-create DeleteCommand
-DeleteCommandParser -> DeleteCommand
-activate DeleteCommand
-
-DeleteCommand --> DeleteCommandParser : d
-deactivate DeleteCommand
-
-DeleteCommandParser --> AddressBookParser : d
-deactivate DeleteCommandParser
-'Hidden arrow to position the destroy marker below the end of the activation bar.
-DeleteCommandParser -[hidden]-> AddressBookParser
-destroy DeleteCommandParser
-
-AddressBookParser --> LogicManager : d
-deactivate AddressBookParser
-
-LogicManager -> DeleteCommand : execute()
-activate DeleteCommand
-
-DeleteCommand -> Model : deletePerson(1)
-activate Model
-
-Model --> DeleteCommand
-deactivate Model
-
-create CommandResult
-DeleteCommand -> CommandResult
-activate CommandResult
-
-CommandResult --> DeleteCommand
-deactivate CommandResult
-
-DeleteCommand --> LogicManager : result
-deactivate DeleteCommand
-
-[<--LogicManager
-deactivate LogicManager
-@enduml
diff --git a/docs/diagrams/ModelClassDiagram.puml b/docs/diagrams/ModelClassDiagram.puml
deleted file mode 100644
index e85a00d4107..00000000000
--- a/docs/diagrams/ModelClassDiagram.puml
+++ /dev/null
@@ -1,56 +0,0 @@
-@startuml
-!include style.puml
-skinparam arrowThickness 1.1
-skinparam arrowColor MODEL_COLOR
-skinparam classBackgroundColor MODEL_COLOR
-
-Package Model <>{
-Interface ReadOnlyAddressBook <>
-Interface Model <>
-Interface ObservableList <>
-Class AddressBook
-Class ReadOnlyAddressBook
-Class Model
-Class ModelManager
-Class UserPrefs
-Class ReadOnlyUserPrefs
-
-Package Person {
-Class Person
-Class Address
-Class Email
-Class Name
-Class Phone
-Class UniquePersonList
-}
-
-Package Tag {
-Class Tag
-}
-}
-
-Class HiddenOutside #FFFFFF
-HiddenOutside ..> Model
-
-AddressBook .up.|> ReadOnlyAddressBook
-
-ModelManager .up.|> Model
-Model .right.> ObservableList
-ModelManager o--> "1" AddressBook
-ModelManager o-left-> "1" UserPrefs
-UserPrefs .up.|> ReadOnlyUserPrefs
-
-AddressBook *--> "1" UniquePersonList
-UniquePersonList o--> "*" Person
-Person *--> Name
-Person *--> Phone
-Person *--> Email
-Person *--> Address
-Person *--> "*" Tag
-
-Name -[hidden]right-> Phone
-Phone -[hidden]right-> Address
-Address -[hidden]right-> Email
-
-ModelManager -->"1" Person : filtered list
-@enduml
diff --git a/docs/diagrams/plantuml/AddPatientSequenceDiagram.puml b/docs/diagrams/plantuml/AddPatientSequenceDiagram.puml
new file mode 100644
index 00000000000..2bba66d0544
--- /dev/null
+++ b/docs/diagrams/plantuml/AddPatientSequenceDiagram.puml
@@ -0,0 +1,76 @@
+@startuml
+!include style.puml
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":CovigentAppParser" as CovigentAppParser LOGIC_COLOR
+participant ":AddPatientCommandParser" as AddPatientCommandParser LOGIC_COLOR
+participant "d:AddPatientCommand" as AddPatientCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("addpatient n/Alex a/36")
+activate LogicManager
+
+LogicManager -> CovigentAppParser : parseCommand("addpatient n/Alex a/36")
+activate CovigentAppParser
+
+create AddPatientCommandParser
+CovigentAppParser -> AddPatientCommandParser
+activate AddPatientCommandParser
+
+AddPatientCommandParser --> CovigentAppParser
+deactivate AddPatientCommandParser
+
+CovigentAppParser -> AddPatientCommandParser : parse("n/Alex a/36")
+activate AddPatientCommandParser
+
+create AddPatientCommand
+AddPatientCommandParser -> AddPatientCommand
+activate AddPatientCommand
+
+
+AddPatientCommand --> AddPatientCommandParser :
+deactivate AddPatientCommand
+
+AddPatientCommandParser --> CovigentAppParser :
+deactivate AddPatientCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+AddPatientCommandParser -[hidden]-> CovigentAppParser
+destroy AddPatientCommandParser
+
+CovigentAppParser --> LogicManager :
+deactivate CovigentAppParser
+
+LogicManager -> AddPatientCommand : execute()
+activate AddPatientCommand
+
+AddPatientCommand -> Model : hasPatient(Patient)
+activate Model
+
+Model --> AddPatientCommand
+deactivate Model
+
+AddPatientCommand -> Model : addPatient(Patient)
+activate Model
+
+Model --> AddPatientCommand
+deactivate Model
+
+create CommandResult
+AddPatientCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> AddPatientCommand
+deactivate CommandResult
+
+AddPatientCommand --> LogicManager : result
+deactivate AddPatientCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/plantuml/AllocateRoomActivityDiagram.puml b/docs/diagrams/plantuml/AllocateRoomActivityDiagram.puml
new file mode 100644
index 00000000000..5f0f90efacd
--- /dev/null
+++ b/docs/diagrams/plantuml/AllocateRoomActivityDiagram.puml
@@ -0,0 +1,34 @@
+@startuml
+skinparam activity {
+ BackgroundColor 176CC1
+ FontName Calibri
+ FontColor White
+ BorderColor 176CC1
+}
+
+skinparam activityDiamond {
+ BackgroundColor 176CC1
+ BorderColor 176CC1
+}
+
+start
+:user inputs allocateroom;
+
+'Since the beta syntax does not support placing the condition outside the
+'diamond we place it as the true branch instead.
+
+if () then (["-" is input as patient name])
+ if () then ([No Patient in Room])
+ :Show error message;
+ else ([else])
+ :Remove patient from room;
+ endif
+else ([else])
+ if () then ([Patient name is valid])
+ :Allocate patient to room;
+ else ([else])
+ :Show error message;
+ endif
+endif
+stop
+@enduml
diff --git a/docs/diagrams/plantuml/AllocateRoomSequenceDiagram.puml b/docs/diagrams/plantuml/AllocateRoomSequenceDiagram.puml
new file mode 100644
index 00000000000..2c561774c5d
--- /dev/null
+++ b/docs/diagrams/plantuml/AllocateRoomSequenceDiagram.puml
@@ -0,0 +1,70 @@
+@startuml
+!include style.puml
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":CovigentAppParser" as CovigentAppParser LOGIC_COLOR
+participant ":AllocateRoomCommandParser" as AllocateRoomCommandParser LOGIC_COLOR
+participant "d:AllocateRoomCommand" as AllocateRoomCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("allocateroom 1 n/Alex")
+activate LogicManager
+
+LogicManager -> CovigentAppParser : parseCommand("allocateroom 1 n/Alex")
+activate CovigentAppParser
+
+create AllocateRoomCommandParser
+CovigentAppParser -> AllocateRoomCommandParser
+activate AllocateRoomCommandParser
+
+AllocateRoomCommandParser --> CovigentAppParser
+deactivate AllocateRoomCommandParser
+
+CovigentAppParser -> AllocateRoomCommandParser : parse("1 n/Alex")
+activate AllocateRoomCommandParser
+
+create AllocateRoomCommand
+AllocateRoomCommandParser -> AllocateRoomCommand
+activate AllocateRoomCommand
+
+
+AllocateRoomCommand --> AllocateRoomCommandParser : d
+deactivate AllocateRoomCommand
+
+AllocateRoomCommandParser --> CovigentAppParser : d
+deactivate AllocateRoomCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+AllocateRoomCommandParser -[hidden]-> CovigentAppParser
+destroy AllocateRoomCommandParser
+
+CovigentAppParser --> LogicManager : d
+deactivate CovigentAppParser
+
+LogicManager -> AllocateRoomCommand : execute()
+activate AllocateRoomCommand
+
+AllocateRoomCommand -> Model : setSingleRoom(roomToEdit, editedRoom)
+activate Model
+
+Model --> AllocateRoomCommand
+deactivate Model
+
+create CommandResult
+AllocateRoomCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> AllocateRoomCommand
+deactivate CommandResult
+
+AllocateRoomCommand --> LogicManager : result
+deactivate AllocateRoomCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/ArchitectureDiagram.puml b/docs/diagrams/plantuml/ArchitectureDiagram.puml
similarity index 100%
rename from docs/diagrams/ArchitectureDiagram.puml
rename to docs/diagrams/plantuml/ArchitectureDiagram.puml
diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/plantuml/ArchitectureSequenceDiagram.puml
similarity index 74%
rename from docs/diagrams/ArchitectureSequenceDiagram.puml
rename to docs/diagrams/plantuml/ArchitectureSequenceDiagram.puml
index ef81d18c337..5377276a89a 100644
--- a/docs/diagrams/ArchitectureSequenceDiagram.puml
+++ b/docs/diagrams/plantuml/ArchitectureSequenceDiagram.puml
@@ -7,19 +7,19 @@ Participant ":Logic" as logic LOGIC_COLOR
Participant ":Model" as model MODEL_COLOR
Participant ":Storage" as storage STORAGE_COLOR
-user -[USER_COLOR]> ui : "delete 1"
+user -[USER_COLOR]> ui : "deletepatient Alex Yeoh"
activate ui UI_COLOR
-ui -[UI_COLOR]> logic : execute("delete 1")
+ui -[UI_COLOR]> logic : execute("deletepatient Alex Yeoh")
activate logic LOGIC_COLOR
-logic -[LOGIC_COLOR]> model : deletePerson(p)
+logic -[LOGIC_COLOR]> model : deletePatient(p)
activate model MODEL_COLOR
model -[MODEL_COLOR]-> logic
deactivate model
-logic -[LOGIC_COLOR]> storage : saveAddressBook(addressBook)
+logic -[LOGIC_COLOR]> storage : savePatientRecords(covigentApp)
activate storage STORAGE_COLOR
storage -[STORAGE_COLOR]> storage : Save to file
diff --git a/docs/diagrams/BetterModelClassDiagram.puml b/docs/diagrams/plantuml/BetterModelClassDiagram.puml
similarity index 100%
rename from docs/diagrams/BetterModelClassDiagram.puml
rename to docs/diagrams/plantuml/BetterModelClassDiagram.puml
diff --git a/docs/diagrams/CommitActivityDiagram.puml b/docs/diagrams/plantuml/CommitActivityDiagram.puml
similarity index 100%
rename from docs/diagrams/CommitActivityDiagram.puml
rename to docs/diagrams/plantuml/CommitActivityDiagram.puml
diff --git a/docs/diagrams/plantuml/DeletePatientSequenceDiagram.puml b/docs/diagrams/plantuml/DeletePatientSequenceDiagram.puml
new file mode 100644
index 00000000000..d6587324da7
--- /dev/null
+++ b/docs/diagrams/plantuml/DeletePatientSequenceDiagram.puml
@@ -0,0 +1,69 @@
+@startuml
+!include style.puml
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":CovigentAppParser" as CovigentAppParser LOGIC_COLOR
+participant ":DeletePatientCommandParser" as DeletePatientCommandParser LOGIC_COLOR
+participant "d:DeletePatientCommand" as DeletePatientCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("deletepatient alex")
+activate LogicManager
+
+LogicManager -> CovigentAppParser : parseCommand("deletepatient 1")
+activate CovigentAppParser
+
+create DeletePatientCommandParser
+CovigentAppParser -> DeletePatientCommandParser
+activate DeletePatientCommandParser
+
+DeletePatientCommandParser --> CovigentAppParser
+deactivate DeletePatientCommandParser
+
+CovigentAppParser -> DeletePatientCommandParser : parse("alex")
+activate DeletePatientCommandParser
+
+create DeletePatientCommand
+DeletePatientCommandParser -> DeletePatientCommand
+activate DeletePatientCommand
+
+DeletePatientCommand --> DeletePatientCommandParser : d
+deactivate DeletePatientCommand
+
+DeletePatientCommandParser --> CovigentAppParser : d
+deactivate DeletePatientCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+DeletePatientCommandParser -[hidden]-> CovigentAppParser
+destroy DeletePatientCommandParser
+
+CovigentAppParser --> LogicManager : d
+deactivate CovigentAppParser
+
+LogicManager -> DeletePatientCommand : execute()
+activate DeletePatientCommand
+
+DeletePatientCommand -> Model : deletePatient(alex)
+activate Model
+
+Model --> DeletePatientCommand
+deactivate Model
+
+create CommandResult
+DeletePatientCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> DeletePatientCommand
+deactivate CommandResult
+
+DeletePatientCommand --> LogicManager : result
+deactivate DeletePatientCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/plantuml/EditTaskSequenceDiagram.puml b/docs/diagrams/plantuml/EditTaskSequenceDiagram.puml
new file mode 100644
index 00000000000..7290f80ce6b
--- /dev/null
+++ b/docs/diagrams/plantuml/EditTaskSequenceDiagram.puml
@@ -0,0 +1,66 @@
+@startuml
+!include style.puml
+
+box Logic LOGIC_COLOR_T1
+participant ":EditTaskCommandParser" as EditTaskCommandParser LOGIC_COLOR
+participant ":EditTaskCommand" as EditTaskCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> EditTaskCommandParser : parse("r/2 t/1 d/HelloWorld")
+activate EditTaskCommandParser
+
+create EditTaskCommand
+EditTaskCommandParser -> EditTaskCommand
+activate EditTaskCommand
+
+EditTaskCommand --> EditTaskCommandParser
+deactivate EditTaskCommand
+
+[<-- EditTaskCommandParser
+deactivate EditTaskCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+EditTaskCommandParser -[hidden]->[
+destroy EditTaskCommandParser
+
+[-> EditTaskCommand : execute()
+activate EditTaskCommand
+
+EditTaskCommand -> Model : getRoomWithRoomNumber(2)
+activate Model
+
+Model --> EditTaskCommand : room2
+deactivate Model
+
+EditTaskCommand -> Model : getTaskFromRoomWithTaskIndex(1, room2)
+activate Model
+
+Model --> EditTaskCommand : task1OfRoom2
+deactivate Model
+
+EditTaskCommand -> EditTaskCommand : createEditedTask("HelloWorld")
+activate EditTaskCommand
+
+EditTaskCommand --> EditTaskCommand : editedTask
+deactivate EditTaskCommand
+
+EditTaskCommand -> Model : setTaskToRoom(task1OfRoom2, editedTask, room2)
+activate Model
+
+Model --> EditTaskCommand
+deactivate Model
+
+create CommandResult
+EditTaskCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> EditTaskCommand
+deactivate CommandResult
+
+[<-- EditTaskCommand : result
+deactivate EditTaskCommand
+@enduml
diff --git a/docs/diagrams/LogicClassDiagram.puml b/docs/diagrams/plantuml/LogicClassDiagram.puml
similarity index 91%
rename from docs/diagrams/LogicClassDiagram.puml
rename to docs/diagrams/plantuml/LogicClassDiagram.puml
index 016ef33e2e2..3174414507b 100644
--- a/docs/diagrams/LogicClassDiagram.puml
+++ b/docs/diagrams/plantuml/LogicClassDiagram.puml
@@ -8,7 +8,7 @@ package Logic {
package Parser {
Interface Parser <>
-Class AddressBookParser
+Class CovigentAppParser
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" CovigentAppParser
+CovigentAppParser .left.> XYZCommandParser: creates >
XYZCommandParser ..> XYZCommand : creates >
XYZCommandParser ..|> Parser
@@ -55,6 +55,7 @@ LogicManager --> Model
Command .right.> Model
note right of XYZCommand: XYZCommand = AddCommand, \nFindCommand, etc
+
Logic ..> CommandResult
LogicManager .down.> CommandResult
Command .up.> CommandResult
diff --git a/docs/diagrams/plantuml/ModelClassDiagram.puml b/docs/diagrams/plantuml/ModelClassDiagram.puml
new file mode 100644
index 00000000000..018e569ec79
--- /dev/null
+++ b/docs/diagrams/plantuml/ModelClassDiagram.puml
@@ -0,0 +1,39 @@
+@startuml
+!include style.puml
+skinparam arrowThickness 1.1
+skinparam arrowColor MODEL_COLOR
+skinparam classBackgroundColor MODEL_COLOR
+
+Package Model <>{
+Interface Model <>
+Class Model
+Class ModelManager
+Class UserPrefs
+Interface ReadOnlyUserPrefs<>
+
+Package PatientRecords {
+Class PatientRecords
+}
+
+Package RoomList {
+Class RoomList
+}
+
+Package RoomTaskRecords {
+Class RoomTaskRecords
+}
+}
+
+
+Class HiddenOutside #FFFFFF
+HiddenOutside ..> Model
+
+
+ModelManager .up.|> Model
+ModelManager o-left-> "1" UserPrefs
+ModelManager o--> "1" PatientRecords
+ModelManager o--> "1" RoomList
+ModelManager o--> "1" RoomTaskRecords
+UserPrefs .up.|> ReadOnlyUserPrefs
+
+@enduml
diff --git a/docs/diagrams/plantuml/PatientRecordsClassDiagram.puml b/docs/diagrams/plantuml/PatientRecordsClassDiagram.puml
new file mode 100644
index 00000000000..2d916bd2f26
--- /dev/null
+++ b/docs/diagrams/plantuml/PatientRecordsClassDiagram.puml
@@ -0,0 +1,43 @@
+@startuml
+!include style.puml
+skinparam arrowThickness 1.1
+skinparam arrowColor MODEL_COLOR
+skinparam classBackgroundColor MODEL_COLOR
+
+Package PatientRecords <>{
+Class PatientRecords
+Interface ReadOnlyList <>
+
+Package Patient {
+Class Patient
+Class Name
+Class Phone
+Class Age
+Class PeriodOfStay
+Class Temperature
+Class Comment
+Class UniquePatientList
+}
+}
+
+Class HiddenOutside #FFFFFF
+HiddenOutside ..> PatientRecords
+
+PatientRecords .left.|> ReadOnlyList
+
+PatientRecords *--> "1" UniquePatientList
+UniquePatientList o--> "*" Patient
+Patient *--> "1" Name
+Patient *--> "1" Phone
+Patient *--> "1" Age
+Patient *--> "1" PeriodOfStay
+Patient *--> "1" Temperature
+Patient *--> "0..1" Comment
+
+Name -[hidden]right-> Phone
+Phone -[hidden]right-> Age
+Age -[hidden]right-> PeriodOfStay
+PeriodOfStay -[hidden]right->Temperature
+Temperature -[hidden]right->Comment
+
+@enduml
diff --git a/docs/diagrams/plantuml/RoomListClassDiagram.puml b/docs/diagrams/plantuml/RoomListClassDiagram.puml
new file mode 100644
index 00000000000..ea12c9f1297
--- /dev/null
+++ b/docs/diagrams/plantuml/RoomListClassDiagram.puml
@@ -0,0 +1,41 @@
+@startuml
+!include style.puml
+skinparam arrowThickness 1.1
+skinparam arrowColor MODEL_COLOR
+skinparam classBackgroundColor MODEL_COLOR
+
+Package RoomList <> {
+Class RoomList
+Interface ReadOnlyList<>
+
+Package Room {
+Class Room
+Class UniqueRoomList
+Class Patient
+Class RoomTasks
+
+Package Task {
+Class Task
+Class DateTimeDue
+Class Description
+Class TaskList
+}
+}
+}
+
+Class HiddenOutside #FFFFFF
+HiddenOutside ..> RoomList
+
+RoomList .left.|> ReadOnlyList
+RoomList *--> "1" UniqueRoomList
+UniqueRoomList o--> "*" Room
+Room *--> "0..1" Patient
+Room *--> "1" RoomTasks
+RoomTasks .left.|> ReadOnlyList
+
+RoomTasks *--> "1" TaskList
+TaskList o--> "*" Task
+Task *--> "1" Description
+Task *--> "0..1" DateTimeDue
+
+@enduml
diff --git a/docs/diagrams/plantuml/RoomTaskRecordsClassDiagram.puml b/docs/diagrams/plantuml/RoomTaskRecordsClassDiagram.puml
new file mode 100644
index 00000000000..2f24e696e18
--- /dev/null
+++ b/docs/diagrams/plantuml/RoomTaskRecordsClassDiagram.puml
@@ -0,0 +1,25 @@
+@startuml
+!include style.puml
+skinparam arrowThickness 1.1
+skinparam arrowColor MODEL_COLOR
+skinparam classBackgroundColor MODEL_COLOR
+
+Package RoomTaskRecords <>{
+
+Class RoomTaskRecords
+Interface ReadOnlyList <>
+
+Package RoomTaskRecords {
+Class RoomTaskRecords
+Class RoomTaskAssociation
+Class Task
+Class Room
+}
+
+RoomTaskRecords .left.|> ReadOnlyList
+
+RoomTaskRecords *--> "*" RoomTaskAssociation
+
+RoomTaskAssociation *-->"1" Task
+RoomTaskAssociation *--> "1" Room
+@enduml
diff --git a/docs/diagrams/StorageClassDiagram.puml b/docs/diagrams/plantuml/StorageClassDiagram.puml
similarity index 100%
rename from docs/diagrams/StorageClassDiagram.puml
rename to docs/diagrams/plantuml/StorageClassDiagram.puml
diff --git a/docs/diagrams/plantuml/TaskAlternativeClassDiagram.puml b/docs/diagrams/plantuml/TaskAlternativeClassDiagram.puml
new file mode 100644
index 00000000000..d1bfaf9601d
--- /dev/null
+++ b/docs/diagrams/plantuml/TaskAlternativeClassDiagram.puml
@@ -0,0 +1,35 @@
+@startuml
+!include style.puml
+skinparam arrowThickness 1.1
+skinparam arrowColor MODEL_COLOR
+skinparam classBackgroundColor MODEL_COLOR
+
+Interface ReadOnlyList <> {
+ getReadOnlyList(): ObservableList
+}
+
+Package Room <> {
+ Class Room {
+ +addtask(Task)
+ +deleteTask(Task)
+ +setTask(Task, editedTask: Task)
+ }
+}
+
+Package Task <> {
+ Class Task
+ Class TaskList
+ Class Description
+ Class DateTimeDue
+}
+
+TaskList -.|> ReadOnlyList
+
+Room *--r> "1" TaskList
+TaskList *--> "*" Task
+Task *--> "1" Description
+Task *--> "0..1" DateTimeDue
+
+Description -[hidden]right-> DateTimeDue
+
+@enduml
diff --git a/docs/diagrams/plantuml/TaskClassDiagram.puml b/docs/diagrams/plantuml/TaskClassDiagram.puml
new file mode 100644
index 00000000000..ee1748df62b
--- /dev/null
+++ b/docs/diagrams/plantuml/TaskClassDiagram.puml
@@ -0,0 +1,38 @@
+@startuml
+!include style.puml
+skinparam arrowThickness 1.1
+skinparam arrowColor MODEL_COLOR
+skinparam classBackgroundColor MODEL_COLOR
+
+Interface ReadOnlyList <> {
+ getReadOnlyList(): ObservableList
+}
+
+Package Room <> {
+ Class Room
+ Class RoomTasks {
+ +addTask(Task)
+ +removeTask(Task)
+ +setTask(Task, editedTask: Task)
+ }
+}
+
+Room *--r> "1" RoomTasks
+RoomTasks -.|> ReadOnlyList
+
+Package Task <> {
+ Class Task
+ Class TaskList
+ Class Description
+ Class DateTimeDue
+}
+
+RoomTasks ..> Task
+RoomTasks *--l> "1" TaskList
+TaskList *--> "*" Task
+Task *--> "1" Description
+Task *--> "0..1" DateTimeDue
+
+Description -[hidden]right-> DateTimeDue
+
+@enduml
diff --git a/docs/diagrams/UiClassDiagram.puml b/docs/diagrams/plantuml/UiClassDiagram.puml
similarity index 55%
rename from docs/diagrams/UiClassDiagram.puml
rename to docs/diagrams/plantuml/UiClassDiagram.puml
index 92746f9fcf7..c4d3028b0a3 100644
--- a/docs/diagrams/UiClassDiagram.puml
+++ b/docs/diagrams/plantuml/UiClassDiagram.puml
@@ -11,15 +11,18 @@ Class UiManager
Class MainWindow
Class HelpWindow
Class ResultDisplay
-Class PersonListPanel
-Class PersonCard
+Class PatientListPanel
+Class RoomListPanel
+Class RoomDetailsPanel
+Class RoomTaskListPanel
+Class RoomTaskDetailsPanel
+Class TaskCard
+Class RoomCard
+Class PatientCard
Class StatusBarFooter
Class CommandBox
}
-package Model <> {
-Class HiddenModel #FFFFFF
-}
package Logic <> {
Class HiddenLogic #FFFFFF
@@ -33,25 +36,36 @@ UiManager -down-> MainWindow
MainWindow --> HelpWindow
MainWindow *-down-> CommandBox
MainWindow *-down-> ResultDisplay
-MainWindow *-down-> PersonListPanel
+MainWindow *-down-> PatientListPanel
+MainWindow *-down-> RoomTaskListPanel
+MainWindow *-down-> RoomListPanel
MainWindow *-down-> StatusBarFooter
-PersonListPanel -down-> PersonCard
+PatientListPanel .right-> PatientCard : defined by >
+RoomTaskListPanel *.left-> TaskCard : defined by >
+RoomTaskListPanel *.right-> RoomTaskDetailsPanel : defined by >
+RoomListPanel *.left-> RoomCard : defined by >
+RoomListPanel *.right-> RoomDetailsPanel : defined by >
MainWindow -left-|> UiPart
ResultDisplay --|> UiPart
CommandBox --|> UiPart
-PersonListPanel --|> UiPart
-PersonCard --|> UiPart
+RoomDetailsPanel --|> UiPart
+RoomCard --|> UiPart
+TaskCard --|> UiPart
+PatientListPanel --|> UiPart
+RoomListPanel --|> UiPart
+RoomTaskListPanel --|> UiPart
+PatientCard --|> UiPart
StatusBarFooter --|> UiPart
HelpWindow -down-|> UiPart
-PersonCard ..> Model
UiManager -right-> Logic
MainWindow -left-> Logic
-PersonListPanel -[hidden]left- HelpWindow
+
+PatientListPanel -[hidden]left- HelpWindow
HelpWindow -[hidden]left- CommandBox
CommandBox -[hidden]left- ResultDisplay
ResultDisplay -[hidden]left- StatusBarFooter
diff --git a/docs/diagrams/plantuml/UiClassDiagram1.puml b/docs/diagrams/plantuml/UiClassDiagram1.puml
new file mode 100644
index 00000000000..3185e022291
--- /dev/null
+++ b/docs/diagrams/plantuml/UiClassDiagram1.puml
@@ -0,0 +1,25 @@
+@startuml
+!include style.puml
+skinparam arrowThickness 1.1
+skinparam arrowColor UI_COLOR_T4
+skinparam classBackgroundColor UI_COLOR
+
+package UI <>{
+Class RoomCard
+Class TaskCard
+Class PatientCard
+}
+
+
+package Model <> {
+Class HiddenLogic #FFFFFF
+}
+
+
+
+RoomCard -down-> Model
+TaskCard -down-> Model
+PatientCard -down-> Model
+
+Model -[hidden]left- UI
+@enduml
diff --git a/docs/diagrams/UndoRedoState0.puml b/docs/diagrams/plantuml/UndoRedoState0.puml
similarity index 100%
rename from docs/diagrams/UndoRedoState0.puml
rename to docs/diagrams/plantuml/UndoRedoState0.puml
diff --git a/docs/diagrams/UndoRedoState1.puml b/docs/diagrams/plantuml/UndoRedoState1.puml
similarity index 100%
rename from docs/diagrams/UndoRedoState1.puml
rename to docs/diagrams/plantuml/UndoRedoState1.puml
diff --git a/docs/diagrams/UndoRedoState2.puml b/docs/diagrams/plantuml/UndoRedoState2.puml
similarity index 100%
rename from docs/diagrams/UndoRedoState2.puml
rename to docs/diagrams/plantuml/UndoRedoState2.puml
diff --git a/docs/diagrams/UndoRedoState3.puml b/docs/diagrams/plantuml/UndoRedoState3.puml
similarity index 100%
rename from docs/diagrams/UndoRedoState3.puml
rename to docs/diagrams/plantuml/UndoRedoState3.puml
diff --git a/docs/diagrams/UndoRedoState4.puml b/docs/diagrams/plantuml/UndoRedoState4.puml
similarity index 100%
rename from docs/diagrams/UndoRedoState4.puml
rename to docs/diagrams/plantuml/UndoRedoState4.puml
diff --git a/docs/diagrams/UndoRedoState5.puml b/docs/diagrams/plantuml/UndoRedoState5.puml
similarity index 100%
rename from docs/diagrams/UndoRedoState5.puml
rename to docs/diagrams/plantuml/UndoRedoState5.puml
diff --git a/docs/diagrams/UndoSequenceDiagram.puml b/docs/diagrams/plantuml/UndoSequenceDiagram.puml
similarity index 100%
rename from docs/diagrams/UndoSequenceDiagram.puml
rename to docs/diagrams/plantuml/UndoSequenceDiagram.puml
diff --git a/docs/diagrams/style.puml b/docs/diagrams/plantuml/style.puml
similarity index 95%
rename from docs/diagrams/style.puml
rename to docs/diagrams/plantuml/style.puml
index fad8b0adeaa..93690b421ce 100644
--- a/docs/diagrams/style.puml
+++ b/docs/diagrams/plantuml/style.puml
@@ -38,6 +38,8 @@ skinparam BackgroundColor #FFFFFFF
skinparam Shadowing false
skinparam Class {
+ AttributeFontColor #FFFFFF
+ AttributeIconSize 0
FontColor #FFFFFF
BorderThickness 1
BorderColor #FFFFFF
@@ -71,5 +73,5 @@ skinparam DefaultTextAlignment center
skinparam packageStyle Rectangle
hide footbox
-hide members
+hide empty members
hide circle
diff --git a/docs/images/ArchitectureSequenceDiagram.png b/docs/images/ArchitectureSequenceDiagram.png
deleted file mode 100644
index 2f1346869d0..00000000000
Binary files a/docs/images/ArchitectureSequenceDiagram.png and /dev/null differ
diff --git a/docs/images/DeleteSequenceDiagram.png b/docs/images/DeleteSequenceDiagram.png
deleted file mode 100644
index fa327b39618..00000000000
Binary files a/docs/images/DeleteSequenceDiagram.png and /dev/null differ
diff --git a/docs/images/LogicClassDiagram.png b/docs/images/LogicClassDiagram.png
deleted file mode 100644
index b9e853cef12..00000000000
Binary files a/docs/images/LogicClassDiagram.png and /dev/null differ
diff --git a/docs/images/ModelClassDiagram.png b/docs/images/ModelClassDiagram.png
deleted file mode 100644
index 280064118cf..00000000000
Binary files a/docs/images/ModelClassDiagram.png and /dev/null differ
diff --git a/docs/images/Ui.png b/docs/images/Ui.png
index 5bd77847aa2..3f36fa47c69 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
deleted file mode 100644
index 7b4b3dbea45..00000000000
Binary files a/docs/images/UiClassDiagram.png and /dev/null differ
diff --git a/docs/images/chiamyunqing.png b/docs/images/chiamyunqing.png
new file mode 100644
index 00000000000..731dde15b8f
Binary files /dev/null and b/docs/images/chiamyunqing.png differ
diff --git a/docs/images/dg/ActivityDiagramForInitRoom.png b/docs/images/dg/ActivityDiagramForInitRoom.png
new file mode 100644
index 00000000000..b2187b51f37
Binary files /dev/null and b/docs/images/dg/ActivityDiagramForInitRoom.png differ
diff --git a/docs/images/dg/ActivityDiagramForRoomFeature.png b/docs/images/dg/ActivityDiagramForRoomFeature.png
new file mode 100644
index 00000000000..fa53addb648
Binary files /dev/null and b/docs/images/dg/ActivityDiagramForRoomFeature.png differ
diff --git a/docs/images/dg/AddPatientSequenceDiagram.png b/docs/images/dg/AddPatientSequenceDiagram.png
new file mode 100644
index 00000000000..4e59fb3f95b
Binary files /dev/null and b/docs/images/dg/AddPatientSequenceDiagram.png differ
diff --git a/docs/images/dg/AllocateRoomActivityDiagram.png b/docs/images/dg/AllocateRoomActivityDiagram.png
new file mode 100644
index 00000000000..0b0fc8f29e7
Binary files /dev/null and b/docs/images/dg/AllocateRoomActivityDiagram.png differ
diff --git a/docs/images/dg/AllocateRoomSequenceDiagram.png b/docs/images/dg/AllocateRoomSequenceDiagram.png
new file mode 100644
index 00000000000..a9b641f0dfe
Binary files /dev/null and b/docs/images/dg/AllocateRoomSequenceDiagram.png differ
diff --git a/docs/images/ArchitectureDiagram.png b/docs/images/dg/ArchitectureDiagram.png
similarity index 100%
rename from docs/images/ArchitectureDiagram.png
rename to docs/images/dg/ArchitectureDiagram.png
diff --git a/docs/images/dg/ArchitectureSequenceDiagram.png b/docs/images/dg/ArchitectureSequenceDiagram.png
new file mode 100644
index 00000000000..49bd8e47495
Binary files /dev/null and b/docs/images/dg/ArchitectureSequenceDiagram.png differ
diff --git a/docs/images/BetterModelClassDiagram.png b/docs/images/dg/BetterModelClassDiagram.png
similarity index 100%
rename from docs/images/BetterModelClassDiagram.png
rename to docs/images/dg/BetterModelClassDiagram.png
diff --git a/docs/images/CommitActivityDiagram.png b/docs/images/dg/CommitActivityDiagram.png
similarity index 100%
rename from docs/images/CommitActivityDiagram.png
rename to docs/images/dg/CommitActivityDiagram.png
diff --git a/docs/images/dg/DeletePatientSequenceDiagram.png b/docs/images/dg/DeletePatientSequenceDiagram.png
new file mode 100644
index 00000000000..d3802b9b5c0
Binary files /dev/null and b/docs/images/dg/DeletePatientSequenceDiagram.png differ
diff --git a/docs/images/dg/EditTaskSequenceDiagram.png b/docs/images/dg/EditTaskSequenceDiagram.png
new file mode 100644
index 00000000000..fb2a0acf460
Binary files /dev/null and b/docs/images/dg/EditTaskSequenceDiagram.png differ
diff --git a/docs/images/dg/JsonSerializablePatientList.png b/docs/images/dg/JsonSerializablePatientList.png
new file mode 100644
index 00000000000..cc4a84ea4ee
Binary files /dev/null and b/docs/images/dg/JsonSerializablePatientList.png differ
diff --git a/docs/images/dg/JsonSerializablePatientRecords.png b/docs/images/dg/JsonSerializablePatientRecords.png
new file mode 100644
index 00000000000..4e5e49e289c
Binary files /dev/null and b/docs/images/dg/JsonSerializablePatientRecords.png differ
diff --git a/docs/images/dg/JsonSerializableRoomList.png b/docs/images/dg/JsonSerializableRoomList.png
new file mode 100644
index 00000000000..1eaa4a93b3e
Binary files /dev/null and b/docs/images/dg/JsonSerializableRoomList.png differ
diff --git a/docs/images/dg/JsonSerializableRoomRecords.png b/docs/images/dg/JsonSerializableRoomRecords.png
new file mode 100644
index 00000000000..4be3e9b7221
Binary files /dev/null and b/docs/images/dg/JsonSerializableRoomRecords.png differ
diff --git a/docs/images/dg/JsonSerializableTaskList.png b/docs/images/dg/JsonSerializableTaskList.png
new file mode 100644
index 00000000000..a37711964f8
Binary files /dev/null and b/docs/images/dg/JsonSerializableTaskList.png differ
diff --git a/docs/images/dg/LogicClassDiagram.png b/docs/images/dg/LogicClassDiagram.png
new file mode 100644
index 00000000000..0e2452b57b8
Binary files /dev/null and b/docs/images/dg/LogicClassDiagram.png differ
diff --git a/docs/images/LogicStorageDIP.png b/docs/images/dg/LogicStorageDIP.png
similarity index 100%
rename from docs/images/LogicStorageDIP.png
rename to docs/images/dg/LogicStorageDIP.png
diff --git a/docs/images/dg/ModelClassDiagram.png b/docs/images/dg/ModelClassDiagram.png
new file mode 100644
index 00000000000..12055ea9523
Binary files /dev/null and b/docs/images/dg/ModelClassDiagram.png differ
diff --git a/docs/images/dg/PatientClassDiagram.png b/docs/images/dg/PatientClassDiagram.png
new file mode 100644
index 00000000000..c89d8e0f802
Binary files /dev/null and b/docs/images/dg/PatientClassDiagram.png differ
diff --git a/docs/images/dg/PatientRecordsClassDiagram.png b/docs/images/dg/PatientRecordsClassDiagram.png
new file mode 100644
index 00000000000..2d7728823bd
Binary files /dev/null and b/docs/images/dg/PatientRecordsClassDiagram.png differ
diff --git a/docs/images/dg/RoomListClassDiagram.png b/docs/images/dg/RoomListClassDiagram.png
new file mode 100644
index 00000000000..ef0f6f95a46
Binary files /dev/null and b/docs/images/dg/RoomListClassDiagram.png differ
diff --git a/docs/images/dg/RoomTaskRecordsClassDiagram.png b/docs/images/dg/RoomTaskRecordsClassDiagram.png
new file mode 100644
index 00000000000..e5de8b9c416
Binary files /dev/null and b/docs/images/dg/RoomTaskRecordsClassDiagram.png differ
diff --git a/docs/images/dg/RoomTaskRecordsClassDiagrams.png b/docs/images/dg/RoomTaskRecordsClassDiagrams.png
new file mode 100644
index 00000000000..e62652ac607
Binary files /dev/null and b/docs/images/dg/RoomTaskRecordsClassDiagrams.png differ
diff --git a/docs/images/dg/Room_SequenceDiagram.png b/docs/images/dg/Room_SequenceDiagram.png
new file mode 100644
index 00000000000..28bdc09c0a2
Binary files /dev/null and b/docs/images/dg/Room_SequenceDiagram.png differ
diff --git a/docs/images/dg/SequenceDiagramForInitRoom.png b/docs/images/dg/SequenceDiagramForInitRoom.png
new file mode 100644
index 00000000000..b59199ac765
Binary files /dev/null and b/docs/images/dg/SequenceDiagramForInitRoom.png differ
diff --git a/docs/images/StorageClassDiagram.png b/docs/images/dg/StorageClassDiagram.png
similarity index 100%
rename from docs/images/StorageClassDiagram.png
rename to docs/images/dg/StorageClassDiagram.png
diff --git a/docs/images/dg/TaskAlternativeClassDiagram.png b/docs/images/dg/TaskAlternativeClassDiagram.png
new file mode 100644
index 00000000000..9072679c0e2
Binary files /dev/null and b/docs/images/dg/TaskAlternativeClassDiagram.png differ
diff --git a/docs/images/dg/TaskClassDiagram.png b/docs/images/dg/TaskClassDiagram.png
new file mode 100644
index 00000000000..2b985621445
Binary files /dev/null and b/docs/images/dg/TaskClassDiagram.png differ
diff --git a/docs/images/dg/UML_Diagram_StorageManager.png b/docs/images/dg/UML_Diagram_StorageManager.png
new file mode 100644
index 00000000000..e251503e7a5
Binary files /dev/null and b/docs/images/dg/UML_Diagram_StorageManager.png differ
diff --git a/docs/images/dg/UML_RoomFeature.png b/docs/images/dg/UML_RoomFeature.png
new file mode 100644
index 00000000000..26bf47261cf
Binary files /dev/null and b/docs/images/dg/UML_RoomFeature.png differ
diff --git a/docs/images/dg/UML_Storage_Diagram.png b/docs/images/dg/UML_Storage_Diagram.png
new file mode 100644
index 00000000000..6f5d211b05b
Binary files /dev/null and b/docs/images/dg/UML_Storage_Diagram.png differ
diff --git a/docs/images/dg/UiClassDiagram.png b/docs/images/dg/UiClassDiagram.png
new file mode 100644
index 00000000000..f42ca39f859
Binary files /dev/null and b/docs/images/dg/UiClassDiagram.png differ
diff --git a/docs/images/dg/UiClassDiagram1.png b/docs/images/dg/UiClassDiagram1.png
new file mode 100644
index 00000000000..da9937f0fbb
Binary files /dev/null and b/docs/images/dg/UiClassDiagram1.png differ
diff --git a/docs/images/UndoRedoState0.png b/docs/images/dg/UndoRedoState0.png
similarity index 100%
rename from docs/images/UndoRedoState0.png
rename to docs/images/dg/UndoRedoState0.png
diff --git a/docs/images/UndoRedoState1.png b/docs/images/dg/UndoRedoState1.png
similarity index 100%
rename from docs/images/UndoRedoState1.png
rename to docs/images/dg/UndoRedoState1.png
diff --git a/docs/images/UndoRedoState2.png b/docs/images/dg/UndoRedoState2.png
similarity index 100%
rename from docs/images/UndoRedoState2.png
rename to docs/images/dg/UndoRedoState2.png
diff --git a/docs/images/UndoRedoState3.png b/docs/images/dg/UndoRedoState3.png
similarity index 100%
rename from docs/images/UndoRedoState3.png
rename to docs/images/dg/UndoRedoState3.png
diff --git a/docs/images/UndoRedoState4.png b/docs/images/dg/UndoRedoState4.png
similarity index 100%
rename from docs/images/UndoRedoState4.png
rename to docs/images/dg/UndoRedoState4.png
diff --git a/docs/images/UndoRedoState5.png b/docs/images/dg/UndoRedoState5.png
similarity index 100%
rename from docs/images/UndoRedoState5.png
rename to docs/images/dg/UndoRedoState5.png
diff --git a/docs/images/UndoSequenceDiagram.png b/docs/images/dg/UndoSequenceDiagram.png
similarity index 100%
rename from docs/images/UndoSequenceDiagram.png
rename to docs/images/dg/UndoSequenceDiagram.png
diff --git a/docs/images/dg/storage.png b/docs/images/dg/storage.png
new file mode 100644
index 00000000000..749d73a3d62
Binary files /dev/null and b/docs/images/dg/storage.png differ
diff --git a/docs/images/findAlexDavidResult.png b/docs/images/findAlexDavidResult.png
deleted file mode 100644
index 235da1c273e..00000000000
Binary files a/docs/images/findAlexDavidResult.png and /dev/null differ
diff --git a/docs/images/itssodium.png b/docs/images/itssodium.png
new file mode 100644
index 00000000000..23b095b9d41
Binary files /dev/null and b/docs/images/itssodium.png differ
diff --git a/docs/images/leemingde.png b/docs/images/leemingde.png
new file mode 100644
index 00000000000..87540cd1970
Binary files /dev/null and b/docs/images/leemingde.png differ
diff --git a/docs/images/raymondge.png b/docs/images/raymondge.png
new file mode 100644
index 00000000000..2e0824346f1
Binary files /dev/null and b/docs/images/raymondge.png differ
diff --git a/docs/images/ug/f10_addpatientexample.png b/docs/images/ug/f10_addpatientexample.png
new file mode 100644
index 00000000000..55613d112fa
Binary files /dev/null and b/docs/images/ug/f10_addpatientexample.png differ
diff --git a/docs/images/ug/f11_findemptyroomexample.png b/docs/images/ug/f11_findemptyroomexample.png
new file mode 100644
index 00000000000..3b16b7740ca
Binary files /dev/null and b/docs/images/ug/f11_findemptyroomexample.png differ
diff --git a/docs/images/ug/f12_allocateroomexample.png b/docs/images/ug/f12_allocateroomexample.png
new file mode 100644
index 00000000000..70ed7df1ce3
Binary files /dev/null and b/docs/images/ug/f12_allocateroomexample.png differ
diff --git a/docs/images/ug/f13_addtaskexample.png b/docs/images/ug/f13_addtaskexample.png
new file mode 100644
index 00000000000..3763c6d289e
Binary files /dev/null and b/docs/images/ug/f13_addtaskexample.png differ
diff --git a/docs/images/ug/f15_addpatientcommand.png b/docs/images/ug/f15_addpatientcommand.png
new file mode 100644
index 00000000000..84a03311e00
Binary files /dev/null and b/docs/images/ug/f15_addpatientcommand.png differ
diff --git a/docs/images/ug/f16_addpatientsuccess.png b/docs/images/ug/f16_addpatientsuccess.png
new file mode 100644
index 00000000000..90d40f78f77
Binary files /dev/null and b/docs/images/ug/f16_addpatientsuccess.png differ
diff --git a/docs/images/ug/f18_deletepatientcommand.png b/docs/images/ug/f18_deletepatientcommand.png
new file mode 100644
index 00000000000..bffb9ee778d
Binary files /dev/null and b/docs/images/ug/f18_deletepatientcommand.png differ
diff --git a/docs/images/ug/f19_deletepatientsuccess.png b/docs/images/ug/f19_deletepatientsuccess.png
new file mode 100644
index 00000000000..8a38fdb2651
Binary files /dev/null and b/docs/images/ug/f19_deletepatientsuccess.png differ
diff --git a/docs/images/ug/f1_ui.png b/docs/images/ug/f1_ui.png
new file mode 100644
index 00000000000..afac4339df1
Binary files /dev/null and b/docs/images/ug/f1_ui.png differ
diff --git a/docs/images/ug/f21_editpatientcommand.png b/docs/images/ug/f21_editpatientcommand.png
new file mode 100644
index 00000000000..9ec5286882e
Binary files /dev/null and b/docs/images/ug/f21_editpatientcommand.png differ
diff --git a/docs/images/ug/f22_editpatientsuccess.PNG b/docs/images/ug/f22_editpatientsuccess.PNG
new file mode 100644
index 00000000000..e8d16b792f6
Binary files /dev/null and b/docs/images/ug/f22_editpatientsuccess.PNG differ
diff --git a/docs/images/ug/f24_patientuibeforesearch.PNG b/docs/images/ug/f24_patientuibeforesearch.PNG
new file mode 100644
index 00000000000..9b60f24a8cb
Binary files /dev/null and b/docs/images/ug/f24_patientuibeforesearch.PNG differ
diff --git a/docs/images/ug/f25_searchpatientcommand.PNG b/docs/images/ug/f25_searchpatientcommand.PNG
new file mode 100644
index 00000000000..c4f4bfcdd54
Binary files /dev/null and b/docs/images/ug/f25_searchpatientcommand.PNG differ
diff --git a/docs/images/ug/f26_searchpatient.png b/docs/images/ug/f26_searchpatient.png
new file mode 100644
index 00000000000..ec81ef7342d
Binary files /dev/null and b/docs/images/ug/f26_searchpatient.png differ
diff --git a/docs/images/ug/f28_listpatientcommand.png b/docs/images/ug/f28_listpatientcommand.png
new file mode 100644
index 00000000000..079b179ba0f
Binary files /dev/null and b/docs/images/ug/f28_listpatientcommand.png differ
diff --git a/docs/images/ug/f29_listpatient.png b/docs/images/ug/f29_listpatient.png
new file mode 100644
index 00000000000..92146dafb19
Binary files /dev/null and b/docs/images/ug/f29_listpatient.png differ
diff --git a/docs/images/ug/f2_downloadcovigent.png b/docs/images/ug/f2_downloadcovigent.png
new file mode 100644
index 00000000000..d1d0c6fac62
Binary files /dev/null and b/docs/images/ug/f2_downloadcovigent.png differ
diff --git a/docs/images/ug/f31_initroomcommand.png b/docs/images/ug/f31_initroomcommand.png
new file mode 100644
index 00000000000..0d17e6bed4d
Binary files /dev/null and b/docs/images/ug/f31_initroomcommand.png differ
diff --git a/docs/images/ug/f32_initroom.png b/docs/images/ug/f32_initroom.png
new file mode 100644
index 00000000000..592f905e325
Binary files /dev/null and b/docs/images/ug/f32_initroom.png differ
diff --git a/docs/images/ug/f34_allocateroomcommand.PNG b/docs/images/ug/f34_allocateroomcommand.PNG
new file mode 100644
index 00000000000..cba62a47c7b
Binary files /dev/null and b/docs/images/ug/f34_allocateroomcommand.PNG differ
diff --git a/docs/images/ug/f35_allocateroomsuccess.PNG b/docs/images/ug/f35_allocateroomsuccess.PNG
new file mode 100644
index 00000000000..099bb59f5fc
Binary files /dev/null and b/docs/images/ug/f35_allocateroomsuccess.PNG differ
diff --git a/docs/images/ug/f37_searchroomnumbercommand.png b/docs/images/ug/f37_searchroomnumbercommand.png
new file mode 100644
index 00000000000..eece2dcef8a
Binary files /dev/null and b/docs/images/ug/f37_searchroomnumbercommand.png differ
diff --git a/docs/images/ug/f38_searchroomnumbersuccess.png b/docs/images/ug/f38_searchroomnumbersuccess.png
new file mode 100644
index 00000000000..b6a3b2e8c03
Binary files /dev/null and b/docs/images/ug/f38_searchroomnumbersuccess.png differ
diff --git a/docs/images/ug/f3_startingcovigent.png b/docs/images/ug/f3_startingcovigent.png
new file mode 100644
index 00000000000..e7ba1b6dcb6
Binary files /dev/null and b/docs/images/ug/f3_startingcovigent.png differ
diff --git a/docs/images/ug/f40_searchroompatientcommand.png b/docs/images/ug/f40_searchroompatientcommand.png
new file mode 100644
index 00000000000..4bcaeb210b2
Binary files /dev/null and b/docs/images/ug/f40_searchroompatientcommand.png differ
diff --git a/docs/images/ug/f41_searchroompatientsuccess.png b/docs/images/ug/f41_searchroompatientsuccess.png
new file mode 100644
index 00000000000..5a19acc22eb
Binary files /dev/null and b/docs/images/ug/f41_searchroompatientsuccess.png differ
diff --git a/docs/images/ug/f43_listroomcommand.png b/docs/images/ug/f43_listroomcommand.png
new file mode 100644
index 00000000000..fc7d4ed85e6
Binary files /dev/null and b/docs/images/ug/f43_listroomcommand.png differ
diff --git a/docs/images/ug/f44_listroom.png b/docs/images/ug/f44_listroom.png
new file mode 100644
index 00000000000..7677b6a4320
Binary files /dev/null and b/docs/images/ug/f44_listroom.png differ
diff --git a/docs/images/ug/f46_findemptyroomcommand.png b/docs/images/ug/f46_findemptyroomcommand.png
new file mode 100644
index 00000000000..4dd858849ae
Binary files /dev/null and b/docs/images/ug/f46_findemptyroomcommand.png differ
diff --git a/docs/images/ug/f47_findemptyroom.png b/docs/images/ug/f47_findemptyroom.png
new file mode 100644
index 00000000000..b8efb39dc3c
Binary files /dev/null and b/docs/images/ug/f47_findemptyroom.png differ
diff --git a/docs/images/ug/f49_addtaskcommand.png b/docs/images/ug/f49_addtaskcommand.png
new file mode 100644
index 00000000000..b1ad897eed0
Binary files /dev/null and b/docs/images/ug/f49_addtaskcommand.png differ
diff --git a/docs/images/ug/f4_covigenttabs.png b/docs/images/ug/f4_covigenttabs.png
new file mode 100644
index 00000000000..2bc1b5071e4
Binary files /dev/null and b/docs/images/ug/f4_covigenttabs.png differ
diff --git a/docs/images/ug/f50_addtasksuccess.png b/docs/images/ug/f50_addtasksuccess.png
new file mode 100644
index 00000000000..3fec8919954
Binary files /dev/null and b/docs/images/ug/f50_addtasksuccess.png differ
diff --git a/docs/images/ug/f51_changingtasknumber.png b/docs/images/ug/f51_changingtasknumber.png
new file mode 100644
index 00000000000..fe03b9d0477
Binary files /dev/null and b/docs/images/ug/f51_changingtasknumber.png differ
diff --git a/docs/images/ug/f53_deletetaskcommand.png b/docs/images/ug/f53_deletetaskcommand.png
new file mode 100644
index 00000000000..19f797dd517
Binary files /dev/null and b/docs/images/ug/f53_deletetaskcommand.png differ
diff --git a/docs/images/ug/f54_deletetasksuccess.png b/docs/images/ug/f54_deletetasksuccess.png
new file mode 100644
index 00000000000..f85178d09c7
Binary files /dev/null and b/docs/images/ug/f54_deletetasksuccess.png differ
diff --git a/docs/images/ug/f56_edittaskcommand.png b/docs/images/ug/f56_edittaskcommand.png
new file mode 100644
index 00000000000..0d4740e7192
Binary files /dev/null and b/docs/images/ug/f56_edittaskcommand.png differ
diff --git a/docs/images/ug/f57_edittasksuccess.png b/docs/images/ug/f57_edittasksuccess.png
new file mode 100644
index 00000000000..905b5a4e89a
Binary files /dev/null and b/docs/images/ug/f57_edittasksuccess.png differ
diff --git a/docs/images/ug/f59_edittaskcommand_removeduedate.png b/docs/images/ug/f59_edittaskcommand_removeduedate.png
new file mode 100644
index 00000000000..2efccc2c6f0
Binary files /dev/null and b/docs/images/ug/f59_edittaskcommand_removeduedate.png differ
diff --git a/docs/images/ug/f5_patientstab.png b/docs/images/ug/f5_patientstab.png
new file mode 100644
index 00000000000..7f360189ed9
Binary files /dev/null and b/docs/images/ug/f5_patientstab.png differ
diff --git a/docs/images/ug/f60_edittasksuccess_removeduedate.png b/docs/images/ug/f60_edittasksuccess_removeduedate.png
new file mode 100644
index 00000000000..5806bb3281b
Binary files /dev/null and b/docs/images/ug/f60_edittasksuccess_removeduedate.png differ
diff --git a/docs/images/ug/f62_searchtaskcommand.png b/docs/images/ug/f62_searchtaskcommand.png
new file mode 100644
index 00000000000..6e9c867cd30
Binary files /dev/null and b/docs/images/ug/f62_searchtaskcommand.png differ
diff --git a/docs/images/ug/f63_searchtasksuccess.png b/docs/images/ug/f63_searchtasksuccess.png
new file mode 100644
index 00000000000..db8576e845c
Binary files /dev/null and b/docs/images/ug/f63_searchtasksuccess.png differ
diff --git a/docs/images/ug/f65_listtaskcommand.png b/docs/images/ug/f65_listtaskcommand.png
new file mode 100644
index 00000000000..0b4eff9d698
Binary files /dev/null and b/docs/images/ug/f65_listtaskcommand.png differ
diff --git a/docs/images/ug/f66_listtasksuccess.png b/docs/images/ug/f66_listtasksuccess.png
new file mode 100644
index 00000000000..07db12fc2d2
Binary files /dev/null and b/docs/images/ug/f66_listtasksuccess.png differ
diff --git a/docs/images/ug/f67_helpcommand.png b/docs/images/ug/f67_helpcommand.png
new file mode 100644
index 00000000000..75537c9b1de
Binary files /dev/null and b/docs/images/ug/f67_helpcommand.png differ
diff --git a/docs/images/ug/f68_helpresultdisplay.png b/docs/images/ug/f68_helpresultdisplay.png
new file mode 100644
index 00000000000..55208d8a6eb
Binary files /dev/null and b/docs/images/ug/f68_helpresultdisplay.png differ
diff --git a/docs/images/ug/f69_helpwindow.png b/docs/images/ug/f69_helpwindow.png
new file mode 100644
index 00000000000..6c2f2bf824f
Binary files /dev/null and b/docs/images/ug/f69_helpwindow.png differ
diff --git a/docs/images/ug/f6_roomstab.png b/docs/images/ug/f6_roomstab.png
new file mode 100644
index 00000000000..8db3882ba85
Binary files /dev/null and b/docs/images/ug/f6_roomstab.png differ
diff --git a/docs/images/ug/f70_exitcommand.png b/docs/images/ug/f70_exitcommand.png
new file mode 100644
index 00000000000..e18c3a55fd8
Binary files /dev/null and b/docs/images/ug/f70_exitcommand.png differ
diff --git a/docs/images/ug/f7_taskstab.png b/docs/images/ug/f7_taskstab.png
new file mode 100644
index 00000000000..00ebfaa8e61
Binary files /dev/null and b/docs/images/ug/f7_taskstab.png differ
diff --git a/docs/images/ug/f8_commandbox.png b/docs/images/ug/f8_commandbox.png
new file mode 100644
index 00000000000..7b75dfb4c1d
Binary files /dev/null and b/docs/images/ug/f8_commandbox.png differ
diff --git a/docs/images/ug/f9_initroomexample.png b/docs/images/ug/f9_initroomexample.png
new file mode 100644
index 00000000000..ec24d65473d
Binary files /dev/null and b/docs/images/ug/f9_initroomexample.png differ
diff --git a/docs/images/ug/icon_hyperlink.png b/docs/images/ug/icon_hyperlink.png
new file mode 100644
index 00000000000..627898132f4
Binary files /dev/null and b/docs/images/ug/icon_hyperlink.png differ
diff --git a/docs/images/ug/icon_info.png b/docs/images/ug/icon_info.png
new file mode 100644
index 00000000000..38c5c9c287c
Binary files /dev/null and b/docs/images/ug/icon_info.png differ
diff --git a/docs/images/ug/icon_italics.png b/docs/images/ug/icon_italics.png
new file mode 100644
index 00000000000..6fce08e4305
Binary files /dev/null and b/docs/images/ug/icon_italics.png differ
diff --git a/docs/images/ug/icon_keyword.png b/docs/images/ug/icon_keyword.png
new file mode 100644
index 00000000000..49f2df06129
Binary files /dev/null and b/docs/images/ug/icon_keyword.png differ
diff --git a/docs/images/ug/icon_roomnumber.png b/docs/images/ug/icon_roomnumber.png
new file mode 100644
index 00000000000..4e80a223902
Binary files /dev/null and b/docs/images/ug/icon_roomnumber.png differ
diff --git a/docs/images/ug/icon_tasknumber.png b/docs/images/ug/icon_tasknumber.png
new file mode 100644
index 00000000000..2dd37052974
Binary files /dev/null and b/docs/images/ug/icon_tasknumber.png differ
diff --git a/docs/images/ug/icon_tasknumbertaskstab.png b/docs/images/ug/icon_tasknumbertaskstab.png
new file mode 100644
index 00000000000..dc8fa895831
Binary files /dev/null and b/docs/images/ug/icon_tasknumbertaskstab.png differ
diff --git a/docs/images/ug/navigatepatientstab.png b/docs/images/ug/navigatepatientstab.png
new file mode 100644
index 00000000000..5dc6712ac23
Binary files /dev/null and b/docs/images/ug/navigatepatientstab.png differ
diff --git a/docs/images/ug/navigateroomstab.png b/docs/images/ug/navigateroomstab.png
new file mode 100644
index 00000000000..4df31ff8104
Binary files /dev/null and b/docs/images/ug/navigateroomstab.png differ
diff --git a/docs/images/ug/navigatetaskstab.png b/docs/images/ug/navigatetaskstab.png
new file mode 100644
index 00000000000..ed2534b61bf
Binary files /dev/null and b/docs/images/ug/navigatetaskstab.png differ
diff --git a/docs/images/w-yeehong.png b/docs/images/w-yeehong.png
new file mode 100644
index 00000000000..5e827d4da4f
Binary files /dev/null and b/docs/images/w-yeehong.png differ
diff --git a/docs/index.md b/docs/index.md
index 7601dbaad0d..0ab60ae8615 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,6 +1,6 @@
---
layout: page
-title: AddressBook Level-3
+title: Covigent
---
[](https://github.com/se-edu/addressbook-level3/actions)
@@ -8,12 +8,9 @@ title: AddressBook Level-3

-**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).
+**Covigent is a desktop app for managing information of quarantined individuals and the tasks to be done by staff of the quarantine facilities**. It is optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). If you type fast, Covigent can improve your efficiency in managing your patients and tasks instead of using traditional GUI apps.
-* 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.
+Check out our [User Guide](https://ay2021s1-cs2103t-w12-1.github.io/tp/UserGuide.html) to get started.
+This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative](https://se-education.org).
-**Acknowledgements**
-
-* Libraries used: [JavaFX](https://openjfx.io/), [Jackson](https://github.com/FasterXML/jackson), [JUnit5](https://github.com/junit-team/junit5)
diff --git a/docs/storage.png b/docs/storage.png
new file mode 100644
index 00000000000..749d73a3d62
Binary files /dev/null and b/docs/storage.png differ
diff --git a/docs/team/chiamyunqing.md b/docs/team/chiamyunqing.md
new file mode 100644
index 00000000000..c3d46826a8c
--- /dev/null
+++ b/docs/team/chiamyunqing.md
@@ -0,0 +1,55 @@
+---
+layout: page
+title: Chiam Yun Qing's Project Portfolio Page
+---
+
+## Project: Covigent
+
+Covigent is a desktop application that is used to aid hotel staff handle the Covid-19 situation better. 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 add a patient to Covigent and the attributes of the patient.
+ * What it does: allows the user to create a new patient with attributes (name, period of stay, temperature, age, phone and an optional comment) in Covigent.
+
+ * Justification: This feature is highly necessary because the user will not be able to manage the quarantine facility with Covigent if new patient cannot be added. The attributes of the patient such as temperature and period of stay are also central and important in the context of a quarantine facility.
+
+ * Highlights: This enhancement affects patient-related commands to be added in future. In particular, if the attributes of the patient are not properly designed in an OOP fashion to be extensible, future developers may find it difficult to make any updates to the attributes of patient.
+
+* **New Feature**: Added the ability to delete a patient from Covigent.
+ * What it does: allows the user to remove a patient from Covigent when the patient is no longer staying in the quarantine facility.
+
+ * Justification: This feature improves the product significantly because the user may no longer want to keep track of the data of patient that are no longer staying in the quarantine facility. This allows the user to focus only on patients residing in the quarantine facility.
+
+* **New Feature**: Added the ability to search for a room in Covigent.
+ * What it does: allows the user to search for a room that a particular patient is residing in or search for a room with a given room number.
+
+ * Justification: This feature improves the user experience of the product significantly because it makes it easier for the user to search for a room to get the room details easily without having to scroll through the room list manually.
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2021s1.github.io/tp-dashboard/#breakdown=true&search=chiamyunqing&sort=groupTitle&sortWithin=title&since=2020-08-14&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other)
+
+
+* **Project management**:
+ * Managed release [v1.3](https://github.com/AY2021S1-CS2103T-W12-1/tp/releases) on GitHub.
+
+
+* **Enhancements to existing features**:
+ * Modified the GUI from AB3 to get a basic structure for the GUI of Covigent. (Pull request [\#24](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/24))
+ * Improved the GUI by adding in a panel to display patient information. (Credit: Code reused from LeeMingDe)(Pull requests [\#110](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/110))
+ * Wrote unit tests for `addpatient`, `deletepatient`, `searchroom`, `allocateroom` and `listroom` commands and patient attributes.(Pull requests [\#10](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/10), [\#59](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/59), [\#60](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/60), [\#99](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/99))
+ * Refactored the codebase to reflect the functionalities of classes clearly. (Pull request [\#80](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/80))
+
+
+* **Documentation**:
+ * User Guide:
+ * Added documentation for the features `addpatient`, `deletepatient`, `searchroom`.
+ * Did cosmetic tweaks to existing documentation of features `help`.
+ * Added a command summary section for user to refer to easily.
+ * Developer Guide:
+ * Updated the implementation of `Model Component`.
+ * Added the implementation details for Patient and its CRUD operations.
+
+
+* **Community**:
+ * PRs reviewed (with non-trivial review comments): [\#12](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/12), [\#26](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/26), [\#27](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/27), [\#79](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/79), [#115](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/115)
+ * Reported bugs and provided suggestions for another team, Homerce: [Link](https://github.com/chiamyunqing/ped/issues)
diff --git a/docs/team/itssodium.md b/docs/team/itssodium.md
new file mode 100644
index 00000000000..ed294b8bd7d
--- /dev/null
+++ b/docs/team/itssodium.md
@@ -0,0 +1,44 @@
+---
+layout: page
+title: Noorul Azlina's Project Portfolio Page
+---
+
+## Project: Covigent
+
+Covigent is a desktop application that is used to aid hotel staff handle the Covid-19 situation better. 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 search for an empty room.
+ * What it does: allows user to find out an empty room, if there are any. This information can be used to add in the
+ * Justification: This feature allows the user to check the room number for an empty room, then inserting the patient there.
+
+* **New Feature**: Added the ability to initialise the a certain number of rooms.
+ * What it does: allows user to define a certain number of rooms to exist in the hotel.
+ * Justification: This feature allows the user to continuously define the number of rooms as needed as the users can make a mistake in defining them.
+ * Highlights: This feature retains the information that is previously stored in the rooms and does not delete them. However, if user were to define the number of rooms less than existing number of occupied rooms, then error is thrown as it is not practical for visitors to leave hotel.
+
+* **New Feature**: Added the ability to list all rooms defined by user
+ * What it does: allows user to look at all rooms defined by user as the UI can change when displaying an empty room.
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2021s1.github.io/tp-dashboard/#breakdown=true&search=itssodium)
+
+* **Enhancement to existing features**:
+ * move tab panel from top to the left [\#105](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/105)
+ * wrote unit test cases for `initroom` and `findemptyroom` commands and room attributes. [\#21](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/21)
+
+* **Additional Code to aid Feature**:
+ * Added most of the classes for rooms [\#26](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/26)
+ * Handled storage in Json format for Rooms and Tasks. [\#64](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/64), [\#84](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/84)
+
+* **Documentation**:
+ * User Guide:
+ * Added documentation for features `initroom`, `findemptyroom` and `listroom`
+ * Add FAQ section for UG to answer common questions asked my users
+ * Developer Guide:
+ * Updated the implementation for Storage
+ * Added implementation details for Room
+
+* **Community**:
+ * Reported Bugs and suggestions for another team, TrackIt [link](https://github.com/itssodium/ped/issues)
+ * PRs reviewed (with non-trivial review comments): [\#69](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/69), [\#85](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/85) and [\#90](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/90)
diff --git a/docs/team/leemingde.md b/docs/team/leemingde.md
new file mode 100644
index 00000000000..d0df520c2a1
--- /dev/null
+++ b/docs/team/leemingde.md
@@ -0,0 +1,46 @@
+---
+layout: page
+title: Lee Ming De's Project Portfolio Page
+---
+
+## Project: Covigent
+
+Covigent is a desktop application that is used to aid hotel staff handle the Covid-19 situation better. 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 edit a patient's information.
+ * What it does: allows the user to change a patient's information (eg, name, temperature, age) after a patient has been added to Covigent.
+ * Justification: This feature improves the product significantly because a user can make mistakes in typing in the details of the patient and the application should provide a convenient way to rectify them.
+
+* **New Feature**: Added the ability for a user to allocate a patient to a room.
+ * What it does: allows the user to allocate a patient to a room or remove a patient from a room.
+ * Justification: This feature improves the product because it allows the user to keep track of the room the patient is in which fulfills the functional requirements of the application.
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2021s1.github.io/tp-dashboard/#breakdown=true&search=leemingde)
+
+* **Enhancements to existing features**:
+ * Updated the GUI color scheme
+ * Improved the GUI by adding in a panel to display information
+ * Added CSS file for the details panel which was later reused by others.
+
+* **Testing**:
+ * Added unit tests for the `allocateRoomParser`, `editPatientCommand`, and `editPatientCommandParser` features.
+ * Added integration tests for `allocateRoomCommand`, `editPatientCommand`.
+
+* **Documentation**:
+ * User Guide:
+ * Added documentation for the features `editpatient` and `allocateroom` [\#44](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/44)
+ * Added introduction for Covigent [\#44](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/44)
+ * Developer Guide:
+ * Added implementation details of the `allocateroom` and `logging` features
+ * Added implementation details of GUI
+ * Added/updated UML diagrams for `Logic Component`, `allocateroom`, `UI` implementation
+ * Helped with formatting for the entire developer guide
+
+* **Community**:
+ * PRs reviewed (with non-trivial review comments): [\#10](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/10),
+ [\#26](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/26), [\#27](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/27),
+ [\#69](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/69), [\#80](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/80),
+ [\#84](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/84), [\#99](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/99)
+ * Reported bugs and provided suggestions for StonksBook, a project by another teams in the class: [link](https://github.com/leemingde/ped/issues)
diff --git a/docs/team/raymondge.md b/docs/team/raymondge.md
new file mode 100644
index 00000000000..dfc5ee5959c
--- /dev/null
+++ b/docs/team/raymondge.md
@@ -0,0 +1,42 @@
+---
+layout: page
+title: Ge Wai Lok's Project Portfolio Page
+---
+
+## Project: Covigent
+
+Covigent is a desktop application that is used to aid hotel staff handle the Covid-19 situation better. 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 search for patients based on name or temperature range.
+ * What it does: allows user to search for patient based on the input, it can be either a sub-name of the patient's name, or a temperature range. All patients matching the criteria will be displayed.
+ * Justification: This feature improves the product by providing the user to find the patients in mind in a more efficient way.
+
+* **New Feature**: Added the ability to search for tasks based on due date.
+ * What it does: allows user look for tasks before a given due date(deadline).
+ * Justification: This feature improves the product by providing the user to prioritise the tasks. The users may use the search result to decide what task to complete first.
+ * Highlights: This feature displays the search result based on the Room number, tasks are grouped to be displayed under room number in the task tab.
+
+* **New Feature**: Added the ability to list all tasks defined by user
+ * What it does: allows user to look at all tasks defined by user as the UI can change when adding, searching or deleting tasks.
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2021s1.github.io/tp-dashboard/#breakdown=true&search=raymondge)
+
+* **Enhancements to existing features**:
+ * Wrote additional test cases for temperatureRange class.
+
+* **Enhancements Code to aid Feature**:
+ * Added most of the implementation of the UI and storage for task.
+ * Improved css for task to make the UI for tasks show one scollbar only instead of showing two scollbar, the problem was due to the implementation of task UI using the room UI.
+
+* **Documentation**:
+ * User Guide:
+ * Added documentation for the features `searchpatient` , `listpatient`, `searchtask` and `listtask`
+ * Added documentation for the section `About this Guide`
+ * Developer Guide:
+ * Added implementation details of the `searchpatient` , `listpatient`, `searchtask` and `listtask` feature.
+ * Added documentation and UML diagram for the section `UI`
+
+ * **Community**:
+ * PRs reviewed (with non-trivial review comments): [\#72](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/72), [\#79](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/79), [\#80](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/80)
diff --git a/docs/team/w-yeehong.md b/docs/team/w-yeehong.md
new file mode 100644
index 00000000000..9d56515d96a
--- /dev/null
+++ b/docs/team/w-yeehong.md
@@ -0,0 +1,61 @@
+---
+layout: page
+title: Wee Yee Hong's Project Portfolio Page
+---
+
+## Project: Covigent
+
+Covigent is a desktop application that is used to aid hotel staff handle the Covid-19 situation better. 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 add a task to a room.
+ * What it does: allows the user to create a new task with description and due date in any room in Covigent.
+ * Justification: This feature improves the product significantly because a user may want to keep track of time-critical tasks related to patients in each of the rooms.
+
+* **New Feature**: Added the ability to delete a task from a room.
+ * What it does: allows the user remove any tasks that she has completed or does not need from a room.
+ * Justification: This feature improves the product significantly because too many tasks in a room can clutter the user interface and make it more difficult for the user to organize her tasks.
+
+* **New Feature**: Added the ability to edit the information of a task in a room.
+ * What it does: allows the user to change the description or due date after a task has been added to a room in Covigent.
+ * Justification: This feature improves the product significantly because a user can make mistakes in typing in the details of a task and the application should provide a convenient way to rectify them.
+
+* **New Feature**: Added the ability to view a list of tasks in the user interface.
+ * What it does: allows the user to see in which rooms the tasks can be found and get an overview of all tasks that are in Covigent, without needing to know the room number of the room in which the task has been added.
+ * Justification: This feature improves the product significantly because a user may forget which room she has added a task to and wants a quick way to look up the task.
+
+* **New Feature**: Allowed commands to support different date-time formats.
+ * What it does: allows the user to select their preferred date-time formats when using commands that have a date or time component.
+ * Justification: This feature improves the product because it allows the user to comfortably use a common and familiar date-time format (e.g. dd/MM/YYYY) in her country without memorizing a specific format.
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2021s1.github.io/tp-dashboard/#breakdown=true&search=w-yeehong)
+
+* **Enhancements to existing features**:
+ * Updated GUI color scheme and separate CSS into multiple files based on the names of the views for easier lookup (Pull request [\#101](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/101)).
+ * Refactored and repackaged the codebase for better organization of files based on the model type handled (Pull requests [\#22](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/22), [#107](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/107)).
+ * Reduced code duplication (Pull request [\#154](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/154)).
+
+* **Testing**:
+ * Added unit tests to test and validate that the description and due date of a task should conform to a specified format. (Pull requests [\#27](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/27), [\#228](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/228))
+ * Added unit tests for the `addtask`, `deletetask`, and `edittask` features (Pull requests [\#27](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/27), [\#78](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/78), [\#89](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/89), [\#242](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/242))
+
+* **Documentation**:
+ * User Guide:
+ * Added documentation for the features `addtask`, `deletetask`, and `edittask`
+ * Improved "Getting Started" section for Covigent
+ * Developer Guide:
+ * Added the implementation details for `Task` and its CRUD operations
+ * Added the section on planned features
+ * Updated to reflect the high-level view of the architecture of Covigent
+
+* **Community**:
+ * PRs reviewed (with non-trivial review comments): [\#10](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/10),
+ [\#12](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/12), [\#26](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/26),
+ [\#60](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/60), [\#64](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/64),
+ [\#72](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/72), [\#100](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/100),
+ [\#105](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/105), [\#244](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/244)
+ * Reported bugs and provided suggestions for Jarvis, a project by another teams in the class: [link](https://github.com/w-yeehong/ped/issues)
+
+* **Tools**:
+ * Integrated a third party library (Mockito) to the project ([\#104](https://github.com/AY2021S1-CS2103T-W12-1/tp/pull/104))
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 44e7c4d1d7b..be52383ef49 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java
index e5cfb161b73..7d3298458e7 100644
--- a/src/main/java/seedu/address/MainApp.java
+++ b/src/main/java/seedu/address/MainApp.java
@@ -15,19 +15,24 @@
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.PatientRecords;
+import seedu.address.model.ReadOnlyList;
import seedu.address.model.ReadOnlyUserPrefs;
+import seedu.address.model.RoomList;
import seedu.address.model.UserPrefs;
+import seedu.address.model.patient.Patient;
+import seedu.address.model.room.Room;
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.storage.patient.JsonPatientRecordsStorage;
+import seedu.address.storage.patient.PatientRecordsStorage;
+import seedu.address.storage.rooms.JsonRoomOccupancyStorage;
+import seedu.address.storage.rooms.RoomRecordsStorage;
import seedu.address.ui.Ui;
import seedu.address.ui.UiManager;
@@ -48,7 +53,7 @@ public class MainApp extends Application {
@Override
public void init() throws Exception {
- logger.info("=============================[ Initializing AddressBook ]===========================");
+ logger.info("=============================[ Initializing CovigentApp ]===========================");
super.init();
AppParameters appParameters = AppParameters.parse(getParameters());
@@ -56,8 +61,11 @@ 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);
+ PatientRecordsStorage patientRecordsStorage =
+ new JsonPatientRecordsStorage(userPrefs.getCovigentAppFilePath());
+ RoomRecordsStorage roomOccupancyStorage = new JsonRoomOccupancyStorage(
+ userPrefs.getRoomsOccupiedFilePath());
+ storage = new StorageManager(patientRecordsStorage, roomOccupancyStorage, userPrefsStorage);
initLogging(config);
@@ -69,28 +77,45 @@ 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 covigent app and RoomList
+ * and {@code userPrefs}.
+ * The data from the sample covigent app and covigentApp will be used instead if {@code storage}'s covigent app is
+ * not found,or an empty covigent app will be used instead if errors occur when reading {@code storage}'s
+ * address book.
*/
private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) {
- Optional addressBookOptional;
- ReadOnlyAddressBook initialData;
+ Optional> patientRecordsOptional;
+ ReadOnlyList initialData;
+ Optional> readOnlyRoomOccupancy;
+ ReadOnlyList initialRoomList;
+
try {
- addressBookOptional = storage.readAddressBook();
- if (!addressBookOptional.isPresent()) {
- logger.info("Data file not found. Will be starting with a sample AddressBook");
- }
- initialData = addressBookOptional.orElseGet(SampleDataUtil::getSampleAddressBook);
+ readOnlyRoomOccupancy = storage.readOnlyRoomOccupancy();
+ initialRoomList = readOnlyRoomOccupancy.orElseGet(SampleDataUtil::getSampleRoomList);
} catch (DataConversionException e) {
- logger.warning("Data file not in the correct format. Will be starting with an empty AddressBook");
- initialData = new AddressBook();
+ logger.warning(
+ "Room Data file not in the correct format. Will be starting with an empty CovigentApp");
+ initialRoomList = new RoomList();
} 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 CovigentApp");
+ initialRoomList = new RoomList();
}
- return new ModelManager(initialData, userPrefs);
+ try {
+ patientRecordsOptional = storage.readPatientRecords();
+ if (!patientRecordsOptional.isPresent()) {
+ logger.info("Data file not found. Will be starting with a sample CovigentApp");
+ }
+ initialData = patientRecordsOptional.orElseGet(SampleDataUtil::getSampleCovigentApp);
+ } catch (DataConversionException e) {
+ logger.warning(
+ "Patient Data file not in the correct format. Will be starting with an empty CovigentApp");
+ initialData = new PatientRecords();
+ } catch (IOException e) {
+ logger.warning("Problem while reading from the file. Will be starting with an empty CovigentApp");
+ initialData = new PatientRecords();
+ }
+ return new ModelManager(initialData, initialRoomList, userPrefs);
}
private void initLogging(Config config) {
@@ -151,7 +176,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 CovigentApp");
initializedPrefs = new UserPrefs();
}
@@ -167,7 +192,7 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) {
@Override
public void start(Stage primaryStage) {
- logger.info("Starting AddressBook " + MainApp.VERSION);
+ logger.info("Starting CovigentApp " + MainApp.VERSION);
ui.start(primaryStage);
}
diff --git a/src/main/java/seedu/address/commons/core/GuiSettings.java b/src/main/java/seedu/address/commons/core/GuiSettings.java
index ba33653be67..5d4b37dba72 100644
--- a/src/main/java/seedu/address/commons/core/GuiSettings.java
+++ b/src/main/java/seedu/address/commons/core/GuiSettings.java
@@ -10,8 +10,8 @@
*/
public class GuiSettings implements Serializable {
- private static final double DEFAULT_HEIGHT = 600;
- private static final double DEFAULT_WIDTH = 740;
+ private static final double DEFAULT_HEIGHT = 750;
+ private static final double DEFAULT_WIDTH = 1000;
private final double windowWidth;
private final double windowHeight;
diff --git a/src/main/java/seedu/address/commons/core/LogsCenter.java b/src/main/java/seedu/address/commons/core/LogsCenter.java
index 431e7185e76..6ec61e6dfca 100644
--- a/src/main/java/seedu/address/commons/core/LogsCenter.java
+++ b/src/main/java/seedu/address/commons/core/LogsCenter.java
@@ -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 = "covigentapp.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/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java
index 1deb3a1e469..1f0f23dd6e1 100644
--- a/src/main/java/seedu/address/commons/core/Messages.java
+++ b/src/main/java/seedu/address/commons/core/Messages.java
@@ -5,9 +5,31 @@
*/
public class Messages {
+ // common
+
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!";
+ public static final String MESSAGE_TOO_MANY_COMMANDS = "Too many commands entered!";
+
+ // patients
+
+ public static final String MESSAGE_INVALID_PATIENT_NAME = "The patient name provided "
+ + "cannot be found in Covigent.";
+ public static final String MESSAGE_PATIENT_LISTED_OVERVIEW = "%1$d patient listed!";
+
+ // rooms
+
+ public static final String MESSAGE_INVALID_ROOM_NUMBER = "The room number provided "
+ + "cannot be found in Covigent.";
+ public static final String MESSAGE_PATIENT_ALREADY_ASSIGNED = "Patient has already been assigned a room.\nPlease"
+ + " clear patient from the room first.";
+ public static final String MESSAGE_PATIENT_NO_ROOM = "Patient is not assigned to any room yet.";
+
+ // tasks
+
+ public static final String MESSAGE_INVALID_TASK_INDEX = "The task number provided "
+ + "cannot be found in the room.";
+ public static final String MESSAGE_TASK_NOT_EDITED = "Task has not been edited.\nPlease ensure that at least"
+ + " one valid and different value has been provided.";
}
diff --git a/src/main/java/seedu/address/commons/util/DateTimeUtil.java b/src/main/java/seedu/address/commons/util/DateTimeUtil.java
new file mode 100644
index 00000000000..5cd4d643d26
--- /dev/null
+++ b/src/main/java/seedu/address/commons/util/DateTimeUtil.java
@@ -0,0 +1,108 @@
+package seedu.address.commons.util;
+
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DateTimeParseException;
+import java.time.temporal.ChronoField;
+import java.time.temporal.TemporalQuery;
+
+//@@author w-yeehong
+/**
+ * Helper functions for handling date and date-time objects.
+ */
+public class DateTimeUtil {
+
+ // Date formats
+ /** e.g. 20200920 */
+ public static final DateTimeFormatter DATE_FORMAT_YEAR_MONTH_DAY =
+ DateTimeFormatter.ofPattern("yyyyMMdd");
+
+ /** e.g. 20 Sep 2020 */
+ public static final DateTimeFormatter DATE_FORMAT_DAY_MONTH_YEAR_LONG_SPACE_DELIMITED =
+ DateTimeFormatter.ofPattern("d MMM yyyy");
+
+ /** e.g. 20/9/2020 */
+ public static final DateTimeFormatter DATE_FORMAT_DAY_MONTH_YEAR_SLASH_DELIMITED =
+ DateTimeFormatter.ofPattern("d/M/yyyy");
+
+
+ // Date-time formats
+ /** e.g. 20200920 or 20200920 2359 */
+ public static final DateTimeFormatter DATETIME_FORMAT_YEAR_MONTH_DAY_OPTIONAL_TIME =
+ createFormatterWithOptionalTime("yyyyMMdd", " HHmm");
+
+ /** e.g. 20 Sep 2020 (time defaults to 0000) or 20 Sep 2020 2359 */
+ public static final DateTimeFormatter DATETIME_FORMAT_DAY_MONTH_YEAR_LONG_SPACE_DELIMITED_OPTIONAL_TIME =
+ createFormatterWithOptionalTime("d MMM yyyy", " HHmm");
+
+ /** e.g. 20/9/2020 (time defaults to 0000) or 20/09/2020 2359 */
+ public static final DateTimeFormatter DATETIME_FORMAT_DAY_MONTH_YEAR_SLASH_DELIMITED_OPTIONAL_TIME =
+ createFormatterWithOptionalTime("d/M/yyyy", " HHmm");
+
+
+ /**
+ * Parses the text into a date-time object (e.g. {@code LocalDate} or {@code LocalDateTime})
+ * using all given {@code DateTimeFormatter} and returns the first successful result.
+ *
+ * The text is parsed using each formatter in turn. No output is generated if a formatter fails to
+ * parse the text. However, a {@code DateTimeParseException} is thrown if all formatters fail.
+ *
+ * The {@code TemporalQuery} is typically a method reference to a
+ * {@code from(TemporalAccessor)} method.
+ * For example:
+ *
+ * LocalDate date = DateTimeUtil.parseFirstMatching(text, LocalDate::from, formatter1, formatter2);
+ *
+ *
+ * For more details, refer to
+ * https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#
+ * parse-java.lang.CharSequence-java.time.temporal.TemporalQuery-
+ *
+ * @param text The text to parse, cannot be null.
+ * @param query A way to retrieve information from a temporal-based object.
+ * @param formatters Formatters to parse the text with, cannot be null.
+ * @param A date-time class, usually a {@code TemporalAccessor}.
+ * @return The date-time object parsed from text.
+ * @throws DateTimeParseException if text cannot be parsed with any of the formatters or no formatters provided.
+ */
+ public static T parseFirstMatching(
+ CharSequence text, TemporalQuery query, DateTimeFormatter... formatters) {
+ requireAllNonNull(text, query, formatters);
+
+ for (DateTimeFormatter formatter : formatters) {
+ try {
+ return formatter.parse(text, query);
+ } catch (DateTimeParseException e) {
+ // Current formatter is invalid.
+ // Proceed to test next formatter.
+ }
+ }
+
+ String exceptionMessage = String.format("Unable to parse %s", text);
+ int errorIndex = 0; // index in parsed text that was invalid, set to 0 to indicate entirety of text
+
+ throw new DateTimeParseException(exceptionMessage, text, errorIndex);
+ }
+
+ /**
+ * Creates a {@code DateTimeFormatter} with default values of time.
+ * If a time conforms to the time format, the {@code DateTimeFormatter} sets the parsed date-time
+ * to that value. Otherwise, the hour and minute of the parsed date-time are set to 0.
+ *
+ * @param dateFormat The pattern for the date portion of a string parsed by a{@code DateTimeFormatter}.
+ * @param timeFormat The pattern for the time portion of a string parsed by a {@code DateTimeFormatter}.
+ * @return A {@code DateTimeFormatter} that defaults the hour and minute to 0 if time does not conform to format.
+ */
+ private static DateTimeFormatter createFormatterWithOptionalTime(String dateFormat, String timeFormat) {
+ return new DateTimeFormatterBuilder()
+ .appendPattern(dateFormat)
+ .optionalStart()
+ .appendPattern(timeFormat)
+ .optionalEnd()
+ .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
+ .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
+ .toFormatter();
+ }
+}
diff --git a/src/main/java/seedu/address/commons/util/FileUtil.java b/src/main/java/seedu/address/commons/util/FileUtil.java
index b1e2767cdd9..9f73565a49d 100644
--- a/src/main/java/seedu/address/commons/util/FileUtil.java
+++ b/src/main/java/seedu/address/commons/util/FileUtil.java
@@ -18,7 +18,7 @@ public static boolean isFileExists(Path file) {
}
/**
- * Returns true if {@code path} can be converted into a {@code Path} via {@link Paths#get(String)},
+ * Returns true if {@code path} can be converted into a {@code Path} via {@link Paths#get(String, String...)})}},
* otherwise returns false.
* @param path A string representing the file path. Cannot be null.
*/
diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/address/logic/Logic.java
index 92cd8fa605a..0290f6bd230 100644
--- a/src/main/java/seedu/address/logic/Logic.java
+++ b/src/main/java/seedu/address/logic/Logic.java
@@ -7,8 +7,10 @@
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.address.model.ReadOnlyList;
+import seedu.address.model.patient.Patient;
+import seedu.address.model.room.Room;
+import seedu.address.model.room.RoomTaskAssociation;
/**
* API of the Logic component
@@ -16,6 +18,7 @@
public interface Logic {
/**
* Executes the command and returns the result.
+ *
* @param commandText The command as entered by the user.
* @return the result of the command execution.
* @throws CommandException If an error occurs during command execution.
@@ -24,19 +27,28 @@ public interface Logic {
CommandResult execute(String commandText) throws CommandException, ParseException;
/**
- * Returns the AddressBook.
+ * Returns Covigent.
*
- * @see seedu.address.model.Model#getAddressBook()
+ * @see seedu.address.model.Model#getPatientRecords()
*/
- ReadOnlyAddressBook getAddressBook();
+ ReadOnlyList getCovigentApp();
+
+ /** Returns an unmodifiable view of the filtered list of patients. */
+ ObservableList getFilteredPatientList();
+
+ /** Returns an unmodifiable view of the list of rooms. */
+ ObservableList getRoomList();
- /** Returns an unmodifiable view of the filtered list of persons */
- ObservableList getFilteredPersonList();
+ /** Returns an unmodifiable view of the filtered list of rooms. */
+ ObservableList getFilteredRoomList();
+
+ /** Returns an unmodifiable view of the filtered list of room-task associations. */
+ ObservableList getFilteredRoomTaskRecords();
/**
- * Returns the user prefs' address book file path.
+ * Returns the user prefs' Covigent file path.
*/
- Path getAddressBookFilePath();
+ Path getCovigentAppFilePath();
/**
* Returns the user prefs' GUI settings.
@@ -47,4 +59,5 @@ public interface Logic {
* Set the user prefs' GUI settings.
*/
void setGuiSettings(GuiSettings guiSettings);
+
}
diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java
index 9d9c6d15bdc..0ab7e964cee 100644
--- a/src/main/java/seedu/address/logic/LogicManager.java
+++ b/src/main/java/seedu/address/logic/LogicManager.java
@@ -10,13 +10,16 @@
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.CovigentAppParser;
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.model.ReadOnlyList;
+import seedu.address.model.patient.Patient;
+import seedu.address.model.room.Room;
+import seedu.address.model.room.RoomTaskAssociation;
import seedu.address.storage.Storage;
+
/**
* The main LogicManager of the app.
*/
@@ -26,7 +29,7 @@ public class LogicManager implements Logic {
private final Model model;
private final Storage storage;
- private final AddressBookParser addressBookParser;
+ private final CovigentAppParser covigentAppParser;
/**
* Constructs a {@code LogicManager} with the given {@code Model} and {@code Storage}.
@@ -34,7 +37,7 @@ public class LogicManager implements Logic {
public LogicManager(Model model, Storage storage) {
this.model = model;
this.storage = storage;
- addressBookParser = new AddressBookParser();
+ covigentAppParser = new CovigentAppParser();
}
@Override
@@ -42,11 +45,16 @@ public CommandResult execute(String commandText) throws CommandException, ParseE
logger.info("----------------[USER COMMAND][" + commandText + "]");
CommandResult commandResult;
- Command command = addressBookParser.parseCommand(commandText);
+ Command command = covigentAppParser.parseCommand(commandText);
commandResult = command.execute(model);
try {
- storage.saveAddressBook(model.getAddressBook());
+ storage.saveRoomsInformation(model.getModifiableRoomList());
+ } catch (IOException ioe) {
+ throw new CommandException(FILE_OPS_ERROR_MESSAGE);
+ }
+ try {
+ storage.savePatientRecords(model.getPatientRecords());
} catch (IOException ioe) {
throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe);
}
@@ -55,18 +63,23 @@ public CommandResult execute(String commandText) throws CommandException, ParseE
}
@Override
- public ReadOnlyAddressBook getAddressBook() {
- return model.getAddressBook();
+ public ReadOnlyList getCovigentApp() {
+ return model.getPatientRecords();
+ }
+
+ @Override
+ public ObservableList getFilteredPatientList() {
+ return model.getFilteredPatientList();
}
@Override
- public ObservableList getFilteredPersonList() {
- return model.getFilteredPersonList();
+ public ObservableList getRoomList() {
+ return model.getRoomListObservableList();
}
@Override
- public Path getAddressBookFilePath() {
- return model.getAddressBookFilePath();
+ public Path getCovigentAppFilePath() {
+ return model.getCovigentAppFilePath();
}
@Override
@@ -78,4 +91,14 @@ public GuiSettings getGuiSettings() {
public void setGuiSettings(GuiSettings guiSettings) {
model.setGuiSettings(guiSettings);
}
+
+ @Override
+ public ObservableList getFilteredRoomList() {
+ return model.getFilteredRoomList();
+ }
+
+ @Override
+ public ObservableList getFilteredRoomTaskRecords() {
+ return model.getFilteredRoomTaskRecords();
+ }
}
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/commands/patient/AddPatientCommand.java b/src/main/java/seedu/address/logic/commands/patient/AddPatientCommand.java
new file mode 100644
index 00000000000..01ec627a007
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/patient/AddPatientCommand.java
@@ -0,0 +1,70 @@
+package seedu.address.logic.commands.patient;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_AGE;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_COMMENTS;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_PERIOD_OF_STAY;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_PHONE;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_TEMP;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.patient.Patient;
+
+//@@author chiamyunqing
+/**
+ * Adds a patient to the app.
+ */
+public class AddPatientCommand extends Command {
+
+ public static final String COMMAND_WORD = "addpatient";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a patient to Covigent. "
+ + "\nParameters: "
+ + PREFIX_NAME + "NAME "
+ + PREFIX_TEMP + "TEMPERATURE "
+ + PREFIX_PERIOD_OF_STAY + "PERIOD OF STAY "
+ + PREFIX_PHONE + "PHONE "
+ + PREFIX_AGE + "AGE "
+ + "[" + PREFIX_COMMENTS + "COMMENTS]\n"
+ + "Example: " + COMMAND_WORD + " "
+ + PREFIX_NAME + "John Doe "
+ + PREFIX_TEMP + "37.0 "
+ + PREFIX_PERIOD_OF_STAY + "20200914-20200928 "
+ + PREFIX_PHONE + "98765432 "
+ + PREFIX_AGE + "22 "
+ + PREFIX_COMMENTS + "Vegan,asthmatic ";
+
+ public static final String MESSAGE_SUCCESS = "New patient added: %1$s";
+ public static final String MESSAGE_DUPLICATE_PATIENT = "This patient already exists in Covigent.";
+
+ private final Patient toAdd;
+
+ /**
+ * Creates an AddCommand to add the specified {@code Patient}.
+ */
+ public AddPatientCommand(Patient patient) {
+ requireNonNull(patient);
+ toAdd = patient;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ if (model.hasPatient(toAdd)) {
+ throw new CommandException(MESSAGE_DUPLICATE_PATIENT);
+ }
+ model.addPatient(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 AddPatientCommand // instanceof handles nulls
+ && toAdd.equals(((AddPatientCommand) other).toAdd));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/patient/DeletePatientCommand.java b/src/main/java/seedu/address/logic/commands/patient/DeletePatientCommand.java
new file mode 100644
index 00000000000..b74da521434
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/patient/DeletePatientCommand.java
@@ -0,0 +1,66 @@
+package seedu.address.logic.commands.patient;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.Optional;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.patient.Name;
+import seedu.address.model.patient.Patient;
+
+//@@author chiamyunqing
+/**
+ * Deletes a patient identified by the patient's name from the application.
+ * If the patient resides in a room, the patient will be removed and the room will be set to unoccupied.
+ */
+public class DeletePatientCommand extends Command {
+
+ public static final String COMMAND_WORD = "deletepatient";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Deletes the patient identified by the patient's name used in the displayed patient list.\n"
+ + "Parameters: NAME (must match exactly with the name of the patient to be deleted from the patient list)\n"
+ + "Example: " + COMMAND_WORD + " Mary Doe";
+
+ public static final String MESSAGE_DELETE_PATIENT_SUCCESS = "Deleted Patient: %1$s";
+
+ private final Name nameOfPatientToDelete;
+
+ /**
+ * Creates a DeleteCommand to delete the patient with the name {@code String}.
+ * @param nameOfPatientToDelete name in the filtered patient list to be deleted
+ */
+ public DeletePatientCommand(Name nameOfPatientToDelete) {
+ requireNonNull(nameOfPatientToDelete);
+ this.nameOfPatientToDelete = nameOfPatientToDelete;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ Optional patientToDelete = model.getPatientWithName(nameOfPatientToDelete);
+
+ if (patientToDelete.isEmpty()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PATIENT_NAME);
+ }
+
+ if (model.isPatientAssignedToRoom(nameOfPatientToDelete)) {
+ model.removePatientFromRoom(nameOfPatientToDelete);
+ }
+
+ Patient deletedPatient = patientToDelete.get();
+ model.deletePatient(deletedPatient);
+ return new CommandResult(String.format(MESSAGE_DELETE_PATIENT_SUCCESS, deletedPatient));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof DeletePatientCommand // instanceof handles nulls
+ && nameOfPatientToDelete.equals(((DeletePatientCommand) other).nameOfPatientToDelete)); // state check
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/patient/EditPatientCommand.java b/src/main/java/seedu/address/logic/commands/patient/EditPatientCommand.java
new file mode 100644
index 00000000000..ca5965f5c70
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/patient/EditPatientCommand.java
@@ -0,0 +1,235 @@
+package seedu.address.logic.commands.patient;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_AGE;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_COMMENTS;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_PERIOD_OF_STAY;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_PHONE;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_TEMP;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PATIENTS;
+
+import java.util.Optional;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.util.CollectionUtil;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.patient.Age;
+import seedu.address.model.patient.Comment;
+import seedu.address.model.patient.Name;
+import seedu.address.model.patient.Patient;
+import seedu.address.model.patient.PeriodOfStay;
+import seedu.address.model.patient.Phone;
+import seedu.address.model.patient.Temperature;
+
+//@@author LeeMingDe
+/**
+ * Edits a patient in the app with the selected name.
+ * Input of name is case insensitive.
+ */
+public class EditPatientCommand extends Command {
+
+ public static final String COMMAND_WORD = "editpatient";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the patient identified "
+ + "by the patient's name used in the displayed patient list. \n"
+ + "Existing values will be overwritten by the input values.\n"
+ + "Parameters: NAME (must match exactly with the name of the patient to be edited in the patient list) "
+ + "[" + PREFIX_NAME + "NAME] "
+ + "[" + PREFIX_PHONE + "PHONE] "
+ + "[" + PREFIX_TEMP + "TEMPERATURE] "
+ + "[" + PREFIX_AGE + "AGE] "
+ + "[" + PREFIX_PERIOD_OF_STAY + "PERIOD OF STAY] "
+ + "[" + PREFIX_COMMENTS + "COMMENT] "
+ + "\nExample: " + COMMAND_WORD + " john "
+ + PREFIX_PHONE + "91234567 "
+ + PREFIX_TEMP + "36.5";
+
+ public static final String MESSAGE_EDIT_PATIENT_SUCCESS = "Edited Patient: %1$s";
+ public static final String MESSAGE_PATIENT_NOT_EDITED = "At least one field to edit must be provided.";
+ public static final String MESSAGE_DUPLICATE_PATIENT = "This patient already exists in Covigent.";
+
+ private final Name patientToBeEdited;
+ private final EditPatientDescriptor editPatientDescriptor;
+
+ /**
+ * Constructs an EditCommand to edit the patient with the name {@code String}.
+ *
+ * @param patientToBeEdited name in the filtered patient list to edit
+ * @param editPatientDescriptor details to edit the patient with
+ */
+ public EditPatientCommand(Name patientToBeEdited, EditPatientDescriptor editPatientDescriptor) {
+ requireAllNonNull(patientToBeEdited, editPatientDescriptor);
+
+ this.patientToBeEdited = patientToBeEdited;
+ this.editPatientDescriptor = new EditPatientDescriptor(editPatientDescriptor);
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ Optional optionalPatient = model.getPatientWithName(patientToBeEdited);
+ if (optionalPatient.isEmpty()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PATIENT_NAME);
+ }
+
+ Patient patientToEdit = optionalPatient.get();
+ Patient editedPatient = createEditedPatient(patientToEdit, editPatientDescriptor);
+
+ if (!patientToEdit.isSamePatient(editedPatient) && model.hasPatient(editedPatient)) {
+ throw new CommandException(MESSAGE_DUPLICATE_PATIENT);
+ }
+
+ model.setPatient(patientToEdit, editedPatient);
+ model.updateFilteredPatientList(PREDICATE_SHOW_ALL_PATIENTS);
+ model.updateRoomListWhenPatientsChanges(patientToEdit, editedPatient);
+ return new CommandResult(String.format(MESSAGE_EDIT_PATIENT_SUCCESS, editedPatient));
+ }
+
+ /**
+ * Creates and returns a {@code Patient} with the details of {@code patientToEdit}
+ * edited with {@code editPatientDescriptor}.
+ *
+ * @param patientToEdit Patient that is to be edited.
+ * @param editPatientDescriptor Details to edit the patient with.
+ * @return Patient that has been edited.
+ */
+ private static Patient createEditedPatient(Patient patientToEdit, EditPatientDescriptor editPatientDescriptor) {
+ assert patientToEdit != null;
+ assert editPatientDescriptor != null;
+
+ Name updatedName = editPatientDescriptor.getName().orElse(patientToEdit.getName());
+ Phone updatedPhone = editPatientDescriptor.getPhone().orElse(patientToEdit.getPhone());
+ Temperature updatedTemperature = editPatientDescriptor.getTemperature().orElse(patientToEdit.getTemperature());
+ Age updatedAge = editPatientDescriptor.getAge().orElse(patientToEdit.getAge());
+ PeriodOfStay updatedPeriodOfStay = editPatientDescriptor
+ .getPeriodOfStay()
+ .orElse(patientToEdit.getPeriodOfStay());
+ Comment updatedComment = editPatientDescriptor.getComment().orElse(patientToEdit.getComment());
+ return new Patient(updatedName, updatedTemperature, updatedPeriodOfStay,
+ updatedPhone, updatedAge, updatedComment);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) { //short circuit if same object
+ return true;
+ }
+
+ if (!(other instanceof EditPatientCommand)) { // instanceof handles nulls
+ return false;
+ }
+
+ EditPatientCommand e = (EditPatientCommand) other; // state check
+ return patientToBeEdited.equals(e.patientToBeEdited)
+ && editPatientDescriptor.equals(e.editPatientDescriptor);
+ }
+
+ /**
+ * Stores the details to edit the patient with. Each non-empty field value will replace the
+ * corresponding field value of the patient.
+ */
+ public static class EditPatientDescriptor {
+ private Name name;
+ private Phone phone;
+ private Temperature temperature;
+ private Age age;
+ private PeriodOfStay periodOfStay;
+ private Comment comment;
+
+ public EditPatientDescriptor() {}
+
+
+ /**
+ * Constructs a EditPatientDescriptor object with the following fields.
+ *
+ * @param toCopy EditPatientDescriptor to copy the fields from.
+ */
+ public EditPatientDescriptor(EditPatientDescriptor toCopy) {
+ setName(toCopy.name);
+ setPhone(toCopy.phone);
+ setTemperature(toCopy.temperature);
+ setAge(toCopy.age);
+ setPeriodOfStay(toCopy.periodOfStay);
+ setComment(toCopy.comment);
+ }
+
+ public boolean isAnyFieldEdited() {
+ return CollectionUtil.isAnyNonNull(name, phone, temperature, age, periodOfStay, comment);
+ }
+
+ 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 setTemperature(Temperature temperature) {
+ this.temperature = temperature;
+ }
+
+ public Optional getTemperature() {
+ return Optional.ofNullable(temperature);
+ }
+
+ public void setAge(Age age) {
+ this.age = age;
+ }
+
+ public Optional getAge() {
+ return Optional.ofNullable(age);
+ }
+
+ public void setPeriodOfStay(PeriodOfStay periodOfStay) {
+ this.periodOfStay = periodOfStay;
+ }
+
+ public Optional getPeriodOfStay() {
+ return Optional.ofNullable(periodOfStay);
+ }
+
+ public void setComment(Comment comment) {
+ this.comment = comment;
+ }
+
+ public Optional getComment() {
+ return Optional.ofNullable(comment);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) { // short circuit if same object
+ return true;
+ }
+
+ if (!(other instanceof EditPatientDescriptor)) { // instanceof handles nulls
+ return false;
+ }
+
+ EditPatientDescriptor e = (EditPatientDescriptor) other; // state check
+
+ return getName().equals(e.getName())
+ && getPhone().equals(e.getPhone())
+ && getTemperature().equals(e.getTemperature())
+ && getAge().equals(e.getAge())
+ && getPeriodOfStay().equals(e.getPeriodOfStay())
+ && getComment().equals(e.getComment());
+ }
+ }
+ //@@author LeeMingDe
+}
diff --git a/src/main/java/seedu/address/logic/commands/patient/ListPatientCommand.java b/src/main/java/seedu/address/logic/commands/patient/ListPatientCommand.java
new file mode 100644
index 00000000000..92b523de44b
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/patient/ListPatientCommand.java
@@ -0,0 +1,25 @@
+package seedu.address.logic.commands.patient;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PATIENTS;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.model.Model;
+
+/**
+ * Lists all patients in the address book to the user.
+ */
+public class ListPatientCommand extends Command {
+
+ public static final String COMMAND_WORD = "listpatient";
+
+ public static final String MESSAGE_SUCCESS = "All patients are listed.";
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ model.updateFilteredPatientList(PREDICATE_SHOW_ALL_PATIENTS);
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/patient/SearchPatientCommand.java b/src/main/java/seedu/address/logic/commands/patient/SearchPatientCommand.java
new file mode 100644
index 00000000000..3d73e687e0d
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/patient/SearchPatientCommand.java
@@ -0,0 +1,239 @@
+package seedu.address.logic.commands.patient;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_TEMP_RANGE;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.patient.Name;
+import seedu.address.model.patient.NameContainsKeywordsPredicate;
+import seedu.address.model.patient.Patient;
+import seedu.address.model.patient.TemperatureRange;
+import seedu.address.model.patient.TemperatureRangePredicate;
+
+
+/**
+ * Searches a patient or a list of patient according to a name or a range of temperature.
+ */
+public class SearchPatientCommand extends Command {
+
+ public static final String COMMAND_WORD = "searchpatient";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Searches a patient or a list of patients with only one specific criteria. "
+ + "\nParameters: "
+ + PREFIX_NAME + "NAME or "
+ + PREFIX_TEMP_RANGE + "TEMPERATURE RANGE "
+ + "\nExample: " + COMMAND_WORD + " "
+ + PREFIX_TEMP_RANGE + "36.1-37.9 ";
+
+ public static final String MESSAGE_NOT_FOUND = "At least one field to edit must be provided.";
+ public static final String MESSAGE_PATIENT_NOT_FOUND = "No patient matching the criteria has been found.";
+ public static final String MESSAGE_SEARCH_PATIENT_LIST_SUCCESS = "Listed patient(s) matching the criteria.";
+
+ private final SearchPatientDescriptor searchPatientDescriptor;
+ private NameContainsKeywordsPredicate namePredicate;
+ private TemperatureRangePredicate temperaturePredicate;
+
+ /**
+ * Constructs an SearchPatientCommand to edit the patient with the name {@code String}.
+ *
+ * @param searchPatientDescriptor Description of the searchPatient command.
+ */
+ public SearchPatientCommand(SearchPatientDescriptor searchPatientDescriptor) {
+ requireNonNull(searchPatientDescriptor);
+ this.searchPatientDescriptor = searchPatientDescriptor;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ final SearchCriteria criteriaToSearch = this.confirmCriteria(searchPatientDescriptor);
+ List patientList = model.getFilteredPatientList();
+ if (criteriaToSearch == SearchCriteria.CRITERIA_NOT_FOUND) {
+ throw new CommandException(MESSAGE_NOT_FOUND);
+ } else if (criteriaToSearch == SearchCriteria.CRITERIA_IS_NAME) {
+ updateNamePredicate(model, searchPatientDescriptor);
+ return findPatientWithName(searchPatientDescriptor, patientList);
+ } else if (criteriaToSearch == SearchCriteria.CRITERIA_IS_TEMPERATURE) {
+ updateTemperaturePredicate(model, searchPatientDescriptor);
+ return findPatientWithTemperature(searchPatientDescriptor, patientList);
+ } else if (criteriaToSearch == SearchCriteria.TOO_MANY_CRITERIA) {
+ return new CommandResult(Messages.MESSAGE_TOO_MANY_COMMANDS);
+ }
+ throw new CommandException(MESSAGE_NOT_FOUND);
+ }
+
+ /**
+ * Update the predicate for filteredlist.
+ * @param searchPatientDescriptor the patient's name in the descriptor.
+ * @param model the model.
+ */
+ public void updateNamePredicate(Model model, SearchPatientDescriptor searchPatientDescriptor) {
+ namePredicate = new NameContainsKeywordsPredicate(Arrays
+ .asList(searchPatientDescriptor.getStringName().split("\\s+")));
+ model.updateFilteredPatientList(namePredicate);
+ }
+
+ /**
+ * Update the predicate for filteredlist.
+ * @param searchPatientDescriptor the patient's name in the descriptor.
+ * @param model the model.
+ */
+ public void updateTemperaturePredicate(Model model, SearchPatientDescriptor searchPatientDescriptor) {
+ double startingTemperature = searchPatientDescriptor.getTemperatureRange().getStartingTemperature();
+ double endingTemperature = searchPatientDescriptor.getTemperatureRange().getEndingTemperature();
+ temperaturePredicate = new TemperatureRangePredicate(startingTemperature, endingTemperature);
+ model.updateFilteredPatientList(temperaturePredicate);
+ }
+
+ /**
+ * Return the patient's detail with specific name
+ * @param searchPatientDescriptor the patient's name in the descriptor.
+ * @param patientList the patient list stored.
+ * @return a CommandResult of the patients' details.
+ * @throws CommandException if patient is not found.
+ */
+ public CommandResult findPatientWithName(SearchPatientDescriptor searchPatientDescriptor,
+ List patientList) throws CommandException {
+ String nameToSearch = searchPatientDescriptor.getName().toString().trim().toLowerCase();
+ ArrayList patientNameList = new ArrayList<>();
+
+ for (Patient patient : patientList) {
+ String patientName = patient.getName().toString().trim().toLowerCase();
+ if (patientName.contains(nameToSearch)) {
+ patientNameList.add(patient);
+ }
+ }
+
+ if (patientNameList.isEmpty()) {
+ throw new CommandException(MESSAGE_PATIENT_NOT_FOUND);
+ } else {
+ return new CommandResult(MESSAGE_SEARCH_PATIENT_LIST_SUCCESS);
+ }
+ }
+
+ /**
+ * Return the patient's detail with specific Temperature Range.
+ * @param searchPatientDescriptor the patient's name in the descriptor.
+ * @param patientList the patient list stored.
+ * @return a CommandResult of the patients' details.
+ * @throws CommandException if no patient matching the criteria.
+ */
+ public CommandResult findPatientWithTemperature(SearchPatientDescriptor searchPatientDescriptor,
+ List patientList) throws CommandException {
+ double startingTemperature = searchPatientDescriptor.getTemperatureRange().getStartingTemperature();
+ double endingTemperature = searchPatientDescriptor.getTemperatureRange().getEndingTemperature();
+ ArrayList patientWithinTemperatureRange = new ArrayList<>();
+ for (Patient patient : patientList) {
+ if (patient.getTemperature().getValue() >= startingTemperature
+ && patient.getTemperature().getValue() <= endingTemperature) {
+ patientWithinTemperatureRange.add(patient);
+ }
+ }
+
+ if (patientWithinTemperatureRange.isEmpty()) {
+ throw new CommandException(MESSAGE_PATIENT_NOT_FOUND);
+ } else {
+ return new CommandResult(MESSAGE_SEARCH_PATIENT_LIST_SUCCESS);
+ }
+ }
+
+ /**
+ * Confirm the criteria to look for.
+ * @param searchPatientDescriptor Details of the searchPatient Command.
+ * @return criteria to look for.
+ */
+ public SearchCriteria confirmCriteria(SearchPatientDescriptor searchPatientDescriptor) {
+ if (searchPatientDescriptor.getOptionalName().isEmpty()
+ && searchPatientDescriptor.getOptionalTemperatureRange().isEmpty()) {
+ return SearchCriteria.CRITERIA_NOT_FOUND;
+ } else if (searchPatientDescriptor.getOptionalName().isPresent()
+ && searchPatientDescriptor.getOptionalTemperatureRange().isEmpty()) {
+ return SearchCriteria.CRITERIA_IS_NAME;
+ } else if (searchPatientDescriptor.getOptionalName().isEmpty()
+ && searchPatientDescriptor.getOptionalTemperatureRange().isPresent()) {
+ return SearchCriteria.CRITERIA_IS_TEMPERATURE;
+ } else {
+ return SearchCriteria.TOO_MANY_CRITERIA;
+ }
+
+ }
+
+ private enum SearchCriteria {
+ CRITERIA_IS_NAME,
+ CRITERIA_IS_TEMPERATURE,
+ TOO_MANY_CRITERIA,
+ CRITERIA_NOT_FOUND
+ }
+
+ /**
+ * Stores the details to search the patient .
+ * The class is used with @ConfirmArea method to confirm the area to look for.
+ */
+ public static class SearchPatientDescriptor {
+ private Name name;
+ private TemperatureRange temperatureRange;
+ private String stringName;
+ public SearchPatientDescriptor() {
+ }
+ public void setStringName(String stringName) {
+ this.stringName = stringName;
+ }
+
+ public String getStringName() {
+ return stringName;
+ }
+
+ public void setName(Name name) {
+ this.name = name;
+ }
+
+ public Optional getOptionalName() {
+ return Optional.ofNullable(name);
+ }
+
+ public Name getName() {
+ return name;
+ }
+
+ public void setTemperatureRange(TemperatureRange temperatureRange) {
+ this.temperatureRange = temperatureRange;
+ }
+
+ public Optional getOptionalTemperatureRange() {
+ return Optional.ofNullable(temperatureRange);
+ }
+
+ public TemperatureRange getTemperatureRange() {
+ return temperatureRange;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) { // short circuit if same object
+ return true;
+ }
+
+ if (!(other instanceof SearchPatientDescriptor)) { // instanceof handles nulls
+ return false;
+ }
+
+ SearchPatientDescriptor e = (SearchPatientDescriptor) other; // state check
+
+ return getName().equals(e.getName())
+ && getTemperatureRange().equals(e.getTemperatureRange());
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/commands/room/AllocateRoomCommand.java b/src/main/java/seedu/address/logic/commands/room/AllocateRoomCommand.java
new file mode 100644
index 00000000000..29846456ea4
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/room/AllocateRoomCommand.java
@@ -0,0 +1,214 @@
+package seedu.address.logic.commands.room;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_PATIENT_NAME;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_ROOM_NUMBER;
+import static seedu.address.commons.core.Messages.MESSAGE_PATIENT_ALREADY_ASSIGNED;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_NAME;
+
+import java.util.Optional;
+
+import seedu.address.commons.util.CollectionUtil;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.patient.Name;
+import seedu.address.model.patient.Patient;
+import seedu.address.model.room.Room;
+import seedu.address.model.room.RoomTasks;
+
+//@@author LeeMingDe
+/**
+ * Edits the details of a room identified by the room number in the app.
+ * Allows setting/removing/changing patient in the room and changing the room number of the room.
+ */
+public class AllocateRoomCommand extends Command {
+
+ public static final String COMMAND_WORD = "allocateroom";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Allocate a patient to a room. \n"
+ + "Existing values will be overwritten by the input values. \n"
+ + "To make an occupied room empty, the parameter for patient name should be set to '-'.\n"
+ + "Parameters: ROOM NUMBER "
+ + "[" + PREFIX_NAME + "PATIENT NAME]\n"
+ + "Example: " + COMMAND_WORD + " 23 "
+ + PREFIX_NAME + "Mary Doe";
+
+ public static final String MESSAGE_ALLOCATE_ROOM_SUCCESS = "Allocated Room: %1$s";
+ public static final String MESSAGE_NO_PATIENT_TO_REMOVE = "There is no patient in this room to remove.";
+
+ private final Integer roomNumberToAllocate;
+ private final AllocateRoomDescriptor allocateRoomDescriptor;
+ private final boolean toRemove;
+
+ /**
+ * Constructs an AllocateRoomCommand to edit the room with the room number {@code Integer}.
+ *
+ * @param roomNumberToAllocate Room number to edit.
+ * @param allocateRoomDescriptor Details to edit the room with.
+ * @param toRemove Room if it is true.
+ */
+ public AllocateRoomCommand(Integer roomNumberToAllocate, AllocateRoomDescriptor allocateRoomDescriptor,
+ boolean toRemove) {
+ requireAllNonNull(roomNumberToAllocate, allocateRoomDescriptor, toRemove);
+ this.roomNumberToAllocate = roomNumberToAllocate;
+ this.allocateRoomDescriptor = new AllocateRoomDescriptor(allocateRoomDescriptor);
+ this.toRemove = toRemove;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ Optional roomOptional = model.getRoomWithRoomNumber(roomNumberToAllocate);
+
+ if (roomOptional.isEmpty()) {
+ throw new CommandException(MESSAGE_INVALID_ROOM_NUMBER);
+ }
+
+ Room roomToAllocate = roomOptional.get();
+ Room roomWithAllocatedPatient = allocatePatientToRoom(model, roomToAllocate, allocateRoomDescriptor);
+
+ if (!roomToAllocate.isSameRoom(roomWithAllocatedPatient) && model.hasRoom(roomWithAllocatedPatient)) {
+ throw new CommandException(MESSAGE_PATIENT_ALREADY_ASSIGNED);
+ }
+
+ model.setSingleRoom(roomToAllocate, roomWithAllocatedPatient);
+ return new CommandResult(String.format(MESSAGE_ALLOCATE_ROOM_SUCCESS, roomWithAllocatedPatient));
+ }
+
+ /**
+ * Creates and returns a {@code Room} with the details of {@code roomToAllocate}
+ * edited with {@code allocateRoomDescriptor}.
+ *
+ * @param model Current model.
+ * @param roomToAllocate Room that is to be edited.
+ * @param allocateRoomDescriptor Details to edit the room with.
+ * @return Room that has been edited.
+ */
+ private Room allocatePatientToRoom(Model model, Room roomToAllocate,
+ AllocateRoomDescriptor allocateRoomDescriptor) throws CommandException {
+ assert (roomToAllocate != null);
+ assert (allocateRoomDescriptor != null);
+
+ int roomNumber = roomToAllocate.getRoomNumber();
+ RoomTasks roomTaskList = new RoomTasks(roomToAllocate.getReadOnlyTasks());
+ if (toRemove) {
+ if (roomToAllocate.getPatient().isEmpty()) {
+ throw new CommandException(MESSAGE_NO_PATIENT_TO_REMOVE);
+ }
+ return new Room(roomNumber, false, Optional.empty(), roomTaskList);
+ }
+ Name patientName = allocateRoomDescriptor.getPatientName().get(); //definitely has name
+ if (model.isPatientAssignedToRoom(patientName)) {
+ throw new CommandException(MESSAGE_PATIENT_ALREADY_ASSIGNED);
+ }
+ Optional updatedPatient = model.getPatientWithName(patientName);
+ if (updatedPatient.isEmpty()) {
+ throw new CommandException(MESSAGE_INVALID_PATIENT_NAME);
+ } else {
+ Room updatedRoom = new Room(roomNumber, updatedPatient, roomTaskList);
+
+ return updatedRoom;
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) { //short circuit if same object
+ return true;
+ }
+
+ if (!(other instanceof AllocateRoomCommand)) { // instanceof handles nulls
+ return false;
+ }
+
+ AllocateRoomCommand e = (AllocateRoomCommand) other; // state check
+ return roomNumberToAllocate.equals(e.roomNumberToAllocate)
+ && allocateRoomDescriptor.equals(e.allocateRoomDescriptor);
+ }
+
+ /**
+ * Stores the details to edit the room with. Each non-empty field value will replace the
+ * corresponding field value of the room.
+ */
+ public static class AllocateRoomDescriptor {
+ private Integer roomNumber;
+ private Boolean isOccupied;
+ private Name patientName;
+
+ public AllocateRoomDescriptor() {}
+
+ /**
+ * Constructs an AllocateRoomDescriptor object with the following fields.
+ *
+ * @param toCopy AllocateRoomDescriptor to copy the fields from.
+ */
+ public AllocateRoomDescriptor(AllocateRoomDescriptor toCopy) {
+ setOccupied(toCopy.isOccupied);
+ setPatientName(toCopy.patientName);
+ }
+
+ public boolean isAnyFieldEdited() {
+ return CollectionUtil.isAnyNonNull(patientName, isOccupied);
+ }
+
+ public void setRoomNumber(Integer roomNumber) {
+ this.roomNumber = roomNumber;
+ }
+
+ public Optional getRoomNumber() {
+ return Optional.ofNullable(roomNumber);
+ }
+
+ public void setOccupied(Boolean isOccupied) {
+ this.isOccupied = isOccupied;
+ }
+
+ public Optional getIsOccupied() {
+ return Optional.ofNullable(isOccupied);
+ }
+
+ public void setPatientName(Name patientName) {
+ this.patientName = patientName;
+ }
+
+ public Optional getPatientName() {
+ return Optional.ofNullable(patientName);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) { // short circuit if same object
+ return true;
+ }
+
+ if (!(other instanceof AllocateRoomDescriptor)) { // instanceof handles nulls
+ return false;
+ }
+
+ AllocateRoomDescriptor e = (AllocateRoomDescriptor) other; // state check
+ return getIsOccupied().equals(e.getIsOccupied())
+ && getPatientName().equals(e.getPatientName());
+ }
+
+ @Override
+ public String toString() {
+ return "AllocateRoomDescriptor{"
+ + ", isOccupied=" + isOccupied
+ + ", patientName=" + patientName
+ + '}';
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "AllocateRoomCommand{"
+ + "roomNumberToEdit=" + roomNumberToAllocate
+ + ", allocateRoomDescriptor=" + allocateRoomDescriptor
+ + '}';
+ }
+ //@@author LeeMingDe
+}
diff --git a/src/main/java/seedu/address/logic/commands/room/FindEmptyRoomCommand.java b/src/main/java/seedu/address/logic/commands/room/FindEmptyRoomCommand.java
new file mode 100644
index 00000000000..6d45abd1c7f
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/room/FindEmptyRoomCommand.java
@@ -0,0 +1,44 @@
+package seedu.address.logic.commands.room;
+
+import java.util.PriorityQueue;
+import java.util.function.Predicate;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.room.Room;
+
+/**
+ * Finds the next empty room with the lowest room number
+ */
+//@@author itssodium
+public class FindEmptyRoomCommand extends Command {
+ public static final String COMMAND_WORD = "findemptyroom";
+ public static final String MESSAGE_NO_EMPTY_ROOM = "There are unfortunately no more empty rooms!";
+ public static final String NUMBER_OF_ROOMS_UNDEFINED = "Please define number of rooms";
+ public static final String MESSAGE_SUCCESS = "Room Number %s is empty";
+
+ public FindEmptyRoomCommand() {}
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ PriorityQueue rooms = model.getRooms();
+ if (model.getNumOfRooms() == 0) {
+ throw new CommandException(NUMBER_OF_ROOMS_UNDEFINED);
+ }
+ Room room = rooms.peek();
+ assert room != null;
+ if (room.isOccupied()) {
+ throw new CommandException(MESSAGE_NO_EMPTY_ROOM);
+ }
+ Predicate predicate = givePredicate(room);
+ model.updateFilteredRoomList(predicate);
+ return new CommandResult(String.format(MESSAGE_SUCCESS, room.getRoomNumber()));
+ }
+
+ private Predicate givePredicate(Room room) {
+ Predicate roomPredicate = room1 -> room1.getRoomNumber() == room.getRoomNumber();
+ return roomPredicate;
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/room/InitRoomCommand.java b/src/main/java/seedu/address/logic/commands/room/InitRoomCommand.java
new file mode 100644
index 00000000000..e048278e55c
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/room/InitRoomCommand.java
@@ -0,0 +1,76 @@
+package seedu.address.logic.commands.room;
+
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_ROOMS;
+
+import java.util.Objects;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+
+/**
+ * Adds the number of hotel rooms in a hotel
+ */
+//@@author itssodium
+public class InitRoomCommand extends Command {
+ public static final String COMMAND_WORD = "initroom";
+ public static final String MESSAGE_ZERO_CANNOT_BE_AN_INPUT = "Please input a positive value";
+ public static final String MESSAGE_NEGATIVE_VALUES_CANNOT_BE_INPUT = "Please check your value! "
+ + "You have input a negative value!";
+ public static final String MESSAGE_LARGE_NUMBER_OF_ROOMS_INPUT = "Please reduce the number of rooms input."
+ + "maximum number of rooms are 5000";
+ public static final String MESSAGE_INSUFFICIENT_ROOMS = "There would be insufficient rooms for existing number of "
+ + "patients of %d";
+ public static final String MESSAGE_SUCCESS = "Initialize the number of rooms to %d rooms in the application";
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Initializes the number of rooms in the "
+ + "quarantine facility to the app, if there was data given previously, they would be stored.\n"
+ + "Parameters: NUMBER_OF_ROOMS\n"
+ + "Example: " + COMMAND_WORD + " 123";
+
+ private static final int ZERO = 0;
+ private static final int MAXIMUM_NUMBER_OF_ROOMS = 500;
+
+ private int numOfRooms;
+
+ /**
+ * Creates an AddCommand to add the number of rooms available in a hotel
+ */
+ public InitRoomCommand(int numOfRooms) {
+ this.numOfRooms = numOfRooms;
+ }
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ model.setInitNumOfRooms(numOfRooms);
+ model.updateFilteredRoomList(PREDICATE_SHOW_ALL_ROOMS);
+ if (numOfRooms == ZERO) {
+ throw new CommandException(MESSAGE_ZERO_CANNOT_BE_AN_INPUT);
+ } else if (numOfRooms < ZERO) {
+ throw new CommandException(MESSAGE_NEGATIVE_VALUES_CANNOT_BE_INPUT);
+ } else if (numOfRooms > MAXIMUM_NUMBER_OF_ROOMS) {
+ throw new CommandException(MESSAGE_LARGE_NUMBER_OF_ROOMS_INPUT);
+ } else if (model.getNumOfRooms() > numOfRooms && !model.hasSpaceForRooms()) {
+ throw new CommandException(String.format(MESSAGE_INSUFFICIENT_ROOMS, model.getNumOfExcessOccupiedRooms()));
+ }
+ model.initRooms(numOfRooms);
+ model.updateFilteredRoomList(PREDICATE_SHOW_ALL_ROOMS);
+ return new CommandResult(String.format(MESSAGE_SUCCESS, numOfRooms));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ InitRoomCommand that = (InitRoomCommand) o;
+ return numOfRooms == that.numOfRooms;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(numOfRooms);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/room/ListRoomCommand.java b/src/main/java/seedu/address/logic/commands/room/ListRoomCommand.java
new file mode 100644
index 00000000000..7e1465043b6
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/room/ListRoomCommand.java
@@ -0,0 +1,23 @@
+package seedu.address.logic.commands.room;
+
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_ROOMS;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+
+public class ListRoomCommand extends Command {
+ public static final String COMMAND_WORD = "listroom";
+ public static final String MESSAGE_SUCCESS = "All rooms are listed.";
+ public static final String NUMBER_OF_ROOMS_UNDEFINED =
+ "There is no room in the app yet. Please define the number of rooms using initRooms command.";
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ if (model.getRooms().size() == 0) {
+ throw new CommandException(NUMBER_OF_ROOMS_UNDEFINED);
+ }
+ model.updateFilteredRoomList(PREDICATE_SHOW_ALL_ROOMS);
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/room/SearchRoomCommand.java b/src/main/java/seedu/address/logic/commands/room/SearchRoomCommand.java
new file mode 100644
index 00000000000..73b1d14f36e
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/room/SearchRoomCommand.java
@@ -0,0 +1,143 @@
+package seedu.address.logic.commands.room;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_PATIENT_NAME;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_ROOM_NUMBER;
+import static seedu.address.commons.core.Messages.MESSAGE_PATIENT_NO_ROOM;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.room.RoomCliSyntax.PREFIX_ROOM_NUMBER;
+
+import java.util.Optional;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.commons.util.CollectionUtil;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.patient.Name;
+
+//@@author chiamyunqing
+/**
+ * Searches a room by the given room number or by the patient name who resides in the room.
+ */
+public class SearchRoomCommand extends Command {
+
+ public static final String COMMAND_WORD = "searchroom";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Searches the room with the given room number or with the given individual.\n"
+ + "Only one of the parameter can be provided.\n"
+ + "Parameters: "
+ + PREFIX_ROOM_NUMBER + "ROOM NUMBER or "
+ + PREFIX_NAME + "NAME \n"
+ + "Example: " + COMMAND_WORD + " "
+ + PREFIX_ROOM_NUMBER + "130 or "
+ + PREFIX_NAME + "John Doe";
+
+ public static final String MESSAGE_SUCCESS = "Room has been found and listed.";
+ private final SearchRoomDescriptor descriptor;
+
+ /**
+ * Creates a SearchRoomCommand to look for the specified room based on the inputs
+ * in searchRoomDescriptor.
+ *
+ * @param descriptor Details to search the room with.
+ */
+ public SearchRoomCommand(SearchRoomDescriptor descriptor) {
+ requireNonNull(descriptor);
+ this.descriptor = descriptor;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ assert(descriptor.hasParameter());
+
+ if (descriptor.getRoomNumber().isPresent()) {
+ Integer roomNumber = descriptor.roomNumber;
+ Index index = model.checkIfRoomPresent(roomNumber);
+ if (index.getZeroBased() == 0) {
+ throw new CommandException(MESSAGE_INVALID_ROOM_NUMBER);
+ }
+ model.updateFilteredRoomList(room -> room.getRoomNumber() == roomNumber);
+ return new CommandResult(MESSAGE_SUCCESS);
+
+ }
+
+ Name patientName = descriptor.patientName;
+ if (model.getPatientWithName(patientName).isEmpty()) {
+ throw new CommandException(MESSAGE_INVALID_PATIENT_NAME);
+ } else if (!model.isPatientAssignedToRoom(patientName)) {
+ throw new CommandException(MESSAGE_PATIENT_NO_ROOM);
+ }
+ model.updateFilteredRoomList(room -> room.isOccupied()
+ && room.getPatient().get().getName().equals(patientName));
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof SearchRoomCommand // instanceof handles nulls
+ && descriptor.equals(((SearchRoomCommand) other).descriptor));
+ }
+
+ /**
+ * Stores the details to search the room.
+ * Each non-empty field value will replace the corresponding field value of the room.
+ */
+ public static class SearchRoomDescriptor {
+ private Integer roomNumber;
+ private Name patientName;
+
+ public SearchRoomDescriptor() {
+ }
+ /**
+ * Constructs a SearchRoomDescriptor object with the following fields.
+ *
+ * @param toCopy SearchRoomDescriptor to copy the fields from.
+ */
+ public SearchRoomDescriptor(SearchRoomDescriptor toCopy) {
+ setRoomNumber(toCopy.roomNumber);
+ setPatientName(toCopy.patientName);
+ }
+
+ public boolean hasParameter() {
+ return CollectionUtil.isAnyNonNull(roomNumber, patientName);
+ }
+
+ public void setRoomNumber(Integer roomNumber) {
+ this.roomNumber = roomNumber;
+ }
+
+ public Optional getRoomNumber() {
+ return Optional.ofNullable(roomNumber);
+ }
+
+ public void setPatientName(Name patientName) {
+ this.patientName = patientName;
+ }
+
+ public Optional getPatientName() {
+ return Optional.ofNullable(patientName);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) { // short circuit if same object
+ return true;
+ }
+
+ if (!(other instanceof SearchRoomDescriptor)) { // instanceof handles nulls
+ return false;
+ }
+
+ SearchRoomDescriptor e = (SearchRoomDescriptor) other; // state check
+ return getRoomNumber().equals(e.getRoomNumber())
+ && getPatientName().equals(e.getPatientName());
+ }
+ }
+}
+
+
diff --git a/src/main/java/seedu/address/logic/commands/task/AddTaskCommand.java b/src/main/java/seedu/address/logic/commands/task/AddTaskCommand.java
new file mode 100644
index 00000000000..cc17b83bb63
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/task/AddTaskCommand.java
@@ -0,0 +1,74 @@
+package seedu.address.logic.commands.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.parser.room.RoomCliSyntax.PREFIX_ROOM_NUMBER;
+import static seedu.address.logic.parser.task.TaskCliSyntax.PREFIX_DESCRIPTION;
+import static seedu.address.logic.parser.task.TaskCliSyntax.PREFIX_DUE_DATE;
+
+import java.util.Optional;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.room.Room;
+import seedu.address.model.task.Task;
+
+//@@author w-yeehong
+/**
+ * Adds a {@code Task} to a {@code Room}.
+ */
+public class AddTaskCommand extends Command {
+
+ public static final String COMMAND_WORD = "addtask";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a task to Covigent. "
+ + "\nParameters: "
+ + PREFIX_DESCRIPTION + "DESCRIPTION "
+ + PREFIX_ROOM_NUMBER + "ROOM NUMBER "
+ + "[" + PREFIX_DUE_DATE + "DUE DATE]\n"
+ + "Example: " + COMMAND_WORD + " "
+ + PREFIX_DESCRIPTION + "Remind John to return his bedsheets "
+ + PREFIX_ROOM_NUMBER + "3 "
+ + PREFIX_DUE_DATE + "20200928 2359";
+
+ public static final String MESSAGE_ADD_TASK_SUCCESS = "New Task added to Room %1$d. \nDescription: %2$s";
+
+ private final Task taskToAdd;
+ private final int roomNumber;
+
+ /**
+ * Creates an AddTaskCommand to add the specified {@code Task} to a {@code Room}
+ * with the {@code roomNumber}.
+ */
+ public AddTaskCommand(Task task, int roomNumber) {
+ requireNonNull(task);
+ assert roomNumber > 0 : "Room number should be greater than 0.";
+ taskToAdd = task;
+ this.roomNumber = roomNumber;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ Optional optionalRoom = model.getRoomWithRoomNumber(roomNumber);
+ assert optionalRoom != null : "The return value from Model#getRoomWithRoomNumber(...) should never be null.";
+
+ Room room = optionalRoom.orElseThrow(() ->
+ new CommandException(Messages.MESSAGE_INVALID_ROOM_NUMBER));
+
+ model.addTaskToRoom(taskToAdd, room);
+ return new CommandResult(String.format(MESSAGE_ADD_TASK_SUCCESS,
+ roomNumber, taskToAdd));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof AddTaskCommand // instanceof handles nulls
+ && taskToAdd.equals(((AddTaskCommand) other).taskToAdd)
+ && roomNumber == (((AddTaskCommand) other).roomNumber));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/task/DeleteTaskCommand.java b/src/main/java/seedu/address/logic/commands/task/DeleteTaskCommand.java
new file mode 100644
index 00000000000..2e32a926d23
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/task/DeleteTaskCommand.java
@@ -0,0 +1,82 @@
+package seedu.address.logic.commands.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.parser.room.RoomCliSyntax.PREFIX_ROOM_NUMBER;
+import static seedu.address.logic.parser.task.TaskCliSyntax.PREFIX_TASK_NUMBER;
+
+import java.util.Optional;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.room.Room;
+import seedu.address.model.task.Task;
+
+//@@author w-yeehong
+/**
+ * Deletes a {@code Task} from a {@code Room}.
+ * The {@code Room} is identified by its room number.
+ * The {@code Task} is identified by its one-based index in the {@code TaskList}
+ * of {@code Room}.
+ */
+public class DeleteTaskCommand extends Command {
+
+ public static final String COMMAND_WORD = "deletetask";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Deletes a task from Covigent. "
+ + "\nParameters: "
+ + PREFIX_ROOM_NUMBER + "ROOM NUMBER "
+ + PREFIX_TASK_NUMBER + "TASK NUMBER "
+ + "\nExample: " + COMMAND_WORD + " "
+ + PREFIX_ROOM_NUMBER + "1 "
+ + PREFIX_TASK_NUMBER + "3";
+
+ public static final String MESSAGE_DELETE_TASK_SUCCESS = "Task %1$d deleted from Room %2$d. \nDescription: %3$s";
+
+ private final int roomNumber;
+ private final Index taskIndex;
+
+ /**
+ * Creates a DeleteTaskCommand to remove the {@code Task} with {@code taskIndex} from
+ * the {@code Room} with the {@code roomNumber}.
+ */
+ public DeleteTaskCommand(int roomNumber, Index taskIndex) {
+ requireNonNull(taskIndex);
+ assert roomNumber > 0 : "Room number should be greater than 0.";
+ this.roomNumber = roomNumber;
+ this.taskIndex = taskIndex;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ // Get the room from which the user wants to delete the task
+ Optional optionalRoom = model.getRoomWithRoomNumber(roomNumber);
+ assert optionalRoom != null : "The return value from Model#getRoomWithRoomNumber(...) should never be null.";
+ Room room = optionalRoom.orElseThrow(() ->
+ new CommandException(Messages.MESSAGE_INVALID_ROOM_NUMBER));
+
+ // Get the task which the user wants to delete
+ Optional optionalTask = model.getTaskFromRoomWithTaskIndex(taskIndex, room);
+ assert optionalTask != null : "The return value from Model#getTaskFromRoomWithTaskIndex(...)"
+ + " should not be null.";
+ Task taskToDelete = optionalTask.orElseThrow(() ->
+ new CommandException(Messages.MESSAGE_INVALID_TASK_INDEX));
+
+ model.deleteTaskFromRoom(taskToDelete, room);
+ return new CommandResult(String.format(MESSAGE_DELETE_TASK_SUCCESS,
+ taskIndex.getOneBased(), roomNumber, taskToDelete));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof DeleteTaskCommand // instanceof handles nulls
+ && roomNumber == (((DeleteTaskCommand) other).roomNumber)
+ && taskIndex.equals((((DeleteTaskCommand) other).taskIndex)));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/task/EditTaskCommand.java b/src/main/java/seedu/address/logic/commands/task/EditTaskCommand.java
new file mode 100644
index 00000000000..5b78faff8c1
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/task/EditTaskCommand.java
@@ -0,0 +1,168 @@
+package seedu.address.logic.commands.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.logic.parser.room.RoomCliSyntax.PREFIX_ROOM_NUMBER;
+import static seedu.address.logic.parser.task.TaskCliSyntax.PREFIX_DESCRIPTION;
+import static seedu.address.logic.parser.task.TaskCliSyntax.PREFIX_DUE_DATE;
+import static seedu.address.logic.parser.task.TaskCliSyntax.PREFIX_TASK_NUMBER;
+
+import java.util.Optional;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.commons.util.CollectionUtil;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.room.Room;
+import seedu.address.model.task.DateTimeDue;
+import seedu.address.model.task.Description;
+import seedu.address.model.task.Task;
+
+//@@author w-yeehong
+/**
+ * Edits and replaces a {@code Task} in a {code Room}.
+ * The {@code Room} is identified by its index in the {@code RoomList}
+ * of {@code Model}.
+ * The {@code Task} is identified by its index in the {@code TaskList}
+ * of {@code Room}.
+ */
+public class EditTaskCommand extends Command {
+
+ public static final String COMMAND_WORD = "edittask";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits a task in Covigent.\n"
+ + "Existing values will be overwritten by the input values.\n"
+ + "Parameters: "
+ + PREFIX_ROOM_NUMBER + "ROOM NUMBER "
+ + PREFIX_TASK_NUMBER + "TASK NUMBER "
+ + "[" + PREFIX_DESCRIPTION + "DESCRIPTION] "
+ + "[" + PREFIX_DUE_DATE + "DUE DATE]"
+ + "\nExample: " + COMMAND_WORD + " "
+ + PREFIX_ROOM_NUMBER + "1 "
+ + PREFIX_TASK_NUMBER + "3 "
+ + PREFIX_DUE_DATE + "20200930 1700";
+
+ public static final String MESSAGE_EDIT_TASK_SUCCESS = "Task %1$d edited from Room %2$d. \nDescription: %3$s";
+
+ private final int roomNumber;
+ private final Index taskIndex;
+ private final EditTaskDescriptor editTaskDescriptor;
+
+ /**
+ * Creates an EditTaskCommand to replace a {@code Task} in a {@code Room} with another
+ * {@code Task} described by {@code editTaskDescriptor}.
+ */
+ public EditTaskCommand(int roomNumber, Index taskIndex, EditTaskDescriptor editTaskDescriptor) {
+ requireAllNonNull(taskIndex, editTaskDescriptor);
+ assert roomNumber > 0 : "Room number should be greater than 0.";
+ this.roomNumber = roomNumber;
+ this.taskIndex = taskIndex;
+ this.editTaskDescriptor = new EditTaskDescriptor(editTaskDescriptor);
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ // Get the room from which the user wants to delete the task
+ Optional optionalRoom = model.getRoomWithRoomNumber(roomNumber);
+ assert optionalRoom != null : "The return value from Model#getRoomWithRoomNumber(...) should never be null.";
+ Room room = optionalRoom.orElseThrow(() ->
+ new CommandException(Messages.MESSAGE_INVALID_ROOM_NUMBER));
+
+ // Get the task which the user wants to edit
+ Optional optionalTask = model.getTaskFromRoomWithTaskIndex(taskIndex, room);
+ assert optionalTask != null : "The return value from Model#getTaskFromRoomWithTaskIndex(...)"
+ + " should not be null.";
+ Task taskToEdit = optionalTask.orElseThrow(() ->
+ new CommandException(Messages.MESSAGE_INVALID_TASK_INDEX));
+
+ Task editedTask = createEditedTask(taskToEdit, editTaskDescriptor);
+ if (taskToEdit.equals(editedTask)) {
+ throw new CommandException(Messages.MESSAGE_TASK_NOT_EDITED);
+ }
+
+ model.setTaskToRoom(taskToEdit, editedTask, room);
+ return new CommandResult(String.format(MESSAGE_EDIT_TASK_SUCCESS,
+ taskIndex.getOneBased(), roomNumber, editedTask));
+ }
+
+ /**
+ * Creates and returns a {@code Task} with the details of {@code taskToEdit}
+ * edited with {@code editTaskDescriptor}.
+ *
+ * @param taskToEdit Task that is to be edited.
+ * @param editTaskDescriptor Details to edit the task with.
+ * @return Task that has been edited.
+ */
+ private static Task createEditedTask(Task taskToEdit, EditTaskDescriptor editTaskDescriptor) {
+ requireAllNonNull(taskToEdit, editTaskDescriptor);
+
+ Description updatedDescription = editTaskDescriptor.getDescription().orElse(taskToEdit.getDescription());
+ DateTimeDue updatedDueAt = editTaskDescriptor.getDateTimeDue().orElse(taskToEdit.getDueAt());
+
+ return new Task(updatedDescription, updatedDueAt);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof EditTaskCommand // instanceof handles nulls
+ && roomNumber == (((EditTaskCommand) other).roomNumber)
+ && taskIndex.equals(((EditTaskCommand) other).taskIndex)
+ && editTaskDescriptor.equals(((EditTaskCommand) other).editTaskDescriptor));
+ }
+
+ /**
+ * Stores the details used to edit the task. Each non-empty field value will replace the
+ * corresponding field value of the task.
+ */
+ public static class EditTaskDescriptor {
+ private Description description;
+ private DateTimeDue dueAt;
+
+ // Prevents instantiation
+ public EditTaskDescriptor() {}
+
+ /**
+ * Constructs a EditTaskDescriptor object with the following fields.
+ *
+ * @param toCopy EditTaskDescriptor to copy the fields from.
+ */
+ public EditTaskDescriptor(EditTaskDescriptor toCopy) {
+ setDescription(toCopy.description);
+ setDateTimeDue(toCopy.dueAt);
+ }
+
+ public boolean isAnyFieldEdited() {
+ return CollectionUtil.isAnyNonNull(description, dueAt);
+ }
+
+ public void setDescription(Description description) {
+ this.description = description;
+ }
+
+ public Optional getDescription() {
+ return Optional.ofNullable(description);
+ }
+
+ public void setDateTimeDue(DateTimeDue dueAt) {
+ this.dueAt = dueAt;
+ }
+
+ public Optional getDateTimeDue() {
+ return Optional.ofNullable(dueAt);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof EditTaskDescriptor // instanceof handles nulls
+ && getDescription().equals(((EditTaskDescriptor) other).getDescription())
+ && getDateTimeDue().equals(((EditTaskDescriptor) other).getDateTimeDue()));
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/task/ListTaskCommand.java b/src/main/java/seedu/address/logic/commands/task/ListTaskCommand.java
new file mode 100644
index 00000000000..6f3433a498d
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/task/ListTaskCommand.java
@@ -0,0 +1,25 @@
+package seedu.address.logic.commands.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_TASKS;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.model.Model;
+
+/**
+ * Lists all Tasks in the Covigent to the user.
+ */
+public class ListTaskCommand extends Command {
+
+ public static final String COMMAND_WORD = "listtask";
+
+ public static final String MESSAGE_SUCCESS = "All tasks are listed.";
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ model.updateTasksInFilteredRoomTaskRecords(PREDICATE_SHOW_ALL_TASKS);
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/task/SearchTaskCommand.java b/src/main/java/seedu/address/logic/commands/task/SearchTaskCommand.java
new file mode 100644
index 00000000000..fc7549c76c7
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/task/SearchTaskCommand.java
@@ -0,0 +1,81 @@
+package seedu.address.logic.commands.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.logic.parser.task.TaskCliSyntax.PREFIX_DUE_DATE;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javafx.collections.ObservableList;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.room.Room;
+import seedu.address.model.task.DateTimeDue;
+import seedu.address.model.task.DueDatePredicate;
+import seedu.address.model.task.Task;
+
+/**
+ * Searches a {@code Task} before a {@code DateTimeDue}.
+ */
+public class SearchTaskCommand extends Command {
+
+ public static final String COMMAND_WORD = "searchtask";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Searches tasks in Covigent. "
+ + "\nParameters: "
+ + "[" + PREFIX_DUE_DATE + "DUE DATE]\n"
+ + "Example: " + COMMAND_WORD + " "
+ + PREFIX_DUE_DATE + "20200928 2359";
+
+ public static final String MESSAGE_SEARCH_TASK_SUCCESS = "Tasks before the due date found.";
+ public static final String MESSAGE_TASK_NOT_FOUND = "There is no task that matches your criteria.";
+
+
+ private final DateTimeDue duedate;
+ private ObservableList tasks;
+ private DueDatePredicate datePredicate;
+
+ /**
+ * Creates an SearchTaskCommand to Search the specified {@code Task} with {@code DateTimeDue}
+ */
+ public SearchTaskCommand(DateTimeDue duedate) {
+ requireAllNonNull(duedate);
+ this.duedate = duedate;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List rooms = model.getRoomListObservableList();
+ ArrayList taskListWithDesirableResult = new ArrayList<>();
+ datePredicate = new DueDatePredicate(duedate);
+
+ for (Room room : rooms) {
+ tasks = room.getReadOnlyTasks();
+ for (Task task : tasks) {
+ if (datePredicate.test(task)) {
+ taskListWithDesirableResult.add(task);
+ break;
+ }
+ }
+ }
+
+ if (taskListWithDesirableResult.size() < 1) {
+ model.updateTasksInFilteredRoomTaskRecords(datePredicate);
+ throw new CommandException(MESSAGE_TASK_NOT_FOUND);
+ }
+ assert taskListWithDesirableResult.size() >= 1;
+ model.updateTasksInFilteredRoomTaskRecords(datePredicate);
+ return new CommandResult(String.format(MESSAGE_SEARCH_TASK_SUCCESS));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this
+ || (other instanceof SearchTaskCommand
+ && duedate.equals(((SearchTaskCommand) other).duedate));
+ }
+}
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/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java
deleted file mode 100644
index 1e466792b46..00000000000
--- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.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;
-
-/**
- * Parses user input.
- */
-public class AddressBookParser {
-
- /**
- * Used for initial separation of command word and args.
- */
- private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)");
-
- /**
- * Parses user input into command for execution.
- *
- * @param userInput full user input string
- * @return the command based on the user input
- * @throws ParseException if the user input does not conform the expected format
- */
- public Command parseCommand(String userInput) throws ParseException {
- final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim());
- if (!matcher.matches()) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE));
- }
-
- final String commandWord = matcher.group("commandWord");
- final String arguments = matcher.group("arguments");
- switch (commandWord) {
-
- case AddCommand.COMMAND_WORD:
- return new AddCommandParser().parse(arguments);
-
- case EditCommand.COMMAND_WORD:
- return new EditCommandParser().parse(arguments);
-
- case DeleteCommand.COMMAND_WORD:
- return new DeleteCommandParser().parse(arguments);
-
- case ClearCommand.COMMAND_WORD:
- return new ClearCommand();
-
- case FindCommand.COMMAND_WORD:
- return new FindCommandParser().parse(arguments);
-
- case ListCommand.COMMAND_WORD:
- return new ListCommand();
-
- case ExitCommand.COMMAND_WORD:
- return new ExitCommand();
-
- case HelpCommand.COMMAND_WORD:
- return new HelpCommand();
-
- default:
- throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
- }
- }
-
-}
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/CovigentAppParser.java b/src/main/java/seedu/address/logic/parser/CovigentAppParser.java
new file mode 100644
index 00000000000..eaa67def197
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/CovigentAppParser.java
@@ -0,0 +1,134 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.ExitCommand;
+import seedu.address.logic.commands.HelpCommand;
+import seedu.address.logic.commands.patient.AddPatientCommand;
+import seedu.address.logic.commands.patient.DeletePatientCommand;
+import seedu.address.logic.commands.patient.EditPatientCommand;
+import seedu.address.logic.commands.patient.ListPatientCommand;
+import seedu.address.logic.commands.patient.SearchPatientCommand;
+import seedu.address.logic.commands.room.AllocateRoomCommand;
+import seedu.address.logic.commands.room.FindEmptyRoomCommand;
+import seedu.address.logic.commands.room.InitRoomCommand;
+import seedu.address.logic.commands.room.ListRoomCommand;
+import seedu.address.logic.commands.room.SearchRoomCommand;
+import seedu.address.logic.commands.task.AddTaskCommand;
+import seedu.address.logic.commands.task.DeleteTaskCommand;
+import seedu.address.logic.commands.task.EditTaskCommand;
+import seedu.address.logic.commands.task.ListTaskCommand;
+import seedu.address.logic.commands.task.SearchTaskCommand;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.logic.parser.patient.AddPatientCommandParser;
+import seedu.address.logic.parser.patient.DeletePatientCommandParser;
+import seedu.address.logic.parser.patient.EditPatientCommandParser;
+import seedu.address.logic.parser.patient.SearchPatientCommandParser;
+import seedu.address.logic.parser.room.AllocateRoomCommandParser;
+import seedu.address.logic.parser.room.InitRoomCommandParser;
+import seedu.address.logic.parser.room.SearchRoomCommandParser;
+import seedu.address.logic.parser.task.AddTaskCommandParser;
+import seedu.address.logic.parser.task.DeleteTaskCommandParser;
+import seedu.address.logic.parser.task.EditTaskCommandParser;
+import seedu.address.logic.parser.task.SearchTaskCommandParser;
+
+/**
+ * Parses user input.
+ */
+public class CovigentAppParser {
+
+ /**
+ * Used for initial separation of command word and args.
+ */
+ private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)");
+
+ /**
+ * Parses user input into command for execution.
+ *
+ * @param userInput full user input string
+ * @return the command based on the user input
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public Command parseCommand(String userInput) throws ParseException {
+ final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim());
+ if (!matcher.matches()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE));
+ }
+
+ final String commandWord = matcher.group("commandWord").toLowerCase();
+ final String arguments = matcher.group("arguments");
+
+ switch (commandWord) {
+
+ // create
+
+ case AddPatientCommand.COMMAND_WORD:
+ return new AddPatientCommandParser().parse(arguments);
+
+ case InitRoomCommand.COMMAND_WORD:
+ return new InitRoomCommandParser().parse(arguments);
+
+ case AddTaskCommand.COMMAND_WORD:
+ return new AddTaskCommandParser().parse(arguments);
+
+ // update
+
+ case EditPatientCommand.COMMAND_WORD:
+ return new EditPatientCommandParser().parse(arguments);
+
+ case AllocateRoomCommand.COMMAND_WORD:
+ return new AllocateRoomCommandParser().parse(arguments);
+
+ case EditTaskCommand.COMMAND_WORD:
+ return new EditTaskCommandParser().parse(arguments);
+
+ // read
+
+ case ListPatientCommand.COMMAND_WORD:
+ return new ListPatientCommand();
+
+ case ListTaskCommand.COMMAND_WORD:
+ return new ListTaskCommand();
+
+ // delete
+
+ case DeletePatientCommand.COMMAND_WORD:
+ return new DeletePatientCommandParser().parse(arguments);
+
+ case DeleteTaskCommand.COMMAND_WORD:
+ return new DeleteTaskCommandParser().parse(arguments);
+
+ // others
+
+ case SearchPatientCommand.COMMAND_WORD:
+ return new SearchPatientCommandParser().parse(arguments);
+
+ case SearchRoomCommand.COMMAND_WORD:
+ return new SearchRoomCommandParser().parse(arguments);
+
+ case SearchTaskCommand.COMMAND_WORD:
+ return new SearchTaskCommandParser().parse(arguments);
+
+ case FindEmptyRoomCommand.COMMAND_WORD:
+ return new FindEmptyRoomCommand();
+
+ case ExitCommand.COMMAND_WORD:
+ return new ExitCommand();
+
+ case HelpCommand.COMMAND_WORD:
+ return new HelpCommand();
+
+ case ListRoomCommand.COMMAND_WORD:
+ return new ListRoomCommand();
+
+ default:
+ throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java b/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
deleted file mode 100644
index 522b93081cc..00000000000
--- a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.DeleteCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-
-/**
- * Parses input arguments and creates a new DeleteCommand object
- */
-public class DeleteCommandParser implements Parser {
-
- /**
- * Parses the given {@code String} of arguments in the context of the DeleteCommand
- * and returns a DeleteCommand object for execution.
- * @throws ParseException if the user input does not conform the expected format
- */
- public DeleteCommand parse(String args) throws ParseException {
- try {
- Index index = ParserUtil.parseIndex(args);
- return new DeleteCommand(index);
- } catch (ParseException pe) {
- throw new ParseException(
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE), pe);
- }
- }
-
-}
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
index b117acb9c55..bb280472fb8 100644
--- a/src/main/java/seedu/address/logic/parser/ParserUtil.java
+++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java
@@ -2,123 +2,72 @@
import static java.util.Objects.requireNonNull;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.stream.Stream;
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;
+import seedu.address.logic.parser.room.RoomCliSyntax;
+import seedu.address.logic.parser.task.TaskCliSyntax;
/**
* 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_UNSIGNED_INT = "Please ensure that the value "
+ + "for the field \"%1$s\" is a number between 1 and " + Integer.MAX_VALUE + "."
+ + "\nYour current input: %2$s";
+ //@author LeeMingDe
/**
- * 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}.
+ * Parses {@code roomNumber} into an {@code Integer} and returns it.
* Leading and trailing whitespaces will be trimmed.
*
- * @throws ParseException if the given {@code phone} is invalid.
+ * @throws ParseException if the specified room number is invalid (not non-zero unsigned integer).
*/
- public static Phone parsePhone(String phone) throws ParseException {
- requireNonNull(phone);
- String trimmedPhone = phone.trim();
- if (!Phone.isValidPhone(trimmedPhone)) {
- throw new ParseException(Phone.MESSAGE_CONSTRAINTS);
+ public static Integer parseRoomNumber(String roomNumber) throws ParseException {
+ requireNonNull(roomNumber);
+ String trimmedRoomNumber = roomNumber.trim();
+ if (!StringUtil.isNonZeroUnsignedInteger(trimmedRoomNumber)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_UNSIGNED_INT,
+ RoomCliSyntax.PREFIX_ROOM_NUMBER, roomNumber));
}
- return new Phone(trimmedPhone);
+ return Integer.parseInt(trimmedRoomNumber);
}
+ //@author LeeMingDe
/**
- * Parses a {@code String address} into an {@code Address}.
+ * Parses {@code taskIndex} into an {@code Index} and returns it.
* Leading and trailing whitespaces will be trimmed.
*
- * @throws ParseException if the given {@code address} is invalid.
+ * @throws ParseException if the specified task index is invalid (not non-zero unsigned integer).
*/
- 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);
+ public static Index parseTaskIndex(String taskIndex) throws ParseException {
+ requireNonNull(taskIndex);
+ String trimmedIndex = taskIndex.trim();
+ if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_UNSIGNED_INT,
+ TaskCliSyntax.PREFIX_TASK_NUMBER, taskIndex));
}
- return new Email(trimmedEmail);
+ return Index.fromOneBased(Integer.parseInt(trimmedIndex));
}
/**
- * 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.
+ * Returns true if none of the prefixes contains empty {@code Optional} values in the given
+ * {@code ArgumentMultimap}.
*/
- 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);
+ public static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
}
/**
- * Parses {@code Collection tags} into a {@code Set}.
+ * Returns true if exactly one prefix contains a non-empty {@code Optional} value in the given
+ * {@code ArgumentMultimap}.
*/
- 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;
+ public static boolean isExactlyOnePrefixPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes)
+ .filter(prefix -> argumentMultimap.getValue(prefix).isPresent())
+ .count() == 1;
}
}
diff --git a/src/main/java/seedu/address/logic/parser/patient/AddPatientCommandParser.java b/src/main/java/seedu/address/logic/parser/patient/AddPatientCommandParser.java
new file mode 100644
index 00000000000..8de827da398
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/patient/AddPatientCommandParser.java
@@ -0,0 +1,65 @@
+package seedu.address.logic.parser.patient;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.commands.patient.AddPatientCommand.MESSAGE_USAGE;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_AGE;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_COMMENTS;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_PERIOD_OF_STAY;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_PHONE;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_TEMP;
+
+import seedu.address.logic.commands.patient.AddPatientCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.patient.Age;
+import seedu.address.model.patient.Comment;
+import seedu.address.model.patient.Name;
+import seedu.address.model.patient.Patient;
+import seedu.address.model.patient.PeriodOfStay;
+import seedu.address.model.patient.Phone;
+import seedu.address.model.patient.Temperature;
+
+//@@author chiamyunqing
+/**
+ * Parses input arguments and creates a new AddPatientCommand object.
+ */
+public class AddPatientCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the AddPatientCommand
+ * and returns an AddPatientCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public AddPatientCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_TEMP, PREFIX_PERIOD_OF_STAY,
+ PREFIX_PHONE, PREFIX_AGE, PREFIX_COMMENTS);
+
+ if (!ParserUtil.arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_TEMP,
+ PREFIX_PERIOD_OF_STAY, PREFIX_PHONE, PREFIX_AGE)
+ || !argMultimap.getPreamble().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, MESSAGE_USAGE));
+ }
+
+ Name name = PatientParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get());
+ Temperature temp = PatientParserUtil.parseTemperature(argMultimap.getValue(PREFIX_TEMP).get());
+ PeriodOfStay periodOfStay = PatientParserUtil.parsePeriodOfStay(
+ argMultimap.getValue(PREFIX_PERIOD_OF_STAY).get());
+ Phone phone = PatientParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get());
+ Age age = PatientParserUtil.parseAge(argMultimap.getValue(PREFIX_AGE).get());
+ Comment comment = new Comment("-");
+
+ if (ParserUtil.arePrefixesPresent(argMultimap, PREFIX_COMMENTS)) {
+ comment = PatientParserUtil.parseComment(argMultimap.getValue(PREFIX_COMMENTS).get());
+ }
+
+ Patient patient = new Patient(name, temp, periodOfStay, phone, age, comment);
+ return new AddPatientCommand(patient);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/patient/DeletePatientCommandParser.java b/src/main/java/seedu/address/logic/parser/patient/DeletePatientCommandParser.java
new file mode 100644
index 00000000000..9384bc92c66
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/patient/DeletePatientCommandParser.java
@@ -0,0 +1,29 @@
+package seedu.address.logic.parser.patient;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.address.logic.commands.patient.DeletePatientCommand;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.patient.Name;
+
+//@@author chiamyunqing
+/**
+ * Parses input arguments and creates a new DeletePatientCommand object.
+ */
+public class DeletePatientCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the DeletePatientCommand
+ * and returns a DeletePatientCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public DeletePatientCommand parse(String args) throws ParseException {
+ try {
+ Name patientName = PatientParserUtil.parseName(args);
+ return new DeletePatientCommand(patientName);
+ } catch (ParseException pe) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeletePatientCommand.MESSAGE_USAGE));
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/patient/EditPatientCommandParser.java b/src/main/java/seedu/address/logic/parser/patient/EditPatientCommandParser.java
new file mode 100644
index 00000000000..b79589eaae6
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/patient/EditPatientCommandParser.java
@@ -0,0 +1,80 @@
+package seedu.address.logic.parser.patient;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_AGE;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_COMMENTS;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_PERIOD_OF_STAY;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_PHONE;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_TEMP;
+
+import seedu.address.logic.commands.patient.EditPatientCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.patient.Name;
+
+//@author LeeMingDe
+/**
+ * Parses input arguments and creates a new EditPatientCommand object.
+ */
+public class EditPatientCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the EditPatientCommand
+ * and returns an EditPatientCommand object for execution.
+ *
+ * @param args that are inputted by the user.
+ * @return EditPatientCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format.
+ */
+ public EditPatientCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE,
+ PREFIX_COMMENTS, PREFIX_TEMP, PREFIX_AGE, PREFIX_PERIOD_OF_STAY);
+
+ Name patientTobeEdited;
+ try {
+ patientTobeEdited = PatientParserUtil.parseName(argMultimap.getPreamble().trim().toLowerCase());
+ } catch (ParseException pe) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditPatientCommand.MESSAGE_USAGE));
+ }
+ if (args.trim().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditPatientCommand.MESSAGE_USAGE));
+ }
+ EditPatientCommand.EditPatientDescriptor editPatientDescriptor = new EditPatientCommand.EditPatientDescriptor();
+ if (argMultimap.getValue(PREFIX_NAME).isPresent()) {
+ editPatientDescriptor.setName(PatientParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()));
+ }
+ if (argMultimap.getValue(PREFIX_PHONE).isPresent()) {
+ editPatientDescriptor.setPhone(PatientParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()));
+ }
+ if (argMultimap.getValue(PREFIX_TEMP).isPresent()) {
+ editPatientDescriptor.setTemperature(
+ PatientParserUtil.parseTemperature(argMultimap.getValue(PREFIX_TEMP).get()));
+ }
+ if (argMultimap.getValue(PREFIX_AGE).isPresent()) {
+ editPatientDescriptor.setAge(PatientParserUtil.parseAge(argMultimap.getValue(PREFIX_AGE).get()));
+ }
+ if (argMultimap.getValue(PREFIX_PERIOD_OF_STAY).isPresent()) {
+ editPatientDescriptor.setPeriodOfStay(
+ PatientParserUtil.parsePeriodOfStay(argMultimap.getValue(PREFIX_PERIOD_OF_STAY).get()));
+ }
+ if (argMultimap.getValue(PREFIX_COMMENTS).isPresent()) {
+ editPatientDescriptor.setComment(
+ PatientParserUtil.parseComment(argMultimap.getValue(PREFIX_COMMENTS).get()));
+ }
+
+ if (!editPatientDescriptor.isAnyFieldEdited()) {
+ throw new ParseException(EditPatientCommand.MESSAGE_PATIENT_NOT_EDITED);
+ }
+
+ return new EditPatientCommand(patientTobeEdited, editPatientDescriptor);
+ }
+
+}
+
+
diff --git a/src/main/java/seedu/address/logic/parser/patient/PatientCliSyntax.java b/src/main/java/seedu/address/logic/parser/patient/PatientCliSyntax.java
new file mode 100644
index 00000000000..a82085b3d23
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/patient/PatientCliSyntax.java
@@ -0,0 +1,19 @@
+package seedu.address.logic.parser.patient;
+
+import seedu.address.logic.parser.Prefix;
+
+/**
+ * Contains Command Line Interface (CLI) syntax definitions common to multiple patient-related commands
+ */
+public class PatientCliSyntax {
+
+ /* Prefix definitions */
+ public static final Prefix PREFIX_NAME = new Prefix("n/");
+ public static final Prefix PREFIX_TEMP = new Prefix("t/");
+ public static final Prefix PREFIX_PERIOD_OF_STAY = new Prefix("d/");
+ public static final Prefix PREFIX_PHONE = new Prefix("p/");
+ public static final Prefix PREFIX_AGE = new Prefix("a/");
+ public static final Prefix PREFIX_COMMENTS = new Prefix("c/");
+ public static final Prefix PREFIX_TEMP_RANGE = new Prefix("tr/");
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/patient/PatientParserUtil.java b/src/main/java/seedu/address/logic/parser/patient/PatientParserUtil.java
new file mode 100644
index 00000000000..5213c0846d6
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/patient/PatientParserUtil.java
@@ -0,0 +1,126 @@
+package seedu.address.logic.parser.patient;
+
+import static java.util.Objects.requireNonNull;
+
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.patient.Age;
+import seedu.address.model.patient.Comment;
+import seedu.address.model.patient.Name;
+import seedu.address.model.patient.PeriodOfStay;
+import seedu.address.model.patient.Phone;
+import seedu.address.model.patient.Temperature;
+import seedu.address.model.patient.TemperatureRange;
+
+/**
+ * Contains utility methods used for parsing strings in the various patient-related Parser classes.
+ */
+public class PatientParserUtil {
+
+ /**
+ * 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);
+ }
+
+ //@@author chiamyunqing
+ /**
+ * Parses a {@code String temperature} into a {@code Temperature}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code temperature} is invalid.
+ */
+ public static Temperature parseTemperature(String temp) throws ParseException {
+ requireNonNull(temp);
+ String trimmedTemp = temp.trim();
+ if (!Temperature.isValidTemperature(trimmedTemp)) {
+ throw new ParseException(Temperature.MESSAGE_CONSTRAINTS);
+ }
+ return new Temperature(trimmedTemp);
+ }
+
+ /**
+ * Parses a {@code String period of stay} into a {@code PeriodOfStay}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code period of stay} is invalid.
+ */
+ public static PeriodOfStay parsePeriodOfStay(String periodOfStay) throws ParseException {
+ requireNonNull(periodOfStay);
+ String trimmedPeriodOfStay = periodOfStay.trim();
+ if (!PeriodOfStay.isValidPeriodOfStay(trimmedPeriodOfStay)) {
+ throw new ParseException(PeriodOfStay.getErrorMessage(trimmedPeriodOfStay));
+ }
+ return new PeriodOfStay(trimmedPeriodOfStay);
+ }
+
+ /**
+ * Parses a {@code String age} into a {@code Age}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code age} is invalid.
+ */
+ public static Age parseAge(String age) throws ParseException {
+ requireNonNull(age);
+ String trimmedAge = age.trim();
+ if (!Age.isValidAge(trimmedAge)) {
+ throw new ParseException(Age.getErrorMessage(trimmedAge));
+ }
+ return new Age(trimmedAge);
+ }
+
+ /**
+ * Parses a {@code String comment} into a {@code Comment}
+ * Leading and trailing whitespaces will be trimmed
+ *
+ * @return an "-" comment if no comment is added
+ */
+ public static Comment parseComment(String comment) {
+ if (comment == null || comment.trim().length() == 0) {
+ return new Comment("-");
+ } else {
+ return new Comment(comment.trim());
+ }
+ }
+ //@@author chiamyunqing
+
+ //@@author raymondge
+ /**
+ * Parses a {@code String temperature} into a {@code Temperature}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code temperature} is invalid.
+ */
+ public static TemperatureRange parseTemperatureRange(String tempRange) throws ParseException {
+ requireNonNull(tempRange);
+ String trimmedTempRange = tempRange.trim();
+ if (!TemperatureRange.isValidTemperatureRange(trimmedTempRange)) {
+ throw new ParseException(TemperatureRange.MESSAGE_CONSTRAINTS_TEMPERATURERANGE);
+ }
+ return new TemperatureRange(trimmedTempRange);
+ }
+ //@@author raymondge
+}
diff --git a/src/main/java/seedu/address/logic/parser/patient/SearchPatientCommandParser.java b/src/main/java/seedu/address/logic/parser/patient/SearchPatientCommandParser.java
new file mode 100644
index 00000000000..6ee4759f5f1
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/patient/SearchPatientCommandParser.java
@@ -0,0 +1,49 @@
+package seedu.address.logic.parser.patient;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_TEMP_RANGE;
+
+import seedu.address.logic.commands.patient.SearchPatientCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new SearchPatientCommand object
+ */
+public class SearchPatientCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the SearchPatientCommand
+ * and returns an SearchPatientCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public SearchPatientCommand parse(String args) throws ParseException {
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_TEMP_RANGE);
+
+ if (!ParserUtil.isExactlyOnePrefixPresent(argMultimap, PREFIX_NAME, PREFIX_TEMP_RANGE)
+ || !argMultimap.getPreamble().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, SearchPatientCommand.MESSAGE_USAGE));
+ }
+
+ SearchPatientCommand.SearchPatientDescriptor searchPatientDescriptor =
+ new SearchPatientCommand.SearchPatientDescriptor();
+
+ if (argMultimap.getValue(PREFIX_NAME).isPresent()) {
+ String nameWithoutPrefix = argMultimap.getValue(PREFIX_NAME).get();
+ searchPatientDescriptor.setStringName(nameWithoutPrefix);
+ searchPatientDescriptor.setName(PatientParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()));
+ }
+
+ if (argMultimap.getValue(PREFIX_TEMP_RANGE).isPresent()) {
+ searchPatientDescriptor.setTemperatureRange(
+ PatientParserUtil.parseTemperatureRange(argMultimap.getValue(PREFIX_TEMP_RANGE).get()));
+ }
+
+ return new SearchPatientCommand(searchPatientDescriptor);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/room/AllocateRoomCommandParser.java b/src/main/java/seedu/address/logic/parser/room/AllocateRoomCommandParser.java
new file mode 100644
index 00000000000..5bba4c9caed
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/room/AllocateRoomCommandParser.java
@@ -0,0 +1,66 @@
+package seedu.address.logic.parser.room;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_NAME;
+
+import seedu.address.logic.commands.room.AllocateRoomCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.logic.parser.patient.PatientParserUtil;
+
+//@author LeeMingDe
+/**
+ * Parses input arguments and creates a new AllocateRoomCommand object.
+ */
+public class AllocateRoomCommandParser implements Parser {
+ private static final String INPUT_REMOVE_PATIENT = "-";
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the EditPatientCommand
+ * and returns an EditPatientCommand object for execution.
+ *
+ * @param args that are inputted by the user.
+ * @return EditPatientCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format.
+ */
+ public AllocateRoomCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_NAME);
+
+ Integer roomToBeAllocated;
+ boolean toRemove = false;
+ try {
+ roomToBeAllocated = ParserUtil.parseRoomNumber(argMultimap.getPreamble().trim());
+ } catch (ParseException pe) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AllocateRoomCommand.MESSAGE_USAGE));
+ }
+
+ if (args.trim().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AllocateRoomCommand.MESSAGE_USAGE));
+ }
+
+ AllocateRoomCommand.AllocateRoomDescriptor
+ allocateRoomDescriptor = new AllocateRoomCommand.AllocateRoomDescriptor();
+
+ if (argMultimap.getValue(PREFIX_NAME).isPresent()) {
+ String patientFieldInput = argMultimap.getValue(PREFIX_NAME).get();
+ if (patientFieldInput.equals(INPUT_REMOVE_PATIENT)) {
+ toRemove = true; //empty the room
+ allocateRoomDescriptor.setOccupied(false);
+ } else {
+ allocateRoomDescriptor.setPatientName(PatientParserUtil.parseName(patientFieldInput));
+ }
+ }
+
+ if (!allocateRoomDescriptor.isAnyFieldEdited()) {
+ throw new ParseException(AllocateRoomCommand.MESSAGE_USAGE);
+ }
+
+ return new AllocateRoomCommand(roomToBeAllocated, allocateRoomDescriptor, toRemove);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/room/InitRoomCommandParser.java b/src/main/java/seedu/address/logic/parser/room/InitRoomCommandParser.java
new file mode 100644
index 00000000000..f9b40193a71
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/room/InitRoomCommandParser.java
@@ -0,0 +1,39 @@
+package seedu.address.logic.parser.room;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.commands.room.InitRoomCommand.MESSAGE_USAGE;
+
+import seedu.address.logic.commands.room.InitRoomCommand;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses user input and creates new AddRoomsCommand object
+ */
+//@@author itssodium
+public class InitRoomCommandParser implements Parser {
+ public static final String NUMBER_OF_ROOMS_GIVEN_IN_DIGITS = "Please give the number of digits in integers\n"
+ + "Example: initRoom 200";
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the AddPatientCommand
+ * and returns an AddRoomsCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public InitRoomCommand parse(String args) throws ParseException {
+ String trimmedArgs = args.trim();
+ if (trimmedArgs.isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, MESSAGE_USAGE));
+ //if user does not give number of room
+ }
+ int numberOfRooms = -1; //used so that it can be used to test for NumberFormatException
+ try {
+ numberOfRooms = Integer.parseInt(trimmedArgs);
+ } catch (NumberFormatException nfe) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, NUMBER_OF_ROOMS_GIVEN_IN_DIGITS));
+ //if user does not give number of rooms in terms of integers but gives in terms of words
+ }
+ return new InitRoomCommand(numberOfRooms);
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/room/RoomCliSyntax.java b/src/main/java/seedu/address/logic/parser/room/RoomCliSyntax.java
new file mode 100644
index 00000000000..096afe557ca
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/room/RoomCliSyntax.java
@@ -0,0 +1,13 @@
+package seedu.address.logic.parser.room;
+
+import seedu.address.logic.parser.Prefix;
+
+/**
+ * Contains Command Line Interface (CLI) syntax definitions common to multiple commands.
+ */
+public class RoomCliSyntax {
+
+ /* Prefix definitions */
+ public static final Prefix PREFIX_ROOM_NUMBER = new Prefix("r/");
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/room/SearchRoomCommandParser.java b/src/main/java/seedu/address/logic/parser/room/SearchRoomCommandParser.java
new file mode 100644
index 00000000000..3a24d2286b6
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/room/SearchRoomCommandParser.java
@@ -0,0 +1,52 @@
+package seedu.address.logic.parser.room;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.commands.room.SearchRoomCommand.MESSAGE_USAGE;
+import static seedu.address.logic.parser.patient.PatientCliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.room.RoomCliSyntax.PREFIX_ROOM_NUMBER;
+
+import seedu.address.logic.commands.room.SearchRoomCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.logic.parser.patient.PatientParserUtil;
+import seedu.address.model.patient.Name;
+
+//@@author chiamyunqing
+/**
+ * Parses input arguments and creates a new SearchRoomCommand object.
+ */
+public class SearchRoomCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of SearchRoomCommand
+ * and returns a SearchRoomCommand object for execution.
+ * @throws ParseException if the user input does not conform to the expected format
+ */
+ @Override
+ public SearchRoomCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_ROOM_NUMBER);
+
+ if (!ParserUtil.isExactlyOnePrefixPresent(argMultimap, PREFIX_NAME, PREFIX_ROOM_NUMBER)
+ || !argMultimap.getPreamble().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, MESSAGE_USAGE));
+ }
+
+ SearchRoomCommand.SearchRoomDescriptor descriptor = new SearchRoomCommand.SearchRoomDescriptor();
+
+ if (argMultimap.getValue(PREFIX_NAME).isPresent()) {
+ Name patientName = PatientParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get());
+ descriptor.setPatientName(patientName);
+ return new SearchRoomCommand(descriptor);
+ }
+ //definitely have prefix room number if no prefix name
+ Integer roomNumber = ParserUtil.parseRoomNumber(argMultimap.getValue(PREFIX_ROOM_NUMBER).get());
+ descriptor.setRoomNumber(roomNumber);
+ return new SearchRoomCommand(descriptor);
+
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/task/AddTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/task/AddTaskCommandParser.java
new file mode 100644
index 00000000000..8529b14dba3
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/task/AddTaskCommandParser.java
@@ -0,0 +1,46 @@
+package seedu.address.logic.parser.task;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.room.RoomCliSyntax.PREFIX_ROOM_NUMBER;
+import static seedu.address.logic.parser.task.TaskCliSyntax.PREFIX_DESCRIPTION;
+import static seedu.address.logic.parser.task.TaskCliSyntax.PREFIX_DUE_DATE;
+
+import seedu.address.logic.commands.task.AddTaskCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.task.DateTimeDue;
+import seedu.address.model.task.Description;
+import seedu.address.model.task.Task;
+
+//@@author w-yeehong
+/**
+ * Parses input arguments and creates a new AddTaskCommand object.
+ */
+public class AddTaskCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the AddTaskCommand
+ * and returns an AddTaskCommand object for execution.
+ *
+ * @throws ParseException if the user input does not conform to the expected format.
+ */
+ public AddTaskCommand parse(String args) throws ParseException {
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_DESCRIPTION, PREFIX_ROOM_NUMBER, PREFIX_DUE_DATE);
+
+ if (!ParserUtil.arePrefixesPresent(argMultimap, PREFIX_DESCRIPTION, PREFIX_ROOM_NUMBER)
+ || !argMultimap.getPreamble().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE));
+ }
+
+ Description description = TaskParserUtil.parseDescription(argMultimap.getValue(PREFIX_DESCRIPTION).get());
+ int roomNumber = ParserUtil.parseRoomNumber(argMultimap.getValue(PREFIX_ROOM_NUMBER).get());
+ DateTimeDue dueAt = TaskParserUtil.parseDateTimeDue(argMultimap.getValue(PREFIX_DUE_DATE)); // optional
+
+ Task task = new Task(description, dueAt);
+
+ return new AddTaskCommand(task, roomNumber);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/task/DeleteTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/task/DeleteTaskCommandParser.java
new file mode 100644
index 00000000000..2342556824e
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/task/DeleteTaskCommandParser.java
@@ -0,0 +1,40 @@
+package seedu.address.logic.parser.task;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.room.RoomCliSyntax.PREFIX_ROOM_NUMBER;
+import static seedu.address.logic.parser.task.TaskCliSyntax.PREFIX_TASK_NUMBER;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.task.DeleteTaskCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+
+//@@author w-yeehong
+/**
+ * Parses input arguments and creates a new DeleteTaskCommand object.
+ */
+public class DeleteTaskCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the DeleteTaskCommand
+ * and returns a DeleteTaskCommand object for execution.
+ *
+ * @throws ParseException if the user input does not conform to the expected format.
+ */
+ public DeleteTaskCommand parse(String args) throws ParseException {
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_ROOM_NUMBER, PREFIX_TASK_NUMBER);
+
+ if (!ParserUtil.arePrefixesPresent(argMultimap, PREFIX_ROOM_NUMBER, PREFIX_TASK_NUMBER)
+ || !argMultimap.getPreamble().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteTaskCommand.MESSAGE_USAGE));
+ }
+
+ int roomNumber = ParserUtil.parseRoomNumber(argMultimap.getValue(PREFIX_ROOM_NUMBER).get());
+ Index taskNumber = ParserUtil.parseTaskIndex(argMultimap.getValue(PREFIX_TASK_NUMBER).get());
+
+ return new DeleteTaskCommand(roomNumber, taskNumber);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/task/EditTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/task/EditTaskCommandParser.java
new file mode 100644
index 00000000000..f87ef4c67c3
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/task/EditTaskCommandParser.java
@@ -0,0 +1,71 @@
+package seedu.address.logic.parser.task;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.room.RoomCliSyntax.PREFIX_ROOM_NUMBER;
+import static seedu.address.logic.parser.task.TaskCliSyntax.PREFIX_DESCRIPTION;
+import static seedu.address.logic.parser.task.TaskCliSyntax.PREFIX_DUE_DATE;
+import static seedu.address.logic.parser.task.TaskCliSyntax.PREFIX_TASK_NUMBER;
+
+import java.util.Optional;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.task.EditTaskCommand;
+import seedu.address.logic.commands.task.EditTaskCommand.EditTaskDescriptor;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+
+//@@author w-yeehong
+/**
+ * Parses input arguments and creates a new EditTaskCommand object.
+ */
+public class EditTaskCommandParser implements Parser {
+
+ public static final String INPUT_REMOVE_DUE_DATE = "-";
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the EditTaskCommand
+ * and returns an EditTaskCommand object for execution.
+ *
+ * @throws ParseException if the user input does not conform to the expected format.
+ */
+ public EditTaskCommand parse(String args) throws ParseException {
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args,
+ PREFIX_ROOM_NUMBER, PREFIX_TASK_NUMBER, PREFIX_DESCRIPTION, PREFIX_DUE_DATE);
+
+ if (!ParserUtil.arePrefixesPresent(argMultimap, PREFIX_ROOM_NUMBER, PREFIX_TASK_NUMBER)
+ || !argMultimap.getPreamble().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditTaskCommand.MESSAGE_USAGE));
+ }
+
+ // Compulsory fields
+ int roomNumber = ParserUtil.parseRoomNumber(argMultimap.getValue(PREFIX_ROOM_NUMBER).get());
+ Index taskIndex = ParserUtil.parseTaskIndex(argMultimap.getValue(PREFIX_TASK_NUMBER).get());
+
+ // Optional fields
+ EditTaskDescriptor editTaskDescriptor = new EditTaskDescriptor();
+
+ if (argMultimap.getValue(PREFIX_DESCRIPTION).isPresent()) {
+ String description = argMultimap.getValue(PREFIX_DESCRIPTION).get();
+ editTaskDescriptor.setDescription(TaskParserUtil.parseDescription(description));
+ }
+
+ if (argMultimap.getValue(PREFIX_DUE_DATE).isPresent()) {
+ String dueAt = argMultimap.getValue(PREFIX_DUE_DATE).get();
+ editTaskDescriptor.setDateTimeDue(TaskParserUtil.parseDateTimeDue((dueAt.equals(INPUT_REMOVE_DUE_DATE))
+ ? Optional.empty()
+ : Optional.of(dueAt)));
+ }
+
+ if (!editTaskDescriptor.isAnyFieldEdited()) {
+ // Do not execute as no changes have been made
+ throw new ParseException(Messages.MESSAGE_TASK_NOT_EDITED);
+ }
+
+ return new EditTaskCommand(roomNumber, taskIndex, editTaskDescriptor);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/task/SearchTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/task/SearchTaskCommandParser.java
new file mode 100644
index 00000000000..1c026312cb1
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/task/SearchTaskCommandParser.java
@@ -0,0 +1,38 @@
+package seedu.address.logic.parser.task;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.task.TaskCliSyntax.PREFIX_DUE_DATE;
+
+import seedu.address.logic.commands.task.SearchTaskCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.task.DateTimeDue;
+
+/**
+ * Parses input arguments and creates a new SearchTaskCommand object
+ */
+public class SearchTaskCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the SearchTaskCommand
+ * and returns an SearchTaskCommand object for execution.
+ *
+ * @throws ParseException if the user input does not conform to the expected format.
+ */
+ public SearchTaskCommand parse(String args) throws ParseException {
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_DUE_DATE);
+
+ if (!ParserUtil.isExactlyOnePrefixPresent(argMultimap, PREFIX_DUE_DATE)
+ || !argMultimap.getPreamble().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, SearchTaskCommand.MESSAGE_USAGE));
+ }
+
+ DateTimeDue dueAt = TaskParserUtil.parseDateTimeDue(argMultimap.getValue(PREFIX_DUE_DATE)); // optional
+
+
+ return new SearchTaskCommand(dueAt);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/task/TaskCliSyntax.java b/src/main/java/seedu/address/logic/parser/task/TaskCliSyntax.java
new file mode 100644
index 00000000000..66382072624
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/task/TaskCliSyntax.java
@@ -0,0 +1,15 @@
+package seedu.address.logic.parser.task;
+
+import seedu.address.logic.parser.Prefix;
+
+/**
+ * Contains Command Line Interface (CLI) syntax definitions common to multiple task-related commands
+ */
+public class TaskCliSyntax {
+
+ /* Prefix definitions */
+ public static final Prefix PREFIX_DESCRIPTION = new Prefix("d/");
+ public static final Prefix PREFIX_DUE_DATE = new Prefix("dd/");
+ public static final Prefix PREFIX_TASK_NUMBER = new Prefix("t/");
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/task/TaskParserUtil.java b/src/main/java/seedu/address/logic/parser/task/TaskParserUtil.java
new file mode 100644
index 00000000000..3a4df78014b
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/task/TaskParserUtil.java
@@ -0,0 +1,51 @@
+package seedu.address.logic.parser.task;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.Optional;
+
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.task.DateTimeDue;
+import seedu.address.model.task.Description;
+
+/**
+ * Contains utility methods used for parsing strings in the various task-related Parser classes.
+ */
+public class TaskParserUtil {
+
+ /**
+ * Parses a {@code String description} into a {@code Description}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given description is invalid.
+ */
+ public static Description parseDescription(String description) throws ParseException {
+ requireNonNull(description);
+ String trimmedDescription = description.trim();
+ if (!Description.isValidDescription(trimmedDescription)) {
+ throw new ParseException(Description.MESSAGE_CONSTRAINTS);
+ }
+ return new Description(trimmedDescription);
+ }
+
+ /**
+ * Parses a {@code Optional optionalDueAt} into a {@code DateTimeDue}.
+ * {@code optionalDueAt} can be empty but must not be null.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given date-time string is invalid.
+ */
+ public static DateTimeDue parseDateTimeDue(Optional optionalDueAt) throws ParseException {
+ requireNonNull(optionalDueAt);
+ boolean isValid = optionalDueAt
+ .map(String::trim)
+ .map(DateTimeDue::isValidDateTimeDue)
+ .orElse(true); // empty Optional considered valid
+
+ if (!isValid) {
+ throw new ParseException(DateTimeDue.MESSAGE_CONSTRAINTS);
+ }
+
+ return new DateTimeDue(optionalDueAt);
+ }
+}
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
index d54df471c1f..14e0e79e157 100644
--- a/src/main/java/seedu/address/model/Model.java
+++ b/src/main/java/seedu/address/model/Model.java
@@ -1,18 +1,29 @@
package seedu.address.model;
import java.nio.file.Path;
+import java.util.Optional;
+import java.util.PriorityQueue;
import java.util.function.Predicate;
import javafx.collections.ObservableList;
import seedu.address.commons.core.GuiSettings;
-import seedu.address.model.person.Person;
+import seedu.address.commons.core.index.Index;
+import seedu.address.model.patient.Name;
+import seedu.address.model.patient.Patient;
+import seedu.address.model.room.Room;
+import seedu.address.model.room.RoomTaskAssociation;
+import seedu.address.model.task.Task;
/**
* The API of the Model component.
*/
public interface Model {
/** {@code Predicate} that always evaluate to true */
- Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true;
+ Predicate PREDICATE_SHOW_ALL_PATIENTS = unused -> true;
+
+ Predicate PREDICATE_SHOW_ALL_ROOMS = unused -> true;
+
+ Predicate PREDICATE_SHOW_ALL_TASKS = unused -> true;
/**
* Replaces user prefs data with the data in {@code userPrefs}.
@@ -35,53 +46,226 @@ public interface Model {
void setGuiSettings(GuiSettings guiSettings);
/**
- * Returns the user prefs' address book file path.
+ * Returns the user prefs' covigent app file path.
+ */
+ Path getCovigentAppFilePath();
+
+ /**
+ * Sets the user prefs' covigent app file path.
+ */
+ void setCovigentAppFilePath(Path covigentAppFilePath);
+
+ /**
+ * Replaces patient records with the data in {@code covigentApp}.
+ */
+ void setPatientRecords(ReadOnlyList patientRecords);
+
+ /** Returns the patient records */
+ ReadOnlyList getPatientRecords();
+
+ /**
+ * Replaces room list with the data in {@code covigentApp}.
*/
- Path getAddressBookFilePath();
+ void setRoomList(ReadOnlyList rooms);
/**
- * Sets the user prefs' address book file path.
+ * Returns the room task records.
*/
- void setAddressBookFilePath(Path addressBookFilePath);
+ ReadOnlyList getRoomTaskRecords();
/**
- * Replaces address book data with the data in {@code addressBook}.
+ * Returns true if a patient with the same identity as {@code patient} exists in the patient records.
*/
- void setAddressBook(ReadOnlyAddressBook addressBook);
+ boolean hasPatient(Patient patient);
- /** Returns the AddressBook */
- ReadOnlyAddressBook getAddressBook();
+ void setInitNumOfRooms(int numOfRooms);
+ /**
+ * Returns the patient with the {@code nameOfPatient} if it exists. Otherwise, an empty optional
+ * is returned.
+ */
+ Optional getPatientWithName(Name nameOfPatient);
/**
- * Returns true if a person with the same identity as {@code person} exists in the address book.
+ * Deletes the given patient.
+ * The patient must exist in the patient records.
*/
- boolean hasPerson(Person person);
+ void deletePatient(Patient target);
/**
- * Deletes the given person.
- * The person must exist in the address book.
+ * Adds the given patient.
+ * {@code patient} must not already exist in the patient records.
*/
- void deletePerson(Person target);
+ void addPatient(Patient patient);
/**
- * Adds the given person.
- * {@code person} must not already exist in the address book.
+ * Replaces the given patient {@code target} with {@code editedPatient}.
+ * {@code target} must exist in the patient records.
+ * The patient identity of {@code editedPatient} must not be the same as
+ * another existing patient in the patient records.
*/
- void addPerson(Person person);
+ void setPatient(Patient target, Patient editedPatient);
/**
- * 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.
+ * Checks if patient is already assigned to a room.
+ *
+ * @param name Of the patient.
+ * @return Boolean value of whether patient is already assigned.
*/
- void setPerson(Person target, Person editedPerson);
+ boolean isPatientAssignedToRoom(Name name);
- /** Returns an unmodifiable view of the filtered person list */
- ObservableList getFilteredPersonList();
+ /**
+ * Returns an unmodifiable view of the list of {@code Patient} backed by the internal list of
+ * {@code UniquePatientList}.
+ */
+ ObservableList getFilteredPatientList();
/**
- * Updates the filter of the filtered person list to filter by the given {@code predicate}.
+ * Updates the filter of the filtered patient list to filter by the given {@code predicate}.
* @throws NullPointerException if {@code predicate} is null.
*/
- void updateFilteredPersonList(Predicate predicate);
+ void updateFilteredPatientList(Predicate predicate);
+
+ /**
+ * Returns total number of rooms in the application's {@code RoomList}.
+ */
+ int getNumOfRooms();
+
+ /**
+ * @param num is the number of rooms to define in a hotel.
+ */
+ void initRooms(int num);
+
+ /**
+ * Returns whether a decrease in number of rooms would have space for existing rooms
+ */
+ boolean hasSpaceForRooms();
+
+ /**
+ * Returns number of occupied rooms whose room number is more than the number of rooms to be defined
+ * using initRoom command
+ */
+ int getNumOfExcessOccupiedRooms();
+ /**
+ * Returns true if a room with the same identity as {@code room} exists in Covigent.
+ *
+ * @param room The room .
+ * @return true if {@code room} is in Covigent; false otherwise.
+ */
+ boolean hasRoom(Room room);
+
+ /**
+ * Returns the room with the {@code roomNumber} if it exists. Otherwise, an empty optional
+ * is returned.
+ */
+ Optional getRoomWithRoomNumber(int roomNumber);
+
+ /**
+ * sets specified room to roomList
+ */
+ void setRoom(Room room);
+ /**
+ * Replaces the given room {@code target} with {@code editedRoom}.
+ * {@code target} must exist in the application.
+ * The room identity of {@code editedRoom} must not be the same as
+ * another existing room in the application.
+ *
+ * @param target Of the room to be changed.
+ * @param editedRoom Is the newly edited room.
+ */
+ void setSingleRoom(Room target, Room editedRoom);
+
+ /**
+ * Removes the patient with the given name {@code patientName} from the room.
+ */
+ void removePatientFromRoom(Name patientName);
+
+ /**
+ * Checks if the given room number is present in the application.
+ *
+ * @param roomNumber to check if it is in the application.
+ * @return Index Of room that is found.
+ */
+ Index checkIfRoomPresent(Integer roomNumber);
+
+ /**
+ * Updates the room with the new edited patient.
+ *
+ * @param patientToEdit Patient that is to be edited.
+ * @param editedPatient Patient that is edited.
+ */
+ void updateRoomListWhenPatientsChanges(Patient patientToEdit, Patient editedPatient);
+
+ /**
+ * Returns an unmodifiable view of the list of {@code Room} backed by the internal list of
+ * {@code RoomList}.
+ */
+ ObservableList getRoomListObservableList();
+
+ RoomList getModifiableRoomList();
+
+ /**
+ * Returns an unmodifiable view of the list of {@code Room} backed by the internal list of
+ * {@code RoomList}.
+ */
+ ObservableList getFilteredRoomList();
+
+ /**
+ * Updates the filter of the filtered rooms to filter by the given {@code predicate}.
+ * @throws NullPointerException if {@code predicate} is null.
+ */
+ void updateFilteredRoomList(Predicate predicate);
+
+ /**
+ * Returns Priority Queue of rooms
+ */
+ PriorityQueue getRooms();
+
+ /**
+ * Returns the task with the {@code taskIndex} in {code room} if it exists.
+ * Otherwise, an empty optional is returned.
+ */
+ Optional getTaskFromRoomWithTaskIndex(Index taskIndex, Room room);
+
+ /**
+ * Adds {@code task} to {@code room}.
+ * The room must exist in {@code CovigentApp}.
+ *
+ * @param task The task to add.
+ * @param room The room to which the task should be added.
+ */
+ void addTaskToRoom(Task task, Room room);
+
+ /**
+ * Deletes {@code task} from {@code room}.
+ * The room must exist in Covigent.
+ * The task must exist in room.
+ *
+ * @param task The task to delete.
+ * @param room The room from which the task should be delete.
+ */
+ void deleteTaskFromRoom(Task task, Room room);
+
+ /**
+ * Replaces the given task {@code target} with {@code editedTask}.
+ * The room must exist in Covigent.
+ * The task must exist in room.
+ *
+ * @param target The task to replace.
+ * @param editedTask The modified task to replace the original.
+ * @param room The room from which the task should be replaced.
+ */
+ void setTaskToRoom(Task target, Task editedTask, Room room);
+
+ /**
+ * Update the tasks in {@code filteredRoomTaskRecords} with {@code taskPredicate}.
+ *
+ * @param taskPredicate The predicate to filter the tasks.
+ */
+ void updateTasksInFilteredRoomTaskRecords(Predicate taskPredicate);
+
+ /**
+ * Returns an unmodifiable view of the list of {@code RoomTaskAssociation} backed by the
+ * internal list of {@code RoomTaskRecords}.
+ */
+ ObservableList getFilteredRoomTaskRecords();
}
diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java
index 0650c954f5c..e9443c3aa14 100644
--- a/src/main/java/seedu/address/model/ModelManager.java
+++ b/src/main/java/seedu/address/model/ModelManager.java
@@ -4,6 +4,8 @@
import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
import java.nio.file.Path;
+import java.util.Optional;
+import java.util.PriorityQueue;
import java.util.function.Predicate;
import java.util.logging.Logger;
@@ -11,7 +13,12 @@
import javafx.collections.transformation.FilteredList;
import seedu.address.commons.core.GuiSettings;
import seedu.address.commons.core.LogsCenter;
-import seedu.address.model.person.Person;
+import seedu.address.commons.core.index.Index;
+import seedu.address.model.patient.Name;
+import seedu.address.model.patient.Patient;
+import seedu.address.model.room.Room;
+import seedu.address.model.room.RoomTaskAssociation;
+import seedu.address.model.task.Task;
/**
* Represents the in-memory model of the address book data.
@@ -19,29 +26,46 @@
public class ModelManager implements Model {
private static final Logger logger = LogsCenter.getLogger(ModelManager.class);
- private final AddressBook addressBook;
+ private final PatientRecords patientRecords;
+ private final RoomList roomList;
+ private final RoomTaskRecords roomTaskRecords;
private final UserPrefs userPrefs;
- private final FilteredList filteredPersons;
+ private final FilteredList filteredPatients;
+ private final FilteredList filteredRooms;
+ private final FilteredList filteredRoomTaskRecords;
/**
- * Initializes a ModelManager with the given addressBook and userPrefs.
+ * Initializes a ModelManager with the given patient records, room records and userPrefs.
*/
- public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs) {
+ public ModelManager(ReadOnlyList patientRecords, ReadOnlyList roomList,
+ ReadOnlyUserPrefs userPrefs) {
super();
- requireAllNonNull(addressBook, userPrefs);
+ requireAllNonNull(patientRecords, userPrefs);
- logger.fine("Initializing with address book: " + addressBook + " and user prefs " + userPrefs);
+ logger.fine("Initializing with Covigent App: " + patientRecords + " and user prefs " + userPrefs);
- this.addressBook = new AddressBook(addressBook);
+ this.patientRecords = new PatientRecords(patientRecords);
+ this.roomList = new RoomList(roomList);
this.userPrefs = new UserPrefs(userPrefs);
- filteredPersons = new FilteredList<>(this.addressBook.getPersonList());
+
+ RoomTaskRecords theRoomTaskRecords;
+ try {
+ theRoomTaskRecords = RoomTaskRecords.getInstance();
+ } catch (AssertionError e) { // need to first initialize RoomTasksRecords
+ theRoomTaskRecords = RoomTaskRecords.init(this.roomList.getReadOnlyList());
+ }
+
+ roomTaskRecords = theRoomTaskRecords;
+ filteredPatients = new FilteredList<>(this.patientRecords.getReadOnlyList());
+ filteredRooms = new FilteredList<>(this.roomList.getReadOnlyList());
+ filteredRoomTaskRecords = new FilteredList<>(this.roomTaskRecords.getReadOnlyList());
}
public ModelManager() {
- this(new AddressBook(), new UserPrefs());
+ this(new PatientRecords(), new RoomList(), new UserPrefs());
}
- //=========== UserPrefs ==================================================================================
+ //=========== UserPrefs =================================================================================
@Override
public void setUserPrefs(ReadOnlyUserPrefs userPrefs) {
@@ -66,69 +90,275 @@ public void setGuiSettings(GuiSettings guiSettings) {
}
@Override
- public Path getAddressBookFilePath() {
- return userPrefs.getAddressBookFilePath();
+ public Path getCovigentAppFilePath() {
+ return userPrefs.getCovigentAppFilePath();
}
@Override
- public void setAddressBookFilePath(Path addressBookFilePath) {
- requireNonNull(addressBookFilePath);
- userPrefs.setAddressBookFilePath(addressBookFilePath);
+ public void setCovigentAppFilePath(Path covigentAppFilePath) {
+ requireNonNull(covigentAppFilePath);
+ userPrefs.setCovigentAppFilePath(covigentAppFilePath);
}
- //=========== AddressBook ================================================================================
+ //=========== Patient Records ===========================================================================
@Override
- public void setAddressBook(ReadOnlyAddressBook addressBook) {
- this.addressBook.resetData(addressBook);
+ public void setPatientRecords(ReadOnlyList patientRecords) {
+ this.patientRecords.resetData(patientRecords);
}
@Override
- public ReadOnlyAddressBook getAddressBook() {
- return addressBook;
+ public ReadOnlyList getPatientRecords() {
+ return patientRecords;
}
+ //=========== RoomList ==================================================================================
+
@Override
- public boolean hasPerson(Person person) {
- requireNonNull(person);
- return addressBook.hasPerson(person);
+ public void setRoomList(ReadOnlyList rooms) {
+ this.roomList.resetData(rooms);
}
+ //=========== RoomTaskRecords ===========================================================================
+
@Override
- public void deletePerson(Person target) {
- addressBook.removePerson(target);
+ public ReadOnlyList getRoomTaskRecords() {
+ return roomTaskRecords;
}
+ //=========== Patients ==================================================================================
+
@Override
- public void addPerson(Person person) {
- addressBook.addPerson(person);
- updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+ public boolean hasPatient(Patient patient) {
+ requireNonNull(patient);
+ return patientRecords.hasPatient(patient);
}
+ //@@author chiamyunqing
@Override
- public void setPerson(Person target, Person editedPerson) {
- requireAllNonNull(target, editedPerson);
+ public Optional getPatientWithName(Name nameOfPatient) {
+ requireNonNull(nameOfPatient);
+ return patientRecords.getPatientWithName(nameOfPatient);
+ }
- addressBook.setPerson(target, editedPerson);
+ @Override
+ public void deletePatient(Patient target) {
+ patientRecords.removePatient(target);
+ //model's responsibility to update room list when patient is updated
+ this.updateRoomListWhenPatientsChanges(target, null);
}
+ //@@author chiamyunqing
- //=========== Filtered Person List Accessors =============================================================
+ @Override
+ public void addPatient(Patient patient) {
+ updateFilteredPatientList(PREDICATE_SHOW_ALL_PATIENTS);
+ patientRecords.addPatient(patient);
+ }
+
+ @Override
+ public void setPatient(Patient target, Patient editedPatient) {
+ requireAllNonNull(target, editedPatient);
+ patientRecords.setPatient(target, editedPatient);
+ }
+
+ //@@author LeeMingDe
+ @Override
+ public boolean isPatientAssignedToRoom(Name name) {
+ requireNonNull(name);
+ for (Room room : roomList.getRoomObservableList()) {
+ if (room.getPatient().isPresent()) {
+ Name patientNameInRoom = room.getPatient().get().getName();
+ if (patientNameInRoom.equals(name)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ //@@author LeeMingDe
+
+ //=========== Filtered Patient List Accessors ===========================================================
+
+ @Override
+ public ObservableList getFilteredPatientList() {
+ return filteredPatients;
+ }
+
+ @Override
+ public void updateFilteredPatientList(Predicate predicate) {
+ requireNonNull(predicate);
+ filteredPatients.setPredicate(predicate);
+ }
+
+ //=========== Room List =================================================================================
+
+ //@@author itssodium
+ @Override
+ public int getNumOfExcessOccupiedRooms() {
+ return roomList.getNumOfExcessOccupiedRooms();
+ }
+ @Override
+ public boolean hasSpaceForRooms() {
+ return roomList.hasSpaceForRooms();
+ }
+ @Override
+ public int getNumOfRooms() {
+ return roomList.getNumOfRooms();
+ }
+ @Override
+ public void setInitNumOfRooms(int numOfRooms) {
+ roomList.setPreferredNumOfRooms(numOfRooms);
+ }
+ @Override
+ public void initRooms(int num) {
+ roomList.initRooms(num);
+ }
+ @Override
+ public void setRoom(Room room) {
+ roomList.setRoom(room);
+ }
+ //@@author itssodium
+ //@@author LeeMingDe
+ @Override
+ public boolean hasRoom(Room room) {
+ requireNonNull(room);
+ return roomList.containsRoom(room);
+ }
+
+ @Override
+ public void setSingleRoom(Room target, Room editedRoom) {
+ requireAllNonNull(target, editedRoom);
+ roomList.setSingleRoom(target, editedRoom);
+ }
+ //@@author LeeMingDe
+
+ //@@author chiamyunqing
+ @Override
+ public void removePatientFromRoom(Name patientName) {
+ assert (isPatientAssignedToRoom(patientName));
+ roomList.removePatientFromRoom(patientName);
+ }
+ //@@author chiamyunqing
+
+ //@@author LeeMingDe
+ @Override
+ public Index checkIfRoomPresent(Integer roomNumber) {
+ ObservableList roomObservableList = this.getRoomListObservableList();
+ Index index = Index.fromZeroBased(0);
+ for (int i = 1; i <= roomObservableList.size(); i++) {
+ int roomNum = roomObservableList.get(i - 1).getRoomNumber();
+ boolean isValidRoom = (Integer.valueOf(roomNum)).equals(roomNumber);
+ if (isValidRoom) {
+ index = Index.fromZeroBased(i);
+ break;
+ }
+ }
+ return index;
+ }
+
+ @Override
+ public void updateRoomListWhenPatientsChanges(Patient patientToEdit, Patient editedPatient) {
+ requireNonNull(patientToEdit);
+ ObservableList roomObservableList = this.roomList.getRoomObservableList();
+ for (int i = 0; i < roomObservableList.size(); i++) {
+ Optional patient = roomObservableList.get(i).getPatient();
+ if (isPatientAssignedToRoom(patientToEdit.getName()) && patient.isPresent()
+ && patient.get().isSamePatient(patientToEdit)) {
+ Room updatedRoom = roomObservableList.get(i);
+ if (editedPatient == null) {
+ updatedRoom.setOccupied(false);
+ }
+ updatedRoom.setPatient(editedPatient);
+ roomObservableList.set(i, updatedRoom);
+ break;
+ }
+ }
+ }
+ //@@author LeeMingDe
+
+ //@@author w-yeehong
+ @Override
+ public Optional getRoomWithRoomNumber(int roomNumber) {
+ assert (roomNumber > 0) : "Room number should be greater than 0.";
+ return roomList.getRoomWithRoomNumber(roomNumber);
+ }
+ //@@author w-yeehong
+
+ //=========== Filtered RoomList Accessors ===============================================================
+
+ @Override
+ public ObservableList getRoomListObservableList() {
+ return roomList.getReadOnlyList();
+ }
+
+ @Override
+ public RoomList getModifiableRoomList() {
+ return roomList;
+ }
+
+ @Override
+ public PriorityQueue getRooms() {
+ return this.getModifiableRoomList().getRooms();
+ }
- /**
- * Returns an unmodifiable view of the list of {@code Person} backed by the internal list of
- * {@code versionedAddressBook}
- */
@Override
- public ObservableList getFilteredPersonList() {
- return filteredPersons;
+ public ObservableList getFilteredRoomList() {
+ return filteredRooms;
}
@Override
- public void updateFilteredPersonList(Predicate predicate) {
+ public void updateFilteredRoomList(Predicate predicate) {
requireNonNull(predicate);
- filteredPersons.setPredicate(predicate);
+ filteredRooms.setPredicate(predicate);
+
+ }
+
+ //=========== Tasks =====================================================================================
+
+ //@@author w-yeehong
+ @Override
+ public Optional getTaskFromRoomWithTaskIndex(Index taskIndex, Room room) {
+ requireAllNonNull(taskIndex, room);
+ return room.getTaskWithTaskIndex(taskIndex);
+ }
+
+ @Override
+ public void addTaskToRoom(Task task, Room room) {
+ requireAllNonNull(task, room);
+ assert roomList.containsRoom(room) : "Room must be one of the rooms in the RoomList.";
+ room.addTask(task);
+ }
+
+ @Override
+ public void deleteTaskFromRoom(Task task, Room room) {
+ requireAllNonNull(task, room);
+ assert roomList.containsRoom(room) : "Room must be one of the rooms in the RoomList.";
+ room.deleteTask(task);
}
+ @Override
+ public void setTaskToRoom(Task target, Task editedTask, Room room) {
+ requireAllNonNull(target, editedTask, room);
+ assert roomList.containsRoom(room) : "Room must be one of the rooms in the RoomList.";
+ room.setTask(target, editedTask);
+ }
+ //@@author w-yeehong
+
+ //=========== Filtered RoomTaskRecords Accessors ========================================================
+
+ @Override
+ public void updateTasksInFilteredRoomTaskRecords(Predicate taskPredicate) {
+ requireNonNull(taskPredicate);
+ filteredRoomTaskRecords.setPredicate(roomTaskAssociation -> taskPredicate.test(roomTaskAssociation.getTask()));
+ }
+
+ @Override
+ public ObservableList getFilteredRoomTaskRecords() {
+ return filteredRoomTaskRecords;
+ }
+
+ //=========== Miscellaneous =============================================================================
+
@Override
public boolean equals(Object obj) {
// short circuit if same object
@@ -143,9 +373,11 @@ public boolean equals(Object obj) {
// state check
ModelManager other = (ModelManager) obj;
- return addressBook.equals(other.addressBook)
+
+ return patientRecords.equals(other.patientRecords)
+ && roomList.equals(other.roomList)
&& userPrefs.equals(other.userPrefs)
- && filteredPersons.equals(other.filteredPersons);
+ && filteredPatients.equals(other.filteredPatients)
+ && filteredRooms.equals(other.filteredRooms);
}
-
}
diff --git a/src/main/java/seedu/address/model/PatientRecords.java b/src/main/java/seedu/address/model/PatientRecords.java
new file mode 100644
index 00000000000..3518642b0ae
--- /dev/null
+++ b/src/main/java/seedu/address/model/PatientRecords.java
@@ -0,0 +1,136 @@
+package seedu.address.model;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.List;
+import java.util.Optional;
+
+import javafx.collections.ObservableList;
+import seedu.address.model.patient.Name;
+import seedu.address.model.patient.Patient;
+import seedu.address.model.patient.UniquePatientList;
+
+/**
+ * Wraps all data at the app level
+ * Duplicate patients are not allowed (by .isSamePatient comparison)
+ */
+public class PatientRecords implements ReadOnlyList {
+
+ private final UniquePatientList patients;
+
+ /*
+ * 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.
+ */
+ {
+ patients = new UniquePatientList();
+ }
+
+ public PatientRecords() {}
+
+ /**
+ * Creates an CovigentApp using the Patients in the {@code toBeCopied}
+ */
+ public PatientRecords(ReadOnlyList toBeCopied) {
+ this();
+ resetData(toBeCopied);
+ }
+
+ //// list overwrite operations
+
+ /**
+ * Replaces the contents of the patient list with {@code patients}.
+ * {@code patients} must not contain duplicate patients.
+ */
+ public void setPatients(List patients) {
+ this.patients.setPatients(patients);
+ }
+
+ /**
+ * Resets the existing data of this {@code PatientRecords} with {@code newData}.
+ */
+ public void resetData(ReadOnlyList newData) {
+ requireNonNull(newData);
+
+ setPatients(newData.getReadOnlyList());
+ }
+
+ //// patient-level operations
+
+ /**
+ * Returns true if a patient with the same identity as {@code patient} exists in the patient records.
+ */
+ public boolean hasPatient(Patient patient) {
+ requireNonNull(patient);
+ return patients.contains(patient);
+ }
+
+ //@@author chiamyunqing
+ /**
+ * Returns the patient with the input name.
+ * @param name of patient to find.
+ * @return the patient with the name if it exists.
+ */
+ public Optional getPatientWithName(Name name) {
+ requireNonNull(name);
+ return patients.getPatientWithName(name);
+ }
+
+ //@@author
+
+ /**
+ * Adds a patient to the address book.
+ * The patient must not already exist in the address book.
+ */
+ public void addPatient(Patient p) {
+ patients.add(p);
+ }
+
+ /**
+ * Replaces the given patient {@code target} in the list with {@code editedPatient}.
+ * {@code target} must exist in the address book.
+ * The patient identity of {@code editedPatient} must not be the same as another existing patient
+ * in the address book.
+ */
+ public void setPatient(Patient target, Patient editedPatient) {
+ requireNonNull(editedPatient);
+
+ patients.setPatient(target, editedPatient);
+ }
+
+ /**
+ * Removes {@code key} from this {@code PatientRecords}.
+ * {@code key} must exist in the address book.
+ */
+ public void removePatient(Patient key) {
+ patients.remove(key);
+ }
+
+ //// util methods
+
+ @Override
+ public String toString() {
+ return patients.asUnmodifiableObservableList().size() + " patients";
+ // TODO: refine later
+ }
+
+ @Override
+ public ObservableList getReadOnlyList() {
+ return patients.asUnmodifiableObservableList();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof PatientRecords // instanceof handles nulls
+ && patients.equals(((PatientRecords) other).patients));
+ }
+
+ @Override
+ public int hashCode() {
+ return patients.hashCode();
+ }
+}
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/ReadOnlyList.java b/src/main/java/seedu/address/model/ReadOnlyList.java
new file mode 100644
index 00000000000..ea4967836ee
--- /dev/null
+++ b/src/main/java/seedu/address/model/ReadOnlyList.java
@@ -0,0 +1,15 @@
+package seedu.address.model;
+
+import javafx.collections.ObservableList;
+
+/**
+ * Unmodifiable view of a list.
+ */
+public interface ReadOnlyList {
+
+ /**
+ * Returns an unmodifiable view of a list.
+ */
+ ObservableList getReadOnlyList();
+
+}
diff --git a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java b/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java
index befd58a4c73..3f9f081c223 100644
--- a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java
+++ b/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java
@@ -11,6 +11,6 @@ public interface ReadOnlyUserPrefs {
GuiSettings getGuiSettings();
- Path getAddressBookFilePath();
+ Path getCovigentAppFilePath();
}
diff --git a/src/main/java/seedu/address/model/RoomList.java b/src/main/java/seedu/address/model/RoomList.java
new file mode 100644
index 00000000000..9048bdeb129
--- /dev/null
+++ b/src/main/java/seedu/address/model/RoomList.java
@@ -0,0 +1,179 @@
+package seedu.address.model;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.Optional;
+import java.util.PriorityQueue;
+import java.util.logging.Logger;
+
+import javafx.collections.ObservableList;
+import seedu.address.commons.core.LogsCenter;
+import seedu.address.model.patient.Name;
+import seedu.address.model.room.Room;
+import seedu.address.model.room.UniqueRoomList;
+import seedu.address.storage.patient.JsonPatientRecordsStorage;
+
+/**
+ * Contains information regarding the Room information
+ */
+//@@author itssodium
+public class RoomList implements ReadOnlyList {
+ private static final Logger logger = LogsCenter.getLogger(JsonPatientRecordsStorage.class);
+
+ private final UniqueRoomList rooms;
+
+ /*
+ * 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.
+ */
+ {
+ rooms = new UniqueRoomList();
+ }
+
+ public RoomList() {}
+
+ /**
+ * Converts data from readOnlyRoomList to roomList
+ */
+ public RoomList(ReadOnlyList readOnlyRoomList) {
+ this();
+ resetData(readOnlyRoomList);
+ }
+
+ public boolean hasSpaceForRooms() {
+ return rooms.hasSpaceForRooms();
+ }
+
+ public int getNumOfExcessOccupiedRooms() {
+ return rooms.getNumOfExcessOccupiedRooms();
+ }
+ /**
+ * Resets the existing data of this {@code RoomList} with {@code newData}.
+ */
+ public void resetData(ReadOnlyList readOnlyRoomList) {
+ rooms.resetData(readOnlyRoomList);
+ }
+ /**
+ * Returns Priority Queue of rooms
+ */
+ public PriorityQueue getRooms() {
+ return rooms.getRooms();
+ }
+
+ /**
+ * Returns number of rooms in hotel
+ */
+ public int getNumOfRooms() {
+ return rooms.getNumOfRooms();
+ }
+
+ public void setInitNumOfRooms(int numOfRooms) {
+ rooms.setPreferredNumOfRooms(numOfRooms);
+ }
+
+ public ObservableList getRoomObservableList() {
+ return rooms.getRoomObservableList();
+ }
+
+ public void setRoom(Room room) {
+ rooms.setRoom(room);
+ }
+ /**
+ * Adds the number of the rooms in a hotel
+ *
+ * @param numOfRooms is the number of rooms to be added
+ */
+ public void initRooms(int numOfRooms) {
+ rooms.initRooms(numOfRooms);
+ }
+
+ /**
+ * Adds this room to the RoomList
+ * @param room is added to RoomList
+ */
+ public void initRooms(Room room) {
+ rooms.initRooms(room);
+ }
+
+ //@@author w-yeehong
+ /**
+ * Returns the room with the provided {@code roomNumber}.
+ * An empty optional is returned if such a room is not found in the {@code RoomList}.
+ *
+ * @param roomNumber The room number of the room.
+ * @return the optional-wrapped room if found, otherwise an empty optional
+ */
+ public Optional getRoomWithRoomNumber(int roomNumber) {
+ assert (roomNumber > 0) : "Room number should be greater than 0.";
+ for (Room room : getReadOnlyList()) {
+ if (roomNumber == room.getRoomNumber()) {
+ return Optional.of(room);
+ }
+ }
+ return Optional.empty();
+ }
+ //@@author w-yeehong
+
+ /**
+ * Returns the backing list as an unmodifiable {@code ObservableList}.
+ */
+ @Override
+ public ObservableList getReadOnlyList() {
+ return rooms.asUnmodifiableObservableList();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof RoomList // instanceof handles nulls
+ && rooms.equals(((RoomList) other).rooms));
+ }
+
+ /**
+ * Returns true if the list contains an equivalent room as the given argument.
+ */
+ public boolean containsRoom(Room toCheck) {
+ requireNonNull(toCheck);
+ return rooms.containsRoom(toCheck);
+ }
+
+ //@@author chiamyunqing
+ /**
+ * Removes the patient with the given name {@code patientName} from the room.
+ */
+ public void removePatientFromRoom(Name patientName) {
+ requireNonNull(patientName);
+ rooms.clearRoom(patientName);
+ }
+
+ //@author LeeMingDe
+ /**
+ * Replaces the room {@code target} in the list with {@code editedRoom}.
+ * {@code target} must exist in the list.
+ * The room identity of {@code editedRoom} must not be the same as another existing room in the list.
+ *
+ * @param target Room to be changed.
+ * @param editedRoom Room that has been changed.
+ */
+ public void setSingleRoom(Room target, Room editedRoom) {
+ rooms.setSingleRoom(target, editedRoom);
+ }
+ //@author LeeMingDe
+
+ @Override
+ public int hashCode() {
+ return rooms.hashCode();
+ }
+
+ public void setPreferredNumOfRooms(int numOfRooms) {
+ rooms.setPreferredNumOfRooms(numOfRooms);
+ }
+
+ public void setRooms(PriorityQueue rooms) {
+ this.rooms.setRooms(rooms);
+ }
+
+}
diff --git a/src/main/java/seedu/address/model/RoomTaskRecords.java b/src/main/java/seedu/address/model/RoomTaskRecords.java
new file mode 100644
index 00000000000..2fac3268546
--- /dev/null
+++ b/src/main/java/seedu/address/model/RoomTaskRecords.java
@@ -0,0 +1,119 @@
+package seedu.address.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ListChangeListener;
+import javafx.collections.ObservableList;
+import seedu.address.commons.core.LogsCenter;
+import seedu.address.model.room.Room;
+import seedu.address.model.room.RoomTaskAssociation;
+import seedu.address.model.task.Task;
+
+/**
+ * RoomTaskRecords exists mainly for the purpose of exposing an ObservableList for the user interface of
+ * {@code Task} to display the list of tasks in all {@code Room}.
+ *
+ * It stores a list of {@code RoomTaskAssociation}. {@code RoomTaskAssociation} is preferred to {@code Task}
+ * as it provides an API to quickly query room number and task index of a task.
+ *
+ * RoomTaskRecords follows the Singleton pattern. Solution adapted with modifications from:
+ * https://stackoverflow.com/questions/1050991/singleton-with-arguments-in-java
+ */
+public class RoomTaskRecords implements ReadOnlyList {
+
+ private static RoomTaskRecords theOne = null;
+
+ private static final Logger logger = LogsCenter.getLogger(RoomTaskRecords.class);
+
+ private final ObservableList internalList = FXCollections.observableArrayList();
+ private final ObservableList internalUnmodifiableList =
+ FXCollections.unmodifiableObservableList(internalList);
+
+ private RoomTaskRecords() { // set to private to ensure that creation is done through init(...) method
+ }
+
+ /**
+ * Returns the RoomTaskRecords.
+ *
+ * @throws AssertionError if RoomTaskRecords has not been initialized.
+ */
+ public static RoomTaskRecords getInstance() {
+ if (theOne == null) {
+ throw new AssertionError("RoomTaskRecords has to be initialized first.");
+ }
+
+ return theOne;
+ }
+
+ /**
+ * Creates and initializes the RoomTaskRecords. The information about the rooms and the tasks in
+ * those rooms are obtained from {@code roomList}. A listener is attached to {@code roomList} to
+ * ensure that the associations between rooms and tasks are synchronized even when there are
+ * changes to {@code roomList}.
+ *
+ * Only one instance of RoomTaskRecords can be created.
+ *
+ * @param roomList The list of rooms from which to create the associations between room and task.
+ * @return The singleton instance of RoomTaskRecords.
+ * @throw AssertionError if RoomTaskRecords has already been initialized
+ */
+ public static synchronized RoomTaskRecords init(ObservableList roomList) {
+ if (theOne != null) {
+ throw new AssertionError("RoomTaskRecords has already been initialized.");
+ }
+
+ logger.finer("Creating RoomTaskRecords and attaching a listener to refresh room-task associations...");
+
+ theOne = new RoomTaskRecords();
+ theOne.createRoomTaskAssociations(roomList);
+ theOne.updateAssociationIfChanged(roomList);
+
+ logger.finer("Successfully attached listener to RoomTaskRecords.");
+
+ return theOne;
+ }
+
+ /**
+ * Creates the associations between each room and all the tasks in the rooms.
+ * These associations are stored into {@code internalList}.
+ */
+ private void createRoomTaskAssociations(ObservableList roomList) {
+ List associations = new ArrayList<>();
+
+ for (Room room : roomList) {
+ int taskIndex = 1;
+ for (Task task : room.getReadOnlyTasks()) {
+ associations.add(new RoomTaskAssociation(room, task, taskIndex));
+ taskIndex++;
+ }
+ }
+
+ internalList.setAll(associations);
+ }
+
+ /**
+ * Adds a listener to {@code roomList} to recreate all {@code RoomTaskAssociation} whenever
+ * there is a change.
+ *
+ * This ensures that the associations are properly synchronized and the task indexes are correct.
+ */
+ private void updateAssociationIfChanged(ObservableList roomList) {
+ roomList.addListener(new ListChangeListener() {
+ @Override
+ public void onChanged(Change extends Room> change) {
+ while (change.next()) {
+ logger.fine("Changes detected in list of rooms. Updating room-task associations...");
+ createRoomTaskAssociations(roomList);
+ }
+ }
+ });
+ }
+
+ @Override
+ public ObservableList getReadOnlyList() {
+ return internalUnmodifiableList;
+ }
+}
diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/seedu/address/model/UserPrefs.java
index 25a5fd6eab9..6fbbaa03852 100644
--- a/src/main/java/seedu/address/model/UserPrefs.java
+++ b/src/main/java/seedu/address/model/UserPrefs.java
@@ -14,8 +14,10 @@
public class UserPrefs implements ReadOnlyUserPrefs {
private GuiSettings guiSettings = new GuiSettings();
- private Path addressBookFilePath = Paths.get("data" , "addressbook.json");
-
+ private Path covigentAppFilePath = Paths.get("data" , "covigentapp.json");
+ private Path numberOfRoomsFilePath = Paths.get("data", "numberOfRooms.txt");
+ private Path roomsOccupiedFilePath = Paths.get("data", "roomInformation.json");
+ private Path taskFilePath = Paths.get("data", "task.json");
/**
* Creates a {@code UserPrefs} with default values.
*/
@@ -35,7 +37,7 @@ public UserPrefs(ReadOnlyUserPrefs userPrefs) {
public void resetData(ReadOnlyUserPrefs newUserPrefs) {
requireNonNull(newUserPrefs);
setGuiSettings(newUserPrefs.getGuiSettings());
- setAddressBookFilePath(newUserPrefs.getAddressBookFilePath());
+ setCovigentAppFilePath(newUserPrefs.getCovigentAppFilePath());
}
public GuiSettings getGuiSettings() {
@@ -47,13 +49,25 @@ public void setGuiSettings(GuiSettings guiSettings) {
this.guiSettings = guiSettings;
}
- public Path getAddressBookFilePath() {
- return addressBookFilePath;
+ public Path getCovigentAppFilePath() {
+ return covigentAppFilePath;
+ }
+
+ public void setCovigentAppFilePath(Path covigentAppFilePath) {
+ requireNonNull(covigentAppFilePath);
+ this.covigentAppFilePath = covigentAppFilePath;
+ }
+
+ public Path getNumberOfRoomsFilePath() {
+ return numberOfRoomsFilePath;
+ }
+
+ public Path getRoomsOccupiedFilePath() {
+ return roomsOccupiedFilePath;
}
- public void setAddressBookFilePath(Path addressBookFilePath) {
- requireNonNull(addressBookFilePath);
- this.addressBookFilePath = addressBookFilePath;
+ public Path getTaskOccupiedFilePath() {
+ return taskFilePath;
}
@Override
@@ -68,19 +82,19 @@ public boolean equals(Object other) {
UserPrefs o = (UserPrefs) other;
return guiSettings.equals(o.guiSettings)
- && addressBookFilePath.equals(o.addressBookFilePath);
+ && covigentAppFilePath.equals(o.covigentAppFilePath);
}
@Override
public int hashCode() {
- return Objects.hash(guiSettings, addressBookFilePath);
+ return Objects.hash(guiSettings, covigentAppFilePath);
}
@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 : " + covigentAppFilePath);
return sb.toString();
}
diff --git a/src/main/java/seedu/address/model/patient/Age.java b/src/main/java/seedu/address/model/patient/Age.java
new file mode 100644
index 00000000000..fa5fa2d10ab
--- /dev/null
+++ b/src/main/java/seedu/address/model/patient/Age.java
@@ -0,0 +1,100 @@
+package seedu.address.model.patient;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.AppUtil.checkArgument;
+
+//@@author chiamyunqing
+/**
+ * Represents a Patient's age recorded in the app.
+ * A valid patient age is between 0 (inclusive) and 120 (exclusive),
+ * as declared in {@link #isValidAge(String)}.
+ * If the age is invalid, the corresponding error message should be retrieved
+ * via {@link #getErrorMessage(String)}.
+ * Guarantees: immutable.
+ */
+public class Age {
+
+ public static final String MESSAGE_AGE_NOT_NUMBER =
+ "Age should only contain numbers.";
+
+ public static final String MESSAGE_INVALID_AGE_RANGE =
+ "Age should be between the range 0 (inclusive) to 120 (exclusive).";
+
+ public static final String VALIDATION_REGEX = "\\d{1,3}";
+ private static final int MAX_AGE = 120;
+ private final int value;
+
+ /**
+ * Constructs a {@code Age}.
+ *
+ * @param age A valid age.
+ */
+ public Age(String age) {
+ requireNonNull(age);
+ checkArgument(isValidAge(age), MESSAGE_AGE_NOT_NUMBER);
+ value = Integer.parseInt(age);
+ }
+
+ /**
+ * Returns true if a given string matches the validation regex.
+ */
+ private static boolean isRegexCorrect(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ /**
+ * Returns true if a given string is within the age range 0 (inclusive) to
+ * 120 (exclusive).
+ */
+ private static boolean isWithinValidAgeRange(String test) {
+ assert(isRegexCorrect(test));
+ return (Integer.parseInt(test) >= 0) && (Integer.parseInt(test) < MAX_AGE);
+ }
+
+ /**
+ * Returns true if a given string is a valid age.
+ */
+ public static boolean isValidAge(String test) {
+ return isRegexCorrect(test) && isWithinValidAgeRange(test);
+ }
+
+ /**
+ * Returns the precise error message according to the error that arises.
+ * This method should only be called if isValidAge(test) returns false.
+ *
+ * @param test the string with error in converting to age.
+ * @return the exact error message that corresponds to the error.
+ */
+ public static String getErrorMessage(String test) {
+ assert(!isValidAge(test));
+ if (!isRegexCorrect(test)) {
+ return MESSAGE_AGE_NOT_NUMBER;
+ } else {
+ return MESSAGE_INVALID_AGE_RANGE;
+ }
+ }
+
+ /**
+ * Returns the value of the age.
+ */
+ public int getValue() {
+ return this.value;
+ }
+
+ @Override
+ public String toString() {
+ return Integer.toString(value);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Age // instanceof handles nulls
+ && value == ((Age) other).getValue()); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return Integer.toString(value).hashCode();
+ }
+}
diff --git a/src/main/java/seedu/address/model/patient/Comment.java b/src/main/java/seedu/address/model/patient/Comment.java
new file mode 100644
index 00000000000..efa4f286c4e
--- /dev/null
+++ b/src/main/java/seedu/address/model/patient/Comment.java
@@ -0,0 +1,40 @@
+package seedu.address.model.patient;
+
+import static java.util.Objects.requireNonNull;
+
+//@@author chiamyunqing
+/**
+ * Represents important comments of the Patient in the app.
+ * Guarantees: immutable; is an optional attribute of patient.
+ */
+public class Comment {
+ public final String value;
+
+ /**
+ * Constructs a {@code Comment}.
+ *
+ * @param comment A comment that is represented by any string.
+ */
+ public Comment(String comment) {
+ requireNonNull(comment);
+ assert(comment.length() != 0);
+ value = comment;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Comment // instanceof handles nulls
+ && value.equals(((Comment) 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/patient/Name.java
similarity index 74%
rename from src/main/java/seedu/address/model/person/Name.java
rename to src/main/java/seedu/address/model/patient/Name.java
index 79244d71cf7..57cd8f69827 100644
--- a/src/main/java/seedu/address/model/person/Name.java
+++ b/src/main/java/seedu/address/model/patient/Name.java
@@ -1,23 +1,23 @@
-package seedu.address.model.person;
+package seedu.address.model.patient;
import static java.util.Objects.requireNonNull;
import static seedu.address.commons.util.AppUtil.checkArgument;
/**
- * Represents a Person's name in the address book.
+ * Represents a Patient's name in the app.
* 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";
-
- /*
+ "Names should only contain alphanumeric characters and spaces, and it should not be blank.\n"
+ + "The maximum length of name is set to 150 characters.";
+ /**
* 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} ]*";
-
+ private static final int MAX_NAME_LENGTH = 150;
public final String fullName;
/**
@@ -35,7 +35,8 @@ public Name(String name) {
* Returns true if a given string is a valid name.
*/
public static boolean isValidName(String test) {
- return test.matches(VALIDATION_REGEX);
+ return test.matches(VALIDATION_REGEX)
+ && test.length() <= MAX_NAME_LENGTH;
}
@@ -48,7 +49,7 @@ public String toString() {
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
+ && fullName.toLowerCase().equals(((Name) other).fullName.toLowerCase())); // state check
}
@Override
diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/patient/NameContainsKeywordsPredicate.java
similarity index 77%
rename from src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
rename to src/main/java/seedu/address/model/patient/NameContainsKeywordsPredicate.java
index c9b5868427c..c68777ac1db 100644
--- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
+++ b/src/main/java/seedu/address/model/patient/NameContainsKeywordsPredicate.java
@@ -1,4 +1,4 @@
-package seedu.address.model.person;
+package seedu.address.model.patient;
import java.util.List;
import java.util.function.Predicate;
@@ -6,9 +6,9 @@
import seedu.address.commons.util.StringUtil;
/**
- * Tests that a {@code Person}'s {@code Name} matches any of the keywords given.
+ * Tests that a {@code Patient}'s {@code Name} matches any of the keywords given.
*/
-public class NameContainsKeywordsPredicate implements Predicate {
+public class NameContainsKeywordsPredicate implements Predicate {
private final List keywords;
public NameContainsKeywordsPredicate(List keywords) {
@@ -16,9 +16,9 @@ public NameContainsKeywordsPredicate(List keywords) {
}
@Override
- public boolean test(Person person) {
+ public boolean test(Patient patient) {
return keywords.stream()
- .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getName().fullName, keyword));
+ .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(patient.getName().fullName, keyword));
}
@Override
diff --git a/src/main/java/seedu/address/model/patient/Patient.java b/src/main/java/seedu/address/model/patient/Patient.java
new file mode 100644
index 00000000000..370e091310c
--- /dev/null
+++ b/src/main/java/seedu/address/model/patient/Patient.java
@@ -0,0 +1,115 @@
+package seedu.address.model.patient;
+
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.util.Objects;
+
+//@@author chiamyunqing
+/**
+ * Represents a Patient in the app.
+ * Guarantees: details are present and not null, field values are validated, immutable.
+ */
+public class Patient {
+
+ private final Name name; //identifier field
+ private final Temperature temperature;
+ private final PeriodOfStay periodOfStay;
+ private final Phone phone;
+ private final Age age;
+ private final Comment comment; // an optional field, if null is initialised to "-"
+
+ /**
+ * Every field, except comment, must be present and not null.
+ */
+ public Patient(Name name, Temperature temperature, PeriodOfStay periodOfStay,
+ Phone phone, Age age, Comment comment) {
+ requireAllNonNull(name, temperature, periodOfStay, phone, age);
+ this.name = name;
+ this.temperature = temperature;
+ this.periodOfStay = periodOfStay;
+ this.phone = phone;
+ this.age = age;
+ this.comment = comment == null ? new Comment("-") : comment;
+ }
+
+ public Name getName() {
+ return name;
+ }
+
+ public Phone getPhone() {
+ return phone;
+ }
+
+ public Temperature getTemperature() {
+ return temperature;
+ }
+
+ public PeriodOfStay getPeriodOfStay() {
+ return periodOfStay;
+ }
+
+ public Age getAge() {
+ return age;
+ }
+
+ public Comment getComment() {
+ return comment;
+ }
+
+ /**
+ * Returns true if both patients have the same name.
+ * This defines a weaker notion of equality between two patients.
+ */
+ public boolean isSamePatient(Patient otherPatient) {
+ if (otherPatient == this) {
+ return true;
+ }
+ return otherPatient != null
+ && otherPatient.getName().equals(getName());
+ }
+
+ /**
+ * Returns true if both patients have the same identity and data fields.
+ * This defines a stronger notion of equality between two patients.
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ if (!(other instanceof Patient)) {
+ return false;
+ }
+
+ Patient otherPatient = (Patient) other;
+ return otherPatient.getName().equals(getName())
+ && otherPatient.getTemperature().equals(getTemperature())
+ && otherPatient.getPeriodOfStay().equals(getPeriodOfStay())
+ && otherPatient.getPhone().equals(getPhone())
+ && otherPatient.getAge().equals(getAge());
+ }
+
+ @Override
+ public int hashCode() {
+ // use this method for custom fields hashing instead of implementing your own
+ return Objects.hash(name, temperature, periodOfStay, phone, age, comment);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(getName() + "\n")
+ .append("Temperature: ")
+ .append(getTemperature() + "\n")
+ .append("Period of stay: ")
+ .append(getPeriodOfStay().readerFriendlyString() + "\n")
+ .append("Phone: ")
+ .append(getPhone() + "\n")
+ .append("Age: ")
+ .append(getAge() + "\n")
+ .append("Comment: ")
+ .append(getComment() + "\n");
+ return builder.toString();
+ }
+}
diff --git a/src/main/java/seedu/address/model/patient/PeriodOfStay.java b/src/main/java/seedu/address/model/patient/PeriodOfStay.java
new file mode 100644
index 00000000000..2cb16ecf7df
--- /dev/null
+++ b/src/main/java/seedu/address/model/patient/PeriodOfStay.java
@@ -0,0 +1,128 @@
+package seedu.address.model.patient;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.AppUtil.checkArgument;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+
+//@@author chiamyunqing
+/**
+ * Represents a Patient's period of stay in the facility.
+ * Guarantees: immutable; is valid as declared in {@link #isValidPeriodOfStay(String)}
+ * If the period of stay is invalid, the corresponding error message should be retrieved
+ * via {@link #getErrorMessage(String)}.
+ */
+public class PeriodOfStay {
+
+ public static final String MESSAGE_WRONG_REGEX =
+ "Period of stay should be in the format YYYYMMDD-YYYYMMDD. \nE.g. 20200911-20200924";
+ public static final String MESSAGE_INVALID_DATE =
+ "The dates of the period of stay must be valid.\nIn particular, the start date of the period of stay "
+ + "must be before or equals the end date.\nE.g. 20200901-20200901 or 20200901-20200914.";
+
+ public static final String VALIDATION_REGEX = "\\d{8}[-]\\d{8}";
+
+ private final LocalDate startDate;
+ private final LocalDate endDate;
+
+ /**
+ * Constructs a {@code PeriodOfStay}.
+ *
+ * @param periodOfStay A valid period of stay.
+ */
+ public PeriodOfStay(String periodOfStay) {
+ requireNonNull(periodOfStay);
+ checkArgument(isRegexCorrect(periodOfStay), MESSAGE_WRONG_REGEX);
+ checkArgument(isValidDates(periodOfStay), MESSAGE_INVALID_DATE);
+ startDate = LocalDate.parse(periodOfStay.split("-")[0], DateTimeFormatter.ofPattern("yyyyMMdd"));
+ endDate = LocalDate.parse(periodOfStay.split("-")[1], DateTimeFormatter.ofPattern("yyyyMMdd"));
+ }
+
+ /**
+ * Returns true if a given string matches the validation regex.
+ */
+ private static boolean isRegexCorrect(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ /**
+ * Returns true if a given string has valid start and end dates.
+ * Start and end dates are valid if start date is before or equals end date.
+ */
+ private static boolean isValidDates(String test) {
+ assert(isRegexCorrect(test));
+ String[] dates = test.split("-");
+ try {
+ LocalDate start = LocalDate.parse(dates[0], DateTimeFormatter.ofPattern("yyyyMMdd"));
+ LocalDate end = LocalDate.parse(dates[1], DateTimeFormatter.ofPattern("yyyyMMdd"));
+ return start.compareTo(end) <= 0; //check start date less than or equals end date
+ } catch (DateTimeParseException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if a given string is a valid period of stay.
+ */
+ public static boolean isValidPeriodOfStay(String test) {
+ return isRegexCorrect(test) && isValidDates(test);
+ }
+
+ /**
+ * Returns the precise error message according to the error that arises.
+ * This method should only be called if isValidPeriodOfStay(test) returns false.
+ *
+ * @param test the string with error in converting to periodOfStay.
+ * @return the exact error message that corresponds to the error.
+ */
+ public static String getErrorMessage(String test) {
+ assert(!isValidPeriodOfStay(test));
+ if (!isRegexCorrect(test)) {
+ return MESSAGE_WRONG_REGEX;
+ } else {
+ return MESSAGE_INVALID_DATE;
+ }
+ }
+
+ public LocalDate getStartDate() {
+ return this.startDate;
+ }
+
+ public LocalDate getEndDate() {
+ return this.endDate;
+ }
+
+ /**
+ * Returns a string that is more human readable (e.g. 09 Jan 2020), meant for UI.
+ *
+ * @return reader friendly string.
+ */
+ public String readerFriendlyString() {
+ return startDate.format(DateTimeFormatter.ofPattern("dd MMM yyyy")) + " to "
+ + endDate.format(DateTimeFormatter.ofPattern("dd MMM yyyy"));
+ }
+
+ /**
+ * Primarily used for storage of data.
+ */
+ @Override
+ public String toString() {
+ return startDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + "-"
+ + endDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof PeriodOfStay // instanceof handles nulls
+ && startDate.compareTo(((PeriodOfStay) other).startDate) == 0
+ && endDate.compareTo(((PeriodOfStay) other).endDate) == 0); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return this.toString().hashCode();
+ }
+}
diff --git a/src/main/java/seedu/address/model/person/Phone.java b/src/main/java/seedu/address/model/patient/Phone.java
similarity index 74%
rename from src/main/java/seedu/address/model/person/Phone.java
rename to src/main/java/seedu/address/model/patient/Phone.java
index 872c76b382f..eeda2704059 100644
--- a/src/main/java/seedu/address/model/person/Phone.java
+++ b/src/main/java/seedu/address/model/patient/Phone.java
@@ -1,18 +1,20 @@
-package seedu.address.model.person;
+package seedu.address.model.patient;
import static java.util.Objects.requireNonNull;
import static seedu.address.commons.util.AppUtil.checkArgument;
/**
- * Represents a Person's phone number in the address book.
+ * Represents a Patient's phone number in the app.
* 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";
+ "Phone numbers should only contain numbers.\n"
+ + "Phone numbers should be at least 3 digits long and can only be up to 20 digits (inclusive).";
public static final String VALIDATION_REGEX = "\\d{3,}";
+ private static final int MAX_PHONE_DIGITS_ALLOWED = 20;
public final String value;
/**
@@ -30,7 +32,7 @@ public Phone(String phone) {
* Returns true if a given string is a valid phone number.
*/
public static boolean isValidPhone(String test) {
- return test.matches(VALIDATION_REGEX);
+ return test.matches(VALIDATION_REGEX) && test.length() <= MAX_PHONE_DIGITS_ALLOWED;
}
@Override
diff --git a/src/main/java/seedu/address/model/patient/Temperature.java b/src/main/java/seedu/address/model/patient/Temperature.java
new file mode 100644
index 00000000000..7687bde7179
--- /dev/null
+++ b/src/main/java/seedu/address/model/patient/Temperature.java
@@ -0,0 +1,79 @@
+package seedu.address.model.patient;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.AppUtil.checkArgument;
+
+//@@author chiamyunqing
+/**
+ * Represents a Patient's temperature recorded in the app.
+ * A valid temperature must be to 1 decimal place and is between 32.0 (inclusive)
+ * to 41.0 (inclusive) degree Celsius as declared in {@link #isValidTemperature(String)}.
+ * Guarantees: immutable.
+ */
+public class Temperature {
+ public static final String MESSAGE_CONSTRAINTS =
+ "Temperature should only contain numbers and it should be to one decimal place. (E.g. 36.0).\n"
+ + "The range of temperature should be between 32.0 (inclusive) to 41.0 (inclusive) degree Celsius.";
+
+ public static final String VALIDATION_REGEX = "\\d\\d[.]\\d";
+ private static final double MIN_TEMP_RANGE = 32.0;
+ private static final double MAX_TEMP_RANGE = 41.0;
+ private final double value;
+
+ /**
+ * Constructs a {@code Temperature}.
+ * @param temperature A valid temperature.
+ */
+ public Temperature(String temperature) {
+ requireNonNull(temperature);
+ checkArgument(isValidTemperature(temperature), MESSAGE_CONSTRAINTS); //ensures temp is always to 1 d.p.
+ value = Double.parseDouble(temperature);
+ }
+
+ /**
+ * Returns true if a given string matches the regex.
+ */
+ private static boolean isRegexCorrect(String test) {
+ return test.matches(VALIDATION_REGEX);
+ }
+
+ /**
+ * Returns true if a given string is within temperature range of 32.0 to 41.0 degree Celsius.
+ */
+ private static boolean isWithinTempRange(String test) {
+ assert(isRegexCorrect(test));
+ Double temperature = Double.parseDouble(test);
+ return temperature >= MIN_TEMP_RANGE && temperature <= MAX_TEMP_RANGE;
+ }
+
+ /**
+ * Returns true if a given string is a valid temperature.
+ */
+ public static boolean isValidTemperature(String test) {
+ return isRegexCorrect(test) && isWithinTempRange(test);
+ }
+
+ /**
+ * Returns the float value of the temperature reading.
+ */
+ public double getValue() {
+ return this.value;
+ }
+
+ @Override
+ public String toString() {
+ return Double.toString(value);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Temperature // instanceof handles nulls
+ && value == ((Temperature) other).getValue()); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return Double.toString(value).hashCode();
+ }
+}
diff --git a/src/main/java/seedu/address/model/patient/TemperatureRange.java b/src/main/java/seedu/address/model/patient/TemperatureRange.java
new file mode 100644
index 00000000000..56bf34da92b
--- /dev/null
+++ b/src/main/java/seedu/address/model/patient/TemperatureRange.java
@@ -0,0 +1,84 @@
+package seedu.address.model.patient;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.AppUtil.checkArgument;
+
+/**
+ * The temperature range class serves to update a list of patients that fall within the temperature range.
+ * A temperature range object contains two immutable temperature objects for comparison.
+ */
+public class TemperatureRange {
+ public static final String MESSAGE_CONSTRAINTS_TEMPERATURERANGE =
+ "Temperature range should contain temperature-temperature";
+ public static final String MESSAGE_CONSTRAINTS_TEMPERATURE =
+ "Temperature should only contain numbers, and it should be to one decimal place. (E.g. 36.0)";
+ public static final String VALIDATION_REGEX_TEMPERATURE = "\\d\\d[.]\\d";
+ public static final String VALIDATION_REGEX_TEMPERATURERANGE =
+ VALIDATION_REGEX_TEMPERATURE + "[-]" + VALIDATION_REGEX_TEMPERATURE;
+ public final double startingTemperature;
+ public final double endingTemperature;
+
+ /**
+ * Constructs a {@code TemperatureRange}.
+ * @param temperatureRange A valid temperature range.
+ */
+ public TemperatureRange (String temperatureRange) {
+ requireNonNull(temperatureRange);
+ checkArgument(isValidTemperatureRange(temperatureRange), MESSAGE_CONSTRAINTS_TEMPERATURERANGE);
+ String[] temperatures = temperatureRange.split("-");
+ checkArgument(isValidTemperature(temperatures[0]), MESSAGE_CONSTRAINTS_TEMPERATURE);
+ //ensures temp is always to 1 d.p.
+ checkArgument(isValidTemperature(temperatures[0]), MESSAGE_CONSTRAINTS_TEMPERATURE);
+ //ensures temp is always to 1 d.p.
+ startingTemperature = Double.parseDouble(temperatures[0]);
+ endingTemperature = Double.parseDouble(temperatures[1]);
+
+ }
+
+ /**
+ * Returns the starting temperature for the temperature range .
+ */
+ public double getStartingTemperature () {
+ return this.startingTemperature;
+ }
+
+ /**
+ * Returns the ending temperature for the temperature range .
+ */
+ public double getEndingTemperature () {
+ return this.endingTemperature;
+ }
+
+ /**
+ * Returns true if a given string is a valid temperature.
+ */
+ public static boolean isValidTemperature(String test) {
+ return test.matches(VALIDATION_REGEX_TEMPERATURE);
+ }
+
+ /**
+ * Returns true if a given string is a valid temperature Range .
+ */
+ public static boolean isValidTemperatureRange(String test) {
+ return test.matches(VALIDATION_REGEX_TEMPERATURERANGE);
+ }
+
+ @Override
+ public String toString() {
+ return startingTemperature + " to " + endingTemperature;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof TemperatureRange // instanceof handles nulls
+ && startingTemperature == ((TemperatureRange) other).startingTemperature
+ && endingTemperature == ((TemperatureRange) other).endingTemperature); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return this.toString().hashCode();
+ }
+}
+
diff --git a/src/main/java/seedu/address/model/patient/TemperatureRangePredicate.java b/src/main/java/seedu/address/model/patient/TemperatureRangePredicate.java
new file mode 100644
index 00000000000..96df0e66730
--- /dev/null
+++ b/src/main/java/seedu/address/model/patient/TemperatureRangePredicate.java
@@ -0,0 +1,35 @@
+package seedu.address.model.patient;
+
+import java.util.function.Predicate;
+
+/**
+ * Tests that a {@code Patient}'s {@code Temperature} falls within the temperature range.
+ */
+public class TemperatureRangePredicate implements Predicate {
+ private final double startingTemperature;
+ private final double endingTemperature;
+
+ /**
+ * Constructs a {@code TemperatureRangePredicate}.
+ * @param startingTemperature The start of temperature range.
+ * @param endingTemperature The end of temperature range.
+ */
+ public TemperatureRangePredicate(double startingTemperature, double endingTemperature) {
+ this.startingTemperature = startingTemperature;
+ this.endingTemperature = endingTemperature;
+ }
+
+ @Override
+ public boolean test(Patient patient) {
+ double temperature = patient.getTemperature().getValue();
+ return startingTemperature <= temperature && endingTemperature >= temperature;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof TemperatureRangePredicate // instanceof handles nulls
+ && startingTemperature == (((TemperatureRangePredicate) other).startingTemperature) // state check
+ && endingTemperature == (((TemperatureRangePredicate) other).endingTemperature)); // state check
+ }
+}
diff --git a/src/main/java/seedu/address/model/patient/UniquePatientList.java b/src/main/java/seedu/address/model/patient/UniquePatientList.java
new file mode 100644
index 00000000000..e6c7b5e9f99
--- /dev/null
+++ b/src/main/java/seedu/address/model/patient/UniquePatientList.java
@@ -0,0 +1,158 @@
+package seedu.address.model.patient;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.address.model.patient.exceptions.DuplicatePatientException;
+import seedu.address.model.patient.exceptions.PatientNotFoundException;
+
+/**
+ * A list of patients that enforces uniqueness between its elements and does not allow nulls.
+ * A patient is considered unique by comparing using {@code Patient#isSamePatient(Patient)}.
+ * As such, adding and updating of patients uses Patient#isSamePatient(Patient) for equality so as to ensure
+ * that the patient being added or updated is unique in terms of identity in the UniquePatientList.
+ * However, the removal of a patient uses Patient#equals(Object) so as to ensure that the patient with
+ * exactly the same fields will be removed.
+ *
+ * Supports a minimal set of list operations.
+ *
+ * @see Patient#isSamePatient(Patient)
+ */
+public class UniquePatientList implements Iterable {
+
+ private final ObservableList internalList = FXCollections.observableArrayList();
+ private final ObservableList internalUnmodifiableList =
+ FXCollections.unmodifiableObservableList(internalList);
+
+ /**
+ * Returns true if the list contains an equivalent patient as the given argument.
+ */
+ public boolean contains(Patient toCheck) {
+ requireNonNull(toCheck);
+ return internalList.stream().anyMatch(toCheck::isSamePatient);
+ }
+
+ //@@author chiamyunqing
+ /**
+ * Returns the patient with the input name.
+ * @param name of patient to find.
+ * @return the patient with the name if it exists.
+ */
+ public Optional getPatientWithName(Name name) {
+ requireNonNull(name);
+ for (Patient patient : internalList) {
+ if (patient.getName().equals(name)) {
+ return Optional.of(patient);
+ }
+ }
+ return Optional.empty();
+ }
+
+ //@@author
+ /**
+ * Adds a patient to the list.
+ * The patient must not already exist in the list.
+ */
+ public void add(Patient toAdd) {
+ requireNonNull(toAdd);
+ if (contains(toAdd)) {
+ throw new DuplicatePatientException();
+ }
+ internalList.add(toAdd);
+ int index = internalList.indexOf(toAdd);
+ internalList.set(index, toAdd); //creates a change for listener
+ }
+
+ /**
+ * Replaces the patient {@code target} in the list with {@code editedPatient}.
+ * {@code target} must exist in the list.
+ * The patient identity of {@code editedPatient} must not be the same as another existing patient in the list.
+ */
+ public void setPatient(Patient target, Patient editedPatient) {
+ requireAllNonNull(target, editedPatient);
+
+ int index = internalList.indexOf(target);
+ if (index == -1) {
+ throw new PatientNotFoundException();
+ }
+
+ if (!target.isSamePatient(editedPatient) && contains(editedPatient)) {
+ throw new DuplicatePatientException();
+ }
+
+ internalList.set(index, editedPatient);
+ }
+
+ /**
+ * Removes the equivalent patient from the list.
+ * The patient must exist in the list.
+ */
+ public void remove(Patient toRemove) {
+ requireNonNull(toRemove);
+ if (!internalList.remove(toRemove)) {
+ throw new PatientNotFoundException();
+ }
+ }
+
+ public void setPatients(UniquePatientList replacement) {
+ requireNonNull(replacement);
+ internalList.setAll(replacement.internalList);
+ }
+
+ /**
+ * Replaces the contents of this list with {@code patients}.
+ * {@code patients} must not contain duplicate patients.
+ */
+ public void setPatients(List patients) {
+ requireAllNonNull(patients);
+ if (!patientsAreUnique(patients)) {
+ throw new DuplicatePatientException();
+ }
+
+ internalList.setAll(patients);
+ }
+
+ /**
+ * 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 UniquePatientList // instanceof handles nulls
+ && internalList.equals(((UniquePatientList) other).internalList));
+ }
+
+ @Override
+ public int hashCode() {
+ return internalList.hashCode();
+ }
+
+ /**
+ * Returns true if {@code patients} contains only unique patients.
+ */
+ private boolean patientsAreUnique(List patients) {
+ for (int i = 0; i < patients.size() - 1; i++) {
+ for (int j = i + 1; j < patients.size(); j++) {
+ if (patients.get(i).isSamePatient(patients.get(j))) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/seedu/address/model/patient/exceptions/DuplicatePatientException.java b/src/main/java/seedu/address/model/patient/exceptions/DuplicatePatientException.java
new file mode 100644
index 00000000000..f690368941d
--- /dev/null
+++ b/src/main/java/seedu/address/model/patient/exceptions/DuplicatePatientException.java
@@ -0,0 +1,11 @@
+package seedu.address.model.patient.exceptions;
+
+/**
+ * Signals that the operation will result in duplicate Patients (Patients are considered duplicates if they
+ * have the same identity).
+ */
+public class DuplicatePatientException extends RuntimeException {
+ public DuplicatePatientException() {
+ super("Operation would result in duplicate patients");
+ }
+}
diff --git a/src/main/java/seedu/address/model/patient/exceptions/PatientNotFoundException.java b/src/main/java/seedu/address/model/patient/exceptions/PatientNotFoundException.java
new file mode 100644
index 00000000000..681e9fe0af0
--- /dev/null
+++ b/src/main/java/seedu/address/model/patient/exceptions/PatientNotFoundException.java
@@ -0,0 +1,6 @@
+package seedu.address.model.patient.exceptions;
+
+/**
+ * Signals that the operation is unable to find the specified patient.
+ */
+public class PatientNotFoundException extends RuntimeException {}
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/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/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/room/ComparableRoom.java b/src/main/java/seedu/address/model/room/ComparableRoom.java
new file mode 100644
index 00000000000..8acca9fe18a
--- /dev/null
+++ b/src/main/java/seedu/address/model/room/ComparableRoom.java
@@ -0,0 +1,20 @@
+package seedu.address.model.room;
+
+import java.util.Comparator;
+
+public class ComparableRoom implements Comparator {
+ @Override
+ public int compare(Room room1, Room room2) {
+ if (room1.isOccupied() == room2.isOccupied()) {
+ if (room1.getRoomNumber() < room2.getRoomNumber()) {
+ return -1;
+ } else {
+ return 1;
+ }
+ } else if (room1.isOccupied()) {
+ return 1;
+ } else {
+ return -1;
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/model/room/Room.java b/src/main/java/seedu/address/model/room/Room.java
new file mode 100644
index 00000000000..4b380c130a3
--- /dev/null
+++ b/src/main/java/seedu/address/model/room/Room.java
@@ -0,0 +1,240 @@
+package seedu.address.model.room;
+
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import javafx.collections.ObservableList;
+import seedu.address.commons.core.index.Index;
+import seedu.address.model.ReadOnlyList;
+import seedu.address.model.patient.Patient;
+import seedu.address.model.task.Task;
+import seedu.address.model.task.exceptions.TaskNotFoundException;
+
+/**
+ * Represents Room in the app
+ */
+public class Room {
+
+ private int roomNumber;
+ private boolean isOccupied;
+ private Optional patient;
+ private RoomTasks tasks;
+
+ /**
+ * Creates room object where isOccupied is always false
+ */
+ public Room(int roomNumber) {
+ requireAllNonNull(roomNumber);
+ this.roomNumber = roomNumber;
+ this.isOccupied = false;
+ this.patient = Optional.empty();
+ tasks = new RoomTasks();
+ }
+
+ /**
+ * Creates room object where roomNumber and isOccupied values are values given by user
+ */
+ public Room(int roomNumber, boolean isOccupied) {
+ requireAllNonNull(roomNumber, isOccupied);
+ this.roomNumber = roomNumber;
+ this.isOccupied = isOccupied;
+ this.patient = Optional.empty();
+ tasks = new RoomTasks();
+ }
+
+ /**
+ * Creates a room object containing a patient that can be found in the application.
+ *
+ * @param roomNumber Room Number of the room.
+ * @param patient Patient to be added to the room.
+ * @param tasks RoomTasks containing tasks for the room.
+ */
+ public Room(int roomNumber, Optional patient, RoomTasks tasks) {
+ requireAllNonNull(roomNumber, patient, tasks);
+ this.roomNumber = roomNumber;
+ this.isOccupied = true;
+ this.patient = patient;
+ this.tasks = tasks;
+ }
+
+ /**
+ * Creates a Room object where none of the values are pre determined by app
+ */
+ public Room(int roomNumber, boolean isOccupied, Optional patient, RoomTasks tasks) {
+ requireAllNonNull(roomNumber, isOccupied, patient, tasks);
+ this.roomNumber = roomNumber;
+ this.isOccupied = isOccupied;
+ this.patient = patient;
+ this.tasks = tasks;
+ }
+
+ public int getRoomNumber() {
+ return roomNumber;
+ }
+
+ //// patient
+
+ public Optional getPatient() {
+ return this.patient;
+ }
+
+ public boolean isOccupied() {
+ return isOccupied;
+ }
+
+ public void setOccupied(boolean isOccupied) {
+ this.isOccupied = isOccupied;
+ }
+
+ public void setPatient(Patient patient) {
+ this.patient = Optional.ofNullable(patient);
+ }
+
+ //// tasks
+
+ /**
+ * Returns an unmodifiable version of the list of tasks in this room as an {@code ObservableList}.
+ */
+ public ObservableList getReadOnlyTasks() {
+ return tasks.getReadOnlyList();
+ }
+
+ /**
+ * Returns an unmodifiable version of the list of tasks in this room as a {@code ReadOnlyList}.
+ */
+ public ReadOnlyList getReadOnlyList() {
+ return tasks;
+ }
+
+ /**
+ * Returns the task with the provided {@code taskIndex} from this room.
+ * An empty optional is returned if such a task is not found in the room.
+ *
+ * @param taskIndex The index of the task in this room.
+ * @return the optional-wrapped task if found, otherwise an empty optional
+ */
+ public Optional