Project: BoNUS
BoNUS is a desktop personal organizer application dedicated to NUS students to carry out various tasks such as storing contacts, scheduling for upcoming events, timetable planning as well as a calendar to better organise their campus life.
This project is the result of a semester-long software engineering module at NUS. It is built my teammates and me, as listed here. Most of the backend codes are written in Java, while JavaFX is adapted as the frontend framework.
Code contributed:
Enhancement Added: Generic Property
Adding a customize property : (cfg)config --add-property
Adds a new customize property field available to all persons or events.
Format: (cfg)config --add-property s/SHORT_NAME f/FULL_NAME [m/MESSAGE r/REGULAR_EXPRESSION]
Example:
-
config --add-property s/ag f/age
-
config --add-property s/b f/birthday m/Birthday should be in the format of DD/MM/YYYY r/[^\s].*
|
Justification
Our application BoNUS will not be able to stand out from all the similar products if we simply provide users with a few additional fields to store the information of their contacts. Instead, to suit the various needs from users, we have to provide the flexibility to allow users to define customize properties on their own.
Users can use the config --add-property
command to define as many new properties as they want, after which they could
set these properties when they use the add
command to add a new contact.
In the current design and implementation, the PropertyManager
class is used to store and manage the meta-data of all
properties. Default properties like Name
, Phone
, Email
and Address
are pre-loaded into PropertyManager
, while
user-defined properties will be added into PropertyManager
by config --add-property
command.
Generic property
We are using a generic Property
class to support arbitrary field feature.
Inspiration
Users should not be limited to the provided four fields, i.e. Name
, Email
, Phone
, Address
(we are talking about
the contact component here, of course one more DateTime
for event component). They should have the freedom to enter all
kinds of information about their contacts apart from the pre-defined ones.
Through a brief product survey on other existing similar software in the market, we found that they usually ask users to
type all other information in the so-called Description
or Details
field. This is not a good design because doing
so will make the information stored messy. The application is used to organize personal information conveniently. It is
a major drawback if the data are not stored (and thus presented to users) in a well-organized way.
Learning from many modern database implementations, we should think of the data as two tables: one for contacts and the other one for events. Each table is composed of many rows and many columns. A single contact/event is one row, while all their different properties/fields are the columns (as can be seen from Figure 4.3.1.1 and 4.3.1.2).
Figure 4.3.1.1 : Data Table View of phpMyAdmin (a MySQL visualization tool)
Figure 4.3.1.2 : Add New Column in phpMyAdmin
Design Consideration
Aspect: Where to store the "metadata" of different properties (short name, full name, regular expression, etc.)
Alternative 1 (current choice): Create a new class PropertyManager
in Figure 4.3.2.1
Pros: Efficient (there is only one copy) and easy for future development since it is centralized.
Cons: Requires major change to Model
component and Storage
component.
Alternative 2: Store these data along with each specific property class, like Name
, Email
Pros: Able to adapt the current implementation of Model
component.
Cons: Hard to implement AddPropertyCommand
, and difficult to manage as the project grows larger.
Figure 4.3.2.1 : Class Diagram for PropertyManager
Implementation Outline
-
Create a more general class to capture the common patterns among all columns (all different fields/properties): according to the basic OOP concept, a more generic class should become the superclass
Property
; then, other more specific classes (likeName
,Email
,Phone
, etc.) can inherit from it. This design reduces a lot of code duplicates. -
Find a way to store the metadata of all columns (fields/properties): in popular SQL database implementation, they usually have a separate database reserved for the database server system itself. We must store similar information somewhere as well. Thus, we create a
PropertyManager
to store these "metadata", including short names, full names, constraint messages and regular expressions used for input validation. They are allstatic
variables because there should only be one copy of these "metadata". It will waste a lot of resources if we store these "metadata" with each instance of theProperty
class. -
Pre-loaded properties: Things like
Name
,Email
andPhone
are widely used. They should ship with the application and users do not need any additional setup steps to use them. -
Add new customize properties: advanced users should be provided with a command (
config --add-property
) to add their own customize fields (as shown in Figure 4.3.3.1). They should have the freedom to arbitrarily choose things like short name, full name, etc. They can easily add/edit these properties of each contact stored in the application, just like the pre-loaded ones.
Figure 4.3.3.1 : Sequence Diagram for Adding a Customize Property
Enhancement Added: Import NUSMods Timetable
From NUSMods URL
(Exclusive feature for NUS students)
The BoNUS team understands that NUSMods has become an indispensable school timetable builder
for almost all students at NUS. Thus, you are definitely allowed to import your timetable from NUSMods to the BoNUS
application.
Format: (i)import --nusmods YOUR_NUSMODS_URL
Example:
-
import --nusmods https://nusmods.com/timetable/2017-2018/sem1?CS2103T[TUT]=C01
|
Justification
This feature addresses a specific need of NUS students, since they are our target users.
For university students, the lessons and exams reflected on their school timetable account for a large part of their schedule. When they are using BoNUS, it is very likely they want to put all these activities into the application as upcoming events. However, it becomes very tedious to do so manually.
Most of the NUS students are currently using NUSMods as their school timetable builder. Their NUSMods timetable contains information about all their lessons and exams. Thus, it would be very convenient if users could directly import their NUSMods timetable into BoNUS in one step.
Import timetable from NUSMods
We implement an ImportNusmodsCommand
to help users directly import their NUSMods timetable to BoNUS by simply copy-paste
the URL.
Inspiration
As stated in User Guide, BoNUS helps you better(B) organize(o) your NUS life. Thus, we want to make the application an integrated personal manager for NUS students. The main activities for most students are study-related and most NUS students are currently using NUSMods to build their school timetable (as shown in Figure 4.7.1.1).
Figure 4.7.1.1 : NUSMods Website Interface
Let’s imagine some of our users want to use the event feature in BoNUS. They want to input final examinations for all the modules they are taking as upcoming events. It would be very inconvenient and tedious if they have to do this manually. Even worse, it is very likely they are already using NUSMods and thus are not willing to add these events again. They may end up not using the event feature at all.
However, users may find it very useful if they can import their NUSMods timetable using a simple command. Eventually, they would choose BoNUS because they can manage both contacts and events in one application conveniently and the migration from NUSMods to BoNUS is not troublesome.
Design Considerations
Aspect: Relationship between ImportXmlCommand
and ImportNusmodsCommand
Alternative 1 (current choice): Add a new abstract ImportCommand
class and let both of them become its sub-commands
(inherit from it).
Pros: This is inspired by many popular command-line tools (like Git). import
is called the actual command, while
--xml
and --script
is called the options. Most Unix/Linux users would be used to this approach. This is important for
us because we assume our users are typists and they are very likely to frequently use these command-line tools.
Cons: Need to write extra codes and parsing also becomes more complicated.
Alternative 2: Implement these two commands separately.
Pros: Easy to implement and similar to other commands.
Cons: Our users may not be used to it. The command word will become longer. It is not a good OOP practice as well
because common details are not abstracted into a parent class and this produces duplicate codes.
(Similar strategy has been adopted in ConfigCommand
)
Aspect: How to obtain user’s NUSMods timetable
Alternative 1 (current choice): Let users copy-paste the URL as a parameter of ImportNusmodsCommand
.
Pros: Simple to use and easy to implement as well
Cons: Need to check whether the URL is valid and from NUSMods (currently using regular expression).
Alternative 2: Implement a built-in browser and render the NUSMods page
Pros: Users are more used to this interface.
Cons: Need much extra work to implement the built-in browser. The page may not be rendered well since the built-in
browser is typically smaller than OS browser and NUSMods does not fully adopt responsive UI framework
and may not work well on a small browser window.
Implementation Outline
ImportCommand
abstract class
Create an ImportCommand
abstract class and let ImportXmlCommand
and ImportNusmodsCommand
inherit from it (as in
Figure 4.7.3.1). It is also a good practice to use an enumeration ImportType
because the possible types of the import
are within a fixed set of values. This leads to better modularity in ImportCommandParser
as well.
Figure 4.7.3.1 : Class Diagram for Related Import Commands
Parsing of NUSMods Timetable URL
Implement utility method to validate a given URL and parse the GET
parameters. Although it is possible to utilize
external library like Apache HttpComponents, we decide to implement on our own because it is relative
simple to do so and using external library comes with extra expenses (such as licence, etc).
public static Map<String, String> fetchUrlParameters(URL url) throws UnsupportedEncodingException {
String query = urlDecode(url.getQuery());
if (Strings.isNullOrEmpty(query)) {
return Collections.emptyMap();
}
Map<String, String> pairs = new HashMap<>();
for (String pair: query.split("&")) {
int index = pair.indexOf("=");
pairs.put(pair.substring(0, index), pair.substring(index + 1));
}
return pairs;
}
Fetch information from NUSMods API
The URL parsed just now only contains the module codes and grouping for each module. In order to add upcoming events, we need more information such as module names, examination dates, etc. We decide to use API provided by NUSMods to fetch the information we need. NUSMods API is in JSON format, which would be very simple for us as we already use Jackson library in our project.
/**
* Read JSON data from a given URL and convert the data to an instance of the given class.
* @param url is the URL to the remote JSON data.
*/
public static <T> T fromJsonUrl(URL url, Class<T> instanceClass) throws IOException {
return objectMapper.readValue(url, instanceClass);
}
Add upcoming events
After obtaining all the information we need, we can simply use the addEvent
method in ModelManager
class to add the
final examinations as upcoming events into BoNUS. This should be a similar process as AddEventCommand
.
Enhancement Proposed: Import From BoNUS-specified Script file
From .bo
format
(Coming in v2.0)
Imports the data in an external BoNUS script file (which ends with .bo
), including data from all three components:
Contacts, Events and Calendar, into the application.
Format: (i)import --script FILEPATH
Examples:
-
For
Windows
users:
import --script C:\Users\John Doe\Documents\bonus.bo
-
For
macOS
andLinux
users:
import --script /Users/John Doe/Documents/bonus.bo
For |
Justification
This feature is meant for advanced users. To build an epic application, we need to essentially build an ecosystem for this software. According to the Unix philosophy, providing a shell scripting and command language is the minimum requirement for a complete system.
With the support for scripting file, advance users (or system administers if BoNUS is used as an enterprise application) can generate a scripting file and import it into BoNUS. Data management and frequent operations can be done easily in one step. Otherwise, they have to type one command each time in the GUI interface, which becomes a very tedious work.
Enhancement Proposed: Export Data to Microsoft ExcelTM Worksheet
To Microsoft ExcelTM Worksheet
(Coming in v2.0)
Exports the current data in the application to an external file of Microsoft ExcelTM format.
Format: (p)export --excel FILEPATH
Examples:
-
For
Windows
users:
export --excel C:\Users\John Doe\Documents\bonus.xls
-
For
macOS
andLinux
users:
export --excel /Users/John Doe/Documents/bonus.xls
For |
Justification
We already support ExportCommand
so that users can save data to a separate location as a backup. However, .xml
files
are not considered to be user-friendly (except for programmers and geeks).
Thus, it becomes essential for us to natively support exporting data to a format with better visuals. As stated before, data stored in BoNUS can be considered as tables. Naturally, it comes to my mind that Microsoft ExcelTM would be a perfect format to present data to users.
Other contributions
-
Repository setup, CI setup and Slack automatic notification using WebHook (Pull requests #1, #6, #7)
-
Design and refine multiple parts of UI (Pull requests #41, #43, #44, #82, #106)
-
Support setting customize colors for tags (Pull requests #83, #101, #147)
-
Support natural language parsing (Pull request #148)
-
Support adding avatar to contacts (Pull request #162)
-
Write unit tests for various classes
-
Update various sections in
AboutUs
,ContactUs
,UserGuide
andDeveloperGuide
, etc.
Project: Lions Befrienders Management System
I worked at CVWO (Computing for Voluntary Welfare Organisations) as a web developer during the Year 1 summer vacation.
My team at CVWO rewrote, upgraded and deployed the management system for Lions Befrienders (Singapore), which was formed in 1995 and served thousands of senior citizens. This system saves a lot of time for staff at Lions Befrienders to manage their growing enormous clients across the country, while ensuring high service quality.
Project: A Multi-User 3D Game Environment for CS1101S
This project aims at building a 3D game environment to assist CS1101S students in learning programming. The game is built using Unity3D game engine. It provides vivid visualization to help students have a deeper understanding of the related data structure and algorithms used.
CS1101S is a module taught in the Department of Computer Science at the NUS School of Computing. It serves as a rigorous and thorough introduction to programming methodology.