Developer Guide
- Introduction
- Acknowledgements
- Setting up, getting started
- Design
- Implementation
-
Appendix: Requirements
- Product scope
- User stories
-
Use cases
- UC01 - Add a student
- UC02 - Delete a student
- UC03 - Delete all students from a module
- UC04 - Finding a student
- UC05 - Check all the tasks that a student has
- UC06 - Marking an undone task as complete
- UC07 - Marking a done task as incomplete
- UC08 - Edit a student
- UC09 - Save a copy of the data in TAPA
- UC10 - List all students
- UC11 - Assign a task to a student
- UC12 - View the completion status of a particular task
- UC13 - Delete a task assigned to a student
- UC14 - Sorting list of students by their number of incomplete tasks in descending order
- UC15 - Finding out what a certain command does
- Non-Functional Requirements
- Glossary
-
Appendix: Instructions for manual testing
- Launch and shutdown
- Adding a student
- Deleting students by index or student ID
- Deleting students by module code
- Finding students
- Assigning task(s) to students
- Checking all the tasks that a student has
- Marking an incomplete task as complete
- Marking a complete task as incomplete
- Viewing the completion status of a particular task
- Sorting the list of students in TAPA by the number of incomplete tasks in descending order
- Displaying a manual guide for TAPA
- Archiving details
- Saving data
Introduction
TAPA (Teaching Assistant’s Personal Assistant) is a desktop app that allows TAs to better manage their student’s progress, especially for those who are teaching multiple classes/modules at the same time. It is optimised for use on a CLI.
TAPA’s developer guide is written for developers who wish to contribute to our project. The developer guide will explain the technical aspects of the inner workings behind TAPA, and how the various components will come together.
Acknowledgements
This project is based on the AddressBook-Level3 project created by the SE-EDU initiative.
Setting up, getting started
Refer to TAPA’s Quick Start Guide.
Design
Architecture

The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
Main components of the architecture
Main has two classes called Main and MainApp. It is responsible for,
- At app launch: Initializes the components in the correct sequence, and connects them up with each other.
- At shut down: Shuts down the components and invokes cleanup methods where necessary.
Commons represents a collection of classes used by multiple other components.
The rest of the App consists of four components.
-
UI: The UI of the App. -
Logic: The command executor. -
Model: Holds the data of the App in memory. -
Storage: Reads data from, and writes data to, the hard disk.
How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete 1.

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, PersonListPanel, 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 displaysPersonobject 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, it uses theAddressBookParserclass 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 aPerson). - The result of the command execution is encapsulated as a
CommandResultobject which is returned fromLogic.
The Sequence Diagrams below illustrate the interactions within the Logic component for the execute("delete 1") API call.


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
AddressBookParserclass 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.,AddCommand) which theAddressBookParserreturns back as aCommandobject. - All
XYZCommandParserclasses (e.g.,AddCommandParser,DeleteCommandParser, …) inherit from theParserinterface so that they can be treated similarly where possible e.g, during testing.
Model component
API : Model.java

The Model component,
- stores TAPA’s data i.e., all
Personobjects (which are contained in aUniquePersonListobject). - stores the currently ‘selected’
Personobjects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiableObservableList<Person>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 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 TAPA’s data and user preference data in json format, and read them back into corresponding objects.
- inherits from both
AddressBookStorageandUserPrefStorage, 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.address.commons package.
Implementation
This section describes some noteworthy details on how certain features are implemented.
Add Command
Description
The add command allows users to add a particular student into TAPA.
Since not all fields are compulsory during the execution of the add command,
the user’s input is being parsed in AddressBookParser. After which, a new AddCommand
object will be created, and is subsequently executed by the LogicManager.
Implementation
- Upon receiving the user input,
the
LogicManagerstarts to parse the given input text usingAddressBookParser#parseCommand(). - The
AddressBookParserinvokes the respectiveParserbased on the first word of the input text. - Since the first word in the user input matches the word “add”,
AddCommandParser#parse(arguments)will be called. In this case, the arguments refer to the remaining input text after the exclusion of the command word (“add”). -
In the
AddCommandParser#parse(arguments), the arguments will be tokenized into anArgumentMultimap, by usingArgumentTokenizer#tokenize(String argsString, Prefix... prefixes).
Note: A ParseExceptionwill be thrown if the prefix of the compulsory fields are missing. -
The
AddCommandParserwill pass the studentId input (found in theArgumentMultimap) intoParserUtil#parseStudentId(String studentId).
Note: A NullPointerExceptionwill be thrown if the supplied string argument isnull. - In
ParserUtil#parseStudentId(String studentId), the supplied argument will be trimmed usingString#trim(). -
StudentId#isValidId(String studentId)will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a newStudentIdobject will be created and returned to theAddCommandParser. If the argument is not valid, aParseExceptionwill be thrown. -
Step 5 to 7 will be repeated for the other compulsory fields (
name,moduleCode) and optional fields (phone,telegramHandle,email), by using their respective parse methods inParserUtil.Field Parse Methods Index parseIndex(String oneBasedIndex) StudentId parseStudentId(String studentId) Name parseName(String name) ModuleCode parseModuleCode(String moduleCode) Phone parsePhone(String phone) TelegramHandle parseTelegramHandle(String telegramHandle) Email parseEmail(String email) Task parseTask(String task)
Note: If an optional field is not supplied (i.e. not found in the ArgumentMultimap), the extra parsing process in steps 5 to 7 will be skipped. Instead, the respective object will be created and initialized tonull. - The
AddCommandParserwill create a newPerson. - A new
AddCommandwill be created (using thePersonin Step 9) and returned to theLogicManager. - The
LogicManagerwill then callAddCommand#execute(Model model). -
In the
AddCommand, themodel#hasPerson(Person person)will be invoked. If thePersonalready exist in TAPA, aCommandExceptionwill be thrown.
Note: In TAPA, two Personare considered as equal only if they have the samestudentId. - The
AddCommandwill callmodel.addPerson(Person person), which adds thePersoninto theAddressBook. - Lastly, the
AddCommandwill create a newCommandResult, which will be returned toLogicManager.
The following sequence diagram shows how the add operation works:


Delete Command
Description
The delete command allows users to delete particular students from TAPA.
Since not all fields are compulsory during the execution of the delete command,
the user’s input is being parsed in AddressBookParser. After which, a new DeleteCommand
object will be created, and is subsequently executed by the LogicManager.
Implementation
- Upon receiving the user input,
the
LogicManagerstarts to parse the given input text usingAddressBookParser#parseCommand(). - The
AddressBookParserinvokes the respectiveParserbased on the first word of the input text. - Since the first word in the user input matches the word “delete”,
DeleteCommandParser#parse(arguments)will be called. In this case, the arguments refer to the remaining input text after the exclusion of the command word (“delete”). -
In the
DeleteCommandParser#parse(arguments), the arguments will be tokenized into anArgumentMultimap, by usingArgumentTokenizer#tokenize(String argsString, Prefix... prefixes).
Note: A ParseExceptionwill be thrown if the prefix of the compulsory fields are missing. -
The
DeleteCommandParserwill pass the studentId input (found in theArgumentMultimap) intoParserUtil#parseStudentId(String studentId).
Note: A NullPointerExceptionwill be thrown if the supplied string argument isnull. - In
ParserUtil#parseStudentId(String studentId), the supplied argument will be trimmed usingString#trim(). -
StudentId#isValidId(String studentId)will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a newStudentIdobject will be created and returned to theDeleteCommandParser. If the argument is not valid, aParseExceptionwill be thrown.
Note: The above description for Steps 5 to 7 is specifically for when studentIdis used as the input field. Depending on the type of input field used (StudentIdorIndex), Steps 5 to 7 will be executed using the parse methods inParserUtilthat are specific to the field. In the case of indices, anIndexarray is created in place of theStudentId.Field Parse Methods Index parseIndex(String oneBasedIndex) StudentId parseStudentId(String studentId) Name parseName(String name) ModuleCode parseModuleCode(String moduleCode) Phone parsePhone(String phone) TelegramHandle parseTelegramHandle(String telegramHandle) Email parseEmail(String email) Task parseTask(String task) - A new
DeleteCommandwill be created (using theStudentIdorIndexarray returned in Step 8) and returned to theLogicManager. - The
LogicManagerwill then callDeleteCommand#execute(Model model). - In the
DeleteCommand, a newStudentIdContainsKeywordsPredicateis created ifStudentIdwas used as the input. - If
StudentIdwas used, themodel#updateFilteredPersonList(Predicate<Person> predicate)will then be invoked, which updates the filter of thePersonListto filter by the givenStudentIdContainsKeywordsPredicate, after which the entry (if any) that matches theStudentIdContainsKeywordsPredicatewill be deleted by invokingmodel#deletePerson(Person person). - Otherwise, if an
Indexarray was used, a list ofPersons corresponding to theirIndexin the displayed list will be created, after which they will be processed one by one for deletion. - Lastly, the
DeleteCommandwill create a newCommandResult, which will be returned toLogicManager.
The following sequence diagram shows how the delete operation works:


