Introduction
nustracker is a standalone desktop app that aims to help event directors and administrative personnel of NUS student organisations to manage the organisation of undergraduate student events more easily.
As this app is geared towards the tech-literate generation, it is designed to use a Command-Line Interface (CLI) to speed up usage for fast typists, while still making use of a clean Graphical User Interface (GUI).
nustracker allows event directors to manage student events attendance information of the large undergraduate student base.
- Introduction
- Setting up, getting started
- Design
- Implementation
- Documentation, logging, testing, configuration, dev-ops
- Appendix: Requirements
- Appendix: Instructions for manual testing
- Manual test cases:
Setting up, getting started
Refer to the guide Setting up and getting started.
Design
Architecture
The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
Main components of the architecture
Main
has two classes called Main
and MainApp
. It is responsible for,
- At app launch: Initializes the components in the correct sequence, and connects them up with each other.
- At shut down: Shuts down the components and invokes cleanup methods where necessary.
Commons
represents a collection of classes used by multiple other components.
The rest of the App consists of four components.
-
UI
: The UI of the App. -
Logic
: The command executor. -
Model
: Holds the data of the App in memory. -
Storage
: Reads data from, and writes data to, the hard disk.
How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete id/e1234567
.
Sequence diagram of execution of delete id/e1234567
Each of the four main components (also shown in the diagram above),
- defines its API in an
interface
with the same name as the Component. - implements its functionality using a concrete
{Component Name}Manager
class (which follows the corresponding APIinterface
mentioned in the previous point).
For example, the Logic
component defines its API in the Logic.java
interface and implements its functionality using the LogicManager.java
class which follows the Logic
interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component’s being coupled to the implementation of a component), as illustrated in the (partial) class diagram below.
The sections below give more details of each component.
UI component
The API of this component is specified in Ui.java
The UI consists of a MainWindow
that is made up of parts e.g.CommandBox
, ResultDisplay
, StudentListPanel
, StatusBarFooter
, EventListPanel
etc. All these, including the MainWindow
, inherit from the abstract UiPart<T>
class which captures the commonalities between classes that represent parts of the visible GUI.
The UI
component uses the JavaFX UI framework and heavily utilizes CSS as well. The layout of these UI parts are defined in matching .fxml
files that are in the src/main/resources/view
folder. For example, the layout of the MainWindow
is specified in MainWindow.fxml
The styling for the UI components is controlled by the DarkTheme.css
and LightTheme.css
files. These .css files
are also switched for every component whenever the user requests a change in theme, via the ThemeApplier
.
The UI
component,
- executes user commands using the
Logic
component. - listens for changes to
Model
data so that the UI can be updated with the modified data. - keeps a reference to the
Logic
component, because theUI
relies on theLogic
to execute commands. - depends on some classes in the
Model
component, as it displaysStudent
objects residing in theModel
.
Logic component
API : Logic.java
Here’s a (partial) class diagram of the Logic
component:
How the Logic
component works:
- When
Logic
is called upon to execute a command, it uses theAddressBookParser
class to parse the user command. - This results in a
Command
object (more precisely, an object of one of its subclasses e.g.,AddCommand
) which is executed by theLogicManager
. - The command can communicate with the
Model
when it is executed (e.g. to add a student). - The result of the command execution is encapsulated as a
CommandResult
object which is returned fromLogic
.
The Sequence Diagram below illustrates the interactions within the Logic
component for the execute("delete id/e0123456")
API call.
Detailed sequence diagram for delete id/e0123456

DeleteCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Here are the other classes in Logic
(omitted from the class diagram above) that are used for parsing a user command:
How the parsing works:
- When called upon to parse a user command, the
AddressBookParser
class creates anXYZCommandParser
(XYZ
is a placeholder for the specific command name e.g.,AddCommandParser
) which uses the other classes shown above to parse the user command and create aXYZCommand
object (e.g.,AddCommand
) which theAddressBookParser
returns back as aCommand
object. - All
XYZCommandParser
classes (e.g.,AddCommandParser
,DeleteCommandParser
, …) inherit from theParser
interface so that they can be treated similarly where possible e.g, during testing.
Model component
API : Model.java
The Model
component,
- stores the address book data i.e.,
- all
Student
objects (which are contained in aUniqueStudentList
object). - all
Event
objects (which are contained in aUniqueEventList
object).
- all
- stores the currently ‘selected’
Student
objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiableObservableList<Student>
that can be ‘observed’ - similarly, stores the currently ‘selected’
Event
objects as a separate filtered list which is exposed to outsiders as an unmodifiableObservableList<Event>
that can be ‘observed’ - the UI is bound to these lists so the UI can automatically update when the data in either list changes.
- stores a
UserPref
object that represents the user’s preferences. This is exposed to the outside as aReadOnlyUserPref
objects. - does not depend on any of the other three components (as the
Model
represents data entities of the domain, they should make sense on their own without depending on other components)
Storage component
API : Storage.java
The Storage
component,
- can save both address book data and user preference data in json format, and read them back into corresponding objects.
- inherits from both
AddressBookStorage
andUserPrefStorage
, which means it can be treated as either one (if only the functionality of only one is needed). - depends on some classes in the
Model
component (because theStorage
component’s job is to save/retrieve objects that belong to theModel
)
Common classes
Classes used by multiple components are in the nustracker.commons
package.
Implementation
This section describes some noteworthy details on how certain features are implemented.
Changing the profile picture glow feature
This feature allows the user to change the color of the glow surrounding the profile pictures, which by default is a purplish/pink (#e9affff).
The main mechanism behind this feature is the use of EventHandlers, provided by the JavaFX platform, to listen for color selections made by the user to update the glow accordingly.
A following is a snippet of how an EventHandler was attached to the ColorPicker (using pseudonym for ColorPicker.)
nameOfColorPicker.setOnAction(e -> {
updateGlowColor(getGlowHexCode());})
Next, the main mechanism.
There are a few classes at play for the main process:
-
ColorPicker
(default JavaFX class) SettingsWindow
ImageEditor
StudentListPanel
The following sequence diagram shows the typical chain of events within the internal system, followed by a brief description.
- When a color is selected (change detected), the
SettingsWindow#updateGlowColor()
is called. - There is a self-invocation of the
SettingsWindow#getGlowHexCode()
method, leading to the new glow color hex code being retrieved by usingColorPicker#getValue()
. - This value is then verified using the
ImageEditor#isValidColorHexCode()
. - This valid value (assuming Step 3 returns true, else
ImageStorage.DEFAULT_COLOR
is used) is then used as a parameter when callingStudentListPanel#updateGlow()
.
Next, let’s take a closer look at what happens within StudentListPanel.
- When
StudentListPanel#updateGlowColor()
is called, there is a self-invocation ofStudentListPanel#refreshPanel()
. - This then leads to another self invocation of the
StudentListPanel#fillPanelWithCells()
method. - Within the
StudentListPanel#fillPanelWithCells()
method, theListView#setItems()
andListView#setCellFactory()
methods are called. These methods—without going into too much detail—basically set the list that is used for ListView, and recreate every cell within in. For more information, please read the JavaFX documentation here.
That was an overall view of how this feature was implemented. Although there were retracted details, their absence will not undermine the understanding of the feature.
Design Considerations
-
Option 1 (Current): Change glow color via the ColorPicker GUI
This was chosen as the final choice over a command as it is more intuitive, as the user is able to browse through a large selection of colors and immediately view changes when selecting a color. -
Option 2 (CLI): Change glow color via a command
This was not chosen as it is much less intuitive, as the user would have to input a color hex code which the everyday user might not be aware of (like white is #ffffff, etc.). Additionally, changing the glow color usually occurs once and is not an action a user might perform repeatedly, further reducing the necessity of a command.
Creating an event
This is a feature to allow the user to create an event. Currently, each event has a name, date, time, participant list and blacklist. Users can specify the name, date and time of an event using the create
command.
This feature comes with the following classes:
- nustracker.logic.commands.CreateCommand
- nustracker.logic.parser.CreateCommandParser
- nustracker.model.event.*
The following sequence diagram shows how the create operation works:
Sequence diagram for creating an event
- Note that LogicManager is called using execute(“create n/Orientation d/08-01-2021 t/1000”). This information was truncated to reduce clutter in the diagram.
- The event is only added if there are no other events in the model that have the same name. This is checked using the
hasEvent
method.
The following sequence diagram shows how a create operation gets its arguments from the prefixes:
Sequence diagram for parsing a create command’s arguments
AddressBook contains a UniqueEventList to hold a list of events. UniqueEventList implements the Iterable<Event>
interface and stores events in an ObservableList<Event>
.
The following sequence diagram shows how an event is added to the UniqueEventList through the Model:
Sequence diagram for adding an event to UniqueEventList
- The UniqueEventList checks for duplicate events using the
hasEvent
method before adding the event. - After the event is added, the UI is immediately updated and the new event is reflected as an
EventCard
in theEventListPanel
.
Enrolling a Student into an Event
This is a feature to allow the user to enroll a student into an event. Currently, the implementation allows for each student to be enrolled into any chosen event as long as he/she is not on that event’s blacklist. A student could be enrolled into more than one event.
This feature comes with the following classes:
- nustracker.logic.commands.EnrollCommand
- nustracker.logic.parser.EnrollCommandParser
The following sequence diagram shows how the enroll operation works:
Sequence diagram for enrolling a student into an event
- Note that LogicManager is called using execute(“enroll id/e0322322 ev/Sports Camp”). This information was truncated to reduce clutter in the diagram.
- For details of how the EnrollCommand internally enrolls a student into an event internally, please check out the corresponding activity diagram below.
The following sequence diagram shows how a enroll operation gets its arguments from the prefixes:
Sequence diagram for parsing enroll command arguments
The following activity diagram shows how the enroll command enrolls a student into an event:
Activity diagram to show how the enroll command enrolls a student into an event
Filtering Feature
This is a feature to allow the user to filter the data by different fields. Currently, the implementation allows the user to filter by student IDs, names, majors, years, or event.
This feature comes with the following classes:
- nustracker.logic.commands.FilterCommand
- nustracker.logic.commands.FilterEventCommand
- nustracker.logic.commands.FilterIdCommand
- nustracker.logic.commands.FilterMajorCommand
- nustracker.logic.commands.FilterNameCommand
- nustracker.logic.commands.FilterYearCommand
- nustracker.logic.parser.FilterCommandParser
- nustracker.model.student.EnrolledEventsContainsKeywordsPredicate
- nustracker.model.student.MajorContainsKeywordsPredicate
- nustracker.model.student.NameContainsKeywordsPredicate
- nustracker.model.student.StudentIdContainsKeywordsPredicate
- nustracker.model.student.YearContainsKeywordsPredicate
The filter mechanism is facilitated by FilterCommand
, an abstract class that extends Command
.
Each field that can be used for filtering is created as a new child class which extends FilterCommand
(e.x. filtering by name is implemented in FilterNameCommand
).
Each one of these children classes has a predicate attribute which stores the keywords given by the user and uses them to filter the list of students.
The following class diagram gives an overview on the design of the filter
command
Class diagram for the filter command
- Notes that
FilterEventCommand
is the only class which extendsFilterCommand
and does not store a predicate, but anEventName
instead.
The following sequence diagram shows how filtering by student ID works:
Sequence diagram for filtering by student ID
-
FilterCommandParser
determines which field is used for filtering from the prefix that the user inputs (in this case the prefix isid/
, henceFilterCommandParser
callsFilterIdCommand
)
Exporting Feature
This is a feature to allow the user to export a given data field. Currently, the implementation only works for emails and can only export a csv file.
This feature comes with the following classes:
- nustracker.logic.commands.ExportCommand
- nustracker.logic.parser.ExportCommandParser
- nustracker.storage.Exporting
The following sequence diagram shows how the export operation works:
Sequence diagram for exporting
Design Considerations
-
Alternative 1 (current choice): Parameters are passed to the Exporting class to instruct it on how and what to export. There is only 1 Exporting class with 1 method.
- Pros: Commands are free from clutter, and all exporting changes are done in the Exporting class (i.e. formatting the string, choosing a filetype etc.)
- Cons: The Exporting class might become convoluted and complicated as it gets updated in the future.
-
Alternative 2: Each command manages its own formatting and passes the formatted content to Exporting class.
- Pros: Exporting class will have a very specific purpose and is very clear.
- Cons: Changes to a specific filetype might incur changes in many commands. (e.g. if the way that we export csv files is changed, then every command that exports as a csv file will have to change)
-
Alternative 3: Exporting class is extended to accommodate for filetypes, and also accounts for the formatting of the data.
- Pros: Very structured, easy to extend and add new commands that require export. Easy to add new filetypes for exporting and change which filetypes different commands use.
- Cons: Takes longer to implement than the other 2 options
In the end the first choice was chosen as it was more structured, and take less time to implement than alternative 3. We would consider alternative 3 to be the best long term option, and would implement it as such if time permitted.
[Proposed] Undo/redo feature
Proposed Implementation
The proposed undo/redo mechanism is facilitated by VersionedAddressBook
. It extends AddressBook
with an undo/redo history, stored internally as an addressBookStateList
and currentStatePointer
. Additionally, it implements the following operations:
-
VersionedAddressBook#commit()
— Saves the current address book state in its history. -
VersionedAddressBook#undo()
— Restores the previous address book state from its history. -
VersionedAddressBook#redo()
— Restores a previously undone address book state from its history.
These operations are exposed in the Model
interface as Model#commitAddressBook()
, Model#undoAddressBook()
and Model#redoAddressBook()
respectively.
Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
Step 1. The user launches the application for the first time. The VersionedAddressBook
will be initialized with the initial address book state, and the currentStatePointer
pointing to that single address book state.
Step 2. The user executes delete id/e1234567
command to delete the student with student ID “e1234567” in the address book. The delete
command calls Model#commitAddressBook()
, causing the modified state of the address book after the delete id/e1234567
command executes to be saved in the addressBookStateList
, and the currentStatePointer
is shifted to the newly inserted address book state.
Step 3. The user executes add n/David …
to add a new student. The add
command also calls Model#commitAddressBook()
, causing another modified address book state to be saved into the addressBookStateList
.

Model#commitAddressBook()
, so the address book state will not be saved into the addressBookStateList
.
Step 4. The user now decides that adding the student was a mistake, and decides to undo that action by executing the undo
command. The undo
command will call Model#undoAddressBook()
, which will shift the currentStatePointer
once to the left, pointing it to the previous address book state, and restores the address book to that state.

currentStatePointer
is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. The undo
command uses Model#canUndoAddressBook()
to check if this is the case. If so, it will return an error to the user rather
than attempting to perform the undo.
The following sequence diagram shows how the undo operation works:

UndoCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The redo
command does the opposite — it calls Model#redoAddressBook()
, which shifts the currentStatePointer
once to the right, pointing to the previously undone state, and restores the address book to that state.

currentStatePointer
is at index addressBookStateList.size() - 1
, pointing to the latest address book state, then there are no undone AddressBook states to restore. The redo
command uses Model#canRedoAddressBook()
to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
Step 5. The user then decides to execute the command events
. Commands that do not modify the address book, such as events
, will usually not call Model#commitAddressBook()
, Model#undoAddressBook()
or Model#redoAddressBook()
. Thus, the addressBookStateList
remains unchanged.
The following activity diagram summarizes what happens when a user executes a new command:
Design considerations:
Aspect: How undo & redo executes:
-
Alternative 1 (current choice): Saves the entire address book.
- Pros: Easy to implement.
- Cons: May have performance issues in terms of memory usage.
-
Alternative 2: Individual command knows how to undo/redo by
itself.
- Pros: Will use less memory (e.g. for
delete
, just save the student being deleted). - Cons: We must ensure that the implementation of each individual command are correct.
- Pros: Will use less memory (e.g. for
Documentation, logging, testing, configuration, dev-ops
Appendix: Requirements
Product scope
Target user profile:
- manpower and administrative personnel of NUS student organisations.
- has a need to manage the attendance of a significant number of students in their organisation.
- needs an app to collate their organisation’s events and their corresponding manpower/participants information in one place.
- prefers desktop apps over other types.
- can type fast and prefers typing to mouse interactions.
- is reasonably comfortable using CLI apps.
Value proposition:
- able to store information of students in an NUS student organisation.
- create and track attendance for the organisation’s events.
- manage attendance more efficiently and faster than a typical mouse/GUI driven app.
- automates the extraction of the contact details (like email) of an event’s participants.
User stories
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* * * |
potential user | easily get the app running | quickly start using the App |
* * * |
new user | view a tutorial of basic commands | learn how to use the software quickly |
* * * |
new user | view help screen | quickly refer to commands |
* * * |
user | view all the student data | keep track of all NUS undergraduate students |
* * * |
user | view all events | keep track of the student events that the user manages |
* * * |
user | exit the software | close the software |
* * * |
user | create a new student | add students newly admitted to NUS into the database |
* * * |
user | delete a student | delete students who have graduated from the database |
* * * |
user | create a new event | add new events to be managed using the app |
* * * |
user | delete an event | remove events that are no longer relevant |
* * * |
user | test the app using sample data | test the app and its commands easily before loading in real student data |
* * |
intermediate user | edit student data | update previous mistake in data entry or update a change in student data |
* * |
expert user | export email of selected students | use the email list to mass email relevant students |
* * |
expert user | export event data file | easily share or transfer event data to load in another computer |
* * |
expert user | export student data file | easily share or transfer the student database to load in another computer |
* * |
user | blacklist students from events | track which students are blacklisted from attending events |
* * |
user | remove students from an event’s blacklist | allow that student to attend the event |
* * |
user | load student data from external file | quickly add a large number of students |
* * |
user | load event data file | update the list of events being managed in database |
* * |
user | filter students by event | find students attending a particular event |
* * |
user | filter students by year | select students who have certain years of seniority in NUS |
* * |
user | view event list of student | see what events a student has attended before or are attending |
* * |
user | filter students by major | find students of a particular major |
* * |
user | filter students by faculty | find students from a particular faculty |
* * |
user | open settings menu | adjust the settings of the app to my preferences |
* * |
user | toggle between the events and students list | quickly and efficiently view the list I want to see |
* * |
user | use auto save | save the database constantly and automatically |
* |
expert user | mass edit student data | update data of similar students more efficiently |
Use cases
For all use cases below, the System is nustracker and the Actor is the user, unless specified otherwise.
Use case UC1 - Add a student
Preconditions: -
Guarantees: New student info is saved, and displayed.
MSS:
- User types in command.
- nustracker adds the user to the address book.
-
nustracker displays that user has been added, and corresponding details.
Use case ends
Extensions:
- 1a. User types in an invalid format.
- 1a1. nustracker shows an error message, and displays the correct format to use.
- 1b. A student with the same student ID, phone number or email already exists in nustracker.
- 1b1. nustracker shows an error message, and informs the user that a duplicate student already exists.
Use case ends.
- 1b1. nustracker shows an error message, and informs the user that a duplicate student already exists.
Use case UC2 - Delete a student
Preconditions: -
Guarantees: Student is deleted from program, and display is updated
MSS:
- User requests to delete a specific student in the list.
- nustracker deletes the student, and informs user.
Use case ends.
Extensions:
- 1a. User types in an invalid format
- 1a1. nustracker shows an error message, and displays the correct format to use.
Use case ends
- 1a1. nustracker shows an error message, and displays the correct format to use.
- 1b. The student does not exist.
- 1b1. nustracker shows an error message, informing the user that the student does not exist.
Use case ends.
- 1b1. nustracker shows an error message, informing the user that the student does not exist.
Use case UC3 - Filter students by name
Preconditions: -
Guarantees: The list of students is not altered
MSS:
- User requests to filter students by multiple names.
- nustracker displays a list of students whose names contain the specified keywords.
Use case ends.
Extensions:
- 1a. User types an incorrect format of the command.
- 1a1. nustracker shows an error message with the correct format of the command.
Use case ends.
- 1a1. nustracker shows an error message with the correct format of the command.
- 2a. nustracker does not find students with the specified name.
- 2a1. nustracker displays an empty list.
Use case ends.
- 2a1. nustracker displays an empty list.
Use case UC4 - Filter students by student ID
Preconditions: -
Guarantees: The list of students is not altered
MSS:
- User requests to filter students by multiple student IDs.
- nustracker displays a list of students whose student IDs contains the specified keywords.
Use case ends.
Extensions:
- 1a. User types an incorrect format of the command.
- 1a1. nustracker shows an error message with the correct format of the command.
Use case ends.
- 1a1. nustracker shows an error message with the correct format of the command.
- 1b. User types multiple prefixes to filter by.
- 1b1. nustracker shows an error message.
Use case ends.
- 1b1. nustracker shows an error message.
-
2a. The list of students is empty.
Use case ends. - 2b. nustracker does not find students with the specified Student IDs.
- 2b1. nustracker displays an empty list.
Use case ends.
- 2b1. nustracker displays an empty list.
Use case UC5 - Find the students attending a certain event
Preconditions: -
Guarantees: The list of students is not altered
MSS:
- User requests to filter students by event name.
- nustracker displays a list of students who are attending that event.
Use case ends.
Extensions:
- 1a. User types an incorrect format of the command.
- 1a1. nustracker shows an error message with the correct format of the command.
Use case ends.
- 1a1. nustracker shows an error message with the correct format of the command.
- 1b. User types multiple prefixes to filter by.
- 1b1. nustracker shows an error message.
Use case ends.
- 1b1. nustracker shows an error message.
-
2a. The list of students is empty.
Use case ends. - 2b. nustracker does not find any students attending the specified event.
- 2b1. nustracker displays an empty list.
Use case ends.
- 2b1. nustracker displays an empty list.
Use case UC6 - Filter students by year
Preconditions: -
Guarantees: The list of students is not altered
MSS:
- User requests to filter students by year.
- nustracker displays a list of students who are studying in that year.
Use case ends.
Extensions:
- 1a. User types an incorrect format of the command.
- 1a1. nustracker shows an error message with the correct format of the command.
Use case ends.
- 1a1. nustracker shows an error message with the correct format of the command.
- 1b. User types multiple prefixes to filter by.
- 1b1. nustracker shows an error message.
Use case ends.
- 1b1. nustracker shows an error message.
- 1c. User enters an invalid value for year.
- 1c1. nustracker shows an error message.
Use case ends.
- 1c1. nustracker shows an error message.
-
2a. The list of students is empty.
Use case ends. - 2b. nustracker does not find any students studying in the specified year.
- 2b1. nustracker displays an empty list.
Use case ends.
- 2b1. nustracker displays an empty list.
Use case UC7 - Filter students by major
Preconditions: -
Guarantees: The list of students is not altered
MSS:
- User requests to filter students by majors.
- nustracker displays a list of students who are studying the specified major.
Use case ends.
Extensions:
- 1a. User types an incorrect format of the command.
- 1a1. nustracker shows an error message with the correct format of the command.
Use case ends.
- 1a1. nustracker shows an error message with the correct format of the command.
- 1b. User types multiple prefixes to filter by.
- 1b1. nustracker shows an error message.
Use case ends.
- 1b1. nustracker shows an error message.
- 1c. User enters an invalid major.
- 1c1. nustracker shows an error message.
Use case ends.
- 1c1. nustracker shows an error message.
-
2a. The list of students is empty.
Use case ends. - 2b. nustracker does not find any students studying the specified major.
- 2b1. nustracker displays an empty list.
Use case ends.
- 2b1. nustracker displays an empty list.
Use case UC8 - Create an event
Preconditions: -
Guarantees: New event info is saved, and displayed
MSS:
- User types in command.
- nustracker adds the event to the address book.
- nustracker displays that the event has been added, and corresponding details.
Use case ends.
Extensions:
- 1a. User types in an invalid format
- 1a1. nustracker shows an error message, and displays the correct format to use.
Use case ends.
- 1a1. nustracker shows an error message, and displays the correct format to use.
- 1b. An event with the same name already exists in the address book.
- 1b1. nustracker shows an error message, informing the user that an event with the same name already exists.
Use case ends.
- 1b1. nustracker shows an error message, informing the user that an event with the same name already exists.
Use case UC9 - Delete an event
Preconditions: -
Guarantees: Event is deleted from program, and display is updated
MSS:
- User types in command.
- nustracker deletes the event from the address book.
- nustracker displays that the event has been deleted, and corresponding details.
- nustracker updates the students who are enrolled in the deleted event.
Use case ends.
Extensions:
- 1a. User types in an invalid format
- 1a1. nustracker shows an error message, and displays the correct format to use.
Use case ends.
- 1a1. nustracker shows an error message, and displays the correct format to use.
- 1b. The event does not exist in the address book.
- 1b1. nustracker shows an error message, informing the user that the event does not exist.
Use case ends.
- 1b1. nustracker shows an error message, informing the user that the event does not exist.
Use case UC10 - Blacklist a student
Preconditions: -
Guarantees: Student is blacklisted from the event, and display is updated
MSS:
- User types in command.
- nustracker adds student to the event’s blacklist.
- nustracker displays that the student has been blacklisted.
Use case ends.
Extensions:
- 1a. User types in an invalid format
- 1a1. nustracker shows an error message, and displays the correct format to use.
Use case ends.
- 1a1. nustracker shows an error message, and displays the correct format to use.
- 1b. The event does not exist in the address book.
- 1b1. nustracker shows an error message, informing the user that the event does not exist.
Use case ends.
- 1b1. nustracker shows an error message, informing the user that the event does not exist.
- 1c. The student is already in the event’s blacklist.
- 1c1. nustracker shows an error message, informing the user that the student is already in the event’s blacklist.
Use case ends.
- 1c1. nustracker shows an error message, informing the user that the student is already in the event’s blacklist.
- 1d. The student is enrolled in the event.
- 1d1. nustracker shows an error message, informing the user that the student is enrolled in the event.
Use case ends.
- 1d1. nustracker shows an error message, informing the user that the student is enrolled in the event.
Use case UC11 - Whitelist a student
Preconditions: -
Guarantees: Student is removed from the event’s blacklist, and display is updated
MSS:
- User types in command.
- nustracker removes student from the event’s blacklist.
- nustracker displays that the student has been removed from the blacklist.
Use case ends.
Extensions:
- 1a. User types in an invalid format
- 1a1. nustracker shows an error message, and displays the correct format to use.
Use case ends.
- 1a1. nustracker shows an error message, and displays the correct format to use.
- 1b. The event does not exist in the address book.
- 1b1. nustracker shows an error message, informing the user that the event does not exist.
Use case ends.
- 1b1. nustracker shows an error message, informing the user that the event does not exist.
- 1c. The student is not in the event’s blacklist.
- 1c1. nustracker shows an error message, informing the user that the student is not in the event’s blacklist.
Use case ends.
- 1c1. nustracker shows an error message, informing the user that the student is not in the event’s blacklist.
Use case UC12 - Enroll a student into an event
Preconditions: -
Guarantees: The student gets enrolled into the specified event if both the student and event exist.
MSS:
- User requests to enroll a student into an event.
- nustracker updates the event to have this student as a participant.
- nustracker updates the student to be enrolled into this event.
- nustracker shows that the student has now been enrolled.
Use case ends.
Extensions:
- 1a. User types in an invalid format.
- 1a1. nustracker shows an error message, and displays the correct format to use.
Use case ends.
- 1a1. nustracker shows an error message, and displays the correct format to use.
- 1b. The specified student does not exist in nustracker.
- 1b1. nustracker shows an error message, informing the user that the specified student does not exist.
Use case ends.
- 1b1. nustracker shows an error message, informing the user that the specified student does not exist.
- 1c. The specified event does not exist in nustracker.
- 1c1. nustracker shows an error message, informing the user that the specified event does not exist.
Use case ends.
- 1c1. nustracker shows an error message, informing the user that the specified event does not exist.
- 1d. The specified student is currently already enrolled into the event.
- 1d1. nustracker shows an error message, informing the user that the specified student is already currently enrolled.
Use case ends.
- 1d1. nustracker shows an error message, informing the user that the specified student is already currently enrolled.
Use case UC13 - Remove a student from an event
Preconditions: -
Guarantees: The student is not enrolled into the specified event after the use case ends.
MSS:
- User requests to remove a student from an event.
- nustracker updates the event to remove this student from being a participant.
- nustracker updates the student to not be enrolled into this event anymore.
- nustracker shows that the student has now been removed from the event.
Use case ends.
Extensions:
- 1a. User types in an invalid format.
- 1a1. nustracker shows an error message, and displays the correct format to use.
Use case ends.
- 1a1. nustracker shows an error message, and displays the correct format to use.
- 1b. The specified student does not exist in the nustracker.
- 1b1. nustracker shows an error message, informing the user that the specified student does not exist.
Use case ends.
- 1b1. nustracker shows an error message, informing the user that the specified student does not exist.
- 1c. The specified event does not exist in the nustracker.
- 1c1. nustracker shows an error message, informing the user that the specified event does not exist.
Use case ends.
- 1c1. nustracker shows an error message, informing the user that the specified event does not exist.
- 1d. The specified student is not currently enrolled into the event.
- 1d1. nustracker shows an error message, informing the user that the specified student cannot be removed from the event as the student is not a participant.
Use case ends.
- 1d1. nustracker shows an error message, informing the user that the specified student cannot be removed from the event as the student is not a participant.
Use case UC14 - Display event/student list
Preconditions: -
Guarantees: The full unfiltered event/student list is displayed.
MSS:
- User enters a command to show event/student list.
- nustracker shows the full unfiltered event/student list.
Use case ends.
Extensions:
- 1a. User types in an invalid format.
- 1a1. nustracker shows an error message, and displays the correct format to use.
Use case ends.
- 1a1. nustracker shows an error message, and displays the correct format to use.
- 2a. The student list is filtered by a previous filter command.
- 2a1. nustracker overwrites the filter, and displays the full unfiltered student list.
Use case ends.
- 2a1. nustracker overwrites the filter, and displays the full unfiltered student list.
Use case UC15 - Export emails
Preconditions: -
Guarantees: -
MSS:
- User requests to export emails from a list of students and provides the name of the file to save it in.
- nustracker exports the emails and places them in a save file.
- nustracker shows a confirmation message that the emails have been successfully exported.
Use case ends.
Extensions:
- 1a. User types in an invalid format.
- 1a1. nustracker shows an error message, and displays the correct format to use.
Use case ends.
- 1a1. nustracker shows an error message, and displays the correct format to use.
- 1b. User types in an invalid name for the save file.
- 1b1. nustracker shows an error message, informing the user that the file name they have chosen is invalid.
Use case ends.
- 1b1. nustracker shows an error message, informing the user that the file name they have chosen is invalid.
Use case UC16 - Change profile picture glow color
Preconditions: There are students within nustracker.
Guarantees: The profile picture glow color will change according to the user’s input.
MSS:
- User opens the Settings window.
- User opens the color picker, and selects color.
-
nustracker detects this change, and changes the profile picture glow color.
Use case ends.
Use case UC17 - Change profile picture glow color _via_ the .json file
Preconditions: There are students within nustracker.
Guarantees: The profile picture glow color will change according to the user’s input.
MSS:
- User closes nustracker.
- User opens the preferences.json file, and edits the profile color using a color hex code.
-
nustracker detects this change, and changes profile picture glow color.
Use case ends.
- 3a. User uses an invalid color hex code.
- 3a1. User opens nustracker.
- 3a1. nustracker detects an invalid hex code and uses the default color (#e9afff) instead.
- 3a2. User closes nustracker and sets hex code again.
Steps 3a1 to 3a2 are repeated until a valid color hex code is used.
Use case ends.
Use case UC18 - Set/Change profile picture
Preconditions: Image size is ideally less than 10mb, is a .png or .jpg image file, and is located within the profile-pictures folder that is created on system startup.
Guarantees: Student with the corresponding Student ID now has a profile picture.
MSS:
- User selects the image that they want to set as the target student (e1111111)’s profile picture.
- User renames the image to
e1111111
. - User refreshes nustracker or restarts it.
-
nustracker detects this change, and sets the student’s profile picture.
Use case ends.
Extensions:
- 4a. User renames the image wrongly
- 4a1. nustracker does not detect any changes, and student’s profile picture is not updated.
- 4a2. User renames image again.
- 4a3. User refreshes nustracker or restarts it.
Steps 4a1 to 4a3 are repeated until correct image name is used.
Use case ends.
Non-Functional Requirements
- Should work on any mainstream OS as long as it has Java
11
or above installed. - Should be able to hold up to 40000 students and still be able to respond to user input within 2 seconds.
- Should be able to hold a reasonable amount of events without any degradation in performance.
- A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands rather than using the mouse.
- Should be able to save all data on local storage.
- The application should work without having to be installed first.
Glossary
- Mainstream OS: Windows, Linux, Unix, OS-X
- Command-Line Interface: A text-based user interface allowing users to interact with applications by typing commands.
- Graphical User Interface: A graphical user interface that allows users to interact with applications through the use of interactive visuals.
- NUS: An abbreviation for National University of Singapore.
Appendix: Instructions for manual testing
Given below are instructions to test the app manually.

Launch and shutdown
-
Initial launch
-
Download the jar file and copy into an empty folder
-
Double-click the jar file. If you are using Mac, please start the .jar file via the terminal.
Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
-
-
Saving window preferences
-
Resize the window to an optimum size. Move the window to a different location. Close the window.
-
Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-
Manual test cases:
Create an event
- Assumptions: Sample data is loaded / Orientation Camp event exists in app.
- Test case 1:
create n/Orientation Camp d/10-08-2022 t/1030
- Expected: Error message saying event already exists is displayed.
- Test case 2:
create n/Practical Exam d/14-11-2021 t/1700
- Expected: Practical Exam event is created and displayed at the bottom of event list.
Enrolling a student
- Assumptions: Sample data is loaded / Sports Camp event and Student with student ID e1234567 exist in app.
- Test case 1:
enroll id/e1234567 ev/This event does not exist
- Expected: Error message saying event does not exist is displayed.
- Test case 2:
enroll id/e1234567 ev/Sports Camp
- Expected: Student is enrolled into the Sports Camp event and student ID e1234567 is displayed in its enrolled list.
Deleting an event
- Assumptions: Sample data is loaded / Math Olympiad event exists in app.
- Test case 1:
delete ev/This event does not exist
- Expected: Error message saying event does not exist is displayed.
- Test case 2:
delete ev/Math Olympiad
- Expected: The Math Olympiad event is deleted and removed from the event list.
Deleting a student
- Assumptions: Sample data is loaded / Student with student ID e1234567 exists in app.
- Test case 1:
delete id/e1234567 ev/Orientation Camp
- Expected: Error message saying delete command can only delete either a student or event at one time is displayed.
- Test case 2:
delete id/e1234567
- Expected: Student with student ID “e1234567” is deleted and removed from the student list.
Exporting a list of emails
- Assumptions: Sample data is loaded / The currently displayed student list is not empty.
- Test case 1:
export fn/Emails
- Expected: A file Emails.csv is created in the /data folder in your root directory where the app is run. The file will contain all the emails of the displayed students.
Test command inputs
- Test extraneous prefixes:
-
students n/abc
: command ignores prefix and executes as expected -
create n/Test event d/07-11-2021 t/1135 m/CS
: command does not accept extra prefixes and displayed invalid command message -
add n/Jeremy m/CS id/e9556882 y/4 p/90121325 e/jeremy@u.nus.edu p/84756230
: command takes the latest prefix and creates a new student with phone number 84756230
-
- Test invalid prefixes
-
delete id/1234567
: student ID requires an ‘e’ in front of 7 digits -
blacklist id/e1234567 ev/Orientation Camp!
: event name only allows alphanumeric characters and spaces -
add n/June m/BZA id/e8112233 y/1 p/81236540 e/june@a
: email’s domain (after @) has to be at least 2 characters long
-
Local Save File

addressbook.json
in the data folder, then open nustracker and type in a command to save the sample data into a save file.
-
Proper handling of a corrupted JSON save file
-
Go to the folder containing the save data (The folder named: data) and open
addressbook.json
. -
Choose a comma in the file and add a close curly brace character to the right of it like this:
,}
. Save your edits. -
Re-launch the app by double-clicking the jar file.
Expected: nustracker will not be able to load the data and the student and event lists are blank.
-
-
Proper handling of a JSON save file with missing data
-
Go to the folder containing the save data (The folder named: data) and open
addressbook.json
. -
Choose a student in the file and delete one or more of the lines containing student data.
-
Re-launch the app by double-clicking the jar file.
Expected: nustracker will not be able to load the data and the student and event lists are blank.
-
-
Proper handling of a JSON save file with conflicting data
i. Go to the folder containing the save data (The folder named: data) and open
addressbook.json
.ii. Choose a student in the file and take note of his/her student ID.
iii. Choose an event in the file, and add this student ID into both the participants list and the blacklist.
iv. If we choose a student with student ID
e0123456
and the eventPhysics Camp
, the data in the JSON file should look like this:Before: "participants" : [ ], "blacklist" : [ ]
After: "participants" : [ "e0123456" ], "blacklist" : [ "e0123456" ]
v. Re-launch the app by double-clicking the jar file.
Expected: nustracker will not be able to load the data and the student and event lists are blank.
Deleting a student
-
Deleting a student
-
Test case 1:
delete id/1234567
Prerequisites: Load sample data or ensure a student with the student id e1234567 exists in the address book.Expected: Student with student ID “e1234567” is deleted. Details of the deleted student shown in the status message. Timestamp in the status bar is updated.
-
Test case 2:
delete id/e0000000
Prerequisites: Load sample data or ensure no student has the student id e0000000 exists in the address book.Expected: No student is deleted. Error details shown in the status message. Status bar remains the same.
-
Test case 3:
delete id/e12345
Expected: Incorrect student id format. Error details shown in the status message. Status bar remains the same. -
Other incorrect delete commands to try:
delete id/
,delete id/abc
,delete id/[incorrect student id format]
(correct student id format :eXXXXXXX
where X is an integer from 0-9)
Expected: Similar to previous.
-
-
{ more test cases … }
Changing the profile picture

-
Test case 1:
Rename sample image name to e*******.png
Prerequisites: A student with Student IDe*******
exists within nustracker.
Expected: After using theRefresh
command or restarting nustracker, the student with Student IDe*******
has that particular profile picture. -
Test case 2:
Remove profile picture beloning to e*******
Prerequisites: A student with Student IDe*******
exists and currently has a profile picture (That is, there is an image in the profile-pictures with a name corresponding to the student’s Student ID).
Expected: After using theRefresh
command or restarting nustracker, the student’s profile picture reverts to the default image.