Developer Guide
MedInfo is a desktop application that empowers clinics and hopitals to manage their patients.
This Developer Guide provides an in-depth documentation on how MedInfo is designed and implemented. It covers the architecture of MedInfo and provides detailed descriptions regarding the implementation design.
You can use this guide to maintain, upgrade, and evolve MedInfo.
Table of contents
- Getting Started
- Design
- Implementation
- Appendix: Requirements
- Appendix: Instructions for Manual Testing
- Appendix: Planned Enhancements
Setting up, getting started
Refer to the guide Setting up and getting started.
Design
 Tip: The
 Tip: The .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.
Architecture

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 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 the App consists of 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.
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),
- defines its API in an interfacewith the same name as the Component.
- implements its functionality using a concrete {Component Name}Managerclass (which follows the corresponding APIinterfacementioned 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.
UI 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,
- executes user commands using the Logiccomponent.
- listens for changes to Modeldata so that the UI can be updated with the modified data.
- keeps a reference to the Logiccomponent, because theUIrelies on theLogicto execute commands.
- depends on some classes in the Modelcomponent, as it displaysPersonobject residing in theModel.
Logic component
API : Logic.java
Here’s a (partial) class diagram of the Logic component:

How the Logic component works:
- When Logicis called upon to execute a command, it uses theMedInfoParserclass to parse the user command.
- This results in a Commandobject (more precisely, an object of one of its subclasses e.g.,AddCommand) which is executed by theLogicManager.
- The command can communicate with the Modelwhen it is executed (e.g. to add a patient).
- The result of the command execution is encapsulated as a CommandResultobject which is returned back fromLogic.
The Sequence Diagram below illustrates the interactions within the Logic component for the execute("delete 1") API call.

 Note: The lifeline for
 Note: The lifeline for DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
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:
- When called upon to parse a user command, the MedInfoParserclass creates anXYZCommandParser(XYZis a placeholder for the specific command name e.g.,AddCommandParser) which uses the other classes shown above to parse the user command and create aXYZCommandobject (e.g.,AddCommand) which theMedInfoParserreturns back as aCommandobject.
- All XYZCommandParserclasses (e.g.,AddCommandParser,DeleteCommandParser, …) inherit from theParserinterface so that they can be treated similarly where possible e.g, during testing.
Model component
API : Model.java

The Model component,
- stores the address book data i.e., all Personobjects (which are contained in aUniquePersonListobject).
- stores the currently ‘selected’ Personobjects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiableObservableList<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.
- stores a UserPrefobject that represents the user’s preferences. This is exposed to the outside as aReadOnlyUserPrefobjects.
- does not depend on any of the other three components (as the Modelrepresents data entities of the domain, they should make sense on their own without depending on other components)
Storage component
API : Storage.java

The Storage component,
- can save both address book data and user preference data in json format, and read them back into corresponding objects.
- inherits from both MedInfoStorageandUserPrefStorage, which means it can be treated as either one (if only the functionality of only one is needed).
- depends on some classes in the Modelcomponent (because theStoragecomponent’s job is to save/retrieve objects that belong to theModel)
Common classes
Classes used by multiple components are in the seedu.medinfo.commons package.
Implementation
This section describes some noteworthy details on how certain features are implemented in MedInfo.
Adding a patient
In MedInfo, a user can add a patient using the add command.
Implementation
- The addcommand takes in 2 compulsory fields (name and NRIC) and 1 optional field (status)
- It is supported by the AddCommandParserthat extracts the relevant fields from the entered command.
The following activity diagram summarizes what happens when a user enters an add command:

Details:
- The user enters an addcommand with the name and NRIC specified.
- If the user entered a Status(prefixed bys/), the patient created will have that status.
- The created patient is added to the model.
Adding a ward
In MedInfo, a user can add a patient using the addward command.
Implementation
- The addcommand takes in 1 compulsory field (ward name) and 1 optional field (capacity)
- It is supported by the AddWardCommandParserthat extracts the relevant fields from the entered command.
The following activity diagram summarizes what happens when a user enters an addward command:

Details:
- The user enters an addwardcommand with the ward name specified.
- If the user entered a Capacity(prefixed byc/), the ward created will have that capacity.
- The created ward is added to the model.
Editing a patient
In MedInfo, a user can edit a patient using the edit command.
Implementation
- The editcommand takes in 1 compulsory argument (index) and up to 3 optional fields (status, ward and discharge date).
- It is supported by the EditCommandParserthat extracts the relevant fields from the entered command.
The following activity diagram summarizes what happens when a user enters an edit command:

Details:
- The index is based on the last displayed list of patients. This design choice was made as:
    - A user would most likely perform a findorlistoperation to confirm the patient to edit.
- Finding patient by NRIC would be too cumbersome for the user.
 
- A user would most likely perform a 
- Name and NRIC are not editable as these are identifying fields of a patient.
Deleting a patient
In MedInfo, a user can edit a patient using the delete command.
Implementation
- The deletecommand takes in 1 compulsory argument (index).
- It is supported by the DeleteCommandParserthat extracts the index from the entered command.
The following activity diagram summarizes what happens when a user enters a delete command:

Details:
- When a user executes this command, they are greeted with an alert window to confirm deletion.
    - Clicking ‘OK’ at this point will let MedInfo proceed with the deletion.
- Clicking ‘Cancel’ or closing the window will abort the deletion and trigger a listoperation.
 
- Aborting a deletion leads to a listoperation so that the user can view all patients.
- The index is based on the last displayed list of patients. This design choice was made as:
    - A user would most likely perform a findorlistoperation to confirm the patient to delete.
- Finding patient by NRIC would be too cumbersome for the user.
 
- A user would most likely perform a 
Finding patients
In MedInfo, a user can find patients matching certain conditions using the find command.
Implementation
- The findcommand takes in 1 compulsory field (one of either name, NRIC or status).
- It is supported by the FindCommandParserwhich extracts one of the possible fields:- Name entered in the command (prefixed by name/)
- NRIC entered in the command (prefixed by nric/)
- Status entered in the command (prefixed by s/)
 
- Name entered in the command (prefixed by 
- If the user enters multiple fields, MedInfo highlights the error to the user.
The following activity diagram summarizes what happens when a user enters a find command:

List all patients
In MedInfo, a user can list all patients using the list command.
Implementation
- The listcommand does not take in any arguments.
The following activity diagram summarizes what happens when a user enters a find command:

[Proposed] Data archiving
{Explain here how the data archiving feature will be implemented}
Documentation, logging, testing, configuration, dev-ops
Appendix: Requirements
Target user profile
- has a need to manage a significant number of patients coming into an A&E in a private hospital
- can type fast
- prefers typing to execute commands and allocating patients by their status to their respective wards
- is reasonably comfortable using CLI apps
Value proposition
- solve the problem of slow and multiple step process of allocating patients to their respective wards in an A&E
- provide faster access to a particular patient’s details for hospital admin staff
- provide a more efficient process of managing patients by their status to cater to patients who are in urgent need of care, which in turn provides a better quality of service
- provide a simple system to keep track and update a patient’s discharge date
User stories
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that I can… | 
|---|---|---|---|
| * * * | staff member | add a patient | record more information later | 
| * * * | staff member | add a ward | assign patients to the ward later | 
| * * * | staff member | add personal particulars to a patient | record their name and NRIC | 
| * * * | staff member | add current status of patient | keep track of patient status | 
| * * * | staff member | add current ward of patient | keep track of patient location | 
| * * * | staff member | add a discharge date to hospitalised patients | keep track of discharge dates | 
| * * * | staff member | view the list of commands | use the system proficiently | 
| * * * | staff member | search for patients by personal particulars | do a basic search to find a certain patient | 
| * * * | staff member | search for patients by discharge date | plan for future patient discharges | 
| * * * | staff member | update personal particulars of a patient | keep the personal particulars of a patient up to date | 
| * * * | staff member | update patient ward | move patients to different wards | 
| * * * | staff member | update the status of a patient | keep the status of a patient up to date | 
| * * * | staff member | update the discharge date of hospitalised patients | change the discharge date of a hospitalised patient due to unexpected medical complications | 
| * * * | staff member | remove a patient | put the patient on hold or remove duplicate entries | 
| * * * | staff member | remove the discharge date of a patient | put the patient’s discharge date on hold while awaiting further assessment | 
| * * | staff member | view the list of patients sorted by discharge date | plan for future patient discharges | 
| * * | staff member | see patients with approaching discharge dates | be aware of approaching discharge patients | 
| * * | staff member | view patients by ward | find patients in a ward and check the occupancy within certain wards | 
| * * | staff member | view patients by status | address higher priority patients more quickly | 
| * * | staff member | view list of wards | see current wards in system at a glance | 
| * * | staff member | view list of patients | see current patients in system at a glance | 
| * * | staff member | update the name of a ward | keep the name of a ward up to date | 
| * * | staff member | update the capacity of a ward | keep the maximum number of patients in a ward up to date | 
| * * | staff member | view the current total occupancy | see the total number of patients currently admitted | 
| * * | staff member | view the total capacity of a ward | see the maximum number of patients I can admit to this ward | 
| * * | staff member | view the current occupancy of a ward | see the number of patients currently admitted to a ward, and to know if a ward is full | 
| * * | staff member | confirm a deletion of a patient | avoid accidentally deleting a patient, which cannot be undone | 
Use cases
(For all use cases below, the System is the MedInfo and the Actor is the user, unless specified otherwise)
Use case: UC01 - Add a patient
MSS
- User requests to add a new patient to MedInfo.
- The user enters patient details.
    - The following are required information:
        - Name
- NRIC
 
- The following are non-required information:
        - Status
- Ward
 
 
- The following are required information:
        
- The system adds the user into the MedInfo system.
- 
    The system shows the new created user in the patient list. Use case ends. 
Extensions
- 
    2a. If any of the required fields are not completed. - 2a1. the user is informed of this and show the correct format for the command
 
Use case resumes at step 2.
- 
    2b. If the entered NRIC is already present in another record in the system. - 2b1. the user is informed that the NRIC is already present in the system.
 Use case resumes at step 2. 
- 
    2c. If the input field is invalid. - 2c1. the user is informed of this, and correct format for the command is displayed.
 Use case resumes at step 2. 
- 
    2d. If the entered ward is not present in the system. - 2d1. the user is informed that the ward does not exist in the system.
 Use case resumes at step 2. 
Use case: UC02 - Delete a patient
MSS
- User requests to list filtered patients
- MedInfo shows a list of filtered patients
- User requests to delete a specific patient in the list by index number
- MedInfo shows confirmation window
- 
    MedInfo deletes the patient Use case ends. 
Extensions
- 
    2a. The list is empty. Use case ends. 
- 
    3a. The requested patient’s index number is invalid. - 
        3a1. MedInfo shows an error message. Use case resumes at step 2. 
 
- 
        
- 
    4a. The user cancels the deletion in the confirmation window - 
        4a1. MedInfo shows the patient list 
- 
        4b1. MedInfo shows an error message. Use case resumes at step 2. 
 
- 
        
Use case: UC03 - Edit a patient
MSS
- User requests to list filtered patients
- MedInfo shows a list of filtered patients
- User requests to edit a specific patient in the list by index number
    - The following can be edited:
        - Status
- Ward
- Discharge Date
 
- The following cannot be edited:
        - Name
- NRIC
 
 
- The following can be edited:
        
- 
    MedInfo edits the patient Use case ends. 
Extensions
- 
    2a. The list is empty. Use case ends. 
- 
    3a. The requested patient’s index number is invalid. - 
        3a1. MedInfo shows an error message. Use case resumes at step 2. 
 
- 
        
- 
    3b. The prefixes entered are invalid. - 
        3b1. MedInfo shows an error message. Use case resumes at step 2. 
 
- 
        
- 
    3b. The Status entered is invalid. - 
        3b1. MedInfo shows an error message. Use case resumes at step 2. 
 
- 
        
- 
    3b. The Ward entered is invalid. - 
        3b1. MedInfo shows an error message. Use case resumes at step 2. 
 
- 
        
- 
    3b. The Discharge Date entered is invalid. - 
        3b1. MedInfo shows an error message. Use case resumes at step 2. 
 
- 
        
- 
    3d. User tries to edit a non-editable field (Name/NRIC). - 
        3d1. MedInfo shows an error message. Use case resumes at step 2. 
 
- 
        
Use case: UC04 - Find a patient
MSS
- User requests to find specific patients by either NRIC or Name or Status or Ward
- 
    MedInfo shows a list of patients Use case ends. 
Extensions
- 
    1a. The requested patient’s NRIC does not exist in the system. - 
        1a1. MedInfo does not list any patients. Use case ends. 
 
- 
        
- 
    1b. The requested patient’s Name does not exist in the system. - 
        1b1. MedInfo does not list any patients. Use case ends. 
 
- 
        
- 
    1c. The requested patient’s Status does not exist in the system. - 
        1c1. MedInfo does not list any patients. Use case ends. 
 
- 
        
- 
    1d. The requested patient’s Ward does not exist in the system. 
- 
    1d1. MedInfo does not list any patients. Use case ends. 
Use case: UC05 - Clear all patients
MSS
- User requests to clear all the patient records in the system
- MedInfo shows confirmation window
- 
    MedInfo deletes all patients in the system Use case ends. 
- 3a. The user cancels the deletion in the confirmation window
    - 3a1. MedInfo shows the patient list
 
Use case: UC06 - Add a new ward
MSS
- User requests to add a new ward to MedInfo.
- The user enters ward details.
    - The following are required information:
        - Name
 
- The following are non-required information:
        - Capacity
 
 
- The following are required information:
        
- The system adds the ward into the MedInfo system.
- 
    The system shows the new created ward in the ward list. Use case ends. 
Extensions
- 
    2a. If any of the required fields are not completed. - 2a1. the user is informed of this and show the correct format for the command
 
Use case resumes at step 2.
- 
    2b. If the entered Name is already present in another record in the system. - 2b1. the user is informed that the Name is already present in the system.
 Use case resumes at step 2. 
- 
    2c. If the input field is invalid. - 2c1. the user is informed of this, and correct format for the command is displayed.
 Use case resumes at step 2. 
Use case: UC07 - Delete a ward
MSS
- User requests to list wards
- MedInfo shows a list of wards
- User requests to delete a specific ward in the list by index number
- MedInfo shows confirmation window
- 
    MedInfo deletes the patient Use case ends. 
Extensions
- 
    2a. The ward list is empty. Use case ends. 
- 
    3a. The requested ward’s index number is invalid. - 
        3a1. MedInfo shows an error message. Use case resumes at step 2. 
 
- 
        
- 
    3b. The requested ward has patients inside - 3b1. MedInfo shows an error message.
 Use case resumes at step 2. 
- 
    4a. The user cancels the deletion in the confirmation window - 
        4a1. MedInfo shows the patient list Use case resumes at step 2 
 
- 
        
Use case: UC08 - Sort Patients
MSS
- User requests to list patients
- MedInfo shows a list of patients
- User requests to sort all the patients by a specific order
- MedInfo sorts all the patients
- 
    MedInfo displays the sorted list Use case ends 
Extensions
- 
    - The patient list is empty
 Use case ends. 
- 3a. The requested sorting order is invalid
    - 
        3a1. MedInfo shows an error message. Use case resumes at step 2. 
 
- 
        
- 3b. The requested sorting field is invalid
    - 
        3b1. MedInfo shows an error message. Use case resumes at step 2. 
 
- 
        
Non-Functional Requirements
- Should work on any mainstream OS as long as it has Java 11or 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 mask the NRIC of patients when listing (e.g. XXXXX264G).
- The product is not required to validate the medical records.
Glossary
- Mainstream OS: Windows, Linux, Unix, OS-X
- CLI: Command Line Interface
- Use case: It describes an interaction between the user and the system for a specific functionality of the system.
- 
Priority Level: Level of seriousness of a patient’s health condition (e.g. Stable,Mild,Severe)
- Medical Record: Blood type, allergies, medical cases and history of medical conditions
Appendix: Instructions for manual testing
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.
 Note: These instructions only provide a starting point for testers to work on;
testers are expected to do more exploratory testing.
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.
 
- 
        
Delete a patient
- 
    Deleting a patient while all patients are being shown - 
        Prerequisites: List all patients using the listcommand. 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.
 
- 
        
Save data
- Dealing with missing data files
    - MedInfo will display sample data if data files cannot be found in the data directory.
 
- Dealing with corrupted data files
    - MedInfo will clear the current data if the data files are corrupted or modified invalidly.
 
Appendix: Planned Enhancements
Given below are a few enhancements we hope to bring into future iterations of MedInfo:
Date-time validation:
Currently, MedInfo allows the user to input dates in the past (e.g.01/01/1000 1000). While there may be reason to
input past date-times, such as if the user forgot to enter dates previously, MedInfo is meant to be a current
patient tracking system. As such, inputting dates from the past would not make sense as the patients would have been
discharged already (and hence have no reason to be recorded in MedInfo).
Also, MedInfo currently allows entering time in non HHmm format (e.g. ‘210.4’). This shall be looked into while
improving validation overall.
Possible Implementation:
- Future validation could be implemented by adding a method in Discharge.javato check if a given date is a valid future discharge date (by comparing to the current date)
- The method created above would then be called within parseDischarge()inParserUtil.javato ensure that a valid future discharge date-time was entered
Strict NRIC validation:
Currently, MedInfo checks whether a valid NRIC has been entered based on a validaton regex within
Nric.java (^[STFG]\d{7}[A-Z]$). This regex restricts the NRIC to be a capital letter (either
S/F/T/G) followed by 7 numbers and a capital letter. True valid NRICs make use of stronger validation
logic, involving check digits. Such validation would need to be added before using MedInfo in a
real-life scenario. However, due to the constraints it would place on testing during development,
it shall be implemented in the future instead.
UI component behaviour on window resizing
On resizing, the status bar maintains its centered location as from the full-size window. As a result, the information in it gets truncated. As this information is critical, future enhancements should address this, and other UI components that get cut off on window resizing.
Possible implementations:
- adjusting padding
- setting position constraint
- setting a higher minimum window width
Multiple parameter search
Currently, MedInfo only allows finding patients by onw of four parameters:
- name (name/)
- NRIC (nric/)
- status (s/)
- ward name (w/)
The find command does not allow multiple parameters to be used at once. For example, attempting to find critical
patients in ward ‘ER1’ with the command find s/red w/ER1 would result in an error. However, as a hospital
staff, finding patients matching multiple criteria is a valid use-case. Hence, this is planned as a future enhancement.
Find by ward
Currently, the find command in MedInfo finds patients by wards as it does patients by name, i.e. by displaying
all patients that match any of the keywords supplied. As a result, the logic is slightly flawed. Consider the
scenario of trying to find patients in a ward named ‘Class A’, when the other wards in the system include ‘Class B’
and ‘Class C’. Entering find w/Class A would also display patients in the other 2 wards due to the common keyword
‘Class’. This should be addressed in future iterations of MedInfo by making the find command match ward name
exactly.
Handling long names
Currently, long names are truncated (with ...) once they go past the maximum displayable length. This makes it
impossible to get long patient names after entry into the system. This would need to be addressed in the future.
Possible implementation:
- limit name input to 40 characters: While simple to implement (change validation regex in Name.javato[\\p{Alnum}][\\p{Alnum} ]{0,39}, it is not recommended, as it does not handle the case of patients with names longer than 40 characters
- text wrapping to display the whole name within the patient card in the UI
Expand help command
Currently, entering the help command in MedInfo opens a small dialog box with a link to MedInfo’s website. While
the user can read the user guide from the website to learn how to use the commands, perhaps a quick command summary
could be added to this window for returning users who do not wish to open the website but just need a quick refresher
on the commands.
Possible implementation:
- add command summary in text to help window display