DeleteModule Command
Description
The deleteModule command allows users to delete all students of the inputted ModuleCode from TAPA.
During the execution of the deleteModule command, the user’s input is being parsed in AddressBookParser.
After which, a new DeleteModuleCommand object will be created, and is subsequently executed by the LogicManager.
Implementation
- Upon receiving the user input,
the
LogicManagerstarts to parse the given input text usingAddressBookParser#parseCommand(). - The
AddressBookParserinvokes the respectiveParserbased on the first word of the input text. - Since the first word in the user input matches the word “deleteModule”,
DeleteModuleCommandParser#parse(arguments)will be called. In this case, the arguments refer to the remaining input text after the exclusion of the command word (“deleteModule”). -
In the
DeleteModuleCommandParser#parse(arguments), the arguments will be tokenized into anArgumentMultimap, by usingArgumentTokenizer#tokenize(String argsString, Prefix... prefixes).
Note: A ParseExceptionwill be thrown if the prefix of the compulsory field is missing. -
The
DeleteModuleCommandParserwill pass the moduleCode input (found in theArgumentMultimap) intoParserUtil#parseModuleCode(String moduleCode).
Note: A NullPointerExceptionwill be thrown if the supplied string argument isnull. - In
ParserUtil#parseModuleCode(String moduleCode), the supplied argument will be trimmed usingString#trim(). -
ModuleCode#isValidModuleCode(String moduleCode)will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a newModuleCodeobject will be created and returned to theDeleteModuleCommandParser. If the argument is not valid, aParseExceptionwill be thrown. - The
DeleteModuleCommandParserwill create a newModuleCodeContainsKeywordsPredicate. - A new
DeleteModuleCommandwill be created (using theModuleCodeContainsKeywordsPredicatereturned in Step 8) and returned to theLogicManager. - The
LogicManagerwill then callDeleteModuleCommand#execute(Model model). - The
model#updateFilteredPersonList(Predicate<Person> predicate)will then be invoked, which updates the filter of thePersonListto filter by the givenModuleIdContainsKeywordsPredicate. - Each
Personthat appears in the filtered list will then be deleted by invokingmodel#deletePerson(Person person). - Lastly, the
DeleteModuleCommandwill create a newCommandResult, which will be returned toLogicManager.
The following sequence diagram shows how the deleteModule operation works:


Find Command
Description
The find command allows users to find a particular student into TAPA.
Since not all fields are compulsory during the execution of the find command,
the user’s input is being parsed in AddressBookParser. After which, a new FindCommand
object will be created, and is subsequently executed by the LogicManager.
Implementation
- Upon receiving the user input,
the
LogicManagerstarts to parse the given input text usingAddressBookParser#parseCommand(). - The
AddressBookParserinvokes the respectiveParserbased on the first word of the input text. - Since the first word in the user input matches the word “find”,
FindCommandParser#parse(arguments)will be called. In this case, the arguments refer to the remaining input text after the exclusion of the command word (“find”). -
In the
FindCommandParser#parse(arguments), the arguments will be tokenized into anArgumentMultimap, by usingArgumentTokenizer#tokenize(String argsString, Prefix... prefixes).
Note: A ParseExceptionwill be thrown if the prefix of the compulsory fields are missing. -
The
FindCommandParserwill pass the studentId input (found in theArgumentMultimap) intoParserUtil#parseStudentId(String studentId).
Note: A NullPointerExceptionwill be thrown if the supplied string argument isnull. - In
ParserUtil#parseStudentId(String studentId), the supplied argument will be trimmed usingString#trim(). -
StudentId#isValidId(String studentId)will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a newStudentIdobject will be created and returned to theFindCommandParser. If the argument is not valid, aParseExceptionwill be thrown.
Note: The above description for Steps 5 to 7 is specifically for when studentIdis used as the input field. Depending on the type of input field used (studentId,name,moduleCode), Steps 5 to 7 will be executed using the parse methods inParserUtilthat are specific to the field.Field Parse Methods Index parseIndex(String oneBasedIndex) StudentId parseStudentId(String studentId) Name parseName(String name) ModuleCode parseModuleCode(String moduleCode) Phone parsePhone(String phone) TelegramHandle parseTelegramHandle(String telegramHandle) Email parseEmail(String email) Task parseTask(String task) - The
FindCommandParserwill create a newPredicate. - A new
FindCommandwill be created (using thePredicatein Step 8) and returned to theLogicManager. - The
LogicManagerwill then callFindCommand#execute(Model model). - In the
FindCommand, themodel#updateFilteredPersonList(Predicate<Person> predicate)will be invoked, which updates the filter of thePersonListto filter by the givenPredicate. - Lastly, the
FindCommandwill create a newCommandResult, which will be returned toLogicManager.
The following sequence diagram shows how the find operation works:


Task Command
Description
The task command allows users to check and view all the tasks belonging to a particular student.
During the execution of the task command, the user’s input is being parsed in AddressBookParser.
After which, a new TaskCommand object will be created, and is subsequently executed by the LogicManager.
Implementation
- Upon receiving the user input,
the
LogicManagerstarts to parse the given input text usingAdddressBookParser#parseCommand(). - The
AddressBookParserinvokes the respectiveParserbased on the first word of the input text. - Since the first word in the user input matches the word “task”,
TaskCommandParser#parse(arguments)will be called. In this case, the arguments refer to the remaining input text after the exclusion of the command word (“task”). -
In the
TaskCommandParser#parse(arguments), the arguments will be tokenized into anArgumentMultimap, by usingArgumentTokenizer#tokenize(String argsString, Prefix... prefixes).
Note: A ParseExceptionwill be thrown if the prefix ofStudentIdis missing, as it is a compulsory field. -
The
TaskCommandParserwill pass the studentId input (found in theArgumentMultimap) intoParserUtil#parseStudentId(String studentId).
Note: A NullPointerExceptionwill be thrown if the supplied string argument isnull. - In
ParserUtil#parseStudentId(String studentId), the supplied argument will be trimmed usingString#trim(). -
StudentId#isValidId(String studentId)will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a new StudentId object will be created and returned to theTaskCommandParser. If the argument is not valid, aParseExceptionwill be thrown. - A new
TaskCommandwill be created (using theStudentIdobject created in Step 7) and returned to theLogicManager. - The
LogicManagerwill then callTaskCommand#execute(Model model). - In the
TaskCommand, aStudentIdContainsKeywordsPredicateis created using the studentId. - The
model#updateFilteredPersonList(predicate)is then invoked such that the list is filtered by the predicate created. -
The
model#getFilteredPersonList()is then called. The size of the resulting list determines if there is anyPersonthat corresponds to the specifiedstudentId. If the size is equals to 0, aCommandExceptionwill be thrown.
Note: The studentIdis a UNIQUE field in TAPA, so multiple students cannot have the samestudentId. - The
Personobject in the filtered list is then extracted out usingmodel#getFilteredPersonList().get(0). - The
TaskListbelong to thisPersoncan then be retrieved usingPerson#getTaskList(). - If this
TaskListis null or empty, aCommandExceptionwill be thrown. - The
TaskCommanditerates through thisTaskList, and categorises the tasks into two newTaskListaccording to the task’s completion status. - Lastly, the
TaskCommandwill create a newCommandResultby using theTaskListin Step 16. ThisCommandResultwill then be returned toLogicManager.



Mark Command
Description
The mark command marks a specific undone task as done for a particular student. During the execution of the mark command, the user’s input is being parsed in AddressBookParser. After which, a new MarkCommand object will be created, and is subsequently executed by the LogicManager.
Implementation
- Upon receiving the user input, the
LogicManagerstarts to parse the given input text usingAddressBookParser#parseCommand(). - The
AddressBookParserinvokes the respectiveParserbased on the first word of the input text. - Since the first word in the user input matches the word “mark”,
MarkCommandParser#parse(arguments)will be called. In this case, the arguments refer to the remaining input text after the exclusion of the command word “mark”. -
In the
AddressBookParser#parseCommand(arguments), the arguments will be tokenized into anArgumentMultiMap, byusing ArgumentTokenizer#tokenize(String argsString, Prefix... prefixes).
Note: A ParseExceptionwill be thrown if the prefix of the compulsory fields are missing or if the arguments are invalid. -
The
MarkCommandParserwill pass the studentId input (found in theArgumentMultiMap) intoParserUtil#parseStudentId(String studentId).
Note: A NullPointerExceptionwill be thrown if the supplied string argument isnull. - In
ParserUtil#parseStudentId(String studentId), the supplied argument will be trimmed usingString#trim(). -
StudentId#isValidId(String studentId)will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a newStudentIdobject will be created and returned to theMarkCommandParser. If the argument is not valid, aParseExceptionwill be thrown. -
The
MarkCommandParserwill pass the index input (found in theArgumentMultiMap) intoParserUtil#parseIndex(Index index).
Note: A NullPointerExceptionwill be thrown if the supplied string argument is null. - In
ParserUtil#parseStudentId(Index index), the supplied argument will be trimmed usingString#trim(). -
Index#isValidId(Index index)will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a newIndexobject will be created and returned to theMarkCommandParser. If the argument is not valid, aParseExceptionwill be thrown. - The
MarkCommandParserwill create a newMarkCommandobject using theStudentIdandIndexcreated in Step 7 and 10 respectively. - The
LogicManagerwill then callMarkCommand#execute(Model model). -
The
MarkCommandwill callmodel#markTaskOfPerson(Student studentId, Index index), which marks the task (corresponding to the supplied index) of the given student as done.
Note: A CommandExceptionwill be thrown if the suppliedindexorstudentIdis invalid, or if the task is already marked as completed. - Lastly, the
MarkCommandwill create a newCommandResult, which will be returned toLogicManager.
The following sequence diagrams shows how the mark command works:


