Overview

I am a software developer and second year computer science student at the National University of Singapore. I am really passionate about developing technology that can make the world a better place. This portfolio page documents my contributions to one of the most meaningful projects I’ve worked for - HealthHub.

Project: Health Hub

About the project

HealthHub

HealthHub is a command-line desktop application built by my team and I, for our Software Engineering project. We chose to morph it to a home-care patient management system, because of our passion in the health care industry. This enhanced application allows Hospital Administrators and senior management to create, assign and organise patient records seamlessly. HealhHub also organises staff information and manages statistics to assist in the Hospital’s planning and allocation of resources.

Note the following symbols and formatting used in this document:

add A grey highlight (called a mark-up) indicates that this is a command that can be inputted into the command line and executed by the application.
Request Grey highlight beginning with a capital letter indicates a component, class or object in the architecture of the application.

Summary of contributions

  • Major enhancement: Created the Request class to encapsulate a request, and it’s relevant CRUD commands.

    • What it does: Encapsulates the necessary information to be stored in a patient request.

    • Justification: Laid the foundation to the entire project. All components of our project (UI, Storage, Logic and Model) required the creation of a Request class for further development of core functionality.

    • Highlights: This enhancement affecting all existing classes, requiring some overhaul of the existing code base and thorough interaction of the differing components.

  • Major enhancement: Created assign and complete request commands.

    • What it does: Allows the admin to assign Healthworkers to requests, and complete any ongoing requests.

    • Justification: These features are necessary for the product, and allows the administrator manage all patient requests by assigning the relevant healthworker with the appropriate skill sets.

    • Highlights: Creation of these features required thorough understanding of how the existing details of the Logic and Model components, as knowledge of how information is cached in the application’s memory was essential to allow for rapid assigning. Also implemented a scheduling algorithm that allows users to ensure that requests assigned to `HealthWorker`s are at least 2 hours apart. This prevents the user from accidentally assigning the same Healthworker to requests with clashing times.

  • Minor enhancement: added a filter command that allows the user to navigate through all requests stored by filtering by a specific value.

  • Code contributed: [Reposense]

  • Other contributions:

    • Project management:

      • Managed releases v1.3 onwards (3 releases) on GitHub

      • Added reposense compatibility

      • Added coveralls compatibility to project README

    • Community:

      • PRs reviewed: view here

      • Reported bugs and suggestions for other teams in the class (examples: 1, 2, 3, 4)

Contributions to the User Guide

Filter requests:

Format: filter request <keyword> [<more_keywords>]

Shortcut(s):
1. filter r <keyword> [<more_keywords>]
2. filter 2 <keyword> [<more_keywords>]

where [<more_keywords] refer to the fields you would like to search for.

After entering the command with valid inputs, you will see the entire list of requests whose fields match the parameters specified in the command. To filter requests, you can specify any of the following filtering criteria: dt/DATE, n/NAME, p/PHONE, st/STATUS, i/NRIC, c/CONDITION. Note that you can also chain multiple criteria together to get a more specific filter result.

For example, let’s say you want to filter all the requests made by the patient with NRIC S9123456G that have been completed. You can simply enter the command: filter request i/S9123456A st/COMPLETED, and the request list panel to the left of the screen would update to show you all the requests you are looking for.

Before:

filterrequestbefore

Figure 5.5.2.1 shows the request list prior to executing the filter request command

After:

filterrequestafter

Figure 5.5.2.2 shows the request list after executing filter request i/S9123456A st/COMPLETED

The request list panel on the left would filter to show just the requests queried by the user.

If there are no such requests that match the user’s query, an empty list would be show on the left panel.

 

Notes:

  • The search is case insensitive for all fields apart from specialisation(e.g hans will match Hans), and the order of the keywords does not matter(e.g Hans Bo will match Bo Hans).

  • Search using partial words will return all results with fields containing that subword. (e.g filter request n/Tan may return people with the surnames Tan or Tang)

  • Note that to filter by status, the status has to be spelt out in full. e.g filter r st/pending

 

Multiple conditions for filtering requests can be added simultaneously for more expressive search.

Example:

filter r n/<name> p/<phone> filters the request list for requests whose patient’s name contains the specified name substring and the specified phone number.

To revert the view back to the original request list, enter the list request command.

Examples:

  • filter request n/alice
    Returns all patients whose name contains "alice".

  • filter r p/9177
    Returns all requests with contacts numbers that have "9177" in it’s field.

  • filter 2 dt/30-01-2019 10:00:00
    Returns all requests scheduled on 30th Jan 2019, at 10 am sharp.

Filtering requests within a specific date range

Let’s say you’ve grown to have an overwhelming number of requests, because you’ve been doing so successfully! Suppose you now would like to look back and take a look at the requests that you had over a specific date range. You can do so using the following command:

Format: filter request dt/start dt/end
Shortcut(s):
1. filter r dt/start dt/end
2. filter 2 dt/start dt/end

Examples:

  • filter r dt/01-01-2019 00:00:00 dt/01-06-2019 00:00:00
    filters the requests between 1st Jan 2019 (inclusive) and 1st June 2019 (exclusive).

Contributions to the Developer Guide

Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project.

Assign Request feature

The assign request feature allows an administrator to assign a request to a particular healthworker.

Current Implementation

The following sequence diagram shows the sequence flow from the LogicManager to the ModelManager when a user enters a assign request command:

assignreq

Figure 3.3.1.1 Sequence diagram to illustrate Logic component interactions for assign request command.

assignReqToHw

Figure 3.3.1.2 Sequence diagram to illustrate Logic and Model component interactions for AssignRequestCommand.

addHwRequestDates

