PROJECT: TheTracker

Overview

TheTracker (v1.4) is a desktop application to help students track and plan different events and modules.

Summary of contributions

  • Major enhancements: added removeperson, list.

  • removeperson

    • What it does: allows the user to remove a person who was recently inserted into a module or occasion.

    • Justification: This feature helps the user, when a student is not in a module or occasion anymore, to remove the person from the said module or occasion.

  • list

    • What it does: allows the user to switch between contexts, the different contexts of PERSON, MODULE, and OCCASION.

    • Justification: This feature helps users contextualize.

  • Minor enhancement: added an autocomplete feature.

  • Code contributed: [Functional code & Test code]

  • Other contributions:

    • Project management:

      • Managed releases v1.3 - v1.4 (2 releases) on GitHub

    • Enhancements to existing features:

      • Updated the GUI color scheme (Pull request #184, #167)

      • Module, XML, UI Module Tests (Pull request #103, #87, #51)

Contributions to the User Guide

Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users.

Removing person from event: removeperson

A command which will remove a person from a module or an occasion.

Format for module:
removeperson pi/PERSON_INDEX mi/MODULE_INDEX
Format for occasion:
removeperson pi/PERSON_INDEX oi/OCCASION_INDEX

removeperson will only work if there is an existing person inside an existing module or occasion and vice versa.

If the person is not inside the module or occasion, or vice versa, it will not work.

If you cannot see your module or occasion to select to remove (as the GUI is in PERSON context), just click the menu bar items to swap context, and continue typing your command in the command box.

Listing all entries : list + person

The different list commands will show the specified list in TheTracker.

List all Persons: listperson

Switches context to that of PERSON in TheTracker.

It will show the complete list of persons in the TheTracker and the user is able to view the modules and occasions each person is taking.

Format: listperson

List all Modules: listmodule

Switches context to that of MODULE in TheTracker.

It will show the complete list of modules in the TheTracker and the user is able to view the students list of each module.

Format: listmodule

List all Occasions: listoccasion

Switches context to that of OCCASION in TheTracker.

It will show the complete list of occasions in the TheTracker and the user is able to view the attendance list of each occasion.

Format: listoccasion

If you have filtered the list using the find command, you can use the listperson, listmodule and listoccasion commands to populate the entire list again.

Autocomplete

A feature that gives a drop-down list of suggested commands based on substrings that a user types.

Examples:

"add" - addperson, addmodule, addoccasion are suggested.

You can use the up & down arrows to find your intended command in the drop-down list, and press Enter to select it.

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.

RemovePerson Feature

The removeperson command is a complementary feature to the insertperson command. It enables the removal of a Person from either a Module students list or an Occasion attendance list. This thus means that the module or occasion will be removed from the respective list that the Person carries. The activity diagram below illustrates what happens when removeperson is called:

RemovePersonActivityDiagram

Current Implementation

Currently, removeperson creates a whole new copy of the Person, and a whole new copy of the Module to replace. The difference with the copy and the original is that their internal elements contain one less element, and the new copy is populated with shallow duplicates.

A shallow duplicate is a copy but with an empty internal list. For example, a shallow duplicate of Person contains an empty module list and empty occasion list. A shallow duplicate of Module contains an empty students list.

The reason why this is done will be explained in the design considerations below.

Design Considerations

For this feature to be possible, it has to be possible to somehow remove the link between said Person and Module/Occasion. The link (or pointer) to the objects can be best illustrated in the class diagram below:

PersonModuleOccasionClassDiagram

As seen, the Person class is associated with the Module class and the Occasion class as Person stores a list of modules and occasions. A person can thus have associations with multiple modules and occasions. This relationship is bidirectional as a Module can have associations with multiple persons. This is the same for occasions with persons. There is no association between Module and occasion. Thus, the relationships between Person and module, & Person and occasion are bidirectional.

Let us take an example of a Person associated with many modules, and vice versa. A possible implementation of the removeperson feature may be to remove the pointers between said Person and the corresponding Module in mind. However, this is not feasible in TheTracker due to our implementation of VersionedAddressBook. TheTracker keeps various states of itself and its components after every command which changes an object. Below is a simple state list diagram of the VersionedAddressBook:

VersionedABStateListDiagram

When the user first opens up TheTracker, an instance of the VersionedAddressBook is opened and the currentStatePointer points to instance 1 as shown in the diagram. When the user changes the person object, an entirely new copy of the state of TheTracker is created and inserted as a new VersionedAddressBook with currentStatePointer being updated.

As removing a pointer from an object does not entail changing an attribute inside the object, a brand new object has to be created for every instance when removeperson is called. This would enable the removeperson command to be compatible with undo and redo which use the different VersionedAddressBook to complete the job.

This new object would have to be fundamentally almost an exact replica of the old object, with the only difference being the internal lists of modules Person keeps or internal lists of persons Module keeps. However, let us take an example Person who is linked to several Modules. If this Person severs links with a Module, and a new list is created (only without said Module), this means that the list will try to add the other Modules into itself. These other Modules already contain an old instance of this Person, but their lists will also have to be updated with the new Person, which is adding these Modules in the first place! This creates an infinite recursive loop.

To mitigate this problem, we had to make a shallow duplicate of the Person / Module / Occasion (with an empty list to prevent infinite recursion), and put in a complete duplicate (we named it deep duplicate) when repopulating the internal list of Person / Module / Occasion.

List feature

The list feature acts as a switching between the lists of Person, Module, Occasion. In essence, it acts as a context switch between the 3.

Current Implementation

Currently, the list command will raise a context switch event, a ShowPersonRequestEvent if the listperson command is called. This then tells the MainWindow to update with the correct list of persons in its list panel, and to change the browser panel to show the lists of Module and Occasion that Person may have.

private void handlePerson() {
    getBrowserPlaceholder().getChildren().clear();
    getEntityListPanelPlaceholder().getChildren().clear();
    personListPanel.clearSelection();

    personListPanel.updatePanel(logic.getFilteredPersonList());
    getBrowserPlaceholder().getChildren().add(personBrowserPanel.getRoot());
    getEntityListPanelPlaceholder().getChildren().add(personListPanel.getRoot());

    logic.setActiveType(PERSON);
    AttendanceListUtil.postClearEvent();
}

The above code shows how the MainWindow deals with the context switch, which includes the setting of the active type (the context of the current window), so that contextual commands such as delete and select are able to function properly with correct indices.

The following sequence diagram shows how the listperson operation works:

ListPersonSequenceDiagram

Design Considerations

We had to examine whether it was better to: Alternative 1: Be able to make all commands contextual, and commands cannot be used out of context. This means that the list will set the context to limit other commands.

Alternative 2: Leave it possible for other commands to be called even if the context is not correct.

In the end, we chose alternative 1 so that users have the freedom to call specific commands without even looking at the specific list of choice, and to have more freedom to play around in the application.

Autocomplete

The autocomplete feature is facilitated by a stored list of commands and its own parser on the user’s command line inputs. The parser will enable the autocomplete to check the user’s input against a list of commands which are final and known by the address book. The autocomplete parser will be checking after every input in the command line, making it a real time feature.

Current Implementation

Currently, the feature calls on ControlsFX API to enable the autocomplete feature. It uses TextFields to have an autocomplete binding on the command box created which takes in the user input for commands. The list is populated by an inbuilt base commands list where all possible known commands are stored.

Proposed Improvements (Coming in v2.0)

While checking, the feature will try to give a regex match of the command and also provide suggestions on correct arguments based on current entities stored in TheTracker’s address book.