PROJECT: TeethHub

Overview

My teammates and I were assigned the task of either improving an existing Command-Line Interfaces (CLI) based program by the name of AddressBook4 or to use it as the basis for our own program. We chose to transform it into TeethHub.

TeethHub is a desktop patient-record application meant for tech-savvy dental practitioners who prefer interacting with Command-Line Interfaces (CLI) based programs over Graphical User Interface (GUI) based ones. The program allows dentists to enter patient data, manage records and teeth data tied to each patient, view information in a variety of ways, as well as import and export information into either .json or .pdf format. The user interacts with it using a CLI, and it has a GUI created with JavaFX to display data for the user. It is written in Java, and has about 20 kLoC.

My responsibility was implement different ways the dentist could view the stored information within the program. To that end, I created the sort and stat commands as well as enhanced the existing functionality of the find program. The below segments go into greater detail of these implementations as well as the sections I have written within both the user guide and the developer guide.

Summary of contributions

The segment below summarises the most pertinent improvements and enhancements I made towards the team’s overall goals.

  • Added the ability to sort displayed data

    • What it does: allows the user to sort either patient or record data according to their desired parameter and sort order depending on the mode it’s in.

    • Justification: A user can have large amounts of data stored within the program. This feature improves the product significantly by allow the user to view that data in the desired parameter order so that it becomes easier for the user to locate them.

    • Highlights: This feature automatically switches the type of data (patient or record) that it sorts depending on the mode the program is in. This feature reorders the stored data within the json storage file as well.

  • Added the ability to find patients and records through all available parameters

    • What it does: allows the user to find a desired patient or record based on the specified parameter(s) and keywords. The user can additionally choose if they want the search to be case sensitive, and if the search should find data containing at least one keyword or if the search should find data that contains all keywords.

    • Justification: A user can have large amounts of data stored within the program. This feature allows the user greater refinement over the parameters to find a particular desired patient.

    • Highlights: This feature automatically switches the type of data (patient or record) that it searches through depending on the mode the program is in.

  • Added the ability to view a patient’s statistics report

    • What it does: allows the user to view a detailed report of the select patient containing their latest teeth, all linked user information, as well as a breakdown of their associated records.

    • Justification: A patient might be a frequent visitor to the user’s dental practice, hence the user may want a detailed report so that they can analyze potential trends.

    • Highlights: This feature has three different ways of record data visualization; a simple table; a bar chart, and a pie chart.

  • Added a Next Of Kin class as an attribute for a patient.

  • Added a Procedure class as an attribute for a record.

Code contributed: [Reposense]

Other contributions:

  • Project management:

    • Created and maintained the group project repository

    • Managed releases v1.1 - v1.4 (6 releases) on GitHub

    • Responsible for approving and merging the Pull Requests of fellow teammates

    • Created majority of open issues and distributed responsibilities for the issues to relevant team members

    • Created and assigned relevant tags to issues within the project

  • Enhancements to existing features:

    • Updated README to reflect information for TeethHub instead of AddressBook4

  • Community:

    • Reported bugs and suggestions for other team members #58 #106

  • Tools:

    • Integrated a web page & documentation checker (Netlify) to the team repository

    • Integrated a new Github plugin (TravisCI) to verify test cases to the team repo

    • Integrated a new Github plugin (Coveralls) to determine the extend of test case coverage of our code to the team repo

Contributions to the User Guide

The text below is the documentation done for the user guide that I feel highlights my ability to write end-user friendly documentation through the showcase of a few important sections.

sort

Sorts the records by an input parameter in an input order.

Format: sort PARAM [ORDER]

  • valid PARAM options in patient mode: address, dob, email, name, nric, phone, sex, drug, kinN, kinR, kinP, kinA, desc.

  • valid PARAM options in record mode: desc, date, proc.

  • valid ORDER options: asce, desc

    • default ORDER if unspecified is ascending

Example:

ID Name Sex Phone Date of Birth

0

Alice

M

84521666

03/07/2003

1

