1. Introduction
This Project Portfolio Page documents my contributions to the development of CLInic
, the product of a team of five
students from NUS School Of Computing as part of the CS2103T Software Engineering
module. The main
features of the application are coded in Java
while the GUI is handled by JavaFX
, HTML
and CSS
.
CLInic
is a desktop application made to manage and expedite operations in clinics. The main impetus behind CLInic
was to distil the CLI’s efficiency of typing commands, as its cryptic walls of text was intimidating to the
general, non tech-savvy populous. Hence, CLInic
marries the simplistic design and efficient command issuing mechanism
of the CLI with an intuitive Graphical User Interface (GUI). This culminated in an application that is easy for
anyone to use, all while providing the powerful functionalities and efficiencies offered by a CLI.
Below are some of the key features provided by CLInic
:
-
Allows users to manage patient and medicine information
-
Allows users to easily generate documents to be issued by a clinic like
Medical Certificates
efficiently -
Provides intuitive workarounds to normally arduous but common administrative tasks such as restocking and dispensing medicine
I played a major role in the development of the Document
class, the relevant Receipt
, MedicalCertificate
and ReferralLetter
classes that extend it and the relevant patient management operations that are required for
them to work.
2. Summary of contributions
-
Major enhancement: Implemented the
Document
class, its accompanying HTML template and extending classes, which includes theReceipt
,MedicalCertificate
andReferralLetter
classes.-
What it does: It takes in the information of a document that is to be printed by the clinic and generates a
HTML
file for it. -
Justification: This functionality simplifies the generation of documents that are required by the clinic. This makes the administrative tasks in the clinic easier and faster, boosting the productivity of its users, translating into shorter wait times at the clinic for the patients.
-
Highlights: This functionality allows for seamless transfer of information from doctors to receptionists of the clinic during consultation, which when coupled with the fast retrieval of information from the application’s database of
Patient
andMedicine
information, makes for efficient generation of relevant documents.
-
-
Minor enhancements:
-
Improved and helped with the implementation of
ServedPatient
andServedPatientListManager
, which are intermediate abstractions(placeholders) that help to 'finalise' the information to be used for the generation ofDocument
. -
Integrated
MedicalCertificate
with theDocumentAddContentCommand
. -
Designed the
HTML
template which all the classes that extendDocument
use to format their information.
-
-
Code contributed: View the code I have written for the project here!
-
Other contributions:
-
Enhancements to features:
-
Community:
-
Documentation:
-
3. Contributions to the User Guide
Given below are the sections I have contributed to the User Guide. They showcase my ability to write documentation targeting end-users. |
3.1. Implementation of the Patient Record Management System
Adding a patient: add
Did someone just walk in, wanting to see the doctor?
Add him to CLInic’s patient database using the add
command!
Alias: a
Format: add n/NAME ic/IC_NUMBER p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…
Pro tip(s):
|
Important:
Omission of any mandatory parameters will result in the failure of adding the patient to the database.
|
Upon successful execution, you should see the patient with his details added to the patient list on the left.
Examples:
-
add n/Clinton Law ic/S9638902L p/97947435 e/clinton@cs2103t.com a/Tembusu College
Adds a patient namedClinton Law
, with IC numberS9638902L
, phone number97947435
, emailclinton@cs2103t.com
and address ofTembusu College
to CLInic’s patient database, as shown below.
add
command specified above and left clicking Clinton’s
patient card in the patient list on the left, indicated by the black cursor.Editing a patient: edit
Uhoh! Made a mistake keying in a patient’s particulars? Or perhaps a patient had recently changed his address?
Fret not! Simply update his particulars using the edit
command!
Alias: e
Format: edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…
Thing(s) to note:
|
Pro tip(s):
You can remove all of a patient’s tags by typing the t/ prefix without specifying any tags.
|
Upon successful execution, you should see the patient’s details updated in the patient list on the left.
Examples:
-
edit 5 p/98534228 e/clawyq@cs2101.com
Updates the phone number and e-mail address of the 5th patient in the list to98534228
andclawyq@cs2101.com
respectively, as shown below.
edit
command specified above.4. Contributions to the Developer Guide
Given below are the sections I have contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project. |
Document
Implementation of Document
The Document
abstract class represents all the documents that can be issued by the clinic. The Receipt
,
MedicalCertificate
and ReferralLetter
concrete classes, which respective commands will be referred
to henceforth as document related commands, all inherit from it. It can be thought of as a formatter that
specifies and organises the common information that all these documents must have with the help of the DocumentTemplate.html
template file.
Shown below is a class diagram illustrating how Document
, Receipt
, MedicalCertificate
and
ReferralLetter
relate to one another.
Document
and document related classes are implemented.As the formatter which directs how the documents are built from the DocumentTemplate.html
template, the Document
abstract class
itself cannot be instantiated. The Document
abstract class
has the following key features:
-
contains the
name
andicNumber
attributes, extracted from theServedPatient
from which theDocument
was constructed from. -
has common methods like
generateContent
to standardise the way in which the contents of theDocument
are formatted. -
has the
formatInformation
abstract method
which the extending classes have to implement.
The following activity diagram summarises what happens internally when a document related command is executed.
Document
itself are labelled in the diagram.As seen in the above activity diagram, upon executing a document related command, the corresponding document will
be constructed from the ServedPatient
object specified by the index
that was passed in with the command,
as detailed in the following steps.
Step 1. The resulting document related object will call the generateDocument
method, which will first make a unique fileName
for the file to be created, identified by the type of Document
, ServedPatient’s
name
and icNumber
.
private String makeFileName() {
return (fileType + FILE_NAME_DELIMITER + "For" + FILE_NAME_DELIMITER + name.toString()
+ FILE_NAME_DELIMITER + icNumber.toString())
.replaceAll("\\s", FILE_NAME_DELIMITER)
.replaceAll("(_)+", FILE_NAME_DELIMITER);
}
The |
Step 2. The DocumentTemplate.html
file is then converted into a string
. It is a template with placeholder
values prefixed by a $
that will be replaced with the actual information pertaining to the ServedPatient’s
consultation.
Shown below is the code snippet that converts the DocumentTemplate
HTML
file into a string
.
private String convertHtmlIntoString() {
StringBuilder contentBuilder = new StringBuilder();
try {
BufferedReader in = new BufferedReader(new FileReader(COMPLETE_TEMPLATE_PATH));
String str;
while ((str = in.readLine()) != null) {
contentBuilder.append(str).append("\n");
}
in.close();
} catch (IOException e) {
System.out.println(TEMPLATE_LOCATE_FAILURE_ERROR_MESSAGE);
}
return contentBuilder.toString();
}
Step 3. The generateContent
method will then be called within the writeContentsIntoDocumentTemplate
method.
The generateContent
method will construct a HashMap
of string
to string
key-value pairs. The keys are the aforementioned
placeholder strings
prefixed by $
found in the HTML
template, while the values are the corresponding information that are to
substitute the placeholders in the HTML
template(keys). The writeContentsIntoDocumentTemplate
method will then use the
key-value pairs found in the HashMap
created by the generateContent
method to replace the placeholder values in the
HTML
template.
private String writeContentsIntoDocumentTemplate() {
String htmlContent = convertHtmlIntoString();
String title = fileType + " for " + this.name;
htmlContent = htmlContent.replace("$title", title);
HashMap<String, String> fieldValues = this.generateContent();
for (Map.Entry<String, String> entry : fieldValues.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
htmlContent = htmlContent.replace(key, value);
}
return htmlContent;
}
private HashMap<String, String> generateContent() {
HashMap<String, String> informationFieldPairs = new HashMap<>();
informationFieldPairs.put(HEADER_PLACEHOLDER, generateHeaders());
informationFieldPairs.put(NAME_PLACEHOLDER, name.toString());
informationFieldPairs.put(ICNUMBER_PLACEHOLDER, icNumber.toString());
informationFieldPairs.put(CONTENT_PLACEHOLDER, formatInformation());
return informationFieldPairs;
}
Step 4. Now that the HTML
template is a string
with the placeholder values replaced by the correct information, a BufferedOutputStream
is used to write the updated string
into the HTML
file, concluding the generation of the Document
HTML
file.
Design Considerations
Aspect: Implementation of the Document
-
Alternative 1 (current choice): Use an
abstract class
to implementDocument
.-
Pros:
-
Allows inheriting classes to use a standardised method to format common information while granting them the flexibility of structuring the contents unique to its document type by means of
abstract methods
.
-
-
Cons:
-
Prevents inheriting classes from becoming an
Enum
asJava
does not supportmultiple inheritance
, since allenums
implicitly inherit fromEnum
. -
More computationally expensive than an
interface
due to the overhead incurred looking up inherited methods and various class members.
-
-
-
Alternative 2: Use an
interface
to implementDocument
.-
Pros:
-
Can convert inheriting classes to
enums
, ensuring that the inputs fed to these classes are valid.
-
-
-
Cons:
-
Unable to standardise the way inheriting classes implement the
generateHeader
method.
-
4.2. Implementation of the Receipt class
Implementation of Receipt
The Receipt
class structure is as follows:
-
Contains a
Map<Medicine, MedicineQuantity>
attribute to record the quantity dispensed of each type ofMedicine
to theServedPatient
from which theReceipt
was constructed from. -
Contains a
HashSet<Service>
attribute to record theServices
administered to the patient. -
Contains a
totalPrice
attribute which stores the total price of all theServices
andMedicines
received by the patient during the consultation.
Users can generate a Receipt
for a specific ServedPatient
by invoking the ReceiptCommand
accompanied by the
ServedPatient
's index in the ServedPatientList
. The below sequence diagram illustrates how the ReceiptCommand
works.
When the ReceiptCommand
is executed, it constructs a new Receipt
object and extracts the relevant information
from the ServedPatient
specified by the index
.
Shown below is how the Map<Medicine, MedicineQuantity>
of a ServedPatient
is unpacked to sieve out the individual
table entries for the cost of different medicines.
private String unpackMedicineAllocation(Map<Medicine, QuantityToDispense> medicineAllocated) {
StringBuilder stringBuilder = new StringBuilder();
for (Map.Entry<Medicine, QuantityToDispense> entry : medicineAllocated.entrySet()) {
Medicine medicine = entry.getKey();
String medicineName = medicine.getMedicineName().toString();
int quantity = entry.getValue().getValue();
float pricePerUnit = Float.parseFloat(medicine.getPricePerUnit().toString());
float totalPriceForSpecificMedicine = pricePerUnit * quantity;
increaseTotalPriceBy(totalPriceForSpecificMedicine);
stringBuilder.append("<tr><td>")
.append(medicineName)
.append(super.HTML_TABLE_DATA_DIVIDER)
.append(quantity)
.append(super.HTML_TABLE_DATA_DIVIDER)
.append(String.format("%.02f", pricePerUnit))
.append(super.HTML_TABLE_DATA_DIVIDER)
.append(String.format("%.02f", totalPriceForSpecificMedicine))
.append("</td></tr>");
}
return stringBuilder.toString();
}