Developer Guide
Table of Contents
-
Preface
-
Setting up, getting started
-
Design
3.1 Architecture: High Level View
3.2 UI Component
3.3 Logic Component
3.4 Model Component
3.5 Storage Component
3.6 Common Classes
-
Implementation
4.1 SOChedule
4.1.1 Overview
4.1.2 Implementation of SOChedule-level Commands
4.2 Task
4.2.1 Overview
4.2.2 Implementation of Task-level Commands
4.3 Event
4.3.1 Overview
4.3.2 Implementation of Event-level Commands
-
Documentation, Logging, Testing, Configuration, Dev-Ops
Appendix
A1. Product Scope
A2. User Stories
A3. Use Cases
A4. Non-Functional Requirements
A5. Glossary
A6. Instructions for Manual Testing
A7. Saving Data
A8. Effort
Note:
The name SOChedule is case-insensitive in the text and images in this Developer Guide.
i.e. SOChedule, SoChedule, Sochedule can be used interchangeably.
1. Preface
SOChedule is a one-stop solution for managing tasks and events, optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI).
The Developer Guide for Sochedule is designed to showcase the high level architecture systems used to design and implement Sochedule.
The link to the repository can be found here.
2. Setting up, getting started
Refer to the guide Setting up and getting started.
3. Design
3.1 Architecture
The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.
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.
Each of the four components,
- defines its API in an
interface
with the same name as the Component. - exposes its functionality using a concrete
{Component Name}Manager
class (which implements the corresponding APIinterface
mentioned in the previous point.
For example, the Logic
component (see the class diagram given below) defines its API in the Logic.java
interface and exposes its functionality using the LogicManager.java
class which implements the Logic
interface.
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_task 1
.
The sections below give more details of each component.
3.2 UI component
API :
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.
The UI
component uses 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.
3.3 Logic component
API :
Logic.java
-
Logic
uses theSocheduleParser
class to parse the user command. - This results in a
Command
object which is executed by theLogicManager
. - The command execution can affect the
Model
(e.g. adding a task or an event). - The result of the command execution is encapsulated as a
CommandResult
object which is passed back to theUi
. - In addition, the
CommandResult
object can also instruct theUi
to perform certain actions, such as displaying help to the user.
Given below is the Sequence Diagram for interactions within the Logic
component for the execute("delete_task 1")
API call.
DeleteTaskCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
3.4 Model component
This section explains the high level design of the Model
component of our application.
The Model
stores:
- a
UserPref
object that represents the user’s preferences. - the Sochedule data.
There are two main packages in Model
:
- the
Task
package contains classes that represent a task. - the
Event
package contains classes that represent an event.
Also, the Model
:
- exposes an unmodifiable
ObservableList<Task>
and an unmodifiableObservableList<Event>
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. - does not depend on any of the other three components.
The class diagram below gives an overview of the Model
component.
Due to size constraint, this diagram omitted the details of the Task
and Event
packages.
For more information, please refer to the class diagrams for Task
and Event
at the later section.
API : Model.java
The class diagram below gives the design of the Task
package.
The class diagram below gives the design of the Event
package.
Tag
list and a Category
list in the Sochedule
, which Task
and Event
can refer.
This allows Sochedule
to only require one Tag
object per unique Tag
, and one Category
object per unique Object
,
instead of each Task
and Event
needing their own Tag
and Category
object.3.4.1 Design considerations for Task-related Models
When implementing Task-related models, it is important to avoid adding duplicate tasks. For example, it is undesirable for users to add the same task, completing CS2103 Quiz before 2021-06-01, twice into the task list. Because these two tasks contain the same information and can potentially cause confusion for users when he completes one and finds another task with the same description still left uncompleted.
In our application, we require users to minimally provide the name, deadline and priority when creating a task. To ensure duplicates are handled, our team went through several alternatives and here are our considerations.
Alternative 1 (Chosen Implementation) | Alternative 2 |
---|---|
|
|
We chose Alternative 1 because it is more flexible and suitable for users’ need.
There can be multiple tasks with same name but other different fields, like deadlines.
For example, a user may need to create two tasks with the same name 2103 quiz
,
but one is due on this Monday and the other is due the next Monday. Both of these 2 tasks should be allowed in our task list.
Another example can be that a user may want to create two tasks with the same name quiz
, deadline 2022-01-01
and priority 3
, but one is with tag CS2103
and the other one is with tag CS2102
.
Both of these 2 tasks should be allowed in our task list.
3.4.2 Design considerations for Event-related Models
Similar to Task-related Models, we face the same challenge when choosing between checking for the equality of name only and checking for all fields entered by the user. We chose to check for all fields for the same reasons as mentioned above.
3.4.3 Design considerations for Name
Object
When implementing the Name class, one of the considerations we need to decide is about its maximum length. Due to constraints in GUI, if the task or event has an extremely long name, only part of the name can be displayed, and the rest will be hidden and cannot be viewed. This is something undesirable.
Alternative 1 (Chosen Implementation) | Alternative 2 |
---|---|
|
|
We chose Alternative 1 because this is the most suitable option given the limited development time and more controllable impacts on other components of the application. More importantly, we estimate that the current maximum length is sufficient to meet most of our users’ common needs. Thus, under normal usage, this additional restrictions will not cause great inconveniences to our users.
3.4.3 Design considerations for Tag
and Category
Object
Similar to Name
Object, we face the same challenge when displaying tasks or events with tags and categories
of excessively long length.
We choose to set the maximum length to 15 characters long for the similar reasons as mentioned above.
3.5 Storage component
API : Storage.java
The Storage
component,
- can save
UserPref
objects in json format and read it back. - can save the Sochedule data in json format and read it back.
3.6 Common classes
Classes used by multiple components are in the seedu.address.commons
package.
Classes used by both Task
and Event
are in the seedu.address.model.common
package.
4 Implementation
This section describes some noteworthy details on how SOChedule, Task and Event are implemented.
4.1 SOChedule
4.1.1 Overview
SOChedule consists of two lists: a task list and an event list. The task list is used to accommodate different tasks specified by users while the event list is used to accommodate different events specified by users.
While both task list and event list can be updated independently by their corresponding commands (e.g. add_task
,
delete_event
), there are some SOChedule-Level commands listed as follows that can act on both task list and event list:
4.1.2 Implementation of SOChedule-Level Commands
Implementation of clear
command
In SOChedule, the governing logic behind the clear
command is laid out in ClearCommand.java
The following is a detailed explanation on how ClearCommand.java
is implemented.
Step 1: User executes clear
command to clear task and event lists.
An ClearCommandParser
object is created, and the ClearCommandParser#parse(String args)
method is called.
A ClearCommand
object is returned.
Step 2: On ClearCommand#execute()
, Model#setSochedule(new Sochedule())
is called.
This will replace Sochedule data with a new empty Sochedule.
For brevity, lower level implementation is omitted.
Step 3: On execution completion a CommandResult
is created.
A success message will be appended with CommandResult#MESSAGE_SUCCESS
.
The sequence diagram for ClearCommand
can be found below.
Implementation of summary
command
In SOChedule, the governing logic behind the summary
command is laid out in SummaryCommand.java
The following is a detailed explanation on how SummaryCommand.java
is implemented.
Step 1: User executes summary
command to get a summary of the current completion status of tasks and events.
An SummaryCommandParser
object is created, and the SummaryCommandParser#parse(String args)
method is called.
A SummaryCommand
object is returned.
Step 2: In SummaryCommand#execute()
, the following methods care called to get different statistics on task and event completion:
Model#getNumCompletedTask()
Model#getFilteredTaskList()
Model#getNumOverdueTask()
Model#getNumIncompleteTask()
-
Model#getNumIncomingEvents()
For brevity, lower level implementation is omitted.
Step 3: On execution completion a CommandResult
is created.
A success message will be appended with CommandResult#MESSAGE_SUCCESS
.
The sequence diagram for SummaryCommand
can be found below.
Implementation of find_schedule
command
In SOChedule, the governing logic behind the find_schedule
command is laid out in FindScheduleCommand.java
The find schedule mechanism is supported mainly by FindScheduleCommand
and FindScheduleCommandParser
.
The relevant methods include:
-
FindScheduleCommandParser#parse(String args)
- Parses the user input into a Date object. -
FindScheduleCommand#execute(Model model)
- Finds the uncompleted tasks with deadlines before or on the specified date and events with start date before or on and end date after or on the specified date.
Given below is an example usage scenario and how the find schedule mechanism behaves at each step.
Step 1: User executes find_schedule 2021-04-01
command to find the ongoing tasks and events before or on the given date.
An FindScheduleCommandParser
object is created, and the FindScheduleCommandParser#parse(String args)
method is called.
The method parses the 2021-04-01
and conducts validation checks.
Two predicates, TaskFindSchedulePredicate(Date date)
and EventFindSchedulePredicate(Date date)
are created based on the given date.
Then, a FindScheduleCommand
object is created given the two predicates and returned.
Step 2: On FindScheduleCommand#execute()
,
Model#updateFilteredTaskList(TaskFindSchedulePredicate taskPredicate)
and Model#updateFilteredEventList(EventFindSchedulePredicate eventPredicate)
are called.
This will update the task list to only show the uncompleted tasks with the deadline before or on the given date.
Similarly, the event list will be updated to only show the events with start date before or on the given date and end date after or on the given date.
For brevity, lower level implementation of Model#updateFilteredTaskList(TaskFindSchedulePredicate taskPredicate)
and Model#updateFilteredEventList(EventFindSchedulePredicate eventPredicate)
are omitted.
Step 3: On execution completion a CommandResult
is created.
A success message will be appended with CommandResult#MESSAGE_FIND_SCHEDULE_SUCCESS
.
The sequence diagram for a sample usage of FindScheduleCommand
can be found below.
taskPredicate
is not shown in the sequence diagram
when calling the method Model#updateFilteredTaskList(TaskFindSchedulePredicate taskPredicate)
.
Same for the method Model#updateFilteredEventList(EventFindSchedulePredicate eventPredicate)
.
Design Considerations
The purpose of find schedule is to find and show our users the list of tasks and events that are worth to be paid attention to at the specified date.
For events, it is clear that events which have not started at the given date (i.e. start date is before the given date) and events which have ended before the given date (i.e. end date is earlier than the given date) should not be selected. This leads to only finding events that are ongoing at the specified date (i.e. with start date before or on and end date after or on the specified date).
For tasks, it is debatable. Completed tasks should not shown. However, some consideration is needed to determine which uncompleted tasks to display.
Alternative 1 (Chosen Implementation) | Alternative 2 |
---|---|
|
|
Alternative 1 is chosen because we believe this implementation can make better use of the date provided and can be more helpful for users to know what tasks should be dealt with first and improve their efficiency in task and event managements.
4.2 Task
4.2.1 Overview
Task
is a type of activity that comes with a Deadline
attribute and can be marked as complete or uncompleted. It is
specified by the following attributes:
Name
Deadline
Priority
-
[Category] ...
(Optional, can be multiple) -
[Tag] ...
(Optional, can be multiple)
Note that a Task
is defined to be the same as another Task
if and only if all of their attributes listed above are
equal correspondingly.
Our Task
supports the following features through a LogicManager
.
add_task
delete_task
edit_task
-
list_task
(Omitted for brevity and simplicity) done_task
undone_task
today_task
find_task
sort_task
pin_task
/unpin_task
clear_completed_task
clear_expired_task
4.2.2 Implementation of Task-level commands
Implementation of add_task
command
In SOChedule, the governing logic behind the add_task
command is laid out in AddTaskCommand.java
The following is a detailed explanation on how AddTaskCommand.java
is implemented.
Step1: User executes add_task n/TASKNAME d/DEADLINE p/PRIORITY [c/CATEGORY]... [t/TAG]...
command to add the
specific task with given arguments. An AddTaskCommandParser
object is created, and the
AddTaskParser#parse(String args)
method is called. The method conducts parses the args
and conducts validation
checks to ensure that it compiles with the specification. An AddTaskCommand
object is returned.
Step 2: On AddTaskCommand#execute()
, Model#addTask(Task taskToAdd)
is called.
This will add the task specified into the task list.
For brevity, lower level implementation of Model#addTask(Task taskToAdd)
is omitted.
Step 3: On execution completion a CommandResult
is created.
A success message will be appended with CommandResult#MESSAGE_ADD_TASK_SUCCESS
.
The UI will also update as the underlying task list has been modified.
The sequence diagram for AddTaskCommand
can be found below.
Implementation of delete_task
command
In SOChedule, the governing logic behind the delete_task
command is laid out in DeleteTaskCommand.java
The following is a detailed explanation on how DeleteTaskCommand.java
is implemented.
Step 1: User executes delete_task INDEX
command to delete the task at the given index.
A DeleteTaskParser
object is created, and the DeleteTaskParser#parse(String args)
method is called.
The method conducts parses the INDEX
and conducts validation checks to ensure that it complies with the specification.
A DeleteTaskCommand
object is returned.
Step 2: On DeleteTaskCommand#execute()
, Model#deleteTask(Task taskToDelete)
is called.
This will delete the task at the specified index.
For brevity, lower level implementation of Model#deleteTask(Task taskToDelete)
is omitted.
Step 3: On execution completion a CommandResult
is created.
A success message will be appended with CommandResult#MESSAGE_DELETE_TASK_SUCCESS
.
The UI will also update as the underlying task list has been modified.
The sequence diagram for DeleteTaskCommand
can be found below.
Implementation of edit_task
command
In SOChedule, the governing logic behind the edit_task
command is laid out in EditTaskCommand.java
The edit task mechanism is supported mainly by EditTaskCommand
and EditTaskCommandParser
.
The relevant methods include:
-
EditTaskCommandParser#parse(String args)
- Parses the user input arguments. -
EditTaskCommand#execute(Model model)
- Edits the task at the specified index and updates its respective values with the supplied values.
Given below is an example usage scenario and how the edit task mechanism behaves at each step.
Step 1: User executes edit_task 1 n/t1
command to Edit the task at the given index.
An EditTaskCommandParser
object is created, and the EditTaskCommandParser#parse(String args)
method is called.
The method parses the 1 n/t1
and conducts validation checks to ensure that it complies with the specification.
An EditTaskDescriptor
object is created, and it contains all the field a task needed.
If the field is edited, then store the edited one; otherwise, store the original value.
An EditTaskCommand
object (with the EditTaskDescriptor
as a parameter) is returned.
Step 2: On EditTaskCommand#execute()
, Model#getFilteredTaskList()
and
Model#createEditedTask(Task taskToEdit, EditTaskDescriptor editTaskDescriptor)
are called.
These will create the edited Task. Then, Model#setTask(Task taskToEdit, Task editedTask)
and
Model#updateFilteredTaskList()
are called. These will update the edited Task into the task list.
Step 3: On execution completion a CommandResult
is created.
A success message EditTaskCommand#MESSAGE_EDIT_TASK_SUCCESS
will be displayed.
The UI will also update as the underlying task list has been modified.
The sequence diagram for a sample usage of EditTaskCommand
can be found below.
Design Considerations
One of the challenges is if we should allow overdue tasks (task with deadlines before today) to be edited.
Alternative 1 (Chosen Implementation) | Alternative 2 |
---|---|
|
|
Alternative 1 is chosen because we believe this implementation is a more suitable choice given our users’ need at normal usage. Furthermore, if users wish to their overall progress for this week, they may choose to act with caution before editing a task or editing it back quickly if they realize they have edited the wrong task.
Implementation of done_task
command
In SOChedule, the governing logic behind the done_task
command is laid out in DoneTaskCommand.java
The done task mechanism is supported mainly by DoneTaskCommand
and DoneTaskCommandParser
.
The relevant methods include:
-
DoneTaskCommandParser#parse(String args)
- Parses the user input into one or more Index objects. -
DoneTaskCommand#execute(Model model)
- Marks the tasks at the given indexes as completed.
Given below is an example usage scenario and how the done task mechanism behaves at each step.
Step 1: User executes done_task 1 2
.
These tasks will be known as target tasks.
A DoneTaskCommandParser
object is created, and the DoneTaskCommandParser#parse(String args)
method is called.
The method parses 1 2
and conducts validation checks to ensure that the given indexes are all valid unsigned non-zero integers.
A DoneTaskCommand
object is returned.
Step 2: On DoneTaskCommand#execute()
,
the indices are further checked to ensure the target tasks exist in the task list and they are not completed.
Afterwards, the information of the target tasks are copied and completed tasks with exactly the same information as the target tasks are created.
Finally, Model#setTask(Task taskToDone, Task completedTask)
are called two times to update the respective target tasks in the task list.
Model#updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS)
method is called to refresh the UI and show the update.
For brevity, lower level implementation of Model#setTask(Task taskToDone, Task completedTask)
,
and Model#updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS)
are omitted.
Step 3: On execution completion a CommandResult
is created.
A success message will be appended with CommandResult#MESSAGE_DONE_TASK_SUCCESS
.
The sequence diagram for a sample usage of DoneTaskCommand
can be found below, using the aforementioned as an example.
PREDICATE_SHOW_ALL_TASKS
is not shown in the sequence diagram
when calling the method Model#updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS)
.
Design Considerations
One of the challenges is if we should add additional support to allow done task command to mark more than one tasks as completed. Here are our considerations.
Alternative 1 | Alternative 2 (Chosen Implementation) |
---|---|
|
|
Alternative 2 is chosen because we believe this implementation is a more suitable choice.
Unlike undone_task
, users are likely to have the demand to mark multiple tasks as complete
under normal usage. Thus, we feel alternative 2 is necessary to serve our users efficiently.
Implementation of undone_task
command
In SOChedule, the governing logic behind the undone_task
command is laid out in UndoneTaskCommand.java
The undone task mechanism is supported mainly by UndoneTaskCommand
and UndoneTaskCommandParser
.
The relevant methods include:
-
UndoneTaskCommandParser#parse(String args)
- Parses the user input into an Index object. -
UndoneTaskCommand#execute(Model model)
- Marks the task at the given index as uncompleted.
Given below is an example usage scenario and how the undone task mechanism behaves at each step.
Step 1: User executes undone_task 1
command to mark the completed task at the given index as uncompleted.
This task will be known as the target task.
An UndoneTaskCommandParser
object is created, and the UndoneTaskCommandParser#parse(String args)
method is called.
The method parses the 1
and conducts validation checks to ensure that the given index is a valid unsigned non-zero integer.
An UndoneTaskCommand
object is returned.
Step 2: On UndoneTaskCommand#execute()
,
the indices are further checked to ensure the target task exist in the task list, and they are not uncompleted to begin with.
Afterwards, the information of the target task is copied, and an uncompleted task with exactly the same information as the target task is created.
Finally, Model#setTask(Task taskToUndone, Task uncompletedTask)
and Model#updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS)
method are called.
These two methods update the target task in the task list and refresh the UI to show the update.
For brevity, lower level implementation of Model#setTask(Task taskToUndone, Task uncompletedTask)
and Model#updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS)
are omitted.
Step 3: On execution completion a CommandResult
is created.
A success message will be appended with CommandResult#MESSAGE_UNDONE_TASK_SUCCESS
.
The sequence diagram for a sample usage of UndoneTaskCommand
can be found below, using the aforementioned as an example.
PREDICATE_SHOW_ALL_TASKS
is not shown in the sequence diagram
when calling the method Model#updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS)
.
The activity diagram that summaries what happens when users execute the UndoneTaskCommand
can be found below.
(For brevity, we assume user command format is valid and ‘show errors’ actions are omitted.)
Design Considerations
One of the challenges is if we should add additional support to allow undone task command to mark more than one tasks as uncompleted. Here are our considerations.
Alternative 1 (Chosen Implementation) | Alternative 2 |
---|---|
|
|
Alternative 1 is chosen because we believe this implementation is a more suitable choice given the limited development and
testing time. More importantly, unlike done_task
, users are unlikely to have the demand to mark multiple tasks as uncompleted at one go
under normal usage. Thus, we feel alternative 1 is sufficient to serve our users.
Implementation of today_task
command
In SOChedule, the governing logic behind the today_task
command is laid out in TodayTaskCommand.java
The following is a detailed explanation on how TodayTaskCommand.java
is implemented.
The TodayTaskCommand is supported mainly by TodayTaskCommand
.
The relevant methods include:
-
TodayTaskCommand#execute(Model model)
- Updates the task list on UI to show all the tasks that has deadline on today which are stored in the internal task list.
Given below is an example usage scenario and how the today_task
mechanism behaves at each step.
Step 1: User executes today_task
command to list all the tasks with deadline on today in the task list.
A TodayTaskCommand
object is returned
Step 2: On TodayTaskCommand#execute()
, Model#updateFilteredTaskList(Predicate<Task> predicate)
is called. This
will update the filtered task list with the predicate specified by the input predicate, which is a predicate of type
TaskDeadlineIsTodayPredicate
. For brevity, lower level implementation of
Model#updateFilteredTaskList(Predicate<Task> predicate)
is omitted.
Step 3: On execution completion, a CommandResult
is created. A success message will be appended with
CommandResult#MESSAGE_TODAY_TASK_SUCCESS
and MESSAGE_TASK_LISTED_OVERVIEW
. The UI will also update as the underlying
task list that has been modified.
The sequence diagram for TodayTaskCommand can be found below.
Implementation of find_task
command
In SOChedule, the governing logic behind the find_task
command is laid out in FindTaskCommand.java
The following is a detailed explanation on how FindTaskCommand.java
is implemented.
The FindTaskCommand is supported mainly by FindTaskCommand
and FindTaskCommandParser
.
The relevant methods include:
-
FindTaskCommandParser#parse(String args)
- Parses the user input into a list of keywords. -
FindTaskCommand#execute(Model model)
- Updates the task list on UI to show all the tasks whose names contain any of the given keywords from the internal task list.
Given below is an example usage scenario and how the find task mechanism behaves at each step.
Step 1: User executes find_task homework assignment
to find all tasks whose names contain any of homework
or
assignment
.
These tasks will be known as the target tasks.
A FindTaskCommandParser
object is created, and the FindTaskCommandParser#parse(String args)
method is called.
The method parses the homework assignment
into a list of strings : [homwork
, assignment
], which is the original
string delimited using whitespace. This list of strings will be passed into the constructor of
TaskNameContainsKeywordPredicate
, which will then be passed into the constucter of FindTaskCommand
.
The FindTaskCommand
object with input predicate is returned.
Step 2:
On FindTaskCommand#execute()
, Model#updateFilteredTaskList(Predicate<Task> predicate)
is called. This
will update the filtered task list with the predicate specified by the input predicate, which is a predicate of type
TaskNameContainsKeywordPredicate
. For brevity, lower level implementation of
Model#updateFilteredTaskList(Predicate<Task> predicate)
is omitted.
Step 3: On execution completion a CommandResult
is created.
A success message will be appended with CommandResult#MESSAGE_TASKS_LISTED_OVERVIEW
.
The sequence diagram for FindTaskCommand
can be found below, using find_task hw1
as an example.
Implementation of sort_task
command
In SOChedule, the governing logic behind the sort_task
command is laid out in SortTaskCommand.java
The following is a detailed explanation on how SortTaskCommand.java
is implemented in the Logic component.
The SortTaskCommand is supported mainly by SortTaskCommand
and SortTaskCommandParser
.
The relevant methods include:
-
SortTaskCommandParser#parse(String args)
- Parses the user input into a list of keywords. -
SortTaskCommand#execute(Model model)
- Updates the task list on UI to based on theARGUMENT
given.
Given below is an example usage scenario and how the sort task mechanism behaves at each step, using sort_task name
as an example.
Step 1: User executes sort_task name
command to sort the tasks based on the SORT_VAR
provided.
An SortTaskCommandParser
object is created, and the SortTaskCommandParser#parse(String args)
method is called.
The method conducts parses name
and conducts validation checks to ensure that it complies with the specification.
A SortTaskCommand
object is returned.
Step 2: On SortTaskCommand#execute()
, Model#sortTasks(String comparingVar)
is called.
This will cause the task list to sort itself, based on the provided comparingVar
(name
, in this case).
For brevity, lower level implementation of Model#sortTasks(String comparingVar)
is omitted.
Step 3: On execution completion a CommandResult
is created.
A success message will be appended with CommandResult#MESSAGE_SORT_TASK_SUCCESS
.
The UI will also update as the underlying task list has been modified.
The sequence diagram for sortTaskCommand
can be found below, using the aforementioned as an example.
Lower Level implementation
The following is a brief explanation , as illustrated by a sequence diagram, of how sorting is implemented inside the Model component.
Design Considerations for SortTaskCommand
Alternative 1 (Chosen Implementation) | Alternative 2 |
---|---|
|
|
Our group decided to go with alternative 1 and implemented an additional sort comparator known as TaskComparator
.
This is to ensure smoother UX, as well as better integration with other commands.
By implementing it in this way, our group is able to ensure that the sort order remains consistent over commands that could either:
- Alter the number of tasks shown at any one time (See
find_task
) - Change the order of task appearance independent of
sort_task
(Seepin_task
)
This would enable SOChedule to better serve the needs of its user base.
Implementation of pin_task
/unpin_task
commands
In SOChedule, the governing logic behind the pin_task
command is laid out in PinTaskCommand.java
,
while the governing logic behind unpin_task
command is laid out in UnpinTaskCommand.java
The following is a detailed explanation on how PinTaskCommand.java
is implemented.
Since UnpinTaskCommand is largely similar in implementation to PinTaskCommand, it will be omitted for brevity.
The PinTaskCommand is supported mainly by PinTaskCommand
and PinTaskCommandParser
.
The relevant methods include:
-
PinTaskCommandParser#parse(String args)
- Parses the user input into a givenINDEX
. -
PinTaskCommand#execute(Model model)
- Marks target task as pinned, and updates the UI accordingly.
Given below is an example usage scenario and how the pin task mechanism behaves at each step, using pin_task 1
as an example.
Step 1: User executes pin_task 1
command to pin the task at the given index.
An PinTaskCommandParser
object is created, and the PinTaskCommandParser#parse(String args)
method is called.
The method conducts parses 1
and conducts validation checks to ensure that it complies with the specification.
A PinTaskCommand
object is returned.
Step 2: On PinTaskCommand#execute()
, Model#pinTask(Task task)
is called.
This will pin the task at the specified index.
Subsequently, the underlying task list will be sorted by calling Model#sortTasksDefault()
, with pinned tasks being first in priority, followed by the last argument used for sorting
(if sort_task
was not called before, task list will be sorted by name).
For brevity, lower level implementation of Model#pinTask(Task task)
is omitted.
Step 3: On execution completion a CommandResult
is created.
A success message will be appended with CommandResult#MESSAGE_PIN_TASK_SUCCESS
.
The UI will also update as the underlying task list has been modified.
The sequence diagram for PinTaskCommand
can be found below.
It is largely similar to SortTaskCommand
, with a some minor differences:
- Instead of
SortTask
-related parsers and commands,PinTask
-related parsers and commands are created and activated. - Additional call to
Model#sortTasksDefault()
afterModel#pinTask(Task)
The below activity diagram summarises what happens when pin_task
is called, using pin_task 1
as an example.
It can also be similarly extrapolated and applied to unpin_task
.
Implementation of clear_completed_task
command
In SOChedule, the governing logic behind the clear_completed_task
command is laid out in ClearCompletedTaskCommand.java
The following is a detailed explanation on how ClearCompletedTaskCommand is implemented.
Step 1: User executes clear_completed_task
command to clear completed tasks in task list.
A ClearCompletedTaskCommand
object is created and returned.
Step 2: On ClearCompletedTaskCommand#execute()
, Model#clearCompletedTasks()
is called.
This will delete all ticked tasks (all completed tasks).
For brevity, lower level implementation of Model#clearCompletedTasks()
is omitted.
Step 3: On execution completion a CommandResult
is created.
A success message ClearCompletedTaskCommand#MESSAGE_CLEAR_COMPLETED_TASK_SUCCESS
will be displayed.
The sequence diagram for ClearCompletedTaskCommand
can be found below.
Implementation of clear_expired_task
command
In SOChedule, the governing logic behind the clear_expired_task
command is laid out in ClearExpiredTaskCommand.java
The following is a detailed explanation on how ClearExpiredTaskCommand.java
is implemented.
Step 1: User executes clear_expired_task
command to clear expired tasks in task list.
A ClearExpiredTaskCommand
object is created and returned.
Step 2: On ClearExpiredTaskCommand#execute()
, Model#clearExpiredTasks()
is called.
This will delete all expired tasks whose deadlines have already passed.
For brevity, lower level implementation of Model#clearExpiredTasks()
is omitted.
Step 3: On execution completion a CommandResult
is created.
A success message ClearExpiredTaskCommand#MESSAGE_CLEAR_EXPIRED_TASK_SUCCESS
will be displayed.
The sequence diagram for ClearExpiredTaskCommand
can be found below.
4.3 Event
4.3.1 Overview
Event
is a type of activity that has a specific StartDate
and StartTime
following an EndDate
and EndTime
.
It is specified by the following attributes:
Name
StartDate
StartTime
EndDate
EndTime
-
[Category] ...
(Optional, can be multiple) -
[Tag] ...
(Optional, can be multiple)
Note that an Event
is defined to be the same as another Event
if and only if all of their attributes listed above
are equal correspondingly.
Our Event
supports the following features through a LogicManager
add_event
delete_event
edit_event
-
list_event
(Omitted for brevity and simplicity) today_event
find_event
clear_expired_event
free_time
4.3.2 Implementation of Event-level commands
Implementation of add_event
command
In SOChedule, the governing logic behind the add_event
command is laid out in AddEventCommand.java
The following is a detailed explanation on how AddEventCommand.java
is implemented.
Step 1: User executes add_event n/TASKNAME sd/STARTDATE st/STARTTIME ed/ENDDATE et/ENDTIME [c/CATEGORY]... [t/TAG]...
command to add the specific event with given arguments. An AddEventCommandParser
object is created, and the
AddEventCommandParser#parse(String args)
method is called. The method conducts parses the args
and conducts validation
checks to ensure that it compiles with the specification. An AddEventCommand
object is returned.
Step 2: On AddEventCommand#execute()
, Model#addEvent(Event eventToAdd)
is called.
This will add the event specified into the event list.
For brevity, lower level implementation of Model#addEvent(Event eventToAdd)
is omitted.
Step 3: On execution completion a CommandResult
is created.
A success message AddEventCommand#MESSAGE_ADD_EVENT_SUCCESS
will be displayed.
The UI will also update as the underlying event list has been modified.
The sequence diagram for AddEventCommand
can be found below.
Implementation of delete_event
command
In SOChedule, the governing logic behind the delete_event
command is laid out in DeleteEventCommand.java
The following is a detailed explanation on how DeleteEventCommand is implemented.
Step 1: User executes delete_event 1
command to delete the event at the given index.
A DeleteEventCommandParser
object is created, and the DeleteEventParser#parse(String args)
method is called.
The method conducts parses the 1
and conducts validation checks to ensure that it complies with the specification.
A DeleteEventCommand
object is returned.
Step 2: On DeleteEventCommand#execute()
, Model#deleteEvent(Event eventToDelete)
is called.
This will delete the event at the specified index.
For brevity, lower level implementation of Model#deleteEvent(Event eventToDelete)
is omitted.
Step 3: On execution completion a CommandResult
is created.
A success message DeleteEventCommand#MESSAGE_DELETE_EVENT_SUCCESS
will be displayed.
The UI will also update as the underlying event list has been modified.
The sequence diagram for DeleteEventCommand
can be found below.
Implementation of edit_event
command
In SOChedule, the governing logic behind the edit_event
command is laid out in EditEventCommand.java
The following is a detailed explanation on how EditEventCommand is implemented.
The edit_event
feature was implemented with a static class EditEventDescriptor
introduced.
Step 1: User executes edit_event 1 n/e1
command to Edit the event at the given index.
An EditEventCommandParser
object is created, and the EditEventCommandParser#parse(String args)
method is called.
The method conducts parses the 1 n/e1
and conducts validation checks to ensure that it complies with the specification.
An EditEventDescriptor
object is created, and it contains all the field an Event needed.
If the field is edited, then store the edited one; otherwise, store the original value.
An EditEventCommand
object (with the EditEventDescriptor
as a parameter) is returned.
Step 2: On EditEventCommand#execute()
, Model#getFilteredEventList()
and
Model#createEditedEvent(Event eventToEdit, EditEventDescriptor editEventDescriptor)
are called.
These will create the edited Event. Then, Model#setEvent(Event eventToEdit, Event editedEvent)
and
Model#updateFilteredEventList()
are called. These will update the edited Event into the event list.
Step 3: On execution completion a CommandResult
is created.
A success message EditEventCommand#MESSAGE_EDIT_EVENT_SUCCESS
will be displayed.
The UI will also update as the underlying event list has been modified.
The sequence diagram for EditEventCommand
can be found below, using the aforementioned as an example.
The following activity diagram summarises what happens when a user executes a EditEventCommand: (For brevity, “Show error” actions are omitted.)
›
Design Considerations for EditEventCommand
Alternative 1 (Chosen Implementation) | Alternative 2 |
---|---|
|
|
We chose alternative 1 because when an event ends, it is meaningless to let users make changes on any field other than end date and time. We did consider the fact that an event in the real world could be extended, so we allow users to make changes on end date and time from an expired timestamp to an unexpired timestamp. Besides, we allowed an expired task to be edited is because if the task is expired but not completed yet, it would then become an “overdue task”, while there’s no “overdue event”.
Implementation of today_event
command
In SOChedule, the governing logic behind the today_event
command is laid out in TodayEventCommand.java
The following is a detailed explanation on how TodayEventCommand is implemented.
The TodayEventCommand is supported mainly by TodayEventCommand
.
The relevant methods include:
-
TodayEventCommand#execute(Model model)
- Updates the event list on UI to show all the events whose time duration has overlaps with today in the event list.
Given below is an example usage scenario and how the today_event
mechanism behaves at each step.
Step 1: User executes today_event
command to list all the events whose duration has overlap with today
in the event list.
A TodayEventCommand
object is returned
Step 2: On TodayEventCommand#execute()
, Model#updateFilteredEventList(Predicate<Event> predicate)
is called. This
will update the filtered event list with the predicate specified by the input predicate, which is a predicate of type
EventCoversTodayPredicate
. For brevity, lower level implementation of
Model#updateFilteredEventList(Predicate<Event> predicate)
is omitted.
Step 3: On execution completion, a CommandResult
is created. A success message will be appended with
CommandResult#MESSAGE_TODAY_EVENT_SUCCESS
and MESSAGE_EVENT_LISTED_OVERVIEW
. The UI will also update as the underlying
event list that has been modified.
The sequence diagram for TodayEventCommand can be found below.
Implementation of find_event
command
In SOChedule, the governing logic behind the find_event
command is laid out in FindEventCommand.java
The following is a detailed explanation on how FindEventCommand is implemented.
The FindEventCommand is supported mainly by FindEventCommand
and FindEventCommandParser
.
The relevant methods include:
-
FindEventCommandParser#parse(String args)
- Parses the user input into a list of keywords. -
FindEventCommand#execute(Model model)
- Updates the event list on UI to show all the events whose names contain any of the given keywords from the internal event list.
Given below is an example usage scenario and how the find event mechanism behaves at each step.
Step 1: User executes find_event project meeting
to find all events whose names contain any of project
or
meeting
.
Let us call these task the target tasks.
A FindEventCommandParser
object is created, and the FindEventCommandParser#parse(String args)
method is called.
The method parses the project meeting
into a list of strings : [project
, meeting
], which is the original
string splitted by whitespace. This list of strings will be passed into the constructor of
EventNameContainsKeywordPredicate
, which will then be passed into the constuctor of a FindEventCommand
.
The FindEventCommand
object with input predicate is returned.
Step 2:
On FindEventCommand#execute()
, Model#updateFilteredEventList(Predicate<Event> predicate)
is called. This
will update the filtered event list with the predicate specified by the input predicate, which is a predicate of type
EventNameContainsKeywordPredicate
. For brevity, lower level implementation of
Model#updateFilteredEventList(Predicate<Eventk> predicate)
is omitted.
Step 3: On execution completion a CommandResult
is created.
A success message will be appended with CommandResult#MESSAGE_EVENTS_LISTED_OVERVIEW
.
The sequence diagram for FindEventCommand
can be found below, using find_event meeting
as an example.
Implementation of clear_expired_event
command
In SOChedule, the governing logic behind the clear_expired_event
command is laid out in ClearExpiredEventCommand.java
The following is a detailed explanation on how ClearExpiredEventCommand is implemented.
Step 1: User executes clear_expired_event
command to clear expired events in the event list.
A ClearExpiredEventCommand
object is created and returned.
Step 2: On ClearExpiredEventCommand#execute()
, Model#clearExpiredEvents()
is called.
This will delete all expired events whose end date time have already passed.
For brevity, lower level implementation of Model#clearExpiredEvents()
is omitted.
Step 3: On execution completion a CommandResult
is created.
A success message ClearExpiredEventCommand#MESSAGE_CLEAR_EXPIRED_EVENT_SUCCESS
will be displayed.
The sequence diagram for ClearExpiredEventCommand
can be found below.
Implementation of free_time
command
In SOChedule, the governing logic behind the free_time
command is laid out in FindFreeTimeCommand.java
The following is a detailed explanation on how FindFreeTimeCommand is implemented.
Step 1: User executes free_time DATE
command to find free time slots in the given day.
An FindFreeTimeCommandParser
object is created, and the FindFreeTimeCommandParser#parse(String args)
method is called.
The method conducts parses the args
and conducts validation checks to ensure that it complies with the specification.
A FindFreeTimeCommand
object is returned.
Step 2: On FindFreeTimeCommand#execute()
, Model#getFreeTimeSlots(Date date)
is called.
This will get free time slots and store in a string arraylist.
For brevity, lower level implementation of Model#getFreeTimeSlots(Date date)
is omitted.
Step 3: On execution completion a CommandResult
is created.
A success message will be appended with CommandResult#MESSAGE_FIND_FREE_TIME_SUCCESS
.
The sequence diagram for FindFreeTimeCommand
can be found below.
The below activity diagram summarises what happens when free_time
is called.
Design Considerations for FindFreeTimeCommand
Alternative 1 (Chosen Implementation) | Alternative 2 |
---|---|
|
|
We choose alternative 1 because it presents code in a clearer way. Breaking up long methods into shorter methods will improve readability of the code. Implementing code under UniqueEventList also reduces dependency.
5. Documentation, logging, testing, configuration, dev-ops
Appendix
A1. Product scope
Target user profile:
- NUS SOC Students
- Have a need to manage a significant number of tasks and events
- Have trouble tracking their schedule
- Prefer using CLI rather than GUI
- Reasonably comfortable using CLI apps
- Can type fast and hate mouse
- Prefer desktop apps over other types
Value proposition:
- Provide a simple platform for target users to efficiently manage their schedule
- Track and manage users’ tasks and events quickly
- Provide useful features that improve the efficiency of users in task and event management
A2. User stories
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Task Related
Priority | As a … | I want to … | So that … |
---|---|---|---|
* * * |
SOC Student | Add a task to my schedule | I can track my task better |
* * * |
SOC Student | Delete a task from my schedule | I can have flexibility in my schedule |
* * * |
SOC Student | Edit tasks in my schedule | I can have flexibility in my schedule |
* * * |
SOC Student | View tasks in my schedule | I can have a better sense of what will happen in the following days or weeks |
* * |
SOC Student | Mark a task complete in my schedule | I can track which tasks I have completed |
* * |
SOC Student | Undo a completed task in my schedule | I undo the marking if it is done by mistake |
* * |
SOC Student | Sort my tasks in my schedule in various orderings | I can prioritise my time better |
* * |
SOC Student | Pin certain tasks in my schedule | I can prioritise my time better |
* * |
SOC Student | Unpin certain tasks in my schedule | I can prioritise my time better |
* |
SOC Student | View tasks with the deadline on current date | I can have a better sense of what tasks are due today |
* |
SOC Student | Search tasks by certain keywords | I can view the details of the task that I want to find |
* |
SOC Student | Clear completed tasks | I can make my schedule cleaner |
* |
SOC Student | Clear expired tasks | I can make my schedule cleaner |
* |
SOC Student | Allocate a priority score to a task | I can prioritise my time better |
* |
SOC Student | Allocate a category to a task | I can know what category my tasks belong to |
Event Related
Priority | As a … | I want to … | So that … |
---|---|---|---|
* * * |
SOC Student | Add an event to my schedule | I can track my events better |
* * * |
SOC Student | Delete an event from my schedule from my schedule | I can have flexibility in my schedule |
* * * |
SOC Student | Edit events in my schedule | I can have flexibility in my schedule |
* * * |
SOC Student | View events in my schedule | I can have a better sense of what will happen in the following days or weeks |
* * |
SOC Student | Find free time slots on a specific date | I can allocate my time better |
* |
SOC Student | View events that are happening today | I can have a better sense of what events are happening today |
* |
SOC Student | Search events by certain keywords | I can view the details of the event that I want to find |
* |
SOC Student | Clear expired events | I can make my schedule cleaner |
* |
SOC Student | Allocate a priority score to an event | I can prioritise my time better |
* |
SOC Student | Allocate a category to an event | I can know what category my events belong to |
Both Task and Event Related
Priority | As a … | I want to … | So that … |
---|---|---|---|
* * |
SOC Student | Find tasks and events before or on a given date | I can keep track of my tasks and events better |
* * |
SOC Student | Have a summary of task completion status and events in next 7 days | I can keep track of my progress and plan ahead for my schedule |
* |
SOC Student | Clear the entire schedule | I can start adding tasks and events from fresh |
{More to be added}
A3. Use cases
Use case: UC01 - Adding a task
MSS
- User wishes to add a new task.
- User enters the required parameters.
- SOChedule displays a success message for adding the task.
Use case ends.
Extensions
-
2a. Some required information about the task is missing in the command.
- 2a1. SOChedule displays an error message.
Use case ends.
- 2a1. SOChedule displays an error message.
-
2b. The date provided for the deadline of task is invalid
- 2b1. SOChedule displays an error message.
Use case ends.
- 2b1. SOChedule displays an error message.
Use case: UC02 - Deleting a task
MSS
- User requests to list tasks (UC04).
- SOChedule shows a list of tasks.
- User chooses to delete a task.
- User enters the index of the task to be deleted.
- SOChedule displays a success message for deleting the task.
Use case ends.
Extensions
-
2a. The task list is empty.
Use case ends. -
3a. The given index is invalid.
- 3a1. SOChedule displays an error message.
Use case resumes at step 2.
- 3a1. SOChedule displays an error message.
Use case: UC03 - Editing a task
MSS
- User requests to list tasks (UC04).
- SOChedule shows a list of tasks.
- User chooses to edit a task.
- SOChedule edits the task and displays a success message for editing the task.
Use case ends.
Extensions
-
2a. The task list is empty.
Use case ends. -
3a. User enters erroneous input.
- 3a1. SOChedule shows an error message.
Use case resumes at step 2.
- 3a1. SOChedule shows an error message.
-
3b. The task to be edited is completed
- 3b1. SOChedule displays an error message.
Use case resumes at step 2.
- 3b1. SOChedule displays an error message.
Use case: UC04 - Listing tasks
MSS
- User requests to list all tasks in the SOChedule.
- SOChedule displays a list of all tasks added.
Use case ends.
Extensions
-
1a. No task have been added.
- 1a1. SOChedule displays an empty list and informs user that the task list is empty.
Use case ends.
- 1a1. SOChedule displays an empty list and informs user that the task list is empty.
Use case: UC05 - Marking one or more tasks as completed
MSS
- User requests to list tasks (UC04).
- SOChedule shows a list of tasks.
- User chooses to mark one or more tasks as completed.
- SOChedule displays a success message for marking the task as completed.
Use case ends.
Extensions
-
2a. The task list is empty.
Use case ends. -
3a. Any of the tasks specified by the user is not found in the current task list.
- 3a1. SOChedule shows an error message.
Use case resumes at step 2.
- 3a1. SOChedule shows an error message.
-
3b. Any of the task specified by the user is already marked as completed.
- 3b1. SOChedule shows an error message.
Use case resumes at step 2.
- 3b1. SOChedule shows an error message.
-
3c. User enters erroneous input.
- 3c1. SOChedule shows an error message.
Use case resumes at step 2.
- 3c1. SOChedule shows an error message.
Use case: UC06 - Marking a task as uncompleted
MSS
- User requests to list tasks (UC04).
- SOChedule shows a list of tasks.
- User chooses to mark a task as uncompleted.
- SOChedule displays a success message for marking the task as uncompleted.
Use case ends.
Extensions
-
2a. The task list is empty.
Use case ends.
-
3a. The task specified by the user is not found in the current task list.
- 3a1. SOChedule shows an error message.
Use case resumes at step 2.
- 3a1. SOChedule shows an error message.
-
3b. The task specified by the user is already marked as uncompleted.
- 3b1. SOChedule shows an error message.
Use case resumes at step 2.
- 3b1. SOChedule shows an error message.
-
3c. User enters erroneous input.
- 3c1. SOChedule shows an error message.
Use case resumes at step 2.
- 3c1. SOChedule shows an error message.
Use case: UC07 - Getting tasks today
MSS
- User requests to list all tasks with deadline on today in the SOChedule.
- SOChedule displays a list of all tasks with deadline on today.
Use case ends.
Extensions
-
1a. No task have deadline on today.
- 1a1. SOChedule displays an empty list and informs user that the 0 task has been listed.
Use case ends.
- 1a1. SOChedule displays an empty list and informs user that the 0 task has been listed.
Use case: UC08 - Finding tasks by name
MSS
- User requests to search all the tasks whose name contains any of the input keywords.
- SOChedule displays a list of all tasks with name containing any of the input keywords.
Use case ends.
Extensions
-
1a. No task name contains any of the given keywords.
- 1a1. SOChedule displays an empty list and informs user that 0 task has been listed.
Use case ends.
- 1a1. SOChedule displays an empty list and informs user that 0 task has been listed.
Use case: UC09 - Sorting all tasks
MSS
- User requests to list tasks (UC04).
- SOChedule shows a list of tasks.
- User chooses to sort the task list based on a sort parameter.
- SOChedule sorts the task list, and displays a success message.
Use case ends.
Extensions
-
2a. The task list is empty.
Use case ends.
-
3a. The given sort argument is invalid.
- 3a1. SOChedule shows an error message indicating the invalidity of the sort argument.
Use case resumes at step 2.
- 3a1. SOChedule shows an error message indicating the invalidity of the sort argument.
Use case: UC10 - Pinning a task
MSS
- User requests to list tasks (UC04).
- SOChedule shows a list of tasks.
- User requests to pin a specific task in the list.
- SOChedule pins the task, sorts the task list (UC09), and displays a success message for pinning the task.
Use case ends.
Extensions
-
2a. The task list is empty.
Use case ends.
-
3a. The task specified by the user is not found in the current task list.
- 3a1. SOChedule shows an error message.
Use case resumes at step 2.
- 3a1. SOChedule shows an error message.
-
3b. The task specified by index is already pinned
- 3b1. SOChedule shows an error message.
Use Case resumes at step 2.
- 3b1. SOChedule shows an error message.
-
3c. User enters erroneous input.
- 3c1. SOChedule shows an error message.
Use case resumes at step 2.
- 3c1. SOChedule shows an error message.
Use case: UC11 - Unpinning a task
MSS
- User requests to list tasks (UC04).
- SOChedule shows a list of tasks.
- User requests to unpin a specific task in the list.
- SOChedule unpins the task, sorts the task list (UC09), and displays a success message for unpinning the task.
Use case ends.
Extensions
-
2a. The task list is empty.
Use case ends.
-
3a. The task specified by the user is not found in the current task list.
- 3a1. SOChedule shows an error message.
Use case resumes at step 2.
- 3a1. SOChedule shows an error message.
-
3b. The task specified by index is not pinned
- 3b1. SOChedule shows an error message.
Use Case resumes at step 2.
- 3b1. SOChedule shows an error message.
-
3c. User enters erroneous input.
- 3c1. SOChedule shows an error message.
Use case resumes at step 2.
- 3c1. SOChedule shows an error message.
Use case: UC12 - Clearing all completed tasks
MSS
- User requests to clear all completed tasks.
- SOChedule displays a success message for clearing all completed tasks.
Use case ends.
Use case: UC13 - Clearing all expired tasks
MSS
- User requests to clear all expired tasks.
- SOChedule displays a success message for clearing all expired tasks.
Use case ends.
Use case: UC14 - Adding an event
MSS
- User requests to add a new event.
- SOChedule displays a success message for adding the event.
Use case ends.
Extensions
-
1a. Some required information about the event is missing in the command.
- 1a1. SOChedule displays an error message.
Use case ends.
- 1a1. SOChedule displays an error message.
-
1b. The date provided for the event is invalid
- 1b1. SOChedule displays an error message.
Use case ends.
- 1b1. SOChedule displays an error message.
Use case: UC15 - Deleting an event
MSS
- User requests to list events (UC17).
- SOChedule shows a list of events.
- User requests to delete a specific event in the list.
- SOChedule displays a success message for deleting the event.
Use case ends.
Extensions
-
2a. The event list is empty.
Use case ends.
-
3a. The given index is invalid.
- 3a1. SOChedule shows an error message.
Use case resumes at step 2.
- 3a1. SOChedule shows an error message.
Use case: UC16 - Editing an event
MSS
- User requests to list events (UC17).
- SOChedule shows a list of events.
- User requests to edit a specific event in the list.
- SOChedule displays a success message for editing the event.
Use case ends.
Extensions
-
3a. User enters erroneous input.
- 3a1. SOChedule shows an error message.
Use case resumes at step 2.
- 3a1. SOChedule shows an error message.
-
3b. The event to be edited is expired
- 3b1. SOChedule displays an error message.
Use case resumes at step 2.
- 3b1. SOChedule displays an error message.
Use case: UC17 - Listing events
MSS
- User requests to list all events in the SOChedule.
- SOChedule displays a list of all events added.
Use case ends.
Extensions
-
1a. No events have been added.
- 1a1. SOChedule displays an empty list and informs user that the event list is empty.
Use case ends.
- 1a1. SOChedule displays an empty list and informs user that the event list is empty.
Use case: UC18 - Getting today’s events
MSS
- User requests to list all events that are happening on today in the SOChedule.
- SOChedule displays a list of all events that are happening on today.
Use case ends.
Extensions
-
1a. No event is happening on today.
- 1a1. SOChedule displays an empty list and informs user that the 0 event has been listed.
Use case ends.
- 1a1. SOChedule displays an empty list and informs user that the 0 event has been listed.
Use case: UC19 - Find an event
MSS
- User requests to search all the events whose name contains any of the input keywords.
- SOChedule displays a list of all events with name containing any of the input keywords.
Use case ends.
Extensions
-
1a. No event name contains any of the given keywords.
- 1a1. SOChedule displays an empty list.
Use case ends.
- 1a1. SOChedule displays an empty list.
Use case: UC20 - Clearing expired events
MSS
- User requests to clear all expired events.
- SOChedule displays a success message for clearing all expired events.
Use case ends.
Use case: UC21 - Finding schedule given a date
MSS
- User wishes to find schedule given a specified date.
- SOChedule shows the schedule of the user.
Use case ends.
Extensions
-
2a. User enters erroneous input.
- 2a1. SOChedule shows an error message.
Use case resumes at step 1.
- 2a1. SOChedule shows an error message.
-
2b. Both task list and event list are empty.
- 2b1. SOChedule shows an empty task list and event list.
Use case ends.
- 2b1. SOChedule shows an empty task list and event list.
Use case: UC22 - Finding free time slots
MSS
- User requests to find free time slots on a given date.
- SOChedule shows a list of free time slots on that date.
Use case ends.
Extensions
-
2a. There is no free time on the given date.
- 2a1. SOChedule notifies user that there is no free time.
Use case ends.
- 2a1. SOChedule notifies user that there is no free time.
-
2b. The given date is invalid.
- 2b1. SOChedule displays an error message.
Use case ends.
- 2b1. SOChedule displays an error message.
Use case: UC23 - Getting a summary of SOChedule
MSS
- User requests to have a summary.
- SOChedule shows a list of different types of tasks and events happening in the next 7 days.
Use case ends.
Use case: UC24 - Clearing SOChedule
MSS
- User requests to clear the whole SOChedule.
- SOChedule clears all tasks and events stored.
- SOChedule shows an empty list of tasks and events.
Use case ends.
A4. 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 500 tasks without a noticeable sluggishness in performance for typical usage.
- Should be able to hold up to 500 events without a noticeable sluggishness in performance for typical usage.
- A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
- Should give a response to user’s input within 5 seconds.
- The source code should be open source.
A5. Glossary
- Mainstream OS: Windows, Linux, Unix, OS-X
- Event: Activities that start at a specific time and ends at a specific time.
- Task: Activities to be undertaken that can be marked complete/uncompleted. It also has a compulsory date field to indicate its deadline.
A6. Instructions for manual testing
Given below are instructions to test the app manually.
-
Initial launch
-
Download the jar file and copy into an empty folder
-
For testing purposes, a sample
sochedule.json
is provided here. Place this file in a directory nameddata
.data
should be in the same relative path asSOChedule.jar
. -
Double-click the jar file.
Expected: Shows the GUI with a set of sample data.
-
Adding a task
-
Adding a task
-
Prerequisites: No duplicates tasks could exist.
-
Test case:
add_task n/Homework 1 d/2021-05-10 p/8
Expected: Task successfully added, detailed information shown in the status bar. -
Test case:
add_task n/Assignment d/2021-05-11 p/9 c/Assignment
Expected: Task successfully added, detailed information shown in the status bar. -
Test case:
add_task n/Past Task d/2021-01-07 p/7
Expected: Task is not added, since deadline is past. Detailed error message shown in the status bar. -
Other incorrect commands to try:
add_task
,add_task n/Task 1
, etc.
-
Deleting a task
-
Deleting a task while all tasks are being shown
-
Prerequisites: List all tasks using the
list_task
command. Multiple tasks in the list. -
Test case:
delete_task 1
Expected: First task is deleted from the list. Details of the deleted task shown in the status message. -
Test case:
delete_task 0
Expected: No task is deleted. Error details shown in the status message. Status bar remains the same. -
Other incorrect delete commands to try:
delete_task
,delete_task x
,...
(where x is larger than the list size)
Expected: Similar to previous.
-
Editing a task
- Edits an uncompleted task in the task list
-
Prerequisites: List all tasks using the
list_task
command. Task list is not empty. Currently, no tasks in the task list has a task nametask1
. -
Test case:
edit_task 1 n/task1
Expected: The name of the first task in the task list is updated totask1
. Details of the edited task to appear in status bar. -
Other incorrect command to try :
edit_task
-
Marking one or more tasks as done
-
Marks one or more uncompleted tasks from the task list as completed
-
Prerequisites: List all tasks using the
list_task
command. Task list is not empty. All of the tasks to be completed are currently marked as uncompleted. -
Test case:
done_task 1 2
Expected: The first and second task in the task list are marked as completed. “Completed 2 Task(s).” to appear in status bar. -
Other incorrect command to try :
done_task abc
.
-
Marking a task as uncompleted
-
Marks a completed task from the task list as uncompleted
-
Prerequisites: List all tasks using the
list_task
command. Task list is not empty. The task to be uncompleted is currently marked as completed. -
Test case:
undone_task 1
Expected: The first task in the task list are marked as uncompleted. “Uncompleted 1 Task.” to appear in status bar. -
Other incorrect command to try :
undone_task abc
.
-
Listing all tasks
-
Listing all tasks
- Test case:
list_task
Expected: All the tasks currently present in the task list will be shown.
If the task list is currently empty, a messageThere is no task present!
will be shown. Otherwise, a messageListed all task(s).
will be shown.
- Test case:
Getting today’s tasks
-
Getting today’s tasks
- Test case:
today_task
Expected: All the tasks with deadline on today will be shown.
A messageListed all tasks whose deadline is today
andx task(s) listed!
will be shown, wherex
is the number of tasks with deadline on today.
- Test case:
Finding tasks by names
-
Finding tasks by names
- Test case:
find_task homework assignment
Expected: All the tasks whose name contains any ofhomework
orassignment
in the task list will be shown.
A messagex task(s) listed!
will be shown, wherex
is the number of tasks that satisfies the condition.
- Test case:
Sorting the task list
-
Sorting the task list
-
Prerequisites: List all tasks using the
list_task
command. Task list is not empty. -
Test case:
sort_task priority
Expected: “Sorted Tasks” to appear in status bar. Task list is now sorted by priority (highest priority to lowest priority). Pinned tasks remain on top, but also sorted by priority. -
Test case:
sort_task 123
Expected: This is an invalid input. “Invalid command format!” to appear in status bar. Task list remains unchanged. -
Other valid parameters to test:
name
,completion
anddeadline
.
-
Pinning a task
-
Pinning a task while all tasks are being shown
-
Prerequisites: List all tasks using the
list_task
command. Task list is not empty. -
Test case:
pin_task 3
(Assuming there are 3 tasks in task list)
Expected: “Pinned Task” to appear in status bar. Third task is now on top of the task list, with a pin icon beside its name. -
Test case:
pin_task 0
Expected: This is an invalid input. “Invalid command format!” to appear in status bar. No task is pinned and task list remains unchanged. -
Test case:
pin_task 1
(Assuming Task 1 is already pinned)
Expected: This is an invalid input. “This task is already pinned.” to appear in status bar. Task list remains unchanged. -
Test case:
pin_task 999
(Assuming there are less than 999 tasks in task list)
Expected: This is an out-of-bounds input. “The task at this index does not exist.” to appear in status bar. No task is pinned and task list remains unchanged. -
Other incorrect delete commands to try:
pin_task
,pin_task x
(where x is larger than the list size)
Expected: Similar to previous cases.
-
Unpinning a task
-
Unpinning a task while all tasks are being shown
-
Prerequisites: List all tasks using the
list_task
command. Multiple tasks in the list. At least one task in pinned. -
Test case:
unpin_task 1
(Assuming Task 1 is pinned)
Expected: “Unpinned Task” to appear in status bar. First task may or may not be at the top of task list. For that task, pin icon beside its name is removed. -
Test case:
unpin_task 0
Expected: This is an invalid input. “Invalid command format!” to appear in status bar. Task list remains unchanged. -
Test case:
unpin_task 3
(Assuming Task 3 exists and is not pinned)
Expected: This is an invalid input. “This task is not pinned to begin with.” to appear in status bar. Task list remains unchanged. -
Test case:
unpin_task 999
(Assuming there are less than 999 tasks in task list)
Expected: This is an out-of-bounds input. “The task at this index does not exist.” to appear in status bar. No task is pinned and task list remains unchanged. -
Other incorrect delete commands to try:
unpin_task
,unpin_task x
(where x is larger than the list size)
Expected: Similar to previous cases.
-
Clearing completed tasks
-
Clearing completed tasks
- Test case:
clear_completed_task
Expected: Tasks marked as done are cleared from the list.
Success messageCompleted tasks (if any) have been cleared!
will always be shown in the status message, regardless of whether there is any completed task or not.
- Test case:
Clearing expired tasks
-
Clearing expired tasks
- Test case:
clear_expired_task
Expected: Tasks with past deadlines are cleared from the list.
Success messageExpired tasks (if any) have been cleared!
will always be shown in the status message, regardless of whether there is any expired task or not.
- Test case:
Adding an event
-
Adding an event
-
Prerequisites: No duplicates events could exist.
-
Test case:
add_event n/CS2103 meeting sd/2022-05-27 st/15:00 ed/2022-05-27 et/17:00
Expected: Event successfully added, detailed information shown in the status bar. -
Test case:
add_event n/1 Year Anniversary sd/2021-03-14 st/08:00 ed/2022-03-17 et/21:00
Expected: Event successfully added, detailed information shown in the status bar. -
Test case:
add_event n/Inter College Game sd/2000-03-23 st/12:00 ed/2000-03-23 et/14:00
Expected: No event is added, since end date time is past. Detailed error message shown in the status bar. -
Other incorrect commands to try:
add_event
,add_event n/Meeting 1
, etc.
-
Deleting an event
-
Deleting an event
-
Prerequisites: List all events using the
list
command. At least one event in the list. -
Test case:
delete_event 1
Expected: First event is deleted from the list. Details of the deleted event shown in the status message. -
Test case:
delete_event 50
(50 is larger than the list size)
Expected: No event is deleted. Error messageThe event index provided is invalid.
shown in the status message. -
Test case:
delete_event -1
Expected: No event is deleted. Error messageIndex should be an integer greater then 0.
shown in the status message. -
Other incorrect delete commands to try:
delete_event
,delete_event x
,...
(where x is larger than the list size)
Expected: Similar to previous.
-
Editing an event
-
Editing an event
-
Prerequisites: There are events in the list.
-
Test case:
edit_event 1 t/
Expected: Clearing all the tags of the first event in the list. -
Test case:
edit_event 1 n/editedEventName
Expected: The name of the first event in the list is changed toeditedEventName
. -
Other incorrect commands to try:
edit_event
,edit_event n/editedEventName
, etc.
-
Listing all events
-
Listing all events
- Test case:
list_event
Expected: All the events currently present in the event list will be shown.
If the event list is currently empty, a messageThere is no event present!
will be shown. Otherwise, a messageListed all event(s).
will be shown.
- Test case:
Getting today’s events
-
Getting today’s events
- Test case:
today_event
Expected: All the events that happening on today will be shown.
A messageListed events happen on today
andx event(s) listed!
will be shown, wherex
is the number of events that happen on today.
- Test case:
Finding events by names
-
Finding events by names
- Test case:
find_event project meeting
Expected: All the events whose name contains any ofproject
ormeeting
in the event list will be shown.
A messagex event(s) listed!
will be shown, wherex
is the number of events that satisfies the condition.
- Test case:
Clearing expired events
-
Clearing expired events
- Test case:
clear_expired_event
Expected: Events with past end date time are cleared from the list.
Success messageExpired events (if any) have been cleared!
will always be shown in the status message, regardless of whether there is any expired event or not.
- Test case:
Finding schedule given a date
-
Finding uncompleted tasks that are due before or on the specified date and events with start date before or on the specified date and end date after or on specified date.
-
Prerequisites: List all tasks using
list_task
command and all events using thelist_event
command. - Test case:
find_schedule 2022-05-01
- Assuming task list only has one task and its deadline is at
2022-05-01
and event list only has one event and its start date is at2022-04-01
and end date is at2022-06-01
.
Excepted: Displays uncompleted tasks with deadline before or on2021-05-01
and events with start date before or on2021-05-01
and end date after or on2021-05-01
. “Displayed the required tasks and events.
1 task(s) listed!
1 event(s) listed!” appears in the status bar.
- Assuming task list only has one task and its deadline is at
- Other incorrect command to try:
find_schedule 2021-005-01
.
-
Finding free time slots
-
Finding free time slots
-
Test case:
free_time 2022-06-10
Expected: Displays a list of free time slots on 2021-06-10. Success messageFound free time slots on 2022-04-27:
will be shown if free time slots were found.-
If there are available free time slots, a list of free time slots will be displayed after the success message.
-
If there are no events happening on the day,
The entire day is free!
will be displayed after the success message. -
If no free time slots were found,
There is no free time in the day!
will be displayed.
-
-
Test case:
free_time 2021-02-29
Expected: Displays an error message for invalid date.
-
Getting a summary of SOChedule
-
Getting a summary of SOChedule
- Test case:
summary
Expected: Displays a summary for SOChedule. Success messageSummary:
, followed by detailed aboutTask
, and details aboutEvent
.
- Test case:
Clearing SOChedule
-
Clearing SOChedule
- Test case:
clear
Expected: All Tasks and Events in SOChedule are cleared.
Success messageSochedule has been cleared!
will always be shown in the status message, regardless of whether there is any Task or Event.
- Test case:
A7. Saving data
-
Dealing with missing/corrupted/missing data files
- SOChedule will re-initialise and provide an empty Task list and Event list.
A8. Effort
Creating SOChedule took considerable effort and required significant effort from all members. To achieve this, all members committed to meticulous planning, regular team meetings, effective communication and strong collaboration to ensure that SOChedule is delivered on time and in a satisfactory state.
Major Changes
The original code base, Address Book 3 (AB3), was an application that was based around contacts management. SOChedule, on the other hand, is an application that aims to help NUS School of Computing (SoC) students to effectively manage their tasks and events. As such, much changes had to be made to the original code base to ensure that the code is conducive for SOChedule.
-
Major components had to be rewritten or adapted to suit SOChedule’s needs. This includes
Model
,Logic
,UI
,Storage
, among other smaller components. This rewrite had to be completed prior to the development of additional features, and demanded significant time and effort similar to building the product from scratch. -
Beyond storing a single object type,
Person
in AB3, SOChedule is a major upgrade as it is able to handle two radically different object types, namelyTask
andEvent
. This significantly increased the complexity of our project as most of AB3 code are no longer applicable for use in SOChedule. This would mean that additional time was required to plan out the new objects and attributes thoroughly before implementation could begin. Furthermore, some attributes required addition validation checks beyond a simple presence and alphanumeric check. For instance, the date-related attributes inEvent
(i.e.START_DATE
andEND_DATE
) required more thoughtful consideration as there were more specific requirements required, such as past date checks. Such considerations could also have knock-on consequences on other attributes within the same class (date-related attributes could affect the checks for time-related attributes). This would naturally increase the level of complexity of this project.` -
Additional, non-trivial UI modifications had to be made as well. Beyond simple changes to the aesthetics, changes were made to how the UI functioned. Originally, AB3 only required one
ListView
to handle a singlePerson
class. As SOChedule contains 2 different classes, twoListView
were required, each coming with their own interface to underlying code. Additional thought was required to ensure smooth integration with backend code and smooth user experience.
Challenges
-
Due to the additional attributes, there were much more attribute handling and edge case considerations. As such, the planning phase was made much more complicated as there was a need for thorough consideration of the new classes and their corresponding attributes. Concurrently, we also had to make sure that the code we implemented adhered to well-known coding principles to ensure code quality. To solve this, we laid down the design requirements early on in the project and ensured that all members had a clear overview of each other’s work and responsibilities. Throughout development, regular team meetings were held to keep each other up to date on each other’s progress. With the open communication and frequent updates, we were able to help each other test and proofread. Should there be any deviation from the intended outcome, issues were quickly raised and squashed. Through this iterative process, SOChedule was refined.
-
Due to the increase in complexity over AB3, there were also challenges faced throughout implementation. Some challenges included requiring a thorough understanding of the existing code base and component interactions, being clear of the separation of concerns and the actual implementation of the new commands, while balancing this with the tight deadlines and other commitments. To solve this, we split the workload based on components, in order to ensure that every team member could be the local expert on a component, and by commands. With this setup, each team member was a jack of all trades, and master of one. This smoothened the development process greatly as there was a sense of ownership with each member’s commands, while also having the ability to seek clarification on any particular component.
Conclusion
Overall, while being undeniably tough and demanding, our group managed to unite and push through the challenges we faced incrementally. While the workload was relentless, the process was made much better and smoother through clear communications and careful planning. This made the development process much more enjoyable, and has definitely turned all of us into a better software developer in more ways than one.