Figure 3.3.1.3 Sequence diagram illustrates addition of the relevant Date objects into the TreeSet<Date> of the healthWorker.

checkConflictingRequests

Figure 3.3.1.4 Sequence diagram illustrates interaction between AssignRequestCommand and healthWorkerAppointments

  1. When LogicManager receives the execute command, it calls the parseCommand method in RequestBookParser.

  2. RequestBookParser will receive assign as the command and instantiate AssignRequestCommandParser to further parse the command.

  3. If the arguments specified in the assign command are invalid, a AssignCommand will be created and returned back to the LogicManager.

  4. LogicManager will proceed to call the execute command of AssignCommand

  5. AssignRequestCommand will proceed to call the getFilteredRequestList method of Model.

  6. Iterate through the requestIds, if valid, add the request corresponding to that index to the set of Request.

  7. Iterates through all the requests already assigned to that healthWorker. If there is a conflict of schedule (i.e Requests assigned to that healthWorker are less than 2 hours apart), a CommandException is thrown.

  8. Writes the updated request to the RequestBook in ModelManager, if all the request timings are valid.

Design Consideration

Aspect: Algorithm in ensuring no clashing requests assigned to healthworkers - Data Structure and implementation
  • Alternative 1 (current choice): Using a Balanced Binary Search Tree (java TreeSet) to keep track of the RequestDate of each request attended to by a particular healthWorker.

    • Reasoning: Since the allowed time interval between 2 consecutive requests should be at least 2 hours, we can take advantage of of this by only keeping track of the start time of requests. Hence we can utilise the ceiling(), contains() and floor() methods of the TreeSet, which runs effeciently in O(log N) time (where N is the number of requests). Here is the code snippet that implements this:

    // Note: healthWorkerAppointments is the TreeSet that stores the appointment dates
    Date date = request.getRequestDate().getDate();
    calendar.setTime(date);
    calendar.add(Calendar.HOUR_OF_DAY, -MIN_REQUEST_DURATION); // MIN_REQUEST_DURATION = 2 hours
    Date lowerLimit = calendar.getTime();
    calendar.add(Calendar.HOUR_OF_DAY, 2 * MIN_REQUEST_DURATION);
    Date upperLimit = calendar.getTime();

    if (healthWorkerAppointments.contains(date) || (healthWorkerAppointments.lower(date) != null
          && healthWorkerAppointments.lower(date).after(lowerLimit))
          || (healthWorkerAppointments.higher(date) != null
          && healthWorkerAppointments.ceiling(date).before(upperLimit))) {
              throw new CommandException(Messages.MESSAGE_HEALTHWORKER_OCCUPIED_CANNOT_ASSIGN);
    }

    healthWorkerAppointments.add(date);

Here is a pictorial representation of the algorithm:

assignRegionCheck

Figure 3.3.1.5 Shows the visualisation of time ranges that are valid.

  • Alternative 2: For each request to be assigned, manually iterate through the Request list to ensure that there are not clashing dates. Pros: Easy to implement Cons: Slow - in the worst case, if all the requests get assigned at once, this operation will run in O(n^2) time.

Add Request feature

Current Implementation

The add request command allows the LogicManager to create a new request and add it to the list of requests. Adding a new request requires the patient’s name, patient’s phone number, patient’s address, patient’s NRIC number and the patient’s conditions. The format of the add request command is add request n/NAME p/PHONE i/NRIC a/ADDRESS dt/DATETIME c/CONDITION.

The following sequence shows the sequence when the add command is execute by the LogicManager:

addrequest

Figure 3.2.1.1 Sequence Diagram for add request command

From the diagram above:

  1. LogicManager 's execute is called when the administrator keys in add request and it calls upon parseCommand of HealthHubParser to parse the command

  2. HealthHubParser will initialize AddCommandParser and invoke the method parse to further parse the command.

  3. parse will be invoked and passed the parameters of the add command.

  4. If all the arguments of the add commands are valid, AddRequestCommand will be returned to the LogicManager

  5. LogicManger will then calls the method execute method of AddRequestCommand

  6. AddRequestCommand will call addRequest passing Request as an argument to Model and after calls commitRequestBook method from Model, if all the arguments in the Request are valid.

  7. A CommandResult will be returned at the end.

Design Considerations

Aspect: Data Structure for the list of Requests
  • Alternative 1 (Current Approach): Using a UniqueRequestList

    • Pros: The comparison is not as rigid. You can create requests with similar names/phones as long as it passes a less stringent criteria.

    • Cons: You need additional overhead. You need to create an extra class and function to check.

  • Alternative 2: Using a Set

    • Pros: Do not need an extra function. You can use use equals for comparison

    • Cons: It is a strict check and as a result you will not be allowed to create requests with same phone/same name etc.

Aspect: Data Structure of Request
  • Alternative 1 (Current Approach): All parameters in Request are abstracted out to have a class of its own.

    • Pros: It adheres to the Single Responsibility Principles (SRP) and the Separation of Concerns (SoC) as each parameter checks whether it is valid

    • Cons: Many different classes are created which increases the complexity of the code

  • Alternative 2: Store all parameters of Request as String

    • Pros: Easy to implement.

    • Cons: Violates SRP as one single class will need to check if the arguments are valid.

The RequestStatus class within the Request object utilises the Java Enum to ensure type safety in user inputs.

The implementation of the RequestStatus class is as follows:

    private enum Status {
        PENDING,
        ONGOING,
        COMPLETED
    }

     public RequestStatus(String status) {
         this.requestState = Status.valueOf(status);
     }

Through this, any user String that is passed in as an argument for the RequestStatus field is automatically type checked, ensuring that there are no invalid request statuses entered.