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:
 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 interfacewith the same name as the Component.
- exposes its functionality using a concrete {Component Name}Managerclass (which implements the corresponding APIinterfacementioned 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 Logiccomponent.
- Listens for changes to Modeldata so that the UI can be updated with the modified data.
3.3 Logic component

API :
Logic.java
- 
Logicuses theSocheduleParserclass to parse the user command.
- This results in a Commandobject 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 CommandResultobject which is passed back to theUi.
- In addition, the CommandResultobject can also instruct theUito 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.

 Note: 
The lifeline for
 Note: 
The lifeline for DeleteTaskCommandParsershould 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 UserPrefobject that represents the user’s preferences.
- the Sochedule data.
There are two main packages in Model:
- the Taskpackage contains classes that represent a task.
- the  Eventpackage 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.

 Note: An (arguably) more OOP model can store a
 
Note: An (arguably) more OOP model can store a 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 UserPrefobjects 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.

 Note: 
Due to the size constraint and brevity, the argument
 Note: 
Due to the size constraint and brevity, the argument 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
 Note:
The implementation of the noteworthy ones will be listed in the next section.
Some implementations of features are omitted because their implementation is similar to that of other features.
 Note:
The implementation of the noteworthy ones will be listed in the next section.
Some implementations of features are omitted because their implementation is similar to that of other features.
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 DoneTaskCommandcan be found below, using the aforementioned as an example.

 Note: 
Due to the size constraint, the argument
 Note: 
Due to the size constraint, the argument 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.

 Note: 
Due to the size constraint, the argument
 Note: 
Due to the size constraint, the argument 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 theARGUMENTgiven.
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
 Note:
The implementation of the noteworthy ones will be listed in the next section.
Some implementations of features are omitted because their implementation is similar to that of other features.
 Note:
The implementation of the noteworthy ones will be listed in the next section.
Some implementations of features are omitted because their implementation is similar to that of other features.
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 11or 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.
 Note: 
These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.
 Note: 
These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.
- 
    Initial launch - 
        Download the jar file and copy into an empty folder 
- 
        For testing purposes, a sample sochedule.jsonis provided here. Place this file in a directory nameddata.datashould 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_taskcommand. 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_taskcommand. 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_taskcommand. 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_taskcommand. 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 todayandx task(s) listed!will be shown, wherexis 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 ofhomeworkorassignmentin the task list will be shown.
 A messagex task(s) listed!will be shown, wherexis 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_taskcommand. 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,completionanddeadline.
 
- 
        
Pinning a task
- 
    Pinning a task while all tasks are being shown - 
        Prerequisites: List all tasks using the list_taskcommand. 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_taskcommand. 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:00Expected: 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:00Expected: 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:00Expected: 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 listcommand. 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/editedEventNameExpected: 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 todayandx event(s) listed!will be shown, wherexis 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 ofprojectormeetingin the event list will be shown.
 A messagex event(s) listed!will be shown, wherexis 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_taskcommand and all events using thelist_eventcommand.
- Test case: find_schedule 2022-05-01
 - Assuming task list only has one task and its deadline is at 2022-05-01and event list only has one event and its start date is at2022-04-01and end date is at2022-06-01.
 Excepted: Displays uncompleted tasks with deadline before or on2021-05-01and events with start date before or on2021-05-01and 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, Personin AB3, SOChedule is a major upgrade as it is able to handle two radically different object types, namelyTaskandEvent. 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_DATEandEND_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 ListViewto handle a singlePersonclass. As SOChedule contains 2 different classes, twoListViewwere 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.