This project is based on the AddressBook-Level3 project created by the SE-EDU initiative.
Refer to the guide Setting up and getting started.
The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
Main components of the architecture
Main (consisting of classes Main and MainApp) is in charge of the app launch and shut down.
The bulk of the app's work is done by the following four components:
UI: The UI of the App.Logic: The command executor.Model: Holds the data of the App in memory.Storage: Reads data from, and writes data to, the hard disk.Commons represents a collection of classes used by multiple other components.
How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete 1.
Each of the four main components (also shown in the diagram above),
interface with the same name as the Component.{Component Name}Manager class (which follows the corresponding API interface mentioned in the previous point.For example, the Logic component defines its API in the Logic.java interface and implements its functionality using the LogicManager.java class which follows the Logic interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component's being coupled to the implementation of a component), as illustrated in the (partial) class diagram below.
The sections below give more details of each component.
The API of this component is specified in Ui.java
The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, PersonListPanel, StatusBarFooter etc. All these, including the MainWindow, inherit from the abstract UiPart class which captures the commonalities between classes that represent parts of the visible GUI.
The UI component uses the 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,
Logic component.Model data so that the UI can be updated with the modified data.Logic component, because the UI relies on the Logic to execute commands.Model component, as it displays Person object residing in the Model.API : Logic.java
Here's a (partial) class diagram of the Logic component:
The sequence diagram below illustrates the interactions within the Logic component, taking execute("delete 1") API call as an example.
Note: The lifeline for DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram. The same goes for subsequent sequence diagrams in this guide.
How the Logic component works:
Logic is called upon to execute a command, it is passed to an AddressBookParser object which in turn creates a parser that matches the command (e.g., DeleteCommandParser) and uses it to parse the command.Command object (more precisely, an object of one of its subclasses e.g., DeleteCommand) which is executed by the LogicManager.Model when it is executed (e.g. to delete a person).Model) to achieve.CommandResult object which is returned back from Logic.Here are the other classes in Logic (omitted from the class diagram above) that are used for parsing a user command:
How the parsing works:
AddressBookParser class creates an XYZCommandParser (XYZ is a placeholder for the specific command name e.g., AddCommandParser) which uses the other classes shown above to parse the user command and create a XYZCommand object (e.g., AddCommand) which the AddressBookParser returns back as a Command object.XYZCommandParser classes (e.g., AddCommandParser, DeleteCommandParser, ...) inherit from the Parser interface so that they can be treated similarly where possible e.g, during testing.API : Model.java
The Model component,
Person objects (which are contained in a UniquePersonList object).Person objects (e.g., results of a search query and a schedule query) as a filtered patient list and a filtered and sorted appointment list which are exposed to outsiders as two separate unmodifiable ObservableList<Person> 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.UserPref object that represents the user’s preferences. This is exposed to the outside as a ReadOnlyUserPref objects.Model represents data entities of the domain, they should make sense on their own without depending on other components)API : Storage.java
The Storage component,
AddressBookStorage and UserPrefStorage, which means it can be treated as either one (if only the functionality of only one is needed).Model component (because the Storage component's job is to save/retrieve objects that belong to the Model)Classes used by multiple components are in the seedu.address.commons package.
This section describes some noteworthy details on how certain features are implemented.
The add command allows users to add new patients. The command requires:
Here is an activity diagram that summarises the key steps taken.
The AddCommandParser class is responsible for parsing user input. It uses ArgumentTokenizer to tokenize the input string, extracting:
The parser will check that the compulsory Name, ID, and Ward fields are present, and that there are no duplicate parameters included in the input string. The optional Diagnosis and Medication fields will be parsed as empty strings if they are not included in the input string.
During this parsing process:
Person instance is created to hold the relevant fields.The AddCommand class performs the following when adding a patient:
Person instance will be added to the existing patient record in the Model.The AddCommand class enforces validation rules to ensure non-duplicates and potential incorrect input fields.
ID.
Ward and ID fields. An appropriate warning will be displayed if they are present.The addnotes command allows users to add notes to a specific patient. The command requires:
Here is a sequence diagram which showcases the flow of the program as well as the key steps taken.
The AddNotesCommandParser class is responsible for parsing user input. It uses ArgumentTokenizer to tokenize the input string, extracting:
During this parsing process:
Notes instance is created to hold the note details.The AddNotesCommand class performs the following steps to add Notes to a patient:
Retrieve Patient Information:
Uses the index from the parser to locate the patient in the latest filtered list of patients.
Create New Person Instance with the Notes instance:
Notes details.Person instance, with the Notes.Replace Existing Patient Record:
The new Person instance, with the Notes, replaces the existing patient record in the Model.
Updating filtered list:
The Model will then update the filtered list of patients to show all patients.
The AddNotesCommandParser and AddNotesCommand classes enforce validation rules to ensure that valid index and notes are being passed in.
AddNotesCommandParser checks if the index is an unsigned non-zero integer.AddNotesCommand checks if the index is greater than the number of patients in the last displayed list.
AddNotesCommandParser checks if the user input for notes is empty and throws an error message stating that the user is unable to add empty notes to a patient.The makeappt command allows users to add an appointment tied to a specific patient. The command requires:
The AddAppointmentCommandParser class is responsible for parsing user input. It uses ArgumentTokenizer to tokenize the input string, extracting:
During this parsing process:
Appointment instance is created to hold the appointment details.The AddAppointmentCommand class performs the following steps to add an appointment:
Retrieve Patient Information:
Uses the index from the parser to locate the patient in the latest filtered list of patients.
Create New Person Instance with Appointment:
Appointment details.Person instance with patient information and Appointment instance.Replace Existing Patient Record:
The new Person instance, containing the Appointment, replaces the existing patient record in the Model.
The AddAppointmentCommandParser and AddAppointmentCommand classes enforce validation rules to ensure correct date formats and scheduling logic:
Format Verification:
AddAppointmentCommandParser checks if the date and time format follows dd-MM-yyyy-HH-mm.Conflict Checking:
AddAppointmentCommand checks if the new appointment overlaps with any existing appointments for the patient.The scheduledate command allows users to filter the appointments occurring on a specified date. The command requires:
The ScheduleDateCommandParser class is responsible for parsing user input. It uses ParserUtil extracting:
During this parsing process:
AppointmentContainsDatePredicate instance is created to hold the date predicate details.The ScheduleDateCommand class performs the following steps to filter the appointments:
Update filteredAppointments:
Uses the AppointmentContainsDatePredicate from the parser to update filteredAppointments in Model.
Display sortedAppointments:
sortedAppointments will be updated with the updated filteredAppointments in Model.
sortedAppointments is displayed.
The ScheduleDateCommandParser class enforces validation rules to ensure correct date format and scheduling logic:
ScheduleDateCommandParser checks if the date format follows dd-MM-yyyy.The find command allows users to search through the entire patient list and filter it based on a given field and certain keywords. The command requires:
The FindCommandParser class is responsible for parsing user input. It uses ArgumentTokenizer to tokenize the input string, extracting:
During the parsing process:
FieldContainsKeywordPredicate instance is created to hold the field and Keyword(s) details.The FindCommand class performs the following steps to filter the patient list:
Update filteredPersons:
Uses the FieldContainsKeywordPredicate from the parser to update filteredPersons in Model.
This will perform a search on the specified field for every patient, returning true if any word in the field contains any of the keyword(s) as a substring.
Display filteredPersons:
The displayed list of patients will automatically update with the new filteredPersons as it is an ObservableList.
The FindCommandParser class enforces validation rules to ensure that the input is valid:
FindCommandParser checks if there is one and only one field specified.Last edited functionalityCurrently, there is no way to tell when a patient was last edited. This information might be crucial in a healthcare setting where the healthcare professional may need to know how recent the information is.
Planned implementation
We can make it such that a Person object contains a LocalDateTime field called lastEdited that keeps track of when the Person was last updated. This field will be updated whenever a new Person is created, be it from the add command or any of the other commands that edits a Person. The lastEdited field will be displayed in the result display screen.
Currently, whenever a user enters a command that requires INDEX as a parameter, such as the view or delete command, and enters an index that is either non-positive or greater than Integer.MAX_VALUE of 2147483647, WardWatch will show the general invalid command format message followed by the command usage message.
Planned implementation
We plan to make the current invalid index message more specific and add more error messages in the case where users pass in the following invalid indexes:
The person index provided is invalid and is not specific enough. We plan to change it to The index provided does not refer to any patient in the displayed list, please check the displayed list again! which will give users a better idea of what went wrong.Integer.MAX_VALUE, the error message The index provided is greater than 2147483647 which is unfortunately not supported in our product, please try again with a smaller index! will be shown.INDEX provided must be a positive integer, please try again! will be shown.
viewappt commandCurrently, our makeappt command only allows users to create appointments with a short description. This prevents users from adding too much information to the current description which may be restrictive.
Planned implementation
We plan to separate appointment title and description which gives users more flexibility. Appointment title will just be a short description such as Surgery or Medical checkup and support a character limit of 40. Appointment description will be for additional information about the appointment that the user may want to add. The appointment description will support a much longer character limit of 300 but will not be shown in the appointment list panel as the long inputs may cause issues with the UI.
As such we will also implement a viewappt command that allows users to view all information about the appointment including the new appointment description.
Currently, some of the commands in WardWatch such as scheduleall and scheduledate are very long and may be hard to type for users.
Planned implementation
We plan to add command shortcuts for longer commands such as sAll and sDate for the commands scheduleall and scheduledate respectively. These command shortcuts will work alongside the original commands, meaning that whether the user types in sAll or scheduleall, WardWatch will recognise both as the scheduleall command.
This is so that seasoned and more advanced users have the option to optimise their workflow by utilising the command shortcuts while newer users still have the option of using the more intuitive sounding commands which reduces the learning curve.
addnotes command showing all patientsCurrently, the successful execution of an addnotes command will subsequently reset the last filtered list of patients to show all patients again. Resetting the displayed list may make it difficult for the user to confirm his/her changes.
Planned implementation
We plan to change the implementation of addnotes command such that the patient list will remain filtered after the successful addition of notes.
Currently, the checking for duplicate patient ID when creating a new patient is case-sensitive, meaning that patients with similar IDs except for the casing of letters will be considered different. For example, the IDs P12345 and p12345 will be considered different. This may increase user errors when they are searching for a specific patient.
Planned implementation
We plan to make the duplicate ID cross-checking case-insensitive such that similar IDs that differ only by casing will be considered as duplicate. This will help to reduce the room for human error when using our product.
Target user profile:
Value proposition:
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that I can… |
|---|---|---|---|
* * * | new user | see usage instructions | refer to instructions when I forget how to use the App |
* * * | doctor | add a new patient | |
* * * | doctor | delete a patient | remove entries that I no longer need |
* * * | doctor | search for patients by name or ID | quickly find and review specific patient information |
* * | doctor | hide private contact details | minimize chance of someone else seeing them by accident |
* | tech-savvy doctor | have advanced search and filter options to quickly find and organize patient information | easily manage large volumes of data |
* * * | nurse | view a patient's medication and treatment schedule, ward location and diagnosis all in one place | ensure medications are administered on time and in the correct dosage |
* * | nurse | access a list of patients I am responsible for during my shift | manage my time efficiently and ensure that all patients receive timely care |
* * * | As a detail-oriented doctor | add notes to patients | manage information about the patient |
* * * | doctor | edit my patients' information | update their conditions as they change |
* * * | forgetful doctor | receive daily reminders on the current day's appointment | avoid overlooking any important tasks or visit schedules |
* * * | doctor | make appointments for my patients | keep track of my schedule |
* * * | doctor | delete my patient's appointments | keep my schedule updated |
(For all use cases below, the System is the WardWatch and the Actor is the doctor, unless specified otherwise)
Use case: UC01 - Add a patient
MSS
Doctor submits new patient information.
WardWatch displays a success message containing information of new patient.
Use case ends.
Extensions
1a. The information entered is invalid.
1a1. WardWatch shows an invalid patient information error message.
Use case resumes at step 1.
1b. The format of the input is invalid.
1b1. WardWatch shows an invalid format error message.
Use case resumes at step 1.
Use case: UC02 - Delete a patient
Preconditions: WardWatch is displaying a non-empty list of patients.
MSS
Doctor requests to delete a specific patient from the displayed list.
WardWatch deletes the patient.
Use case ends.
Extensions
1a. Doctor request to delete invalid patient.
1a1. WardWatch shows an invalid patient message.
Use case resumes at step 1.
Use case: UC03 - Update a patient
Preconditions: WardWatch is displaying a non-empty list of patients.
MSS
Doctor submits new patient information of specific patient.
WardWatch displays information of updated patient.
Use case ends.
Extensions
1a. The information entered is invalid.
1a1. WardWatch shows an invalid patient information error message.
Use case resumes at step 1.
1b. The format of the input is invalid.
1b1. WardWatch shows an invalid format error message.
Use case resumes at step 1.
Use case: UC04 - Search a patient
MSS
Doctor searches for patients.
WardWatch shows a list of patients matching the search.
Use case ends.
Extensions
2a. Doctor tries to do an invalid search.
2a1. WardWatch shows an invalid search error message.
Use case resumes at step 1.
2b. There is no patient that matches the search.
2b1. WardWatch shows that there are no matching patients.
Use case ends.
2c. The format of the input is invalid.
2c1. WardWatch shows an invalid format error message.
Use case resumes at step 1.
Use case: UC05 - View patient
Preconditions: WardWatch is displaying a non-empty list of patients.
MSS
Doctor request to view a specific patient from the list.
WardWatch displays information about the specific patient.
Use case ends.
Extensions
1a. Doctor request to view invalid patient.
1a1. WardWatch shows an invalid patient message.
Use case resumes at step 1.
Use case: UC06 - List patients
MSS
Doctor request to list all patients.
WardWatch shows a list of all patients.
Use case ends.
Extensions
2a. The list is empty.
2a1. WardWatch shows that list is empty.
Use case ends.
Use case: UC07 - Add Appointment
MSS
Doctor submits new Appointment information for a patient.
WardWatch displays success message with the updated patient information.
Use case ends.
Extensions
1a. The information entered is invalid.
1a1. WardWatch shows an invalid Appointment information error message.
Use case resumes at step 1.
1b. The format of the input is invalid.
1b1. WardWatch shows an invalid format error message.
Use case resumes at step 1.
Use case: UC08 - Delete Appointment
Preconditions: WardWatch is displaying a non-empty list of patients.
MSS
Doctor request to delete an Appointment tied to a patient.
WardWatch deletes specified appointment.
WardWatch shows a success message.
Use case ends.
Extensions
1a. The delete appointment command format entered is invalid.
1a1. WardWatch shows an incorrect format error message.
Use case resumes at step 1.
1b. Doctor requests to delete an Appointment from an invalid patient.
1b1. WardWatch shows an invalid patient message.
Use case resumes at step 1.
1c. Doctor requests to delete a non-existing Appointment from a patient.
1c1. WardWatch shows patient does not have Appointment error message.
Use case resumes at step 1.
Use case: UC09 - Change Appointment
MSS
Doctor deletes existing Appointment(UC08).
Doctor adds new Appointment with updated details(UC07).
Use case ends.
Use case: UC10 - See Schedule for a certain day
MSS
Doctor request to see schedule for a certain day.
WardWatch shows a success message and displays all appointments for that day.
Use case ends.
Extensions
1a. The date format is invalid.
1a1. WardWatch shows an invalid date error message.
Use case resumes at step 1.
Use case: UC11 - See all Schedules
MSS
Doctor request to see schedule for all days.
WardWatch displays all appointments for all days.
Use case ends.
Extensions
1a. The schedule all command format is invalid.
1a1. WardWatch shows an error message.
Use case resumes at step 1.
Use case: UC12 - Add Notes tied to a specific patient
Preconditions: WardWatch is displaying a non-empty list of patients.
MSS
Doctor submits new Notes for a certain patient.
WardWatch displays a success message with the Patient information and the new Notes.
Use case ends.
Extensions
1a. The information entered is invalid.
1a1. WardWatch shows an invalid Patient Notes information error message.
Use case resumes at step 1.
1b. The format of the input is invalid.
1b1. WardWatch shows an invalid format error message.
Use case resumes at step 1.
Use case: UC13 - delete Notes tied to a specific patient
MSS
Doctor request to delete Notes from a specific Patient.
WardWatch deletes the Patient Notes.
Use case ends.
Extensions
1a. The delete Notes command format entered is invalid.
1a1. WardWatch shows an incorrect format error message.
Use case resumes at step 1.
1b. Doctor requests to delete Notes from an invalid patient.
1c. Doctor requests to delete non-existing Notes from a patient.
1c1. WardWatch shows Patient does not have Appointment error message.
Use case resumes at step 1.
17 or above installed.Given below are instructions to test the app manually.
Note: These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.
Initial launch
Download the .jar file and copy into an empty folder
cd into the folder and run java -jar wardwatch.jar
Expected: Shows the GUI with a set of sample contacts.
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 running the command above.
Expected: The most recent window size and location is retained.
Command: add
add n/John Doe i/P00001 w/A1 d/Type 1 Diabetes m/MetforminJohn DoeP00001A1Type 1 DiabetesMetformin-- add n/Kathy Prince i/P00002 w/D1 d/GastritisKathy PrinceP00002D1Gastritis--- add n/Joshua Lim i/P00003 w/C3 m/ParacetemolJoshua LimP00003C3-Paracetemol-- add n/Emily Tan i/P00004 w/B2Emily TanP00004B2---- Command: edit
edit 1 n/Jeff Bean i/P10000 w/G5 d/influenza m/paracetomolJeff BeanP10000G5influenzaparacetomoledit 1 n/Samuel LeeSamuel Leeedit 1 i/P20001 w/C1P20001C1edit 1 d/Bronchitis m/Amoxicillin w/D2D2BronchitisAmoxicillinCommand: delete
delete 1delete 0delete, delete x (where x is larger than the list size)Command: find
find n/Emily TanEmily or Tan as a substring.
find i/P00001P00001 as a substring.
find w/A1A1 as a substring.
find d/DiabetesDiabetes as a substring.
find m/MetforminMetformin as a substring.
Command: view
view 1Command: addnotes
addnotes 1 pn/patient prone to falling patient prone to fallingaddnotes 1 pn/Command: delnotes
delnotes 1-delnotes 1Command: makeappt
makeappt 1 a/ Surgery s/ 01-01-2024-20-00 e/ 01-01-2024-23-00Surgery FROM 01 January 2024, 08:00 pm TO 01 January 2024, 11:00 pm makeappt 1 a/ Checkup s/ 02-01-2024-20-00 e/ 02-01-2024-23-00Appointment overlaps with another pre-existing appointment! Please check your schedule and try again Command: delappt
delappt 1- delappt 1The Patient indicated does not have an appointment Command: scheduledate
scheduledate 01-01-2024scheduledate 02-01-20240 appointment(s) on 02 January 2024 listed and the appointments list shows no appointments.
Command: scheduleall
scheduleallDisplayed all appointments and the appointment list will show all appointments.
This section presents an overview of the work invested by our team in developing WardWatch. We will discuss the complexity and scope, obstacles encountered, and effort required to bring this project to completion.
WardWatch expands on the Person entity originally found in AB3 by adding new entities, such as Appointment and Medication, to meet healthcare-specific demands. These additions introduced new requirements for feature interactions, data management, and storage, which proved more intricate than initially expected.
Beyond adapting AB3’s original features to better fit our target users, WardWatch introduces numerous commands to enhance the application’s usability, particularly for managing patient information and healthcare operations. Integrating these features smoothly with existing functionality demanded considerable attention to detail.
While each of us contributed fewer lines of code than in individual assignments, the group project required substantial coordination and teamwork. This collaboration was essential to ensure cohesive integration and functionality across all new features.
New Patient Data Fields
To meet the requirements of a healthcare management application, additional fields—such as diagnosis, medications, notes, and appointments were incorporated to provide a more comprehensive patient profile.
Enhanced Search Capabilities
Our team upgraded the find command from AB3 to offer greater flexibility, allowing searches by not only name but also fields like diagnosis and medications. The enhanced find feature also enables filtering by specific criteria, which involved a full redesign of the search logic and thorough testing.
User Interface (UI) Enhancements
We revamped the interface to align with WardWatch’s new features and a healthcare-oriented theme. Additionally, the UI logic was refined to enable future developers to make changes with ease.
Appointment Tracking
The appointment tracking features represent one of the most significant additions, necessitating major changes to existing structures and multiple new commands to manage appointment schedules. This feature was the most complex and required a substantial effort to coordinate data interactions across various entities. We also had to factor in creating the class AppointmentContainsDatePredicate that implements Predicate
Appointments Scheduling
Appointments scheduling was another big change we made for our application. It required a thorough understanding of storage management and the Java libraries such as LocalDateTime and ObservableList, etc.
Notes
Our team introduced Notes management commands, such as addnotes and delnotes, which involved creating new classes to support the Notes field and commands. We also took additional steps to ensure compatibility with existing command functionality.
Understanding the AB3 Codebase
One major hurdle was grasping the existing AB3 codebase, including the structure, class dependencies, and functionality. This required us to carefully analyze how existing features would interact with our additions, which took considerable time and planning.
Data Interaction Between New and Existing Entities
Linking new entities like Appointment with the Person entity required a thoughtful approach. We needed to create a clear data structure to maintain relationships without introducing dependencies that could hinder usability.
UI Space Constraints
Designing a user-friendly interface within limited screen space was a significant challenge. We needed to balance providing sufficient information with maintaining a streamlined layout. After several iterations, we finalized a design that offers essential data without cluttering the interface.
Implementation of new fields
The addition of new fields such as diagnosis and medication functionalities were more intricate than anticipated. These features required careful planning to account for various scenarios, recognising the balance between restricting the user input to overstricting. Regular discussions helped to streamline our ideas tasks and address any arising issues efficiently.
Implementation of Appointments
In particular, we faced difficulties when attempting to implement the schedule as an ObservableList<Person> as it not only had to be filtered, but also had to be sorted. Having to understand the API of ObservableList provided by JavaFX was challenging. We also had to factor in creating the class AppointmentContainsDatePredicate that implements Predicate<Person> such that the list can actually be filtered, which brought about additional complexity.
Data Management Strategy
Deciding on a data management structure for appointments and medications presented additional challenges. We carefully considered how to balance the storage of patient data within main entities or across relevant contexts.
Debugging and Testing
Testing and debugging were crucial for ensuring a stable and smooth experience for users. While unit testing was straightforward, identifying edge cases was challenging. Rigorous testing was essential to guarantee proper error handling and avoid application crashes due to unexpected inputs.
In conclusion, our team manged to design and implement features, addressed bugs, and managed potential integration issues. Although we faced initial difficulties with complex features like appointment and management, collaboration enabled us to overcome these obstacles, ultimately achieving our goals for WardWatch.