Unmark Command
Description
The unmark command marks a specific done task as undone for a particular student. During the execution of the unmark command, the user’s input is being parsed in AddressBookParser. After which, a new UnmarkCommand object will be created, and is subsequently executed by the LogicManager.
Implementation
- Upon receiving the user input, the
LogicManagerstarts to parse the given input text usingAddressBookParser#parseCommand(). - The
AddressBookParserinvokes the respectiveParserbased on the first word of the input text. - Since the first word in the user input matches the word “unmark”,
UnmarkCommandParser#parse(arguments)will be called. In this case, the arguments refer to the remaining input text after the exclusion of the command word “unmark”. -
In the
AddressBookParser#parseCommand(arguments), the arguments will be tokenized into anArgumentMultiMap, byusing ArgumentTokenizer#tokenize(String argsString, Prefix... prefixes).
Note: A ParseExceptionwill be thrown if the prefix of the compulsory fields are missing or if the arguments are invalid. -
The
UnmarkCommandParserwill pass the studentId input (found in theArgumentMultiMap) intoParserUtil#parseStudentId(String studentId).
Note: A NullPointerExceptionwill be thrown if the supplied string argument isnull. - In
ParserUtil#parseStudentId(String studentId), the supplied argument will be trimmed usingString#trim(). -
StudentId#isValidId(String studentId)will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a newStudentIdobject will be created and returned to theUnmarkCommandParser. If the argument is not valid, aParseExceptionwill be thrown. -
The
UnmarkCommandParserwill pass the index input (found in theArgumentMultiMap) intoParserUtil#parseIndex(Index index).
Note: A NullPointerExceptionwill be thrown if the supplied string argument isnull. - In
ParserUtil#parseStudentId(Index index), the supplied argument will be trimmed usingString#trim(). -
Index#isValidId(Index index)will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a newIndexobject will be created and returned to theUnmarkCommandParser. If the argument is not valid, aParseExceptionwill be thrown. - The
UnmarkCommandParserwill create a newUnmarkCommandobject using theStudentIdandIndexcreated in Step 7 and 10 respectively. - The
LogicManagerwill then callUnmarkCommand#execute(Model model). -
The
UnmarkCommandwill callmodel#unmarkTaskOfPerson(Student studentId, Index index), which marks the task (corresponding to the supplied index) of the given student as undone.
Note: A CommandExceptionwill be thrown if the suppliedindexorstudentIdis invalid, or if the task is already marked as not complete. - Lastly, the
UnmarkCommandwill create a newCommandResult, which will be returned toLogicManager.
The following sequence diagrams shows how the unmark command works:


Clear Command
Description
The clear command deletes all students currently stored in TAPA. Before all the students are deleted, the user will have to confirm their decision by inputting “confirm”.
Implementation
- When the user inputs “clear”, the
LogicManagerparses the given input text usingAddressBookParser#parseCommand(). - A new
ClearCommandis created byAddressBookParserand returned to theLogicManager. - The
LogicManagercallsClearCommand#execute(Model model), which returns a newCommandResultobject (with itsisClearRequestfield set totrue) to theLogicManager. - The
CommandResult(with itsisClearRequestfield set totrue) is then returned to theMainWindow. -
To confirm the user’s decision to clear TAPA, the
MainWindowexecutesMainWindow#handleClearRequest()which updates theCommandBoxto only recognise a “confirm” input for the next command.
Note: A CommandExceptionwill be thrown if the user inputs anything other than “confirm” for the next input. TheCommandBoxwill then return to its normal operation, accepting all commands as described in the user guide.
- If the user inputs “confirm”, the
LogicManagerparses the given input text usingAddressBookParser#parseCommand(), then a newConfirmClearCommandis created and returned to theLogicManager. - The
LogicManagerwill then callConfirmClearCommand#execute(Model model). - The
ConfirmClearCommandcallsModel#setAddressBook(new AddressBook())which resets the current list of students stored in TAPA to an empty list. - Lastly, the
ConfirmClearCommandcreates a newCommandResult, which is returned to theLogicManager.

