Developer Guide

Le Tracker Development ~
Welcome to the Developer Guide for Le Tracker!
This guide is intended to provide developers with an overview of the Le Tracker codebase, such as the design of the codebase and the implementation details of each feature as needed.
This guide also contains the requirements of Le Tracker to provide insights on the decision making process of the team and the goals of the application.
Before reading, it is recommended that developers read the User Guide first to gain an understanding of the features provided by Le Tracker.
Le Tracker was developed with Java 11 and thus, it is recommended that developers use this version of Java.
Table of Contents
- Acknowledgements
- Setting up, getting started
- Design
-
Implementation
- Navigation feature
- List module, lecture and video feature
- Find module, lecture and video feature
- Add module, lecture, and video feature
- Edit module, lecture, and video feature
- Delete module, lecture, and video feature
- Mark / UnMark video feature
- Tag module, lecture, and video feature
- Untag module, lecture, and video feature
- Exporting data feature
- Import archived data feature
- Clear feature
- Documentation, logging, testing, configuration, dev-ops
- Appendix: Requirements
- Appendix: Instructions for manual testing
- Appendix: Effort
- Appendix: Planned enhancements
Acknowledgements
- Forked from: AddressBook Level-3
- Libraries utilised: Jackson, JavaFX, JUnit 5
- Tools utilised: Gradle
Setting up, getting started
Refer to the guide Setting up and getting started.
Design
.puml files used to create diagrams in this document can be found in the diagrams folder. Refer to the PlantUML Tutorial at se-edu/guides to learn how to create and edit diagrams.
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 CS2040S.

