> {
- class State1 as "__ab0:AddressBook__"
- class State2 as "__ab1:AddressBook__"
- class State3 as "__ab3:AddressBook__"
+ class State1 as "__hx0:HealthcareXpress__"
+ class State2 as "__hx1:HealthcareXpress__"
+ class State3 as "__hx2:HealthcareXpress__"
}
State1 -[hidden]right-> State2
State2 -[hidden]right-> State3
-class Pointer as "Current State" #FFFFF
+class Pointer as "Current State" #FFFFFF
Pointer -up-> State3
-note right on link: State ab2 deleted.
+note right on link: State hx2 deleted.
@end
diff --git a/docs/diagrams/UndoSequenceDiagram.puml b/docs/diagrams/UndoSequenceDiagram.puml
index 410aab4e412..63f7f65d73c 100644
--- a/docs/diagrams/UndoSequenceDiagram.puml
+++ b/docs/diagrams/UndoSequenceDiagram.puml
@@ -3,7 +3,7 @@
box Logic LOGIC_COLOR_T1
participant ":LogicManager" as LogicManager LOGIC_COLOR
-participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+participant ":HealthcareXpressParser" as HealthcareXpressParser LOGIC_COLOR
participant "u:UndoCommand" as UndoCommand LOGIC_COLOR
end box
@@ -14,18 +14,18 @@ end box
[-> LogicManager : execute(undo)
activate LogicManager
-LogicManager -> AddressBookParser : parseCommand(undo)
-activate AddressBookParser
+LogicManager -> HealthcareXpressParser : parseCommand(undo)
+activate HealthcareXpressParser
create UndoCommand
-AddressBookParser -> UndoCommand
+HealthcareXpressParser -> UndoCommand
activate UndoCommand
-UndoCommand --> AddressBookParser
+UndoCommand --> HealthcareXpressParser
deactivate UndoCommand
-AddressBookParser --> LogicManager : u
-deactivate AddressBookParser
+HealthcareXpressParser --> LogicManager : u
+deactivate HealthcareXpressParser
LogicManager -> UndoCommand : execute()
activate UndoCommand
diff --git a/docs/diagrams/UndoUnmarkActivityDiagram.puml b/docs/diagrams/UndoUnmarkActivityDiagram.puml
new file mode 100644
index 00000000000..10790cd44ac
--- /dev/null
+++ b/docs/diagrams/UndoUnmarkActivityDiagram.puml
@@ -0,0 +1,25 @@
+@startuml
+!include style.puml
+
+start
+:User executes mark command;
+
+if () then ([uid and dateslot index are both present])
+ if () then ([uid refers to a valid patient])
+ if () then ([dateslot index is valid])
+ if () then ([dateslot at index is unmarked])
+ :Mark the dateslot at the index for the patient with uid;
+ else ([else])
+ :Show error message about dateslot already being marked;
+ endif
+ else ([else])
+ :Show error message about dateslot index being invalid;
+ endif
+ else ([else])
+ :Show error message about invalid uid;
+ endif
+else ([else])
+ :Show error message about missing uid and/or missing dateslot index;
+endif
+stop
+@enduml
diff --git a/docs/diagrams/UndoUnmarkSequenceDiagram.puml b/docs/diagrams/UndoUnmarkSequenceDiagram.puml
new file mode 100644
index 00000000000..896b3827584
--- /dev/null
+++ b/docs/diagrams/UndoUnmarkSequenceDiagram.puml
@@ -0,0 +1,84 @@
+@startuml
+'https://plantuml.com/sequence-diagram
+!include style.puml
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":HealthcareXpressParser" as HealthcareXpressParser LOGIC_COLOR
+participant ":UndoUnmarkCommandParser" as UndoUnmarkCommandParser LOGIC_COLOR
+participant "m:UndoUnmarkCommand" as UndoUnmarkCommand LOGIC_COLOR
+participant ":InternalEditor" as InternalEditor 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("unmark userInput")
+activate LogicManager
+
+LogicManager -> HealthcareXpressParser : parseCommand("unmark userInput")
+activate HealthcareXpressParser
+
+create UndoUnmarkCommandParser
+HealthcareXpressParser -> UndoUnmarkCommandParser
+activate UndoUnmarkCommandParser
+
+UndoUnmarkCommandParser --> HealthcareXpressParser
+deactivate UndoUnmarkCommandParser
+
+HealthcareXpressParser -> UndoUnmarkCommandParser : parse("userInput")
+activate UndoUnmarkCommandParser
+
+create UndoUnmarkCommand
+UndoUnmarkCommandParser -> UndoUnmarkCommand
+activate UndoUnmarkCommand
+
+UndoUnmarkCommand --> UndoUnmarkCommandParser : m
+deactivate UndoUnmarkCommand
+
+UndoUnmarkCommandParser --> HealthcareXpressParser : m
+deactivate UndoUnmarkCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+UndoUnmarkCommandParser -[hidden]-> HealthcareXpressParser
+destroy UndoUnmarkCommandParser
+
+HealthcareXpressParser --> LogicManager : m
+deactivate HealthcareXpressParser
+
+LogicManager -> UndoUnmarkCommand : execute()
+activate UndoUnmarkCommand
+
+Create InternalEditor
+UndoUnmarkCommand -> InternalEditor
+activate InternalEditor
+
+InternalEditor --> UndoUnmarkCommand
+deactivate InternalEditor
+
+UndoUnmarkCommand -> InternalEditor : editPatient()
+activate InternalEditor
+
+InternalEditor -> Model : setPerson()
+activate Model
+
+Model --> InternalEditor
+deactivate Model
+
+deactivate InternalEditor
+
+create CommandResult
+UndoUnmarkCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> UndoUnmarkCommand
+deactivate CommandResult
+
+UndoUnmarkCommand --> LogicManager : result
+deactivate UndoUnmarkCommand
+
+[<--LogicManager
+deactivate LogicManager
+
+@enduml
diff --git a/docs/diagrams/UnmarkActivityDiagram.puml b/docs/diagrams/UnmarkActivityDiagram.puml
new file mode 100644
index 00000000000..a9f2bdcc7cf
--- /dev/null
+++ b/docs/diagrams/UnmarkActivityDiagram.puml
@@ -0,0 +1,21 @@
+@startuml
+!include style.puml
+
+start
+:User executes mark command;
+
+if () then ([uid and dateslot index are both present])
+ if () then ([uid refers to a valid patient])
+ if () then ([dateslot index is valid])
+ :Unmark the dateslot at the index for the patient with uid;
+ else ([else])
+ :Show error message about invalid dateslot index;
+ endif
+ else ([else])
+ :Show error message about invalid uid;
+ endif
+else ([else])
+ :Show error message about missing uid and/or missing dateslot index;
+endif
+stop
+@enduml
diff --git a/docs/diagrams/UnmarkSequenceDiagram.puml b/docs/diagrams/UnmarkSequenceDiagram.puml
new file mode 100644
index 00000000000..0e45b995e02
--- /dev/null
+++ b/docs/diagrams/UnmarkSequenceDiagram.puml
@@ -0,0 +1,84 @@
+@startuml
+'https://plantuml.com/sequence-diagram
+!include style.puml
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":HealthcareXpressParser" as HealthcareXpressParser LOGIC_COLOR
+participant ":UnmarkCommandParser" as UnmarkCommandParser LOGIC_COLOR
+participant "m:UnmarkCommand" as UnmarkCommand LOGIC_COLOR
+participant ":InternalEditor" as InternalEditor 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("unmark userInput")
+activate LogicManager
+
+LogicManager -> HealthcareXpressParser : parseCommand("unmark userInput")
+activate HealthcareXpressParser
+
+create UnmarkCommandParser
+HealthcareXpressParser -> UnmarkCommandParser
+activate UnmarkCommandParser
+
+UnmarkCommandParser --> HealthcareXpressParser
+deactivate UnmarkCommandParser
+
+HealthcareXpressParser -> UnmarkCommandParser : parse("userInput")
+activate UnmarkCommandParser
+
+create UnmarkCommand
+UnmarkCommandParser -> UnmarkCommand
+activate UnmarkCommand
+
+UnmarkCommand --> UnmarkCommandParser : m
+deactivate UnmarkCommand
+
+UnmarkCommandParser --> HealthcareXpressParser : m
+deactivate UnmarkCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+UnmarkCommandParser -[hidden]-> HealthcareXpressParser
+destroy UnmarkCommandParser
+
+HealthcareXpressParser --> LogicManager : m
+deactivate HealthcareXpressParser
+
+LogicManager -> UnmarkCommand : execute()
+activate UnmarkCommand
+
+Create InternalEditor
+UnmarkCommand -> InternalEditor
+activate InternalEditor
+
+InternalEditor --> UnmarkCommand
+deactivate InternalEditor
+
+UnmarkCommand -> InternalEditor : editPatient()
+activate InternalEditor
+
+InternalEditor -> Model : setPerson()
+activate Model
+
+Model --> InternalEditor
+deactivate Model
+
+deactivate InternalEditor
+
+create CommandResult
+UnmarkCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> UnmarkCommand
+deactivate CommandResult
+
+UnmarkCommand --> LogicManager : result
+deactivate UnmarkCommand
+
+[<--LogicManager
+deactivate LogicManager
+
+@enduml
diff --git a/docs/diagrams/UpdateContactActivityDiagram.puml b/docs/diagrams/UpdateContactActivityDiagram.puml
new file mode 100644
index 00000000000..27550c1aa05
--- /dev/null
+++ b/docs/diagrams/UpdateContactActivityDiagram.puml
@@ -0,0 +1,21 @@
+@startuml
+start
+:User executes update contact command;
+
+if () then ([all fields are present with exactly 1 input])
+ if () then ([person to edit is a patient])
+ if () then ([contact category is Next of Kin or Physician])
+ :Update contact and return;
+ else ([else])
+ :Show error message about invalid contact category;
+ endif
+ else ([else])
+ :Show error message about invalid category;
+ endif
+else ([else])
+:Show error message about invalid command format;
+endif
+stop
+@enduml
+
+
diff --git a/docs/diagrams/UpdateContactSequenceDiagram.puml b/docs/diagrams/UpdateContactSequenceDiagram.puml
new file mode 100644
index 00000000000..6f50312e021
--- /dev/null
+++ b/docs/diagrams/UpdateContactSequenceDiagram.puml
@@ -0,0 +1,55 @@
+@startuml
+
+participant ":LogicManager" as LogicManager
+participant ":HealthcareXpressParser" as HealthcareXpressParser
+participant ":UpdateContactCommandParser" as UpdateContactCommandParser
+participant ":UpdateContactCommand" as UpdateContactCommand
+participant ":CommandResult" as CommandResult
+
+participant ":Model" as Model
+
+[-> LogicManager : execute("updatecontact id/3 n/ John Doe p/ 81234567 e/ johndoe@example.com c/ D")
+activate LogicManager
+
+LogicManager -> HealthcareXpressParser : parseCommand("updatecontact...")
+activate HealthcareXpressParser
+
+create UpdateContactCommandParser
+HealthcareXpressParser -> UpdateContactCommandParser
+activate UpdateContactCommandParser
+
+UpdateContactCommandParser --> HealthcareXpressParser
+
+HealthcareXpressParser -> UpdateContactCommandParser : parse("updatecontact...")
+
+create UpdateContactCommand
+UpdateContactCommandParser --> UpdateContactCommand
+activate UpdateContactCommand
+UpdateContactCommand --> UpdateContactCommandParser
+UpdateContactCommandParser --> HealthcareXpressParser : UpdateContactCommand
+deactivate UpdateContactCommandParser
+HealthcareXpressParser --> LogicManager : UpdateContactCommand
+deactivate HealthcareXpressParser
+
+LogicManager --> UpdateContactCommand : execute()
+UpdateContactCommand --> Model: getFilteredPersonsList()
+activate Model
+Model --> UpdateContactCommand
+create BasePerson
+UpdateContactCommand --> BasePerson
+activate BasePerson
+BasePerson --> UpdateContactCommand
+UpdateContactCommand --> Model : updateFilteredPersonsList(BasePerson)
+Model --> UpdateContactCommand
+deactivate BasePerson
+deactivate Model
+
+create CommandResult
+UpdateContactCommand --> CommandResult
+CommandResult --> UpdateContactCommand
+UpdateContactCommand --> LogicManager : CommandResult
+deactivate UpdateContactCommand
+<- LogicManager : CommandResult
+
+@enduml
+
diff --git a/docs/diagrams/tracing/LogicSequenceDiagram.puml b/docs/diagrams/tracing/LogicSequenceDiagram.puml
index fdcbe1c0ccc..2b6c0e46359 100644
--- a/docs/diagrams/tracing/LogicSequenceDiagram.puml
+++ b/docs/diagrams/tracing/LogicSequenceDiagram.puml
@@ -2,7 +2,7 @@
!include ../style.puml
Participant ":LogicManager" as logic LOGIC_COLOR
-Participant ":AddressBookParser" as abp LOGIC_COLOR
+Participant ":HealthcareXpressParser" as abp LOGIC_COLOR
Participant ":EditCommandParser" as ecp LOGIC_COLOR
Participant "command:EditCommand" as ec LOGIC_COLOR
diff --git a/docs/images/AddNurse.png b/docs/images/AddNurse.png
new file mode 100644
index 00000000000..1460306d487
Binary files /dev/null and b/docs/images/AddNurse.png differ
diff --git a/docs/images/AddPatient.png b/docs/images/AddPatient.png
new file mode 100644
index 00000000000..df127ff7708
Binary files /dev/null and b/docs/images/AddPatient.png differ
diff --git a/docs/images/AddPatientActivityDiagram.png b/docs/images/AddPatientActivityDiagram.png
new file mode 100644
index 00000000000..50de9d664a1
Binary files /dev/null and b/docs/images/AddPatientActivityDiagram.png differ
diff --git a/docs/images/AddSequenceDiagram.png b/docs/images/AddSequenceDiagram.png
new file mode 100644
index 00000000000..05c2752648c
Binary files /dev/null and b/docs/images/AddSequenceDiagram.png differ
diff --git a/docs/images/Assign.png b/docs/images/Assign.png
new file mode 100644
index 00000000000..74e6ce8264f
Binary files /dev/null and b/docs/images/Assign.png differ
diff --git a/docs/images/AssignActivityDiagram.png b/docs/images/AssignActivityDiagram.png
new file mode 100644
index 00000000000..28a29b9c52e
Binary files /dev/null and b/docs/images/AssignActivityDiagram.png differ
diff --git a/docs/images/AssignSequenceDiagram.png b/docs/images/AssignSequenceDiagram.png
new file mode 100644
index 00000000000..561024e9d00
Binary files /dev/null and b/docs/images/AssignSequenceDiagram.png differ
diff --git a/docs/images/CommitActivityDiagram.png b/docs/images/CommitActivityDiagram.png
index c08c13f5c8b..e4cc7bebb18 100644
Binary files a/docs/images/CommitActivityDiagram.png and b/docs/images/CommitActivityDiagram.png differ
diff --git a/docs/images/Deassign.png b/docs/images/Deassign.png
new file mode 100644
index 00000000000..f72aa21050b
Binary files /dev/null and b/docs/images/Deassign.png differ
diff --git a/docs/images/Delete.png b/docs/images/Delete.png
new file mode 100644
index 00000000000..7880a14c9a2
Binary files /dev/null and b/docs/images/Delete.png differ
diff --git a/docs/images/DeleteSequenceDiagram.png b/docs/images/DeleteSequenceDiagram.png
index fa327b39618..3fcca6c5b37 100644
Binary files a/docs/images/DeleteSequenceDiagram.png and b/docs/images/DeleteSequenceDiagram.png differ
diff --git a/docs/images/Edit.png b/docs/images/Edit.png
new file mode 100644
index 00000000000..16831790dec
Binary files /dev/null and b/docs/images/Edit.png differ
diff --git a/docs/images/Find.png b/docs/images/Find.png
new file mode 100644
index 00000000000..ca92e2ed6b4
Binary files /dev/null and b/docs/images/Find.png differ
diff --git a/docs/images/Help.png b/docs/images/Help.png
new file mode 100644
index 00000000000..fd32f316660
Binary files /dev/null and b/docs/images/Help.png differ
diff --git a/docs/images/HelpQuickCommandHelp.png b/docs/images/HelpQuickCommandHelp.png
new file mode 100644
index 00000000000..a9a8bc6a082
Binary files /dev/null and b/docs/images/HelpQuickCommandHelp.png differ
diff --git a/docs/images/ListActivityDiagram.png b/docs/images/ListActivityDiagram.png
new file mode 100644
index 00000000000..20752a17e30
Binary files /dev/null and b/docs/images/ListActivityDiagram.png differ
diff --git a/docs/images/ListNurse.png b/docs/images/ListNurse.png
new file mode 100644
index 00000000000..8ae58bb1aaf
Binary files /dev/null and b/docs/images/ListNurse.png differ
diff --git a/docs/images/ListPatientheartDiasease.png b/docs/images/ListPatientheartDiasease.png
new file mode 100644
index 00000000000..1a556a9fd78
Binary files /dev/null and b/docs/images/ListPatientheartDiasease.png differ
diff --git a/docs/images/ListSequenceDiagram.png b/docs/images/ListSequenceDiagram.png
new file mode 100644
index 00000000000..cc6bfc1317e
Binary files /dev/null and b/docs/images/ListSequenceDiagram.png differ
diff --git a/docs/images/LogicClassDiagram.png b/docs/images/LogicClassDiagram.png
index 9e9ba9f79e5..e38ec134841 100644
Binary files a/docs/images/LogicClassDiagram.png and b/docs/images/LogicClassDiagram.png differ
diff --git a/docs/images/MarkActivityDiagram.png b/docs/images/MarkActivityDiagram.png
new file mode 100644
index 00000000000..a83ad39addc
Binary files /dev/null and b/docs/images/MarkActivityDiagram.png differ
diff --git a/docs/images/MarkSequenceDiagram.png b/docs/images/MarkSequenceDiagram.png
new file mode 100644
index 00000000000..5da4287b7b6
Binary files /dev/null and b/docs/images/MarkSequenceDiagram.png differ
diff --git a/docs/images/ModelClassDiagram.png b/docs/images/ModelClassDiagram.png
index 04070af60d8..496b35d45b2 100644
Binary files a/docs/images/ModelClassDiagram.png and b/docs/images/ModelClassDiagram.png differ
diff --git a/docs/images/ParserClasses.png b/docs/images/ParserClasses.png
index e7b4c8880cd..442e0ca3778 100644
Binary files a/docs/images/ParserClasses.png and b/docs/images/ParserClasses.png differ
diff --git a/docs/images/PatientClassDiagram.png b/docs/images/PatientClassDiagram.png
new file mode 100644
index 00000000000..441a0f2720f
Binary files /dev/null and b/docs/images/PatientClassDiagram.png differ
diff --git a/docs/images/PersonClassDiagram.png b/docs/images/PersonClassDiagram.png
new file mode 100644
index 00000000000..c1958630c76
Binary files /dev/null and b/docs/images/PersonClassDiagram.png differ
diff --git a/docs/images/Ui.png b/docs/images/Ui.png
index 5bd77847aa2..d018dfd6e82 100644
Binary files a/docs/images/Ui.png and b/docs/images/Ui.png differ
diff --git a/docs/images/UiV1.3.png b/docs/images/UiV1.3.png
new file mode 100644
index 00000000000..324ea6f5b55
Binary files /dev/null and b/docs/images/UiV1.3.png differ
diff --git a/docs/images/UndoRedoState0.png b/docs/images/UndoRedoState0.png
index 8f7538cd884..fa8a0e78466 100644
Binary files a/docs/images/UndoRedoState0.png and b/docs/images/UndoRedoState0.png differ
diff --git a/docs/images/UndoRedoState1.png b/docs/images/UndoRedoState1.png
index df9908d0948..98ff69b1a13 100644
Binary files a/docs/images/UndoRedoState1.png and b/docs/images/UndoRedoState1.png differ
diff --git a/docs/images/UndoRedoState2.png b/docs/images/UndoRedoState2.png
index 36519c1015b..f3cb19af548 100644
Binary files a/docs/images/UndoRedoState2.png and b/docs/images/UndoRedoState2.png differ
diff --git a/docs/images/UndoRedoState3.png b/docs/images/UndoRedoState3.png
index 19959d01712..17846041445 100644
Binary files a/docs/images/UndoRedoState3.png and b/docs/images/UndoRedoState3.png differ
diff --git a/docs/images/UndoRedoState4.png b/docs/images/UndoRedoState4.png
index 4c623e4f2c5..c3e79c32f7e 100644
Binary files a/docs/images/UndoRedoState4.png and b/docs/images/UndoRedoState4.png differ
diff --git a/docs/images/UndoRedoState5.png b/docs/images/UndoRedoState5.png
index 84ad2afa6bd..bf16b94cae0 100644
Binary files a/docs/images/UndoRedoState5.png and b/docs/images/UndoRedoState5.png differ
diff --git a/docs/images/UndoSequenceDiagram.png b/docs/images/UndoSequenceDiagram.png
index 6addcd3a8d9..5b5c0f777c5 100644
Binary files a/docs/images/UndoSequenceDiagram.png and b/docs/images/UndoSequenceDiagram.png differ
diff --git a/docs/images/UndoUnmark.png b/docs/images/UndoUnmark.png
new file mode 100644
index 00000000000..c527045edf2
Binary files /dev/null and b/docs/images/UndoUnmark.png differ
diff --git a/docs/images/UndoUnmarkActivityDiagram.png b/docs/images/UndoUnmarkActivityDiagram.png
new file mode 100644
index 00000000000..28e24fcfbc3
Binary files /dev/null and b/docs/images/UndoUnmarkActivityDiagram.png differ
diff --git a/docs/images/UndoUnmarkSequenceDiagram.png b/docs/images/UndoUnmarkSequenceDiagram.png
new file mode 100644
index 00000000000..dd556b50f11
Binary files /dev/null and b/docs/images/UndoUnmarkSequenceDiagram.png differ
diff --git a/docs/images/Unmark.png b/docs/images/Unmark.png
new file mode 100644
index 00000000000..f3463a7cf2c
Binary files /dev/null and b/docs/images/Unmark.png differ
diff --git a/docs/images/UnmarkActivityDiagram.png b/docs/images/UnmarkActivityDiagram.png
new file mode 100644
index 00000000000..b871b3095b4
Binary files /dev/null and b/docs/images/UnmarkActivityDiagram.png differ
diff --git a/docs/images/UnmarkSequenceDiagram.png b/docs/images/UnmarkSequenceDiagram.png
new file mode 100644
index 00000000000..0801c272e9e
Binary files /dev/null and b/docs/images/UnmarkSequenceDiagram.png differ
diff --git a/docs/images/UpdateContactActivityDiagram.png b/docs/images/UpdateContactActivityDiagram.png
new file mode 100644
index 00000000000..05634277606
Binary files /dev/null and b/docs/images/UpdateContactActivityDiagram.png differ
diff --git a/docs/images/UpdateContactSequenceDiagram.png b/docs/images/UpdateContactSequenceDiagram.png
new file mode 100644
index 00000000000..1a9e5ad2711
Binary files /dev/null and b/docs/images/UpdateContactSequenceDiagram.png differ
diff --git a/docs/images/checkSimilar.png b/docs/images/checkSimilar.png
new file mode 100644
index 00000000000..5a762b64b02
Binary files /dev/null and b/docs/images/checkSimilar.png differ
diff --git a/docs/images/helpMessageUpdated.png b/docs/images/helpMessageUpdated.png
new file mode 100644
index 00000000000..e1fed3e6283
Binary files /dev/null and b/docs/images/helpMessageUpdated.png differ
diff --git a/docs/images/johnbenedictyan.png b/docs/images/johnbenedictyan.png
new file mode 100644
index 00000000000..8286aaedaee
Binary files /dev/null and b/docs/images/johnbenedictyan.png differ
diff --git a/docs/images/lolfoollors.png b/docs/images/lolfoollors.png
new file mode 100644
index 00000000000..6f12aed4c59
Binary files /dev/null and b/docs/images/lolfoollors.png differ
diff --git a/docs/images/mlzt2000.png b/docs/images/mlzt2000.png
new file mode 100644
index 00000000000..969d68fc38b
Binary files /dev/null and b/docs/images/mlzt2000.png differ
diff --git a/docs/images/updatecontact.png b/docs/images/updatecontact.png
new file mode 100644
index 00000000000..8a5e225db39
Binary files /dev/null and b/docs/images/updatecontact.png differ
diff --git a/docs/images/xhphoong.png b/docs/images/xhphoong.png
new file mode 100644
index 00000000000..02248ad6382
Binary files /dev/null and b/docs/images/xhphoong.png differ
diff --git a/docs/images/yeehaoo.png b/docs/images/yeehaoo.png
new file mode 100644
index 00000000000..9ef4e97f0a9
Binary files /dev/null and b/docs/images/yeehaoo.png differ
diff --git a/docs/index.md b/docs/index.md
index 7601dbaad0d..1728d50d133 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,17 +1,17 @@
---
layout: page
-title: AddressBook Level-3
+title: HealthcareXpress
---
[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/se-edu/addressbook-level3/actions)
-[![codecov](https://codecov.io/gh/se-edu/addressbook-level3/branch/master/graph/badge.svg)](https://codecov.io/gh/se-edu/addressbook-level3)
+[![codecov](https://codecov.io/gh/AY2223S1-CS2103-F13-4/tp/branch/master/graph/badge.svg?token=C354PCI8TZ)](https://codecov.io/gh/AY2223S1-CS2103-F13-4/tp)
![Ui](images/Ui.png)
-**AddressBook is a desktop application for managing your contact details.** While it has a GUI, most of the user interactions happen using a CLI (Command Line Interface).
+**HealthcareXpess is a desktop application for medical administrators to manage patients and nurses.** While it has a GUI, most of the user interactions happen using a CLI (Command Line Interface).
-* If you are interested in using AddressBook, head over to the [_Quick Start_ section of the **User Guide**](UserGuide.html#quick-start).
-* If you are interested about developing AddressBook, the [**Developer Guide**](DeveloperGuide.html) is a good place to start.
+* If you are interested in using HealthcareXpress, head over to the [_Quick Start_ section of the **User Guide**](https://ay2223s1-cs2103-f13-4.github.io/tp/UserGuide.html)).
+* If you are interested about developing HealthcareXpress, the [**Developer Guide**](https://ay2223s1-cs2103-f13-4.github.io/tp/DeveloperGuide.html)) is a good place to start.
**Acknowledgements**
diff --git a/docs/team/johnbenedictyan.md b/docs/team/johnbenedictyan.md
new file mode 100644
index 00000000000..c5849a808f2
--- /dev/null
+++ b/docs/team/johnbenedictyan.md
@@ -0,0 +1,109 @@
+---
+layout: page
+title: John Benedict's Project Portfolio Page
+---
+
+### Project: HealthCare Xpress
+
+HealthCare Xpress is a desktop application that is to be used by medical administrator for managing patients that require home-visits and nurses. It helps medical administrators manage nurses, patients, their next of kin and attending physicians.The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has 10042 lines of code.
+
+Given below are my contributions to the project.
+
+- **New Features**:
+
+ 1. Uid
+
+ - What it does:
+ - Unique Id and the manager to manage operations associated with the uid.
+ - Justification:
+ - Uid solves the issue whereby the medical administrator may enter very similar persons into Healthcare Xpress.
+ - Uid helps to differentiate between these individuals.
+ - Highlights:
+ - Implementing a unique set of uid was challenging.
+
+
+ 1. Delete Command
+
+ - What it does:
+ - Deletes the person based on their uid.
+ - Justification:
+ - The delete command is an essential command so that the medical administrator can remove persons who are no longer relevant.
+
+
+ 3. Check Similar Command
+
+ - What it does:
+ - Deletes the person based on their uid.
+ - Justification:
+ - The delete command is an essential command so that the medical administrator can remove persons who are no longer relevant.
+
+
+- **Code contributed**: [RepoSense link](https://nus-cs2103-ay2223s1.github.io/tp-dashboard/?search=ay2223s1-cs2103-f13-4&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2022-09-16&tabOpen=true&tabType=authorship&tabAuthor=johnbenedictyan&tabRepo=AY2223S1-CS2103-F13-4%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false)
+
+- **Project management**:
+
+ - Assigned teammates to different issues and kept track of their progress
+
+
+- **Enhancements to existing features**:
+
+ - Refactor code to use streams and optional.
+ - Refactor code to increase SLAP [#126](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/126) [#224](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/224)
+ - Improve List Parser to account for commonly misspelt words [#111](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/111)
+
+
+- **Documentation**:
+
+ - User Guide:
+ - Delete Command
+ - Other miscellaneous parts and proofreading
+ - Developer Guide:
+ - Target user profile
+ - Value proposition
+ - User stories
+ - Delete command implementation
+ - Unique ID implementation
+ - Assign Command
+ - Deassign Command
+ - Other miscellaneous parts and proofreading
+
+
+- **Contributions to the Developer Guide**
+ ### Assign Feature
+
+ #### Motivation:
+
+ - The assign feature is necessary so that the medical administrator can visually see which nurse is attending which patient's home visit.
+
+ #### Implementation:
+
+ ![AssignSequenceDiagram](../images/AssignSequenceDiagram.png)
+
+ Step 1. The user executes `assign id/3 id/2`
+
+ Step 2. `HealthcareXpressParser` creates an `AssignCommandParser` to parse the arguments.
+
+ Step 3. `AssignCommandParser` checks validity of the given arguments and creates an `AssignCommand`.
+
+ Step 4. The `AssignCommand` is executed, and a new `InternalEditor` is created.
+
+ Step 5. `AssignCommand` calls the `InternalEditor`'s methods of `editPatient` and `editNurse`.
+
+ Step 6. `Model` updates the database, and displays all the persons.
+
+ The activity diagram below summarises exception handling of AssignCommand:
+
+ ![AssignActivityDiagram](../images/AssignActivityDiagram.png)
+
+
+ #### Design considerations:
+
+ - **Aspect: How the parse interprets the order of uids**
+ - **Alternative 1:** Fix the order of the uid, so patient then nurse
+ - Pros: There will be less checking needed to deduce the class of the persons involved.
+ - Cons: The user experience will suffer as the medical administrator might not be able to accurately remember which uid corresponding to which person, the nurse or the patient.
+
+ - **Alternative 2:** Have no fix order, as long as one nurse uid and one patient uid is inputted
+ - Pros: The user experience will be better as there will be more leeway.
+ - Cons: Harder to implement and more testing is required.
+
diff --git a/docs/team/lolfoollors.md b/docs/team/lolfoollors.md
new file mode 100644
index 00000000000..82e8b599950
--- /dev/null
+++ b/docs/team/lolfoollors.md
@@ -0,0 +1,53 @@
+---
+layout: page
+title: lolfoollors's Project Portfolio Page
+---
+
+### Project: HealthCare Xpress
+
+HealthCare Xpress is a desktop application that is to be used by medical administrator for managing patients that require home-visits and nurses. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 16 kLoC.
+
+Given below are my contributions to the project.
+
+* **New Feature**: Added the ability to add nurse.
+ * What it does: It allows the app to add nurses into HealthCare Xpress.
+ * Justification: This is critical in letting the application run as intended. The medical administrator would be able to add nurse and view which nurse might be available for different patients.
+ * Highlights: This feature was done mainly by refactoring existing code
+
+* **Major Enhancement**: Overhauled the entire help window.
+ * What it does: It allows the user to look in the help window to understand the functions more.
+ * Justification: It provides a quick and easily access to a help book in case of emergency when there is no internet available. Furthermore, it also provides a sample input and output to show to the user how to use it and the expected outcome.
+ * Highlights:
+ * There is a mini app display to show sample input and output for the command selected.
+ * The text is animated to show the user how it is typed in.
+ * There is a search bar for the user to search for the command easily.
+ * There is a link to our GitHub page and User guide if the user still does not understand how to use it.
+ * There is a help command at the bottom right to show more details on how to use it.
+ * Operates in a different thread so you need not wait for the animation to finish before using the app.
+
+* **Minor Enhancements**: Overhauled Date checking for date class.
+ * What it does: It now not only checks for valid date format but also checks for leap year and valid dates.
+ * Justification: It is critical to Healthcare Xpress working properly as date can only be written in 1 format. If written other than designated format before, the app will just totally ignore the user.
+ * Highlights:
+ * Now checks for valid dates properly.
+
+* **Minor Enhancements**: Updated GUI of the app.
+ * What it does: Improved looks of program.
+ * Justification: To differentiate from other project applications.
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2223s1.github.io/tp-dashboard/?search=ay2223s1-cs2103-f13-4&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2022-09-16&tabOpen=true&tabType=authorship&tabAuthor=LolfoollorS&tabRepo=AY2223S1-CS2103-F13-4%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false)
+
+* **Project management**:
+ * Code Review
+ * Testing of Code
+
+* **Documentation**:
+ * User Guide:
+ * Add Nurse
+ * Help Window
+ * Fixed documentation bugs and edits. [#220](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/220/files) [#246](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/246)
+
+* **Community**:
+ * Reported 15 bugs during PE-D exercise.
+
+
diff --git a/docs/team/mlzt2000.md b/docs/team/mlzt2000.md
new file mode 100644
index 00000000000..bb85460dcdb
--- /dev/null
+++ b/docs/team/mlzt2000.md
@@ -0,0 +1,38 @@
+### Project: Healthcare Xpress
+
+Healthcare Xpress is a desktop medical address book application used by medical administrators, for managing medical staff and patients. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10000 lines of code.
+
+Given below are my contributions to the project.
+
+* **New Feature: Mark [Defunct], replaced by `unmark` and `undounmark`**
+ * What it does: Marks a patient as visited.
+ * Justification: A core functionality of the application is to show that patients have been visited by their assigned nurse.
+ * Highlights: This command made use of existing code that supported the Edit command, making it a more specific version of the Edit functionality.
+ * Pull request: [#82](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/82)
+
+
+* **Code Contributed:** [RepoSense link](https://nus-cs2103-ay2223s1.github.io/tp-dashboard/?search=low&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2022-09-16&tabOpen=true&tabType=authorship&tabAuthor=mlzt2000&tabRepo=AY2223S1-CS2103-F13-4%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false)
+
+
+* **Enhancements to existing features: Filtered List [Not part of final product]**
+ * What it does: Allows user to filter out patients that have not been assigned nurses, and nurses that have not been completely assigned with patients.
+ * Justification: There is a need to find out which patients have not been assigned so that user does not miss out on any patients. There is then a need to find nurses that are still available to conduct home visits.
+ * Pull request: [#129](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/129)
+
+
+* **Contributions to team-based tasks**:
+ * Code reviews.
+ * Overall testing of code.
+
+
+* **Documentation**:
+ * User Guide:
+ * Mark Command [Defunct], replaced by `unmark` and `undounmark`.
+ * Developer Guide:
+ * Non-functional requirements.
+ * Mark Command [Defunct], replaced by `unmark` and `undounmark`.
+
+
+* **Community**:
+ * Reported bugs during PE-D.
+
diff --git a/docs/team/xhphoong.md b/docs/team/xhphoong.md
new file mode 100644
index 00000000000..13005dc9e9c
--- /dev/null
+++ b/docs/team/xhphoong.md
@@ -0,0 +1,65 @@
+---
+layout: page
+title: xhphoong's Project Portfolio Page
+---
+
+### Project: HealthCare Xpress
+
+Healthcare Xpress is a desktop medical address book application used by medical administrators, for managing medical staff and patients. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10k lines of code.
+
+Given below are my contributions to the project.
+
+* **New Features**:
+
+1. Assign a Patient's dateslot(s) to a nurse
+ * What it does: Allows the medical administrator to assign a patient's dateslot(s) to a nurse.
+ * Justification: This is the main feature of our product. The medical administrator assign the patient's dateslot(s) to nurse and the system will record down the assign status of each date slot and the homevisits that the nurses have to attend to. The system will also auto check time crashes. This makes the administrative assigning process more easy and effective.
+ * Related Pull Requests: [#239](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/239) [#118](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/118)
+
+2. Deassign a Patient's dateslot(s) / a Nurse's homevisit(s)
+ * What it does: Allows the medical administrator to deassign a patient's dateslot(s) / a nurse's homevisit(s).
+ * Justification: In case of a sudden change made or wrong assigning made, the medical administrator can deassign the patient's dateslot(s) / the nurse's homevisit(s).
+ * Related Pull Requests: [#239](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/239) [#118](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/118)
+
+3. Unmark a Patient's dateslot as fail to visit
+ * What it does: Allows the medical administrator to unmark a patient's dateslot that has passed as fail to visit.
+ * Justification: When the nurse attended to the homevisits but the patient were not there or other circumstance that made the nurse to fail visit the patient, the medical administrator can unmark a patient's dateslot as fail to visit so that the medical administrator can keep track of the visit status of each date slot and determine whether there is a need to schedule a new home visit date and slot with the patient.
+ * Related Pull Requests: [#239](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/239) [#118](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/118)
+
+4. Undo unmark a Patient's dateslot as success visit
+ * What it does: Allows the medical administrator to undo the unmarking of a patient's dateslot that has passed to success visit.
+ * Justification: When the medical administrator had unmark the wrong date slot, the medical administrator can undo the unmarking of a patient's dateslot to success visit so that the medical administrator can keep track of the correct visit status of each date slot.
+ * Related Pull Requests: [#239](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/239) [#123](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/123)
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2223s1.github.io/tp-dashboard/?search=xhphoong&breakdown=true&sort=groupTitle&sortWithin=title&since=2022-09-16&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other&tabOpen=true&tabType=authorship&tabAuthor=xhphoong&tabRepo=AY2223S1-CS2103-F13-4%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code~other&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false)
+
+
+* **Enhancements to existing features**:
+
+1. Add gender attribute to person. [#67](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/67/files)
+2. Add patient that extends from person and has date and slot attribute. [#118](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/118) [#67](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/67/files)
+3. Add home visit, unavailable date list and fully scheduled date list attributes to the nurse (created by other teammates). [#118](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/118)
+4. Modify the add feature to add patient. [#67](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/67/files)
+5. Modify the edit feature to edit newly-added attributes such as date and slot, unavailable date and gender. [#239](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/239) [#118](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/118) [#79](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/79) [#67](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/67/files)
+
+* **Documentation**:
+ * User Guide:
+ * Add Patient Feature
+ * Edit Feature
+ * Assign Feature
+ * Deassign Feature
+ * Unmark Feature
+ * UndoUnmark Feature
+ * Related Pull Requests : [#130](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/130) [#122](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/122)
+ * Developer Guide:
+ * Use cases [#248](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/248) [#29](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/29)
+ * Initial Add Command Implementation [#104](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/104)
+
+* **Contributions to team-based tasks**:
+ * Setting up the GitHub team organisation and repo
+ * Code reviews made for other teammates' pull requests
+ * Fix bugs and errors
+ * Improve code quality
+
+
+
diff --git a/docs/team/yeehaoo.md b/docs/team/yeehaoo.md
new file mode 100644
index 00000000000..a869888d127
--- /dev/null
+++ b/docs/team/yeehaoo.md
@@ -0,0 +1,51 @@
+### Project: Healthcare Xpress
+
+Healthcare Xpress is a desktop medical address book application used by medical administrators, for managing medical staff and patients. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 8200 lines of code.
+
+Given below are my contributions to the project.
+
+
+
+* **New Feature**: Update Emergency Contact
+ * What it does: Allows the medical administrator to add and update attending physician and next of kin contacts for patients.
+ * Justification: In case of emergency, the medical administrator would be able to quickly reach the attending physician and next of kin, and inform them of the emergency. For example, if an incident occurs during a nurse's home visit, the attending physician can be reached within a quick query instead of having to query some other database.
+ * Highlights: This implementation was challenging to make efficient, and the plan initially was to create two commands to solve this issue. However, it was found that they could be combined through polymorphism instead and the problem was solved efficiently.
+ * Pull request: [#110](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/110)
+
+
+* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2223s1.github.io/tp-dashboard/?search=ay2223s1-cs2103-f13-4&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2022-09-16&tabOpen=true&tabType=authorship&tabAuthor=yeehaoo&tabRepo=AY2223S1-CS2103-F13-4%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false)
+
+
+* **Enhancements to existing features**: Filtered List
+ * What it does: Allows the medical administrator to filter enrolled patients or nurses by several filters, including category, gender, tags and address.
+ * Justification: This feature allows the medical administrator to quickly filter the list of people based on given specifications, to facilitate other tasks such as assigning patients to nurses based on location, or other such queries.
+ * Highlights: The implementation took some time because instead of creating a new function, the current implementation had to be examined and adapted to our use case. Once the current mechanism was understood, then the tweaks were applied.
+ * Pull request: [#68](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/68)
+
+
+* **Contributions to team-based tasks**:
+ * Managed issues and milestones
+ * Handled deadlines, frequent check-ins with team
+ * Code reviews for many pull requests
+
+
+* **Documentation**:
+ * User Guide:
+ * List feature
+ * Update emergency contact feature
+ * Help feature
+ * Find feature
+ * Enhance overall grammar and readability [#230](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/230)
+ * Developer Guide:
+ * List feature
+ * Update emergency contact feature
+ * Edited add feature's comments [#247](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/247)
+ * Update hyperlinks [#245](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/245)
+ * Update DG diagrams [#247](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/247)
+ * Person class diagram [#249](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/249)
+ * Enhance overall grammar and readability [#249](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/249)
+
+
+* **Community**:
+ * PRs reviewed: [#29](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/29), [#32](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/32), [#44](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/44), [#75](https://github.com/AY2223S1-CS2103-F13-4/tp/pull/75)
+ * Reported bugs during PE-D exercise.
diff --git a/docs/tutorials/AddRemark.md b/docs/tutorials/AddRemark.md
index 880c701042f..09e24328acb 100644
--- a/docs/tutorials/AddRemark.md
+++ b/docs/tutorials/AddRemark.md
@@ -43,7 +43,7 @@ public class RemarkCommand extends Command {
### Hook `RemarkCommand` into the application
-Now that we have our `RemarkCommand` ready to be executed, we need to update `AddressBookParser#parseCommand()` to recognize the `remark` keyword. Add the new command to the `switch` block by creating a new `case` that returns a new instance of `RemarkCommand`.
+Now that we have our `RemarkCommand` ready to be executed, we need to update `HealthcareXpressParser#parseCommand()` to recognize the `remark` keyword. Add the new command to the `switch` block by creating a new `case` that returns a new instance of `RemarkCommand`.
You can refer to the changes in this [diff](https://github.com/se-edu/addressbook-level3/commit/35eb7286f18a029d39cb7a29df8f172a001e4fd8#diff-399c284cb892c20b7c04a69116fcff6ccc0666c5230a1db8e4a9145def8fa4ee).
@@ -216,7 +216,7 @@ public RemarkCommand parse(String args) throws ParseException {
-:information_source: Don’t forget to update `AddressBookParser` to use our new `RemarkCommandParser`!
+:information_source: Don’t forget to update `HealthcareXpressParser` to use our new `RemarkCommandParser`!
diff --git a/docs/tutorials/TracingCode.md b/docs/tutorials/TracingCode.md
index 4fb62a83ef6..ee9f3b5edbd 100644
--- a/docs/tutorials/TracingCode.md
+++ b/docs/tutorials/TracingCode.md
@@ -120,7 +120,7 @@ Recall from the User Guide that the `edit` command has the format: `edit INDEX [
CommandResult commandResult;
//Parse user input from String to a Command
- Command command = addressBookParser.parseCommand(commandText);
+ Command command = HealthcareXpressParser.parseCommand(commandText);
//Executes the Command and stores the result
commandResult = command.execute(model);
@@ -141,7 +141,7 @@ Recall from the User Guide that the `edit` command has the format: `edit INDEX [
1. _Step over_ the logging code since it is of no interest to us now.
![StepOver](../images/tracing/StepOver.png)
-1. _Step into_ the line where user input in parsed from a String to a Command, which should bring you to the `AddressBookParser#parseCommand()` method (partial code given below):
+1. _Step into_ the line where user input in parsed from a String to a Command, which should bring you to the `HealthcareXpressParser#parseCommand()` method (partial code given below):
``` java
public Command parseCommand(String userInput) throws ParseException {
...
diff --git a/src/main/java/seedu/address/AppParameters.java b/src/main/java/seedu/address/AppParameters.java
index ab552c398f3..56c76c7f73f 100644
--- a/src/main/java/seedu/address/AppParameters.java
+++ b/src/main/java/seedu/address/AppParameters.java
@@ -18,14 +18,6 @@ public class AppParameters {
private Path configPath;
- public Path getConfigPath() {
- return configPath;
- }
-
- public void setConfigPath(Path configPath) {
- this.configPath = configPath;
- }
-
/**
* Parses the application command-line parameters.
*/
@@ -43,6 +35,14 @@ public static AppParameters parse(Application.Parameters parameters) {
return appParameters;
}
+ public Path getConfigPath() {
+ return configPath;
+ }
+
+ public void setConfigPath(Path configPath) {
+ this.configPath = configPath;
+ }
+
@Override
public boolean equals(Object other) {
if (other == this) {
diff --git a/src/main/java/seedu/address/Main.java b/src/main/java/seedu/address/Main.java
index 052a5068631..1c4908730b9 100644
--- a/src/main/java/seedu/address/Main.java
+++ b/src/main/java/seedu/address/Main.java
@@ -4,17 +4,18 @@
/**
* The main entry point to the application.
- *
+ *
* This is a workaround for the following error when MainApp is made the
* entry point of the application:
- *
- * Error: JavaFX runtime components are missing, and are required to run this application
- *
+ *
+ * Error: JavaFX runtime components are missing, and are required to run this
+ * application
+ *
* The reason is that MainApp extends Application. In that case, the
* LauncherHelper will check for the javafx.graphics module to be present
* as a named module. We don't use JavaFX via the module system so it can't
* find the javafx.graphics module, and so the launch is aborted.
- *
+ *
* By having a separate main class (Main) that doesn't extend Application
* to be the entry point of the application, we avoid this issue.
*/
diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java
index 4133aaa0151..08a77159db3 100644
--- a/src/main/java/seedu/address/MainApp.java
+++ b/src/main/java/seedu/address/MainApp.java
@@ -69,9 +69,12 @@ 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 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.
*/
private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) {
Optional addressBookOptional;
@@ -124,7 +127,8 @@ protected Config initConfig(Path configFilePath) {
initializedConfig = new Config();
}
- //Update config file in case it was missing to begin with or there are new/unused fields
+ // Update config file in case it was missing to begin with or there are
+ // new/unused fields
try {
ConfigUtil.saveConfig(initializedConfig, configFilePathUsed);
} catch (IOException e) {
@@ -134,7 +138,8 @@ protected Config initConfig(Path configFilePath) {
}
/**
- * Returns a {@code UserPrefs} using the file at {@code storage}'s user prefs file path,
+ * Returns a {@code UserPrefs} using the file at {@code storage}'s user prefs
+ * file path,
* or a new {@code UserPrefs} with default configuration if errors occur when
* reading from the file.
*/
@@ -155,7 +160,8 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) {
initializedPrefs = new UserPrefs();
}
- //Update prefs file in case it was missing to begin with or there are new/unused fields
+ // Update prefs file in case it was missing to begin with or there are
+ // new/unused fields
try {
storage.saveUserPrefs(initializedPrefs);
} catch (IOException e) {
diff --git a/src/main/java/seedu/address/commons/core/Config.java b/src/main/java/seedu/address/commons/core/Config.java
index 91145745521..8de795addfa 100644
--- a/src/main/java/seedu/address/commons/core/Config.java
+++ b/src/main/java/seedu/address/commons/core/Config.java
@@ -37,7 +37,7 @@ public boolean equals(Object other) {
if (other == this) {
return true;
}
- if (!(other instanceof Config)) { //this handles null as well.
+ if (!(other instanceof Config)) { // this handles null as well.
return false;
}
@@ -55,8 +55,8 @@ public int hashCode() {
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append("Current log level : " + logLevel);
- sb.append("\nPreference file Location : " + userPrefsFilePath);
+ sb.append("Current log level : ").append(logLevel);
+ sb.append("\nPreference file Location : ").append(userPrefsFilePath);
return sb.toString();
}
diff --git a/src/main/java/seedu/address/commons/core/GuiSettings.java b/src/main/java/seedu/address/commons/core/GuiSettings.java
index ba33653be67..414b62b3b7a 100644
--- a/src/main/java/seedu/address/commons/core/GuiSettings.java
+++ b/src/main/java/seedu/address/commons/core/GuiSettings.java
@@ -27,7 +27,8 @@ public GuiSettings() {
}
/**
- * Constructs a {@code GuiSettings} with the specified height, width and position.
+ * Constructs a {@code GuiSettings} with the specified height, width and
+ * position.
*/
public GuiSettings(double windowWidth, double windowHeight, int xPosition, int yPosition) {
this.windowWidth = windowWidth;
@@ -52,7 +53,7 @@ public boolean equals(Object other) {
if (other == this) {
return true;
}
- if (!(other instanceof GuiSettings)) { //this handles null as well.
+ if (!(other instanceof GuiSettings)) { // this handles null as well.
return false;
}
@@ -71,9 +72,9 @@ public int hashCode() {
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append("Width : " + windowWidth + "\n");
- sb.append("Height : " + windowHeight + "\n");
- sb.append("Position : " + windowCoordinates);
+ sb.append("Width : ").append(windowWidth).append("\n");
+ sb.append("Height : ").append(windowHeight).append("\n");
+ sb.append("Position : ").append(windowCoordinates);
return sb.toString();
}
}
diff --git a/src/main/java/seedu/address/commons/core/LogsCenter.java b/src/main/java/seedu/address/commons/core/LogsCenter.java
index 431e7185e76..fdee8761f32 100644
--- a/src/main/java/seedu/address/commons/core/LogsCenter.java
+++ b/src/main/java/seedu/address/commons/core/LogsCenter.java
@@ -11,23 +11,27 @@
/**
* Configures and manages loggers and handlers, including their logging level
* Named {@link Logger}s can be obtained from this class
- * These loggers have been configured to output messages to the console and a {@code .log} file by default,
- * at the {@code INFO} level. A new {@code .log} file with a new numbering will be created after the log
- * file reaches 5MB big, up to a maximum of 5 files.
+ * These loggers have been configured to output messages to the console and a
+ * {@code .log} file by default,
+ * at the {@code INFO} level. A new {@code .log} file with a new numbering will
+ * be created after the log
+ * file reaches 5MB big, up to a maximum of 5 files.
*/
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 Level currentLogLevel = Level.INFO;
- private static final Logger logger = LogsCenter.getLogger(LogsCenter.class);
private static FileHandler fileHandler;
private static ConsoleHandler consoleHandler;
+ private static final Logger logger = LogsCenter.getLogger(LogsCenter.class);
/**
* Initializes with a custom log level (specified in the {@code config} object)
- * Loggers obtained *AFTER* this initialization will have their logging level changed
- * Logging levels for existing loggers will only be updated if the logger with the same name
+ * Loggers obtained *AFTER* this initialization will have their logging level
+ * changed
+ * Logging levels for existing loggers will only be updated if the logger with
+ * the same name
* is requested again from the LogsCenter.
*/
public static void init(Config config) {
@@ -95,6 +99,7 @@ private static void addFileHandler(Logger logger) {
/**
* Creates a {@code FileHandler} for the log file.
+ *
* @throws IOException if there are problems opening the file.
*/
private static FileHandler createFileHandler() throws IOException {
diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java
index 1deb3a1e469..1bdfdca6f29 100644
--- a/src/main/java/seedu/address/commons/core/Messages.java
+++ b/src/main/java/seedu/address/commons/core/Messages.java
@@ -7,7 +7,13 @@ public class Messages {
public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command";
public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s";
- public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The person index provided is invalid";
+ public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The index provided is invalid";
+ public static final String MESSAGE_INVALID_PERSON_DISPLAYED_UID = "The person uid provided is invalid";
public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
+ public static final String MESSAGE_INVALID_CATEGORY = "Invalid category detected!";
+ public static final String MESSAGE_UPDATECONTACT_INVALID_CATEGORY = "Contact info can only be set for patients.";
+ public static final String MESSAGE_UPDATECONTACT_INVALID_CONTACT_CATEGORY =
+ "Contact must be a physician (category D) or next of kin (category K)";
+
}
diff --git a/src/main/java/seedu/address/commons/core/Version.java b/src/main/java/seedu/address/commons/core/Version.java
index 12142ec1e32..c9511d13eff 100644
--- a/src/main/java/seedu/address/commons/core/Version.java
+++ b/src/main/java/seedu/address/commons/core/Version.java
@@ -32,24 +32,9 @@ public Version(int major, int minor, int patch, boolean isEarlyAccess) {
this.isEarlyAccess = isEarlyAccess;
}
- public int getMajor() {
- return major;
- }
-
- public int getMinor() {
- return minor;
- }
-
- public int getPatch() {
- return patch;
- }
-
- public boolean isEarlyAccess() {
- return isEarlyAccess;
- }
-
/**
* Parses a version number string in the format V1.2.3.
+ *
* @param versionString version number string
* @return a Version object
*/
@@ -64,7 +49,23 @@ public static Version fromString(String versionString) throws IllegalArgumentExc
return new Version(Integer.parseInt(versionMatcher.group(1)),
Integer.parseInt(versionMatcher.group(2)),
Integer.parseInt(versionMatcher.group(3)),
- versionMatcher.group(4) == null ? false : true);
+ versionMatcher.group(4) != null);
+ }
+
+ public int getMajor() {
+ return major;
+ }
+
+ public int getMinor() {
+ return minor;
+ }
+
+ public int getPatch() {
+ return patch;
+ }
+
+ public boolean isEarlyAccess() {
+ return isEarlyAccess;
}
@JsonValue
diff --git a/src/main/java/seedu/address/commons/core/index/Index.java b/src/main/java/seedu/address/commons/core/index/Index.java
index 19536439c09..edfe6ebe7c0 100644
--- a/src/main/java/seedu/address/commons/core/index/Index.java
+++ b/src/main/java/seedu/address/commons/core/index/Index.java
@@ -2,14 +2,18 @@
/**
* Represents a zero-based or one-based index.
- *
- * {@code Index} should be used right from the start (when parsing in a new user input), so that if the current
- * component wants to communicate with another component, it can send an {@code Index} to avoid having to know what
- * base the other component is using for its index. However, after receiving the {@code Index}, that component can
- * convert it back to an int if the index will not be passed to a different component again.
+ *
+ * {@code Index} should be used right from the start (when parsing in a new user
+ * input), so that if the current
+ * component wants to communicate with another component, it can send an
+ * {@code Index} to avoid having to know what
+ * base the other component is using for its index. However, after receiving the
+ * {@code Index}, that component can
+ * convert it back to an int if the index will not be passed to a different
+ * component again.
*/
public class Index {
- private int zeroBasedIndex;
+ private final int zeroBasedIndex;
/**
* Index can only be created by calling {@link Index#fromZeroBased(int)} or
@@ -23,14 +27,6 @@ private Index(int zeroBasedIndex) {
this.zeroBasedIndex = zeroBasedIndex;
}
- public int getZeroBased() {
- return zeroBasedIndex;
- }
-
- public int getOneBased() {
- return zeroBasedIndex + 1;
- }
-
/**
* Creates a new {@code Index} using a zero-based index.
*/
@@ -45,10 +41,19 @@ public static Index fromOneBased(int oneBasedIndex) {
return new Index(oneBasedIndex - 1);
}
+ public int getZeroBased() {
+ return zeroBasedIndex;
+ }
+
+ public int getOneBased() {
+ return zeroBasedIndex + 1;
+ }
+
@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof Index // instanceof handles nulls
- && zeroBasedIndex == ((Index) other).zeroBasedIndex); // state check
+ && zeroBasedIndex == ((Index) other).zeroBasedIndex); // state check
}
+
}
diff --git a/src/main/java/seedu/address/commons/core/index/ReverseIndexComparator.java b/src/main/java/seedu/address/commons/core/index/ReverseIndexComparator.java
new file mode 100644
index 00000000000..7e20d43f212
--- /dev/null
+++ b/src/main/java/seedu/address/commons/core/index/ReverseIndexComparator.java
@@ -0,0 +1,21 @@
+package seedu.address.commons.core.index;
+
+import java.util.Comparator;
+
+/**
+ * Represents a comparator to compare index number to give a reverse order from
+ * high to low.
+ */
+public class ReverseIndexComparator implements Comparator {
+
+ /**
+ * Compare the index number.
+ *
+ * @param firstIndex the first index to be compared.
+ * @param secondIndex the second index to be compared.
+ */
+ public int compare(Index firstIndex, Index secondIndex) {
+ return -1 * Integer.compare(firstIndex.getZeroBased(), secondIndex.getZeroBased());
+ }
+
+}
diff --git a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java b/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java
index 19124db485c..94adaff5f50 100644
--- a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java
+++ b/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java
@@ -5,15 +5,17 @@
*/
public class IllegalValueException extends Exception {
/**
- * @param message should contain relevant information on the failed constraint(s)
+ * @param message should contain relevant information on the failed
+ * constraint(s)
*/
public IllegalValueException(String message) {
super(message);
}
/**
- * @param message should contain relevant information on the failed constraint(s)
- * @param cause of the main exception
+ * @param message should contain relevant information on the failed
+ * constraint(s)
+ * @param cause of the main exception
*/
public IllegalValueException(String message, Throwable cause) {
super(message, cause);
diff --git a/src/main/java/seedu/address/commons/util/AppUtil.java b/src/main/java/seedu/address/commons/util/AppUtil.java
index 87aa89c0326..0b50a7421e4 100644
--- a/src/main/java/seedu/address/commons/util/AppUtil.java
+++ b/src/main/java/seedu/address/commons/util/AppUtil.java
@@ -19,7 +19,8 @@ public static Image getImage(String imagePath) {
}
/**
- * Checks that {@code condition} is true. Used for validating arguments to methods.
+ * Checks that {@code condition} is true. Used for validating arguments to
+ * methods.
*
* @throws IllegalArgumentException if {@code condition} is false.
*/
@@ -30,9 +31,11 @@ public static void checkArgument(Boolean condition) {
}
/**
- * Checks that {@code condition} is true. Used for validating arguments to methods.
+ * Checks that {@code condition} is true. Used for validating arguments to
+ * methods.
*
- * @throws IllegalArgumentException with {@code errorMessage} if {@code condition} is false.
+ * @throws IllegalArgumentException with {@code errorMessage} if
+ * {@code condition} is false.
*/
public static void checkArgument(Boolean condition, String errorMessage) {
if (!condition) {
diff --git a/src/main/java/seedu/address/commons/util/CollectionUtil.java b/src/main/java/seedu/address/commons/util/CollectionUtil.java
index eafe4dfd681..35c4f36b37c 100644
--- a/src/main/java/seedu/address/commons/util/CollectionUtil.java
+++ b/src/main/java/seedu/address/commons/util/CollectionUtil.java
@@ -12,14 +12,17 @@
*/
public class CollectionUtil {
- /** @see #requireAllNonNull(Collection) */
+ /**
+ * @see #requireAllNonNull(Collection)
+ */
public static void requireAllNonNull(Object... items) {
requireNonNull(items);
Stream.of(items).forEach(Objects::requireNonNull);
}
/**
- * Throws NullPointerException if {@code items} or any element of {@code items} is null.
+ * Throws NullPointerException if {@code items} or any element of {@code items}
+ * is null.
*/
public static void requireAllNonNull(Collection> items) {
requireNonNull(items);
diff --git a/src/main/java/seedu/address/commons/util/FileUtil.java b/src/main/java/seedu/address/commons/util/FileUtil.java
index b1e2767cdd9..4de0598ac07 100644
--- a/src/main/java/seedu/address/commons/util/FileUtil.java
+++ b/src/main/java/seedu/address/commons/util/FileUtil.java
@@ -18,8 +18,10 @@ 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)},
* otherwise returns false.
+ *
* @param path A string representing the file path. Cannot be null.
*/
public static boolean isValidPath(String path) {
@@ -32,7 +34,9 @@ public static boolean isValidPath(String path) {
}
/**
- * Creates a file if it does not exist along with its missing parent directories.
+ * Creates a file if it does not exist along with its missing parent
+ * directories.
+ *
* @throws IOException if the file or directory cannot be created.
*/
public static void createIfMissing(Path file) throws IOException {
@@ -42,7 +46,8 @@ public static void createIfMissing(Path file) throws IOException {
}
/**
- * Creates a file if it does not exist along with its missing parent directories.
+ * Creates a file if it does not exist along with its missing parent
+ * directories.
*/
public static void createFile(Path file) throws IOException {
if (Files.exists(file)) {
diff --git a/src/main/java/seedu/address/commons/util/JsonUtil.java b/src/main/java/seedu/address/commons/util/JsonUtil.java
index 8ef609f055d..d2eb9db0d38 100644
--- a/src/main/java/seedu/address/commons/util/JsonUtil.java
+++ b/src/main/java/seedu/address/commons/util/JsonUtil.java
@@ -30,7 +30,7 @@ public class JsonUtil {
private static final Logger logger = LogsCenter.getLogger(JsonUtil.class);
- private static ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules()
+ private static final ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules()
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE)
@@ -49,10 +49,14 @@ static T deserializeObjectFromJsonFile(Path jsonFile, Class classOfObject
}
/**
- * Returns the Json object from the given file or {@code Optional.empty()} object if the file is not found.
- * If any values are missing from the file, default values will be used, as long as the file is a valid json file.
- * @param filePath cannot be null.
- * @param classOfObjectToDeserialize Json file has to correspond to the structure in the class given here.
+ * Returns the Json object from the given file or {@code Optional.empty()}
+ * object if the file is not found.
+ * If any values are missing from the file, default values will be used, as long
+ * as the file is a valid json file.
+ *
+ * @param filePath cannot be null.
+ * @param classOfObjectToDeserialize Json file has to correspond to the
+ * structure in the class given here.
* @throws DataConversionException if the file format is not as expected.
*/
public static Optional readJsonFile(
@@ -79,6 +83,7 @@ public static Optional readJsonFile(
/**
* Saves the Json object to the specified file.
* Overwrites existing file if it exists, creates a new file if it doesn't.
+ *
* @param jsonFile cannot be null
* @param filePath cannot be null
* @throws IOException if there was an error during writing to the file
@@ -90,9 +95,9 @@ public static void saveJsonFile(T jsonFile, Path filePath) throws IOExceptio
serializeObjectToJsonFile(filePath, jsonFile);
}
-
/**
* Converts a given string representation of a JSON data to instance of a class
+ *
* @param The generic type to create an instance of
* @return The instance of T with the specified values in the JSON string
*/
@@ -102,8 +107,9 @@ public static T fromJsonString(String json, Class instanceClass) throws I
/**
* Converts a given instance of a class into its JSON data string representation
+ *
* @param instance The T object to be converted into the JSON string
- * @param The generic type to create an instance of
+ * @param The generic type to create an instance of
* @return JSON data representation of the given class instance, in string
*/
public static String toJsonString(T instance) throws JsonProcessingException {
@@ -128,7 +134,6 @@ protected Level _deserialize(String value, DeserializationContext ctxt) {
* Gets the logging level that matches loggingLevelString
*
* Returns null if there are no matches
- *
*/
private Level getLoggingLevel(String loggingLevelString) {
return Level.parse(loggingLevelString);
diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/seedu/address/commons/util/StringUtil.java
index 61cc8c9a1cb..cb555f1a94d 100644
--- a/src/main/java/seedu/address/commons/util/StringUtil.java
+++ b/src/main/java/seedu/address/commons/util/StringUtil.java
@@ -2,6 +2,7 @@
import static java.util.Objects.requireNonNull;
import static seedu.address.commons.util.AppUtil.checkArgument;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -14,25 +15,27 @@ public class StringUtil {
/**
* Returns true if the {@code sentence} contains the {@code word}.
- * Ignores case, but a full word match is required.
- *
examples:
+ * Ignores case, but a full word match is required.
+ *
+ * examples:
+ *
+ *
* containsWordIgnoreCase("ABc def", "abc") == true
* containsWordIgnoreCase("ABc def", "DEF") == true
* containsWordIgnoreCase("ABc def", "AB") == false //not a full word match
- *
+ *
+ *
* @param sentence cannot be null
- * @param word cannot be null, cannot be empty, must be a single word
+ * @param word cannot be null, cannot be empty, must be a single word
*/
public static boolean containsWordIgnoreCase(String sentence, String word) {
- requireNonNull(sentence);
- requireNonNull(word);
+ requireAllNonNull(sentence, word);
String preppedWord = word.trim();
checkArgument(!preppedWord.isEmpty(), "Word parameter cannot be empty");
checkArgument(preppedWord.split("\\s+").length == 1, "Word parameter should be a single word");
- String preppedSentence = sentence;
- String[] wordsInPreppedSentence = preppedSentence.split("\\s+");
+ String[] wordsInPreppedSentence = sentence.split("\\s+");
return Arrays.stream(wordsInPreppedSentence)
.anyMatch(preppedWord::equalsIgnoreCase);
@@ -45,14 +48,16 @@ public static String getDetails(Throwable t) {
requireNonNull(t);
StringWriter sw = new StringWriter();
t.printStackTrace(new PrintWriter(sw));
- return t.getMessage() + "\n" + sw.toString();
+ return t.getMessage() + "\n" + sw;
}
/**
* Returns true if {@code s} represents a non-zero unsigned integer
* e.g. 1, 2, 3, ..., {@code Integer.MAX_VALUE}
* Will return false for any other non-null string input
- * e.g. empty string, "-1", "0", "+1", and " 2 " (untrimmed), "3 0" (contains whitespace), "1 a" (contains letters)
+ * e.g. empty string, "-1", "0", "+1", and " 2 " (untrimmed), "3 0" (contains
+ * whitespace), "1 a" (contains letters)
+ *
* @throws NullPointerException if {@code s} is null.
*/
public static boolean isNonZeroUnsignedInteger(String s) {
diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/address/logic/Logic.java
index 92cd8fa605a..ec60af76e34 100644
--- a/src/main/java/seedu/address/logic/Logic.java
+++ b/src/main/java/seedu/address/logic/Logic.java
@@ -16,10 +16,11 @@
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.
- * @throws ParseException If an error occurs during parsing.
+ * @throws ParseException If an error occurs during parsing.
*/
CommandResult execute(String commandText) throws CommandException, ParseException;
@@ -30,7 +31,9 @@ public interface Logic {
*/
ReadOnlyAddressBook getAddressBook();
- /** Returns an unmodifiable view of the filtered list of persons */
+ /**
+ * Returns an unmodifiable view of the filtered list of persons
+ */
ObservableList getFilteredPersonList();
/**
diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java
index 9d9c6d15bdc..e35d08bf830 100644
--- a/src/main/java/seedu/address/logic/LogicManager.java
+++ b/src/main/java/seedu/address/logic/LogicManager.java
@@ -10,7 +10,7 @@
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.HealthcareXpressParser;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.Model;
import seedu.address.model.ReadOnlyAddressBook;
@@ -26,15 +26,16 @@ public class LogicManager implements Logic {
private final Model model;
private final Storage storage;
- private final AddressBookParser addressBookParser;
+ private final HealthcareXpressParser healthcareXpressParser;
/**
- * Constructs a {@code LogicManager} with the given {@code Model} and {@code Storage}.
+ * Constructs a {@code LogicManager} with the given {@code Model} and
+ * {@code Storage}.
*/
public LogicManager(Model model, Storage storage) {
this.model = model;
this.storage = storage;
- addressBookParser = new AddressBookParser();
+ healthcareXpressParser = new HealthcareXpressParser();
}
@Override
@@ -42,7 +43,7 @@ public CommandResult execute(String commandText) throws CommandException, ParseE
logger.info("----------------[USER COMMAND][" + commandText + "]");
CommandResult commandResult;
- Command command = addressBookParser.parseCommand(commandText);
+ Command command = healthcareXpressParser.parseCommand(commandText, model);
commandResult = command.execute(model);
try {
diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java
index 71656d7c5c8..ac0e51cfab8 100644
--- a/src/main/java/seedu/address/logic/commands/AddCommand.java
+++ b/src/main/java/seedu/address/logic/commands/AddCommand.java
@@ -2,10 +2,14 @@
import static java.util.Objects.requireNonNull;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_CATEGORY;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE_AND_SLOT;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_GENDER;
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.logic.parser.CliSyntax.PREFIX_UNAVAILABLE_DATE;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
@@ -18,24 +22,39 @@ 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. "
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a patient/nurse to the address book. "
+ "Parameters: "
+ + PREFIX_CATEGORY + "CATEGORY "
+ PREFIX_NAME + "NAME "
+ + PREFIX_GENDER + "GENDER "
+ PREFIX_PHONE + "PHONE "
+ PREFIX_EMAIL + "EMAIL "
+ PREFIX_ADDRESS + "ADDRESS "
- + "[" + PREFIX_TAG + "TAG]...\n"
+ + "[" + PREFIX_TAG + "TAG]... \n"
+ + "If add patient, you can choose to add details: "
+ + PREFIX_DATE_AND_SLOT + "HOME_VISIT_DATE_AND_SLOT \n"
+ + "If add nurse, you can choose to add details: "
+ + PREFIX_UNAVAILABLE_DATE + "UNAVAILABLE_DATE_TO_HOME_VISIT \n"
+ "Example: " + COMMAND_WORD + " "
+ + PREFIX_CATEGORY + "P "
+ PREFIX_NAME + "John Doe "
+ + PREFIX_GENDER + "M "
+ PREFIX_PHONE + "98765432 "
+ PREFIX_EMAIL + "johnd@example.com "
+ PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 "
+ PREFIX_TAG + "friends "
- + PREFIX_TAG + "owesMoney";
+ + PREFIX_TAG + "owesMoney "
+ + PREFIX_DATE_AND_SLOT + "2022-11-11,2";
- 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";
+ public static final String MESSAGE_INVALID_FIELD_NURSE = "The person to be added is a nurse, "
+ + "should not have date and slot.";
+ public static final String MESSAGE_INVALID_FIELD_PATIENT = "The person to be added is a patient, "
+ + "should not have unavailable date.";
+ public static final String MESSAGE_SUCCESS = "New %1$s added: %2$s";
+ public static final String MESSAGE_DUPLICATE_PERSON = "This %1$s already exists in the address book";
+ public static final String MESSAGE_SIMILAR_PERSON = "This %1$s is similar someone we found"
+ + " in the address book: %2$s. We have added them anyways.";
private final Person toAdd;
/**
@@ -51,17 +70,23 @@ public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
if (model.hasPerson(toAdd)) {
- throw new CommandException(MESSAGE_DUPLICATE_PERSON);
+ throw new CommandException(String.format(MESSAGE_DUPLICATE_PERSON, toAdd.getCategoryIndicator()));
}
+ if (model.findSimilarPerson(toAdd).isPresent()) {
+ model.addPerson(toAdd);
+ return new CommandResult(String.format(MESSAGE_SIMILAR_PERSON, toAdd.getCategoryIndicator(),
+ model.findSimilarPerson(toAdd).get()));
+ }
model.addPerson(toAdd);
- return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
+ return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd.getCategoryIndicator(), 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));
+ && toAdd.equals(((AddCommand) other).toAdd));
}
+
}
diff --git a/src/main/java/seedu/address/logic/commands/AssignCommand.java b/src/main/java/seedu/address/logic/commands/AssignCommand.java
new file mode 100644
index 00000000000..69c57a05794
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/AssignCommand.java
@@ -0,0 +1,146 @@
+package seedu.address.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE_AND_SLOT_INDEX;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_UID;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+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.Date;
+import seedu.address.model.person.DateSlot;
+import seedu.address.model.person.HomeVisit;
+import seedu.address.model.person.Nurse;
+import seedu.address.model.person.Patient;
+import seedu.address.model.person.Person;
+import seedu.address.model.person.Uid;
+
+/**
+ * Assigns a patient's home-visit dateslot to nurse.
+ */
+public class AssignCommand extends Command {
+
+ public static final String COMMAND_WORD = "assign";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Assign a patient's home visit dateslot to a nurse"
+ + "by using the unique id number of the patient, nurse and the dateslot index.\n"
+ + "Parameters: " + PREFIX_UID + "UID of a nurse (must be a positive integer) "
+ + PREFIX_UID + "UID of a patient (must be a positive integer)"
+ + " [" + PREFIX_DATE_AND_SLOT_INDEX + "DATE_AND_SLOT_INDEX] \n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_UID + "1 "
+ + PREFIX_UID + "2 "
+ + PREFIX_DATE_AND_SLOT_INDEX + "1 ";
+
+ public static final String MESSAGE_SUCCESS = "%1$s's dateslot/dateslots assigned to %2$s.";
+
+ public static final String MESSAGE_BOTH_NURSE = "The given uids are both nurses.";
+ public static final String MESSAGE_BOTH_PATIENT = "The given uids are both patients.";
+
+ private final Uid uid1;
+ private final Uid uid2;
+ private final List dateslotIndex;
+
+ /**
+ * Creates an AssignCommand to assgin specific patient's date slot to a nurse.
+ */
+ public AssignCommand(Uid uid1, Uid uid2, List dateslotIndex) {
+ requireAllNonNull(uid1, uid2, dateslotIndex);
+ this.uid1 = uid1;
+ this.uid2 = uid2;
+ this.dateslotIndex = new ArrayList<>();
+ this.dateslotIndex.addAll(dateslotIndex);
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ List lastShownList = model.getFilteredPersonList();
+ Optional person1 = lastShownList.stream().filter(p -> p.getUid().equals(uid1)).findFirst();
+ Optional person2 = lastShownList.stream().filter(p -> p.getUid().equals(uid2)).findFirst();
+
+ if (person1.isEmpty() || person2.isEmpty()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_UID);
+ }
+
+ Person firstPerson = person1.get();
+ Person secondPerson = person2.get();
+ Patient patient = getPatient(firstPerson, secondPerson);
+ Nurse nurse = getNurse(firstPerson, secondPerson);
+ markAssign(model, patient, nurse);
+
+ return new CommandResult(String.format(MESSAGE_SUCCESS, patient.toLiteString(), nurse.toLiteString()));
+ }
+
+ private Patient getPatient(Person person1, Person person2) throws CommandException {
+ Boolean isPerson1Patient = person1.isPatient();
+ Boolean isPerson2Patient = person2.isPatient();
+
+ if (isPerson1Patient && isPerson2Patient) {
+ throw new CommandException(MESSAGE_BOTH_PATIENT);
+ }
+ if (isPerson1Patient || isPerson2Patient) {
+ return isPerson1Patient
+ ? (Patient) person1
+ : (Patient) person2;
+ }
+ throw new CommandException(MESSAGE_BOTH_NURSE);
+ }
+
+ private Nurse getNurse(Person person1, Person person2) throws CommandException {
+ Boolean isPerson1Nurse = person1.isNurse();
+ Boolean isPerson2Nurse = person2.isNurse();
+
+ if (isPerson1Nurse && isPerson2Nurse) {
+ throw new CommandException(MESSAGE_BOTH_NURSE);
+ }
+ if (isPerson1Nurse || isPerson2Nurse) {
+ return isPerson1Nurse
+ ? (Nurse) person1
+ : (Nurse) person2;
+ }
+ throw new CommandException(MESSAGE_BOTH_PATIENT);
+ }
+
+ private void markAssign(Model model, Patient patient, Nurse nurse) throws CommandException {
+ Long patientUidNo = patient.getUid().getUid();
+ Long nurseUidNo = nurse.getUid().getUid();
+ List patientDateSlotList = patient.getDatesSlots();
+ List nurseHomeVisitList = nurse.getHomeVisits();
+ List nurseFullyScheduledList = nurse.getFullyScheduledDates();
+ List nurseUnavailableDates = nurse.getUnavailableDates();
+
+ DateSlotManager marker = new DateSlotManager(patientDateSlotList, this.dateslotIndex);
+ List updatedDateSlotList = marker.markAssigned(nurseHomeVisitList, nurseUnavailableDates, nurseUidNo);
+ HomeVisitManager creator = new HomeVisitManager(nurseHomeVisitList, nurseFullyScheduledList);
+ List updatedHomeVisitList = creator.createHomeVisitList(patientDateSlotList,
+ this.dateslotIndex, patientUidNo);
+ List updatedFullyScheduledList = creator.getFullyScheduledDateList();
+
+ InternalEditor editor = new InternalEditor(model);
+ editor.editPatient(patient, updatedDateSlotList);
+ editor.editNurse(nurse, updatedHomeVisitList, updatedFullyScheduledList);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof AssignCommand) {
+ AssignCommand o = (AssignCommand) other;
+ System.out.println(uid1.equals(o.uid1));
+ System.out.println(uid2.equals(o.uid2));
+ System.out.println(dateslotIndex.equals(o.dateslotIndex));
+ }
+ return other == this // short circuit if same object
+ || (other instanceof AssignCommand // instanceof handles nulls
+ && uid1.equals(((AssignCommand) other).uid1)
+ && uid2.equals(((AssignCommand) other).uid2)
+ && dateslotIndex.equals(((AssignCommand) other).dateslotIndex));
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/commands/CheckSimilarCommand.java b/src/main/java/seedu/address/logic/commands/CheckSimilarCommand.java
new file mode 100644
index 00000000000..f2efd100685
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/CheckSimilarCommand.java
@@ -0,0 +1,43 @@
+package seedu.address.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.Optional;
+
+import javafx.collections.ObservableList;
+import seedu.address.commons.core.Messages;
+import seedu.address.model.Model;
+import seedu.address.model.person.Person;
+
+/**
+ * Finds and lists all persons in address book whose are similar.
+ */
+public class CheckSimilarCommand extends Command {
+
+ public static final String COMMAND_WORD = "checkSimilar";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Returns persons that maybe similar";
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ ObservableList personList = model.getFilteredPersonList();
+ for (int i = 0; i < personList.size(); i++) {
+ Person curr = personList.get(i);
+ Optional similarPerson = personList.stream()
+ .filter(x -> x.isSimilarPerson(curr) && !x.isSamePerson(curr)).findAny();
+ if (similarPerson.isPresent()) {
+ model.updateFilteredPersonList(x -> x.isSamePerson(curr) || x.isSamePerson(similarPerson.get()));
+ return new CommandResult(
+ String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size()));
+ }
+ }
+ return new CommandResult(
+ String.format("No similar people found!"));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this;
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java
index 9c86b1fa6e4..a1fc50a6a1b 100644
--- a/src/main/java/seedu/address/logic/commands/ClearCommand.java
+++ b/src/main/java/seedu/address/logic/commands/ClearCommand.java
@@ -11,8 +11,7 @@
public class ClearCommand extends Command {
public static final String COMMAND_WORD = "clear";
- public static final String MESSAGE_SUCCESS = "Address book has been cleared!";
-
+ public static final String MESSAGE_SUCCESS = "Healthcare Xpress record system has been cleared!";
@Override
public CommandResult execute(Model model) {
diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/seedu/address/logic/commands/Command.java
index 64f18992160..f1b391becf6 100644
--- a/src/main/java/seedu/address/logic/commands/Command.java
+++ b/src/main/java/seedu/address/logic/commands/Command.java
@@ -4,7 +4,8 @@
import seedu.address.model.Model;
/**
- * Represents a command with hidden internal logic and the ability to be executed.
+ * Represents a command with hidden internal logic and the ability to be
+ * executed.
*/
public abstract class Command {
diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/seedu/address/logic/commands/CommandResult.java
index 92f900b7916..4f06a6069db 100644
--- a/src/main/java/seedu/address/logic/commands/CommandResult.java
+++ b/src/main/java/seedu/address/logic/commands/CommandResult.java
@@ -11,10 +11,14 @@ public class CommandResult {
private final String feedbackToUser;
- /** Help information should be shown to the user. */
+ /**
+ * Help information should be shown to the user.
+ */
private final boolean showHelp;
- /** The application should exit. */
+ /**
+ * The application should exit.
+ */
private final boolean exit;
/**
diff --git a/src/main/java/seedu/address/logic/commands/DateSlotChecker.java b/src/main/java/seedu/address/logic/commands/DateSlotChecker.java
new file mode 100644
index 00000000000..fca5f047cda
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/DateSlotChecker.java
@@ -0,0 +1,131 @@
+package seedu.address.logic.commands;
+
+import java.util.List;
+import java.util.Optional;
+
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.person.Date;
+import seedu.address.model.person.DateSlot;
+import seedu.address.model.person.HomeVisit;
+
+/**
+ * To check date slot related stuff.
+ */
+public class DateSlotChecker {
+
+ public static final String MESSAGE_VISITED_DATESLOT = "The date slot %1$s has already passed.";
+ public static final String MESSAGE_ASSIGNED_DATESLOT = "The date slot %1$s has been assigned already.";
+ public static final String MESSAGE_TIME_CRASHES = "There is already an existing homevisit in this dateslot %1$s."
+ + "Please assign another nurse";
+ public static final String MESSAGE_UNAVAILABLE_DATE = "The nurse is unavailable on this day %1$s. "
+ + "Please assign another nurse";
+ public static final String MESSAGE_NOT_ASSIGNED_DATESLOT = "The dateslot %1$s has not been assigned.";
+ public static final String MESSAGE_NOT_VISITED_DATESLOT = "The visit dates has not reached."
+ + "Cannot unmark it as fail to visit .";
+ public static final String MESSAGE_NOT_VISITED_DATESLOT_TWO = "The visit dates has not reached."
+ + "Cannot undo unmark it as success visit.";
+ public static final String MESSAGE_SUCCESS_VISIT_DATESLOT = "This dates has already been marked as "
+ + "success visited. " + "Cannot undo unmark it as success visit.";
+
+ private final DateSlot dateSlot;
+
+ /**
+ * Create DateSlotChecker.
+ * @param dateSlot
+ */
+ public DateSlotChecker(DateSlot dateSlot) {
+ this.dateSlot = dateSlot;
+ }
+
+ /**
+ * Check whether the date slot has been visited.
+ * @throws CommandException if visited
+ */
+ public void checkVisited() throws CommandException {
+ if (dateSlot.getHasVisited()) {
+ throw new CommandException(String.format(MESSAGE_VISITED_DATESLOT,
+ dateSlot.getDateSlotFormatted()));
+ }
+ }
+
+ /**
+ * Check whether the date slot has not been visited.
+ * @throws CommandException if not visited
+ */
+ public void checkNotVisited() throws CommandException {
+ if (!dateSlot.getHasVisited()) {
+ throw new CommandException(MESSAGE_NOT_VISITED_DATESLOT);
+ }
+ }
+
+ /**
+ * Check whether the date slot has not been visited.
+ * @throws CommandException if not visited
+ */
+ public void checkNotVisitedForUndoUnmark() throws CommandException {
+ if (!dateSlot.getHasVisited()) {
+ throw new CommandException(MESSAGE_NOT_VISITED_DATESLOT_TWO);
+ }
+ }
+
+ /**
+ * Check whether the date slot is a success visit
+ * @throws CommandException if it is a success visit
+ */
+ public void checkSuccessVisited() throws CommandException {
+ if (dateSlot.getIsSuccessVisit()) {
+ throw new CommandException(MESSAGE_SUCCESS_VISIT_DATESLOT);
+ }
+ }
+
+ /**
+ * Check whether the date slot has not been assigned
+ * @throws CommandException if date slot not assigned
+ */
+ public void checkNotAssigned() throws CommandException {
+ if (!dateSlot.getHasAssigned()) {
+ throw new CommandException(String.format(MESSAGE_NOT_ASSIGNED_DATESLOT,
+ dateSlot.getDateSlotFormatted()));
+ }
+ }
+
+ /**
+ * Check whether the date slot has been assigned
+ * @throws CommandException if date slot is assigned
+ */
+ public void checkAssigned() throws CommandException {
+ if (dateSlot.getHasAssigned()) {
+ throw new CommandException(String.format(MESSAGE_ASSIGNED_DATESLOT, dateSlot.getDateSlotFormatted()));
+ }
+ }
+
+ /**
+ * Check whether the date slot has time clash with the homeVisitList.
+ * @param homeVisitList
+ * @throws CommandException if there is time clash
+ */
+ public void checkCrashes(List homeVisitList) throws CommandException {
+ Optional homeVisit = homeVisitList.stream().filter(
+ h -> h.getDateSlot().getDateTime().equals(dateSlot.getDateTime())).findFirst();
+ if (!homeVisit.isEmpty()) {
+ throw new CommandException(String.format(MESSAGE_TIME_CRASHES, dateSlot.getDateSlotFormatted()));
+ }
+ }
+
+ /**
+ * Check whether the date slot has time clash with the unavailabilityDateList.
+ * @param unavailabilityDateList
+ * @throws CommandException if there is time clash
+ */
+ public void checkUnavailability(List unavailabilityDateList) throws CommandException {
+ Optional date = unavailabilityDateList.stream().filter(
+ d -> d.getDate().equals(dateSlot.getDate())).findFirst();
+ if (!date.isEmpty()) {
+ throw new CommandException(String.format(MESSAGE_UNAVAILABLE_DATE, dateSlot.getDateSlotFormatted()));
+ }
+ }
+
+
+}
+
+
diff --git a/src/main/java/seedu/address/logic/commands/DateSlotManager.java b/src/main/java/seedu/address/logic/commands/DateSlotManager.java
new file mode 100644
index 00000000000..0d8245f9075
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/DateSlotManager.java
@@ -0,0 +1,255 @@
+package seedu.address.logic.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.commons.core.index.ReverseIndexComparator;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.person.Date;
+import seedu.address.model.person.DateSlot;
+import seedu.address.model.person.HomeVisit;
+
+/**
+ * A class that manage all date slot related task.
+ */
+public class DateSlotManager {
+
+ public static final String MESSAGE_OUTOFBOUND_DATESLOT_INDEX = "The date slot index given is out of bounds.";
+ public final List dateSlotList;
+ public final List dateSlotIndexList;
+
+ /**
+ * Construct a DateSlotManager.
+ * @param dateSlotList
+ * @param dateSlotIndex
+ */
+ public DateSlotManager(List dateSlotList, List dateSlotIndex) {
+ this.dateSlotList = new ArrayList<>();
+ for (DateSlot dateSlot : dateSlotList) {
+ this.dateSlotList.add(dateSlot.clone());
+ }
+ this.dateSlotIndexList = new ArrayList<>(dateSlotIndex);
+ }
+
+ /**
+ * Construct a DateSlotManger with empty date slot index list.
+ * @param dateSlotList
+ */
+ public DateSlotManager(List dateSlotList) {
+ this.dateSlotList = new ArrayList<>();
+ for (DateSlot dateSlot : dateSlotList) {
+ this.dateSlotList.add(dateSlot.clone());
+ }
+ this.dateSlotIndexList = new ArrayList<>();
+ }
+
+ /**
+ * Construct a DateSlotManger with only one index.
+ * @param dateSlotList
+ * @param index
+ */
+ public DateSlotManager(List dateSlotList, Index index) {
+ this.dateSlotList = new ArrayList<>();
+ for (DateSlot dateSlot : dateSlotList) {
+ this.dateSlotList.add(dateSlot.clone());
+ }
+ this.dateSlotIndexList = new ArrayList<>();
+ this.dateSlotIndexList.add(index);
+ }
+
+ /**
+ * Mark the respective date slot as assigned if there is no time clashes
+ * @param homeVisitList
+ * @param unavailableDateList
+ * @param nurseUidNo
+ * @return updated dateSlot list
+ * @throws CommandException
+ */
+ public List markAssigned(List homeVisitList, List unavailableDateList,
+ Long nurseUidNo) throws CommandException {
+ if (dateSlotIndexList.isEmpty()) {
+ markAllAssigned(homeVisitList, unavailableDateList, nurseUidNo);
+ } else {
+ markSpecificAssigned(homeVisitList, unavailableDateList, nurseUidNo);
+ }
+ return dateSlotList;
+ }
+
+ private void markAllAssigned(List homeVisitList, List unavailableDateList,
+ Long nurseUidNo) throws CommandException {
+ for (DateSlot dateSlot : dateSlotList) {
+ markAssignedCheck(dateSlot, homeVisitList, unavailableDateList);
+ dateSlot.mark(nurseUidNo);
+ }
+ }
+
+ private void markSpecificAssigned(List homeVisitList, List unavailableDateList,
+ Long nurseUidNo) throws CommandException {
+ sortIndex();
+ checkIndexOutOfBound();
+ for (Index index : dateSlotIndexList) {
+ DateSlot dateSlot = dateSlotList.get(index.getZeroBased());
+ markAssignedCheck(dateSlot, homeVisitList, unavailableDateList);
+ dateSlot.mark(nurseUidNo);
+ }
+ }
+
+ private void markAssignedCheck(DateSlot dateSlot, List homeVisitList, List unavailableDateList)
+ throws CommandException {
+ DateSlotChecker checker = new DateSlotChecker(dateSlot);
+ checker.checkVisited();
+ checker.checkAssigned();
+ checker.checkCrashes(homeVisitList);
+ checker.checkUnavailability(unavailableDateList);
+ }
+
+ private void sortIndex() {
+ ReverseIndexComparator comp = new ReverseIndexComparator();
+ this.dateSlotIndexList.sort(comp);
+ }
+
+ /**
+ * Check whether the index given is out of bound.
+ */
+ public void checkIndexOutOfBound() throws CommandException {
+ if (dateSlotIndexList.get(0).getZeroBased() >= dateSlotList.size()) {
+ throw new CommandException(MESSAGE_OUTOFBOUND_DATESLOT_INDEX);
+ }
+ }
+
+ /**
+ * Unmark the respective date slot as unassigned.
+ * @return updated dateSlot list
+ * @throws CommandException
+ */
+ public List unmarkAssigned() throws CommandException {
+ if (dateSlotIndexList.isEmpty()) {
+ unmarkAllAssigned();
+ } else {
+ unmarkSpecificAssigned();
+ }
+ return dateSlotList;
+ }
+
+ private void unmarkAllAssigned() throws CommandException {
+ for (DateSlot dateSlot : dateSlotList) {
+ unmarkAssignedCheck(dateSlot);
+ dateSlot.unmark();
+ }
+ }
+
+ private void unmarkSpecificAssigned() throws CommandException {
+ sortIndex();
+ checkIndexOutOfBound();
+ for (Index index : dateSlotIndexList) {
+ DateSlot dateSlot = dateSlotList.get(index.getZeroBased());
+ unmarkAssignedCheck(dateSlot);
+ dateSlot.unmark();
+ }
+ }
+
+ /**
+ * Unmark the specific date slot that has the same dateTime with the dateSlot given.
+ * @param dateSlot
+ * @return updated dateSlot list
+ */
+ public List unmarkSpecificAssignedFromHomeVisit(DateSlot dateSlot) {
+ DateSlot dateSlotToBeUnmarked = dateSlotList.stream().filter(
+ d -> d.getDateTime().equals(dateSlot.getDateTime())).findFirst().get();
+ dateSlotToBeUnmarked.unmark();
+ return dateSlotList;
+ }
+
+ private void unmarkAssignedCheck(DateSlot dateSlot) throws CommandException {
+ DateSlotChecker checker = new DateSlotChecker(dateSlot);
+ checker.checkVisited();
+ checker.checkNotAssigned();
+ }
+
+ /**
+ * Unmark the specified dateslot as fail visited.
+ * @return updated dateSlot list
+ * @throws CommandException
+ */
+ public List unmarkSuccessVisited() throws CommandException {
+ checkIndexOutOfBound();
+ DateSlot dateToBeUnmark = dateSlotList.get(dateSlotIndexList.get(0).getZeroBased());
+ unmarkSuccessVisitedCheck(dateToBeUnmark);
+ dateToBeUnmark.markFail();
+ return dateSlotList;
+ }
+
+ private void unmarkSuccessVisitedCheck(DateSlot dateSlot) throws CommandException {
+ DateSlotChecker checker = new DateSlotChecker(dateSlot);
+ checker.checkNotVisited();
+ }
+
+ /**
+ * Undo the unmark of specified date slot as success visit.
+ * @return updated dateSlot list
+ * @throws CommandException
+ */
+ public List undoUnmarkFailVisited() throws CommandException {
+ checkIndexOutOfBound();
+ DateSlot dateToBeUndoUnmark = dateSlotList.get(dateSlotIndexList.get(0).getZeroBased());
+ undoUnmarkFailVisitedCheck(dateToBeUndoUnmark);
+ dateToBeUndoUnmark.markSuccess();
+ return dateSlotList;
+ }
+
+ private void undoUnmarkFailVisitedCheck(DateSlot dateSlot) throws CommandException {
+ DateSlotChecker checker = new DateSlotChecker(dateSlot);
+ checker.checkNotVisitedForUndoUnmark();
+ checker.checkSuccessVisited();
+ }
+
+ /**
+ * Remove the respective date slot from the date slot list.
+ * @return updated dateSlot list
+ * @throws CommandException
+ */
+ public List removeDateSlot() throws CommandException {
+ if (dateSlotIndexList.isEmpty()) {
+ removeAllDateSlot();
+ } else {
+ removeSpecificDateSlot();
+ }
+ return dateSlotList;
+ }
+
+ private void removeAllDateSlot() {
+ dateSlotList.clear();
+ }
+
+ private void removeSpecificDateSlot() throws CommandException {
+ sortIndex();
+ checkIndexOutOfBound();
+ for (Index index : dateSlotIndexList) {
+ DateSlot dateSlot = dateSlotList.get(index.getZeroBased());
+ dateSlotList.remove(dateSlot);
+ }
+ }
+
+ /**
+ * Add the dateSlotToBeAdded given by user to the existing date slot list.
+ * @param dateSlotToBeAdded
+ * @return updated dateSlot list
+ */
+ public List addDateSlot(List dateSlotToBeAdded) {
+ dateSlotList.addAll(dateSlotToBeAdded);
+ return dateSlotList;
+ }
+
+ /**
+ * Get the date slot list.
+ */
+ public List getDateSlot() {
+ return this.dateSlotList;
+ }
+
+
+}
+
+
+
diff --git a/src/main/java/seedu/address/logic/commands/DeassignCommand.java b/src/main/java/seedu/address/logic/commands/DeassignCommand.java
new file mode 100644
index 00000000000..82c0c81fffe
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/DeassignCommand.java
@@ -0,0 +1,118 @@
+package seedu.address.logic.commands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE_AND_SLOT_INDEX;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_UID;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+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.category.Category;
+import seedu.address.model.person.Date;
+import seedu.address.model.person.DateSlot;
+import seedu.address.model.person.HomeVisit;
+import seedu.address.model.person.Nurse;
+import seedu.address.model.person.Patient;
+import seedu.address.model.person.Person;
+import seedu.address.model.person.Uid;
+
+/**
+ * Deassigns a home-visit slot.
+ */
+public class DeassignCommand extends Command {
+
+ public static final String COMMAND_WORD = "deassign";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Deassign home visit dateslot"
+ + "by using the unique id number of the patient or the nurse and respective index.\n"
+ + "Parameters: " + PREFIX_UID + "UID of a nurse/patient (must be a positive integer) "
+ + "If it is a patient, to indicate the specific dateslot to be deassigned: "
+ + "[" + PREFIX_DATE_AND_SLOT_INDEX + "DATE_AND_SLOT_INDEX] \n"
+ + "If it is a nurse, to indicate the specific homevisit to be deassigned: "
+ + "[" + PREFIX_DATE_AND_SLOT_INDEX + "HOME_VISIT_INDEX] \n"
+ + "Example: " + COMMAND_WORD + PREFIX_UID + " 1 "
+ + PREFIX_DATE_AND_SLOT_INDEX + "1";
+
+ public static final String MESSAGE_SUCCESS = "%1$s 's dateslot/homevisit has been deassigned.";
+
+ private final Uid uid;
+ private final List dateslotOrHomevisitIndex;
+
+ /**
+ * Creates a DeassignCommand to deassgin specific patient's date slot or
+ * specific nurse's home visit.
+ */
+ public DeassignCommand(Uid uid, List dateslotOrHomevisitIndex) {
+ requireAllNonNull(uid, dateslotOrHomevisitIndex);
+ this.uid = uid;
+ this.dateslotOrHomevisitIndex = new ArrayList<>();
+ this.dateslotOrHomevisitIndex.addAll(dateslotOrHomevisitIndex);
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ List lastShownList = model.getFilteredPersonList();
+ Optional person = lastShownList.stream().filter(p -> p.getUid().equals(uid)).findFirst();
+
+ if (person.isEmpty()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_UID);
+ }
+
+ Person personToBeDeassigned = person.get();
+ if (!(personToBeDeassigned.isNurse() || personToBeDeassigned.isPatient())) {
+ throw new IllegalArgumentException(Category.MESSAGE_CONSTRAINTS);
+ }
+ if (personToBeDeassigned.isPatient()) {
+ unmarkAssignedPatient(model, personToBeDeassigned, lastShownList);
+ } else {
+ unmarkAssignedNurse(model, personToBeDeassigned, lastShownList);
+ }
+
+ return new CommandResult(String.format(MESSAGE_SUCCESS, personToBeDeassigned.getUid().getUid()));
+ }
+
+ private void unmarkAssignedPatient(Model model, Person person, List personList) throws CommandException {
+ List patientDateSlotList = ((Patient) person).getDatesSlots();
+ DateSlotManager unmarker = new DateSlotManager(patientDateSlotList, dateslotOrHomevisitIndex);
+ List updatedDateSlotList = unmarker.unmarkAssigned();
+
+ InternalHomeVisitRemoverFromDateSlot homeVisitRemover = new InternalHomeVisitRemoverFromDateSlot(model,
+ personList, patientDateSlotList, dateslotOrHomevisitIndex);
+ homeVisitRemover.removeHomeVisitsForDateSlot();
+
+ InternalEditor editor = new InternalEditor(model);
+ editor.editPatient(person, updatedDateSlotList);
+ }
+
+ private void unmarkAssignedNurse(Model model, Person person, List personList) throws CommandException {
+ List homeVisitsList = ((Nurse) person).getHomeVisits();
+ List fullyScheduledList = ((Nurse) person).getFullyScheduledDates();
+ HomeVisitManager remover = new HomeVisitManager(homeVisitsList, dateslotOrHomevisitIndex, fullyScheduledList);
+ List updatedHomeVisitList = remover.removeHomeVisits();
+ List updatedFullyScheduledDatesList = remover.getFullyScheduledDateList();
+
+ InternalUnmarkerFromHomeVisit dateSlotUnmarker = new InternalUnmarkerFromHomeVisit(model, personList,
+ homeVisitsList, dateslotOrHomevisitIndex);
+ dateSlotUnmarker.unmarkDateSlotForHomeVisit();
+
+ InternalEditor editor = new InternalEditor(model);
+ editor.editNurse(person, updatedHomeVisitList, updatedFullyScheduledDatesList);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof DeassignCommand // instanceof handles nulls
+ && uid.equals(((DeassignCommand) other).uid)
+ && dateslotOrHomevisitIndex.equals(((DeassignCommand) other).dateslotOrHomevisitIndex));
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java
index 02fd256acba..a7b5ff2fdbc 100644
--- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java
+++ b/src/main/java/seedu/address/logic/commands/DeleteCommand.java
@@ -1,33 +1,40 @@
package seedu.address.logic.commands;
import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_UID;
import java.util.List;
+import java.util.Optional;
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.DateSlot;
+import seedu.address.model.person.HomeVisit;
+import seedu.address.model.person.Nurse;
+import seedu.address.model.person.Patient;
import seedu.address.model.person.Person;
+import seedu.address.model.person.Uid;
/**
- * Deletes a person identified using it's displayed index from the address book.
+ * Deletes a patient/nurse 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";
+ + ": Deletes the patient/nurse identified by the unique id number used in the displayed person list.\n"
+ + "Parameters: UID (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_UID + " 1";
- public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s";
+ public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted %1$s: %2$s";
- private final Index targetIndex;
+ private final Uid targetUid;
- public DeleteCommand(Index targetIndex) {
- this.targetIndex = targetIndex;
+ public DeleteCommand(Uid targetUid) {
+ this.targetUid = targetUid;
}
@Override
@@ -35,19 +42,63 @@ 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);
+ Optional personToDelete = lastShownList.stream().filter(p -> p.getUid().equals(targetUid)).findFirst();
+ if (!personToDelete.isPresent()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_UID);
}
+ Person confirmedPersonToDelete = personToDelete.get();
- Person personToDelete = lastShownList.get(targetIndex.getZeroBased());
- model.deletePerson(personToDelete);
- return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete));
+ Boolean hasBeenDeleted = false;
+ Boolean hasBeenUnmark = false;
+ if (confirmedPersonToDelete.isPatient()) {
+ hasBeenDeleted = deleteRespectiveHomeVisit(model, confirmedPersonToDelete, lastShownList);
+ } else {
+ hasBeenUnmark = unmarkRespectiveDateSlot(model, confirmedPersonToDelete, lastShownList);
+ }
+ String extraMessage = "";
+ if (hasBeenDeleted) {
+ extraMessage = "The respective home visit has also been deleted.";
+ }
+ if (hasBeenUnmark) {
+ extraMessage = "The respective date slot has also been unmarked.";
+ }
+ model.deletePerson(confirmedPersonToDelete);
+ return new CommandResult(
+ String.format("%s %s",
+ String.format(MESSAGE_DELETE_PERSON_SUCCESS,
+ confirmedPersonToDelete.getCategoryIndicator(), confirmedPersonToDelete),
+ extraMessage));
}
@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
+ && targetUid.equals(((DeleteCommand) other).targetUid)); // state check
+ }
+
+ private Boolean deleteRespectiveHomeVisit(Model model, Person person, List personList)
+ throws CommandException {
+ boolean hasDeleted = false;
+ List dateSlotList = ((Patient) person).getDatesSlots();
+ InternalHomeVisitRemoverFromDateSlot homeVisitRemover = new InternalHomeVisitRemoverFromDateSlot(model,
+ personList, dateSlotList);
+ hasDeleted = homeVisitRemover.removeHomeVisitsForDateSlot();
+ return hasDeleted;
}
+
+ private Boolean unmarkRespectiveDateSlot(Model model, Person person, List personList)
+ throws CommandException {
+ boolean hasUnmarked = false;
+ List homeVisitList = ((Nurse) person).getHomeVisits();
+ if (!homeVisitList.isEmpty()) {
+ InternalUnmarkerFromHomeVisit dateSlotUnmarker = new InternalUnmarkerFromHomeVisit(model, personList,
+ homeVisitList);
+ dateSlotUnmarker.unmarkDateSlotForHomeVisit();
+ hasUnmarked = true;
+ }
+ return hasUnmarked;
+ }
+
}
+
diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java
index 7e36114902f..2da6a30c1a7 100644
--- a/src/main/java/seedu/address/logic/commands/EditCommand.java
+++ b/src/main/java/seedu/address/logic/commands/EditCommand.java
@@ -1,13 +1,22 @@
package seedu.address.logic.commands;
import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_CATEGORY;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE_AND_SLOT;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE_AND_SLOT_INDEX;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_GENDER;
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.logic.parser.CliSyntax.PREFIX_UID;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_UNAVAILABLE_DATE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_UNAVAILABLE_DATE_INDEX;
import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -16,14 +25,25 @@
import seedu.address.commons.core.Messages;
import seedu.address.commons.core.index.Index;
+import seedu.address.commons.core.index.ReverseIndexComparator;
import seedu.address.commons.util.CollectionUtil;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
+import seedu.address.model.category.Category;
import seedu.address.model.person.Address;
+import seedu.address.model.person.Date;
+import seedu.address.model.person.DateSlot;
import seedu.address.model.person.Email;
+import seedu.address.model.person.Gender;
+import seedu.address.model.person.HomeVisit;
import seedu.address.model.person.Name;
+import seedu.address.model.person.NextOfKin;
+import seedu.address.model.person.Nurse;
+import seedu.address.model.person.Patient;
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
+import seedu.address.model.person.Physician;
+import seedu.address.model.person.Uid;
import seedu.address.model.tag.Tag;
/**
@@ -33,35 +53,75 @@ 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. "
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the patient/nurse identified "
+ + "by the unique id number used in the displayed person list."
+ "Existing values will be overwritten by the input values.\n"
- + "Parameters: INDEX (must be a positive integer) "
+ + "Parameters: UID (must be a positive integer) "
+ + "[" + PREFIX_CATEGORY + "CATEGORY] "
+ "[" + PREFIX_NAME + "NAME] "
+ + "[" + PREFIX_GENDER + "GENDER] "
+ "[" + PREFIX_PHONE + "PHONE] "
+ "[" + PREFIX_EMAIL + "EMAIL] "
+ "[" + PREFIX_ADDRESS + "ADDRESS] "
+ "[" + PREFIX_TAG + "TAG]...\n"
- + "Example: " + COMMAND_WORD + " 1 "
+ + "Date and Slot are only applicable to patient and Date and Slot Index is used to indicate"
+ + "the specific date and slot to be edited. \n"
+ + "[" + PREFIX_DATE_AND_SLOT + "DATE_AND_SLOT] \n"
+ + "[" + PREFIX_DATE_AND_SLOT_INDEX + "DATE_AND_SLOT_INDEX] \n"
+ + "Unavailable Date are only applicable to nurse and Unavailable Date Index is used to indicate"
+ + " the specific unavailable date to be edited. \n"
+ + "[" + PREFIX_UNAVAILABLE_DATE + "UNAVAILABLE_DATE] \n"
+ + "[" + PREFIX_UNAVAILABLE_DATE_INDEX + "UNAVAILABLE_DATE_INDEX] \n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_UID + " 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_EDIT_PERSON_SUCCESS = "Edited %1$s: %2$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.";
+ public static final String MESSAGE_DUPLICATE_PERSON = "This %1$s already exists in the address book.";
+ public static final String MESSAGE_NURSE_INVALID_DATESLOT_EDIT = "This uid gives a nurse "
+ + "and there are no dates and slot (and their indexes) for nurse. "
+ + "Please remove the date and slot field and its index field.";
+
+ public static final String MESSAGE_PATIENT_INVALID_UNAVAILABLE_DATE_EDIT = "This uid gives a patient "
+ + "and there are no unavailable dates (and their indexes) for patient. "
+ + "Please remove the unavailable dates field and its index field.";
+
+ /*
+ * public static final String
+ * MESSAGE_INVALID_NUMBERS_OF_DATESLOT_AND_DATESLOTINDEX = "The dateSlot index "
+ * + "provided is more than the dateSlot provided." +
+ * "Please remove the dateSlot index or add more dateSlot.";
+ *
+ * public static final String MESSAGE_OUT_OF_BOUND_DATESLOTINDEX =
+ * "The dateSlot index given is out of bounds "
+ * + "of the existing list." +
+ * "Please retype another index that is within the range or left it empty.";
+ *
+ * public static final String
+ * MESSAGE_INVALID_NUMBERS_OF_UNAVAILABLEDATES_AND_UNAVAILABLEDATESINDEX =
+ * "The unavailable date index "
+ * + "provided is more than the unavailable date provided."
+ * + "Please remove the unavailable date index or add more unavailable date.";
+ *
+ * public static final String MESSAGE_OUT_OF_BOUND_UNAVAILABLEDATESINDEX =
+ * "The unavailable date index "
+ * + "given is out of bounds of the existing list."
+ * + "Please retype another index that is within the range or left it empty.";
+ */
- private final Index index;
+ private final Uid targetUid;
private final EditPersonDescriptor editPersonDescriptor;
/**
- * @param index of the person in the filtered person list to edit
- * @param editPersonDescriptor details to edit the person with
+ * @param targetUid Uid 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);
+ public EditCommand(Uid targetUid, EditPersonDescriptor editPersonDescriptor) {
+ requireAllNonNull(targetUid, editPersonDescriptor);
- this.index = index;
+ this.targetUid = targetUid;
this.editPersonDescriptor = new EditPersonDescriptor(editPersonDescriptor);
}
@@ -69,37 +129,148 @@ public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) {
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
List lastShownList = model.getFilteredPersonList();
+ Optional personToEdit = lastShownList.stream().filter(p -> p.getUid().equals(targetUid)).findFirst();
- if (index.getZeroBased() >= lastShownList.size()) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ if (personToEdit.isEmpty()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_UID);
}
- Person personToEdit = lastShownList.get(index.getZeroBased());
- Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor);
+ Person confirmedPersonToEdit = personToEdit.get();
+
+ checkDescriptionGiven(editPersonDescriptor, confirmedPersonToEdit);
- if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) {
- throw new CommandException(MESSAGE_DUPLICATE_PERSON);
+ Person editedPerson = createEditedPerson(model, lastShownList, confirmedPersonToEdit, editPersonDescriptor);
+
+ if (!confirmedPersonToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) {
+ throw new CommandException(String.format(MESSAGE_DUPLICATE_PERSON,
+ confirmedPersonToEdit.getCategoryIndicator()));
}
- model.setPerson(personToEdit, editedPerson);
+ model.setPerson(confirmedPersonToEdit, editedPerson);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
- return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson));
+ return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS,
+ confirmedPersonToEdit.getCategoryIndicator(), editedPerson));
+
+ }
+
+ private void checkDescriptionGiven(EditPersonDescriptor editPersonDescriptor, Person personToEdit)
+ throws CommandException {
+ boolean hasDatesSlots = editPersonDescriptor.getDatesSlots().isPresent();
+ boolean hasDateSlotIndexes = editPersonDescriptor.getDateSlotIndexes().isPresent();
+ boolean hasUnavailableDates = editPersonDescriptor.getUnavailableDates().isPresent();
+ boolean hasUnavailableDateIndexes = editPersonDescriptor.getDateIndexes().isPresent();
+ boolean isNurse = editPersonDescriptor.getCategory().equals("N") || personToEdit instanceof Nurse;
+
+ if (isNurse && (hasDateSlotIndexes || hasDatesSlots)) {
+ throw new CommandException(MESSAGE_NURSE_INVALID_DATESLOT_EDIT);
+ }
+ if (hasUnavailableDates || hasUnavailableDateIndexes) {
+ throw new CommandException(MESSAGE_PATIENT_INVALID_UNAVAILABLE_DATE_EDIT);
+ }
}
/**
* Creates and returns a {@code Person} with the details of {@code personToEdit}
* edited with {@code editPersonDescriptor}.
*/
- private static Person createEditedPerson(Person personToEdit, EditPersonDescriptor editPersonDescriptor) {
+ public Person createEditedPerson(Model model, List personList, Person personToEdit,
+ EditPersonDescriptor editPersonDescriptor) throws CommandException {
assert personToEdit != null;
-
+ Category updatedCategory = editPersonDescriptor.getCategory().orElse(personToEdit.getCategory());
+ Uid uid = editPersonDescriptor.getUid().orElse(personToEdit.getUid());
Name updatedName = editPersonDescriptor.getName().orElse(personToEdit.getName());
+ Gender updatedGender = editPersonDescriptor.getGender().orElse(personToEdit.getGender());
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);
+ if (personToEdit instanceof Patient && updatedCategory.isPatient()) {
+ return createUpdatedPatient(uid, updatedName, updatedGender, updatedPhone, updatedEmail, updatedAddress,
+ updatedTags, editPersonDescriptor, personToEdit, model, personList);
+
+ } else if (updatedCategory.isPatient()) {
+ return createNewPatient(uid, updatedName, updatedGender, updatedPhone, updatedEmail, updatedAddress,
+ updatedTags, editPersonDescriptor);
+
+ } else if (personToEdit instanceof Nurse && updatedCategory.isNurse()) {
+ return createUpdatedNurse(uid, updatedName, updatedGender, updatedPhone, updatedEmail, updatedAddress,
+ updatedTags, editPersonDescriptor, personToEdit, model, personList);
+
+ } else if (updatedCategory.isNurse()) {
+ return createNewNurse(uid, updatedName, updatedGender, updatedPhone, updatedEmail, updatedAddress,
+ updatedTags, editPersonDescriptor);
+ }
+ throw new IllegalArgumentException(Category.MESSAGE_CONSTRAINTS);
+ }
+
+ private Patient createUpdatedPatient(Uid uid, Name updatedName, Gender updatedGender, Phone updatedPhone,
+ Email updatedEmail, Address updatedAddress, Set updatedTags,
+ EditPersonDescriptor editPersonDescriptor, Person personToEdit,
+ Model model, List personList) throws CommandException {
+
+ Optional updatedPhysician = editPersonDescriptor.getPhysician()
+ .orElse(((Patient) personToEdit).getAttendingPhysician());
+ Optional updatedNextOfKin = editPersonDescriptor.getNextOfKin()
+ .orElse(((Patient) personToEdit).getNextOfKin());
+
+ List originalDateSlot = ((Patient) personToEdit).getDatesSlots();
+ Optional> toBeUpdateDateSlot = editPersonDescriptor.getDatesSlots();
+ Optional> toBeUpdateDateSlotIndexes = editPersonDescriptor.getDateSlotIndexes();
+ EditedDateSlotCreator creator = new EditedDateSlotCreator(model, personList, originalDateSlot,
+ toBeUpdateDateSlot, toBeUpdateDateSlotIndexes);
+ List updatedDateSlot = creator.createEditedDateSlotList();
+
+ return new Patient(uid, updatedName, updatedGender, updatedPhone, updatedEmail,
+ updatedAddress, updatedTags, updatedDateSlot, updatedPhysician, updatedNextOfKin);
+ }
+
+ private Patient createNewPatient(Uid uid, Name updatedName, Gender updatedGender, Phone updatedPhone,
+ Email updatedEmail, Address updatedAddress, Set updatedTags,
+ EditPersonDescriptor editPersonDescriptor) {
+
+ Optional updatedPhysician = editPersonDescriptor.getPhysician()
+ .orElse(Optional.empty());
+ Optional updatedNextOfKin = editPersonDescriptor.getNextOfKin()
+ .orElse(Optional.empty());
+ List updatedDateSlot = editPersonDescriptor.getDatesSlots().orElse(null);
+
+ return new Patient(uid, updatedName, updatedGender, updatedPhone, updatedEmail,
+ updatedAddress, updatedTags, updatedDateSlot, updatedPhysician, updatedNextOfKin);
+ }
+
+ private Nurse createUpdatedNurse(Uid uid, Name updatedName, Gender updatedGender, Phone updatedPhone,
+ Email updatedEmail, Address updatedAddress, Set updatedTags,
+ EditPersonDescriptor editPersonDescriptor, Person personToEdit,
+ Model model, List personList) throws CommandException {
+
+ List originalDate = ((Nurse) personToEdit).getUnavailableDates();
+ Optional> toBeUpdateDate = editPersonDescriptor.getUnavailableDates();
+ Optional> toBeUpdateDateIndexes = editPersonDescriptor.getDateIndexes();
+ EditedUnavailableDateCreator creator = new EditedUnavailableDateCreator(model, personToEdit, personList,
+ originalDate, toBeUpdateDate, toBeUpdateDateIndexes);
+ List updatedUnavailableDate = creator.createEditedUnavailableDateList(editPersonDescriptor);
+
+ List updatedFullyScheduledDateList = editPersonDescriptor.getFullyScheduledDates()
+ .orElse(((Nurse) personToEdit).getFullyScheduledDates());
+ List updatedHomeVisitList = editPersonDescriptor.getHomeVisits()
+ .orElse(((Nurse) personToEdit).getHomeVisits());
+
+ return new Nurse(uid, updatedName, updatedGender, updatedPhone, updatedEmail, updatedAddress, updatedTags,
+ updatedUnavailableDate, updatedHomeVisitList, updatedFullyScheduledDateList);
+ }
+
+ private Nurse createNewNurse(Uid uid, Name updatedName, Gender updatedGender, Phone updatedPhone,
+ Email updatedEmail, Address updatedAddress, Set updatedTags,
+ EditPersonDescriptor editPersonDescriptor) {
+
+ List updatedUnavailableDate = editPersonDescriptor.getUnavailableDates().orElse(null);
+ List updatedHomeVisitList = editPersonDescriptor.getHomeVisits().orElse(null);
+ List updatedFullyScheduledDateList = editPersonDescriptor.getFullyScheduledDates()
+ .orElse(null);
+
+ return new Nurse(uid, updatedName, updatedGender, updatedPhone, updatedEmail, updatedAddress, updatedTags,
+ updatedUnavailableDate, updatedHomeVisitList, updatedFullyScheduledDateList);
}
@Override
@@ -116,74 +287,140 @@ public boolean equals(Object other) {
// state check
EditCommand e = (EditCommand) other;
- return index.equals(e.index)
+ return targetUid.equals(e.targetUid)
&& editPersonDescriptor.equals(e.editPersonDescriptor);
}
/**
- * Stores the details to edit the person with. Each non-empty field value will replace the
+ * 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 Category category;
+ private Uid uid;
private Name name;
+ private Gender gender;
private Phone phone;
private Email email;
private Address address;
private Set tags;
-
- public EditPersonDescriptor() {}
+ private List datesSlots;
+ private List dateSlotIndexes;
+ private List homeVisits;
+ private List unavailableDates;
+ private List dateIndexes;
+ private List fullyScheduledDates;
+ private Optional physician;
+ private Optional nextOfKin;
+
+ public EditPersonDescriptor() {
+ }
/**
* Copy constructor.
* A defensive copy of {@code tags} is used internally.
*/
public EditPersonDescriptor(EditPersonDescriptor toCopy) {
+ setCategory(toCopy.category);
+ setUid(toCopy.uid);
setName(toCopy.name);
+ setGender(toCopy.gender);
setPhone(toCopy.phone);
setEmail(toCopy.email);
setAddress(toCopy.address);
setTags(toCopy.tags);
+ setDatesSlots(toCopy.datesSlots);
+ setDateSlotIndexes(toCopy.dateSlotIndexes);
+ setHomeVisits(toCopy.homeVisits);
+ setUnavailableDates(toCopy.unavailableDates);
+ setDateIndexes(toCopy.dateIndexes);
+ setFullyScheduledDates(toCopy.fullyScheduledDates);
+ setPhysician(toCopy.physician);
+ setNextOfKin(toCopy.nextOfKin);
+
}
/**
* Returns true if at least one field is edited.
*/
public boolean isAnyFieldEdited() {
- return CollectionUtil.isAnyNonNull(name, phone, email, address, tags);
+ return CollectionUtil.isAnyNonNull(name, gender, phone, email, address,
+ tags, datesSlots, dateSlotIndexes, unavailableDates, dateIndexes);
}
- public void setName(Name name) {
- this.name = name;
+ public Optional getCategory() {
+ return Optional.ofNullable(category);
+ }
+
+ public void setCategory(Category category) {
+ this.category = category;
+ }
+
+ /**
+ * @return the id
+ */
+ public Optional getUid() {
+ return Optional.ofNullable(uid);
+ }
+
+ /**
+ * @param uid the id to set
+ */
+ public void setUid(Uid uid) {
+ this.uid = uid;
}
public Optional getName() {
return Optional.ofNullable(name);
}
- public void setPhone(Phone phone) {
- this.phone = phone;
+ public void setName(Name name) {
+ this.name = name;
+ }
+
+ public Optional getGender() {
+ return Optional.ofNullable(gender);
+ }
+
+ public void setGender(Gender gender) {
+ this.gender = gender;
}
public Optional getPhone() {
return Optional.ofNullable(phone);
}
- public void setEmail(Email email) {
- this.email = email;
+ public void setPhone(Phone phone) {
+ this.phone = phone;
}
public Optional getEmail() {
return Optional.ofNullable(email);
}
- public void setAddress(Address address) {
- this.address = address;
+ public void setEmail(Email email) {
+ this.email = email;
}
public Optional getAddress() {
return Optional.ofNullable(address);
}
+ public void setAddress(Address address) {
+ this.address = address;
+ }
+
+ /**
+ * 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();
+ }
+
/**
* Sets {@code tags} to this object's {@code tags}.
* A defensive copy of {@code tags} is used internally.
@@ -193,12 +430,132 @@ public void setTags(Set tags) {
}
/**
- * Returns an unmodifiable tag set, which throws {@code UnsupportedOperationException}
- * if modification is attempted.
- * Returns {@code Optional#empty()} if {@code tags} is null.
+ * Returns a dateSlot list
+ * Returns {@code Optional#empty()} if {@code dateSlots} is null.
*/
- public Optional> getTags() {
- return (tags != null) ? Optional.of(Collections.unmodifiableSet(tags)) : Optional.empty();
+ public Optional> getDatesSlots() {
+ return (datesSlots != null) ? Optional.of(new ArrayList(datesSlots)) : Optional.empty();
+ }
+
+ /**
+ * Sets {@code datesSlots} to this object's {@code datesSlots}.
+ */
+ public void setDatesSlots(List datesSlots) {
+ this.datesSlots = (datesSlots != null) ? new ArrayList(datesSlots) : null;
+ }
+
+ /**
+ * Returns a dateSlotIndexes list
+ * Returns {@code Optional#empty()} if {@code dateSlotIndexes} is null.
+ */
+ public Optional> getDateSlotIndexes() {
+ return (dateSlotIndexes != null) ? Optional.of(new ArrayList(dateSlotIndexes)) : Optional.empty();
+ }
+
+ /**
+ * Sets {@code dateSlotIndexes} to this object's {@code dateSlotIndexes}.
+ */
+ public void setDateSlotIndexes(List dateSlotIndexes) {
+ this.dateSlotIndexes = (dateSlotIndexes != null) ? new ArrayList(dateSlotIndexes) : null;
+ }
+
+ /**
+ * Returns a homeVisit list
+ * Returns {@code Optional#empty()} if {@code homeVisits} is null.
+ */
+ public Optional> getHomeVisits() {
+ return (homeVisits != null) ? Optional.of(new ArrayList(homeVisits)) : Optional.empty();
+ }
+
+ /**
+ * Sets {@code homeVisits} to this object's {@code homeVisits}.
+ */
+ public void setHomeVisits(List homeVisits) {
+ this.homeVisits = (homeVisits != null) ? new ArrayList(homeVisits) : null;
+ }
+
+ /**
+ * Returns a unavailableDate list
+ * Returns {@code Optional#empty()} if {@code unavailableDate} is null.
+ */
+ public Optional> getUnavailableDates() {
+ return (unavailableDates != null) ? Optional.of(new ArrayList(unavailableDates)) : Optional.empty();
+ }
+
+ /**
+ * Sets {@code unavailableDate} to this object's {@code unavailableDates}.
+ */
+ public void setUnavailableDates(List unavailableDates) {
+ this.unavailableDates = (unavailableDates != null) ? new ArrayList(unavailableDates) : null;
+ }
+
+ /**
+ * Returns a dateIndexes list
+ * Returns {@code Optional#empty()} if {@code dateIndexes} is null.
+ */
+ public Optional> getDateIndexes() {
+ return (dateIndexes != null) ? Optional.of(new ArrayList(dateIndexes)) : Optional.empty();
+ }
+
+ /**
+ * Sets {@code dateIndexes} to this object's {@code dateIndexes}.
+ */
+ public void setDateIndexes(List dateIndexes) {
+ this.dateIndexes = (dateIndexes != null) ? new ArrayList(dateIndexes) : null;
+ }
+
+ /**
+ * Returns a fullyScheduledlist
+ * Returns {@code Optional#empty()} if {@code fullyScheduledDates} is null.
+ */
+ public Optional> getFullyScheduledDates() {
+ return (fullyScheduledDates != null) ? Optional.of(new ArrayList(fullyScheduledDates))
+ : Optional.empty();
+ }
+
+ /**
+ * Sets {@code fullyScheduledDates} to this object's {@code fullScheduledDates}.
+ */
+ public void setFullyScheduledDates(List fullyScheduledDates) {
+ this.fullyScheduledDates = (fullyScheduledDates != null) ? new ArrayList(fullyScheduledDates) : null;
+ }
+
+ /**
+ * Returns the attending physician
+ *
+ * @return {@code Optional#empty()} if {@code physician} is null.
+ */
+ public Optional> getPhysician() {
+ return (physician != null) ? Optional.of(physician) : Optional.empty();
+ }
+
+ /**
+ * Sets {@code p} to this object's {@code physician}.
+ *
+ * @return
+ */
+ public EditPersonDescriptor setPhysician(Optional p) {
+ physician = p;
+ return this;
+ }
+
+ /**
+ * Returns the next of kin
+ *
+ * @return {@code Optioanl.empty()} if {@code nextOfKin} is null.
+ */
+ public Optional> getNextOfKin() {
+ return (nextOfKin != null) ? Optional.of(nextOfKin) : Optional.empty();
+ }
+
+ /**
+ * Sets {@code n} to this object's {@code nextOfKin}
+ *
+ * @return
+ */
+ public EditPersonDescriptor setNextOfKin(Optional n) {
+ nextOfKin = n;
+ return this;
}
@Override
@@ -216,11 +573,339 @@ public boolean equals(Object other) {
// state check
EditPersonDescriptor e = (EditPersonDescriptor) other;
- return getName().equals(e.getName())
+ return getUid().equals(e.getUid())
+ && getName().equals(e.getName())
+ && getCategory().equals(e.getCategory())
+ && getGender().equals(e.getGender())
&& getPhone().equals(e.getPhone())
&& getEmail().equals(e.getEmail())
&& getAddress().equals(e.getAddress())
- && getTags().equals(e.getTags());
+ && getDatesSlots().equals(e.getDatesSlots())
+ && getDateSlotIndexes().equals(e.getDateSlotIndexes())
+ && getTags().equals(e.getTags())
+ && getHomeVisits().equals(e.getHomeVisits())
+ && getUnavailableDates().equals(e.getUnavailableDates())
+ && getDateIndexes().equals(e.getDateIndexes())
+ && getFullyScheduledDates().equals(e.getFullyScheduledDates());
}
}
+
+ /**
+ * To create the edited date slot list
+ * If delete date slot occur, the respective home visit will also be deleted
+ */
+ public static class EditedDateSlotCreator {
+
+ public static final String MESSAGE_INVALID_NUMBERS_OF_DATESLOT_AND_DATESLOTINDEX = "The dateSlot index "
+ + "provided is more than the dateSlot provided. "
+ + "Please remove the dateSlot index or add more dateSlot.";
+ private final Model model;
+ private final List personList;
+ private final List originalDateSlotList;
+ private final List toBeUpdateDateSlots;
+ private final List toBeUpdateDateSlotsIndexes;
+ private final Boolean isDateSlotsGivenNull;
+ private final Boolean isDateSlotIndexesGivenNull;
+ private final Boolean isDateSlotsGivenEmpty;
+ private final Boolean isDateSlotIndexesGivenEmpty;
+
+ EditedDateSlotCreator(Model model, List personList, List originalDateSlots,
+ Optional> toBeUpdateDateSlots,
+ Optional> toBeUpdateDateSlotsIndexes) {
+ this.model = model;
+ this.personList = personList;
+ this.originalDateSlotList = originalDateSlots;
+ this.isDateSlotsGivenNull = getIsDateSlotsGivenNull(toBeUpdateDateSlots);
+ this.isDateSlotIndexesGivenNull = getIsDateSlotIndexesGivenNull(toBeUpdateDateSlotsIndexes);
+ this.toBeUpdateDateSlots = createToBeUpdateDateSlotList(toBeUpdateDateSlots);
+ this.toBeUpdateDateSlotsIndexes = createToBeUpdatedIndexList(toBeUpdateDateSlotsIndexes);
+ this.isDateSlotsGivenEmpty = getIsDateSlotsGivenEmpty();
+ this.isDateSlotIndexesGivenEmpty = getIsDateSlotIndexesGivenEmpty();
+ }
+
+ private boolean getIsDateSlotsGivenNull(Optional> toBeUpdateDateSlots) {
+ return toBeUpdateDateSlots.equals(Optional.empty());
+ }
+
+ private boolean getIsDateSlotIndexesGivenNull(Optional> toBeUpdateDateSlotIndexes) {
+ return toBeUpdateDateSlotIndexes.equals(Optional.empty());
+ }
+
+ private List createToBeUpdateDateSlotList(Optional> toBeUpdateDateSlots) {
+ List toBeUpdateDateSlotList = new ArrayList<>();
+ if (!isDateSlotsGivenNull) {
+ toBeUpdateDateSlotList = new ArrayList<>(toBeUpdateDateSlots.get());
+ }
+ return toBeUpdateDateSlotList;
+ }
+
+ private List createToBeUpdatedIndexList(Optional> toBeUpdateDateSlotsIndexes) {
+ List toBeUpdateDateSlotIndexList = new ArrayList<>();
+ if (!isDateSlotIndexesGivenNull) {
+ toBeUpdateDateSlotIndexList = new ArrayList<>(toBeUpdateDateSlotsIndexes.get());
+ }
+ return toBeUpdateDateSlotIndexList;
+ }
+
+ private boolean getIsDateSlotsGivenEmpty() {
+ return !isDateSlotsGivenNull && toBeUpdateDateSlots.isEmpty();
+ }
+
+ private boolean getIsDateSlotIndexesGivenEmpty() {
+ return !isDateSlotIndexesGivenNull && toBeUpdateDateSlotsIndexes.isEmpty();
+ }
+
+ private List createEditedDateSlotList() throws CommandException {
+
+ if (isDelete()) {
+ // Deletes all the dateTime in the existing list/ Deletes specific dateTime in
+ // the existing list
+ return removeActionForDateSlot();
+
+ } else if (isAdd()) {
+ // Add the given dateTime to the existing list
+ return addActionForDateSlot();
+
+ } else if (isEdit()) {
+ // Remove specific dateSlot in the existing list and add the given dateSlot
+ return editActionForDateSlot();
+
+ }
+ // Remain as original dateTime list, no changes made
+ return originalDateSlotList;
+ }
+
+ private Boolean isDelete() {
+ Boolean isAllDeleted = (isDateSlotsGivenNull && isDateSlotIndexesGivenEmpty)
+ || (isDateSlotIndexesGivenNull && isDateSlotsGivenEmpty)
+ || (isDateSlotsGivenEmpty && isDateSlotIndexesGivenEmpty);
+ Boolean isSpecificDeleted = !isDateSlotIndexesGivenEmpty && (isDateSlotsGivenNull || isDateSlotsGivenEmpty)
+ && !isDateSlotIndexesGivenNull;
+ return isAllDeleted || isSpecificDeleted;
+ }
+
+ private Boolean isAdd() {
+ return !isDateSlotsGivenEmpty && (isDateSlotIndexesGivenNull || isDateSlotIndexesGivenEmpty);
+ }
+
+ private Boolean isEdit() {
+ return !isDateSlotsGivenEmpty && !isDateSlotIndexesGivenEmpty;
+ }
+
+ private List removeActionForDateSlot() throws CommandException {
+ DateSlotManager remover = new DateSlotManager(originalDateSlotList, toBeUpdateDateSlotsIndexes);
+ if (!toBeUpdateDateSlotsIndexes.isEmpty()) {
+ remover.checkIndexOutOfBound();
+ }
+ InternalHomeVisitRemoverFromDateSlot homeVisitRemover = new InternalHomeVisitRemoverFromDateSlot(model,
+ personList, originalDateSlotList, toBeUpdateDateSlotsIndexes);
+ homeVisitRemover.removeHomeVisitsForDateSlot();
+ return remover.removeDateSlot();
+ }
+
+ private List addActionForDateSlot() {
+ DateSlotManager adder = new DateSlotManager(originalDateSlotList);
+ return adder.addDateSlot(toBeUpdateDateSlots);
+ }
+
+ private List editActionForDateSlot() throws CommandException {
+ checkDateSlotAndIndex();
+ DateSlotManager editor = new DateSlotManager(originalDateSlotList, toBeUpdateDateSlotsIndexes);
+ if (!toBeUpdateDateSlotsIndexes.isEmpty()) {
+ editor.checkIndexOutOfBound();
+ }
+ InternalHomeVisitRemoverFromDateSlot homeVisitRemover = new InternalHomeVisitRemoverFromDateSlot(model,
+ personList, originalDateSlotList, toBeUpdateDateSlotsIndexes);
+ homeVisitRemover.removeHomeVisitsForDateSlot();
+ editor.removeDateSlot();
+ return editor.addDateSlot(toBeUpdateDateSlots);
+ }
+
+ private void checkDateSlotAndIndex() throws CommandException {
+ if (toBeUpdateDateSlots.size() < toBeUpdateDateSlotsIndexes.size()) {
+ throw new CommandException(MESSAGE_INVALID_NUMBERS_OF_DATESLOT_AND_DATESLOTINDEX);
+ }
+ }
+ }
+
+ /**
+ * To create the edited unavailable date list.
+ * If adding a new unavailable date occurs, then the respective home visit will
+ * be checked and removed if clash
+ */
+ public static class EditedUnavailableDateCreator {
+
+ public static final String MESSAGE_OUT_OF_BOUND_UNAVAILABLE_DATE_INDEX = "The unavailable date index "
+ + "given is out of bounds of the existing list."
+ + " Please retype another index that is within the range or left it empty.";
+
+ public static final String MESSAGE_INVALID_NUMBERS_OF_UNAVAILABLE_DATES_AND_UNAVAILABLE_DATE_INDEXES =
+ "The unavailable date index provided is more than the unavailable date provided."
+ + " Please remove the unavailable date index or add more unavailable date.";
+
+ private final Model model;
+ private final Person nurseToEdit;
+ private final List personList;
+ private final List originalUnavailableDateList;
+ private final List toBeUpdateUnavailableDates;
+ private final List toBeUpdateUnavailableDateIndexes;
+ private final Boolean isUnavailableDatesGivenNull;
+ private final Boolean isUnavailableDateIndexesGivenNull;
+ private final Boolean isUnavailableDatesGivenEmpty;
+ private final Boolean isUnavailableDateIndexesGivenEmpty;
+
+ EditedUnavailableDateCreator(Model model, Person nurseToEdit, List personList,
+ List originalUnavailableDates,
+ Optional> toBeUpdateUnavailableDates,
+ Optional> toBeUpdateUnavailableDateIndexes) {
+ this.model = model;
+ this.nurseToEdit = nurseToEdit;
+ this.personList = personList;
+ this.originalUnavailableDateList = originalUnavailableDates;
+ this.isUnavailableDatesGivenNull = getIsUnavailableDatesGivenNull(toBeUpdateUnavailableDates);
+ this.isUnavailableDateIndexesGivenNull = getIsUnavailableDateIndexesGivenNull(
+ toBeUpdateUnavailableDateIndexes);
+ this.toBeUpdateUnavailableDates = createToBeUpdateUnavailableDateList(toBeUpdateUnavailableDates);
+ this.toBeUpdateUnavailableDateIndexes = createToBeUpdatedIndexList(toBeUpdateUnavailableDateIndexes);
+ this.isUnavailableDatesGivenEmpty = getIsUnavailableDatesGivenEmpty();
+ this.isUnavailableDateIndexesGivenEmpty = getIsUnavailableDateIndexesGivenEmpty();
+ }
+
+ private boolean getIsUnavailableDatesGivenNull(Optional> toBeUpdateUnavailableDates) {
+ return toBeUpdateUnavailableDates.equals(Optional.empty());
+ }
+
+ private boolean getIsUnavailableDateIndexesGivenNull(Optional> toBeUpdateUnavailableDateIndexes) {
+ return toBeUpdateUnavailableDateIndexes.equals(Optional.empty());
+ }
+
+ private List createToBeUpdateUnavailableDateList(Optional> toBeUpdateUnavailableDates) {
+ List toBeUpdateUnavailableDateList = new ArrayList<>();
+ if (!isUnavailableDatesGivenNull) {
+ toBeUpdateUnavailableDateList = new ArrayList<>(toBeUpdateUnavailableDates.get());
+ }
+ return toBeUpdateUnavailableDateList;
+ }
+
+ private List createToBeUpdatedIndexList(Optional> toBeUpdateUnavailableDateIndexes) {
+ List toBeUpdateUnavailableDateIndexList = new ArrayList<>();
+ if (!isUnavailableDateIndexesGivenNull) {
+ toBeUpdateUnavailableDateIndexList = new ArrayList<>(toBeUpdateUnavailableDateIndexes.get());
+ }
+ return toBeUpdateUnavailableDateIndexList;
+ }
+
+ private boolean getIsUnavailableDatesGivenEmpty() {
+ return !isUnavailableDatesGivenNull && toBeUpdateUnavailableDates.isEmpty();
+ }
+
+ private boolean getIsUnavailableDateIndexesGivenEmpty() {
+ return !isUnavailableDateIndexesGivenNull && toBeUpdateUnavailableDateIndexes.isEmpty();
+ }
+
+ private List createEditedUnavailableDateList(EditPersonDescriptor editPersonDescriptor)
+ throws CommandException {
+
+ if (isAllDelete()) {
+ // Deletes all the unavailable dates in the existing list
+ return removeAllActionForUnavailableDate();
+
+ } else if (isSpecificDelete()) {
+ // Deletes specific unavailable dates in the existing list
+ return removeSpecificActionForUnavailableDate();
+
+ } else if (isAdd()) {
+ // Add the given unavailable dates to the existing list
+ return addActionForUnavailableDate(editPersonDescriptor);
+
+ } else if (isEdit()) {
+ // Remove specific unavailable dates in the existing list and add the given
+ // unavailable dates
+ return editActionForUnavailableDates(editPersonDescriptor);
+
+ } else {
+ // Remain as original unavailable dates list, no changes made
+ return originalUnavailableDateList;
+ }
+ }
+
+ private Boolean isAllDelete() {
+ return (isUnavailableDatesGivenNull && isUnavailableDateIndexesGivenEmpty)
+ || (isUnavailableDateIndexesGivenNull && isUnavailableDatesGivenEmpty)
+ || (isUnavailableDatesGivenEmpty && isUnavailableDateIndexesGivenEmpty);
+ }
+
+ private Boolean isSpecificDelete() {
+ return !isUnavailableDateIndexesGivenEmpty && (isUnavailableDatesGivenNull
+ || isUnavailableDatesGivenEmpty) && !isUnavailableDateIndexesGivenNull;
+ }
+
+ private Boolean isAdd() {
+ return !isUnavailableDatesGivenEmpty && (isUnavailableDateIndexesGivenNull
+ || isUnavailableDateIndexesGivenEmpty);
+ }
+
+ private Boolean isEdit() {
+ return !isUnavailableDatesGivenEmpty && !isUnavailableDateIndexesGivenEmpty;
+ }
+
+ private List removeAllActionForUnavailableDate() throws CommandException {
+ return new ArrayList<>();
+ }
+
+ private List removeSpecificActionForUnavailableDate() throws CommandException {
+ sortIndex();
+ checkIndexOutOfBound();
+ for (Index index : toBeUpdateUnavailableDateIndexes) {
+ Date unavailableDate = originalUnavailableDateList.get(index.getZeroBased());
+ originalUnavailableDateList.remove(unavailableDate);
+ }
+ return originalUnavailableDateList;
+ }
+
+ private void sortIndex() {
+ ReverseIndexComparator comp = new ReverseIndexComparator();
+ this.toBeUpdateUnavailableDateIndexes.sort(comp);
+ }
+
+ private void checkIndexOutOfBound() throws CommandException {
+ if (toBeUpdateUnavailableDateIndexes.get(0).getZeroBased() >= originalUnavailableDateList.size()) {
+ throw new CommandException(MESSAGE_OUT_OF_BOUND_UNAVAILABLE_DATE_INDEX);
+ }
+ }
+
+ private List addActionForUnavailableDate(EditPersonDescriptor editPersonDescriptor) {
+ List homeVisitList = ((Nurse) nurseToEdit).getHomeVisits();
+ List fullyScheduledDateList = ((Nurse) nurseToEdit).getFullyScheduledDates();
+ InternalUnmarkerFromHomeVisit unmarker = new InternalUnmarkerFromHomeVisit(model,
+ personList, homeVisitList);
+ unmarker.unmarkDateSlotForUnavailableDates(toBeUpdateUnavailableDates);
+
+ HomeVisitManager remover = new HomeVisitManager(homeVisitList, fullyScheduledDateList);
+ List updatedHomeVisitList = remover.removeHomeVisitFromUnavailableDates(
+ toBeUpdateUnavailableDates);
+ List updatedFullyScheduledDateList = remover.getFullyScheduledDateList();
+ editPersonDescriptor.setHomeVisits(updatedHomeVisitList);
+ editPersonDescriptor.setFullyScheduledDates(updatedFullyScheduledDateList);
+
+ originalUnavailableDateList.addAll(toBeUpdateUnavailableDates);
+ return originalUnavailableDateList;
+ }
+
+ private List editActionForUnavailableDates(EditPersonDescriptor editPersonDescriptor)
+ throws CommandException {
+ checkDateSlotAndIndex();
+ removeSpecificActionForUnavailableDate();
+ addActionForUnavailableDate(editPersonDescriptor);
+ return originalUnavailableDateList;
+ }
+
+ private void checkDateSlotAndIndex() throws CommandException {
+ if (toBeUpdateUnavailableDates.size() < toBeUpdateUnavailableDateIndexes.size()) {
+ throw new CommandException(MESSAGE_INVALID_NUMBERS_OF_UNAVAILABLE_DATES_AND_UNAVAILABLE_DATE_INDEXES);
+ }
+ }
+
+ }
+
}
diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/seedu/address/logic/commands/ExitCommand.java
index 3dd85a8ba90..fbc67241b46 100644
--- a/src/main/java/seedu/address/logic/commands/ExitCommand.java
+++ b/src/main/java/seedu/address/logic/commands/ExitCommand.java
@@ -9,7 +9,7 @@ public class ExitCommand extends Command {
public static final String COMMAND_WORD = "exit";
- public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting Address Book as requested ...";
+ public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Thank you for using Healthcare Xpress!";
@Override
public CommandResult execute(Model model) {
diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java
index d6b19b0a0de..84fcd8fe991 100644
--- a/src/main/java/seedu/address/logic/commands/FindCommand.java
+++ b/src/main/java/seedu/address/logic/commands/FindCommand.java
@@ -7,14 +7,15 @@
import seedu.address.model.person.NameContainsKeywordsPredicate;
/**
- * Finds and lists all persons in address book whose name contains any of the argument keywords.
+ * 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 "
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all patients and nurses 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";
@@ -37,6 +38,6 @@ public CommandResult execute(Model model) {
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
+ && predicate.equals(((FindCommand) other).predicate)); // state check
}
}
diff --git a/src/main/java/seedu/address/logic/commands/HomeVisitManager.java b/src/main/java/seedu/address/logic/commands/HomeVisitManager.java
new file mode 100644
index 00000000000..3c523dbc3a9
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/HomeVisitManager.java
@@ -0,0 +1,223 @@
+package seedu.address.logic.commands;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.commons.core.index.ReverseIndexComparator;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.person.Date;
+import seedu.address.model.person.DateSlot;
+import seedu.address.model.person.HomeVisit;
+
+/**
+ * A class to manage all home visit related task.
+ */
+public class HomeVisitManager {
+
+ public static final String MESSAGE_OUTOFBOUND_HOMEVISIT_INDEX = "The home visit index given is out of bounds.";
+ private static final int NUMBER_OF_SLOT_PER_DAY = 4;
+ public final List homeVisitList;
+ public final List homeVisitIndex;
+ public final List fullyScheduledDateList;
+
+ /**
+ * Construct a HomeVisitManager.
+ * @param homeVisitList
+ * @param homeVisitIndex
+ * @param fullyScheduledDateList
+ */
+ public HomeVisitManager(List homeVisitList, List homeVisitIndex,
+ List fullyScheduledDateList) {
+ this.homeVisitList = new ArrayList<>();
+ for (HomeVisit homeVisit : homeVisitList) {
+ this.homeVisitList.add(homeVisit.clone());
+ }
+ this.homeVisitIndex = new ArrayList<>(homeVisitIndex);
+ this.fullyScheduledDateList = new ArrayList<>(fullyScheduledDateList);
+ }
+
+ /**
+ * Construct a HomeVisitManager with empty home visit index list.
+ * @param homeVisitList
+ * @param fullyScheduledDateList
+ */
+ public HomeVisitManager(List homeVisitList, List fullyScheduledDateList) {
+ this.homeVisitList = new ArrayList<>();
+ for (HomeVisit homeVisit : homeVisitList) {
+ this.homeVisitList.add(homeVisit.clone());
+ }
+ this.homeVisitIndex = new ArrayList<>();
+ this.fullyScheduledDateList = new ArrayList<>(fullyScheduledDateList);
+ }
+
+ /**
+ * Create a homevisit list for a nurse.
+ * @param dateSlotList
+ * @param dateSlotIndexList
+ * @param patientUidNo
+ * @return homevisit list
+ */
+ public List createHomeVisitList(List dateSlotList,
+ List dateSlotIndexList, Long patientUidNo) {
+ if (dateSlotIndexList.isEmpty()) {
+ createAllHomeVisit(dateSlotList, patientUidNo);
+ } else {
+ createSpecificHomeVisit(dateSlotList, dateSlotIndexList, patientUidNo);
+ }
+ return homeVisitList;
+ }
+
+ private void createAllHomeVisit(List dateSlotList, Long patientUidNo) {
+ for (DateSlot dateSlot : dateSlotList) {
+ createHomeVisit(dateSlot, patientUidNo);
+ }
+ }
+
+ private void createSpecificHomeVisit(List dateSlotList, List dateSlotIndexList,
+ Long patientUidNo) {
+ List sortedDateSlotIndexList = sortIndex(dateSlotIndexList);
+ for (Index index : sortedDateSlotIndexList) {
+ DateSlot dateSlot = dateSlotList.get(index.getZeroBased());
+ createHomeVisit(dateSlot, patientUidNo);
+ }
+ }
+
+ private void createHomeVisit(DateSlot dateSlot, Long patientUidNo) {
+ HomeVisit homeVisit = new HomeVisit(dateSlot, patientUidNo);
+ homeVisitList.add(homeVisit);
+ LocalDate date = dateSlot.getDate();
+ addFullyScheduledDate(date);
+ }
+
+ private void addFullyScheduledDate(LocalDate date) {
+ int frequencyCount = 0;
+ for (HomeVisit homevisit : homeVisitList) {
+ LocalDate dateToCheck = homevisit.getDateSlot().getDate();
+ if (dateToCheck.equals(date)) {
+ frequencyCount++;
+ }
+ }
+ if (frequencyCount == NUMBER_OF_SLOT_PER_DAY) {
+ fullyScheduledDateList.add(new Date(date));
+ }
+ }
+
+ private List sortIndex(List indexList) {
+ ReverseIndexComparator comp = new ReverseIndexComparator();
+ indexList.sort(comp);
+ return indexList;
+ }
+
+ /**
+ * Remove homevisit from a nurse's homevisit list.
+ * @return updated homevisit list
+ * @throws CommandException
+ */
+ public List removeHomeVisits() throws CommandException {
+ if (homeVisitIndex.isEmpty()) {
+ removeAllHomeVisit();
+ } else {
+ removeSpecificHomeVisit();
+ }
+ return homeVisitList;
+ }
+
+ private void removeAllHomeVisit() throws CommandException {
+ for (HomeVisit homeVisit : homeVisitList) {
+ LocalDate date = homeVisit.getDateSlot().getDate();
+ removeFullyScheduledDate(date);
+ removeCheck(homeVisit);
+ }
+ homeVisitList.clear();
+ }
+
+ private void removeSpecificHomeVisit() throws CommandException {
+ List sortedHomeVisitIndexList = sortIndex(homeVisitIndex);
+ checkIndexOutOfBound();
+ for (Index index : sortedHomeVisitIndexList) {
+ HomeVisit homeVisit = homeVisitList.get(index.getZeroBased());
+ removeCheck(homeVisit);
+ homeVisitList.remove(homeVisit);
+ LocalDate date = homeVisit.getDateSlot().getDate();
+ removeFullyScheduledDate(date);
+ }
+ }
+
+ private void removeCheck(HomeVisit homeVisit) throws CommandException {
+ DateSlot dateSlot = homeVisit.getDateSlot();
+ DateSlotChecker checker = new DateSlotChecker(dateSlot);
+ checker.checkVisited();
+ }
+
+ private void checkIndexOutOfBound() throws CommandException {
+ if (homeVisitIndex.get(0).getZeroBased() >= homeVisitList.size()) {
+ throw new CommandException(MESSAGE_OUTOFBOUND_HOMEVISIT_INDEX);
+ }
+ }
+
+ /**
+ * Remove corresponding home visit of the given dateSlot from the homevisit list.
+ * @param dateSlot
+ * @return updated home visit list
+ */
+ public List removeHomeVisitFromDateSlot(DateSlot dateSlot) {
+ HomeVisit homeVisitToBeDeleted = homeVisitList.stream().filter(
+ h -> h.getDateSlot().getDateTime().equals(dateSlot.getDateTime())).findFirst().get();
+
+ homeVisitList.remove(homeVisitToBeDeleted);
+ LocalDate date = dateSlot.getDate();
+ removeFullyScheduledDate(date);
+ return this.homeVisitList;
+ }
+
+ private void removeFullyScheduledDate(LocalDate date) {
+ Optional dateToBeDeleted = fullyScheduledDateList.stream().filter(
+ h -> h.getDate().equals(date)).findFirst();
+
+ if (!dateToBeDeleted.isEmpty()) {
+ fullyScheduledDateList.remove(dateToBeDeleted.get());
+ }
+ }
+
+ /**
+ * To get the fully scheduled date list.
+ * @return fullyScheduledDateList
+ */
+ public List getFullyScheduledDateList() {
+ return this.fullyScheduledDateList;
+ }
+
+ /**
+ * Remove corresponding home visit that have time clash with the unavailable date.
+ * @param unavailableDateList
+ * @return updated home visit list
+ */
+ public List removeHomeVisitFromUnavailableDates(List unavailableDateList) {
+ for (Date date : unavailableDateList) {
+ removeHomeVisitFromUnavailableDate(date);
+ }
+ return homeVisitList;
+ }
+
+ private void removeHomeVisitFromUnavailableDate(Date unavailableDate) {
+ List toBeUpdatedHomeVisitList = new ArrayList<>(homeVisitList);
+ for (HomeVisit homeVisit : homeVisitList) {
+ Boolean isSameDate = checkSameDate(homeVisit, unavailableDate);
+ if (isSameDate) {
+ toBeUpdatedHomeVisitList.remove(homeVisit);
+ }
+ }
+ homeVisitList.clear();
+ homeVisitList.addAll(toBeUpdatedHomeVisitList);
+ removeFullyScheduledDate(unavailableDate.getDate());
+ }
+
+ private Boolean checkSameDate(HomeVisit homeVisit, Date unavailableDate) {
+ return homeVisit.getDateSlot().getDate().equals(unavailableDate.getDate());
+ }
+
+}
+
diff --git a/src/main/java/seedu/address/logic/commands/InternalEditor.java b/src/main/java/seedu/address/logic/commands/InternalEditor.java
new file mode 100644
index 00000000000..774e1c6ff34
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/InternalEditor.java
@@ -0,0 +1,81 @@
+package seedu.address.logic.commands;
+
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+import seedu.address.model.Model;
+import seedu.address.model.person.Address;
+import seedu.address.model.person.Date;
+import seedu.address.model.person.DateSlot;
+import seedu.address.model.person.Email;
+import seedu.address.model.person.Gender;
+import seedu.address.model.person.HomeVisit;
+import seedu.address.model.person.Name;
+import seedu.address.model.person.Nurse;
+import seedu.address.model.person.Patient;
+import seedu.address.model.person.Person;
+import seedu.address.model.person.Phone;
+import seedu.address.model.person.Uid;
+import seedu.address.model.tag.Tag;
+
+/**
+ * A class to internally edit a patient / nurse.
+ */
+public class InternalEditor {
+
+ public final Model model;
+
+ public InternalEditor(Model model) {
+ this.model = model;
+ }
+
+ /**
+ * Edit the patient to update the dateSlotList.
+ * @param patient
+ * @param dateSlotList
+ */
+ public void editPatient(Person patient, List dateSlotList) {
+ Uid patientUid = patient.getUid();
+ List lastShownList = model.getFilteredPersonList();
+ Optional personToEdit = lastShownList.stream().filter(p -> p.getUid().equals(patientUid)).findFirst();
+ Person confirmedPersonToEdit = personToEdit.get();
+ Uid uid = confirmedPersonToEdit.getUid();
+ Name name = confirmedPersonToEdit.getName();
+ Gender gender = confirmedPersonToEdit.getGender();
+ Phone phone = confirmedPersonToEdit.getPhone();
+ Email email = confirmedPersonToEdit.getEmail();
+ Address address = confirmedPersonToEdit.getAddress();
+ Set tags = confirmedPersonToEdit.getTags();
+ Person newPerson = new Patient(uid, name, gender, phone, email, address, tags, dateSlotList);
+ model.setPerson(confirmedPersonToEdit, newPerson);
+ model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+ }
+
+ /**
+ * Edit the nurse to update homeVisitList and fullyScheduledDateList.
+ * @param nurse
+ * @param homeVisitList
+ * @param fullyScheduledDateList
+ */
+ public void editNurse(Person nurse, List homeVisitList, List fullyScheduledDateList) {
+ Uid nurseUid = nurse.getUid();
+ List lastShownList = model.getFilteredPersonList();
+ Optional personToEdit = lastShownList.stream().filter(p -> p.getUid().equals(nurseUid)).findFirst();
+ Person confirmedPersonToEdit = personToEdit.get();
+ Uid uid = confirmedPersonToEdit.getUid();
+ Name name = confirmedPersonToEdit.getName();
+ Gender gender = confirmedPersonToEdit.getGender();
+ Phone phone = confirmedPersonToEdit.getPhone();
+ Email email = confirmedPersonToEdit.getEmail();
+ Address address = confirmedPersonToEdit.getAddress();
+ Set tags = confirmedPersonToEdit.getTags();
+ List unavailableDates = ((Nurse) confirmedPersonToEdit).getUnavailableDates();
+ Person newPerson = new Nurse(uid, name, gender, phone, email, address, tags, unavailableDates,
+ homeVisitList, fullyScheduledDateList);
+ model.setPerson(confirmedPersonToEdit, newPerson);
+ model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/InternalHomeVisitRemoverFromDateSlot.java b/src/main/java/seedu/address/logic/commands/InternalHomeVisitRemoverFromDateSlot.java
new file mode 100644
index 00000000000..6356dd4d2e9
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/InternalHomeVisitRemoverFromDateSlot.java
@@ -0,0 +1,109 @@
+package seedu.address.logic.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.commons.core.index.ReverseIndexComparator;
+import seedu.address.model.Model;
+import seedu.address.model.person.Date;
+import seedu.address.model.person.DateSlot;
+import seedu.address.model.person.HomeVisit;
+import seedu.address.model.person.Nurse;
+import seedu.address.model.person.Person;
+
+/**
+ * A class to do the internal removal of home visits when required.
+ */
+public class InternalHomeVisitRemoverFromDateSlot {
+
+ public final Model model;
+ private final List personList;
+ private final List patientDateSlotList;
+ private final List patientDateSlotIndex;
+
+ /**
+ * Construct an InternalHomeVisitRemoverFromDateSlot.
+ * @param model
+ * @param personList
+ * @param patientDateSlotList
+ * @param patientDateSlotIndex
+ */
+ InternalHomeVisitRemoverFromDateSlot(Model model, List personList, List patientDateSlotList,
+ List patientDateSlotIndex) {
+ this.model = model;
+ this.personList = personList;
+ this.patientDateSlotList = patientDateSlotList;
+ this.patientDateSlotIndex = patientDateSlotIndex;
+ }
+
+ /**
+ * Construct an InternalHomeVisitRemoverFromDateSlot with empty date slot index list.
+ * @param model
+ * @param personList
+ * @param patientDateSlotList
+ */
+ InternalHomeVisitRemoverFromDateSlot(Model model, List personList, List patientDateSlotList) {
+ this.model = model;
+ this.personList = personList;
+ this.patientDateSlotList = patientDateSlotList;
+ this.patientDateSlotIndex = new ArrayList<>();
+ }
+
+ /**
+ * Remove the respective home visits.
+ * @return updated homeVisit list
+ */
+ public Boolean removeHomeVisitsForDateSlot() {
+ Boolean hasRemoveHomeVisits = false;
+ if (patientDateSlotIndex.isEmpty()) {
+ hasRemoveHomeVisits = removeHomeVisitsFromAllDateSlot();
+ } else {
+ hasRemoveHomeVisits = removeHomeVisitsFromSpecificDateSlot();
+ }
+ return hasRemoveHomeVisits;
+ }
+
+ private Boolean removeHomeVisitsFromAllDateSlot() {
+ Boolean hasRemoveHomeVisits = false;
+ for (DateSlot dateSlot : patientDateSlotList) {
+ if (dateSlot.getHasAssigned()) {
+ removeHomeVisitFromDateSlot(model, personList, dateSlot);
+ hasRemoveHomeVisits = true;
+ }
+ }
+ return hasRemoveHomeVisits;
+ }
+
+ private Boolean removeHomeVisitsFromSpecificDateSlot() {
+ Boolean hasRemoveHomeVisits = false;
+ ReverseIndexComparator comp = new ReverseIndexComparator();
+ patientDateSlotIndex.sort(comp);
+ for (Index index : patientDateSlotIndex) {
+ DateSlot dateSlot = patientDateSlotList.get(index.getZeroBased());
+ if (dateSlot.getHasAssigned()) {
+ removeHomeVisitFromDateSlot(model, personList, dateSlot);
+ hasRemoveHomeVisits = true;
+ }
+ }
+ return hasRemoveHomeVisits;
+ }
+
+ private void removeHomeVisitFromDateSlot(Model model, List personList, DateSlot dateSlot) {
+ Long nurseUidNo = dateSlot.getNurseUidNo();
+ Person nurse = personList.stream().filter(p -> p.getUid().getUid().equals(nurseUidNo)).findFirst().get();
+ List