Overview
This document showcases my contributions in building desktop application Student Schedule Planner
for software engineering module CS2103T as a member of team T12-3 together with other 4 members.
Student Schedule Planner is a desktop task management application built specially for university students. Our application offers university students more convenience than other todo-list application through a series of features, such as multiple tagging for each tasks, customized task and tag management and so on. This application is built on top of original Address Book Level-4, which is around 6kLoC, written in JAVA OOP fashion. Currently our Student Schedule Planner has approximately 10kLoC.
Summary of contributions
-
Major enhancement: Major enhancement: Task management, which mainly involves two components: one is archive and another is category.
-
What it does: Archive command allows users to archive completed tasks. Archived tasks are stored in separate list, which can be viewed with command
listarchived
. The tags used on tasks can be managed by customizable categories by adding tags to relevant category. -
Justification: Archive is a necessary command for a task managing application, because users have the need to hide completed tasks, and review them in a separate list.
As for category, our application allows user to attach multiple tags to a task when adding the task. Category gives user further freedom and power to manage the tags according to their needs. Our user can create their own categories and add relevant tags into a category. -
Highlights: Both functions, especially category, required good planning of detailed implementation as well as deep understanding and prediction of user-experience. It required deep analysis of users' demand as well as sophisticated and sustainable design to decide how to let user organize the tags and what to use, and the implementation involved building a whole new set of structure and commands. This enhancement affects the future direction and feature design of schedule planner.
-
-
Code contributed: RepoSense
-
Other contributions:
-
Project management:
-
Enhancements to existing features:
-
Added sorting feature that allows tasks to always be displayed in the order of deadline date and priority.
-
Added automatic deletion feature that deletes archived tasks with deadline date earlier than 2 weeks before current date whenever application launches.
-
-
Documentation:
-
Community:
-
Tools:
-
Integrated Codacy to the team repo
-
-
Contributions to the User Guide
Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users. |
Archiving a Task
Archives the specified task from the schedule planner. Once a task is archived, it will be hidden from task list. You can
view archived tasks in archived task list using listarchived
command. For detailed guide regarding
viewing archived tasks, please refer to [Viewing Archived Tasks].
archive INDEX
Example:
archive 1
Task with index 1
is removed from the task list.
Below is the partial screenshots of task list before and after executing the archive command.
The INDEX
refers to the index number shown in the displayed task list. Refer to the task according to the index number.
The INDEX
must be a positive integer 1, 2, 3, …
INDEX
refers to the index of the task in the displayed task list. Refer to the task according to its index
number.
The INDEX
must be a positive integer(≥1)
Use the listarchived command to find out the index of the task to be archived.
View [Viewing Archived Tasks] for detailed guide.
|
Any archived tasks with deadline date earlier than 2 weeks before current date will be deleted from schedule planner when the application relaunches. |
Adding a Category
Add a new category to the schedule planner.
You can organize tags by adding tags to relevant categories. For detailed guide about
how to add tags to category, please refer to [Adding a Tag to a Category].
addcat c/CATEGORY
Example:
addcat c/Steam shopping list
Category name can contain space. For example, Steam
, Steam2
,
Steam shopping list
are all valid category names.
Modules
and Others
are two categories exist by default.
Please take note that category is case-sensitive. For example, category cats and category Cats are
considered different.
|
Duplicated categories are not allowed in schedule planner. All categories must have different names. |
All non-default categories (categories except Modules and Others can be removed.
For detailed guide about how to remove categories, please refer to Deleting a Category.
|
All non-default categories (categories except Modules and Others can be renamed.
For detailed guide about how to rename categories, please refer to Renaming a Category.
|
Clearing a Category
Clears all tags saved under selected category. After executing this command, the selected category will not contain any tags.
clearcat c/CATEGORY
Example:
clearcat c/Modules
When a category is cleared, tags saved in other categories are not affected.
For instance, in above example, if you have tag CS2105
in category Others
as well, after clearing category Modules
, tag CS2105
will still exist in category
Others
.
On the other hand, if tag CS2105
is only saved under category Modules
, then after clearing
category Modules
, the tag CS2105
will be removed from schedule planner.
Deleting a Category
Delete an existing category from schedule planner.
removecat c/CATEGORY
Example:
removecat c/Steam shopping list
Default categories Modules and Others cannot be removed. The only operation available for default categories is to delete
all tags saved under these two categories.
For more detailed guide about how to do so, please refer to Clearing a Category.
|
Renaming a Category
Edit the name of an existing category.
editcat c/ORIGINAL CATEGORY NAME c/NEW CATEGORY NAME
Example:
editcat c/Steam shopping list c/Reading list
Default categories Modules and Others cannot be renamed.
|
Duplicated categories are not allowed in schedule planner. Please make sure the new name for selected category does not overlap with other existing categories in your schedule planner. |
Viewing Tasks in the Order of Deadline Date and Priority
All tasks are automatically loaded in the order of deadlines except for archived tasks.
The order of tasks first depends on deadline date, then priority.
Given below is an example of two tasks with different deadline dates.
Task Do CS2030 lab
is listed before task Self study
because it has
earlier deadline date.
Sorting Tasks by Deadline Date and Priority
All tasks are sorted chronologically by default. The order of tasks first depends on deadline date, then priority.
Given below is an example of two tasks with different deadlines.
Task Do CS2030 lab
is listed before task Self study
because it has
earlier deadline.
If two tasks have the same deadline, then the order depends on priority, one that has
higher priority will appear before one that has lower priority. 3 is the highest priority, while 1 is the lowest.
Given below is an example of two tasks with the same deadline dates.
Please take note that archived tasks are not shown in order. |
Contributions to the Developer Guide
Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project. |
Managing Tags Using Category
The category feature enables users to organize their tags. Users can create category and
save relevant tags inside category. There are two default categories in schedule planner,
category Modules
and category Others
. These two default categories cannot be renamed or
deleted, but user have full freedom to rename or delete other categories added by themselves.
Current Implementation
Each category has a unique name, and contains a list of tags. The list of tags is implemented using UniqueTagList, which does not allow duplicates, in other words, tags with same name. Given below is a snippet of implementation of UniqueTagList:
public class UniqueTagList implements Iterable<Tag> { private boolean tagsAreUnique(List<Tag> tags) { //Checks if tags are unique... } }
Given below is a snippet of implementation of category:
public class Category { //Two attributes, name and tag list private String name; private UniqueTagList tags; ///Other implementation... }
Schedule Planner contains a list of cateogry list, implemented using UniqueCategoryList
.
UniqueCategoryList
is a list used to save categories which does not allow duplicates.
Any two categories with same name are considered identical. Given below is a snippet
its implementation:
public class UniqueCategoryList implements Iterable<Category> { public boolean contains(String name) { //Checks whether this category name has been used... } private boolean categoriesAreUnique(List<Category> categories) { //Checks whether there are duplicate categories... } //Other implementation... }
Given below is an example usage scenario and how the category mechanism behaves at each step:
Step 1. User enters command addcat c/Game list
to add a category named Game list
.
-
The
addcat
command is executed.AddCategoryCommand#execute()
callsModel#addCategory()
. -
Model#addCategory()
callsVersionedSchedulePlanner#addCategory()
. -
SchedulePlanner#addCategory()
then callsUniqueCategoryList#add()
. -
UniqueCategoryList#add()
checks if the existing category list contains any category with identical name as new category, if exists,DuplicateCategoryException()
is thrown; if not, new category is created and added to category list.
Given below is the sequence diagram of add category command which explains how the mechanism works:
When user is adding tasks using unspecified tags (tags that have never been added to any category),
the tags will be automatically added to default category Others
.
Step 2. User enters command addtag c/Game list t/Zelda
to add tag Zelda
into category Game list
.
-
The command string is first passed to
AddTagCommandParser
, which parses stringZelda
to tag (let us call ittagZelda
) and createsAddTag
command. -
The command is then executed.
AddTagCommand#execute()
callsModel#addTag()
and passestagZelda
and stringGame list
as parameter. -
Model#addTag()
callsVersionedSchedulePlanner#addTag()
, passes intagZelda
and stringGame list
as parameter. -
VersionedSchedulePlanner#addCategory()
then callsUniqueCategoryList#getCategory()
, passing in stringGame list
as parameter and obtains corresponding category (let us call itcategoryGameList
). -
Category#addTag()
is then called with parametercategoryGameList
to add tagtagZelda
to categorycategoryGameList
. If there already exists a tag namedZelda
in UniqueTagList of categorycategoryGameList
, exceptionDuplicateTagException
is thrown.
Given below is the sequence diagram of add tag command.
Step 3. User enters command editcat c/Game list c/Reading list
to rename category from Game list
to Reading list
.
-
EditCategoryCommandParser
createsEditCategoryCommand
. WhenEditCategoryCommand
executes, it callsModel#editCategory()
and passes in stringGame list
and stringReading list
as parameter. -
Model#editCategory()
callsVersionedSchedulePlanner#editCategory()
with parameter stringGame list
and stringReading list
. -
VersionedSchedulePlanner
then callsUniqueCategoryList#setCategory()
to obtain the category namedGame list
(let us call itcategoryGameList
) and create a new category with nameReading list
and same tag list as categorycategoryGameList
, replace categorycategoryGameList
with this new category. Below is a snippet of implementation ofUniqueCategoryList#setCategory()
used here:
public void setCategory(String originalName, String newName) { //... //Obtain the category with name "Game list" Category oldCategory = getCategory(originalName); //Creat a new category which is identical to original category except name Category newCategory = new Category(newName, oldCategory.getUniqueTagList()); internalList.set(internalList.indexOf(oldCategory), newCategory); }
Given below is the sequence diagram of edit category command:
-
Sequence Diagram of Edit Category Command
Step 4. User enters command removecat c/Reading list
to remove the category named Reading list
. Let us call this
category categoryReadingList
.
-
RemoveCategoryCommandParser
createsRemoveCategoryCommand
. -
When
RemoveCategoryCommand
executes, it callsModel#removeCategory()
and passes in stringReading list
as parameter. -
Model#removeCategory()
callsVersionedSchedulePlanner#removeCategory()
with parameter stringReading list
. -
VersionedSchedulePlanner
then callsUniqueCategoryList#removeCategory()
to obtain category namedReading list
(let us call itcategoryReadingList
) and remove it. -
After
categoryReadingList
is removed, its tag list is removed as well. For example, if user has added tagZelda
only in category namedReading list
, then after removing this category, tagZelda
will be lost from schedule planner.
Given below is the sequence diagram of remove category command:
Besides adding tag, renaming (editing) and removing, we support clearing category as well.
Clear category command clears the tags list of selected category.
Mechanism of clearing category is very similar to renaming (editing) category.
Model#clearCategory()
calls VersionedSchedulePlanner#clearCategory()
, which then initialize a new empty
category with name "Modules"
.
Below is a code snippet of VersionedSchedulePlanner#clearCategory()
:
public void clearCategory(String name) { //... this.categories.setCategory(name, new Category(name)); }
Below is a code snippet of #UniqueCategoryList#setCategory()` used here, which is slightly different from what is used in editing category:
public void setCategory(String originalName, Category newCategory) { //... Category oldCategory = getCategory(originalName); internalList.set(internalList.indexOf(oldCategory), newCategory); }
We omit the sequence diagram here because of its similarity to edit category command.
Design Consideration
Aspect: How to store and manage tags
-
Alternative 1 (current choice): Store Categories as
UniqueCategoryList
and allow users to add tags to categories. There will be noUniqueTagList
directly managed by schedule planner. All tags are saved under UniqueTagList under individual Category. Because our application is catered for university students, we set two default categories,Modules
andOthers
.-
Pros: We allow users more freedom to manipulate with their tags and categorize their tags. User can add one tag to several categories, and the tags saved under different categories do not interfere with each other. This is the most user-friendly design we can think of so far.
-
Cons: The implementation is more complicated than Alternative 2. Besides, this mechanism requires more commands to operate, which could be harder for user to remember.
-
-
Alternative 2: Store tags in
UniqueTagList
directly managed by schedule planner. The schedule planner has two tag lists, one isModules
and another one isOthers
.-
Pros: It is easy to implement, and the operation requires less commands.
-
Cons: User has less freedom in managing tags. This design is less user-friendly than Alternative 1.
-
Automatic Partial Deletion of Archived Tasks
The automatic deletion feature removes archived tasks with deadlines date earlier than 2 weeks ago from current time
point from archived task list. There are two main reasons behind this feature.
Firstly, we want to optimize the user experience of viewing archived tasks. Users should be able to view archived tasks,
but displaying all archived tasks would make the archived task list too bulky and hard to view. In other words, we want to stop the archived task
list from growing to infinity.
Another reason is we want to save storage space used by our application as much as possible.
Current Implementation
Every time when the application is launched, archived list is checked through. Tasks with deadline date earlier than 2 weeks ago are then permanently deleted from archived task list.
Given below is detailed explanation of how auto-deletion mechanism behaves:
-
Application is launched
-
MainApp#init()
is called, which instantiatesModel
class and callsModel#autoDeleteArchived()
. -
Model#autoDeleteArchived()
then callsTaskList#autoDelete()
. Note thatTaskList
is an object type implemented to store archived tasks.TaskList#autoDelete()
then scan through archived tasks and deletes those archived tasks with deadline date earlier than 2 weeks before current time point.
Design Considerations
Aspect: What tasks should we delete?
We had a rough idea of deleting away "old" tasks. However, how should we define "old"?
-
Alternative 1 (current choice): Delete tasks with deadline date earlier than 2 weeks before current date.
-
Pros: This implementation is easier for testing. Testers do not have to alternate their system time to test the feature.
-
Cons: The logic may be less user-friendly comparing to Alternative 2. A user’s expectation is more likely to be "I can check tasks that were archived recently". For example, if user has just archived a task that has been overdue for 1 month (the deadline date of this task is 1 month earlier than current date), he/she may find it not so intuitive if next time he/she runs the app, the task cannot be found in archived task list.
-
-
Alternative 2 : Delete tasks that were archived 2 weeks before current date.
-
Pros: This implementation may be more user-friendly comparing with Alternative 1.
-
Cons: The feature would be hard to test for testers.
-
Sort tasks
The sorting feature enables tasks to be displayed in the order of deadline date and priority. This feature applies to all tasks except archived tasks.
Current Implementation
Sorting feature does not require any user input command.
Whenever the tasks are listed, they are always listed according to deadline date, then priority. Our application offers
3 priority levels from 1 to 3, 3 is the highest priority and 1 is the lowest.
Assume there are two tasks in a task list, task A and task B. Given below is the scenario when
task list is retrieved from schedule planner using any kind of list
command and how the sorting mechanism
behanves.
-
UniqueTaskList#sorted()
is called andTask#compare()
is parsed in as comparator. -
Task#compare()
calls Date.compare(), which compares the deadline date of task A and task B.-
If task A has earlier deadline date than task B, the order will be task A followed by task B, and vice versa.
-
If task A and task B have the same deadline date,
Priority#compare()
is then called, which compares priority of task A and task B.-
If task A has higher priority than task B, the order will be task A followed by task B and vice versa.
-
If task A and task B have the same priority, then
Name#compare()
is called, which compares the task name of A and B according to JAVAcompareTo()
method ofString
class.
-
-
Given below is a sequence diagram of the sorting feature.
Design Considerations
Aspect: How should sorting be executed
-
Alternative 1 (current choice): Automatically sort tasks whenever tasks are listed. In other words, whenever tasks are shown on UI, they are sorted according to deadline and priority.
-
Pros: The user experience is better using this approach, because tasks are always listed in the order of deadline and priority. The code required is less than Alternative 2 as well.
-
Cons: The performance of the application may be affected if the task list size is significantly large, because the task list has to be traversed and sorted before displaying on UI. Of course considering actual use case, such performance issue should be negligible.
-
-
Alternative 2: Implement sort command exclusively for sorting tasks. For example, use command
sort tasks
to obtain sorted list of all tasks, andsort archived
for sorted list of archived tasks.-
Pros: We do not have to worry about performance issue.
-
Cons: Users have to type command
sort
every time, which is apparently not so user-friendly.
-