Archangel Developer Guide
- 1. Introduction
- 2. Setting up
- 3. Design
- 4. Implementation
- 5. Documentation, logging, testing, configuration, dev-ops
- 6. Appendix: Requirements
- 7. Appendix A: Instructions for manual testing
1. Introduction
1.1 Purpose
This document describes the setting up, design, implementation, documentation of Archangel.
1.2 Audience
The whole documentation is in general for anyone who wants to understand the documentation and implementation of Archangel. The following groups are the intended target of this documentation.
- CS2101/CS2103T Teaching Team - to evaluate Archangel’s software architecture, design, implementation and documentation.
- CS2103T Students - to understand Archangel’s software architecture, design, implementation and documentation in order to enhance and implement some of the features inside the software.
1.3 How to use this guide
This Developer Guide is written in a top-down manner, starting with the overall architecture of Archangel, followed by in-depth descriptions of individual features implemented.
To navigate to a specific section in this guide, you can click on individual headers in the Table of Contents at the top of this markdown document to jump to that section. Within each section, we have also provided brief introductory statements where necessary.
2. Setting up
Refer to the guide Setting up and getting started.
3. Design
3.1 Architecture
The Architecture Diagram given above explains the high-level design of Archangel. Given below is a quick overview of each component.
.puml
files used to create diagrams in this document can be found in the diagrams folder. Refer to the PlantUML Tutorial at se-edu/guides to learn how to create and edit diagrams.
Main
has two classes called Main
and MainApp
. It is responsible for,
- At app launch: Initializes the components in the correct sequence, and connects them up with each other.
- At shut down: Shuts down the components and invokes cleanup methods where necessary.
Commons
represents a collection of classes used by multiple other components.
The rest of Archangel consists of four components.
-
UI
: The UI of Archangel. -
Logic
: The command executor. -
Model
: Holds the data of Archangel in memory. -
Storage
: Reads data from, and writes data to, the hard disk.
Each of the four components,
- defines its API in an
interface
with the same name as the Component. - exposes its functionality using a concrete
{Component Name}Manager
class (which implements the corresponding APIinterface
mentioned in the previous point.
For example, the Logic
component (see the class diagram given below) defines its API in the Logic.java
interface and exposes its functionality using the LogicManager.java
class which implements the Logic
interface.
Diagram 3.1.1 : Logic Class Diagram
How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete 1
.
Diagram 3.1.2 : Architecture Sequence Diagram
The sections below give more details of each component.
3.2 UI component
Diagram 3.2 : UI Class Diagram
API :
Ui.java
The UI consists of a MainWindow
that is made up of parts e.g.CommandBox
, ResultDisplay
, PatientListPanel
, AppointmentListPanel
, StatusBarFooter
etc. All these, including the MainWindow
, inherit from the abstract UiPart
class.
The UI
component uses JavaFx UI framework. The layout of these UI parts are defined in matching .fxml
files that are in the src/main/resources/view
folder. For example, the layout of the MainWindow
is specified in MainWindow.fxml
The UI
component,
- Executes user commands using the
Logic
component. - Listens for changes to
Model
data so that the UI can be updated with the modified data.
3.3 Logic component
Diagram 3.3.1 : Logic Class Diagram
API :
Logic.java
-
Logic
uses theAddressBookParser
class to parse the user command. - This results in a
Command
object which is executed by theLogicManager
. - The command execution can affect the
Model
(e.g. adding a patient). - The result of the command execution is encapsulated as a
CommandResult
object which is passed back to theUi
. - In addition, the
CommandResult
object can also instruct theUi
to perform certain actions, such as displaying help to the user.
Given below is the Sequence Diagram for interactions within the Logic
component for the execute("delete 1")
API call.
Diagram 3.3.2 : Delete Sequence Diagram
DeleteCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
3.4 Model component
Diagram 3.4 : Model Class Diagram
API : Model.java
The Model
,
- stores a
UserPref
object that represents the user’s preferences. - stores Archangel’s data.
- exposes an unmodifiable
ObservableList<Patient>
that can be ‘observed’ e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. - does not depend on any of the other three components.
Tag
list in the AddressBook
, which Patient
references. This allows AddressBook
to only require one Tag
object per unique Tag
, instead of each Patient
needing their own Tag
object.3.5 Storage component
Diagram 3.5 : Storage Class Diagram
API : Storage.java
The Storage
component,
- can save
UserPref
objects in json format and read it back. - can save Archangel’s data in json format and read it back.
3.6 Common classes
Classes used by multiple components are in the seedu.addressbook.commons
package.
4. Implementation
As the previous Design section illustrated the general architecture of the app, this section aims to illustrate what happens at the deeper levels. This section describes some noteworthy details on how certain features are implemented.
4.1 Patient Commands
4.1.1 Before we dive in
It is important to know the architectural design of the app to be able to understand this section. Please ensure that you have read section 3.3 Logic components before diving deeper into this section as most implemented features make use of the same principles.
4.1.2 Structure of Patient Commands
The following diagram shows the overview of a generic patient command PatientXYZCommand
, where XYZ
could be Add
, Delete
etc. :
Diagram 4.1.2 : Patient Command Structure Diagram
In each PatientXYZCommand
class, there are static messages as follows:
-
COMMAND_WORD
- String denoting the command wordParser
will check for to determine which type of command user input should invoke. -
MESSAGE_USAGE
- String containing a input guide message for when user inputs are in incorrect formats.
4.1.3 Add Patient
Implementation
The Add patient command has a highly similar logic and implementation as a Delete patient command (see Diagram 4.1.2 and 3.3.2).
The only notable difference is that an Add patient command does not require parsing of an Index
. (i.e. parse("1")
is not applicable)
</br>On execution, the Patient
object stored in the PatientAddCommand
object will be added to the Model.
4.1.4 Delete Patient
Implementation
The arguments of a Delete patient command includes the Index
of the Patient to be deleted (see Diagram 4.1.2 and 3.3.2). </br>
On execution, the Index
object stored in the PatientDeleteCommand
object will be used to locate the Patient
object to be deleted from the Model.
4.1.5 Edit Patient
Diagram 4.1.5 : PatientEditCommand Sequence Diagram
Implementation
With reference to Diagram 4.1.5 above, the arguments of an Edit patient command includes the Index
of the Patient selected for changes and the changes
the User wants to make to the individual fields of a single Patient
. </br>
What happens at EditCommandParser().parse(arguments)
:
- An
EditPatientDescriptor
object is first created. AnEditPatientDescriptor
object contains all fields that aPatient
has and acts as a placeholder for the changes. - For each field input present in the argument, that respective field of the
EditPatientDescriptor
object will be set accordingly. PatientFindCommand This object contains theIndex
of thePatient
selected for changes, and theEditPatientDescriptor
object created in Step 1 and fully modified by Step 2. - This
PatientEditCommand
object will stored under thecommand
variable and then be executed by theLogicManager
. - At execution, an
editedPatient
object will be created. ThiseditedPatient
object contains all fields that a Patient has and acts as a placeholder for both the changes from theEditPatientDescriptor
object and unchanged fields of the originalPatient
. - Since the
editedPatient
object will contain the corrected set of fields to be reflected on the original Patient, thePatientEditCommand
will replace the currentPatient
object with theeditedPatient
object.
This is how Editing of Patient information is implemented.
4.1.6 Find Patient
Implementation
The arguments of a Find patient command includes the Keywords
that the User wants to search up. Keywords
are seperated by spaces.
What happens at FindCommandParser().parse(arguments)
:
-
Keywords
are put into annameKeywords
array. - A new
SearchNameFilter
object is created with thenameKeywords
array converted to a List. - A new
PatientFindCommand
object is created with theSearchNameFilter
object, and it is then returned to theLogicManager
for execution. - At execution, a list filtered with only those that are related to the
Keywords
is shown.
This is how Find Patient is implemented.
4.2 Appointment Commands
In this section, we will introduce all Appointment-type commands and how they work.
Due to similar implementation of Appointment-type and Patient-type commands
(e.g. p-edit
and a-edit
make use of the same logic), we will be referring to the patient-type counterpart of the same command where applicable.
Any noteworthy details will still be included under each Appointment-type command below.
4.2.1 Schedule Appointment
4.2.1.1 Implementation
The implementation of scheduling an appointment has a similar execution as adding a patient (see 4.1.3). Take note that backdated appointments are allowed (i.e. appointments scheduled before current time) to be able to digitise existing appointment records from clinics.
The Appointment
class stores relevant fields (e.g. AppointmentTime
, Description
) and the Patient
, and/or a string representing the patient’s index in the ObservableList<Patient>
, depending on which constructor is invoked during execution.
4.2.1.2 Reason for design of implementation:
Diagram 4.2.1.2 : AppointmentScheduleCommand Activity Diagram
The reason for having 2 Appointment
constructors is to improve the ease of scheduling an appointment by the user using the CLI.
To address the problem of mandatory fields being highly time-consuming, we have decided to allow users to simply input a patientIndex
to identify the patient from the visible ObservableList<Patient>
without being concerned with typing the exact name or details of the desired patient to assign to the Appointment
.
4.2.1.3 Design consideration:
Aspect: How Patient
is stored in an Appointment
object
-
Alternative 1 (current choice): Saves the
Patient
object and/or thepatientIndex
String- Pros:
- Easy to implement, gives a less stringent check for
isSameAppointment
for other Appointment-type commands (e.g.AppointmentEditCommand
). - This allows for creation of
Appointment
objects which are not duplicates yet have the samePatient
and/orpatientIndex
during command execution.
- Easy to implement, gives a less stringent check for
- Cons: More test cases necessary to ensure that
patientIndex
is correctly parsed and retrieved from patient list inAddressBook
.
- Pros:
-
Alternative 2: Saves only the
Patient
object after parsing thepatientIndex
String- Pros: No extra parsing/handling of
Patient
onceAppointment
object has been created. - Cons: Difficult to edit the patient-field in an
Appointment
object as all fields of thePatient
object itself must be present.
- Pros: No extra parsing/handling of
4.2.2 Delete Appointment
Implementation
The implementation of deleting an appointment has a similar execution as deleting a patient (see 4.1.4).
4.2.3 Edit Appointment
4.2.3.1 Implementation
The implementation of editing an appointment has a similar execution as editing a patient (see 4.1.5). Take note that backdated appointments are allowed to be able to digitise existing appointment records from clinics .
4.2.3.2 Reason for design of implementation:
The reason for having an EditAppointmentDescriptor
is to enforce immutability by always creating the edited appointment as a new Appointment
object.
4.2.3.3 Design consideration:
Aspect: How Patient
is edited in an Appointment
object
-
Alternative 1 (current choice): Edits the
Patient
in theAppointment
using apatientIndex
String (e.g.a-edit 1 pt/2
)- Pros: Easy for users to change the patient for the appointment using a single
patientIndex
. - Cons:
patientIndex
has to be carefully parsed and retrieved from a patient list that correctly reflects the patient list on the GUI.
- Pros: Easy for users to change the patient for the appointment using a single
-
Alternative 2: Edits the
Patient
in theAppointment
bypatientName
(e.g.a-edit 1 pt/John Doe
)- Pros: None.
- Cons: Greater difficulty for users to input the new
Patient
since thepatientName
may not be unique nor accurate to an existing patient in the patient list.
4.2.4 Complete Appointment
Implementation
Sets a specified appointment as completed. The implementation of setting an appointment as completed has a similar execution as editing as appointment (see 4.2.3).
The unique classes associated to this command are :
-
AppointmentCommandParser: AppointmentCompleteCommandParser
— Creates a new AppointmentCompleteCommand object. -
AppointmentCommand: AppointmentCompleteCommand
— Identifies the specified appointment from list and passes it to ModelManager to set as completed.
4.2.5 Filter Appointment Commands
4.2.5.1 Structure
Commands involving filtering of the appointment work similarly by using filters to obtain the appointments needed. For this section, we will be exploring AppointmentFindPatientCommand
which filters Appointments containing Patients whose name includes the given user input.
The Command, Parser and Predicate in the class diagram below can be replaced by different sets of values from Diagram 4.2.5.1b.
Diagram 4.2.5.1a : Appointment Commands with Filters Class Diagram
Filter Appointment Commands including both its Parser and Predicate are listed below:
Command | Parser | Predicate | Filters List by: |
---|---|---|---|
1. AppointmentFindPatientCommand | AppointmentFindPatientCommandParser | SearchPatientFilter | Patient Name |
2. AppointmentTodayCommand | AppointmentTodayCommandParser | SearchAppointmentTodayFilter | Appointments occurring today |
3. AppointmentWeekCommand | AppointmentWeekCommandParser | SearchAppointmentWeekFilter | Appointments occurring this week |
4. AppointmentTagCommand | AppointmentTagCommandParser | SearchAppointmentTagsFilter | Appointment Tag |
5. AppointmentIsMissedCommand | AppointmentMissedCommandParser | SearchAppointmentMissedFilter | Missed Appointments |
6. AppointmentIsCompletedCommand | AppointmentIsCompletedCommandParser | SearchAppointmentCompletedFilter | Completed Appointments |
7. AppointmentListCommand | AppointmentListCommandParser | SearchAppointmentFilter | Pending Appointments |
Diagram 4.2.5.1b : Appointment Commands with Filters Class Diagram
4.2.5.2 Implementation
The search for appointment by patient name works by filtering the appointment list to show only those appointments with the given patient name.
Diagram 4.2.5.2 : Appointment Commands with Filters Sequence Diagram
The unique classes associated to AppointmentFindPatientCommand
command:
-
AppointmentFindPatientCommandParser
— Parses input arguments and creates a new AppointmentFindPatientCommand object. -
SearchPatientFilter
— Checks if the appointment contains any patient which contains any keywords form the arguments. -
AppointmentFindPatientCommand
— Applies the filter to the appointment list.
The implementation of all listing filter appointment commands have a similar execution as AppointmentFindPatientCommand
.
4.2.5.3 Design considerations
-
Alternative 1 (current choice): Store the appointments by date added.
- Pros: Easy to implement and less overhead operations when using adding appointments.
- Cons: May not be the fastest way to search for appointments.
-
Alternative 2: Store the appointments by tags and search the dates by Binary Search.
- Pros: Search operation for this is faster.
- Cons: Additional overhead every time you add an appointment as you need to know where to insert the command. You also need to update the sequence of storage file by tag every time you schedule an appointment. In addition, there might be a conflict for those appointments with more than one tags.
4.2.6 List All Appointments
_Diagram 4.2.6 : Appointment List All Command Sequence Diagram
Implementation
Listing all past and upcoming appointments from the appointment list.
The unique classes associated to this command as shown from Diagram 4.2.6 are :
-
AppointmentCommandParser: AppointmentListAllCommandParser
— Creates a new AppointmentListAllCommand object. -
AppointmentCommand: AppointmentListAllCommand
— Updates filtered appointment list to show all appointments in Archangel.
4.3 Supporting Commands
4.3.1 Undo/redo feature
Implementation
The proposed undo/redo mechanism is facilitated by UserHistoryManager
. It extends AddressBook
with an undo/redo history, stored internally in userHistory
as Stack<Pair<List<Patient>, List<Appointment>>>
. Additionally, it implements the following operations:
-
UserHistoryManager#addHistory()
— Saves the current address book state in its history. -
UserHistoryManager#undoHistory()
— Restores the previous address book state from its history. -
UserHistoryManager#redoHistory()
— Restores a previously undone address book state from its history.
These operations are exposed in the ModelManager
class as ModelManager#getUserHistoryManager()
, ModelManager#undoHistory()
and Model#redoHistory()
respectively.
Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
Step 1. The user launches the application for the first time. The UserHistoryManager
will be initialized with the initial address book user history in the stack.
Step 2. The user executes delete 5
command to delete the 5th patient in the address book. The delete
command calls UserHistoryManager#addHistory()
, causing its current history to be saved into UserHistory
in UserHistoryManager
after the delete 5
command.
Step 3. The user executes add n/David …
to add a new patient. The add
command also calls UserHistoryManager#addHistory()
, causing its current history to be saved into UserHistory
in UserHistoryManager
.
UserHistoryManager#addHistory()
, so the address book state will not be saved into the userHistoryManager
.
Step 4. The user now decides that adding the patient was a mistake, and decides to undo that action by executing the undo
command. The undo
command will call Model#undoHistory()
, which will cause call UserHistoryManager#undoHistory()
,popping the userHistory
stack, adding the current history to redoHistory
and removing the current history from UserHistory
.
AddressBook#setPatients
and AddressBook#setAppointments
will be called, modifying the AddressBook
and undo-ing the history.
Current History
has a size of 1, having only the initial history, then there are no previous AddressBook history to restore. The undo
command uses Model#canUndoAddressBook()
to check if this is the case. If so, it will return an error to the user rather
than attempting to perform the undo.
The following sequence diagram shows how the undo operation works:
UndoCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The redo
command does the opposite — it calls Model#redoHistory()
, which calls UserHistoryManager#redoHistory()
, popping the redoHistory
stack,modifying the AddressBook
and redo-ing the history.
Step 5. The user then decides to execute the command a-list
. Commands that do not modify the address book, such as a-list
, will usually not call Model#undoHistory()
or Model#redoHistory()
. Thus, the UserHistory
remains unchanged.
The following activity diagram summarizes what happens when a user executes a new command:
Reason for design of implementation:
The reason for the design of userHistory using a stack is due to the functionality of undoHistory()
. We want to be able undo the latest changes to the UniquePatientList
or UniqueAppointmentList
.
This follows the Last In,First Out(LIFO)
design which can be implementated using the stack
data structure.
A concern using this design is that the memory usage might be undesirable due to the large of memory usage needed to store every user history at each command. However, after many test runs, we concluded that the memory usage of the user history was insignificant and thus this design can be safely implememented with no drawbacks.
Design consideration:
- This command does not work with filter commands (
a-completed
,a-missed
,a-upcoming
,a-today
,a-find
,a-list
) as its implementation purpose is to assist the user in undo-ing his changes, filter commands do not make changes to the data. It also does not work withp-edit
as the design requires patient details to be accurate as of time schedule, such that the records can accurately reflect the patient’s conditions at the time of the appointment.With this concern in mind, we disabledundo
forp-edit
and the user can simply execute anotherp-edit
command to undo his changes.
Aspect: How undo & redo executes
-
Alternative 1 (current choice): Saves the entire address book.
- Pros: Easy to implement.
- Cons: May have performance issues in terms of memory usage.
-
Alternative 2: Individual command knows how to undo/redo by
itself.
- Pros: Will use less memory (e.g. for
delete
, just save the patient being deleted). - Cons: We must ensure that the implementation of each individual command are correct.
- Pros: Will use less memory (e.g. for
-
Alternative 3: Individual command is contained in a
reversible-pair-action
class. When we want toundo
, we can just call itspair command
.- Pros: Will use less memory (due to the fact that are not saving any additional data).
- Cons: Very difficult to implement, some commands might not have
pair command
(e.g foredit
, it is own pair command but pair command to call for undo is hard to implement).
4.4 Multi-threading
4.4.1 Timer Thread
Implementation
The TimerThread is a separate thread used for automatic tracking of missed appointments, and is initiated by MainApp.
Here is a summary of how the Timer Thread work:
- On initialization,
MainApp
creates an instance ofTimerThread
and calls it’srun()
method to being running the thread. - While
TimerThread
is running, it sleeps for 1 minute using theThread.sleep
method. - After sleeping,
TimerThread
will callLogicManager
’scheckNewlyMissedAppointments
, which in turn will callAddressBookParser
toparseCommand("a-new-misses"))
. -
AddressBookParser
’sparseCommand("a-new-misses")
method will create aNewMissesCommandParser
object and call itsparse()
method. - This
parse()
method mentioned above will create aAppointmentNewMissesCommand
. - The
parse()
method will return aAppointmentNewMissesCommand
object to theLogicManager
for execution. -
AppointmentNewMissesCommand
object’sexecute()
method will be called and withinModel
, everyAppointment
which end time has been passed by 30 minutes will be labelled as missed. - Steps 2 to 6 will repeat until the application is closed.
- On closing the application,
MainApp
calls theTimerThread
object’ssetStop()
method which will break the thread out of the loop.
Reason for design of implementation:
The reason for having a timer on a separate thread from the main app functionality to avoid any conflicts with the manual commands input from the user.
For ease of use, the user is not required to input any command for the TimerThread
to run.
Design consideration:
-
Alternative 1 (current choice): Refresh for new misses in 1 minute intervals.
- Pros: Less behind the scenes computation overhead, allowing for a smoother user experience.
- Cons: Appointments may be labelled missed up to a minute late. However, this is a minor inconvenience and most likely will not be noticed by the user.
-
Alternative 2: Refresh for new misses in 10 second intervals.
- Pros: Appointments will be guaranteed to be correctly labelled.
- Cons: Additional computation overhead, leading to slower application perform. This problem will be emphasized even greater as more appointments are stored.
5. Documentation, logging, testing, configuration, dev-ops
6. Appendix: Requirements
6.1 Product scope
Target user profile:
- has a need to manage a significant number of patient’s contacts/details
- has a preference to check his schedule on desktop over handwritten schedule
- has a need to store patient’s information on desktop
- prefer desktop apps over other types
- can type fast
- prefers typing to mouse interactions
- is reasonably comfortable using CLI apps
Value proposition: provide an application for psychiatrists to manage their patient’s medical information and their upcoming appointments.
6.2 User stories
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* * * |
Psychiatrist | view the appointment history of my patient | decide when I can schedule the next appointment for the patient. |
* * * |
Psychiatrist | delete full patient records | remove any irrelevant patient records |
* * * |
Psychiatrist | record details about the patient | access his/her psychotherapy progress. |
* * * |
Psychiatrist | view my patient’s medical information | access the type and dosage of medication to provide. |
* * * |
Psychiatrist | view my patient’s contact information | contact them for their appointments. |
* * * |
Psychiatrist | store my patient’s reviews/preference | alter the treatment plan to suit his preferences. |
* * |
Psychiatrist | search my appointment list by patient name | access see his progress across his appointments. |
* * |
Psychiatrist | search my appointment list by tags | see the trend of patients from similar groups. |
* * |
Psychiatrist | search my appointment list by current day | access only the appointments scheduled today. |
* * |
Psychiatrist | search my appointment list by current week | view my whole schedule this week. |
{More to be added}
6.3 Use cases
(For all use cases below, the System is Archangel
(the AddressBook) and the Actor is the user
, unless specified otherwise)
Use case: UC1 - Add a patient
MSS
- User requests to add a new patient to the list.
-
Archangel adds the patient.
Use case ends.
Extensions
-
1a. The patient already exists in the list.
-
1a1. Archangel shows duplicate patient error message.
Use case resumes at step 1.
-
-
1b. User inputs are invalid/incomplete.
-
1b1. Archangel shows an error message.
Use case resumes at step 1.
-
Use case: UC2 - Delete a patient
MSS
- User requests to list patients.
- Archangel shows a list of patients.
- User requests to delete a specific patient in the list.
-
Archangel deletes the patient.
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. The given index is invalid.
-
3a1. Archangel shows an error message.
Use case resumes at step 2.
-
Use case: UC3 - Edit a patient
MSS
- User requests to find a patient.
- Archangel shows the patient’s information.
- User requests to edit the patient’s information.
-
Archangel edits the patient’s information.
Use case ends.
Extensions
-
1a. The patient is not found.
-
1a1. Archangel shows an error message.
Use case ends.
-
-
3a. The patient is not found.
-
3a1. Archangel shows an error message.
Use case resumes at step 2.
-
-
3b. User inputs fields that are invalid/does not satisfy requirements.
-
3b1. Archangel shows an error message.
Use case resumes at step 2.
-
Use case: UC4 - Schedule a patient appointment
MSS
- User requests to schedule a patient appointment.
-
Archangel schedule the patient appointment.
Use case ends.
Extensions
-
1a. The appointment has conflict with another appointment.
-
1a1. Archangel shows an error message.
Use case resumes at step 1.
-
-
1b. The appointment’s date/timing is invalid.
-
1b1. Archangel shows an error message.
Use case resumes at step 1.
-
-
1c. The patient to be added to the appointment does not exist.
-
1c1. Archangel shows an error message.
Use case resumes at step 1.
-
Use case: UC5 - Delete a patient appointment
MSS
- User requests to delete a specific appointment in the list.
-
Archangel deletes the appointment.
Use case ends.
Extensions
-
1a. The appointment does not exist.
-
1a1. Archangel shows an error message.
Use case resumes at step 1.
-
-
1b. The appointment list is empty.
-
1a1. Archangel shows an error message.
Use case resumes at step 1.
-
Use case: UC6 - Edit an appointment
MSS
- User requests to edit the appointment’s information.
-
Archangel edits the appointment’s information.
Use case ends.
Extensions
-
1a. The appointment is not found.
-
1a1. Archangel shows an error message.
Use case ends.
-
-
1b. User inputs fields that are invalid/does not satisfy requirements.
-
1b1. Archangel shows an error message.
Use case resumes at step 1.
-
Use case: UC7 - Complete an appointment
MSS
- User requests to set an appointment as completed.
-
Archangel sets the appointment as completed.
Use case ends.
Extensions
-
1a. The appointment is not found.
-
1a1. Archangel shows an error message.
Use case ends.
-
-
1b. The appointment list is empty.
-
1a1. Archangel shows an error message.
Use case resumes at step 1.
-
Use case: UC8 - Filter appointment list to find the upcoming appointments
MSS
- User requests to view only upcoming appointments.
-
Archangel displays only upcoming appointments in the dashboard.
Use case ends.
Extensions
-
1a. User chose to view in the calendar tab.
-
1a1. Archangel shows the upcoming appointments in calendar format.
Use case ends.
-
Use case: UC9 - Filter appointment list to find the appointments occuring today This case is similar to UC8, without the Extensions.
Use case: UC10 - Filter appointment list to find tagged appointments
MSS
- User requests to view only tagged appointments with their input keywords.
-
Archangel displays tagged appointments matching the keywords
Use case ends.
Extensions
-
1a. The keywords did not match any tags.
-
1a1. Archangel was not able to list down any appointments.
Use case ends.
-
Use case: UC11 - Filter appointment list by patients This case is similar to UC10, with the filter being the patient name.
Use case: UC12 - Undo command
MSS
- User requests to undo a previous command.
-
Archangel reverts back to state before previous command.
Use case ends.
Extensions
-
1a. User has not executed any undo-able commands.
-
1a1. Archangel shows an error message.
Use case ends.
-
Use case: UC13 - Redo command
MSS
- User requests to redo a command that was undone.
-
Archangel reverts back to state before undo command.
Use case ends.
Extensions
-
1a. User has not undone any command.
-
1a1. Archangel shows an error message.
Use case ends.
-
Use case: UC14 - Close Archangel program
MSS
- User finishes using Archangel program.
-
User closes the program.
Use case ends.
Extensions
-
1a. The user does not close the program using the correct command/action.
-
1a1. Archangel continues to run.
Use case ends.
-
6.4 Non-Functional Requirements
- Should work on any mainstream OS as long as it has Java
11
or above installed. - Should be able to hold up to 1000 patients without a noticeable sluggishness in performance for typical usage.
- A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
- Should be able to schedule up to 100 appointments per patient without a noticeable sluggishness in performance for typical usage.
{More to be added}
6.5 Glossary
- Mainstream OS: Windows, Linux, Unix, OS-X
7. Appendix A: Instructions for manual testing
Given below are instructions to test the app manually.
7.1 Launch and shutdown
-
Initial launch
-
Download the jar file and copy into an empty folder
-
Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
-
-
Saving window preferences
-
Resize the window to an optimum size. Move the window to a different location. Close the window.
-
Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-
-
{ more test cases … }
7.2 Deleting a patient
-
Deleting a patient while all patients are being shown
-
Prerequisites: List all patients using the
list
command. Multiple patients in the list. -
Test case:
delete 1
Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated. -
Test case:
delete 0
Expected: No patient is deleted. Error details shown in the status message. Status bar remains the same. -
Other incorrect delete commands to try:
delete
,delete x
,...
(where x is larger than the list size)
Expected: Similar to previous.
-
-
{ more test cases … }
7.3 Saving data
-
Dealing with missing/corrupted data files
- {explain how to simulate a missing/corrupted file, and the expected behavior}
-
{ more test cases … }
8. Appendix B: Effort
8.1 Difficulty Level
Archangel is a brown-field project that has modified and improved features from the original AB3. Our Archangel project implements features for 2 main entities/models, namely Appointments and Patients. The inclusion of the Appointment model has increased the functionality and difficulty of the project compared to AB3 which only had Persons. Additionally, our team also explored the use of other external features such as iCalendarAgenda to improve the usability of our application.
8.2 Challenges Faced
As more features were implemented, we faced challenges that arose from the dependencies between the Appointment and Patient classes in order to make Archangel’s functionalities more user-centric and convenient for users (e.g. Deleting a patient also results in deletion of Appointment to reduce obsolete data). Many of the bugs we encountered at the beginning of the project were also due to unfamiliarity with the code base, but as time went by, identified bugs have been resolved to result in the Archangel application today.
9. Acknowledgments
9.1 Code Related
- Implementation of Calendar feature using iCalendarAgenda Credits to Tae Kwon from CS2103T-W11-4 for sharing his code base and knowledge of iCalendarAgenda.
- Implementation of Tabs in the UI is inspired by KeepToo Youtube Channel