Bob

M

96545555

11/02/2019

2

Clara

F

98989898

05/02/2021

  • sort sex

ID

Name

Sex

Phone

Date of Birth

0

Clara

F

98989898

05/02/2021

1

Alice

M

84521666

03/07/2003

2

Bob

M

96545555

11/02/2019

  • sort dob desc

ID Name Sex Phone Date of Birth

0

Clara

F

98989898

05/02/2021

1

Bob

M

96545555

11/02/2019

2

Alice

M

84521666

03/07/2003

stat

StatWindow

Generates a statistics report based on the specified patient’s data. The generated report will contain all extended patient information, a breakdown of all the records linked to the select patient parse in three different formats; a table of records; a bar chart visualization; and a pie chart visualization.

Format: stat INDEX

Record Find

Shows patients whose data contains any of the given keywords according to a specified parameter.

Format: recordfind [CS] [AND] PREFIX/KEYWORD [MORE_KEYWORDS] or rfind [CS] [AND] PREFIX/KEYWORD [MORE_KEYWORDS]

  • Search is case insensitive unless CS is entered before the prefix(es).

  • By specifying AND before the prefix(es), pfind will instead search for patients whose data contains all of the given keywords and parameters.

  • Order of keywords does not matter.

  • Valid Prefix values: See [Breakdown of attributes used within TeethHub]

Example:

  • rfind pro/Braces
    Show all the patients with a procedure containing the keyword Braces.

Contributions to the Developer Guide

The text below is the documentation done for the developer guide that I feel highlights my ability to write technical documentation through the showcase of the more important implementations I did during the creation of the project.

Find feature

The Find mechanism is facilitated through the use of predicates in conjunction with the FilteredList within ModelManager

The below sequence diagram gives an overview of how a Find Command is created. When the proper string arguments for a Find Command is entered into the user interface, the arguments are passed to the Logic Manager and then the AddressBook parser to determine if the input is valid. If it valid, a new FindCommandParser object is then created and handles the remaining user input.

From FindCommandParser, it creates a MultipleContainsKeywordsPredicate before going into a loop that creates the respective parameter ContainsKeywordsPredicate if the parameter is present within the user input. The newly created ContainsKeywordsPredicate objects are passed back to the FindCommandParser and stored within a list. Once the loop has finished the list is passed over to the MultipleContainKeywordsPredicate object before it is used in the creation of a FindCommand object. On success, the FindCommand object is returned to the LogicManager as per the flow in the sequence diagram.

On execution of the Find Command, updateFilteredPersonList is called with the predicate stored within the program itself. It subsequently calls setPredicate(predicatte) and updates the displayed person list to only show patients that matches the given predicate.

FindCommandSequenceDiagram1

Design Considerations

Aspect: Creation of Predicate Classes
  • Current Implementation: Every associated parameter that is found within either a Patient or Record class has an associated parameter predicate classes extended from ContainsKeywordsPredicate class that handles the predicate testing when that parameter is specified to be searched.
    (E.g. The predicate for Name is handled in NameContainsKeywordsPredicate)

    • Alternative 1: Patient and Record would each have an individually associated PatientContainsKeywordsPredicate and RecordContainsKeywordsPredicate that contains each respective parameter predicate class within itself.

      • Alternative Pros: Collates all parameter predicates relevant to either Patient or Record within a singular class. This makes it easier for future developers to discover which file to change should they require to add or remove additional parameter predicates from TeethHub.

      • Alternative Cons: Violates Open-Closed Principle as every time a parameter predicate needs to be added or modified, we are forced to modify the code of either PatientContainsKeywordsPredicate or RecordContainsKeywordsPredicate in order to extend its behavior.

    • Choice Justification: Ultimately, while the current implementation can be considered more troublesome for future developers as they would need to create a new java file for each new parameter, we decided that it was more important for us to maintain proper software engineering principles.

Sort feature

The Sort mechanism is facilitated through the use of Comparators in conjunction with the Unique Lists for both record and patient depending on the programm’s mode when the command is called.

