PROJECT: GradTrak - A Graduation Tracker for NUS Students


Overview

GradTrak is an application that was created to aid students with their graduation requirements. NUS has multiple requirements before its students can file for graduation and checking if all of the requirements have been met is a hassle for most students.

Initially we were given a base code Address Book - Level 4 which we had the choice of either morphing into something entirely different or enhance the current code. My team and I decided to challenge ourselves and morph it into GradTrak.

My team and I had to complete the application within 6 weeks. The final products came out as intended with minor hiccups or problems.

Summary of Contribution

  • Major Feature: Added a search functionality that allows students to see all available NUS modules locally.

    • What it does: Users are able to search locally(without internet) all modules that are currently available in NUS. Users are allowed to search for modules that they interested in by the module’s code or even by searching for keywords found in the module’s name. Based on their search, a list of module/s will be presented to them. The information for each module also contains a prerequisite tree and a workload table so that students can also plan their modules semester by semester.

    • Why this feature: Knowing what modules are available is integral to graduate on time, instead of searching through the internet on what modules are available, bringing this feature to the user/students computer locally will greatly improve the efficiency at which students are able to plan and track their graduation.

    • Highlights: There are thousands of modules that need to be loaded during launch of the application and all of these information is stored in a JSON file allModules.json which was obtained from moduleinformation. Further more a significant number of modules have a prerequisite tree which is crucial for students to see if they are eligible to read a particular module and this prerequisite tree was custom made as we could not find another data structure that fit the prerequisite tree.

  • Minor Enhancement: Designed and implemented a data structure called ModuleTree which helps to display and check prerequisites, implemented a one-way read-only storage class to read the allModules.json file.

  • Code Contributed : [functional code] [Test code]

  • Code Contributions on Dashboard : Contributions

  • Other Contributions:

    • Project Management:

      • Set up Issue Tracker

      • Managed deadlines for team

    • Refactored Code

      • Refactored the storage class to read-only json files.

    • Documentation:

      • Did the README.adoc file and the initial UI mockUp

      • Modified sections of the UG and DG to match the application GradTrak.

    • UI:

      • Implemented a panelhandler so the panel changes with accordance to the command typed in.[PR here]

    • Pull Request Made for this project

Contributions to the User Guide

Given below are sections I contributed to the User Guide which will show my ability to write to end-users who have no prior knowledge on programming. This section of the guide does not delve into the technical aspects of this application, only showing instructions on how to navigate through GradTrak. This sections shows how users can search for modules available in NUS currently and the limitations of this feature.

Display module information: displaymod

The displaymod command shows all the modules that are available in NUS based on the search by the student. This command simply shows modules straight from NUS’s database of modules and does not check if the student has met the prerequisites to read a particular module.

This command will allow students to find out more about a module or even compare modules so as to decide which modules to read in the upcoming semesters. Once decided on which module the student plans to read, they can use [add] command to add the module to their own list.

Searches are case-insensitive.
Students must strictly adhere to syntax of the displaymod command in order to get optimum search results.