Design considerations
Aspect: How TAPA confirms the user’s decision to clear TAPA
-
Alternative 1 (current choice): Have the user input “confirm”, which is treated by TAPA as a command being executed.
- Pros: Easy to implement and test. Having the user type “confirm” is an added safety measure to ensure the user does not clear TAPA accidentally.
- Cons: The user would take a longer time to clear TAPA than if a “confirm” button is implemented.
-
Alternative 2: Have a pop-up window with a “confirm” button which the user can click to confirm or cancel their decision.
- Pros: Faster to click a button than having to type “confirm” to clear TAPA.
- Cons: More difficult to implement and test as it involves extending the UI.
Archive Command
Description
The archive command allows users to save the current state of the data in TAPA,
into a separate .json file. This newly created file can be found in the same
folder as the original data file (in /data). In addition, it will have a file name
that corresponds to the date and time (up to 6 significant figures) in which the
command is being called. This ensures that files created will have a unique file name
in most cases.
Implementation
- Upon receiving the user input,
the
LogicManagerstarts to parse the given input text usingAddressBookParser#parseCommand(). - The
AddressBookParserinvokes the respectiveParserbased on the first word of the input text. - Since the first word in the user input matches the word “archive”,
ArchiveCommand()will be called. - As
ArchiveCommandutilizes the default constructor, it simply returns a newArchiveCommandobject to theAddressBookParser. - This
ArchiveCommandobject will then be subsequently returned to theLogicManager. - The
LogicManagercallsArchiveCommand#execute(Model model). - In
ArchiveCommand, thePathto the existingAddressBookis extracted, by callingmodel#getAddressBookFilePath(). - Similarly, the existing
AddressBookis also extracted, by callingmodel#getAddressBook(). - With the help of the
DateTimeFormatterandLocalDateTimein the Java 8 Date Time API, the file name and path of the new.jsondata file can be obtained. - The new
.jsondata file can now be created, usingFileUtil.createIfMissing(newPath). ACommandExceptionwill be thrown ifArchiveCommandfails to create this file. - The current copy of the
AddressBookcan be “copied” into a newJsonSerializableAddressBook, which will be used to populate the new.jsondata file that was created (by utilizingJsonUtil#saveJsonFile(T JsonFile, Path path)). ACommandExceptionwill be thrown ifArchiveCommandfails to populate the data file. - Lastly, the
ArchiveCommandwill create a newCommandResult, which will then be returned toLogicManager.

Assign Command
Description
The assign command allows users to assign tasks to student.
During the execution of the assign command, the user’s input is being parsed in AddressBookParser.
After which, a new AssignCommand object will be created, and is subsequently executed by the LogicManager.
Implementation
- Upon receiving the user input,
the
LogicManagerstarts to parse the given input text usingAdddressBookParser#parseCommand(). - The
AddressBookParserinvokes the respectiveParserbased on the first word of the input text. - Since the first word in the user input matches the word “assign”,
AssignCommandParser#parse(arguments)will be called. In this case, the arguments refer to the remaining input text after the exclusion of the command word (“assign”). -
In the
AssignCommandParser#parse(arguments), the arguments will be tokenized into anArgumentMultimap, by usingArgumentTokenizer#tokenize(String argsString, Prefex... prefixes).
Note: A ParseExceptionwill be thrown if the prefix ofTaskis missing, or if either the prefix ofStudentIdorModuleCodeis missing, as they are compulsory fields. -
The
AssignCommandParserwill pass the studentId input (found in theArgumentMultimap) intoParserUtil#parseStudentId(String studentId).
Note: A NullPointerExceptionwill be thrown if the supplied string argument isnull. - In
ParserUtil#parseStudentId(String studentId), the supplied argument will be trimmed usingString#trim(). -
StudentId#isValidId(String studentId)will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a new StudentId object will be created and returned to theAssignCommandParser. If the argument is not valid, aParseExceptionwill be thrown.
Note: The above description for Steps 5 to 7 is specifically for when studentIdis used as the input field. In the case ofmoduleCode, theModuleprefix will be used to tokenize the input. Depending on the type of input field used (studentIdormoduleCode), Steps 5 to 7 will be executed using the parse methods inParserUtilthat are specific to the field. The argument’s validity would be checked in their respective classes as well. -
The
AssignCommandParserwill pass the task input (found in theArgumentMultimap) intoParserUtil#parseTask(String task).
Note: A NullPointerExceptionwill be thrown if the supplied string argument isnull. - In
ParserUtil#parseTask(String task), the supplied argument will be trimmed usingString#trim(). -
Task#isValidTaskName(String task)will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a new Task object will be created and returned to theAssignCommandParser. If the argument is not valid, aParseExceptionwill be thrown. -
A new
AssignCommandwill be created (using theStudentIdorModuleCodeobject andTaskobject created) and returned to theLogicManager. -
The
LogicManagerwill then callAssignCommand#execute(Model model). -
If
StudentIdis used,AssignCommand#assignTaskToPerson(StudentId studentId, Task task)method will be invoked, which will in turn invokemodel#assignTaskToPerson(StudentId studentId, Task task)method andAddressBook#assignTaskToPerson(StudentId studentId, Task task)method. IfModuleCodeis used,AssignCommand#assignTaskToAllInModule(ModuleCode moduleCode, Task task)method will be invoked, which will in turn invokemodel#assignTaskToAllInModule(ModuleCode moduleCode, Task task)method andAddressBook#assignTaskToAllInModule(ModuleCode moduleCode, Task task)method. -
If
StudentIdis used,UniquePersonList#assignTaskToPerson(StudentId studentId, Task task)method is called. IfModuleCodeis used,UniquePersonList#assignTaskToAllInModule(ModuleCode moduleCoded, Task task)is called. This will iterate through eachPersonobject and check for matchingstudentIdormoduleCode.
Note:
If no student(s) with a matching studentIdormoduleCodeis found, thenPersonNotFoundExceptionorModuleCodeNotFoundExceptionwill be thrown. -
If a
Studentobject with matchingstudentIdormoduleCodeis found the method usesPerson#isTaskAlreadyPresent(Task task)method to check if thetaskis assigned. If no similartaskis found, the following step will take place.
Note:
If all the student(s) has already been assigned that task, then DuplicateTaskExceptionwill be thrown. If some, not all students in themoduleCodehas already been assigned that task, thenPartialDuplicateTaskExceptionwill be thrown. - The method gets copy of the
Studentobject by invokingPerson#getCopy()method. The copy is updated to includetaskby invokingPerson#addTask(Task task). -
Person#addTask(Task task)method will invokeTaskList#addTask(Task task), which adds the task to a list of assigned tasks. - The
model#updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS)is then invoked such that the list is filtered by the predicate created. In this case all the students will be in the filtered list. - Lastly, the
AssignCommandwill create a newCommandResult, which will be returned toLogicManager.


Progress Command
Description
The progress command allows users to view the completion status of all students who are taking a particular
module and are assigned to a particular task.
During the execution of the progress command, the user’s input is being parsed in AddressBookParser.
After which, a new ProgressCommand object will be created, and is subsequently executed by the LogicManager.
Implementation
- Upon receiving the user input,
the
LogicManagerstarts to parse the given input text usingAddressBookParser#parseCommand(). - The
AddressBookParserinvokes the respectiveParserbased on the first word of the input text. - Since the first word in the user input matches the word “progress”,
ProgressCommandParser#parse(arguments)will be called. In this case, the arguments refer to the remaining input text after the exclusion of the command word (“progress”). -
In the
ProgressCommandParser#parse(arguments), the arguments will be tokenized into anArgumentMultimap, by usingArgumentTokenizer#tokenize(String argsString, Prefix... prefixes).
Note: A ParseExceptionwill be thrown if the prefix of the compulsory fields are missing. -
The
ProgressCommandParserwill pass the moduleCode input (found in theArgumentMultimap) intoParserUtil#parseModuleCode(String moduleCode).
Note: A NullPointerExceptionwill be thrown if the supplied string argument isnull. - In
ParserUtil#parseModuleCode(String moduleCode), the supplied argument will be trimmed usingString#trim(). -
ModuleCode#isValidModuleCode(String moduleCode)will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a newModuleCodeobject will be created and returned to theProgressCommandParser. If the argument is invalid, aParseExceptionwill be thrown. - Steps 5 to 7 will be repeated for the “task name” field, by using its respective parse methods in
ParserUtil. - A new
ProgressCommandwill be created (using the parsedModuleCodeandTaskobjects) and returned to theLogicManager. - The
LogicManagerwill then callProgressCommand#execute(Model model). - In the
ProgressCommand, themodel#checkProgress(ModuleCode moduleCode, Task task)will be invoked. This method iterates through eachPersonobject. If thePersonhas the sameModuleCodeandTaskassigned to him/her, thePersonobject and the completion status (either completed/incomplete, denoted by a boolean value) will be added to aLinkedHashMap<Person, boolean>. - If the resulting
LinkedHashMapis null or empty, aCommandExceptionwill be thrown. - This
LinkedHashMapwill be used to generate the output string. - The output string will be used in creating a new
CommandResultobject. - Lastly, the
CommandResultobject will be returned toLogicManager.


DeleteTask Command
Description
The deleteTask command allows users to delete to task that was previously assigned to students.
During the execution of the deleteTask command, the user’s input is being parsed in AddressBookParser.
After which, a new deleteTaskCommand object will be created, and is subsequently executed by the LogicManager.
Implementation
- Upon receiving the user input,
the
LogicManagerstarts to parse the given input text usingAddressBookParser#parseCommand(). - The
AddressBookParserinvokes the respectiveParserbased on the first word of the input text. - Since the first word in the user input matches the word “deleteTask”,
DeleteTaskCommandParser#parse(arguments)will be called. In this case, the arguments refer to the remaining input text after the exclusion of the command word (“deleteTask”). -
In the
DeleteTaskCommandParser#parse(arguments), the arguments will be tokenized into anArgumentMultimap, by usingArgumentTokenizer#tokenize(String argsString, Prefix... prefixes).
Note: A ParseExceptionwill be thrown if the prefix ofStudentId,Index,ModuleCode, andTaskNameis missing. Either the pair (consisting ofStudentIdandIndex) or the pair (consisting ofModuleCodeandTaskName) must be provided.
-
If either
IndexorStudentIdis given, theindexOrStudentIdGiven(ArgumentMultimap argMultimap)method is invoked.
Note: A ParseExceptionwill be thrown if the prefix ofStudentId, orIndexis missing. BothStudentIdandIndexmust be provided.
i. The
indexOrStudentIdGivenmethod will pass thestudentIdinput (found in theArgumentMultimap) intoParserUtil#parseStudentId(String studentId).
Note: A NullPointerExceptionwill be thrown if the supplied string argument isnull.ii. In
ParserUtil#parseStudentId(String studentId), the supplied argument will be trimmed usingString#trim().iii.
StudentId#isValidId(String studentId)method will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a newStudentIdobject will be created and returned to theDeleteTaskCommandParser. If the argument is not valid, aParseExceptionwill be thrown.iv. The
indexOrStudentIdGivenmethod will pass the index input (found in theArgumentMultimap) intoParserUtil#parseIndex(String oneBasedIndex).
Note: A NullPointerExceptionwill be thrown if the supplied string argument isnull.v. In
ParserUtil#parseIndex(String oneBasedIndex), the supplied argument will be trimmed usingString#trim().vi.
Index#isValidId(String Index)will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a newIndexobject will be created and returned to theDeleteTaskCommandParser. If the argument is not valid, aParseExceptionwill be thrown.vii. A new
DeleteTaskCommand(StudentId studentId, Index index)will be created (using theStudentIdandIndexobject created in Step 3 and 6) and returned to theLogicManager. -
If either
ModuleCodeorTaskNameis given, themoduleCodeOrTaskNameGiven(ArgumentMultimap argMultimap)method is invoked.
Note: A ParseExceptionwill be thrown if the prefix ofModuleCode, orTaskNameis missing. BothModuleCodeandTaskNamemust be provided.
i. The
moduleCodeOrTaskNameGivenmethod will pass the moduleCode input (found in theArgumentMultimap) intoParserUtil#parseModuleCode(String moduleCode).
Note: A NullPointerExceptionwill be thrown if the supplied string argument isnull.ii. In
ParserUtil#parseModuleCode(String moduleCode), the supplied argument will be trimmed usingString#trim().iii.
ModuleCode#isValidModuleCode(String moduleCode)will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a newModuleCodeobject will be created and returned to theDeleteTaskCommandParser. If the argument is not valid, aParseExceptionwill be thrown.iv. The
moduleCodeOrTaskNameGivenmethod will pass the taskName input (found in theArgumentMultimap) intoParserUtil#parseTask(String task).
Note: A NullPointerExceptionwill be thrown if the supplied string argument isnull.v. In
ParserUtil#parseTask(String task), the supplied argument will be trimmed usingString#trim().vi.
Task#isValidTaskName(String test)will then be invoked, which checks if the trimmed argument is valid (according to the Regex supplied). If the argument is valid, a newTaskobject will be created and returned to theDeleteTaskCommandParser. If the argument is not valid, aParseExceptionwill be thrown.vii. A new
DeleteTaskCommand(ModuleCode moduleCode, Task task)will be created (using theModuleCodeandTaskobject created in Step 3 and 6) and returned to theLogicManager. - The
LogicManagerwill then callDeleteTaskCommand#execute(Model model). -
If the both the
studentIdandindexis present thenmodel#deleteTaskOfPerson(StudentId studentId, Index index)method is invoked.i.
AddressBook#deleteTaskOfPerson(StudentId studentId, Index index)is invoked, which invokesUniquePersonList#deleteTaskOfPerson(StudentId studentId, Index index)method.ii. This method will iterate through each
Personobject in and check for matchingstudentId. If found, the method will get a copy of thePersonobject by invokingPerson#getCopy(), deletes the task by invokingPerson#deleteTask(Index index). If the index is out of bounds,InvalidTaskIndexException()will be thrown by thetaskList#deleteTask(Index index)method. If no student with matching studentId is found,PersonNotFoundException()will be thrown.iii. The updated
Personwill be replaced the currentPersonobject.iv. If the task is successfully deleted, the
model#updateFilteredPersonList(Predicate<Person> predicate)will then be invoked bymodel#deleteTaskOfPerson(StudentId studentId, Index index)method, which updates the filter of thePersonListto filter by the givenPREDICATE_SHOW_ALL_PERSONS. -
If the both the
moduleCodeandtaskis present thenmodel#deleteTaskForAllInModule(ModuleCode moduleCode, Task task)method is invoked.i.
AddressBook#deleteTaskForAllInModule(ModuleCode moduleCode, Task task)is invoked, which invokesUniquePersonList#deleteTaskForAllInModule(ModuleCode moduleCode, Task task)method.ii. This method will iterate through each
Personobject in and check for matchingmoduleCode. If found, the method will get a copy of thePersonobject by invokingPerson#getCopy(), deletes the task by invokingPerson#deleteTask(Task task). If no task is found,TaskNotFoundException()will be thrown by thetaskList#deleteTask(Task task)method. If no student with matching moduleCode is found,ModuleCodeNotFoundException()will be thrown.iii. The updated
Personwill be replaced the currentPersonobject.iv. If the task is successfully deleted, the
model#updateFilteredPersonList(Predicate<Person> predicate)will then be invoked bymodel#deleteTaskForAllInModule(ModuleCode moduleCode, Task task)method, which updates the filter of thePersonListto filter by the givenPREDICATE_SHOW_ALL_PERSONS. - Lastly, the
DeleteTaskCommandwill create a newCommandResultwhichCommandResultwill be returned toLogicManager.


History Command
Description
The history command displays a list of the user’s previously executed commands. It is facilitated by CommandHistory, which stores the list of commands.

CommandHistory.
Implementation
- When the user launches the application,
ModelManageris initialised with a newCommandHistoryobject. -
Whenever the user successfully executes a command, the
LogicManagercallsModel#addToCommandHistory(). This adds the command to the list of previously executed commands inCommandHistory.
- When the user inputs “history”, the
LogicManagerparses the given input text usingAddressBookParser#parseCommand(). - A new
HistoryCommandis created byAddressBookParserand returned to theLogicManager. - The
LogicManagerwill then callHistoryCommand#execute(Model model). - Following this, the
HistoryCommandcallsModel#getCommandHistory()to retrieve the list of previously executed commands. - The
HistoryCommandthen callsCommandHistory#display()to convert the list to aStringwhich is returned toLogicManagerthrough a newCommandResult.

Undo Command
Description
The undo command reverts the most recently executed command by restoring TAPA to its previous state before the last command was executed. It is facilitated by AddressBookHistory which saves all the details in TAPA as each command is executed during the current user session.

Implementation
- When the user launches the application,
ModelManageris initialised with a newAddressBookHistoryobject. -
Whenever the user successfully executes a command (excluding
clearandundoitself), theLogicManagercallsModel#saveCurrentAddressBookToHistory(). This adds a copy of TAPA to the list of TAPA’s previous states inAddressBookHistory.
- When the user inputs “undo”, the
LogicManagerparses the given input text usingAddressBookParser#parseCommand(). - A new
UndoCommandis created byAddressBookParserand returned to theLogicManager. - The
LogicManagerwill then callUndoCommand#execute(Model model). - Following this, the
UndoCommandcallsModel#undoAddressBook()to revert the current details stored in TAPA to those stored before the previous command was executed. (WithinModelManager,AddressBookHistory#getPreviousAddressBookis called to retrieve the state of TAPA before the previous command.) - Lastly, the
UndoCommandcreates a newCommandResultwhich is returned to theLogicManager.

Design considerations
Aspect: How the UndoCommand reverts the changes made by the previous command
-
Alternative 1 (current choice): Store the details of TAPA after each successfully executed command, then recover them when
undois executed.- Pros: Easy to implement and test.
- Cons: Will take up more memory with each command executed.
-
Alternative 2: Extend each command to be able to revert the changes it has made to TAPA.
- Pros: Will not incur major performance issues as it uses less memory.
- Cons: More difficult to implement and test. Each command would need a unique implementation to be undone, and this would also need to be implemented for commands added in the future.
Sort Command
Description
The sort command allows the users to view the list of students in TAPA, sorted by the number of incomplete tasks in descending order.
During the execution of the sort command, the user’s input is being parsed in AddressBookParser.
After which, a new SortCommand object will be created, and is subsequently executed by the LogicManager.
Implementation
- Upon receiving the user input,
the
LogicManagerstarts to parse the given input text usingAddressBookParser#parseCommand(). - The
AddressBookParserinvokes the respectiveParserbased on the first word of the input text. - Since the first word in the user input matches the word “sort”,
SortCommand()will be called. - As
SortCommandutilizes the default constructor, it simply returns a newSortCommandobject to theAddressBookParser. - This
SortCommandobject will then be subsequently returned to theLogicManager. - The
LogicManagercallsSortCommand#execute(Model model). - In
SortCommand, the current list of students in TAPA will be sorted by the number of incomplete tasks in descending order by callingmodel#sortFilteredPersonListByTaskLeft(). - In
SortCommand, the current list of students in TAPA will be updated to reflect the changes to the list, after the sort by callingmodel#updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS). - Lastly, the
SortCommandwill create a newCommandResult, which will then be returned toLogicManager.

Manual Command
Description
The manual command displays the format and a short description for a particular command. During the execution of the manual command, the user’s input is being parsed in ManualCommandParser. After which, a new ManualCommand object will be created, and is subsequently executed by the LogicManager.
Implementation
- Upon receiving the user input, the
LogicManagerstarts to parse the given input text usingAddressBookParser#parseCommand(). - The
AddressBookParserinvokes the respectiveParserbased on the first word of the input text. -
Since the first word in the user input matches the word “manual”,
ManualCommandParser#parse(arguments)will be called. In this case, the arguments refer to the remaining input text after the exclusion of the command word “manual”.
Note: A ParseExceptionwill be thrown if the argument is invalid. - The supplied argument will be trimmed using
String#trim(). - The
ManualCommandParserwill create a newManualCommand(using theargumentin Step 4), which will be returned toLogicManager. - The
LogicManagerwill callManualCommand#execute(Model model). If theargumentis invalid, aCommandExceptionwill be thrown. - Lastly, the
ManualCommandwill create a newCommandResultwhich will be returned toLogicManager.
The following sequence diagram shows how the manual command works:

Appendix: Requirements
Product scope
Target user profile
Teaching Assistants who:
- Need to manage a significant number of students (especially across multiple modules)
- Prefer desktop apps over other platforms
- Can type fast
- Prefer typing to mouse interactions
- Are reasonably comfortable using CLI apps
Value proposition
TAPA will allow TAs to better manage their student’s contact and progress,
especially for TAs who are teaching multiple classes/modules at the same time.
It is optimised for use on CLI, and allows for more efficient student detail management for TAs who can type fast.
User stories
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that I can… |
|---|---|---|---|
* * * |
Teaching Assistant | add students to TAPA | know which students are taking my classes |
* * * |
Teaching Assistant | delete a specific student from TAPA | remove student who has withdrawn from the module during the semester |
* * * |
Teaching Assistant | list students alphabetically | print students in a list as their names would appear on the official class list |
* * * |
Teaching Assistant | tag students | know what modules they are taking |
* * * |
Teaching Assistant | filter students by their tags | view the progress of students in each separate tag (different class/module) |
* * * |
Teaching Assistant | define my own tasks for each module | customise the tasks to each module |
* * * |
Teaching Assistant | undo the most recent command entered | revert any unwanted changes (such as deleting student) without much trouble |
* * * |
Teaching Assistant | delete a task given to a student | remove tasks that has incorrect information or has been assigned wrongly |
* * * |
Teaching Assistant | list the students who have/have not completed a specific task | track the completion status of a specific task |
* * * |
Teaching Assistant | assign tasks to a specific student | allocate and track a task that is given to the student |
* * * |
Teaching Assistant who is teaching in multiple semesters | archive the existing data | save a copy on the local machine before undergoing a complete deletion of data |
* * |
Teaching Assistant | see all the tasks that a student currently has | observe his/her progress |
* * |
Teaching Assistant | save existing data to hard drive | access the data again when I reopen the app |
* * |
Teaching Assistant | delete all students from TAPA | remove students that were taught in previous semesters and are no longer relevant |
* * |
Teaching Assistant | mark/unmark students’ tasks according to the completion status | update his/her progress |
* * |
Teaching Assistant | see students’ contact details (such as email address) | contact them if needed |
* * |
Teaching Assistant | find a student | check details of a specific student |
* * |
Teaching Assistant | display the possible actions that I can take, or do | have a quick reference without the need of reading a user guide |
* * |
Teaching Assistant | edit the details of the students | fix any errors that occurred during the insertion of student details |
* * |
Teaching Assistant | delete multiple students from TAPA | remove students that are no longer being taught, without needing to delete them individually |
* * |
Teaching Assistant | display student progress | see who is lagging behind |
* * |
Teaching Assistant | update the student’s tags | edit when the student drop/take a new module |
* * |
Teaching Assistant | sort students by their progress (based on the number of tasks completed) | see how the class is performing |
* * |
Teaching Assistant | edit details of a task given to a student | update the details of an assignment in case of future changes/extensions |
* * |
Teaching Assistant | assign tasks to multiple students | allocate tasks to students without having to individually assign them |
* * |
Teaching Assistant | delete tasks assigned to multiple students | remove any task that has incorrect information without having to individually delete it from each student |
* |
Teaching Assistant | track attendance | mark attendance for modules that require student attendance |
* |
Teaching Assistant | see modules I’m teaching at a glance | remind myself of what needs to be prepared for classes |
* |
Teaching Assistant | see student’s timetable | find a good time to arrange a consult with them |
* |
Teaching Assistant who is a long time user | type in chain commands | execute multiple different commands quickly |
* |
Teaching Assistant who is a long time user | send emails from the command line | send emails to students with specific tags quickly |
* |
Teaching Assistant who is used to CLI commands | customise commands | execute commands quickly |
* |
Teaching Assistant | view grades scored by students in each assignment | understand which topics they are finding difficult |
* |
Teaching Assistant | be able to highlight or feature certain students | know which students are performing the best or need more help |
Use cases
(For all use cases below, the System is the TAPA and the Actor is the user, unless specified otherwise)
UC01 - Add a student
MSS
- User requests to add a specific student.
-
TAPA shows the updated list of students.
Use case ends.
Extensions
-
1a. A student with the same student ID already exists.
-
1a1. TAPA shows an error message.
Use case ends.
-
-
1b. The student ID of the student is not in the input command.
-
1b1. TAPA shows an error message.
Use case ends.
-
-
1c. The name of the student is not in the input command.
-
1c1. TAPA shows an error message.
Use case ends.
-
-
1d. The module code that the student is currently taking is not in the input command.
-
1d1. TAPA shows an error message.
Use case ends.
-
-
1e. The fields specified are in an invalid format.
-
1e1. TAPA shows an error message.
Use case ends.
-
UC02 - Delete a student
MSS
- User requests to list students.
- TAPA shows a list of students.
- User requests to delete a specific student in the list.
-
TAPA deletes the students.
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. The given index is invalid.
-
3a1. TAPA shows an error message.
Use case resumes from step 2.
-
-
3b. The given student ID is invalid.
-
3b1. TAPA shows an error message.
Use case resumes from step 2.
-
UC03 - Delete all students from a module
MSS
- User requests to delete all students from a particular module.
-
TAPA deletes the students.
Use case ends.
Extensions
-
1a. The given module code is invalid.
-
1a1. TAPA shows an error message.
Use case resumes from step 1.
-
-
1b. There are no students taking the module specified by the given module code.
-
1b1. TAPA shows an error message.
Use case resumes from step 1.
-
UC04 - Finding a student
MSS
- User requests to find students that match the inputted search field.
-
TAPA displays the students who fit the request.
Use case ends.
Extensions
-
1a. The given student ID is invalid.
-
1a1. TAPA shows an error message.
Use case resumes from step 1.
-
-
1b. The given module code is invalid.
-
1b1. TAPA shows an error message.
Use case resumes from step 1.
-
UC05 - Check all the tasks that a student has
MSS
- User requests to check all the tasks that a student has.
-
TAPA shows a list of tasks that the student has.
Use case ends.
Extensions
-
1a. The specified student ID is invalid (not in a correct format).
-
1a1. TAPA shows an error message.
Use case ends.
-
-
1b. There is no student with the specified student ID in TAPA.
-
1b1. TAPA shows an error message.
Use case ends.
-
-
2b. The student does not have any tasks assigned to him/her.
-
2b1. TAPA shows an error message.
Use case ends.
-
UC06 - Marking an undone task as complete
MSS
- User requests to list students.
- TAPA shows a list of students.
- User requests to mark a student’s task as done.
-
TAPA shows the updated list of students.
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. If student ID is given, and a student with the given student ID does not exist.
-
3a1. TAPA shows an error message.
Use case ends.
-
-
3b. If the index given is out of range, that is, it is a non-positive number, or greater than the number of tasks assigned to that person.
-
3b1. TAPA shows an error message.
Use case ends.
-
-
3c. The specified task with the given index has already been marked as complete.
-
3c1. TAPA shows an error message.
Use case ends.
-
UC07 - Marking a done task as incomplete
MSS
- User requests to list students.
- TAPA shows a list of students.
- User requests to mark a student’s task as undone.
-
TAPA shows the updated list of students.
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. If student ID is given, and a student with the given student ID does not exist.
-
3a1. TAPA shows an error message.
Use case ends.
-
-
3b. If the index is out of range, that is, it is a non-positive number, or greater than the number of tasks assigned to that person.
-
3b1. TAPA shows an error message.
Use case ends.
-
-
3c. The specified task with the given index has already been marked as incomplete.
-
3c1. TAPA shows an error message.
Use case ends.
-
UC08 - Edit a student
MSS
- User requests to list students.
- TAPA shows a list of students.
- User requests edits to the supplied details of a specific student in the list.
-
TAPA updates the details of the student with the supplied details.
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. The given index is invalid.
-
3a1. TAPA shows an error message.
Use case resumes from step 2.
-
-
3b. The given field is invalid.
-
3b1. TAPA shows an error message.
Use case resumes from step 2.
-
-
3c. The new student ID specified is already in the database.
-
3c1. TAPA shows an error message.
Use case resumes from step 2.
-
UC09 - Save a copy of the data in TAPA
MSS
- User request to save a copy of the data that is currently being stored in TAPA.
- TAPA creates a new data file in the same directory as the existing stored data.
- TAPA copies the content of the existing stored data into the new data file.
Extensions
-
2a. There is already a data file that has the same file name as the new data file that is going to be created.
-
2a1. TAPA does not create a new data file.
Use case resumes from step 3.
-
-
2b. User does not have the permission to create a new file.
-
2b1. TAPA shows an error message.
Use case ends.
-
-
- There is an unexpected error when copying from the existing data file to the new data file.
-
3a1. TAPA shows an error message.
Use case ends.
UC10 - List all students
MSS
- User requests to list students.
-
TAPA shows a list of students in alphabetical order sorted by their name.
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
UC11 - Assign a task to a student
MSS
- User requests TAPA to assign a task to a student. (This can be done for an individual student or for all students taking the same module)
-
TAPA shows the updated list of students.
Use case ends.
Extensions
-
1a. If studentId is given, and a student with the given studentId does not exist.
-
1a1. TAPA shows an error message.
Use case ends.
-
-
1b. If module code is given and no student is taking a module with the given module code.
-
1b1. TAPA shows an error message.
Use case ends.
-
-
1c. The student has already been assigned with a task that has the same name.
-
1c1. TAPA shows an error message.
Use case ends.
-
UC12 - View the completion status of a particular task
MSS
- User request to view which students (in a particular module) have completed or have yet to complete a particular task.
- TAPA shows a list of students who are taking this module and are currently assigned with the specified tasks (along with their respective completion status).
Extensions
-
1a. The specified task name is invalid (not in a correct format).
-
1a1. TAPA shows an error message.
Use case ends.
-
-
1b. The specified module code is invalid (not in a correct format).
-
1b1. TAPA shows an error message.
Use case ends.
-
-
2a. There are no students who are taking this module and are assigned with the specified task.
-
2a1. TAPA shows an error message.
Use case ends.
-
UC13 - Delete a task assigned to a student
MSS
- User requests to list students.
- TAPA shows a list of students.
- User requests to delete a task that was assigned to a student. (This can be done for an individual student or for all the students taking the same module.)
-
TAPA updates the details of the student with the supplied details.
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. If studentId is given, and a student with the given studentId does not exist.
-
3a1. TAPA shows an error message.
Use case ends.
-
-
3b. If the value of the specified index is less than 1 or greater than the number of tasks assigned to that student.
-
3b1. TAPA shows an error message.
Use case ends.
-
-
3c. If module code is given and no student is taking a module with the given module code.
-
3c1. TAPA shows an error message.
Use case ends.
-
-
3d. The task name already is assigned to the present.
-
3d1. TAPA shows an error message.
Use case ends.
-
UC14 - Sorting list of students by their number of incomplete tasks in descending order
MSS
- User requests to sort students.
-
TAPA shows a list of students in order, sorted by their number of incomplete tasks in descending order.
Use case ends.
-
2a. The list is empty.
Use case ends.
UC15 - Finding out what a certain command does
MSS
- User requests TAPA to provide a description for a particular command, as well as how to use the command.
- TAPA provides a short description of what the specified command does.
- TAPA provides the format for how to use the command.
-
TAPA provides an example to show the user how to use the command.
Use case ends.
Extensions
-
1a. The user does not input a specific command.
-
1a1. TAPA provides the list of all available commands.
Use case ends.
-
-
1b. The user inputs a command that is not valid (not in the existing list of commands)
-
1b1. TAPA shows an error message.
Use case ends.
-
Non-Functional Requirements
- Should work on any mainstream OS as long as it has Java
11or above installed. - Should be able to hold up to 1000 students without a noticeable sluggishness in performance for typical usage.
- Usage should be more efficient than a regular contact management application for a user who types fast in English text.
- Should be usable by a novice who has never used a contact management application before.
- The system should respond within 3 seconds.
- The student’s data should only be stored locally.
Glossary
- Mainstream OS: Windows, Linux, Unix, OS-X
- Module: A specific class that a student is taking
- Tag: A category that the student belong to (usually denotes the module that is currently being taken)
- Person: A student in TAPA
- Student ID/Matriculation number: Used interchangeably to refer to the unique identification number of a student
Appendix: Instructions for manual testing
Given below are instructions to test the app manually.
Launch and shutdown
-
Initial launch
-
Download the jar file and copy into an empty folder.
-
Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
-
-
Saving window preferences
-
Resize the window to an optimum size. Move the window to a different location. Close the window.
-
Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-
-
Shutdown
-
Shut down TAPA using the
exitcommand.Expected: TAPA exits immediately.
-
Adding a student
-
Adding a student to TAPA
-
Prerequisites: Sample data is loaded in TAPA.
-
Test case:
add i/A0000000Z m/CS2100 n/Test
Expected: No student is added as there is already another student in TAPA who has the same student ID. Error message will be displayed to the user. -
Test case:
add m/CS2100 n/Test,add i/AXXXXXXXR m/CS2100,add i/AXXXXXXXR n/Test
Expected: No student is added due to missing compulsory fields. Error message will be displayed to the user. -
Test case:
add i/AXXXXXXXR m/CS2100 n/Test
Expected: Student is added into TAPA, even if some/all optional fields are missing. -
Test case:
add i/A!@#$%^&R m/CS2100 n/Test
Expected: No student is added due to invalid format for student ID. Error message will be displayed to the user. -
Other incorrect add commands to try:
add i/AXXXXXXXR m/CS2@00 n/Test,add i/AXXXXXXXR m/CS2100 n/T@st
Expected: Similar to previous
-
Deleting students by index or student ID
-
Deleting a student(s) using their index while all students are being shown
-
Prerequisites: List all students using the
listcommand. Multiple students in the list. -
Test case:
delete 1
Expected: First student is deleted from the list. Details of the deleted student shown in the status message. -
Test case:
delete 1 2
Expected: First and second students are deleted from the list. Status message states that 2 students were deleted. -
Test case:
delete 0
Expected: No student is deleted. Error details shown in the status message. -
Test case:
delete 0 1
Expected: No student is deleted. Error details shown in the status message. -
Test case:
delete
Expected: No student is deleted. Error details shown in the status message. -
Test case:
delete -1
Expected: No student is deleted. Error details shown in the status message. -
Test case:
delete x, where x > number of students in the list
Expected: No student is deleted. Error details shown in the status message.
-
-
Deleting a student using their student ID
- Prerequisites:
- Sample data is loaded in TAPA.
- One student has “A0000000Z” as their student ID.
- No student has “A9999999X” as their student ID.
-
Test case:
delete i/A0000000Z
Expected: The student with student ID “A0000000Z” deleted from the list. Details of the deleted student shown in the status message. -
Test case:
delete i/A9999999X
Expected: No student is deleted. Error details shown in the status message. -
Test case:
delete i/@@@
Expected: No student is deleted. Error details shown in the status message. -
Test case:
delete i/
Expected: No student is deleted. Error details shown in the status message. - Test case:
delete
Expected: No student is deleted. Error details shown in the status message.
- Prerequisites:
Deleting students by module code
-
Deleting students by module code
- Prerequisites:
- Sample data is loaded in TAPA.
- One or more students have “CS2100” as their module code.
- No students have “CS9999” as their module code.
-
Test case:
deleteModule m/CS2100
Expected: The students with module code “CS2100” are deleted from the list. Status message states number of students deleted. -
Test case:
deleteModule m/CS9999
Expected: No student is deleted. Error details shown in the status message. -
Test case:
deleteModule m/@@@
Expected: No student is deleted. Error details shown in the status message. -
Test case:
deleteModule m/
Expected: No student is deleted. Error details shown in the status message. -
Test case:
deleteModule
Expected: No student is deleted. Error details shown in the status message. - Test case:
deleteModule m/CS CS
Expected: No student is deleted. Error details shown in the status message.
- Prerequisites:
Finding students
-
Finding a student using their name
- Prerequisites:
- Sample data is loaded in TAPA.
- One or more students have “John” in their name.
- No students have “Dueet” in their name.
-
Test case:
find n/John
Expected: All students with “John” in their names (but not Johnathan, Johnny etc) are listed. Status message states how many students were listed. -
Test case:
find n/Dueet
Expected: Student list displays no results. Status message states that 0 students were listed. -
Test case:
find n/John i/AAA
Expected: Find command not executed. Error details shown in the status message. -
Test case:
find n/@@@
Expected: Find command not executed. Error details shown in the status message. -
Test case:
find n/
Expected: Find command not executed. Error details shown in the status message. - Test case:
find
Expected: Find command not executed. Error details shown in the status message.
- Prerequisites:
-
Finding a student using their student ID
- Prerequisites:
- Sample data is loaded in TAPA.
- One student has “A0000000Z” as their student ID.
- No student has “A9999999X” as their student ID.
-
Test case:
find i/A0000000Z
Expected: The student with student ID “A0000000Z” is listed. Status message states that one student was listed. -
Test case:
find i/A9999999X
Expected: No students listed. Status message states that 0 students were listed. -
Test case:
find i/A0000000Z n/John
Expected: Find command not executed. Error details shown in the status message. -
Test case:
find i/@@@
Expected: Find command not executed. Error details shown in the status message. -
Test case:
find i/
Expected: Find command not executed. Error details shown in the status message. - Test case:
find
Expected: Find command not executed. Error details shown in the status message.
- Prerequisites:
-
Finding a student using their module code
- Prerequisites:
- Sample data is loaded in TAPA.
- One or more students have “CS2100” as their module code.
- No student has “CS9999” as their module code.
-
Test case:
find m/CS2100
Expected: All students with “CS2100” as their module code are listed. Status message states how many students were listed. -
Test case:
find m/CS9999
Expected: No students listed. Status message states that 0 students were listed. -
Test case:
find m/CS2100 i/A0000000Z
Expected: Find command not executed. Error details shown in the status message. -
Test case:
find m/@@@
Expected: Find command not executed. Error details shown in the status message. -
Test case:
find m/
Expected: Find command not executed. Error details shown in the status message. - Test case:
find
Expected: Find command not executed. Error details shown in the status message.
- Prerequisites:
Assigning task(s) to students
-
Assigning task(s) to students by their student ID
- Prerequisites:
- Sample data is loaded in TAPA.
- The student associated with the student ID (“A0000000Z”) has a task (Task A) assigned to him/her.
-
Test case:
assign,assign i/A1111111Z,assign tn/Task A
Expected: An error message will be displayed to the user, due to missing compulsory fields (student ID and task name). -
Test case:
assign i/A!@#$%^&R tn/Task A,assign i/A1111111Z tn/@@@@
Expected: An error message will be displayed to the user, due to invalid format for student ID or task name. -
Test case:
assign i/AXXXXXXXR tn/Task A
Expected: An error message will be displayed to the user, as there are no students associated with this student ID in TAPA. -
Test case:
assign i/A0000000Z tn/Task A
Expected: An error message will be displayed to the user, as the task (Task A) has already been assigned to the student associated with the student ID (“A0000000Z”). - Test case:
assign i/A0000000Z tn/Task B
Expected: The list of students in TAPA will be updated, with the task (Task B) being assigned to the student associated with the student ID (“A0000000Z”).
- Prerequisites:
-
Assigning task(s) to students by their module code
- Prerequisites:
- Sample data is loaded in TAPA.
- The students associated with the student ID (“A0000000Z”) and (“A1111111Z”) has a task (Task A) assigned to them.
- The student associated with the student ID (“A5555555Z”) has the same module code (CS2100) as the student associated with the student ID (“A0000000Z”).
-
Test case:
assign,assign m/CS2100,assign tn/Task A
Expected: An error message will be displayed to the user, due to missing compulsory fields (module code and task name). -
Test case:
assign m/CS@@@@ tn/Task A,assign m/CS2100 tn/@@@@
Expected: An error message will be displayed to the user, due to invalid format for module code or task name. -
Test case:
assign m/LAM1201 tn/Task A
Expected: An error message will be displayed to the user, as there are no students associated with this module code in TAPA. -
Test case:
assign m/CS2101 tn/Task A
Expected: An error message will be displayed to the user, all the students with the module code (CS2101) already has the specified task (Task A) assigned to them. -
Test case:
assign m/CS2100 tn/Task A
Expected: The list of students in TAPA will be updated, with the task (Task A) being assigned to the student associated with the student ID (“A5555555Z”). A message will be displayed to the user, informing that the task is only assigned to some of the students in the module (CS2100). - Test case:
assign m/CS2100 tn/Task B
Expected: The list of students in TAPA will be updated, with the task (Task B) being assigned to the students associated with the module code (CS2100).
- Prerequisites:
Checking all the tasks that a student has
-
Checking all the tasks that a student has
- Prerequisites:
- Sample data is loaded in TAPA.
- The student associated with the student ID (“A0000000Z”) has a task assigned to him/her.
-
Test case:
task
Expected: An error message will be displayed to the user, due to missing compulsory field (student ID). -
Test case:
task i/A!@#$%^&R
Expected: An error message will be displayed to the user, due to invalid format for student ID. -
Test case:
task i/AXXXXXXXR
Expected: An error message will be displayed to the user, as there are no students associated with this student ID in TAPA. -
Test case:
task i/A1111111Z
Expected: An error message will be displayed to the user, as there are no tasks assigned to this student. - Test case:
task i/A0000000Z
Expected: An output list will be displayed to the user, which consists of all the tasks (“Task A”) that are assigned to the student.
- Prerequisites:
Marking an incomplete task as complete
-
Marking an incomplete task as complete
- Prerequisites:
- Sample data is loaded in TAPA.
- The student associated with the student ID (“A0000000Z”) has an incomplete task assigned to him/her, and the task is the first and only one on his/her task list.
- The student associated with the student ID (“A1111111Z”) has a complete task assigned to him/her, and the task is the first and only one on his/her task list.
-
Test case:
mark,mark i/A0000000Z,mark idx/1
Expected: An error message will be displayed to the user, due to missing compulsory fields (student ID and task index). -
Test case:
mark i/A!@#$%^&R idx/1,mark i/A0000000Z idx/0,mark i/A0000000Z idx/-1
Expected: An error message will be displayed to the user, due to invalid format for student ID or task index. -
Test case:
mark i/A0000000Z idx/3
Expected: An error message will be displayed to the user, due to the task index being out of range. -
Test case:
mark i/A1111111Z idx/1
Expected: An error message will be displayed to the user, due to the task being already marked as complete. - Test case:
mark i/A0000000Z idx/1
Expected: The list of students in TAPA will be updated, with the first task belonging to the student associated with the student ID (“A0000000Z”) marked as complete.
- Prerequisites:
Marking a complete task as incomplete
-
Marking a complete task as incomplete
- Prerequisites:
- Sample data is loaded in TAPA.
- The student associated with the student ID (“A0000000Z”) has an incomplete task assigned to him/her, and the task is the first and only one on his/her task list.
- The student associated with the student ID (“A1111111Z”) has a complete task assigned to him/her, and the task is the first and only one on his/her task list.
-
Test case:
unmark,unmark i/A0000000Z,unmark idx/1
Expected: An error message will be displayed to the user, due to missing compulsory fields (student ID and task index). -
Test case:
unmark i/A!@#$%^&R idx/1,unmark i/A0000000Z idx/0,unmark i/A0000000Z idx/-1
Expected: An error message will be displayed to the user, due to invalid format for student ID or task index. -
Test case:
unmark i/A0000000Z idx/3
Expected: An error message will be displayed to the user, due to the task index being out of range. -
Test case:
unmark i/A0000000Z idx/1
Expected: An error message will be displayed to the user, due to the task being already marked as incomplete. - Test case:
unmark i/A1111111Z idx/1
Expected: The list of students in TAPA will be updated, with the first task belonging to the student associated with the student ID (“A1111111Z”) marked as incomplete.
- Prerequisites:
Viewing the completion status of a particular task
-
Viewing the completion status of a particular task among students in a particular module
- Prerequisites:
- Sample data is loaded in TAPA.
- All students taking the module (“CS2100”) are being assigned with a task (“Task A”).
-
Test case:
progress,progress m/CS2100,progress tn/Task A
Expected: An error message will be displayed to the user, due to missing compulsory fields (module code and task name). -
Test case:
progress m/CS@@@@ tn/Task A,progress m/CS2100 tn/T@sk @
Expected: An error message will be displayed to the user, due to invalid format for module code/task name. -
Test case:
progress m/CS2100 tn/Task B
Expected: An error message will be displayed to the user, as no students who are taking “CS2100” are assigned with “Task B”. - Test case:
progress m/CS2100 tn/Task A
Expected: An output list will be displayed to the user, which consists of all students (and their respective completion status) who are taking “CS2100” and are assigned with “Task A”.
- Prerequisites:
Sorting the list of students in TAPA by the number of incomplete tasks in descending order
-
Sorting the list of students in TAPA by the number of incomplete tasks in descending order
-
Prerequisites: Sample data is loaded in TAPA.
-
Test case:
sort
Expected: The list of students in TAPA will be updated, and the students will be in order by the number of incomplete tasks in descending order.
-
Displaying a manual guide for TAPA
-
Display the format, example, and a short description for a specified command
-
Prerequisites: No prerequisites required
-
Test case:
manual @@@@,manual sleep
Expected: An error message will be displayed to the user, due to the specified command not existing. -
Test case:
manual add
Expected: The format, example, and a short description for the commandaddwill be displayed.
-
-
Displays all possible commands
-
Prerequisites: No prerequisites required
-
Test case:
manual
Expected: All possible commands are listed out.
-
Archiving details
-
Saving a copy of the details currently saved in TAPA into a separate file
-
Prerequisites: Sample data is loaded in TAPA.
-
Test Case:
archive
Expected: A new.jsonfile is created in/data, with the same contents as the original.jsondata file.
-
-
Saving a copy of the details currently saved in TAPA into a separate file
- Prerequisites:
- Sample data is loaded in TAPA.
- Remove the data directory’s (
/data) read and write permissions.
- Test case:
archive
Expected: An error message will be displayed to the user, due to errors in creating/writing to a new.jsonfile.
- Prerequisites:
Saving data
-
Dealing with corrupted entries
- The
datafiles can be found in the data folder of the repository, and will be namedaddressbook. - Modify the first entry in the data file, by deleting the word “Name” from it.
- Restart the application. Expected: TAPA will display an empty list.
- The
-
Dealing with missing entries
- The
datafiles can be found in the data folder of the repository, and will be namedaddressbook. - Remove all entries from the data file.
- Restart the application. Expected: TAPA will display an empty list.
- The
-
Dealing with missing data file
- The
datafiles can be found in the data folder of the repository, and will be namedaddressbook. - Delete
addressbook.json. - Restart the application. Expected: A new data file will be created, and TAPA will populate it with sample data entries. This list of sample entries will be displayed to the user as well.
- The