Upon parsing the arguments, SortCommandParser then checks which mode TeethHub currently is in. If it’s in record / goTo mode, it creates a RecordComparator and returns a SortRecordCommand. Otherwise, a PatientComparator is called instead and returns a SortPatientCommand instead.

When the comparator is retrieved, SortCommandParser then calls orderChecker from itself to determine the isReverse boolean. Finally, the respective parameters are used to create the neccessary SortCommand and returns it to AddressBookParser and then LogicManager.

On execution, there are two behaviours can occur depending on whether the SortCommand is a SortPatientCommand or SortRecordCommand. Should it be an instance of SortRecordCommand, sortRecordsBook(c,isReverse) is called from ModelManager, which in turns called sortRecords(c, isReverse) from VersionedAddressBook and finally calls sortStoredList (c, isReverse) from UniqueRecordList. This sorts the records currently stored according to the parsed comparator and hence changes the order records are displayed to the user.

Should it be a SortPatientCommand instead, the same logic flow occurs except it that calls the respective patient methods and classes instead.

SortCommandSequenceDiagram

Design Considerations

Aspect: Implementation of sort
  • Current Implementation: SortPatientCommand & SortRecordCommand extends from a super SortCommand class and share a common SortCommandParser. They hence share the same command words and allows the user to simply enter sort to sort either the displayed patients or records.

    • Alternative 1: Create separate parsers and commands for sorting patients and records respectively. PatientSortCommand and PatientSortParserCommand could sort patients while in patients mode while RecordSortCommand and RecordSortParserCommand could sort records while in records mode.

      • Alternative Pros: A clearer distinction of what mode the program is in would be made to the user. Additionally, it would be easier to change the parser behavior if necessary in the future of either sort command without affecting the other.

      • Alternative Cons: It would no longer be possible to change any shared behavior of both sort commands simply by modifying the SortCommand super class.

    • Choice Justification: Ultimately, we decided on having a parent SortCommand with its two SortPatientCommand and SortRecordCommand children share a common SortCommandParser. Aside from the fact that SortRecordCommand calls the Record equivalent methods and classes that SortPatientCommand does, the behavior of both sort commands are essentially the same. As such, it made more sense for us to go ahead with our current implementation.

Stat feature

The Stat mechanism is facilitated through the use of the inbuilt JavaFx framework in conjunction with the data stored within each Patient object.

Upon execution of the stat command, the patient to have statistics generated from is set to the StatWindow file which then uses it to create the report. As per the diagram below, StatWindow then obtains all attributes from the patient and sets the latest teeth image to itself.

The StatWindow then creates a Map<String, Integer> with all the valid procedure values found in Procedure as the keys and the values set to 0. StatWindow subsequently iterates through all the records linked to the set patient checking for the record’s procedure type, incrementing the value paired the respective procedure by 1 on a hit. It is from this Map that the records table is generated as well as the bar chart. The pie chart uses the Map as well while ignoring entries whose values have remained at 0.

It is at this point that all necessary data has been populated within the statistics report and it is displayed to the user.

StatActivityDiagram

Design Considerations

Aspect: Selecting the desired patient to stat
  • Current Implementation: The selected patient is determined by the Index number of the currently displayed patients within the PatientListPanel

    • Alternative 1: The selected patient is determined by a given keyword. Upon entering the keyword, the program then searches for the patients that match the keyword. Should multiple patients match the keyword, the command would fail and the user would be prompted to refine their search.

      • Alternative Pros: Combines patientfind and stat together, giving the user greater convenience should they know enough unique details of the patient they wish to stat.

      • Alternative Cons: Reduces the ease of use of the stat command. As the amount of patients stored within the program increases, so does the probability that the entered keywords would match multiple patients.

    • Choice Justification: Ultimately, we decided to stick with Index based selection as it increases the ease of use for the user when there’s a large number of patient entries. As the Index references the displayed patients, the user can hence perform a patientfind operation beforehand and locate the desired patient.