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
interface
with the same name as the Component. - implements its functionality using a concrete
{Component Name}Manager
class (which follows the corresponding APIinterface
mentioned in the previous point).
For example, the Logic
component defines its API in the Logic.java
interface and implements its functionality using the LogicManager.java
class which follows the Logic
interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component’s being coupled to the implementation of a component), as illustrated in the (partial) class diagram below.
The sections below give more details of each component.
UI component
The API of this component is specified in Ui.java
The UI consists of a MainWindow
that is made up of parts e.g.CommandBox
, ResultDisplay
, 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
Logic
component. - listens for changes to
Model
data so that the UI can be updated with the modified data. - keeps a reference to the
Logic
component, because theUI
relies on theLogic
to execute commands. - depends on some classes in the
Model
component, as it displaysPerson
object residing in theModel
.
Logic component
API : Logic.java
Here’s a (partial) class diagram of the Logic
component:
How the Logic
component works:
- When
Logic
is called upon to execute a command, it uses theAddressBookParser
class to parse the user command. - This results in a
Command
object (more precisely, an object of one of its subclasses e.g.,AddCommand
) which is executed by theLogicManager
. - The command can communicate with the
Model
when it is executed (e.g. to add aPerson
). - The result of the command execution is encapsulated as a
CommandResult
object 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
AddressBookParser
class creates anXYZCommandParser
(XYZ
is a placeholder for the specific command name e.g.,AddCommandParser
) which uses the other classes shown above to parse the user command and create aXYZCommand
object (e.g.,AddCommand
) which theAddressBookParser
returns back as aCommand
object. - All
XYZCommandParser
classes (e.g.,AddCommandParser
,DeleteCommandParser
, …) inherit from theParser
interface so that they can be treated similarly where possible e.g, during testing.
Model component
API : Model.java
The Model
component,
- stores TAPA’s data i.e., all
Person
objects (which are contained in aUniquePersonList
object). - stores the currently ‘selected’
Person
objects (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
UserPref
object that represents the user’s preferences. This is exposed to the outside as aReadOnlyUserPref
objects. - does not depend on any of the other three components (as the
Model
represents data entities of the domain, they should make sense on their own without depending on other components)
Storage component
API : Storage.java
The Storage
component,
- can save both TAPA’s data and user preference data in json format, and read them back into corresponding objects.
- inherits from both
AddressBookStorage
andUserPrefStorage
, which means it can be treated as either one (if only the functionality of only one is needed). - depends on some classes in the
Model
component (because theStorage
component’s job is to save/retrieve objects that belong to theModel
)
Common classes
Classes used by multiple components are in the 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
LogicManager
starts to parse the given input text usingAddressBookParser#parseCommand()
. - The
AddressBookParser
invokes the respectiveParser
based 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
ParseException
will be thrown if the prefix of the compulsory fields are missing. -
The
AddCommandParser
will pass the studentId input (found in theArgumentMultimap
) intoParserUtil#parseStudentId(String studentId)
.Note: A
NullPointerException
will 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 newStudentId
object will be created and returned to theAddCommandParser
. If the argument is not valid, aParseException
will 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
AddCommandParser
will create a newPerson
. - A new
AddCommand
will be created (using thePerson
in Step 9) and returned to theLogicManager
. - The
LogicManager
will then callAddCommand#execute(Model model)
. -
In the
AddCommand
, themodel#hasPerson(Person person)
will be invoked. If thePerson
already exist in TAPA, aCommandException
will be thrown.Note: In TAPA, two
Person
are considered as equal only if they have the samestudentId
. - The
AddCommand
will callmodel.addPerson(Person person)
, which adds thePerson
into theAddressBook
. - Lastly, the
AddCommand
will 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
LogicManager
starts to parse the given input text usingAddressBookParser#parseCommand()
. - The
AddressBookParser
invokes the respectiveParser
based 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
ParseException
will be thrown if the prefix of the compulsory fields are missing. -
The
DeleteCommandParser
will pass the studentId input (found in theArgumentMultimap
) intoParserUtil#parseStudentId(String studentId)
.Note: A
NullPointerException
will 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 newStudentId
object will be created and returned to theDeleteCommandParser
. If the argument is not valid, aParseException
will be thrown.Note: The above description for Steps 5 to 7 is specifically for when
studentId
is used as the input field. Depending on the type of input field used (StudentId
orIndex
), Steps 5 to 7 will be executed using the parse methods inParserUtil
that are specific to the field. In the case of indices, anIndex
array 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
DeleteCommand
will be created (using theStudentId
orIndex
array returned in Step 8) and returned to theLogicManager
. - The
LogicManager
will then callDeleteCommand#execute(Model model)
. - In the
DeleteCommand
, a newStudentIdContainsKeywordsPredicate
is created ifStudentId
was used as the input. - If
StudentId
was used, themodel#updateFilteredPersonList(Predicate<Person> predicate)
will then be invoked, which updates the filter of thePersonList
to filter by the givenStudentIdContainsKeywordsPredicate
, after which the entry (if any) that matches theStudentIdContainsKeywordsPredicate
will be deleted by invokingmodel#deletePerson(Person person)
. - Otherwise, if an
Index
array was used, a list ofPerson
s corresponding to theirIndex
in the displayed list will be created, after which they will be processed one by one for deletion. - Lastly, the
DeleteCommand
will 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
LogicManager
starts to parse the given input text usingAddressBookParser#parseCommand()
. - The
AddressBookParser
invokes the respectiveParser
based 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
ParseException
will be thrown if the prefix of the compulsory field is missing. -
The
DeleteModuleCommandParser
will pass the moduleCode input (found in theArgumentMultimap
) intoParserUtil#parseModuleCode(String moduleCode)
.Note: A
NullPointerException
will 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 newModuleCode
object will be created and returned to theDeleteModuleCommandParser
. If the argument is not valid, aParseException
will be thrown. - The
DeleteModuleCommandParser
will create a newModuleCodeContainsKeywordsPredicate
. - A new
DeleteModuleCommand
will be created (using theModuleCodeContainsKeywordsPredicate
returned in Step 8) and returned to theLogicManager
. - The
LogicManager
will then callDeleteModuleCommand#execute(Model model)
. - The
model#updateFilteredPersonList(Predicate<Person> predicate)
will then be invoked, which updates the filter of thePersonList
to filter by the givenModuleIdContainsKeywordsPredicate
. - Each
Person
that appears in the filtered list will then be deleted by invokingmodel#deletePerson(Person person)
. - Lastly, the
DeleteModuleCommand
will 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
LogicManager
starts to parse the given input text usingAddressBookParser#parseCommand()
. - The
AddressBookParser
invokes the respectiveParser
based 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
ParseException
will be thrown if the prefix of the compulsory fields are missing. -
The
FindCommandParser
will pass the studentId input (found in theArgumentMultimap
) intoParserUtil#parseStudentId(String studentId)
.Note: A
NullPointerException
will 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 newStudentId
object will be created and returned to theFindCommandParser
. If the argument is not valid, aParseException
will be thrown.Note: The above description for Steps 5 to 7 is specifically for when
studentId
is 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 inParserUtil
that 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
FindCommandParser
will create a newPredicate
. - A new
FindCommand
will be created (using thePredicate
in Step 8) and returned to theLogicManager
. - The
LogicManager
will then callFindCommand#execute(Model model)
. - In the
FindCommand
, themodel#updateFilteredPersonList(Predicate<Person> predicate)
will be invoked, which updates the filter of thePersonList
to filter by the givenPredicate
. - Lastly, the
FindCommand
will 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
LogicManager
starts to parse the given input text usingAdddressBookParser#parseCommand()
. - The
AddressBookParser
invokes the respectiveParser
based 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
ParseException
will be thrown if the prefix ofStudentId
is missing, as it is a compulsory field. -
The
TaskCommandParser
will pass the studentId input (found in theArgumentMultimap
) intoParserUtil#parseStudentId(String studentId)
.Note: A
NullPointerException
will 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, aParseException
will be thrown. - A new
TaskCommand
will be created (using theStudentId
object created in Step 7) and returned to theLogicManager
. - The
LogicManager
will then callTaskCommand#execute(Model model)
. - In the
TaskCommand
, aStudentIdContainsKeywordsPredicate
is 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 anyPerson
that corresponds to the specifiedstudentId
. If the size is equals to 0, aCommandException
will be thrown.Note: The
studentId
is a UNIQUE field in TAPA, so multiple students cannot have the samestudentId
. - The
Person
object in the filtered list is then extracted out usingmodel#getFilteredPersonList().get(0)
. - The
TaskList
belong to thisPerson
can then be retrieved usingPerson#getTaskList()
. - If this
TaskList
is null or empty, aCommandException
will be thrown. - The
TaskCommand
iterates through thisTaskList
, and categorises the tasks into two newTaskList
according to the task’s completion status. - Lastly, the
TaskCommand
will create a newCommandResult
by using theTaskList
in Step 16. ThisCommandResult
will 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
LogicManager
starts to parse the given input text usingAddressBookParser#parseCommand()
. - The
AddressBookParser
invokes the respectiveParser
based 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
ParseException
will be thrown if the prefix of the compulsory fields are missing or if the arguments are invalid. -
The
MarkCommandParser
will pass the studentId input (found in theArgumentMultiMap
) intoParserUtil#parseStudentId(String studentId)
.Note: A
NullPointerException
will 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 newStudentId
object will be created and returned to theMarkCommandParser
. If the argument is not valid, aParseException
will be thrown. -
The
MarkCommandParser
will pass the index input (found in theArgumentMultiMap
) intoParserUtil#parseIndex(Index index)
.Note: A
NullPointerException
will 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 newIndex
object will be created and returned to theMarkCommandParser
. If the argument is not valid, aParseException
will be thrown. - The
MarkCommandParser
will create a newMarkCommand
object using theStudentId
andIndex
created in Step 7 and 10 respectively. - The
LogicManager
will then callMarkCommand#execute(Model model)
. -
The
MarkCommand
will callmodel#markTaskOfPerson(Student studentId, Index index)
, which marks the task (corresponding to the supplied index) of the given student as done.Note: A
CommandException
will be thrown if the suppliedindex
orstudentId
is invalid, or if the task is already marked as completed. - Lastly, the
MarkCommand
will 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
LogicManager
starts to parse the given input text usingAddressBookParser#parseCommand()
. - The
AddressBookParser
invokes the respectiveParser
based 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
ParseException
will be thrown if the prefix of the compulsory fields are missing or if the arguments are invalid. -
The
UnmarkCommandParser
will pass the studentId input (found in theArgumentMultiMap
) intoParserUtil#parseStudentId(String studentId)
.Note: A
NullPointerException
will 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 newStudentId
object will be created and returned to theUnmarkCommandParser
. If the argument is not valid, aParseException
will be thrown. -
The
UnmarkCommandParser
will pass the index input (found in theArgumentMultiMap
) intoParserUtil#parseIndex(Index index)
.Note: A
NullPointerException
will 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 newIndex
object will be created and returned to theUnmarkCommandParser
. If the argument is not valid, aParseException
will be thrown. - The
UnmarkCommandParser
will create a newUnmarkCommand
object using theStudentId
andIndex
created in Step 7 and 10 respectively. - The
LogicManager
will then callUnmarkCommand#execute(Model model)
. -
The
UnmarkCommand
will callmodel#unmarkTaskOfPerson(Student studentId, Index index)
, which marks the task (corresponding to the supplied index) of the given student as undone.Note: A
CommandException
will be thrown if the suppliedindex
orstudentId
is invalid, or if the task is already marked as not complete. - Lastly, the
UnmarkCommand
will 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
LogicManager
parses the given input text usingAddressBookParser#parseCommand()
. - A new
ClearCommand
is created byAddressBookParser
and returned to theLogicManager
. - The
LogicManager
callsClearCommand#execute(Model model)
, which returns a newCommandResult
object (with itsisClearRequest
field set totrue
) to theLogicManager
. - The
CommandResult
(with itsisClearRequest
field set totrue
) is then returned to theMainWindow
. -
To confirm the user’s decision to clear TAPA, the
MainWindow
executesMainWindow#handleClearRequest()
which updates theCommandBox
to only recognise a “confirm” input for the next command.Note: A
CommandException
will be thrown if the user inputs anything other than “confirm” for the next input. TheCommandBox
will then return to its normal operation, accepting all commands as described in the user guide. - If the user inputs “confirm”, the
LogicManager
parses the given input text usingAddressBookParser#parseCommand()
, then a newConfirmClearCommand
is created and returned to theLogicManager
. - The
LogicManager
will then callConfirmClearCommand#execute(Model model)
. - The
ConfirmClearCommand
callsModel#setAddressBook(new AddressBook())
which resets the current list of students stored in TAPA to an empty list. - Lastly, the
ConfirmClearCommand
creates 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
LogicManager
starts to parse the given input text usingAddressBookParser#parseCommand()
. - The
AddressBookParser
invokes the respectiveParser
based 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
ArchiveCommand
utilizes the default constructor, it simply returns a newArchiveCommand
object to theAddressBookParser
. - This
ArchiveCommand
object will then be subsequently returned to theLogicManager
. - The
LogicManager
callsArchiveCommand#execute(Model model)
. - In
ArchiveCommand
, thePath
to the existingAddressBook
is extracted, by callingmodel#getAddressBookFilePath()
. - Similarly, the existing
AddressBook
is also extracted, by callingmodel#getAddressBook()
. - With the help of the
DateTimeFormatter
andLocalDateTime
in the Java 8 Date Time API, the file name and path of the new.json
data file can be obtained. - The new
.json
data file can now be created, usingFileUtil.createIfMissing(newPath)
. ACommandException
will be thrown ifArchiveCommand
fails to create this file. - The current copy of the
AddressBook
can be “copied” into a newJsonSerializableAddressBook
, which will be used to populate the new.json
data file that was created (by utilizingJsonUtil#saveJsonFile(T JsonFile, Path path)
). ACommandException
will be thrown ifArchiveCommand
fails to populate the data file. - Lastly, the
ArchiveCommand
will 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
LogicManager
starts to parse the given input text usingAdddressBookParser#parseCommand()
. - The
AddressBookParser
invokes the respectiveParser
based 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
ParseException
will be thrown if the prefix ofTask
is missing, or if either the prefix ofStudentId
orModuleCode
is missing, as they are compulsory fields. -
The
AssignCommandParser
will pass the studentId input (found in theArgumentMultimap
) intoParserUtil#parseStudentId(String studentId)
.Note: A
NullPointerException
will 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, aParseException
will be thrown.Note: The above description for Steps 5 to 7 is specifically for when
studentId
is used as the input field. In the case ofmoduleCode
, theModule
prefix will be used to tokenize the input. Depending on the type of input field used (studentId
ormoduleCode
), Steps 5 to 7 will be executed using the parse methods inParserUtil
that are specific to the field. The argument’s validity would be checked in their respective classes as well. -
The
AssignCommandParser
will pass the task input (found in theArgumentMultimap
) intoParserUtil#parseTask(String task)
.Note: A
NullPointerException
will 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, aParseException
will be thrown. -
A new
AssignCommand
will be created (using theStudentId
orModuleCode
object andTask
object created) and returned to theLogicManager
. -
The
LogicManager
will then callAssignCommand#execute(Model model)
. -
If
StudentId
is 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. IfModuleCode
is 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
StudentId
is used,UniquePersonList#assignTaskToPerson(StudentId studentId, Task task)
method is called. IfModuleCode
is used,UniquePersonList#assignTaskToAllInModule(ModuleCode moduleCoded, Task task)
is called. This will iterate through eachPerson
object and check for matchingstudentId
ormoduleCode
.Note: If no student(s) with a matching
studentId
ormoduleCode
is found, thenPersonNotFoundException
orModuleCodeNotFoundException
will be thrown. -
If a
Student
object with matchingstudentId
ormoduleCode
is found the method usesPerson#isTaskAlreadyPresent(Task task)
method to check if thetask
is assigned. If no similartask
is found, the following step will take place.Note: If all the student(s) has already been assigned that task, then
DuplicateTaskException
will be thrown. If some, not all students in themoduleCode
has already been assigned that task, thenPartialDuplicateTaskException
will be thrown. - The method gets copy of the
Student
object by invokingPerson#getCopy()
method. The copy is updated to includetask
by 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
AssignCommand
will 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
LogicManager
starts to parse the given input text usingAddressBookParser#parseCommand()
. - The
AddressBookParser
invokes the respectiveParser
based 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
ParseException
will be thrown if the prefix of the compulsory fields are missing. -
The
ProgressCommandParser
will pass the moduleCode input (found in theArgumentMultimap
) intoParserUtil#parseModuleCode(String moduleCode)
.Note: A
NullPointerException
will 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 newModuleCode
object will be created and returned to theProgressCommandParser
. If the argument is invalid, aParseException
will be thrown. - Steps 5 to 7 will be repeated for the “task name” field, by using its respective parse methods in
ParserUtil
. - A new
ProgressCommand
will be created (using the parsedModuleCode
andTask
objects) and returned to theLogicManager
. - The
LogicManager
will then callProgressCommand#execute(Model model)
. - In the
ProgressCommand
, themodel#checkProgress(ModuleCode moduleCode, Task task)
will be invoked. This method iterates through eachPerson
object. If thePerson
has the sameModuleCode
andTask
assigned to him/her, thePerson
object and the completion status (either completed/incomplete, denoted by a boolean value) will be added to aLinkedHashMap<Person, boolean>
. - If the resulting
LinkedHashMap
is null or empty, aCommandException
will be thrown. - This
LinkedHashMap
will be used to generate the output string. - The output string will be used in creating a new
CommandResult
object. - Lastly, the
CommandResult
object 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
LogicManager
starts to parse the given input text usingAddressBookParser#parseCommand()
. - The
AddressBookParser
invokes the respectiveParser
based 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
ParseException
will be thrown if the prefix ofStudentId
,Index
,ModuleCode
, andTaskName
is missing. Either the pair (consisting ofStudentId
andIndex
) or the pair (consisting ofModuleCode
andTaskName
) must be provided.
-
If either
Index
orStudentId
is given, theindexOrStudentIdGiven(ArgumentMultimap argMultimap)
method is invoked.Note: A
ParseException
will be thrown if the prefix ofStudentId
, orIndex
is missing. BothStudentId
andIndex
must be provided.
i. The
indexOrStudentIdGiven
method will pass thestudentId
input (found in theArgumentMultimap
) intoParserUtil#parseStudentId(String studentId)
.Note: A
NullPointerException
will 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 newStudentId
object will be created and returned to theDeleteTaskCommandParser
. If the argument is not valid, aParseException
will be thrown.iv. The
indexOrStudentIdGiven
method will pass the index input (found in theArgumentMultimap
) intoParserUtil#parseIndex(String oneBasedIndex)
.Note: A
NullPointerException
will 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 newIndex
object will be created and returned to theDeleteTaskCommandParser
. If the argument is not valid, aParseException
will be thrown.vii. A new
DeleteTaskCommand(StudentId studentId, Index index)
will be created (using theStudentId
andIndex
object created in Step 3 and 6) and returned to theLogicManager
. -
If either
ModuleCode
orTaskName
is given, themoduleCodeOrTaskNameGiven(ArgumentMultimap argMultimap)
method is invoked.Note: A
ParseException
will be thrown if the prefix ofModuleCode
, orTaskName
is missing. BothModuleCode
andTaskName
must be provided.
i. The
moduleCodeOrTaskNameGiven
method will pass the moduleCode input (found in theArgumentMultimap
) intoParserUtil#parseModuleCode(String moduleCode)
.Note: A
NullPointerException
will 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 newModuleCode
object will be created and returned to theDeleteTaskCommandParser
. If the argument is not valid, aParseException
will be thrown.iv. The
moduleCodeOrTaskNameGiven
method will pass the taskName input (found in theArgumentMultimap
) intoParserUtil#parseTask(String task)
.Note: A
NullPointerException
will 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 newTask
object will be created and returned to theDeleteTaskCommandParser
. If the argument is not valid, aParseException
will be thrown.vii. A new
DeleteTaskCommand(ModuleCode moduleCode, Task task)
will be created (using theModuleCode
andTask
object created in Step 3 and 6) and returned to theLogicManager
. - The
LogicManager
will then callDeleteTaskCommand#execute(Model model)
. -
If the both the
studentId
andindex
is 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
Person
object in and check for matchingstudentId
. If found, the method will get a copy of thePerson
object 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
Person
will be replaced the currentPerson
object.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 thePersonList
to filter by the givenPREDICATE_SHOW_ALL_PERSONS
. -
If the both the
moduleCode
andtask
is 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
Person
object in and check for matchingmoduleCode
. If found, the method will get a copy of thePerson
object 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
Person
will be replaced the currentPerson
object.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 thePersonList
to filter by the givenPREDICATE_SHOW_ALL_PERSONS
. - Lastly, the
DeleteTaskCommand
will create a newCommandResult
whichCommandResult
will 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,
ModelManager
is initialised with a newCommandHistory
object. -
Whenever the user successfully executes a command, the
LogicManager
callsModel#addToCommandHistory()
. This adds the command to the list of previously executed commands inCommandHistory
. - When the user inputs “history”, the
LogicManager
parses the given input text usingAddressBookParser#parseCommand()
. - A new
HistoryCommand
is created byAddressBookParser
and returned to theLogicManager
. - The
LogicManager
will then callHistoryCommand#execute(Model model)
. - Following this, the
HistoryCommand
callsModel#getCommandHistory()
to retrieve the list of previously executed commands. - The
HistoryCommand
then callsCommandHistory#display()
to convert the list to aString
which is returned toLogicManager
through 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,
ModelManager
is initialised with a newAddressBookHistory
object. -
Whenever the user successfully executes a command (excluding
clear
andundo
itself), theLogicManager
callsModel#saveCurrentAddressBookToHistory()
. This adds a copy of TAPA to the list of TAPA’s previous states inAddressBookHistory
. - When the user inputs “undo”, the
LogicManager
parses the given input text usingAddressBookParser#parseCommand()
. - A new
UndoCommand
is created byAddressBookParser
and returned to theLogicManager
. - The
LogicManager
will then callUndoCommand#execute(Model model)
. - Following this, the
UndoCommand
callsModel#undoAddressBook()
to revert the current details stored in TAPA to those stored before the previous command was executed. (WithinModelManager
,AddressBookHistory#getPreviousAddressBook
is called to retrieve the state of TAPA before the previous command.) - Lastly, the
UndoCommand
creates a newCommandResult
which 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
undo
is 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
LogicManager
starts to parse the given input text usingAddressBookParser#parseCommand()
. - The
AddressBookParser
invokes the respectiveParser
based 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
SortCommand
utilizes the default constructor, it simply returns a newSortCommand
object to theAddressBookParser
. - This
SortCommand
object will then be subsequently returned to theLogicManager
. - The
LogicManager
callsSortCommand#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
SortCommand
will 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
LogicManager
starts to parse the given input text usingAddressBookParser#parseCommand()
. - The
AddressBookParser
invokes the respectiveParser
based 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
ParseException
will be thrown if the argument is invalid. - The supplied argument will be trimmed using
String#trim()
. - The
ManualCommandParser
will create a newManualCommand
(using theargument
in Step 4), which will be returned toLogicManager
. - The
LogicManager
will callManualCommand#execute(Model model)
. If theargument
is invalid, aCommandException
will be thrown. - Lastly, the
ManualCommand
will create a newCommandResult
which 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
11
or 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
exit
command.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
list
command. 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 commandadd
will 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.json
file is created in/data
, with the same contents as the original.json
data 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.json
file.
- Prerequisites:
Saving data
-
Dealing with corrupted entries
- The
data
files 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
data
files 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
data
files 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