There are 2 ways to search for modules:

  • Search by code: All modules have module code associated with it, this makes it easier to remember modules.To search for modules based on code, a c/ prefix must be added after displaymod command, followed by a list of modules which are separated by ,.
    Format: `displaymod c/MODULE_CODE,[MODULE_CODE]

displaymod1cexamplecmd
Figure 1. Single module code search command format

The search above should yield a result:

displaymod1cexampleresult
Figure 2. Single module code search result

However if students wishes to search for multiple modules at once they can follow the example given below:

displaymodMcexamplecmd
Figure 3. Multiple module codes search command format

The search above should yield a result:

displaymodMcexampleresult
Figure 4. Multiple module code search result
  • Search by name: There are cases where students may not remember or know the module code but vaguely remember the module name. Students who find themselves in such a situation can search for modules by their names by adding a n/ prefix after the displaymod command, followed by keyword/s that can be found in the module name. Keywords have to be separated by + symbol.
    Format: displaymod n/KEYWORD+[KEYWORD]

displaymod1nexamplecmd
Figure 5. Single module name search command format

The search above should yield a result:

displaymod1nexampleresult
Figure 6. Single module name search command result

However if students wishes to search for multiple modules at once they can follow the example given below:

displaymodMnexamplecmd
Figure 7. Multiple module name keyword search format

The search above should yield a result:

displaymodMnexampleresult
Figure 8. Multiple module name keyword search result

If the student has successfully managed to display a module of their choice, they will be presented with module/s containing several information that the student will find useful. The example below will show the information provided for each module after a successful search:

displaymoddisplay
Figure 9. What information each module contains

What each number displays:
1. Shows the module code and module name.
2. Shows which department the module belongs to.
3. Displays the amount of module credits a student can gain by reading this module.
4. Displays a brief description of the modules and potentially the topics that may be covered.
5. Contains the prerequisite tree for each module.
6. Contains workload load information, the values are meant to be read as Hours.

Contributions to the Developer Guide

Given below are sections I contributed to the Developer Guide, which is showcase my ability to write technical documentations. This section will contain information on how the ModuleInfo class is implemented and how the custom data structure ModuleTree has be designed to aid with displaying relevant information for students. This documentation will allow readers to understand the backend of this application and potentially aid them in improving this product or even morphing it again.

Storage component

Within the Storage component there are 2 types of storage classes:
1. read and write storage
2. read only storage

Read and write storage

StorageClassDiagram
Figure 10. Structure of the Storage Component

API : Storage.java The Storage component,

  • can save UserPref, UserInfo objects in json format and read it back.

  • can save the GradTrak data in json format and read it back.

Read-only storage

moduleinfostorage
CourseStorage
Figure 11. Structure of read-only storage components
  • loads ModuleInfoStorage and CourseStorage from json format into memory

Displaymod feature

Current implementation

displaymod is a command that displays the information of a module based on the search by the student. The main reason for implementing such a feature is so that students can have immediate access to all available modules in NUS instead of searching through the internet.

Creation of ModuleInfo

Most of the processing of this feature is done during the launch of the application. The modules are created as a object called ModuleInfo. These objects only contain vital information of a particular module and nothing else. This to ensure that only information relevant students are displayed. This process is done with aid of the Storage class, to be more exact it uses [Read-Only] extracting all the data from allModule.Json file found in the resources folder.

The figure below shows the class diagram for ModuleInfo :

ModuleInfoclass

As seen from above the ModuleInfo class is made up of 8 other classes:

ModuleInfoCode

ModuleInfoDepartment

ModuleInfoTitle

ModuleInfoWorkload

ModuleInfoCredits

ModuleInfoPrerequisite

ModuleInfoDescription

ModuleInfoPreclusion For V2.0

The information found in the modules are separated into their own class to maintain modularity in the code. All of these objects are created in the construction of the ModuleInfo Object.

moduleinfoconstructor

Generating prerequisite trees

Within the ModuleInfo class, the ModuleInfoPrerequisite class requires the most pre-processing. If a student wishes to take a particular module, they have to check if they can satisfy the prerequisites, thus presenting the prerequisite tree is paramount to the ModuleInfo class.

ModuleInfoPrerequisite contains a custom data structure called ModuleTree which can be found in the commons.Util package. It was place in the commons package since it was a data structure and other functions or feature may require the ModuleTree i.e. when adding/deleting modules from the ModuleTaken list of the student.

The ModuleTree data structure consist of "smaller" objects called Node, which can also be found in commons.Util. Node can represent one of the following information:

1. Head : The head/root of the ModuleTree which holds a value of the module code of the "larger" ModuleInfo object.

2. Operator : Either "OR" or "AND" to indicate if only one of the module is required to fulfill the prerequisite or all of the listed modules are required respectively.

3. Module Code : The module code that is required to meet the prerequisite.

PrerequisiteTreeAnnotated

The generatePrerequisiteTree() function is called after the ModuleInfoPrerequisite object has been created, since the ModuleTree is dependent on the String input prereq which later be saved as prerequisiteString.

PrerequisiteString

The input prerequisite usually comes in the format:

"Prerequisite":"[MA1312 or MA1521 or MA1505 or (MA1511 and MA1512)] and [ST2334 or ST2131 or ST2132] and [IS3106 or BT3103]"

The input value is then split into an array using regular expressions:

RegexSplitter

This helps with the arrangement of the ModuleTree as shown below:

prerequisiteStep1
Figure 12. Step 1:The first index String is used to create a minor tree
prerequisiteStep2
Figure 13. Step 2:Since the previous String ended with a "OR" the next String is made and added as a child to the predecessor.
prerequisiteStepFinal
Figure 14. Step 3:Finally,the same process is repeated with the other Strings until the tree is complete.

Making it into a list

The final part of this entire process is storing all the ModuleInfo objects into a list. Currently, we did this using an ObservableList<>, this is done so that we can take advantage of the FilteredList<> class by filtering the list using Predicates.

During initial launch, after each module’s information is converted into a ModuleInfo object, it will be added to a ModuleInfoList object which contains an ArrayList<ModuleInfo>. After all the modules are added into ModuleInfoList, ModuleInfoList will be passed into ModelManager and will be converted into an ObservableList<> called allModules. Following that, a FilteredList<> object called displaylist will also be constructed from the allModules ObservableList<>.

Observable

Whenever the student searches for a particular ModuleInfo , the ObservableList<> is always ready and the FilteredList<> will be updated using a Predicate List generated from the keywords searched by the student.

keywords

Design considerations

Aspect: ModuleTree data structure
  • Current implementation : Custom Module tree data structure

    • Pros: Able to handle "AND" or "OR" operations found in the prerequisite Tree.

    • Cons: Takes a extremely long time to implement and design. Not to mention extremely error-prone.

  • Alternative considered : Use a current JDK Tree data structure

    • Pros: Easy to deploy into current code base.

    • Cons: Unable to deal with special operations like "AND" or "OR".

Aspect: Storing ModuleInfo objects in an ObservableList<>

  • Current Implementation : ObservableList<> is used

    • Pros: Allows for FilteredList<> to be used based on predicates; easy implementation.

    • Cons: Requires additional classes to be implemented to handle the use of Predicates.

  • Alternative considered: Sticking to ArrayList<>

    • Pros: Easy to handle as it is a simple data structure.

    • Cons: Harder to search for ModuleInfo objects based on codes and keywords.