termiNus Developer Guide
- Introduction
- Setting up, Getting Started
- Design
- Implementation
- Appendix: Requirements
- Appendix: Instructions for manual testing
Introduction
termiNus is an interactive Command Line Interface (CLI) task manager for undergraduate students in NUS. This program will help them achieve a better grip on their school life as well as assist in better management of their daily expenses and be reminded of any library loans.
This guide gives an overview understanding of the architectural design and implementation of termiNus. It will
assist developers in the knowledge they require to further build upon this application. We hope you have a clearer picture
after reading through our Developer Guide.
Pre-requisite: Proficient in comprehending UML diagrams and notations.
Setting up, Getting Started
Setting up the project in your local machine
Ensure that you have JDK 11 or above installed on your computer.
First, fork this repo, and clone the fork to your local machine.
If you plan to use IntelliJ IDEA (highly recommended):
- Ensure IntelliJ IDEA is configured to use JDK 11.
- Open IntelliJ and a welcome screen should appear.
- Click on
Configure->Structure for New Projects->Project Settings->Project. - Under the
Project SDK:section, select java version “11.0.8” or higher).
- Import the project as a Gradle project.
- Ensure Gradle plugin is enabled by going to
File->Settings->Plugins. - Under the
Installedsection go toBuild Toolsand enable Gradle. - At the welcome page, click on
Open or Import. - Locate the
build.gradlefile within the folder that contains the clone repo and select it. - Choose the
Open as Projectoption when asked. - Accept all default settings and wait for the project to import.
- Ensure Gradle plugin is enabled by going to
- Verify the setup.
- Under the
seedu.dukepackage, locate theDukeclass and run it. - Try a few commands. You may want to refer to the user guide.
- Under the
Before writing the code
- Configure the coding style
- If using IntelliJ IDEA, follow this guide to set up IDEA’s coding style to match ours.
- Set up CI
- This project comes with a GitHub Actions config files (in
.github/workflowsfolder). When GitHub detects those files, it will run the CI for the project automatically at each push to themasterbranch or to any PR. No setup is required for this.
- This project comes with a GitHub Actions config files (in
- Learn the design
- When you are ready to start coding, we recommend that you refer to termiNus’s architecture to get a better idea of the overall design.
Design
Architecture
Architecture Diagram
Below is an architecture diagram of termiNus.

Dukeis the main object of the program and handles all the logic and models related to the program.Uiis the main object that provides an interface betweenDukeand the user.Commandrepresents a command that is provided by the user.Uireads the command before it is sent toParserto create a newCommandobject.Parsercreates a command object by parsing the user’s arguments and sending them toCommandCreator, which returns aCommandobject. For instances where no arguments are needed (such asByeCommand), Parser creates theCommandobject directly.Dukeexecutes theCommandand shows the output to the user throughUi.Commandobject modifies the state ofModel, which consists of multiple lists for different types ofItems.Storagetakes the state ofModeland stores it to file.
Sequence Diagram
Below is a sequence diagram of how the main program functions.

- First, the
mainfunction of theDukeclass creates an instance ofDuke. - During the instantiation of
Duke, aModelobject is created. Dukeloads the state ofModelfrom file by calling theload()method ofModel.- After
Dukeis initialized, theDukeclass calls therun()method ofDuke. Dukecalls methods fromUiclass and shows messages to the user.Dukereads user commands using theUiclass (which acts as an interface betweenDukeand the user).Commandobject is returned toDukewhich is executed.Commandobject interacts withModeland changes its state.Dukesaves the state ofModelto file by calling thesave()method ofModel.Dukecontinues reading commands until aByeCommandis generated by the user.
Ui component
The Ui component is a user interface which reads user input command and output interacting messages.
The Ui component represents a Ui class and acts as an interface between Duke and the user.
The Ui component:
- Reads input from the user.
- Prints the output to the user, for example during the execution of a
Command. - Displays other types of output to the user, such as a calendar.
Parser component
The Parser class is a class forming part of the logic of termiNus. The Parser parses user commands and
returns a Command subclass which corresponds to the full command with arguments.
Command component
The Command component represents an abstract object with state corresponding to a single line of the user’s input.
Every basic command inherits the abstract Command class, with their own attributes and execute operations. After
user input is parsed by Parser, CommandCreator will create and return the corresponding command to be execute.
The Command object:
- Modifies the state of
Modelobject which depends on the state and type ofCommandobject. - Exposes its
execute()method so that it can be passed around before theCommandis executed. - Is executed by the
Dukeobject. - Prints the output to the user through the
Uicomponent.
CommandCreator component
The CommandCreator represents a class with methods that generate Commands from parsed arguments from Parser class.
The CommandCreator class:
- Takes in arguments as needed by
Parserclass. - Splits the arguments further into more parts if the
Commandhas more arguments in the description. - Returns a
Commandsubclass object depending on the method that was called.
Storage component
The Storage class is a class loading data from files when termiNus starts and saving data to files after each command.
The Storage object:
- Is referenced only by
Model. - Expose functions to allow
Modelto pass in the state and saves it to file. - Expose functions to load the state of
Modelfrom file.
Item component
Item is a super class with 5 subclasses inheriting it: Task, Expense, Module, Link, Book.
Here is the class diagram for Item class and its subclasses.

The Item class and its subclasses:
- Contains getters and setters to retrieve and set the attributes.
Model Component

The Model component represents the state of the various lists stored in memory.
The Model component:
- Stores and loads program state to file using the
StorageAPI. - Expose references to its
ItemListobjects so that other objects such asCommandcan modify it.
Implementation
This section describes how certain features are implemented.
Parser
The Parser class is a class that takes in a single line of the user’s command and returns a corresponding Command that can be executed.
The Parser object:
- Expose functions to allow
Modelto pass in the user’s full command to be parsed. - Uses regular expressions to parse the user’s arguments into several parts.
- Passes these parts to
CommandCreatorto create the corresponding command. - Returns the
CommandtoModelthat can be executed.
High level description
The Parser.parse() method takes in fullCommand as an argument, which is the full command entered by the user.
Example commands:
add task tP meeting c/cs2113 p/0add module CS2113 mc/4 ay/2021S1 g/A
The fullCommand is composed of several parts, which consists of a root command (add), description (module CS2113)
and optional arguments (mc/4 ay/2021S1 g/A).
An optional argument consists of 2 parts, which is delimited by a forward slash. In the example above, there are 3 optional
arguments, which are mc/4, ay/2021S1 and g/A. Each optional argument can be represented in this form: <key>/<value>.
In some commands, the optional arguments may be compulsory and is checked by the Parser at runtime.
The parse method parses the fullCommand into these parts before passing them as arguments to CommandCreator
methods and returns a Command object with the corresponding arguments.
The following sequence diagram shows how the Parser works.

The following diagram shows how a command should be parsed into its separate parts.

Implementation details
- The
parsemethod ofParseris invoked by the calling object. In termiNus, the only object that invokes this method isDuke. ThefullCommandis passed an argument, which is the full command entered by the user. - The method parses
fullCommandinto two separateStrings, which arerootCommandandcommandString.rootCommandcontains the first word of the command andcommandStringcontains the rest of the command with the first word removed. This is done using thesplitmethod of theStringclass, then removing therootCommandfrom thefullCommandbefore storing it incommandString. - The method then invokes the
removeArgumentsFromCommandmethod to parse and remove optional arguments from the full command. This is done using regular expression parsing which is detailed in the next section. The results are returned to theparsemethod and stored indescription. - The method then invokes the
getArgumentsFromRegexmethod when therootCommandis not"find"to parse the optional arguments from the full command. The results are stored in aHashMap<String, String>, which is aHashMapof key-value pairs, similar to the form of the optional argument (<key>/<value>). The results are returned to theparsemethod and stored asargumentsMap. - The method then checks the
rootCommandand decides whichCommandto return, which callsCommandCreatormethods with the parsedargumentsMap,description, andcommandString. - For certain commands,
checkAllowedArgumentsmethod is called to ensure that the user did not pass in invalid arguments for that given command, and throws an error if there are invalid arguments. - For single-word commands like
bye,checkFullCommandmethod is called to ensure that the full command corresponds to the command word, and rejects commands likebye 3. - The results of the
CommandCreatormethods are returned as aCommandback to the invoker of theparsemethod.
Regular expression parsing
Two of the previously mentioned methods, removeArgumentsFromCommand and getArgumentsFromRegex make use of regular
expressions to parse the optional arguments.
The diagram below illustrates how the regular expression matches an optional argument.

- The regular expression that parses these optional arguments is
([\w]+/[^\s]+). This regular expression matches 1 or more alphanumeric characters (denoted by[\w]+), followed by a forward slash, then 1 or more non-whitespace character (denoted by[^\s]+). - The expression also uses capturing parenthesis to ensure that the parser does not parse the same argument twice.
Design considerations
- The results of
getArgumentsFromRegexare stored as aHashMapinstead ofArrayListor simply returned as a value. This allows the same method to be reused for different commands, which may accept different optional arguments with different key-value pairs. This ensures that the code follows DRY principles. - The regular expressions parsing means that we do not need to manually parse every different command with different arguments, thus reducing code complexity and SLOC.
Storage
This section describes how the Storage class works
High level description
Methods handling data loading (i.e. loadTask(), loadBook(), loadLinks(), loadModule(), loadExpense() methods)
return an ArrayList of items (i.e. Task, Book, Link, Module, Expense). These will be the initial values of
the item list (i.e. TaskList, BookList, LinkList, ModuleList, ExpenseList). The save() method takes an
inherited instance of ItemList and a String specifying the path to which the file will be saved. The ItemList will
be parsed and saved into files (each ItemList will be saved to a separate file) at the specified path.
Formats of the files:
tasks.txt:
There are 6 fields stored for each Task:
- String
Tfor “Task” - Whether the
Taskhas been done or not (1 for done, 0 for not done) - Description of the
Task - Priority of the
Task(an Integer) - Category of the
Task - Date of the
Task
All the fields are separated by | with a leading and a trailing space. Each Task is stored as one line.
Example: T | 0 | borrow book | 1 | book | 28-10-2020
books.txt:
There are 5 fields stored for each Book:
- String
Bfor “Book” - Whether the
Bookhas been returned or not (1 for returned, 0 for not returned) - Name/Description of the
Book - Borrow date of the
Book - Return date of the
Book
All the fields are separated by | with a leading and a trailing space. Each Book is stored as one line.
Example: B | 0 | cooking book | 11-11-2011 | 11-12-2011
links.txt:
There are 3 fields stored for each Link:
- Module of the
Link - Use of the
Link - URL of the
Link
All the fields are separated by | with a leading and a trailing space. Each Link is stored as one line.
Example: CS2113 | lecture | https://cs2113Lecture.zoom.com
modules.txt:
There are 4 fields for each Module:
- Module code
- Grade
- Modular credits
- Academic year and semester
All the fields are separated by | with a leading and a trailing space. Each Module is stored as one line.
expenses.txt
There are 4 fields for each Expense:
- Description
- Value
- Currency
- Date
All the fields are separated by | with a leading and a trailing space. Each Module is stored as one line.
Currency has default value “SGD”.
Date has default value of the date that the spend command is executed.
Date will be in the format of yyyy-MM-dd, e.g. 2020-11-09.
Implementation details
The following sequence diagram shows how the Storage works.

- At the start of
Duke, a newStorageobject will be created. Dukecalls loading methods (i.e.loadTask(),loadBook(),loadLinks(),loadModule(),loadExpense()) sequentially. Each loading method calls the corresponding helper method (i.e.loadTaskFromLine(),loadBookFromLine(),loadLinkFromLine(),loadModuleFromLine(),loadExpenseFromLine()) to loadItems from each line in the file.- After each command,
Dukecalls thesave()method ofStorageto save all theItems in the list to files.
List feature
List tasks
The list tasks feature allows the user to list all the tasks tracked.
This feature is facilitated by ListCommand.
- The user inputs the command
list tasks. (Assuming the task list is not empty) - The full command string will be parsed by
Parser, whoseparse()method returns aCommandCreatorobject to create aListCommand. - The method
createListCommand()inCommandCreatorfurther parses the input by identifying the keywordtasks, and returns aListCommandfor the whole task list. - The command is executed and the complete list of all the tracked tasks is displayed.
List tasks with priority
The list tasks with priority feature allows the user to list tasks of a certain priority.
This feature is facilitated by Parser and ListCommand.
- The user inputs the command
list tasks p/3. (Assuming the tasks of priority 3 exist.) - The full command string will be parsed by
Parser, whoseparse()method returns aCommandCreatorobject to create aListCommand. - The method
createListCommand()inCommandCreatorfurther parses the input by identifying the keywordtasksandp/, and returns aListCommandfor the task list of priority level 3. - The command is executed and the list of tasks with priority 3 is displayed.
List tasks with category
The list tasks with category feature allows the user to list tasks of a certain category.
This feature is facilitated by Parser and ListCommand.
- The user inputs the command
list tasks c/CS2113. (Assuming the tasks of CS2113 exist.) - The full command string will be parsed by
Parser, whoseparse()method returns aCommandCreatorobject to create aListCommand. - The method
createListCommand()inCommandCreatorfurther parses the input by identifying the keywordtasksandc/, and returns aListCommandfor the task list under CS2113 category. - The command is executed and the list of tasks categorized by CS2113 is displayed.
Add links
The add links feature allows the user to add and save zoom meeting links of modules.
This feature is faclitated by Parser, AddCommand and Storage.
- The user inputs
add links m/CS2113 t/lecture u/https://nus.sg.zoom.us/cs2113/lecture. - The full command string will be parsed by
Parser, whoseparse()method returns aCommandCreatorobject to create aAddCommand. - The method
createAddCommand()inCommandCreatorfurther parses the input by identifying the keywordlink, and returns aAddCommand. - The command is excuted and the link is added into the link list with module name and online class type.
Storagesaves the added link by writing it into thelinks.txtfile.
List links
The list link feature allows the user to list all the zoom meeting links.
This feature is facilitated by Parser and AddCommand.
- The user inputs
list links. (Assuming the link list is not empty). - The full command string will be parsed by
Parser, whoseparse()method returns aCommandCreatorobject to create aListCommand. - The method
createListCommand()inCommandCreatorfurther parses the input by identifying the keywordlinks, and returns aListCommandfor the link list. - The command is excuted and the complete list of links is displayed.
List expenses
The list expenses feature allows the user to list all the expense items in the expense list together with a summary message displaying the total amount of expenses listed for each currency.
This feature is facilitated by Parser and ListExpenseCommand.
- The user inputs
list expenses. - The full command string will be parsed by
Parser, whoseparse()method returns aCommandCreatorobject to create aListExpense Command. - The method
createListCommand()inCommandCreatorfurther parses the input by identifying the keywordexpenses, and calls the static methodcreateListExpenseCommand()in classListExpenseCommand. - The static method
creatListExpenseCommand()in classListExpenseCommandfurther parses the arguments and returns a newListExpenseCommandfor the expense list. - The command is executed and the complete expense list is displayed together with the summary information.
- If the expense list is empty, the message
There are no expense items to be listed in your expense list.will be displayed.
List expenses with currency
The list expenses with currency feature allows the user to list expense items of a curtain currency together with a summary message displaying the total amount of expenses listed for each currency.
This feature is facilitated by Parser and ListExpenseCommand.
- The user inputs the command
list expenses currency/USD. - The full command string will be parsed by
Parser, whoseparse()method returns aCommandCreatorobject to create aListExpense Command. - The method
createListCommand()inCommandCreatorfurther parses the input by identifying the keywordexpenses, and calls the static methodcreateListExpenseCommand()in classListExpenseCommand. - The static method
creatListExpenseCommand()in classListExpenseCommandfurther parses the arguments by identifying keywordcurrency, and returns a newListExpenseCommandfor the expense list. - The command is executed and the expense list with
currencyUSDis displayed together with the summary information.
- If the expense list is empty, the message
There are no expense items to be listed in your expense list.will be displayed.
List expenses with date
The list expenses with date feature allows the user to list expense items of a curtain date together with a summary message displaying the total amount of expenses listed for each currency.
This feature is facilitated by Parser and ListExpenseCommand.
- The user inputs the command
list expenses date/2020-11-09. - The full command string will be parsed by
Parser, whoseparse()method returns aCommandCreatorobject to create aListExpense Command. - The method
createListCommand()inCommandCreatorfurther parses the input by identifying the keywordexpenses, and calls the static methodcreateListExpenseCommand()in classListExpenseCommand. - The static method
creatListExpenseCommand()in classListExpenseCommandfurther parses the arguments by identifying keyworddate, and returns a newListExpenseCommandfor the expense list. - The command is executed and the expense list with
date2020-11-09is displayed together with the summary information.
-
If the expense list is empty, the message
There are no expense items to be listed in your expense list.will be displayed. -
The
dateargument must be in the format ofdate/<yyyy-MM-dd>. If thedateargument does not follow the correct format, an error messagePlease input a valid date string in the format "yyyy-MM-dd"will be displayed.
List expenses with date
The list expenses with date feature allows the user to list expense items of a curtain date together with a summary message displaying the total amount of expenses listed for each currency.
This feature is facilitated by Parser and ListExpenseCommand.
- The user inputs the command
list expenses date/2020-11-09. - The full command string will be parsed by
Parser, whoseparse()method returns aCommandCreatorobject to create aListExpense Command. - The method
createListCommand()inCommandCreatorfurther parses the input by identifying the keywordexpenses, and calls the static methodcreateListExpenseCommand()in classListExpenseCommand. - The static method
creatListExpenseCommand()in classListExpenseCommandfurther parses the arguments by identifying keyworddate, and returns a newListExpenseCommandfor the expense list. - The command is executed and the expense list with
date2020-11-09is displayed together with the summary information.
-
If the expense list is empty, the message
There are no expense items to be listed in your expense list.will be displayed. -
The
dateargument must be in the format ofdate/<yyyy-MM-dd>. If thedateargument does not follow the correct format, an error messagePlease input the date string in the format "yyyy-MM-dd"will be displayed.
List expenses for a certain date range
The list expenses for a certain date range feature allows the user to list expense items of a curtain date range (i.e. today/this week/this month/this year) together with a summary message displaying the total amount of expenses listed for each currency.
This feature is facilitated by Parser and ListExpenseCommand.
- The user inputs the command
list expenses for/WEEK. - The full command string will be parsed by
Parser, whoseparse()method returns aCommandCreatorobject to create aListExpense Command. - The method
createListCommand()inCommandCreatorfurther parses the input by identifying the keywordfor, and calls the static methodcreateListExpenseCommand()in classListExpenseCommand. - The static method
creatListExpenseCommand()in classListExpenseCommandfurther parses the arguments by identifying keywordfor, and returns a newListExpenseCommandfor the expense list. - The command is executed and the expense list for the currency week is displayed together with the summary information.
-
If the expense list is empty, the message
There are no expense items to be listed in your expense list.will be displayed. -
The
forargument is case-insensitive. For example, bothlist expenses for/MONTHandlist expenses for/monthare valid commands.
Calendar feature
Calendar command
The calendar command allows users to print out a calendar view of their tasks within the next X days, where X is a parameter passed by the user.
CalendarCommandobtains a list of tasks fromTaskListby using itsgetTaskListmethod, which returns anArrayListofTaskobjects.- The list of tasks is converted into a
Stream. - The
Taskobjects without dates are filtered out. - The
Taskobjects outside the range of the current date andXdays of the current date are filtered out. - The
ArrayListis sorted by task dates, which uses aComparatordefined in the parameters. - The
Streamis collected back into anArrayList, which has sorted dates of tasks within the nextXdays. - The
ArrayListofTaskobjects are passed to theUi.dukePrintCalendarmethod, which prints the tasks as a calendar. - The
dukePrintCalendarmethod groups tasks by date and a new heading is printed for each day. This is done by comparing eachTaskin the loop with the previous task to check if they have the same date, and to print a new heading if not.
The filtering of the tasks by date is done using this code, which is called on a Stream object.
.filter(task -> currentDate.until(task.getDate(), ChronoUnit.DAYS) >= 0)
.filter(task -> currentDate.until(task.getDate(), ChronoUnit.DAYS) <= daysToPrint)
The sorting of tasks by date is done using this code, which is also called on a Stream object.
.sorted(Comparator.comparing(Task::getDate))
This sorts the stream using a Comparator which is defined inline. The Comparator makes use of the Task.getDate() method to do the comparisons.
This is done instead of defining a new Comparator class as toCompare is already implemented in the LocaDate API, and doing this simplifies the code.
Delete feature
Delete tasks by index
The delete tasks by index feature allows the user to delete a task identified by a certain index.
This feature is facilitated by Parser and DeleteCommand.
- The user inputs the command
delete task 2. (Assuming the task of index2exist.) - The full command string will be parsed by
Parser, whoseparse()command returns aCommandCreatorobject to create aDeleteCommand. - The method
createDeleteCommand()inCommandCreatorfurther parses the input by identifying the keywordtask, and returns aDeleteCommandwith the task index. - The command is executed and the task with index
2is deleted. The deleted task is displayed.
- If the task does not exist in the task list, the error message
~Error~ This task index does not exist. Please try again.will be displayed.
Delete tasks with priority
The delete tasks with priority feature allows the user to delete all the tasks of a certain priority.
This feature is facilicated by Parser and DeleteCommand.
- The user inputs the command
delete tasks p/2. (Assuming the tasks of priority2exist.) - The full command string will be parsed by
Parser, whoseparse()command returns aCommandCreatorobject to create aDeleteCommand. - The method
createDeleteCommand()inCommandCreatorfurther parses the input by identifying the keywordtasksandp/, and returns aDeleteCommandfor the task list of priority level2. - The command is executed and all tasks with priority level
2are deleted. The deleted tasks are displayed.
- If the priority does not exist in the task list, the error message
~Error~ Invalid priority number.will be displayed.
Delete tasks with category
The delete tasks with category feature allows the user to delete all the tasks of a certain category.
This feature is facilicated by Parser and DeleteCommand.
- The user inputs the command
delete tasks c/cs2113. (Assuming the tasks of categorycs2113exist.) - The full command string will be parsed by
Parser, whoseparse()command returns aCommandCreatorobject to create aDeleteCommand. - The method
createDeleteCommand()inCommandCreatorfurther parses the input by identifying the keywordtasksandc/, and returns aDeleteCommandfor the task list of categorycs2113. - The command is executed and all tasks with category
cs2113are deleted. The deleted tasks are displayed.
- If the priority does not exist in the task list, the error message
~Error~ Invalid category.will be displayed.
Delete links by index
The delete links by index feature allows the user to delete a link identified by a certain index.
This feature is facilitated by Parser and DeleteCommand.
- The user inputs the command
delete link 2. (Assuming the link of index2exist.) - The full command string will be parsed by
Parser, whoseparse()command returns aCommandCreatorobject to create aDeleteCommand. - The method
createDeleteCommand()inCommandCreatorfurther parses the input by identifying the keywordlink, and returns aDeleteCommandwith the link index. - The command is executed and the link with index
2is deleted. The deleted link is displayed.
- If the link does not exist in the link list, the error message
~Error~ This link index does not exist. Please try again.will be displayed.
Delete modules by index
The delete modules by index feature allows the user to delete a module identified by a certain index.
This feature is facilitated by Parser and DeleteCommand.
- The user inputs the command
delete module 2. (Assuming the module of index2exist.) - The full command string will be parsed by
Parser, whoseparse()command returns aCommandCreatorobject to create aDeleteCommand. - The method
createDeleteCommand()inCommandCreatorfurther parses the input by identifying the keywordmodule, and returns aDeleteCommandwith the module index. - The command is executed and the module with index
2is deleted. The deleted module is displayed.
- If the module does not exist in the module list, the error message
~Error~ This module index does not exist. Please try again.will be displayed.
Delete expenses by index
The delete expenses by index feature allows the user to delete an expense item identified by a certain index.
This feature is facilitated by Parser and DeleteExpenseCommand.
- The user inputs
delete expense 2. (Assuming the expense item of index2exist.) - The full command string will be parsed by
Parser, whoseparse()method returns aCommandCreatorobject to create aDeleteExpenseCommand. - The method
createDeleteCommand()inCommandCreatorfurther parses the input by identifying the keywordexpenses, and returns aDeleteExpenseCommandwith the expense index. - The command is executed and the expense item with index
2is deleted. the deleted expense item is displayed.
- If the expense item does not exist in the expense list, the error message
~Error~ This expense item does not exist. Please try again.will be displayed.
Delete expenses with currency
The delete expenses with currency feature allows the user to delete all the expense items of a certain currency.
This feature is facilicated by Parser and DeleteExpenseCommand.
- The user inputs the command
delete expenses currency/USD. (Assuming the expenses of currencyUSDexist.) - The full command string will be parsed by
Parser, whoseparse()command returns aCommandCreatorobject to create aDeleteExpenseCommand. - The method
createDeleteCommand()inCommandCreatorfurther parses the input by identifying the keywordexpensesandcurrency/, and returns aDeleteExpenseCommandfor the task list of currencyUSD. - The command is executed and all expense items with currency
USDare deleted. The deleted expense items are displayed.
- If the currency does not exist in the task list, the error message
There is no expense item deleted.will be displayed.
Deleting expenses with date
The delete expenses with date feature allows the user to delete all the expense items of a certain date.
This feature is facilicated by Parser and DeleteExpenseCommand.
- The user inputs the command
delete expenses date/2020-11-09. (Assuming the expenses of date2020-11-09exist.) - The full command string will be parsed by
Parser, whoseparse()command returns aCommandCreatorobject to create aDeleteExpenseCommand. - The method
createDeleteCommand()inCommandCreatorfurther parses the input by identifying the keywordexpensesanddate/, and returns aDeleteExpenseCommandfor the task list of date2020-11-09. - The command is executed and all expense items with date
2020-11-09are deleted. The deleted expense items are displayed.
-
If the currency does not exist in the task list, the error message
There is no expense item deleted.will be displayed. -
The
dateargument must be in the format ofdate/<yyyy-MM-dd>. If thedateargument does not follow the correct format, an error messagePlease input a valid date string in the format "yyyy-MM-dd"will be displayed.
Appendix: Requirements
Product scope
Target user profile
Undergraduate students of National University of Singapore who:
- require help to better manage their school work.
- forgets to return their loan books to the library on time.
- wants a timetable planner for easy reference.
- are lazy to create separate module folders every semester.
- wish to calculate their CAP.
Value proposition
termiNus is an application which helps NUS undergraduates to better manage their school life, by providing daily task or borrowed books tracking, and module-related functions. This increase users’ efficiency and make their life more organized.
User Stories
| Version | Priority | As a … | I want to … | So that I can … |
|---|---|---|---|---|
| v1.0 | High | student | add tasks into a list | keep track of the things I need to do |
| v1.0 | High | student | assign priorities to tasks | focus on the more important things first |
| v1.0 | Medium | student | assign categories to tasks | have a more organised task list |
| v1.0 | High | student | mark tasks as done | keep track of the remaining tasks to do |
| v1.0 | Medium | student | list all tasks in my list | have a better overview |
| v1.0 | High | student | be able to delete unwanted tasks | focus on the tasks which I need |
| v1.0 | High | student | save all data after using the application | retrieve the data upon running the application |
| v2.0 | Medium | student | automatically create folders for my modules | I do not have to manually create them |
| v2.0 | High | student | add recurring tasks | avoid adding the same tasks every week |
| v2.0 | High | student | have a calendar | I can view my current and upcoming tasks |
| v2.0 | High | student | be able to set a tracker my borrowed books | avoid overdue fines |
| v2.0 | Medium | student | sort my tasks based on highest priority | focus on those tasks first |
| v2.0 | High | student | save zoom links in a centralized place | easily attend my online classes instead of looking through my email for the link |
| v2.0 | High | student | add modules and calculate my CAP | have a better projection of my grades and efforts |
| v2.0 | Low | student | login with a password | my system is protected |
Non-Functional Requirements
-
Should work on any mainstream OS as long as it has
Java 11or above installed. -
Should be able to respond to any command in less than 2 seconds.
-
A user should be able to complete majority of tasks faster using CLI than GUI.
Glossary
| Acronym | Full form | Meaning |
|---|---|---|
| CI | Continuous Integration | Combining parts of a software product to form a whole |
| SDK | Software Development Kit | A set of software tools by software vendors |
| IntelliJ | IntelliJ | An Integrated Development Environment written in Java |
| UML | Unified Modeling Language | A modeling language which to visualize the design of a system |
| CLI | Command Line Interface | A program that accepts text inputs to execute operating system functions |
| GUI | Graphical User Interface | An interface that allows users to interact through graphical icons |
| Mainstream OS | Windows, Linux, Unix, OS-X | Operating systems |
| SLOC | Source Lines of Code | The number of lines in a program’s source code |
| DRY | Don’t Repeat Yourself | Every piece of knowledge must have a single, unambiguous, authoritative representation within a system |
| CAP | Cumulative Average Point | The weighted average grade point of all modules taken by a student |
Appendix: Instructions for manual testing
Below are the steps required for manual testing of termiNus
Launch and shutdown
- Initial launch
- Download the latest version of
termiNusfrom here and copy the jar file to an empty folder. - Open a command line window in the same directory and launch termiNus by typing
java -jar termiNus.jarand press enter.
- Download the latest version of
- Shutdown
- Input
byeto exit the program.
- Input
Adding items
- Adding a task
- Test case:
add task tP submission c/CS2113 p/1 date/09-11-2020
Expected: tasktP submissionis added to the task list, with priority of1, category ofCS2113, and a date of09 Nov 2020.
- Test case:
- Adding a recurring task
-
Test case:
addr tP meeting s/26-10-2020 e/27-11-2020 day/tue c/CS2113 p/2
Expected: recurring taskstP meetingare added to the task list, with priority of2, category ofCS2113, and the recurring dates of the Tuesdays during the start and end period. -
Test case:
addr game club c/CCA <br>Expected: an error message is printed since the compulsory argumentss/,e/,day/are all required for a recurring task.
-
- Adding a module
-
Test case:
add module CS1010 d/1 g/A+ mc/4 ay/1920S1
Expected: moduleCS1010completed inAY1920S1is added to the module list, with the gradeA+and MCs of4. -
Test case:
add module STT233 d/1 g/A+ mc/4 ay/1920S1
Expected: an error message is printed since the module name is in incorrect format. -
Test case:
add module ST2334 mc/4 ay/1920S1
Expected: an error message is printed since the compulsory argumentsg/,mc/,ay/are all required for a module.
-
- Adding a link
-
Test case:
add link m/CS2113 t/lecture u/https://cs2113lecture.zoom.com
Expected: the Zoom meeting link forlectureof moduleCS2113is added to the link list. -
Test case:
add link m/CS2113 t/meeting u/https://cs2113meeting.zoom.com
Expected: an error message is printed since the input fort/argument can only belecture,tutorial,lab, orproject.
-
- borrowing a book
- Test case:
borrow Harry Potter date/10-11-2020
Expected: the bookHarry Potteris added to the book list with the loan date10 Nov 2020and due date10 Dec 2020.
- Test case:
- Adding an expense item
-
Test case:
spend lunch v/4 currency/SGD date/2020-11-08
Expected: a4.00SGDexpense onlunchonSunday, November 8,2020is added to the expense list. -
Test case:
spend book v/15
Expected: a15.00SGDexpense onbookon the current day is added to the expense list. (By default, ifcurrency/anddate/arguments are not specified, termiNus will assume the currency isSGDand the date is the current day.)
-
Creating module folders
- Test case:
makefolders
Expected: sub-folders (Lecture NotesandTutorials) are created at the output directories for each module in the module list.
Displaying items
- Displaying tasks
-
Test case:
list tasks
Expected: the complete list of tasks is displayed. -
Test case:
list tasks p/1
Expected: the list of tasks under priority1is displayed. -
Test case:
list tasks p/-1
Expected: an error message is printed, since the priority of a task can only be a non-zero integer. -
Test case:
list tasks p/4
Expected: an error message is printed, since there is no task of this priority. -
Test case:
list tasks c/CS2113
Expected: the list of tasks under categoryCS2113is displayed. -
Test case:
list tasks c/work
Expected: an error message is printed, since there is no task of this category.
-
- Displaying modules
- Test case:
list modules
Expected: the complete list of modules is displayed.
- Test case:
- Displaying links
- Test case:
list links
Expected: the complete list of links is displayed.
- Test case:
- Displaying books
- Test case:
list books
Expected: the complete list of books is displayed.
- Test case:
- Displaying expenses
-
Test case:
list expenses
Expected: the complete list of expenses is displayed, followed by the total expenses calculated for the current day, week, month, and year. -
Test case:
list expenses date/2020-11-09
Expected: the list of expenses onSunday, November 8, 2020is displayed, followed by the total expenses caculated for the given day. -
Test case:
list expenses for/week
Expected: the list of expenses for the current week is displayed.
-
Marking an item as done
Prerequisite: list the desired item list using list command. Multiple items in the list.
- Marking a task as done
- Test case:
done task 1
Expected: the first task in the task list is marked as doneY.
- Test case:
- Marking a module as completed
- Test case:
done module 1
Expected: the first module in the module list is marked as completedCM.
- Test case:
- Marking a book as returned
- Test case:
return 2
Expected: the second book in the book list is marked as returnedR.
- Test case:
Setting the priority of a task
Prerequisite: list the complete task list using list command. Multiple tasks in the list.
- Test case:
set 3 p/2
Expected: the priority of the third task in the task list is set as2.
Setting the category of a task
Prerequisite: list the complete task list using list command. Multiple tasks in the list.
- Test case:
category 2 c/CS2113
Expected: the category of the second task in the task list is set asCS2113.
Setting the date of a task
Prerequisite: list the complete task list using list command. Multiple tasks in the list.
- Test case:
date 2 date/02-01-2021
Expected: the date of the second task in the task list is set as02 Jan 2021.
Printing the task calendar
- Test case:
calendar d/3
Expected: the tasks for the current day and for the next3days are output separately as a calendar.
Searching for tasks with keywords
-
Test case:
find tP
Expected: the tasks containing the keywordtPare displayed. -
Test case:
find t
Expected: an information is printed out to informing there is no matching tasks, since there is no keywordtin any task in the list and incomplete keywords are not allowed.
Deleting items
Prerequisite: list the desired item list using list command. Multiple items in the list.
- Deleting a task/tasks
-
Test case:
delete task 1
Expected: the first task in the task list is deleted. -
Test case:
delete tasks p/1
Expected: the tasks that under priority1are deleted. -
Test case:
delete task p/0
Expected: an error message is printed indicating invalid index, since the delete command for tasks under a certain priority should usetasksinstead oftaskin the input. -
Test case:
delete tasks p/10
Expected: an error message is printed indicating invalid index, since there is no task of priority10in the list. -
Test case:
delete tasks c/CS2113
Expected: the tasks that under categoryCS2113are deleted. -
Test case:
delete task c/CS2113
Expected: an error message is printed indicating invalid index, since the delete command for tasks under a certain category should usetasksinstead oftaskin the input. -
Test case:
delete tasks c/work
Expected: an error message is printed indicating invalid category, since there is no task of categoryworkin the list.
-
- Deleting a module
-
Test case:
delete module 2
Expected: the second module in the module list is deleted. -
Test case:
delete module 8
Expected: an error message is printed, since the module index does not exist.
-
- Deleting a link
-
Test case:
delete link 1
Expected: the first link in the link list is deleted. -
Test case:
delete link 7
Expected: an error message is printed, since the link index does not exist.
-
- Deleting an expense
-
Test case:
delete expense 1
Expected: the first expense in the expense list is deleted. -
Test case:
delete expense 10
Expected: an error message is printed, since the expense index does not exist. -
Test case:
delete expenses date/2020-11-09
Expected: all the expenses onSunday, November 8, 2020are removed from the expense list. -
Test case:
delete expense date/2020-11-09
Expected: an error message is printed indicating invalid index, since the delete command for expenses on a certain day should beexpensesinstead ofexpensein the input.
-
Clearing all items
- Test case:
clear all
Expected: all the tasks, modules, links, books, and expenses are removed.
Getting help
- Test case:
help
Expected: all the available commands and their usages are displayed in the help message.