Each of the four main components (also shown in the diagram above),
- defines its API in an
interfacewith the same name as the Component. - implements its functionality using a concrete
{Component Name}Managerclass (which follows the corresponding APIinterfacementioned 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, ModuleListPanel, StatusBarFooter etc. All these, including the MainWindow, inherit from the abstract UiPart class which captures the commonalities between classes that represent parts of the visible GUI.
The UI component uses the JavaFx UI framework. 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 UI component,
- executes user commands using the
Logiccomponent. - listens for changes to
Modeldata so that the UI can be updated with the modified data. - keeps a reference to the
Logiccomponent, because theUIrelies on theLogicto execute commands. - depends on some classes in the
Modelcomponent, as it displaysModule,Lecture,Videoobjects residing in theModel.
Logic component
API : Logic.java
Here’s a (partial) class diagram of the Logic component:

How the Logic component works:
- When
Logicis called upon to execute a command, several observers subscribe to theTrackerEventSystem. - The command text is first pre-processed (e.g.
NavigationInjectorcould modify the command text by inserting/mod CS2040S /lec Week 1). -
Logicthen uses theTrackerParserclass to parse the user command. - This results in a
Commandobject (more precisely, an object of one of its subclasses e.g.,AddCommand) which is executed by theLogicManager. - The command can communicate with the
Modelwhen it is executed (e.g. to add a module). - The result of the command execution is encapsulated as a
CommandResult. - Based on the
CommandResult, several systems such asNavigationare notified through theTrackerEventSystem. - The
CommandResultobject is then returned back fromLogic.
The Sequence Diagram below illustrates the interactions within the Logic component for the execute("add CS2040S") API call.

AddCommandParser 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
TrackerParserclass creates anXYZCommandParser(XYZis a placeholder for the specific command name e.g.,AddCommandParser) which uses the other classes shown above to parse the user command and create aXYZCommandobject (e.g.,AddVideoCommand) which theTrackerParserreturns back as aCommandobject. - All
XYZCommandParserclasses (e.g.,AddCommandParser,NavCommandParser, …) inherit from theParserinterface so that they can be treated similarly where possible e.g, during testing.
Navigation component
API: Navigation.java
Here’s a (partial) class diagram of the Navigation component:

** This class diagram omits some classes and dependencies in the Navigation component for the purpose of simplicity.
What the Navigation component does:
- Tracking the current working context.
- Tracking navigation through the hierarchy.
- Enforcing valid navigation between adjacent layers in the module-lecture-video hierarchy.
What the Navigation component is NOT RESPONSIBLE for:
- Ensuring that modules or lectures exist in the
Modelcomponent.- This avoids circular dependency as the
Modelcomponent already depends on theNavigationcomponent. - This enforces the single responsibility principle as the
Navigationcomponent does not need to verify the existence of actual module or lecture data in the Tracker system.
- This avoids circular dependency as the
For more information on the Navigation system and how to develop context-sensitive commands that work with the Navigation system, please refer the navigation feature.
Model component
API : Model.java

** This class diagram omits some classes and dependencies in the Model component for the purpose of simplicity (classes excluded include ModuleCode, ModuleName, LectureName, VideoName, Tag and other classes)
The Model component,
- stores the tracker data i.e., all
Moduleobjects which are contained in aUniqueModuleListobject, along with theLectureobjects contained in theUniqueLectureListobjects of saidModuleobjects, as well as theVideoobjects contained in theUniqueVideoListobjects of saidLectureobjects. - stores the currently ‘selected’
Moduleobjects (e.g., results of a search query) as a separate filteredModules list which is exposed to outsiders as an unmodifiableObservableList<Module>that can be ‘observed’ e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. - stores the currently ‘selected’
Lectureobjects (e.g., results of a search query) as a separate filteredLectures list which is exposed to outsiders as an unmodifiableObservableList<Lecture>that can be ‘observed’ e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. - stores the currently ‘selected’
Videoobjects (e.g., results of a search query) as a separate filteredVideos list which is exposed to outsiders as an unmodifiableObservableList<Video>that can be ‘observed’ e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. - stores the navigation component which tracks the current working context.
- stores a
UserPrefobject that represents the user’s preferences. This is exposed to the outside as aReadOnlyUserPrefobjects. - does not depend on any of the other three components (as the
Modelrepresents 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 tracker data and user preference data in json format, and read them back into corresponding objects.
- inherits from both
TrackerStorageandUserPrefStorage, which means it can be treated as either one (if only the functionality of only one is needed). - depends on some classes in the
Modelcomponent (because theStoragecomponent’s job is to save/retrieve objects that belong to theModel).
Common classes
Classes used by multiple components are in the seedu.addressbook.commons package.
Implementation
This section describes some noteworthy details on how certain features are implemented.
Navigation feature
The navigation system was designed to eliminate the need for users to repeat the same /mod /lec arguments for multiple commands. This is based on the observation that users often make multiple commands from the same context (i.e. tracking a specific module or lecture).
How the navigation system works
Similar to the cd command which changes the current working directory in Unix-based systems, the navigation commands (i.e. nav, navb) allows the user to navigate through the module-lecture-video hierarchy to a specified module or lecture. Once the user has navigated to a context, they do not need to include the /mod or /lec arguments for commands related to the current context.
Instead, the navigation system will inject /mod or /lec arguments into the user’s command based on the current working context. Hence, context-sensitive commands will be able to infer the specified module or lecture from these arguments without being directly coupled to the navigation system.
Navigation injection
Here’s a (partial) class diagram for the NavigationInjector component.

How NavigationInjector injects the correct arguments into the command based on the current working context:
-
When
Logicis called upon to execute a command, the command text string is first passed to theInjectorobject via itsinject(String, Model)method. -
The
NavigationInjectorimplementation ofInjectorthen obtains theNavigationContextobject which represents the current working context by communicating with theModel. -
The
NavigationInjectorthen injects the appropriate/modand/lecarguments that represent the current working context into the command text string based on the arguments obtained from theNavigationContextobject. -
The modified command text string is then returned back from
NavigationInjectortoLogic.
Usage scenario
Given below is an example usage scenario and how the navigation system behaves at each step.
Steps:
-
The user launches the application. The Navigation system is initialized with a root context as the current working context.
-
The user wants to navigate to the module CS2040S and executes the
nav CS2040Scommand. The following sequence diagram depictsnav CS2040S’s execution:
-
The user wants to navigate to the lecture Week 1 in the CS2040S context and executes the
nav Week 1command.
Designing context-sensitive commands
We want to reduce the need for similar sounding command names such as add-module, add-lecture, add-video which all involve the “adding” operation. Hence, these context-sensitive commands share a single command name such as add. To determine whether a module, lecture or video is being processed for a given command, we instead parse the context-specifying arguments such as /mod, /lec to instantiate the context specific command.
Hence, we define a common format for context-sensitive commands:
command [/mod {module_code}] [/lec {lecture_name}]
Parsing context-specifying arguments to determine context:
Has /mod argument |
Has /lec argument |
Context | Context Specific Command |
|---|---|---|---|
| No | No | Root Context | XYZModuleCommand |
| Yes | No | Module Context | XYZLectureCommand |
| Yes | Yes | Lecture Context | XYZVideoCommand |
If you are confused about why there appears to be a mismatch between Context and Context Specific Command (i.e. Module Context -> XYZLectureCommand), remember that a context specific command does NOT manipulate the context itself but the objects that are contained under that context (i.e. modules contain lectures).
Implementing your context-sensitive command based on this format will ensure seamless integration with the navigation system.
For concrete examples on how to implement a context-sensitive command, you can refer to the add command or edit command.
List module, lecture and video feature
The list command supports:
- Listing modules in the tracker
- Listing lectures in a module in the tracker
- Listing videos in a lecture which belongs to a module in the tracker
It’s behaviour is dependent on the arguments provided by the user.
The feature utilizes the following classes/variable:
-
ListCommandParser– Creates the appropriateListCommandsubclass object base on the user’s input -
ListCommand– Base class of anyCommandsubclass that list some entity in the tracker -
PREDICATE_SHOW_ALL_MODULES– ConstantPredicatewith typeReadOnlyModulethat list all modules -
LecturePredicate– Class that implementsPredicateinterface with typeReadOnlyLecture -
VideoPredicate– Class that implementsPredicateinterface with typeVideo
The following sequence diagram depicts a list command execution for listing lectures in a module in the tracker.

The following is a description of the code execution flow:
-
ListCommandParser#parse(String)takes the user’s input as an argument and determines the intent of the command as well as the appropriate subclass ofListCommandto create an object for. The following table describes how the intent is determined base on the arguments provided in the user’s input. Any combination of inputs that do not comply with the combination of arguments specified in the table is considered an error and will result in aParseExceptionbeing thrown and the command will not be executed.In Root Context:
Has /modargumentHas /lecargumentIntent PredicatetestedNo No List modules PREDICATE_SHOW_ALL_MODULESYes No List lectures LecturePredicateYes Yes List videos VideoPredicateIn Module Context:
Has /modargumentHas /lecargumentIntent PredicatetestedNo No List lectures LecturePredicateYes No List lectures LecturePredicateNo Yes List videos VideoPredicateYes Yes List videos VideoPredicateIn Lecture Context:
Has /modargumentHas /lecargumentIntent PredicatetestedYes No List lectures LecturePredicateNo Yes/No List videos VideoPredicateYes Yes List videos VideoPredicateIn All Context:
Has /rargumentIntent PredicatetestedYes List module PREDICATE_SHOW_ALL_MODULES -
The argument values are then checked for their validity by using the appropriate methods in
ParserUtil. If any of the values are invalid, aParserExceptionwill be thrown and the command will not be executed. -
The appropriate
ListCommandsubclass object is created and then returned to the caller. -
LogicManagercalls theCommand#execute(Model)method of theCommandobject returned byListCommandParser#parse(String). During execution of the command, aCommandExceptioncan be thrown for the following scenarios:- The
ModulewhichLecturesare to be listed does not exist - The
LecturewhichVideosare to be listed does not exist
- The
-
Note that extra arguments are ignored.
Examples:-
list /r fooorlist bar /r
list /r -
list bar /mod CS2040S
list /mod CS2040S
-
-
If no errors occur (no exceptions are thrown), the command succeeds in listing the modules/lectures/videos.
Find module, lecture and video feature
The find command supports:
- Finding a module in the tracker
- By module code and name
- By module tags
- Finding a lecture in a module in the tracker
- By lecture name
- By lecture tags
- Finding a video in a lecture which belongs to a module in the tracker
- By video name
- By video tags
It’s behaviour is dependent on the arguments provided by the user.
The feature utilizes the following classes:
-
FindCommandParser– Creates the appropriateFindCommandsubclass object base on the user’s input -
FindCommand– Base class of anyCommandsubclass that finds some entity in the tracker -
ModuleContainsKeywordsPredicate– Class that implementsPredicateinterface with typeReadOnlyModule -
ModuleTagContainsKeywordsPredicate– Class that implementsPredicateinterface with typeReadOnlyModule -
LectureNameContainsKeywordsPredicate– Class that implementsPredicateinterface with typeReadOnlyLecture -
LectureTagContainsKeywordsPredicate– Class that implementsPredicateinterface with typeReadOnlyLecture -
VideoNameContainsKeywordsPredicate– Class that implementsPredicateinterface with typeVideo -
VideoTagContainsKeywordsPredicate– Class that implementsPredicateinterface with typeVideo
The following sequence diagram depicts a find command execution for finding a module in the tracker.

Below is an activity diagram that showcase the event that occurs when find command is executed.

The following is a description of the code execution flow:
-
FindCommandParser#parse(String)takes the user’s input as an argument and determines the intent of the command as well as the appropriate subclass ofFindCommandto create an object for. The following table describes how the intent is determined base on the arguments provided in the user’s input. Any combination of inputs that do not comply with the combination of arguments specified in the table is considered an error and will result in aParseExceptionbeing thrown and the command will not be executed.In Root Context:
Has preamble Has /modargumentHas /lecargumentHas /byTagargumentIntent PredicatetestedYes No No No Find module ModuleContainsKeywordsPredicateYes No No Yes Find module ModuleTagContainsKeywordsPredicateYes Yes No No Find lecture LectureNameContainsKeywordsPredicateYes Yes No Yes Find lecture LectureTagContainsKeywordsPredicateYes Yes Yes No Find video VideoNameContainsKeywordsPredicateYes Yes No Yes Find video VideoTagContainsKeywordsPredicateIn Module Context:
Has preamble Has /modargumentHas /lecargumentHas /byTagargumentIntent PredicatetestedYes Yes/No No No Find lecture LectureNameContainsKeywordsPredicateYes Yes/No No Yes Find lecture LectureTagContainsKeywordsPredicateYes Yes/No Yes No Find video VideoNameContainsKeywordsPredicateYes Yes/No Yes Yes Find video VideoTagContainsKeywordsPredicateIn Lecture Context:
Has preamble Has /modargumentHas /lecargumentHas /byTagargumentIntent PredicatetestedYes Yes No No Find lecture LectureNameContainsKeywordsPredicateYes Yes No Yes Find lecture LectureTagContainsKeywordsPredicateYes No No No Find video VideoNameContainsKeywordsPredicateYes Yes Yes No Find video VideoNameContainsKeywordsPredicateYes No No Yes Find video VideoTagContainsKeywordsPredicateYes Yes Yes Yes Find video VideoTagContainsKeywordsPredicateIn All Context:
Has preamble Has /rargumentHas /byTagargumentIntent PredicatetestedYes Yes No Find module ModuleContainsKeywordsPredicateYes Yes Yes Find module ModuleTagContainsKeywordsPredicate -
The argument values are then checked for their validity by using the appropriate methods in
ParserUtil. If any of the values are invalid, aParserExceptionwill be thrown and the command will not be executed. -
The appropriate
FindCommandsubclass object is created and then returned to the caller. -
LogicManagercalls theCommand#execute(Model)method of theCommandobject returned byFindCommandParser#parse(String). During execution of the command, aCommandExceptioncan be thrown for the following scenarios:- The
Modulespecified by user does not exist when listingLectures - The
Lectureof aModuleor theModulespecified by user does not exist when listingVideos
- The
-
If no errors occur (no exceptions are thrown), the command succeeds in finding the module/lecture/video associated to the keyword.
Add module, lecture, and video feature
The add command supports:
- Adding a
Moduleobject to theTrackerobject contained in theModelManagerobject - Adding a
Lectureobject to aModuleobject contained in theTrackerobject - Adding a
Videoobject to aLectureobject contained in aModuleobject that is contained in theTrackerobject
It’s behaviour is dependent on the user’s input.
Notable Classes
-
AddCommandParser– Creates the appropriateAddCommandsubclass object base on the user’s input -
AddCommand– Base class of anyCommandsubclass that handles adding some entity to theTrackerobject -
AddModuleCommand– Subclass ofAddCommandwhich handles adding aModuleobject to theTrackerobject -
AddLectureCommand– Subclass ofAddCommandwhich handles adding aLectureobject to aModuleobject -
AddVideoCommand– Subclass ofAddCommandwhich handles adding aVideoobject to aLectureobject
Execution
The following sequence diagram depicts an add command execution for adding a Module object to the Tracker object.

Notes for AddCommandParser#parse(String)
-
The string passed in contains the arguments in the user’s input and is use to determine the intent of the command as well as the appropriate subclass of
AddCommandto create an object for. The following table describes how the intent is determined base on the arguments provided in the user’s input. Any combination of arguments not described in the table will result in aParseExceptionobject being thrown and the command will not be executed.Has preamble Has /modargumentHas /lecargumentIntent AddCommandsubclassYes No No Add ModuleobjectAddModuleCommandYes Yes No Add LectureobjectAddLectureCommandYes Yes Yes Add VideoobjectAddVideoCommand -
The argument values are checked for their validity by using the appropriate methods in the
ParserUtilclass. If any of the values are invalid, aParserExceptionobject will be thrown and the command will not be executed.
Notes for AddCommand#execute()
- A
CommandExceptionobject can be thrown for the following scenarios:- The
Module/Lecture/Videoobject is the same as another existingModule/Lecture/Videoobject according toModule#isSameModule(Module)/Lecture#isSameLecture(Lecture)/Video#isSameVideo(Video). - The
Moduleobject which aLectureobject is being added to does not exist. - The
Moduleobject which aLectureobject is specified to be in does not exist. - The
Lectureobject which aVideoobject is being added to does not exist.
- The
Edit module, lecture, and video feature
The edit command supports:
- Editing the details of a
Moduleobject in theTrackerobject contained in theModelManagerobject - Editing the details of a
Lectureobject belonging to aModuleobject contained in theTrackerobject - Editing the details of a
Videoobject belonging to aLectureobject contained in aModuleobject that is contained in theTrackerobject
It’s behaviour is dependent on the user’s input.
Notable Classes
-
EditCommandParser– Creates the appropriateEditCommandsubclass object base on the user’s input -
EditCommand– Base class of anyCommandsubclass that handles editing some entity of theTrackerobject -
EditModuleCommand– Subclass ofEditCommandwhich handles editing the details of aModuleobject belonging to theTrackerobject -
EditLectureCommand– Subclass ofEditCommandwhich handles editing the details of aLectureobject belonging to aModuleobject -
EditVideoCommand– Subclass ofEditCommandwhich handles editing the details of aVideoobject belonging to aLectureobject
Execution
The following sequence diagram depicts an edit command execution for editing the name of a Module object in the Tracker object.

Notes for EditCommandParser#parse(String)
-
The string passed in contains the arguments in the user’s input and is use to determine the intent of the command as well as the appropriate subclass of
EditCommandto create an object for. The following table describes how the intent is determined base on the arguments provided in the user’s input. Any combination of arguments not described in the table will result in aParseExceptionobject being thrown and the command will not be executed.Has preamble Has /modargumentHas /lecargumentIntent EditCommandsubclassYes No No Edit ModuleobjectEditModuleCommandYes Yes No Edit LectureobjectEditLectureCommandYes Yes Yes Edit VideoobjectEditVideoCommand -
The argument values are checked for their validity by using the appropriate methods in the
ParserUtilclass. If any of the values are invalid, aParserExceptionobject will be thrown and the command will not be executed. -
If no arguments related to updated fields are provided, a
ParseExceptionobject will be thrown and the command will not be executed.
Notes for EditCommand#execute()
- A
CommandExceptionobject can be thrown for the following scenarios:- The edited
Module/Lecture/Videoobject is the same as anotherModule/Lecture/Videoobject according toModule#isSameModule(Module)/Lecture#isSameLecture(Lecture)/Video#isSameVideo(Video). - The
Moduleobject which aLectureobject is specified to be in does not exist. - The
Lectureobject which aVideoobject is specified to be in does not exist.
- The edited
Delete module, lecture, and video feature
The delete command supports:
- Deleting a single specified module.
- Deleting a single specified lecture under a specified module context.
- Deleting a single specified video under a specified module and specified lecture context.
- Deleting multiple specified modules / lectures / videos under the respective specified contexts mentioned in the above points.
- E.g.: User wishes to delete a module CS2040S.
Executingdelete CS2040Swould allow the user to do so, unless the module does not exist, in which case, Le Tracker will throw an error. - E.g.: User wishes to delete multiple modules CS2107, ST2334 AND CS3230
Executingdelete CS2107, ST2334, CS3230will allow the user to do so. If either module does not exist, nothing is deleted and Le Tracker will throw an error.
- E.g.: User wishes to delete a module CS2040S.
This feature’s behaviour is dependent on the arguments provided by the user, as well as by the state of Le Tracker.
Implementation Details
The feature utilizes the following classes:
-
DeleteCommandParser: parses the arguments appropriately for the appropriateDeleteCommandto be returned to be executed -
DeleteCommand: Abstract class extending fromCommandsfor commands that delete a specified entity from the tracker -
DeleteModuleCommand: Subclass ofDeleteCommandwhich handles the deletion a module from the tracker -
DeleteLectureCommand: Subclass ofDeleteCommandwhich handles the deletion a lecture from a module in the tracker -
DeleteVideoCommand: Subclass ofDeleteCommandwhich handles the deletion a video from a lecture from a module in the tracker. -
DeleteMultipleModulesCommand: Subclass ofDeleteCommandwhich handles the deletion of multiple modules from the tracker -
DeleteMultipleLecturesCommand: Subclass ofDeleteCommandwhich handles the deletion of multiple lectures from the same module in the tracker -
DeleteMultipleVideosCommand: Subclass ofDeleteCommandwhich handles the deletion of multiple videos from the same lecture in the same module in the tracker. -
MultipleEventsParser: Interface that parses string for commands that can be executed on multiple objects at once
The following diagram shows the Class Diagram of the DeleteCommand hierarchy:

The following diagram shows the Sequence Diagram of parsing a delete command into a DeleteMultipleModulesCommand:

The following diagram shows the Sequence Diagram of the execution of a DeleteMultipleModulesCommand, which acts as a continuation of the above diagram:

The following is a description of the code execution flow
-
DeleteCommandParser#parse(String)takes the user’s input as aStringargument and determines the intention of the command (delete module, lecture or video). The following table below depicts the consideration of inputs against the user’s argument:Has Preamble has /modargumenthas /lecargumentIntent Yes No No Delete Module Yes Yes No Delete Lecture Yes Yes Yes Delete Video -
The argument values are then checked on as such:
- ModuleCode: valid mod code that begins with capital letters, followed by numbers. could optionally end with capital letters at the end
- LectureName: valid lecture name that does not contain symbols
- VideoName: valid video name that does not contain symbols
Note: ModuleCode, LectureName and VideoName should not contain commas (“,”). Rather than throwing as errors, Le Tracker will treat it as though the user intended to delete multiple entities
-
The appropriate
DeleteCommandsubclass object is created then returned to its caller.
-
DeleteModuleCommand: single module to be deleted -
DeleteMultipleModulesCommand: more than one module to be deleted -
DeleteLectureCommand: single lecture to be deleted -
DeleteMultipleLecturesCommand: more than one lecture to be deleted -
DeleteVideoCommand: single video to be deleted -
DeleteMultipleVideosCommand: more than one video to be deleted
- If no exceptions are thrown, Le Tracker has successfully managed to delete the specified module(s)/lecture(s)/video(s) the respective context.
Possible exceptions that could be thrown are:- Command contains duplicate entities to be deleted
- Invalid format for any entity
- Entity does not exist in respective context
- If
DeleteMultipleModulesCommand,DeleteMultipleLecturesCommandorDeleteMultipleVideosCommandis parsed, on execution, the command callsDeleteModuleCommand,DeleteLectureCommandorDeleteVideoCommandrespectively
Reasons for such implementation
- Adhering to Open-Close Principle: Open for Extension, Closed for Modification.
- Having abstract classes to group multiple commands together allows for adherence of DRY (Don’t Repeat Yourself) in cases such as
DeleteCommand.COMMAND_WORDin every class
Alternatives considered
- Combine all featured classes into one large single class
- Pros:
- all file content in one single place
- easily adheres to DRY since there would be no need to repeat information across multiple files
- Cons:
- violates Open-Close Principle
- creates a large file that needs to be edited. Hard to search through
- Pros:
Possible further implementation
- encapsulate conditional checks in each delete command execution
- capture the essence of DeleteMultipleModulesCommand in DeleteModuleCommand
- capture the essence of DeleteMultipleLecturesCommand in DeleteLectureCommand
- capture the essence of DeleteMultipleVideosCommand in DeleteVideoCommand
Mark / UnMark video feature
The mark command supports:
- Marking unmarked videos as watched
- Marking marked videos as unwatched
- Marking multiple videos in 1. and 2.
- E.g.: User wishes to mark multiple videos “Vid 1, Vid 2” in lecture “Week 1” of module “CS2040S” as watched.
Executingmark Vid 1, Vid 2 /mod CS2040S /lec Week 1would allow the user to do so, unless either one of the following conditions are true:- the module (CS2040S) does not exist in the Tracker
- the lecture (Week 1) does not exist in the module (CS2040S)
- either of the videos (Vid 1, Vid 2) does not exist in the lecture of the module (CS2040S > Week 1)
- either of the videos (Vid 1, Vid 2) has already been marked as watched
- E.g.: User wishes to mark multiple videos “Vid 3”, “Vid 4” and “Lecture Summary” in lecture “Topic 4” of module “ST2334” as unwatched.
Executingunmark Vid 3, Vid 4, Lecture Summary /mod ST2334 /lec Topic 1would allow the user to do so, unless either one of the following conditions are true:- the module (ST2334) does not exist in the Tracker
- the lecture (Topic 1) does not exist in the module (ST2334)
- either of the videos (Vid 3, Vid 4, Lecture Summary) does not exist in the lecture of the module (ST2334 > Topic 1)
- E.g.: User wishes to mark a single video “Vid 1” in lecture “Topic 4” of module “ST2334” as unwatched.
Executingunmark Vid 1 /mod ST2334 /lec Topic 4would allow the user to do so, unless either one of the following conditions are true:- the module (ST2334) does not exist in the Tracker
- the lecture (Topic 4) does not exist in the module (ST2334)
- the video (Vid 1) is already unmarked
- the video (Vid 1) does not exist in the lecture of the module (ST2334 > Topic 4)
- E.g.: User wishes to mark multiple videos “Vid 1, Vid 2” in lecture “Week 1” of module “CS2040S” as watched.
This feature’s behaviour is dependent on the arguments provided by the user, as well as the state of Le Tracker.
Note the difference between mark multiple and unmark multiple. As of current implementation, unmark multiple does not alert the user if video was already unmarked. However, unmark a single video does.
Implementation Details
The feature utilizes the following classes:
-
MarkCommand: Abstract class extending fromCommandfor commands that mark a specified video as watched or unwatched -
MarkAsWatchedCommandParser: parses arguments appropriately forMarkAsWatchedCommandto be returned to be executed -
MarkAsWatchedCommand: Subclass ofMarkCommandwhich handles marking a video as watched. Can handle marking multiple videos as well -
MarkAsUnwatchedCommandParser: parses arguments appropriately forMarkAsUnwatchedCommandandMarkMultipleAsUnwatchedCommandto be returned to be executed -
MarkAsUnwatchedCommand: Subclass ofMarkCommandwhich handles marking a video as unwatched -
MarkMultipleAsUnwatchedCommand: Subclass ofMarkCommandwhich handles marking multiple videos as unwatched -
MultipleEventsParser: Interface that parses string for commands that can be executed on multiple objects at once
The following diagram shows the Sequence Diagram of parsing a mark command into a MarkAsWatchedCommand:

The following diagram shows the Sequence Diagram of executing a MarkAsWatchedCommand, which adds on to the sequence diagram above:

As a comparison to the diagram above, the following diagram shows the Sequence Diagram of executing a MarkMultipleAsUnwatchedCommand:

The following is a description of the code execution flow:
-
MarkAsWatchedCommandParser#parse(String)/MarkAsUnwatchedCommandParser#parse(Stringtakes the user’s input as aStringargument and determines the target video to be marked. The following table below depicts the command returned against the user’s intentParser Has Multiple Videos Command MarkAsWatchedCommandParserYes / No MarkAsWatchedCommandMarkAsUnwatchedCommandParserYes MarkAsUnwatchedCommandMarkAsUnwatchedCommandParserNo MarkMultipleAsUnwatchedCommand -
The argument values are then checked on as such:
- ModuleCode: valid module code that complies with the module code format
- LectureName: valid lecture name that does not contain symbols
- VideoName: valid lecture name that does not contain symbols
Note: VideoName should not contain commas (“,”). Rather than throwing errors, Le Tracker will treat it as though the user intended to delete multiple videos
-
The appropriate
MarkCommandsubclass object is created then returned to its caller -
Upon execution, the argument values in the
MarkCommandsubclass object are then checked on as such:- ModuleCode: if module with ModuleCode exists in Le Tracker
- LectureName: if lecture with LectureName exists in module ModuleCode
- VideoName: if video(s) with VideoName exists in lecture LectureName of module ModuleCode and whether there are duplicates specified
- For
mark, the videos of the specified VideoName(s) are checked on whether they are marked as watched - For
unmarkand a single VideoName is specified, VideoName is checked on whether it is marked as unwatched - For
unmarkand multiple VideoNames are specified, VideoNames are not checked on whether they are marked as unwatched (unlike its counterparts)
- For
-
If no exceptions are thrown, Le Tracker has successfully managed to mark/unmark the specified video(s)
Reasons for such implementation
- Adhering to Open-Close Principle: Open for Extension, Closed for Modification
- Having abstract classes to group mark commands together allows for adherence of DRY (Don’t Repeat Yourself) in cases such as success message formats in every class
Alternatives considered
- Combine all featured classes into one large single class
Pros:
- all file content in one single place
- easily adheres to DRY since there would be no need to repeat information across multiple files Cons:
- violates Open-Close Principle
- creates a large file that needs to be edited. Hard to search through
Possible further implementation
- Update command result of
MarkMultipleAsUnwatchedCommandto catch when this command is called when the videos are already marked as unwatched, similar toMarkAsUnwatchedCommandandMarkAsWatchedCommand - Collate
MarkAsUnwatchedCommandandMarkMultipleAsUnwatchedCommandinto one class, similar toMarkAsWatchedCommand
Tag module, lecture, and video feature
The tag command supports:
- Adding multiple
Tagobjects to aModuleobject in aTrackerobject contained in theModelManagerobject - Adding multiple
Tagobjects to aLectureobject of aModuleobject contained in aTrackerobject - Adding multiple
Tagobjects to aVideoobject of aLectureobject contained in aModuleobject in aTrackerobject
The tag behaviour is dependent on the arguments provided by the user. Module objects, Lecture objects, and
Video objects can have multiple, unique Tag objects. If a command contains new tags and tags that were already
added to Module objects, Lecture objects, or Video objects, only the new tags will be added.
Notable Classes
The feature utilizes the following classes:
-
TagCommandParser– Creates the appropriateTagCommandobject based on the user’s input -
TagCommand– Handles addingTagobjects to aModule/Lecture/Videoobject based on the user’s input
Execution
The following sequence diagram depicts a tag command execution for adding a Tag object to a Module object in a
Tracker object.

The following is a description of the code execution flow:
-
TagCommandParser#parse()takes in the user input and determine whether the user wanted to tag a module, a lecture, or a video based on the appropriate prefixes included in the user’s input. -
The user input is then checked to determine whether it contains the required prefixes according to the table below. Any combination of inputs that do not satisfy the command’s required prefixes will be considered an error. A
ParseExceptionwill be thrown, and the command will not be executed.Intent has /modprefixhas /lecprefixhas /tagsprefixTag Module No No Yes Tag Lecture Yes No Yes Tag Video Yes Yes Yes - A set of
Tagobjects to add is then determined from the user’s input. Afterwards, The command creates an appropriateTagCommandobject and returns it to the caller. -
LogicManagercalls theCommand#execute()method of theTagCommandobject returned byTagCommandParser#parse(). During the execution, aCommandExceptionwill be thrown if no tags were provided, or if the tracker doesn’t contain the specifiedModuleobject,Lectureobject, orVideoobject. - If no exceptions are thrown, the command succeeds in adding
Tagobjects to theModuleobject,Lectureobject, orVideoobject.
Notes for TagCommandParser#parse()
- A
ParseExceptionwill be thrown if the appropriate prefixes according to the above table aren’t included.
Notes for TagCommand#execute()
- A
CommandExceptionwill be thrown for the following scenarios:- The user did not specify any tags to add.
- The current
Trackerobject does not contain the specifiedModule/Lecture/Videoobject.
Untag module, lecture, and video feature
The untag command supports:
- Removing multiple
Tagobjects from aModuleobject in aTrackerobject that is contained in aModelManagerobject - Removing multiple
Tagobjects from aLectureobject of aModuleobject in aTrackerobject - Removing multiple
Tagobjects from aVideoobject of aLectureobject which belongs to aModuleobject in aTrackerobject
The untag behaviour is dependent on the arguments provided by the user. Multiple Tag objects can be deleted in a
single command. If a command contains non-existent tags and tags that were already added to modules, lectures, or
videos, a CommandException will be thrown. Duplicated tags in the command, if any, will be ignored.
Notable Classes
The feature utilizes the following classes:
-
UntagCommandParser– Creates the appropriateUntagCommandobject based on the user’s input -
UntagCommand– Handles removingTagobjects from aModule/Lecture/Videoobject based on the user’s input
Execution
The following sequence diagram depicts an untag command execution for removing a Tag object from a Module object
in a Tracker object.

The following is a description of the code execution flow:
-
UntagCommandParser#parse()takes in the user input and determine whether the user wants to removeTagobjects aModule,Lecture, orVideoobject based on the appropriate prefixes included in the user’s input. -
The user input is then checked to determine whether it contains the required prefixes according to the table below. Any combination of inputs that do not satisfy the command’s required prefixes will be considered an error.
Intent has /modprefixhas /lecprefixhas /tagsprefixUntag Module No No Yes Untag Lecture Yes No Yes Untag Video Yes Yes Yes - A set of
Tagobjects to remove is then determined from the user’s input. Afterwards, the command creates an appropriateUntagCommandobject and returns it to the caller. -
LogicManagercalls theCommand#execute()method of theUntagCommandobject returned byUntagCommandParser#parse(). - If no exceptions are thrown, the command succeeds in removing the
Tagobjects from theModule/Lecture/Videoobject.
Notes for UntagCommandParser#parse()
- A
ParseExceptionwill be thrown if the appropriate prefixes according to the above table aren’t included.
Notes for UntagCommand#execute()
- A
CommandExceptionwill be thrown for the following scenarios:- The user did not specify any tags to remove.
- The current
Trackerobject does not contain the specifiedModule/Lecture/Videoobject. - The specified tags do not correspond with existing
Tagobjects in theModule/Lecture/Videoobject.
Exporting data feature
The export command supports:
- Saving a
Trackerobject and theModule,Lecture, andVideoobjects it contains to a new file path, in a JSON format file - Saving a
Trackerobject and theModule,Lecture, andVideoobjects it contains to an existing file path, in a JSON format file, overwriting its content
The export behaviour is dependent on the arguments provided by the user.
Notable Classes
The feature utilizes the following classes:
-
ExportCommandParser– Creates the appropriateExportCommandobject based on the user’s input -
ExportCommand– Creates the appropriateCommandResultobject containing the file path for export -
Archive– Handles saving theTrackerobject and theModule,Lecture, andVideoobjects it contains to the specified file path inCommandResult
Execution
The following sequence diagram depicts a export command execution for exporting a Tracker object to a specified
file path

The following is a description of the code execution flow:
-
ExportCommandParser#parse()takes in the user input and determine the file path that the user wants to export to, as well as whether the user wants to overwrite the data in the file path, if it exists, based on the/overwriteflag. - The command creates an appropriate
ExportCommandobject and returns it to the caller. -
LogicManagercalls theCommand#execute()method of theExportCommand. An appropriateCommandResultobject containing aPathobject with the saving file path is then returned to the caller. -
LogicManagercalls theArchive#exportToArchive()method. - If no exceptions are thrown, the command succeeds in saving the
Trackerobject and theModule,Lecture, andVideoobjects it contains to the specified file path.
Notes for ExportCommandParser#parse()
- A
ParseExceptionwill be thrown if the saving file path is not specified in user’s input.
Notes for ExportCommand#execute()
- A
CommandExceptionwill be thrown if the specified file path is invalid.
Notes for Archive#exportToArchive()
- A
CommandExceptionwill be thrown for the following scenarios:- The file at the specified file path does not have write permission.
- The user is trying to export to the current working tracker path.
- The user is trying to export to an existing file without the
/overwriteflag.
Import archived data feature
The import command supports:
- Importing all
Moduleobjects from a valid Le Tracker data file into the currentTrackerobject - Importing all
Moduleobjects from a valid Le Tracker data file into the currentTrackerobject, overwriting currentModuleobjects with importedModuleobjects if these modules exist in the currentTrackerobject - Importing specific
Moduleobjects from a valid Le Tracker data file into the currentTrackerobject - Importing specific
Moduleobjects from a valid Le Tracker data file into the currentTrackerobject, overwriting currentModuleobjects with importedModuleobjects if these modules exist in the currentTrackerobject
The import behaviour is dependent on the arguments provided by the user.
Notable Classes
The feature utilizes the following classes:
-
ImportCommandParser- Creates the appropriateImportCommandobject based on the user’s input -
ImportCommand- Creates the appropriateCommandResultobject containing the file path for import and the set ofModuleCodeobjects that references theModuleobjects to import -
Archive- Handles importingModuleobjects from the file path inCommandResultto the currentTrackerobject
Execution
The following sequence diagram depicts a import command execution for importing a single module from a specified
file path to the current Tracker object


The following is a description of the code execution flow:
-
ImportCommandParser#parse()takes in the user input and determine the file path that the user wants to import from, as well as whether the user wants to overwrite the data in the file path, if it exists, based on the/overwriteflag. - The command creates an appropriate
ImportCommandobject and returns it to the caller. -
LogicManagercallsCommand#execute()method of theImportCommandobject. An appropriateCommandResultobject containing aPathobject with the importing file path and a set ofModuleCodeobjects to reference theModuleobjects to import is then returned to the caller. -
LogicManagercalls theArchive#importFromArchive()method. TheArchiveobject then checks whether the modules in user’s input exist in the current Tracker, and in the specified file path. - If no exceptions are thrown, the command succeeds in importing
Moduleobjects from the specified file path to the currentTrackerobject.
Notes for ImportCommandParser#parse()
- A
ParseExceptionwill be thrown for the following scenarios:- The user specified
/modwithout providing any module code - The importing file path is not specified in user’s input
- The user specified
Notes for ImportCommand#execute()
- A
CommandExceptionwill be thrown if the specified file path is invalid.
Notes for Archive#importFromArchive()
- A
CommandExceptionwill be thrown for the following scenarios:- The file doesn’t exist in the specified file path.
- The file doesn’t have read permission
- The file isn’t a valid Le Tracker data file
- The user is importing modules that doesn’t exist in the saving file
- The user is importing modules that exists in the current
Trackerobject without the/overwriteflag
Clear feature
The clear feature supports clearing the entire tracker of all modules, lectures and videos
The feature utilizes the following classes:
-
ClearCommand- executable command to clear modules, lectures and videos in the tracker
The following is a description of the code execution flow:
-
TrackerParser#parseCommandparses based on the command wordclearto identify that the Clear feature is being called. -
ClearCommand#execute(Model)callsModel#clearTrackerto clear the tracker
Reasons for such implementation
- This implementation allows for adherence to basic Object Oriented Programming principles
Possible further implementation
- add a prompt to check with user whether they really want to clear everything since the command is irreversible
Documentation, logging, testing, configuration, dev-ops
Appendix: Requirements
Product scope
Target user profile:
- NUS students
- Fast typists
- Prefers typing to mouse interactions
- Prefers desktop apps over other types
- Is reasonably comfortable with using CLI apps
- Is attending modules with recorded lectures
- Is having difficulty keeping track of which lecture videos he/she has watched
- Possibly falling behind on lecture materials
- Possibly feeling overwhelmed by large number of lectures per week
Value proposition:
- Track lecture watch progress by recorded videos
- Get an overall glance of one’s watch progress on a module by module or lecture by lecture basis
User stories
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Implemented | Priority | As a/an … | I can … | So that I can… |
|---|---|---|---|---|
* * * |
new user | access a guide on how to use the app | learn how to use the app | |
* * * |
user | add a video | track what videos I have watched | |
* * * |
user | add a lecture | track my watch progress by lectures and organise my videos by lectures | |
* * * |
user | add a module | track my watch progress by modules and organise my lectures | |
* * * |
user | edit details of existing modules | add new details and correct mistakes | |
* * * |
user | edit details of existing lectures | add new details and correct mistakes | |
* * * |
user | edit details of existing videos | add new details and correct mistakes | |
* * * |
user | delete specific modules | remove modules that were added by accident or are no longer relevant to my studies (e.g. dropped / completed) | |
* * * |
user | delete specific lectures | remove lectures that were added by accident | |
* * * |
user | delete specific videos | remove videos that were added by accident | |
* * * |
user | mark videos that I have watched | keep track of which videos I have watched | |
* * * |
user | unmark videos that I have previously marked as watched | correct my mistakes when I mark a video by accident | |
* * * |
user | list my modules | view the details of all modules that are being tracked by the app | |
* * * |
user | list lectures of a specific module | view the details of all lectures of a module | |
* * * |
user | list videos of a specific lecture | view the details of all videos of a lecture | |
* * |
user | find modules, lectures or videos by relevant keywords | can avoid wasting time manually searching through a list to find a specific module, lecture, or video | |
* * |
user | add tags to modules | label and organise my modules more effectively | |
* * |
user | add tags to lectures | label and organise my lectures more effectively | |
* * |
user | add tags to videos | label and organise my lectures more effectively | |
* * |
user | remove tags from modules | remove tags that are no longer relevant or added by accident | |
* * |
user | remove tags from lectures | remove tags that are no longer relevant or added by accident | |
* * |
user | remove tags from videos | remove tags that are no longer relevant or added by accident | |
* * |
user | delete all modules | remove obsolete modules quickly after a semester is over or clear sample modules | |
* * |
user | set timestamps on videos | track where I last left off on a video | |
* * |
user | view the overall watch progress of a module | have an idea of how much progress I have made for a module and how much more progress is left | |
* * |
user | view the overall watch progress of a lecture | have an idea of how much progress I have made for a lecture and how much more progress is left | |
* * |
user | export my progress data to a new file | backup my data or transfer it to a new device | |
* * |
user | export my progress data to an existing file | updated the back up data incase I drop a module or take an add-on module during the semester | |
* * |
user | import all my modules progress | restore my tracker should I change or wipe my device | |
* * |
user | import some of my module progress | revise and relearn the concepts in specific modules I have studied, as well as track whether my productivity level improved | |
* * |
forgetful user | be reminded of where to find the guide | relearn how to use the app | |
* * |
user | navigate through the hierarchy of modules, lectures, and videos | not type the same lengthy arguments each time I type a command | |
* |
user | delete multiple modules of my choosing through one action | quickly remove multiple modules that were added by accident or are no longer relevant to my studies (e.g. dropped / completed) | |
* |
user | delete multiple lectures of my choosing through one action | quickly remove lectures that were added by accident | |
* |
user | delete multiple videos of my choosing through one action | quickly remove videos that were added by accident | |
* |
user | mark multiple videos that I have watched through one action | quickly update my progress when I open up the app after watching multiple videos | |
* |
user | unmark multiple videos that I have previously marked as watched through one action | quickly fix my mistake when I mark multiple videos by accident | |
* |
user | scroll commands I have previously executed | execute similar commands without typing out the command again | |
* |
unmotivated user | feel rewarded for making progress in watching lecture videos | be motivated to keep up or catch up with the syllabus | |
* |
user | be notified when a new lecture video is out | stay up to date with my lectures | |
* |
user | store summaries/notes for lectures | reference those notes when I’m revising the contents of the lecture |
Use cases
(For all use cases below, the System is Le Tracker and the Actor is the user, unless specified otherwise)
Navigate to a lecture context
MSS
- User requests to navigate to a specific lecture belonging to a specific module.
-
Le Tracker navigates to the specified lecture and displays a confirmation message.
Use case ends.
Extensions
-
1a. The user does not enter sufficient details for the lecture.
-
1a1. Le Tracker shows an error message.
Use case ends.
-
-
1b. The specified lecture or module does not exist.
-
1b1. Le Tracker shows an error message.
Use case ends.
-
List modules
MSS
- User wants to see all modules and executes list modules command.
-
A list of modules is populated.
Use case ends.
Extensions
-
1a. The list command is invalid.
-
1a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
List module’s lectures
MSS
- User wants to see all lectures of a module and executes list lectures command with module supplied.
-
A list of lectures of specified module is populated.
Use case ends.
Extensions
-
1a. The module does not exist.
-
1a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
1b. The list command is invalid.
-
1b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
List lecture’s videos
MSS
- User wants to see all videos of a lecture in a module and executes list videos command with a module and a lecture supplied.
-
A list of videos of the specified lecture in the specified module is populated.
Use case ends.
Extensions
-
1a. The module does not exist.
-
1a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
1b. The lecture does not exist.
-
1b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
1c. The list command is invalid.
-
1c1. Le Tracker shows an error message.
Use case resumes at step 1.
-
Find module
MSS
- User wants to find modules that starts with a keyword and executes find modules command with keyword supplied.
-
A list of modules relevant to the keyword is populated.
Use case ends.
-
1a. The keyword is in wrong format.
-
1a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
1b. The find command is invalid.
-
1b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
Find lecture
MSS
- User wants to find lectures in a module that starts with a keyword and executes find lecture command with module and keyword supplied.
-
A list of lectures in the specified module which are relevant to the keyword is populated.
Use case ends.
-
1a. The keyword is in wrong format.
-
1a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
1b. The module does not exist.
-
1b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
1c. The find command is invalid.
-
1c1. Le Tracker shows an error message.
Use case resumes at step 1.
-
Find video
MSS
- User wants to find videos in a lecture belonging in a module that starts with a keyword and executes find video command with module, lecture and keyword supplied.
-
A list of videos in the specified lecture in the specified module which are relevant to the keyword is populated.
Use case ends.
-
1a. The keyword is in wrong format.
-
1a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
1b. The module does not exist.
-
1b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
1c. The lecture does not exist.
-
1c1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
1d. The find command is invalid.
-
1d1. Le Tracker shows an error message.
Use case resumes at step 1.
-
Add a module
MSS
- User requests to add a module and specifies the details of the module.
-
Le Tracker adds the module.
Use case ends.
Extensions
-
1a. The user does not enter sufficient details for the module.
-
1a1. Le Tracker shows an error message.
Use case ends.
-
-
1b. One or more of the details specified is invalid.
-
1b1. Le Tracker shows an error message.
Use case ends.
-
-
1c. The module to be added is a duplicate of an existing module in Le Tracker.
-
1c1. Le Tracker shows an error message.
Use case ends.
-
Add a lecture
MSS
- User requests to add a lecture to a module and specifies the details of the lecture.
-
Le Tracker adds the lecture.
Use case ends.
Extensions
-
1a. The module to add the lecture to does not exist.
-
1a1. Le Tracker shows an error message.
Use case ends.
-
-
1b. The user does not enter sufficient details for the lecture.
-
1b1. Le Tracker shows an error message.
Use case ends.
-
-
1c. One or more of the details specified is invalid.
-
1c1. Le Tracker shows an error message.
Use case ends.
-
-
1d. The lecture to be added is a duplicate of an existing lecture in the module.
-
1d1. Le Tracker shows an error message.
Use case ends.
-
Add a video
MSS
- User requests to add a video to a lecture of a module and specifies the details of the video.
-
Le Tracker adds the video.
Use case ends.
Extensions
-
1a. The module that is supposed to contain the lecture does not exist.
-
1a1. Le Tracker shows an error message.
Use case ends.
-
-
1b. The lecture to add the video to does not exist.
-
1b1. Le Tracker shows an error message.
Use case ends.
-
-
1c. The user does not enter sufficient details for the video.
-
1c1. Le Tracker shows an error message.
Use case ends.
-
-
1d. One or more of the details specified is invalid.
-
1d1. Le Tracker shows an error message.
Use case ends.
-
-
1e. The video to be added is a duplicate of an existing video in the lecture.
-
1e1. Le Tracker shows an error message.
Use case ends.
-
Edit a module
MSS
- User requests to edit a module and specifies the updated details for the module.
-
Le Tracker edits the module.
Use case ends.
Extensions
-
1a. The module the user is requesting to edit does not exist.
-
1a1. Le Tracker shows an error message.
Use case ends.
-
-
1b. The user does not enter any updated details.
-
1b1. Le Tracker shows an error message.
Use case ends.
-
-
1c. One or more of the updated details specified is invalid.
-
1c1. Le Tracker shows an error message.
Use case ends.
-
-
1d. The resulting edited module is a duplicate of another module in Le Tracker.
-
1d1. Le Tracker shows an error message.
Use case ends.
-
Edit a lecture
MSS
- User requests to edit a lecture of a module and specifies the updated details of the lecture.
-
Le Tracker adds the lecture.
Use case ends.
Extensions
-
1a. The module that is supposed to contain the lecture to edit does not exist.
-
1a1. Le Tracker shows an error message.
Use case ends.
-
-
1b. The lecture the user is requesting to edit does not exist.
-
1b1. Le Tracker shows an error message.
Use case ends.
-
-
1c. The user does not enter any updated details.
-
1c1. Le Tracker shows an error message.
Use case ends.
-
-
1d. One or more of the updated details specified is invalid.
-
1d1. Le Tracker shows an error message.
Use case ends.
-
-
1e. The resulting edited lecture is a duplicate of another lecture in the module.
-
1e1. Le Tracker shows an error message.
Use case ends.
-
Edit a video
MSS
- User requests to edit a video of a lecture belonging to a module and specifies the updated details of the video.
-
Le Tracker adds the lecture.
Use case ends.
Extensions
-
1a. The module that is supposed to contain the lecture does not exist.
-
1a1. Le Tracker shows an error message.
Use case ends.
-
-
1b. The lecture that is supposed to contain the video to edit does not exist.
-
1b1. Le Tracker shows an error message.
Use case ends.
-
-
1c. The video the user is requesting to edit does not exist.
-
1c1. Le Tracker shows an error message.
Use case ends.
-
-
1d. The user does not enter any updated details.
-
1d1. Le Tracker shows an error message.
Use case ends.
-
-
1e. One or more of the updated details specified is invalid.
-
1e1. Le Tracker shows an error message.
Use case ends.
-
-
1f. The resulting edited video is a duplicate of another video in the lecture.
-
1f1. Le Tracker shows an error message.
Use case ends.
-
Delete a Module
Preconditions: User has added a module
MSS
- User requests to delete the specific module by specifying the module code
-
Le Tracker deletes the module
Use case ends.
Extensions
-
1a. The given module code does not follow the module code format.
-
1a1. Le Tracker shows an error message.
Use case ends.
1b. Module of module code does not exist in Le Tracker.
-
1b1. Le Tracker shows an error message.
Use case ends.
-
Delete multiple Modules
Preconditions: User has added a few modules
MSS
- User requests to delete specific modules by specifying their respective module codes
- Le Tracker deletes the specified modules
Use case ends.
Extensions
-
1a. At least one of module codes supplied does not follow the module code format.
-
1a1. Le Tracker shows an error message.
Use case ends.
-
-
1b. Module codes supplied contains duplicates.
-
1b1. Le Tracker shows an error message.
Use case ends.
-
-
1c. At least one of the module codes supplied does not belong to any module in Le Tracker.
-
1c1. Le Tracker shows an error message.
Use case ends.
-
Delete a Lecture
Preconditions: User has added a module and a lecture
MSS
- User requests to delete a specific lecture by specifying a module code and lecture name
-
Le Tracker deletes the lecture
Use case ends.
Extensions
-
1a. The supplied module code does not follow the module code format.
-
1a1. Le Tracker shows an error message.
Use case ends.
-
-
1b. The supplied lecture name does not follow the lecture name format.
-
1b1. Le Tracker shows an error message.
Use case ends.
-
-
1c. The module of module code that is supposed to contain the lecture of lecture name does not exist.
-
1c1. Le Tracker shows an error message.
Use case ends.
-
-
1d. The lecture of lecture name does not exist in module of module code.
-
1d1. Le Tracker shows an error message.
Use case ends.
-
Delete multiple Lectures
Preconditions: User has added a module and a few lectures
MSS
- User specifies multiple lecture names to be deleted and a module code
-
Le Tracker deletes the specified lectures of lecture names from the specified module of module code
Use case ends.
Extensions
-
1a. The module code specified does not follow the module code format.
-
1a1. Le Tracker shows an error message.
Use case ends.
-
-
1b. At least one of the lecture names supplied does not follow the lecture name format.
-
1b1. Le Tracker shows an error message.
Use case ends.
-
-
1c. Lecture names supplied contains duplicates.
-
1c1. Le Tracker shows an error message.
Use case ends.
-
-
1d. The module of module code does not exist in Le Tracker.
-
1d1. Le Tracker shows an error message.
Use case ends.
-
-
1e. At least one lecture of the supplied lecture names does not exist in the module of module code.
-
1e1. Le Tracker shows an error message.
Use case ends.
-
Delete a Video
Preconditions: User has added a module, a lecture and a video
MSS
- User requests to delete a specific video by citing its video name, lecture name of the lecture that contains it, and the module code of the module that contains the lecture
-
Le Tracker deletes the video from the lecture of the module
Use case ends.
Extensions
-
1a. Module code supplied does not follow the module code format.
-
1a1. Le Tracker shows an error message.
Use case ends.
-
-
1b. Lecture name supplied does not follow the lecture name format.
-
1b1. Le Tracker shows an error message.
Use case ends.
-
-
1c. Video name supplied does not follow the video name format.
-
1c1. Le Tracker shows an error message.
Use case ends.
-
-
1d. There is no such module of module code in Le Tracker.
-
1d1. Le Tracker shows an error message.
Use case ends.
-
-
1e. There is no such lecture of lecture name in the module.
-
1e1. Le Tracker shows an error message.
Use case ends.
-
-
1f. There is no such video of video name in the lecture.
-
1f1. Le Tracker shows an error message.
Use case ends.
-
Delete multiple Videos
Precondition: User has added a module, a lecture and a few videos
MSS
- User requests to delete the specific videos by supplying their video names, the lecture name of the lecture containing them and the module code of the module containing the lecture
- Le Tracker deletes the specified videos from the lecture of the module
Use case ends.
Extensions
-
1a. Module code supplied does not follow the module code format.
-
1a1. Le Tracker shows an error message.
Use case ends.
-
-
1b. Lecture name supplied does not follow the lecture name format.
-
1b1. Le Tracker shows an error message.
Use case ends.
-
-
1c. At least one of the video names supplied does not follow the video name format.
-
1c1. Le Tracker shows an error message.
Use case ends.
-
-
1d. The video names supplied contains duplicates.
-
1d1. Le Tracker shows an error message.
Use case ends.
-
-
1e. There is no such module of module code in Le Tracker.
-
1e1. Le Tracker shows an error message.
Use case ends.
-
-
1f. There is no such lecture of lecture name in the module.
-
1f1. Le Tracker shows an error message.
Use case ends.
-
-
1g. At least one of the videos of video names supplied do not exist in the lecture.
-
1g1. Le Tracker shows an error message.
Use case ends.
-
Mark/Unmark a video
Preconditions: User has added a module, a lecture and a video
MSS
- User specifies the module code, lecture name and video name to mark/unmark the video as watched/unwatched
-
Le Tracker marks/unmarks the video as watched/unwatched
Use case ends.
Extensions
-
1a. Invalid module code that does not follow module code format is supplied.
-
1a1. Le Tracker shows an error message.
Use case ends.
-
-
1b. Invalid lecture name that does not follow lecture name format is supplied.
-
1b1. Le Tracker shows an error message.
Use case ends.
-
-
1c. Invalid video name that does not follow video name format is supplied.
-
1c1. Le Tracker shows an error message.
Use case ends.
-
-
1d. Module of module code does not exist in Le Tracker.
-
1d1. Le Tracker shows an error message.
Use case ends.
-
-
1e. Lecture of lecture name does not exist in module of module code.
-
1e1. Le Tracker shows an error message.
Use case ends.
-
-
1f. Video name does not exist in lecture of lecture name in module of module code.
-
1f1. Le Tracker shows an error message.
Use case ends.
-
-
2a. Video to mark is already marked as watched.
-
2a1. Le Tracker shows an error message.
Use case ends.
-
-
2b. Video to unmark is already unmarked.
-
2b1. Le Tracker shows an error message.
Use case ends.
-
Mark/Unmark multiple videos
Preconditions: User has added a module, a lecture and a few videos
MSS
- User specifies the module code, lecture name and multiple video names to mark/unmark as watched/unwatched
- Le Tracker marks/unmarks the videos as watched/unwatched
Use case ends.
Extensions
-
1a. Invalid module code that does not follow module code format is supplied.
-
1a1. Le Tracker shows an error message.
Use case ends.
-
-
1b. Invalid lecture name that does not follow lecture name format is supplied.
-
1b1. Le Tracker shows an error message.
Use case ends.
-
-
1c. At least one of video names supplied does not follow video name format.
-
1c1. Le Tracker shows an error message.
Use case ends.
-
-
1d. The video names supplied contain duplicates.
-
1d1. Le Tracker shows an error message.
Use case ends.
-
-
1e. Module of module code does not exist in Le Tracker.
-
1e1. Le Tracker shows an error message.
Use case ends.
-
-
1f. Lecture of lecture name does not exist in module of module code.
-
1f1. Le Tracker shows an error message.
Use case ends.
-
-
1g. At least one of the videos of video names do not exist in lecture of lecture name in module of module code.
-
1g1. Le Tracker shows an error message.
Use case ends.
-
-
2a. At least one of the videos to mark is already marked as watched.
-
2a1. Le Tracker shows an error message.
Use case ends.
-
Tag a module
MSS
- User requests to tag a module.
- User specifies the tags and the reference to the module.
-
The module is tagged.
Use case ends.
Extensions
-
2a. Module does not exist.
-
2a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2b. Reference to module is empty.
-
2b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2c. No tag is provided.
-
2c1. Le Tracker shows an error message.
Use case resumes at step 1.
-
Tag a lecture
Precondition: User has added a module and a lecture
MSS
- User requests to tag a lecture of a module.
- User specifies the tags as well as the lecture and the module the lecture belongs to.
-
The lecture is tagged.
Use case ends.
Extensions
-
2a. Module does not exist.
-
2a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2b. Reference to module is empty.
-
2b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2c. Lecture does not exist.
-
2c1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2d. Reference to lecture is empty.
-
2d1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2e. No tag is provided.
-
2e1. Le Tracker shows an error message.
Use case resumes at step 1.
-
Tag a video
Precondition: User has added a module, a lecture, and a video
MSS
- User requests to tag a video of a lecture.
- User specified the tags, as well as the video, the lecture the video belongs to, and the module the lecture belongs to.
-
The video is tagged.
Use case ends.
Extensions
-
2a. Module does not exist.
-
2a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2b. Reference to module is empty.
-
2b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2c. Lecture does not exist.
-
2c1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2d. Reference to lecture is empty.
-
2d1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2e. Video does not exist.
-
2e1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2f. Reference to video is empty.
-
2f1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2g. No tag is provided.
-
2g1. Le Tracker shows an error message.
Use case resumes at step 1.
-
Untag a module
Precondition: User has added a module, and has tagged that module
MSS
- User requests to remove some tags from a module.
- User specifies the tags to remove and the reference to the module.
-
The module’s tags are removed.
Use case ends.
Extensions
-
2a. Module does not exist.
-
2a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2b. Reference to module is empty.
-
2b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2c. No tag is provided.
-
2c1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2d. Module tags do not exist.
-
2d1. Le Tracker shows an error message.
Use case resumes at step 1.
-
Untag a lecture
Precondition: User has added a module and a lecture, and has tagged the lecture
MSS
- User requests to remove some tags from a lecture of a module.
- User specifies the tags as well as the lecture and the module the lecture belongs to.
-
The lecture’s tags are removed.
Use case ends.
Extensions
-
2a. Module does not exist.
-
2a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2b. Reference to module is empty.
-
2b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2c. Lecture does not exist.
-
2c1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2d. Reference to lecture is empty.
-
2d1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2e. No tag is provided.
-
2e1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2f. Lecture tags do not exist.
-
2f1. Le Tracker shows an error message.
Use case resumes at step 1.
-
Untag a video
Precondition: User has added a module, a lecture, and a video, and has tagged the video
MSS
- User requests to remove some tags from a video of a lecture.
- User specifies the tags, as well as the video, the lecture the video belongs to, and the module the lecture belongs to.
-
The video’s tags are removed.
Use case ends.
Extensions
-
2a. Module does not exist.
-
2a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2b. Reference to module is empty.
-
2b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2c. Lecture does not exist.
-
2c1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2d. Reference to lecture is empty.
-
2d1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2e. Video does not exist.
-
2e1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2f. Reference to video is empty.
-
2f1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2g. No tag is provided.
-
2g1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2h. Video tags do not exist.
-
2h1. Le Tracker shows an error message.
Use case resumes at step 1.
-
Export all modules to a new file
MSS
- User requests to save all data in the current tracker to a new file.
- User specifies the name of the file to save to.
-
All module data in the current tracker is saved to the file.
Use case ends.
Extensions
-
2a. File name is invalid.
-
2a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2b. File already exists.
-
2b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
Export all modules to an existing file
MSS
- User requests to save all data in the current tracker to an existing file.
- User specifies the name of the file to save to, as well as indicating that user wants to overwrite the existing file.
-
All module data in the current tracker is saved to the file.
Use case ends.
Extensions
-
2a. File name is invalid.
-
2a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2b. File cannot be written to.
-
2b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2c. No indication of overwriting file.
-
2c1. Le Tracker shows an error message.
Use case resumes at step 1.
-
Import all modules from a file
MSS
- User requests to import all module data from an existing file.
- User specifies the name of the file to import from.
-
All module data in the file is imported to the current tracker.
Use case ends.
Extensions
-
2a. File name is invalid.
-
2a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2b. File does not exist.
-
2b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2c. File cannot be read.
-
2c1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2d. Some modules already exist in the current tracker.
-
2d1. Le Tracker shows an error message.
Use case resumes at step 1.
-
Import all modules from a file
MSS
- User requests to import all module data from an existing file.
- User specifies the name of the file to import from.
-
All module data in the file is imported to the current tracker.
Use case ends.
Extensions
-
2a. File name is invalid.
-
2a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2b. File does not exist.
-
2b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2c. File cannot be read.
-
2c1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2d. Some modules already exist in the current tracker.
-
2d1. Le Tracker shows an error message.
Use case resumes at step 1.
-
Import some modules from a file
MSS
- User requests to import some modules data from an existing file.
- User specifies the name of the file to import from, as well as references to the modules to be imported.
-
Modules data in the file is imported to the current tracker.
Use case ends.
Extensions
-
2a. File name is invalid.
-
2a1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2b. File does not exist.
-
2b1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2c. File cannot be read.
-
2c1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2d. Some modules already exist in the current tracker.
-
2d1. Le Tracker shows an error message.
Use case resumes at step 1.
-
-
2e. Specified modules do not exist in the saved file.
-
2e1. Le Tracker shows an error message.
Use case resumes at step 1.
-
Clear all Modules
MSS
- User requests to clear all modules
- Le Tracker clears all modules
Non-Functional Requirements
Usability:
- The app should be easy to navigate and use, with a user-friendly interface that is intuitive and clear.
- The app should be accessible to users of different skill levels and backgrounds.
- 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 than using the mouse.
Reliability:
- The app should be reliable and stable, with minimal downtime or disruptions. It should be able to handle a large number of users and requests without crashing or malfunctioning.
Performance:
- The app should respond quickly to user requests, with minimal loading times or delays.
- The app should be able to hold up to 1000 modules, lectures and videos without a noticeable sluggishness in performance for typical usage.
Compatibility:
- The app should work on any mainstream OS as long as it has Java
11or above installed so that it can be accessed and used by a wide range of users.
Maintainability:
- The app should be easy to maintain and update, with clear and well-organized code, documentation, and version control. This will help ensure that the app remains functional and up-to-date over time.
Glossary
-
Argument: A key value pair, of the format
/{key} {value}, specified in the user’s input (e.g./mod CS2040S). It is commonly referred to by the/{key}portion (e.g./mod) - Context: A module code or module code - lecture name pair that represents a location in the module-lecture-video hierarchy
-
Current Working Context: A specified context that allows the navigation system to inject
/modor/lecprefixes into the user’s command - Lecture: A lecture of a module
- Lecture Name: A name given to a lecture by the user
- Mainstream OS: Windows, Linux, Unix, OS-X
- Module: A module or course in NUS
- Module Code: The unique official code assigned to a module by NUS (e.g. CS2103)
- Navigate: To specify a current working context
- Timestamp: The timestamp of a video, representing a specific point in the video, specified in hours, minutes, and seconds
- Video: A video recording of a lecture
- Video Name: A name given to a video by the user
Appendix: Instructions for manual testing
Given below are instructions to test the app manually.
Note: These instructions may not be comprehensive and serve only as a starting point for manual testing; Testers are encouraged to conduct further exploratory testing to find unexpected behaviour.
Please ensure that you begin with the original sample data set before testing!
- Delete the
{leTracker_directory}/datafolder to regenerate the sample data.
To make things easier for testing
- Before testing, execute
export test.jsonto make a copy of the sample data.- You can then execute
import test.json /overwriteto revert any changes and restore the original sample data set.
- You can then execute
Before beginning each test case, ensure that
- You are at the root context
. - You are using the unmodified original sample data set.
List Modules
| Test Case | Expected Result |
|---|---|
list |
Message:Listed all modulesList updates: Show modules with code [ CS2040S, ST2334] |
list /r |
Same as previous |
list foo |
Same as previous |
List Lectures of a Module
| Test Case | Expected Result |
|---|---|
1.nav CS2040S2. list
|
Message:Listed all lectures from module: CS2040SList updates: Show lectures with name [ Week 1, Week 2, … , Week 7] |
list /mod CS2040S |
Same as previous |
List Videos of a Lecture
| Test Case | Expected Result |
|---|---|
1.nav CS2040S2. nav Week 13. list
|
Message:Listed all videos from module: CS2040S, lecture: Week 1List updates: Show videos with name [ Vid 3] |
1.nav CS2040S2. list /lec Week 1
|
Same as previous |
1.nav /mod CS2040S /lec Week 12. list
|
Same as previous |
list /mod CS2040S /lec Week 1 |
Same as previous |
Find Modules
| Test Case | Expected Result |
|---|---|
find cs |
Message:1 modules listed!List updates: Show modules with code [ CS2040S] |
find cs /r |
Same as previous |
find foo |
Message:0 modules listed!List updates: Shows an empty list |
Find Modules by Tag
| Test Case | Expected Result |
|---|---|
find math /byTag |
Message:2 modules listed!List updates: Show modules with code [ CS2040S, ST2334] |
find prob /r /byTag |
Message:1 modules listed!List updates: Show modules with code [ ST2334] |
find foo /byTag |
Message:0 modules listed!List updates: Shows an empty list |
Find Lectures of a Module
| Test Case | Expected Result |
|---|---|
1.nav CS2040S2. find week 1
|
Message:1 lectures listed!List updates: Show lectures with name [ Week 1] |
find week 1 /mod CS2040S |
Same as previous |
find wk /mod CS2040S |
Message:0 lectures listed!List updates: Shows an empty list |
Find Lectures of a Module by Tag
| Test Case | Expected Result |
|---|---|
1.nav CS2040S2. find arr /byTag
|
Message:2 lectures listed!List updates: Show lectures with name [ Week 2, Week 4] |
find arr /mod CS2040S /byTag |
Same as previous |
find arry /mod CS2040S /byTag |
Message:0 lectures listed!List updates: Shows an empty list |
Find Videos of a Lecture
| Test Case | Expected Result |
|---|---|
1.nav CS2040S2. nav Week 13. find vid 3
|
Message:1 videos listed!List updates: Show videos with name [ Vid 3] |
1.nav CS2040S2. find vid 3 /lec Week 1
|
Same as previous |
1.nav /mod CS2040S /lec Week 12. find vid 3
|
Same as previous |
find vid 3 /mod CS2040S /lec Week 1 |
Same as previous |
1.nav /mod CS2040S /lec Week 12. find
|
Message:Invalid command format!List updates: None |
Find Videos of a Lecture by Tag
| Test Case | Expected Result |
|---|---|
1.nav CS2040S2. nav Week 23. find math /byTag
|
Message:1 videos listed!List updates: Show videos with name [ Vid 2] |
1.nav CS2040S2. find math /lec Week 2 /byTag
|
Same as previous |
1.nav /mod CS2040S /lec Week 22. find math /byTag
|
Same as previous |
find math /mod CS2040S /lec Week 2 /byTag |
Same as previous |
1.nav /mod CS2040S /lec Week 22. find
|
Message:Invalid command format!List updates: None |
Add a Module
| Test Case | Expected Result |
|---|---|
add CS2103T /name Software Engineering /tags Coding, 4MCs |
Message:New module added: CS2103T; Name: Software Engineering; Tags: [4MCs][Coding]List updates: New entry for “CS2103T”, with name “Software Engineering” and tags “Coding”, and “4MCs” |
1. nav CS2040S2. add CS2103T /r /name Software Engineering /tags Coding, 4MCs
|
Message: Same as previous List updates: None |
1. nav /mod CS2040S /lec Week 12. add CS2103T /r /name Software Engineering /tags Coding, 4MCs
|
Same as previous |
Some incorrect commands to try from root context:
-
add(incorrect format) -
add CS2040S(duplicate module) -
add 123(invalid module code) -
add CS2103T /name N@me(invalid module name) -
add CS2103T /tags T@g(invalid tag)
Add a Lecture
| Test Case | Expected Result |
|---|---|
add Week 7 /mod CS2040S /tags AVLTree, Census |
Message:New lecture added to module CS2040S: Week 7; Tags: [Census][AVLTree]List updates: Module progress for “CS2040S” entry is changed to “5/7” |
1. nav CS2040S2. add Week 7 /tags AVLTree, Census
|
Message: Same as previous List updates: New entry for “Week 7” with tags “AVLTree” and “Census” |
1. nav /mod CS2040S /lec Week 12. add Week 7 /mod CS2040S /tags AVLTree, Census
|
Message: Same as previous List updates: None |
Some incorrect commands to try from root context:
-
add /mod CS2040S(incorrect format) -
add Week 1 /mod CS2040S(duplicate lecture) -
add Lecture N@me /mod CS2040S(invalid lecture name) -
add Week 7 /mod CS2040S /tags T@g(invalid tag)
Add a Video
| Test Case | Expected Result |
|---|---|
add Vid 3 /mod CS2040S /lec Week 1 /timestamp 01:04:20 /watch /tags Analysis, BigO |
Message:New video added to lecture Week 1 of module CS2040S: Vid 3; Watched; Timestamp: 01:04:20; Tags: [BigO][Analysis]List updates: None |
1. nav CS2040S2. add Vid 3 /lec Week 1 /timestamp 01:04:20 /watch /tags Analysis, BigO
|
Message: Same as previous List updates: Lecture progress for “Week 1” entry is changed to “3/3” |
1. nav /mod CS2040S /lec Week 12. add Vid 3 /lec Week 1 /timestamp 01:04:20 /tags Analysis, BigO
|
Message:New video added to lecture Week 1 of module CS2040S : Vid 3; Not Watched; Timestamp: 01:04:20; Tags: [BigO][Analysis]List updates: New entry for “Vid 3” with timestamp “01:04:20”, tags “Analysis” and “BigO”, and video marked as “not watched” |
Some incorrect commands to try from root context:
-
add /mod CS2040S /lec Week 1(incorrect format) -
add Vid 1 /mod CS2040S /lec Week 1(duplicate video) -
add V!deo /mod CS2040S /lec Week 1(invalid video name) -
add Vid 3 /mod CS2040S /lec Week 1 /tags T@g(invalid tag)
Edit a Module
| Test Case | Expected Result |
|---|---|
edit CS2040S /code CS2040 /name DSAG /tags Analytical, 4MCs |
Message:Edited module: CS2040; Name: DSAG; Tags: [4MCs][Analytical]; Lectures: Week 1; Tags: [Intro]; Videos: Vid 1; Watched; Timestamp: 00:00:00; Tags: [Algo]Vid 2; Watched; Timestamp: 00:00:00; Tags: [Analysis]Week 2; Tags: [Sorting]; Videos: Vid; Watched; Timestamp: 00:00:00Week 3; Tags: [Arrays][LinkedList]; Videos: Vid 1; Watched; Timestamp: 00:00:00; Tags: [Algo]Vid 2; Watched; Timestamp: 00:00:00; Tags: [Analysis]Week 4; Tags: [Stacks][Queues]; Videos: Vid; Watched; Timestamp: 00:00:00Week 5; Tags: [Hashing]; Videos: Vid 1; Watched; Timestamp: 00:00:00; Tags: [Algo]Vid 2; Watched; Timestamp: 00:00:00; Tags: [Analysis]Week 6; Tags: [BloomFilter]; Videos: Vid; Not Watched; Timestamp: 00:24:20List updates: Entry for “CS2040S” updated to “CS2040”, with name “DSAG” and tags “Analytical” and “4MCs” |
1. nav CS2040S2. edit CS2040S /r /code CS2040 /name DSAG /tags Analytical, 4MCs
|
Message: Same as previous List updates: None |
1. nav /mod CS2040S /lec Week 12. edit CS2040S /r /code CS2040 /name DSAG /tags Analytical, 4MCs
|
Same as previous |
Some incorrect commands to try from root context:
-
edit(incorrect format) -
edit CS2040S /code ST2334(duplicate module) -
edit 123(invalid module code) -
edit CS2040S(no updated fields) -
edit CS2103 /code CS2103T(non-existent module) -
edit CS2040S /code 123(invalid module code) -
edit CS2040S /name N@me(invalid module name) -
edit CS2040S /tags T@g(invalid tag)
Edit a Lecture
| Test Case | Expected Result |
|---|---|
edit Week 1 /mod CS2040S /name W1 /tags Intro, BigO |
Message:Edited lecture of module CS2040S: W1; Tags: [BigO][Intro]; Videos: Vid 1; Watched; Timestamp: 00:00:00; Tags: [Algo]Vid 2; Watched; Timestamp: 00:00:00; Tags: [Analysis]List updates: None |
1. nav CS2040S2. edit Week 1 /name W1 /tags Intro, BigO
|
Message: Same as previous List updates: Entry for “Week 1” updated to “W1”, with tags “Intro” and “BigO” |
1. nav /mod CS2040S /lec Week 12. edit Week 1 /mod CS2040S /name W1 /tags Intro, BigO
|
Message: Same as previous List updates: None |
Some incorrect commands to try from root context:
-
edit /mod CS2040S(incorrect format) -
edit Week 1 /mod CS2040S /name Week 2(duplicate lecture) -
edit Week! /mod CS2040S(invalid lecture name) -
edit Week 1 /mod CS2040S(no updated fields) -
edit Week 7 /mod CS2040S /name Week 07(non-existent lecture) -
edit Week 1 /mod CS2040S /name Week!(invalid lecture name) -
edit Week 1 /mod CS2040S /tags T@g(invalid tag)
Edit a Video
| Test Case | Expected Result |
|---|---|
edit Vid 1 /mod CS2040S /lec Week 1 /name Vid 01 /timestamp 01:04:20 /unwatch /tags Analysis, BigO |
Message:Edited video of lecture Week 1 of module CS2040S: Vid 01; Not Watched; Timestamp: 01:04:20; Tags: [BigO][Analysis]List updates: Module progress for “CS2040S” entry is changed to “4/6” |
1. nav CS2040S2. edit Vid 1 /lec Week 1 /name Vid 01 /timestamp 01:04:20 /unwatch /tags Analysis, BigO
|
Message: Same as previous List updates: Lecture progress for “Week 1” entry is changed to “1/2” |
1. nav /mod CS2040S /lec Week 12. edit Vid 1 /name Vid 01 /timestamp 01:04:20 /unwatch /tags Analysis, BigO
|
Message: Same as previous List updates: Entry for “Vid 1” updated to “Vid 01”, with timestamp “01:04:20”, tags “Analysis” and “BigO”, and video marked as “not watched”. |
Some incorrect commands to try from root context:
-
edit /mod CS2040S /lec Week 1(incorrect format) -
edit Vid 1 /mod CS2040S /lec Week 1 /name Vid 2(duplicate video) -
edit V!d 1 /mod CS2040S /lec Week 1(invalid video name) -
edit Vid 1 /mod CS2040S /lec Week 1(no updated fields) -
edit Vid 5 /mod CS2040S /lec Week 1 /name Vid 05(non-existent video) -
edit Vid 1 /mod CS2040S /lec Week 1 /name V!d 1(invalid video name) -
edit Vid 1 /mod CS2040S /lec Week 1 /timestamp 100:00:00(invalid timestamp format) -
edit Vid 1 /mod CS2040S /lec Week 1 /timestamp 00:99:00(invalid timestamp range) -
edit Vid 1 /mod CS2040S /lec Week 1 /tags T@g(invalid tag) -
edit Vid 1 /mod CS2040S /lec Week 1 /watch /unwatch(conflicting arguments)
Delete Module(s)
| Test Case | Expected Result |
|---|---|
delete CS2040S |
Message:Deleted Module: CS2040SList Updates Entry for “CS2040S” removed Context: /r
|
1. nav CS2040S2. delete CS2040S /r
|
Message: Same as previous List Updates: Show list of remaining modules, where entry for “CS2040S” is removed Context: /r
|
1. nav CS2040S2. nav Week 13. delete CS2040S /r
|
Same as previous |
1. nav ST23342. delete CS2040S /r
|
Message: Same as previous List Updates: None Context: /mod ST2334
|
delete CS2040S, ST2334 |
Message:2 Modules deleted(CS2040S, ST2334)List Updates: Entry for “CS2040S” and “ST2334” are removed Context: /r
|
1. nav CS2040S2. delete CS2040S, ST2334 /r
|
Message: Same as previous List Updates: Show list of remaining modules, where entries for “CS2040S” and “ST2334” are removed Context: /r
|
1. nav CS2040S2. nav Week 13. delete CS2040S, ST2334 /r
|
Same as previous |
Some incorrect commands to try from root context:
-
delete(incorrect command format) -
delete mod23(invalid module code format) -
delete CS2040S, CS2040S(duplicate module code) -
delete CS1234(module does not exist)
Delete Lecture(s)
| Test Case | Expected Result |
|---|---|
delete Week 1 /mod CS2040S |
Message:Deleted Lecture: Week 1 from Module CS2040SList Updates: Total number of lectures in the entry for “CS2040S” is updated to 5 Context: /r
|
1. nav CS2040S2. delete Week 1
|
Message: Same as previous List Updates: Entry for “Week 1” removed Context: /mod CS2040S
|
1. nav CS2040S2. nav Week 13. delete Week 1 /mod CS2040S
|
Message: Same as previous List Updates: Show list of remaining lectures of CS2040S, where entry for “Week 1” is removed Context: /mod CS2040S
|
1. nav CS2040S2. delete Week 1, Week 2 /mod CS2040S
|
Message:2 Lectures deleted from Module CS2040S:List Updates: Entries for “Week 1” and “Week 2” removed Context: /mod CS2040S
|
1. nav CS2040S2. nav Week 23. delete Week 1, Week 2 /mod CS2040S
|
Message: Same as previous List Updates: Show list of remaining lectures of CS2040S, where entries for “Week 1” and “Week 2” are removed Context: /mod CS2040S
|
Some incorrect commands to try from root context:
-
delete Week #1 /mod CS2040S(invalid lecture name format) -
delete Week 1 /mod mod23(invalid module code format) -
delete Week 1, Week 1 /mod CS2040S(duplicate lecture names) -
delete Topic 1 /mod CS2040S(lecture does not exist in module) -
delete Week 1 /mod NOT123(module does not exist)
Delete Video(s)
| Test case | Expected Result |
|---|---|
delete Vid 1 /mod CS2040S /lec Week 1 |
Message:Deleted Video: Vid 1 from Lecture Week 1 in Module CS2040SList Updates: None Context: /r
|
1. nav CS2040S2. delete Vid 1 /lec Week 1
|
Message: Same as previous List Updates: Total number of videos for the entry for “Week 1” is updated to 1 Context: /mod CS2040S
|
1. nav CS2040S2. nav Week 13. delete Vid 1
|
Message: Same as previous List Updates: Entry for “Vid 1” removed Context: /mod CS2040S /lec Week 1
|
1. nav CS2040S2. nav Week 13. delete Vid 1, Vid 2 /mod CS2040S /lec Week 1
|
Message:2 Videos deleted from Module CS2040S > Lecture Week 1List Updates: Entry for “Vid 1” and “Vid 2” are removed Context: /mod CS2040S /lec Week 1
|
Some incorrect commands to try from root context:
-
delete Vid 1 /lec Week 1(invalid command format) -
delete V!d 1 /mod CS2040S /lec Week 1(invalid video name format) -
delete Vid 1 /mod CS2040S /lec Week #1(invalid lecture name format) -
delete Vid 1 /mod mod123 /lec Week 1(invalid module code format) -
delete Vid 1, Vid 1 /mod CS2040s /lec Week 1(duplicate video names) -
delete VidNotExist /mod CS2040S /lec Week 1(video does not exist in lecture) -
delete Vid 1 /mod CS2040S /lec LecDoesNotExist(lecture does not exist in module) -
delete Vid 1 /mod NOT123 /lec Week 1(module does not exist)
Mark a Video
| Test Case | Expected Result |
|---|---|
mark Vid /mod CS2040S /lec Week 6 |
Message:Successfully marked 1 Video in Lecture Week 6 Module CS2040S: VidList Updates: Watch progress of entry for “CS2040S” updated to show a full bar with Covered 6/6 lectures
|
1. nav CS2040S2. mark Vid /lec Week 6
|
Message: Same as previous List Updates: Watch progress of entry for “Week 6” is updated to show a full bar with Watched 1/1 videos
|
1. nav CS2040S2. nav Week 6 3. mark Vid
|
Message: Same as previous List Updates: Watch progress of entry for “Vid” is updated to show Watched
|
1. nav ST23342. mark Vid /mod CS2040S /lec Week 6
|
Message: Same as previous List Updates: None |
1. nav CS2040S2. nav Week 63. add Vid 24. mark Vid, Vid2
|
Message: Successfully marked 2 Videos in Lecture Week 6 Module CS2040S: Vid, Vid 2List Updates: Watch progress of entries “Vid” and “Vid 2” are updated to show Watched
|
Some incorrect commands to try from root context:
-
mark(invalid command format) -
mark V!d /mod CS2040S /lec Week 6(invalid video name format) -
mark Vid /mod CS2040S /lec Week #6(invalid lecture name format) -
mark Vid /mod mod123 /lec Week 6(invalid module code format) -
mark Vid, Vid /mod CS2040s /lec Week 6(duplicate video names) -
mark VidNotExist /mod CS2040S /lec Week 6(video does not exist in lecture) -
mark Vid /mod CS2040S /lec LecDoesNotExist(lecture does not exist in module) -
mark Vid /mod NOT123 /lec Week 6(module does not exist) -
mark Vid 1 /mod CS2040S /lec Week 1(video already marked) -
mark Vid 1, Vid 2 /mod CS2040S /lec Week 1(videos already marked)
Unmark a Video
| Test Case | Expected Result |
|---|---|
unmark Vid 1 /mod CS2040S /lec Week 1 |
Message:Successfully unmarked Video in Lecture Week 1 Module CS2040S: Vid 1List Updates: Watch progress of entry for “CS2040S” is updated to show a less filled bar with Covered 4/6 lectures
|
1. nav CS2040S2. unmark Vid 1 /lec Week 1
|
Message: Same as previous List Updates: Watch progress of entry for “Week 1” is updated to show a half full bar with Watched 1/2 videos
|
1. nav CS2040S2. nav Week 13. unmark Vid 1, Vid 2
|
Message:Successfully unmarked 2 Videos in Lecture Week 1 Module CS2040S: Vid 1, Vid 2List Updates: Watch progress of entries for “Vid 1” and “Vid 2” are updated to show Not Watched
|
1. nav CS2040S2. nav Week 13. unmark Vid 1, Vid 24. unmark Vid 1, Vid 2
|
Same as previous |
Some incorrect commands to try from root context:
-
unmark(invalid command format) -
unmark V!d 1 /mod CS2040S /lec Week 1(invalid video name format) -
unmark Vid 1 /mod CS2040S /lec Week #1(invalid lecture name format) -
unmark Vid 1 /mod mod123 /lec Week 1(invalid module code format) -
unmark Vid 1, Vid 1 /mod CS2040s /lec Week 1(duplicate video names) -
unmark VidNotExist /mod CS2040S /lec Week 1(video does not exist in lecture) -
unmark Vid 1 /mod CS2040S /lec LecDoesNotExist(lecture does not exist in module) -
unmark Vid 1 /mod NOT123 /lec Week 1(module does not exist) -
unmark Vid /mod CS2040S /lec Week 6(video already unmarked)
Tag a Module
| Test Case | Expected Result |
|---|---|
tag CS2040S /tags fun, cool |
Message:CS2040S taggedList updates: CS2040S should be tagged with [ fun, cool] |
tag CS2040S /tags Heavy |
Message:CS2040S taggedList updates: None |
tag CS2040S /tags cool, cool |
Message:CS2040S taggedList updates: CS2040S should only be tagged with [ cool] once |
tag CS2040S /tags @@ |
Message:Tag(s) @@ should be alphanumeric |
Some incorrect commands to try from root context:
-
tag CS2040S(invalid format) -
tag CS2040S /tags @@(invalid tag) -
tag LOL /tags yay(invalid module name)
Tag a Lecture
| Test Case | Expected Result |
|---|---|
tag Week 1 /mod CS2040S /tags fun, cool |
Message:Week 1 taggedList updates: None |
1. nav CS2040S 2. tag Week 1 /tags fun, cool
|
Message:Week 1 taggedList updates: Week 1 should be tagged with [ fun, cool] |
1. nav ST2334 2. tag CS2040S /tags fun, cool
|
Message:Week 1 taggedList updates: None |
Some incorrect commands to try from root context:
-
tag Week 1 /mod CS2040S(incorrect format) -
tag Lecture N@me /mod CS2040S /tag yay(invalid lecture name) -
tag Week 7 /mod CS2040S /tags T@g(invalid tag)
Tag a Video
| Test Case | Expected Result |
|---|---|
tag Vid 3 /lec Week 1 /mod CS2040S /tags fun, cool |
Message:Vid 3 taggedList updates: None |
1. nav CS2040S 2. tag Vid 3 /lec Week 1 /tags fun, cool 3. nav Week 1
|
Message:Week 1 taggedList updates: Vid 3 should be tagged with [ fun, cool] |
1. nav /mod CS2040S /lec Week 1 2. tag Vid 3 /tags fun, cool
|
Same as previous |
1. nav /mod ST2334 /lec Topic 1 2. tag Vid 3 /lec Week 1 /mod CS2040S /tags fun, cool |
Message:Vid 3 taggedList updates: None |
Some incorrect commands to try from root context:
-
tag Vid 3 /lec Week 1 /mod CS2040S(incorrect format) -
tag V@lid Name /lec Week 1 /mod CS2040S /tag yay(invalid video name) -
tag Vid 3 /lec Week 1 /mod CS2040S /tags T@g(invalid tag)
Untag a Module
| Test Case | Expected Result |
|---|---|
untag CS2040S /tags Heavy, Math |
Message:CS2040S untaggedList updates: CS2040S should no longer be tagged with [ Heavy, Math] |
untag CS2040S /tags Heavy, Hehe |
Message:Tag Hehe of Module CS2040S does not exist List updates: None |
untag CS2040S /tags Heavy, Heavy |
Message:CS2040S untaggedList updates: CS2040S should no longer be tagged with [ Heavy] |
Some incorrect commands to try from root context:
-
untag CS2040S(invalid format) -
untag CS2040S /tags @@(invalid tag) -
untag LOL /tags yay(invalid module name)
Untag a Lecture
| Test Case | Expected Result |
|---|---|
untag Week 1 /mod CS2040S /tags Intro |
Message:Week 1 untaggedList updates: None |
1. nav CS2040S 2. untag Week 1 /tags Intro
|
Message:Week 1 untaggedList updates: Week 1 should no long be tagged with [ Intro] |
1. nav ST2334 2. untag Week 1 /mod CS2040S /tags Intro
|
Message:Week 1 untaggedList updates: None |
1. nav CS2040S 2. untag Week 2 /tags lol
|
Message:Tag lol of Lecture Week 2 of Module CS2040S does not exist List updates: None |
Some incorrect commands to try from root context:
-
untag Week 1 /mod CS2040S(incorrect format) -
untag Lecture N@me /mod CS2040S /tag yay(invalid lecture name) -
untag Week 7 /mod CS2040S /tags T@g(invalid tag)
Untag a Video
| Test Case | Expected Result |
|---|---|
1. untag Vid 3 /lec Week 1 /mod CS2040S /tags Intro 2. nav /lec Week 1 /mod CS2040S
|
Message:Vid 3 untaggedList updates: None |
1. nav CS2040S 2. untag Vid 3 /lec Week 1 /tags Intro
|
Message:Vid 3 untaggedList updates: None |
1. nav /mod CS2040S /lec Week 1 2. untag Vid 3 /tags Intro
|
Message:Vid 3 untaggedList updates: Vid 3 should no longer be tagged with [ Intro] |
1. nav /mod ST2334 /lec Topic 1 2. untag Vid 3 /lec Week 1 /mod CS2040S /tags Intro
|
Message:Vid 3 untaggedList updates: None |
Some incorrect commands to try from root context:
-
untag Vid 3 /lec Week 1 /mod CS2040S(incorrect format) -
untag V@lid Name /lec Week 1 /mod CS2040S /tag yay(invalid video name) -
untag Vid 3 /lec Week 1 /mod CS2040S /tags T@g(invalid tag)
Export All Modules to a File
| Test Case | Expected Result |
|---|---|
export hello.json |
Message:All modules archived to hello.jsonList updates: None Directory updates: A hello.json file should appear in {JAR_file_location}/data |
1. export hi.json 2. export hi.json
|
Message:File already exist. If you want to overwrite this file, insert /overwrite in the command List updates: None Directory updates: None |
1. export ha.json 2. export ha.json /overwrite
|
Message:All modules archived to ha.json List updates: None Directory updates: None |
export letracker.json /overwrite |
Message:Cannot export to the current working directory of Le Tracker List updates: None Directory updates: None |
Import Modules from a File
| Test Case | Expected Result |
|---|---|
1. export hello.json 2. delete CS2040S, ST2334 3. import hello.json
|
Message:Modules imported to Le Tracker List updates: CS2040S and ST2334 should be deleted and imported back into Le Tracker |
1. export ha.json 2. delete CS2040S 3. import ha.json
|
Message:ST2334 already exist in tracker. If you want to overwrite data in this module, insert /overwrite in the command List updates: None |
1. export he.json 2. delete CS2040S 3. import he.json /mod CS2040S
|
Message:Modules imported to Le Tracker List updates: CS2040S should be deleted and imported back into Le Tracker |
Clear
| Test Case | Expected Result |
|---|---|
clear |
Message:Le Tracker has been cleared!List Updates: Shows empty list |
1. nav CS2040S 2. clear
|
Message: Same as previous List Updates: Shows empty list in |
1. nav CS2040S 2. nav Week 1 3. clear
|
Same as previous |
Appendix: Effort
Adapting Model Component
The main difficulty with developing Le Tracker was adapting the Model component to support a hierarchical structure. In the AddressBook Level-3 codebase that Le Tracker is forked from, the Model component is non-hierarchical, utilizing Person objects to store person contact details. As Le Tracker requires Modules to contain Lectures which in turn contains Videos, a hierarchical structure was needed.
This required a large amount of change to the codebase of the Model component. It also pushed us to consider the pros and cons of breaking immutability of the various classes in the component. By breaking immutability, updating of fields would be much easier and the impacts on the UI component could be minimised. However, this introduces a risk of making bugs more difficult to diagnose. We ultimately decided to have Module and Lecture be immutable such that Lecture objects and Video objects can be added to them respectively. However, we limited the access to these immutable methods through the use of ReadOnlyModule and ReadOnlyLecture interfaces.
Adapting Commands
Due to the use of a hierarchical structure in the Model component, we had to reconsider how commands should behave and how they should be parsed. The code for each command is no longer as straightforward as in AddressBook Level-3. Command parsing must now determine the intent of the user via specific arguments in the user’s input (specifically /mod and /lec). This is necessary to determine for a command such as add, is the user attempting to add a module, a lecture, or a video.
By introducing the /mod and /lec arguments, user commands are now much longer and usability has taken a hit as a result. To counter this issue, we introduced a navigation system which auto injects the /mod and /lec arguments depending on the context. More information about what the navigation system does can be found in the User Guide.
Appendix: Planned enhancements
Feature Flaw #1: Some messages are poorly formatted
Description:
Currently some messages which serve as command feedback are poorly formatted.

- The message is represented as a single line, requiring users to use the horizontal scroll bar when the message extends beyond the width of result display window.
- The message may append excessive information to a single line without any line breaks, making it hard for the user to decipher the feedback of a command.
Here are some examples of poorly formatted messages that the team has identified:
- The following is a sample command for adding a module and it’s output message upon success:
Command:add CS2103T /name Software Engineering /tags Coding, 4MCs
Output:
New module added: CS2103T; Name: Software Engineering; Tags: [4MCs][Coding]
- The following is a sample command for adding a lecture and it’s output message upon success:
Command:add Week 7 /mod CS2040S /tags AVLTree, Census
Output:
New lecture added to module CS2040S: Week 7; Tags: [Census][AVLTree]
- The following is a sample command for adding a video and it’s output message upon success:
Command:add Vid 3 /mod CS2040S /lec Week 1 /timestamp 01:04:20 /watch /tags Analysis, BigO
Output:
New video added to lecture Week 1 of module CS2040S: Vid 3; Watched; Timestamp: 01:04:20; Tags: [BigO][Analysis]
- The following is a sample command for editing a module and it’s output message upon success:
Command:edit CS2040S /code CS2040 /name DSAG /tags Analytical, 4MCs
Output:
Edited module: CS2040; Name: DSAG; Tags: [4MCs][Analytical]; Lectures: Week 1; Tags: [Intro]; Videos: Vid 1; Watched; Timestamp: 00:00:00; Tags: [Algo]Vid 2; Watched; Timestamp: 00:00:00; Tags: [Analysis]Week 2; Tags: [Sorting]; Videos: Vid; Watched; Timestamp: 00:00:00Week 3; Tags: [Arrays][LinkedList]; Videos: Vid 1; Watched; Timestamp: 00:00:00; Tags: [Algo]Vid 2; Watched; Timestamp: 00:00:00; Tags: [Analysis]Week 4; Tags: [Stacks][Queues]; Videos: Vid; Watched; Timestamp: 00:00:00Week 5; Tags: [Hashing]; Videos: Vid 1; Watched; Timestamp: 00:00:00; Tags: [Algo]Vid 2; Watched; Timestamp: 00:00:00; Tags: [Analysis]Week 6; Tags: [BloomFilter]; Videos: Vid; Not Watched; Timestamp: 00:24:20
- The following is a sample command for editing a lecture and it’s output message upon success:
Command:edit Week 1 /mod CS2040S /name W1 /tags Intro, BigO
Output:
Edited lecture of module CS2040S: W1; Tags: [BigO][Intro]; Videos: Vid 1; Watched; Timestamp: 00:00:00; Tags: [Algo]Vid 2; Watched; Timestamp: 00:00:00; Tags: [Analysis]
- The following is a sample command for editing a video and it’s output message upon success:
Command:edit Vid 1 /mod CS2040S /lec Week 1 /name Vid 01 /timestamp 01:04:20 /unwatch /tags Analysis, BigO
Output:
Edited video of lecture Week 1 of module CS2040S: Vid 01; Not Watched; Timestamp: 01:04:20; Tags: [BigO][Analysis]
Proposed Solution:
We plan on changing the output message to be more user friendly and to make better use of the vertical space of the result display window.
Given the above 6 examples, their respective redesigned output will be as such:
- The following is a sample command for adding a module and it’s output message upon success:
Command:add CS2103T /name Software Engineering /tags Coding, 4MCs
Output:
New module added
Code: CS2103T
Name: Software Engineering
Tags: [4MCs] [Coding]
- The following is a sample command for adding a lecture and it’s output message upon success:
Command:add Week 7 /mod CS2040S /tags AVLTree, Census
Output:
New lecture added to module "CS2040S"
Name: Week 7
Tags: [Census] [AVLTree]
- The following is a sample command for adding a video and it’s output message upon success:
Command:add Vid 3 /mod CS2040S /lec Week 1 /timestamp 01:04:20 /watch /tags Analysis, BigO
Output:
New video added to lecture "Week 1" of module "CS2040S"
Name: Vid 3
Status: Not Watched
Timestamp: 01:04:20
Tags: [BigO] [Analysis]
- The following is a sample command for editing a module and it’s output message upon success:
Command:edit CS2040S /code CS2040 /name DSAG /tags Analytical, 4MCs
Output:
Edited module "CS2040S":
Updated Code: CS2040
Updated Name: DSAG
Updated Tags: [4MCs] [Analytical]
- The following is a sample command for editing a lecture and it’s output message upon success:
Command:edit Week 1 /mod CS2040S /name W1 /tags Intro, BigO
Output:
Edited lecture "Week 1" of module "CS2040S":
Updated Name: W1
Updated Tags: [BigO] [Intro]
- The following is a sample command for editing a video and it’s output message upon success:
Command:edit Vid 1 /mod CS2040S /lec Week 1 /name Vid 01 /timestamp 01:04:20 /unwatch /tags Analysis, BigO
Output:
Edited video "Vid 1" of lecture "Week 1" of module "CS2040S":
Updated Name: Vid 01
Updated Watch Status: Not Watched
Updated Timestamp: 01:04:20
Updated Tags: [BigO] [Analysis]
Feature flaw #2: No length limit for module code, module name, lecture name, video name, and tag
Description
There is currently no limit on the length of a module code and module name that can be assigned to a module. This is the same for the name of a lecture and the name of a video. This allows users to assign ridiculously long values to these fields, causing the UI to be truncated. This may also potentially slow down the application, and increase the size of the data file.
The following is an example of a lecture with a very long name, causing the name to be truncated:

Proposed Solution
For the commands that allow a user to assign values to the mentioned fields (add, edit, tag, untag, etc.), the arguments should have their length limited to some value (e.g. 30 characters).
The checking and limiting of length can be done while parsing the arguments and should produce an error message if the maximum length is exceeded:
The following {field} should not exceed the length limit of 30 characters: {value}
Feature flaw #3: Limited Find function capability
Description
When user finds a module, there is only matches for module code/name that starts with the keyword specified by user. This reduces the flexibility of the find function as they might be users who do not remember what a module starts with, which may create an unpleasant experience for them.

Proposed Solution
Instead of matching contents that starts with a keyword, relax it to contain the keyword.
E.g. find 2040 will match CS2040 because CS2040 contains 2040.
Feature flaw #4: Over buffering command history
Description
Commands executed by users are saved in a stack. However, no limit is set to the number of past commands that a user can see. This can lead to having too much memory being allocated for it and having no boundary.
Proposed Solution
Set a limit to the number of commands viewable in command history. Perhaps allowing user to see the last 5 or 10 or 15 commands only, the oldest command will be deleted forever if the limit is exceeded.
Feature flaw #5: Tag constraint message does not capture the full constraint
Description
A tag should only contain alphanumeric characters and spaces, and it should not be blank. However, when an invalid tag is entered as an argument, the error message fails to mention that the tag should not be blank.
For example, if an invalid tag T@g is provided, the error message is as follows:
Tag(s) T@g should be alphanumeric
Proposed Solution
We would like to propose that the error message be more specific. We would also like to improve the formatting (referring to Feature Flaw #1):
The proposed error message is as follows:
Tags should only contain alphanumeric characters, and they should not be blank.
The following tags provided are invalid:
- T@g
Feature flaw #6: Unmark Command does not alert user of already unmarked videos
Description
mark and unmark are similar commands that would mark a video as watched or unwatched respectively. Since these 2 commands are similar, they should have a similar functionality and error messages.
However, the current implementation is flawed as follows:
-
markone or multiple videos: if any video is already marked as watched, an error message is shown to the user -
unmarkone video: if the video is already marked as unwatched, an error message is shown to the user -
unmarkmultiple videos: if any video is already marked as unwatched, a success message is shown
As listed above, calling unmark on multiple videos has a different result as compared to its counterparts.
Proposed Solution
Set unmark for multiple videos to catch when any of the videos specified have already been marked as unwatched, and alert the user with a similar error message to its counterparts.
This implementation would allow for users to better realise what their commands are doing, especially if they are in a different context that does not allow them to visualise the effect of their commands.