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:
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:
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:
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
:
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:
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.