diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs index 4e0fc71ac89f..58b9567e0ca2 100644 --- a/.settings/org.eclipse.buildship.core.prefs +++ b/.settings/org.eclipse.buildship.core.prefs @@ -1,7 +1,6 @@ build.commands=org.eclipse.jdt.core.javabuilder connection.arguments= connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) -connection.gradle.user.home=null connection.java.home=null connection.jvm.arguments= connection.project.dir= diff --git a/.travis.yml b/.travis.yml index a9d9e9b47d87..0b2162e9ddff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: java matrix: include: - jdk: oraclejdk8 -script: travis_retry ./gradlew clean headless allTests coverage coveralls -i +script: travis_retry ./gradlew clean allTests coverage coveralls -i before_install: - "export DISPLAY=:99.0" - "sh -e /etc/init.d/xvfb start" diff --git a/README.md b/README.md index 249a00b3899c..c2454408dc58 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,17 @@ -[![Build Status](https://travis-ci.org/se-edu/addressbook-level4.svg?branch=master)](https://travis-ci.org/se-edu/addressbook-level4) -[![Coverage Status](https://coveralls.io/repos/github/se-edu/addressbook-level4/badge.svg?branch=master)](https://coveralls.io/github/se-edu/addressbook-level4?branch=master) +[![Build Status](https://travis-ci.org/CS2103AUG2016-W10-C3/main.svg?branch=master)](https://travis-ci.org/CS2103AUG2016-W10-C3/main) +[![Coverage Status](https://coveralls.io/repos/github/CS2103AUG2016-W10-C3/main/badge.svg)](https://coveralls.io/github/CS2103AUG2016-W10-C3/main) -# Address Book (Level 4) +# SmartyDo -
+
-* This is a desktop Address Book application. It has a GUI but most of the user interactions happen using +* This is a desktop time scheduler application. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface). -* It is a Java sample application intended for students learning Software Engineering while using Java as - the main programming language. -* It is **written in OOP fashion**. It provides a **reasonably well-written** code example that is - **significantly bigger** (around 6 KLoC)than what students usually write in beginner-level SE modules. -* What's different from [level 3](https://github.com/se-edu/addressbook-level3): - * A more sophisticated GUI that includes a list panel and an in-built Browser. - * More test cases, including automated GUI testing. - * Support for *Build Automation* using Gradle and for *Continuous Integration* using Travis CI. + #### Site Map * [User Guide](docs/UserGuide.md) * [Developer Guide](docs/DeveloperGuide.md) -* [Learning Outcomes](docs/LearningOutcomes.md) * [About Us](docs/AboutUs.md) * [Contact Us](docs/ContactUs.md) - - -#### Acknowledgements - -* Some parts of this sample application were inspired by the excellent - [Java FX tutorial](http://code.makery.ch/library/javafx-8-tutorial/) by *Marco Jakob*. - - -#### Licence : [MIT](LICENSE) diff --git a/SmartyDo.jar b/SmartyDo.jar new file mode 100644 index 000000000000..3d07c6db1fc0 Binary files /dev/null and b/SmartyDo.jar differ diff --git a/bash.exe.stackdump b/bash.exe.stackdump new file mode 100644 index 000000000000..1f94252ecbca --- /dev/null +++ b/bash.exe.stackdump @@ -0,0 +1,2 @@ +Stack trace: +Frame Function Args diff --git a/build.gradle b/build.gradle index 46b06c1e42ec..12a80917a184 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,6 @@ * For more details take a look at the Java Quickstart chapter in the Gradle * user guide available at http://gradle.org/docs/2.2.1/userguide/tutorial_java_projects.html */ - plugins { id "com.github.kt3k.coveralls" version "2.4.0" id "com.github.johnrengelman.shadow" version '1.2.3' @@ -27,6 +26,7 @@ allprojects { // This part is similar to global variables // Access them by using double-quoted strings (GStrings) and referencing by $ e.g. "Variable contains $Variable" + // Natty is used for Natural Language Date Parsing project.ext { controlsFxVersion = '8.40.11' guavaVersion = '19.0' @@ -61,7 +61,7 @@ allprojects { } testCompile "org.testfx:openjfx-monocle:$monocleVersion" } - + sourceSets { main { java { @@ -72,7 +72,7 @@ allprojects { } } } - + shadowJar { archiveName = "addressbook.jar" diff --git a/collated/Collate-TUI.jar b/collated/Collate-TUI.jar new file mode 100644 index 000000000000..50bdfe6902f8 Binary files /dev/null and b/collated/Collate-TUI.jar differ diff --git a/collated/RunCollate.cmd b/collated/RunCollate.cmd new file mode 100644 index 000000000000..ccd94634c9ff --- /dev/null +++ b/collated/RunCollate.cmd @@ -0,0 +1,13 @@ +:: Name: RunCollate.cmd +:: Purpose: Runs Collate! +:: Author: A0135812L Kenneth + +rmdir main /S /q +rmdir test /S /q +rmdir docs /S /q + +java -jar Collate-TUI.jar collate from ../src/main to main include java, fxml, css + +java -jar Collate-TUI.jar collate from ../src/test to test include java + +java -jar Collate-TUI.jar collate from ../docs to docs include md, html \ No newline at end of file diff --git a/collated/docs/A0121261Y.md b/collated/docs/A0121261Y.md new file mode 100644 index 000000000000..100883ef8a46 --- /dev/null +++ b/collated/docs/A0121261Y.md @@ -0,0 +1,52 @@ +# A0121261Y +###### \DeveloperGuide.md +``` md + +## 7.1 Appendix A : User Stories + +Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*` + + +Priority | As a ... | I want to ... | So that I can... +-------- | :-------- | :--------- | :----------- +`* * *` | new user | see usage instructions | refer to instructions when I forget how to use the App +`* * *` | user | add a task by specifying a task description only | record tasks that need to be done +`* * *` | user | delete a task | remove entries that I no longer need +`* * *` | user | find a task by name | locate details of tasks without having to go through the entire list +`* * *` | user |view list of completed and pending tasks | keep track of what needs to be done +`* *` | user with many tasks at a time | sort my tasks by different criteria | view tasks easily +`* *` | user with large projects/ tasks | add subtasks to main task | break down larger task into smaller tasks +`* *` | user with many uncofirmed events | allocate timeslots for tentative meetings/tasks | avoid having plans that might conflict with unconfirmed plans +`* *` | user | undo 1 previous operation | remove commands executed by accident +`* *` | user | specify a target folder as the data storage location | synchronise file with other applications +``` +###### \UserGuide.md +``` md +### 3.8. **Undoing and Redoing** + +With `undo`, you are allowed to reverse your previous changes sequentially while `redo` allows you to reverse the change done by `undo`.
+ +- `undo` command requires the application to have executed atleast one undoable command after launching. +- `redo` command requires the application to have executed atleast one succussful `undo` command after launching. + +Undoable Commands:`add`, `delete`, `edit`, `done` + +> SmartyDo **does not store** history of actions in your computer. +> Your history of actions resets when SmartyDo is launched. +> Also, if you enter any undoable command after entering `redo` or `undo`, your history of actions would be _**removed**_.
+ +Format: `undo`, `redo` + +**Example:**
+Let's say you have added a task and your friend told you that your tutor has changed the date. You would like to undo it. You can undo it as long as you just added it, as shown below. + +
Figure 9.1. Before(left) and after(right) of an undo command
+ +By entering `undo` command, SmartyDo updates your list of tasks to how it was before you executed an undoable action. From the screenshot above, you can see that the date of the task named "Presentation" had changed. + +However, you realized that your friend was wrong and you want to change the date back again. In this case, you do not need to use edit command again. Instead you can simply use `redo` command, as shown below. + +
Figure 9.2. Before(left) and after(right) of an undo command
+ +By using `redo` command, SmartyDo updates your list of tasks to how it was before you executed `undo` command. From the screenshot above, you can see that the "Presentation" task has been restored to its previous state. +``` diff --git a/collated/docs/A0126649W.md b/collated/docs/A0126649W.md new file mode 100644 index 000000000000..13e7745ab33d --- /dev/null +++ b/collated/docs/A0126649W.md @@ -0,0 +1,269 @@ +# A0126649W +###### \DeveloperGuide.md +``` md +## 7.2 Appendix B : Use Cases + +(For all use cases below, the **System** is the `SmartyDo` and the **Actor** is the `user`, unless specified otherwise) + +### Use case: Add task + +**MSS** + +1. User requests to add new task +2. SmartyDo shows list of upcoming tasks with new task added
+Use case ends. + +**Extensions** + +1a. The given index is invalid + +> Use case ends + +### Use case: Edit task + +**MSS** + +1. User requests to view upcoming tasks +2. SmartyDo shows a list of upcoming tasks +3. User requests to edit a specific task in the list +4. SmartyDo edits the task
+Use case ends. + +**Extensions** + +2a. The list is empty + +> Use case ends + +3a. The given index is invalid + +> 3a1. SmartyDo shows an error message
+ Use case resumes at step 2 + +### Use case: Undo task + +**MSS** + +1. User requests to undo the previous command +2. SmartyDo performs undo and shows updated list of upcoming tasks
+Use case ends. + +**Extensions** + +1a. There is no previous command + +> Use case ends + +### Use case: Redo task + +**MSS** + +1. User requests to redo the command reversed by the undo command +2. SmartyDo performs redo and shows updated list of upcoming tasks
+Use case ends. + +**Extensions** + +1a. There is no previous undo command + +> Use case ends + +### Use case: View task + +**MSS** + +1. User requests to view upcoming tasks that matches specific `string` +2. SmartyDo shows a list of upcoming tasks
+Use case ends. + +**Extensions** + +1a. The given `string` is invalid + +> Use case ends + +### Use case: Mark task + +**MSS** + +1. User requests to view upcoming tasks +2. SmartyDo shows a list of upcoming tasks +3. User requests to mark a specific task in the list +4. SmartyDo marks the task
+Use case ends. + +**Extensions** + +2a. The list is empty + +> Use case ends + +3a. The given index is invalid + +> 3a1. SmartyDo shows an error message
+ Use case resumes at step 2 + +### Use case: Delete task + +**MSS** + +1. User requests to view upcoming tasks +2. SmartyDo shows a list of upcoming tasks +3. User requests to delete a specific task in the list +4. SmartyDo deletes the task
+Use case ends. + +**Extensions** + +2a. The list is empty + +> Use case ends + +3a. The given index is invalid + +> 3a1. SmartyDo shows an error message
+ Use case resumes at step 2 + +### Use case: Locate task + +**MSS** + +1. User requests to view upcoming tasks +2. SmartyDo shows a list of upcoming tasks +3. User requests to locate a specific task in the list +4. SmartyDo shows location of the task
+Use case ends. + +**Extensions** + +2a. The list is empty + +> Use case ends + +3a. The given index is invalid + +> 3a1. SmartyDo shows an error message
+ Use case resumes at step 2 + +### Use case: Save file + +**MSS** + +1. User requests to save file to specific `file path` +2. SmartyDo saves to `file path`
+Use case ends. + +**Extensions** + +1a. The `file path` is invalid + +> Use case ends + +### Use case: Load file + +**MSS** + +1. User requests to load file from specific `file path` +2. SmartyDo loads from `file path`
+Use case ends. + +**Extensions** + +1a. The `file path` is invalid + +> Use case ends +``` +###### \UserGuide.md +``` md +## 3. Getting Started +In this section, you will be introduced to the various commands that you will need when using SmartyDo. These commands will be described to you in the format described below. + +**Command Format**
+Words in `lower case` are the command.
+Words in `upper case` are the parameters.
+Items in `square brackets` are optional.
+The order of parameters is flexible.
+ +### 3.1. **Requesting Help From SmartyDo** + +You can use the help command to gain access to this user guide should you need any help with the commands and their format. Should you enter an invalid command (e.g. `abcd`), information will be shown, when possible, to help correct your mistakes. You may also access this function through a keyboard shortcut.
+ +Format: `help` +Keyboard Shortcut: `Ctrl+F1` + +**Example:**
+If you wish to get help on using SmartyDo, you may enter `help` into the Command Bar. + +
Figure 2. SmartyDo's Help Command
+ +After entering the command, a new window will appear showing you a summary of all commands and keyboard shortcuts. +``` +###### \UserGuide.md +``` md +### 3.5. **Editing Task Details** + +You might want to edit details of a task for several reasons. For example, when deadline was extended you will need to update the SmartyDo for this change. Using `edit` command will solve this problem. + +Format: `edit INDEX PARAMETER_TYPE NEW_VALUE` + +PARAMETER_TYPE the type of the parameter we want to change and NEW_VALUE is the new value for that parameter.
+`edit` command edits the task at the specified INDEX. You can easily identify the INDEX of the task by looking at the Visual Box.
+If the task you want to edit is not shown in the Visual Box, you can use `view` or `find` command to find the required task.
+ +**Example:**
+Let's say you want to add deadline time for task named "Presentation". Then, you must first check the INDEX of that task. In this case, the INDEX of the task is 1. So to add deadline for this task, enter `edit 1 t; DEADLINE`. This will update the deadline of the task. A demonstration of this functionality shown below. + +
Figure 6. Before(left) and after(right) of an edit command
+ +### 3.6. **Deleting Tasks** + +Sometimes, you may also want to delete tasks due to unexpected circumstances. To help you to handle such problem, `delete` command can be used. `delete` command is simply deleting task from SmartyDo. + +Format: `delete INDEX` + +Similar to `edit` command, `delete` command also uses INDEX. INDEX can be found in Visual Box by using `view` command and `find` command. + +**Example:**
+If you want to delete specfic task, find the INDEX of that task. Let's say the INDEX is 1. Then, enter `delete 1` in the command bar. + +
Figure 7. Example of delete command
+ +After entering `delete` command, SmartyDo will delete the task specified by the INDEX and will show the updated list in the Visual Box. In the screenshot above, you can see that the "Presentation" task has been deleted from SmartyDo. + +### 3.7. **Marking Completed Tasks** + +Instead of deleting the task, you may want to mark the task as complete and store the details of the task in the SmartyDo. In this case, you can use `done` command. By using `done` command, you can easily identify the completed tasks from the list. + +Format: `done INDEX` + +Similar to `delete` command and `edit` command, INDEX is used in `done` command. + +**Example:**
+You have now completed the task named "Presentation" and now you want to mark this task as complete. To do this, you will need to check the INDEX of this task. In this case, INDEX of this task is 1. So, entering `done 1` will mark "User Guide" task as complete. + +
Figure 8. Example of done command
+ +After entering the `done` command, you are now able to identify the completed task easily from the list. +``` +###### \UserGuide.md +``` md +### 5.1. **Command Summary** +|**Command**|**Parameters**|**Format**| +|:---------:|:--------:|-------| +|Help || `help`| +|Save |FILEPATH.xml|`save FILEPATH.xml`| +|Load |FILEPATH.xml|`load FILEPATH.xml`| +|Add |TASK_NAME(n; required if TASK_NAME is not the first parameter), DATE_TIME,[LOCATION], [TAG] |`add n; TASK_NAME d; DATE START_TIME END_TIME t/ TAG a; LOCATION `| +|Edit |INDEX|`edit INDEX`| +|Delete |INDEX|`delete INDEX`| +|Done |INDEX|`done INDEX`| +|Undo ||`undo`| +|Redo ||`redo`| +|Select |INDEX|`select INDEX`| +|Find |KEYWORD, [MORE_KEYWORD]|`find KEYWORD [MORE_KEYWORD]`| +|View |PARAM|`view PARAM`| +|Locate |INDEX|`locate INDEX`| +|Clear ||`clear`| +|Exit ||`exit`| +Table 5. Command Summary +``` diff --git a/collated/docs/A0135767U.md b/collated/docs/A0135767U.md new file mode 100644 index 000000000000..0d24da5d413b --- /dev/null +++ b/collated/docs/A0135767U.md @@ -0,0 +1,97 @@ +# A0135767U +###### \DeveloperGuide.md +``` md +## 7.5 Appendix E : Product Survey + +| Existing Product | Pros | Cons | +| :---: | :---: | :---: | +| Google Calendar | Allows creation of task and events and reside them in the same view. Free to use. Synchronises with gmail account. Allows conversion of email invites into events | Does not have blockout slots | +| Sticky Notes | Free on Windows Store. Always open. Easy to bring up. Shows all items, always. Easy addition/editing/removal of tasks. Can store notes/weblinks. Can store handwritten notes. Supports basic text formatting. | No backup mechanism. Unable to change font. Manual sorting. Resets to default settings on restart. No “calendar view�. Takes up desktop space. Unable to minimise. Can be quite cluttered and messy| +| Todo.txt | Does not rely on network access to operate. Able to synchronise with cloud storage. Allows priority scheduling. Breaks difficult objectives into small steps to reach the goal. Records date of completion for tasks. Simple GUI and lightweight Application | No support for recurring tasks. No reminder for upcoming due dates | +``` +###### \UserGuide.md +``` md +### 3.2. **Choosing Your Save Location** + +You can choose where to save your data on your computer by using the `save` command. The save location will be referenced from the directory in which SmartyDo is stored. From this point, all data will be saved to the file you specified. + +Format: `save FILEPATH.xml` + +**Example:**
+If you wish to save your files to the filepath data/todolist.xml, you may enter `save data/todolist.xml` into the Command Bar. + +
Figure 3. SmartyDo's Save Command
+ +After entering the command, MessageBox will show you if your new save file has been successfully created. + +### 3.3. **Loading Save Files** +You can load different save files from your computer into SmartyDo by using the `load` command. The location from which your save file is retrieved will be referenced from the directory in which SmartyDo is stored. From this point, all data will be saved to the file you specified. + +Format: `load FILEPATH.xml` + +**Example:**
+If you wish to load a previously saved file stored in data/my_todo_list.xml, you may enter `load data/my_todo_list.xml` into the Command Bar. + +
Figure 4. SmartyDo's Load Command
+ +After entering the command, MessageBox will show you if the save file has been successfully loaded to SmartyDo. +``` +###### \UserGuide.md +``` md +### 3.9. **Selecting Specific Tasks** + +Select the task identified by the parameter. A full detailed description will appear in a pop up window. + +Format: `select PARAM` + +**Example:**
+Let's say you want to know detailed information about the third task in the Visual Box. All you need to do is enter `select 3` into command bar, just as shown below. + +
Figure 10. Example of select command
+ +After entering the command, Browser Panel will show a detailed description about task 3. + +### 3.10. **Finding Specific Tasks** + +If you want to find tasks that contain specific keyword in their name, you can use `find` command. `find` command is a command that will list all the tasks matching atleast one keyword. You can enter more than one keyword for `find` command. + +Format: `find KEYWORD [MORE_KEYWORDS]` + +
Figure 11. Example of find command
+ +> Beware that keywords are case sensitive and only the task's name is searched. However, the order of the keywords does not matter. e.g. `find cs2103 project` is same as `find project cs2103` + +### 3.11. **Filtering the Task List** + +You can filter the list of tasks that you are viewing on the Visual Box. + +Format: `view KEYWORD` where KEYWORD in this case are any of the following: ALL/OVERDUE/UPCOMING/COMPLETED/INCOMPLETE + +For example, after finding specific tasks, to return the Visual Box back to where it lists all the tasks, simply input `view ALL` just as shown below. + +
Figure 12. Example of view command
+ +### 3.12. **Locating a Destination** +You may search for destinations listed in the LOCATION parameter of your task by using the `locate` command. A separate window will appear showing the details of the location mentioned (if any) in your task. Each task can be referred to by the index displayed in front of its title. + +Format: `locate INDEX` + +**Example:**
+If you wish to search for the location of the task named Presentation which has the index of 3, you may enter `locate 3` into the Command Bar. + +
Figure 13. Example of locate command
+ +After entering the command, a new window will appear showing you the details of the task you requested. +``` +###### \UserGuide.md +``` md +### 5.2. **Keyboard Shortcuts** +|**Command**|**Shortcut**| +|:---:|:---:| +|help|`Ctrl+F1`| +|list all| `Ctrl+1`| +|list overdue| `Ctrl+2`| +|list upcoming| `Ctrl+3`| +|list completed| `Ctrl+4`| +|list incomplete| `Ctrl+5`| +``` diff --git a/collated/docs/A0135812L.md b/collated/docs/A0135812L.md new file mode 100644 index 000000000000..9f2e31ba63e0 --- /dev/null +++ b/collated/docs/A0135812L.md @@ -0,0 +1,345 @@ +# A0135812L +###### \DeveloperGuide.md +``` md +## 1. Introduction +Welcome to the developer guide for SmartyDo. This guide is meant to enable budding developers like yourself to better understand the implementation of our program. Through this guide, we hope that you will be able to learn not only about how SmartyDo is implemented, but about different parts of the application that you are able to improve yourself. +``` +###### \DeveloperGuide.md +``` md + +## 2. Setting up + +#### 2.1 Prerequisites +To ensure that you are able to run SmartyDo smoothly, do ensure that you have met the following prerequisites: + +1. Installed **JDK `1.8.0_60`** or later
+ + > This app may not work as intended with earlier versions of Java 8.
+ This app will not work with earlier versions of Java. + +2. Installed **Eclipse** IDE +3. Installed **e(fx)clipse** plugin for Eclipse (Follow the instructions given on + [this page](http://www.eclipse.org/efxclipse/install.html#for-the-ambitious)) +4. Installed **Buildship Gradle Integration** plugin from the Eclipse Marketplace + + +#### 2.2 Importing the project into Eclipse +To import the lastest version of this project into Eclipse, follow the instructions as given below: + +0. Fork this repo, and clone the fork to your computer +1. Open Eclipse (Note: Ensure you have installed the **e(fx)clipse** and **buildship** plugins as given + in the prerequisites above) +2. Click `File` > `Import` +3. Click `Gradle` > `Gradle Project` > `Next` > `Next` +4. Click `Browse`, then locate the project's directory +5. Click `Finish` + + > * If you are asked whether to 'keep' or 'overwrite' config files, choose to 'keep'. + > * Depending on your connection speed and server load, it can even take up to 30 minutes for the set up to finish + (This is because Gradle downloads library files from servers during the project set up process) + > * If Eclipse auto-changed any settings files during the import process, you can discard those changes. + +## 3. Design + +### 3.1 Architecture +The **_Architecture Diagram_** given above will explain to you the high-level design of the App. Below, we will give you a quick overview of each component. + +
Figure 1. Overview of Main + +`Main` has only one class called [`MainApp`](../src/main/java/seedu/address/MainApp.java). It is responsible for, +* At app launch: `Main` will initialize the components in the correct sequence, and connect them up with each other. +* At shut down: `Main` will shut down the components and invoke cleanup method where necessary. + +[**`Commons`**](#36-common-classes) represents a collection of classes used by multiple other components. +Two of those classes play important roles at the architecture level. +* `EventsCentre`: This class (written using [Google's Event Bus library](https://github.com/google/guava/wiki/EventBusExplained)) + is used by components to communicate with other components using events (i.e. a form of _Event Driven_ design) +* `LogsCenter`: Used by many classes to write log messages to the App's log file. + +The rest of the App consists four components. +* [**`UI`**](#ui-component): The UI of the App. +* [**`Logic`**](#logic-component): Executes commands given by the user. +* [**`Model`**](#model-component): Holds the data of the App in-memory. +* [**`Storage`**](#storage-component): Reads data from, and writes data to the hard disk. + + +Each of the four components will +* Define its _API_ in an `interface` with the same name as the Component. +* Expose its functionality using a `{Component Name}Manager` class. + +For example, the `Logic` component (see the class diagram given below) defines it's API in the `Logic.java` +interface and exposes its functionality using the `LogicManager.java` class.
+
Figure 2. Overview of Logic
+ +The _Sequence Diagram_ below will show you how the components interact for the scenario where the user issues the +command `delete 3`. + +
Figure 3. Sequence Diagram: Delete 1
+ +>Note how the `Model` simply raises a `ToDoChangedEvent` when the To-Do data are changed, + instead of asking the `Storage` to save the updates to the hard disk. + +The diagram below will show you how the `EventsCenter` reacts to that event, which eventually results in the updates +being saved to the hard disk and the status bar of the UI being updated to reflect the 'Last Updated' time.
+
Figure 4. Sequence Diagram: ToDoEventChange
+ +> Note how the event is propagated through the `EventsCenter` to the `Storage` and `UI` without `Model` having + to be coupled to either of them. This is an example of how this Event Driven approach helps us reduce direct + coupling between components. + +The follwing sections will give you more details about each component. + +### 3.2 UI component + +The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `TaskListPanel`, +`StatusBarFooter`, `BrowserPanel` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class +and they can be loaded using the `UiPartLoader`. + +
Figure 5. Overview of UI
+ +**API** : [`Ui.java`](../src/main/java/seedu/address/ui/Ui.java) + +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`](../src/main/java/seedu/address/ui/MainWindow.java) is specified in + [`MainWindow.fxml`](../src/main/resources/view/MainWindow.fxml) + +The `UI` component will +* Execute user commands using the `Logic` component. +* Bind itself to some data in the `Model` so that the UI can auto-update when data in the `Model` change. +* Respond to events raised from various parts of the App and updates the UI accordingly. + +### 3.3 Logic component +Logic is in charge of reading user input and executing the correct commands. It is also in charge of give the user feedback on their input. + +
Figure 6. Overview of Logic
+ +**API** : [`Logic.java`](../src/main/java/seedu/address/logic/Logic.java) + +1. `Logic` uses the `Parser` class to parse the user command. +2. This results in a `Command` object which is executed by the `LogicManager`. +3. The command execution can affect the `Model` (e.g. adding a task) and/or raise events. +4. The result of the command execution is encapsulated as a `CommandResult` object which is passed back to the `Ui`. +5. `Logic` loads the `undo/redo Manager` which is initially an empty stack. If the command that is recently executed successfully belongs to a undoable command, the undo/redo manager will record it. + +Below, you will find the Sequence Diagram for interactions within the `Logic` component for the `execute("delete 1")` + API call.
+
Figure 7. Sequence Diagram: Delete in Logic
+ +### 3.4 Model component +Model is in charge of the structure of the to-do list, and serves as the manager of the abstraction layer between Logic and the actual list of tasks. + +
Figure 8. Overview of Model
+ +**API** : [`Model.java`](../src/main/java/seedu/address/model/Model.java) + +The `Model`, +* stores a `UserPref` object that represents the user's preferences. +* stores the To-Do data. +* exposes a `UnmodifiableObservableList` 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. + +### 3.5 Storage component +Storage is in charge of saving and retrieving data from files stored on the user’s device. + +
Figure 9. Overview of Storage
+ +**API** : [`Storage.java`](../src/main/java/seedu/address/storage/Storage.java) + +The `Storage` component, +* can save `UserPref` objects in json format and read it back. +* can save the SmartyDo data in xml format and read it back. + +### 3.6 Common classes + +You may find classes used by multiple components are in the `seedu.addressbook.commons` package. + +## 4. Implementation + +### 4.1 Logging + +We are using `java.util.logging` package for logging. You can use `LogsCenter` class to manage the logging levels +and logging destinations. + +* You can control the logging level by using the `logLevel` setting in the configuration file + (See [Configuration](#configuration)) +* You can obtain the `Logger` for a class by using `LogsCenter.getLogger(Class)` which will log messages according to + the specified logging level +* Currently log messages are output through: `Console` and to a `.log` file. + +**Logging Levels** +|Level|Details| +|---|---| +| `SEVERE` | Critical problem detected which may possibly cause the termination of the application. +| `WARNING` | Can continue, but with caution. +| `INFO` | Information showing the noteworthy actions by the App. +| `FINE` | Details that are not usually noteworthy but may be useful in debugging e.g. printout of the actual list instead of just its size + +### 4.2 Configuration + +You can control certain properties of the application (e.g App name, logging level) through the configuration file +(default: `config.json`): + + +## 5. Testing + +You can find tests in the `./src/test/java` folder. + +**In Eclipse**: +> If you are not using a recent Eclipse version (i.e. _Neon_ or later), you will need to enable assertions in JUnit tests + as described [here](http://stackoverflow.com/questions/2522897/eclipse-junit-ea-vm-option). + +* You can run all tests by right-clicking on the `src/test/java` folder and choose + `Run as` > `JUnit Test` +* You can also run a subset of tests by right-clicking on a test package, test class, or a test and choose + to run as a JUnit test. + +**Using Gradle**: +* You may refer to [UsingGradle.md](UsingGradle.md) to see how to run tests using Gradle. + +We have two types of tests: + +1. **GUI Tests** - These are _System Tests_ that test the entire App by simulating user actions on the GUI. + These are in the `guitests` package. + +2. **Non-GUI Tests** - These are tests not involving the GUI. They include, + 1. _Unit tests_ targeting the lowest level methods/classes.
+ e.g. `seedu.address.commons.UrlUtilTest` + 2. _Integration tests_ that are checking the integration of multiple code units + (those code units are assumed to be working).
+ e.g. `seedu.address.storage.StorageManagerTest` + 3. _Hybrids of unit and integration tests._ These test are checking multiple code units as well as + how they are connected together.
+ e.g. `seedu.address.logic.LogicManagerTest` + +**Headless GUI Testing** : +Thanks to the [TestFX](https://github.com/TestFX/TestFX) library we use, + our GUI tests can be run in the _headless_ mode. + In the headless mode, GUI tests do not show up on the screen. + That means the developer can do other things on the Computer while the tests are running.
+ See [UsingGradle.md](UsingGradle.md#running-tests) to learn how to run tests in headless mode. + +## 6. Dev Ops + +### 6.1 Build Automation + +You may read [UsingGradle.md](UsingGradle.md) to learn how to use Gradle for build automation. + +### 6.2 Continuous Integration + +We use [Travis CI](https://travis-ci.org/) to perform _Continuous Integration_ on our projects. +You may read [UsingTravis.md](UsingTravis.md) for more details. + +### 6.3 Making a Release + +Here are the steps to create a new release. + + 1. Generate a JAR file [using Gradle](UsingGradle.md#creating-the-jar-file). + 2. Tag the repo with the version number. e.g. `v0.1` + 2. [Create a new release using GitHub](https://help.github.com/articles/creating-releases/) + and upload the JAR file your created. + +### 6.4 Managing Dependencies + +A project often depends on third-party libraries. For example, SmartyDo depends on the +[Jackson library](http://wiki.fasterxml.com/JacksonHome) for XML parsing. Managing these _dependencies_ +can be automated using Gradle. For example, Gradle can download the dependencies automatically, which +is better than these alternatives.
+a. Include those libraries in the repo (this bloats the repo size)
+b. Require developers to download those libraries manually (this creates extra work for developers)
+ + +## 7. Appendix +``` +###### \DeveloperGuide.md +``` md +## 7.3 Appendix C : Non Functional Requirements + +1. Should work on any [mainstream OS](#mainstream-os) as long as it has Java `1.8.0_60` or higher installed. +2. Should be able to hold up to 2 years of entries estimated to be 8000 entries. +3. Should come with automated unit tests and open source code. +4. Should favor DOS style commands over Unix-style commands. + +``` +###### \UserGuide.md +``` md +## 1. Introduction +SmartyDo is a **to-do-list** application. With SmartyDo, forgetting upcoming deadlines and sleepless nights over incomplete tasks are a thing of the past. SmartyDo **increases your efficiency** by showing the lists of tasks that can be completed simultaneously. Treat SmartyDo like your personal assistant and just focus on **completing your tasks**! + +## 2. Quick Start +**Launch SmartyDo**: Simply double-click on the `SmartyDo.jar` file to start SmartyDo. You will be greeted with a simple interface that has three components: a **Visual Box**, a **Message Box** and a **Command Bar**. + +
Figure 1. Welcome Screen
+ +**Command Bar** is where you enter short commands to tell SmartyDo what to do.
+**Visual Box** is where you can see a comprehensive list of your tasks.
+**Message Box** shows the result of your command.
+``` +###### \UserGuide.md +``` md +### 3.4. **Adding Tasks Into SmartyDo** + +You can add a task into SmartyDo by using the add command. There are number of parameters that you can use to add more details to the task. Below is a summary of the various parameters and their usage:
+ +Here is the summary of the parameters and their usage: + +| Parameter | Flag | Format Requirements | Optional | +| ------------- |:-------------:| -----:|:---:| +| `TASK_NAME` | | _**n;**_ required if `TASK_NAME` is not the first parameter | No | +| `DATE_TIME` | **t;** | [Date] [Start_Time] [End_Time] , delimited by spaces | Yes | +| `TAG` | _**t/**_ | alphanumeric | Yes | +| `LOCATION` | _**a;**_ | alphanumeric | Yes | +| `DESCRIPTION` | _**d;**_ | alphanumeric | Yes | +Table 3.2. Add Command Parameters + +- `TASK_NAME` is the name of the task and this parameter is compulsary. +- `Date` is the date of the task supports date format of +dd/mmm/yyyy eg:20-Jan-2017 and dd/mm/yyyy with `/` interchangleable with `.` and `-` eg: 20-01-2017. +- `START_TIME` and `END_TIME` is the starting time and ending time of the task respectively. You may consider to use these parameters when starting time and/or deadline is known. You may omit the details of 'DATE_TIME' which will result in a task that has no time frame. +- `TAG` is the characteristic you can add to the task. Such tags can be "Urgent", "HighPriority" and etc. +- `LOCATION` is the place of task being done. You can use this parameter to remind you where to go to complete the task. +- 'DESCRIPTION' is where you can include some extra information about your task. + +Format : `add TASK_NAME [t; DATE START_TIME] [a;LOCATION] [t/TAG] [d;` + +> You don't have to enter the optional parameters when you don't need them. The order of the parameters are not fixed. You can enter the parameters in any order. For example, `add t/[TAG] t; DATE START_TIME ` is also correct format. + +**Example:**
+Let's say you want to add task named "Presentation" which is scheduled for 18 July 2016, 9:00AM. All you need to do is enter the following as shown below. + +
Figure 5. Example of add command
+ +After entering the command, MessageBox will show you task is successfully added into SmartyDo and you will see the updated list of task in the Visual Box. +``` +###### \UserGuide.md +``` md +### 3.13. **Clearing Saved Data** +You may clear all data stored in SmartyDo by using the `clear` command. SmartyDo will prompt you to confirm this action. Enter `yes` to complete the command. Entering a different command will cancel the `clear` command. + +Format: `clear` + +**Example**
+If you wish to clear all data in SmartyDo, you many enter `clear` into the CommandBox. + +
Figure 14. Example of locate command
+ +After entering the command, a prompt will appear in the MessageBox asking you to confirm this action. Enter `yes` to proceed. + +### 3.14. **Exiting SmartyDo** + +After using SmartyDo, you can exit the program by using `exit` command. + +Format: `exit` + +By entering `exit` command in the command box, SmartyDo will quit and save the data. + +## 4. Smart Features + +### 4.1. **FlexiCommand** +It is okay if you cannot remember the syntax entirely! As long as you remember the keyword some reshuffling of the parameters entered is fine. Our program will ask you for confirmation if we are unsure what you want. + +### 4.2. **Saving the Data** +SmartyDo will automatically save your data in the hard disk after any command that changes the data. There is no need to save manually. + +``` diff --git a/collated/main/A0121261Y.md b/collated/main/A0121261Y.md new file mode 100644 index 000000000000..3323da24c5a2 --- /dev/null +++ b/collated/main/A0121261Y.md @@ -0,0 +1,1001 @@ +# A0121261Y +###### \java\seedu\address\logic\commands\AddCommand.java +``` java +/** + * Adds a task to the SmartyDo. + */ +public class AddCommand extends Command implements Undoable { + + public static final String COMMAND_WORD = "add"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a task to the SmartyDo. " + + "Parameters: NAME t;DATE et;TIME d;DESCRIPTION a;LOCATION [tag;TAG]...\n" + + "Example: " + COMMAND_WORD + + " CS2103 t;10-12-2016 10:00AM 11:00AM d;description a;Nus Computing t/sadLife"; + + public static final String MESSAGE_SUCCESS = "New task added: %1$s"; + public static final String MESSAGE_DUPLICATE_TASK = "This task already exists in the SmartyDo"; + + private final Task toAdd; + private boolean isExecutedBefore; + + /** + * Convenience constructor using raw values. + * + * @throws IllegalValueException if any of the raw values are invalid + */ + + public AddCommand(String name, String time, String description, String address, Set tags) + throws IllegalValueException { + Time addTime; + final Set tagSet = new HashSet<>(); + for (String tagName : tags) { + tagSet.add(new Tag(tagName)); + } + + if (time!=null) + addTime = new Time(time); + else + addTime = null; + + this.toAdd = new Task( + new Name(name), + Optional.ofNullable(addTime), + new Description(description), + new Location(address), + new UniqueTagList(tagSet) + ); + isExecutedBefore = false; + } + + /** + * Task with time only + */ + public AddCommand(String name, String date, String startTime, String description, String address, Set tags) + throws IllegalValueException { + assert !CollectionUtil.isAnyNull(date, startTime); + final Set tagSet = new HashSet<>(); + for (String tagName : tags) { + tagSet.add(new Tag(tagName)); + } + + Time addTime = new Time(date, startTime); + this.toAdd = new Task( + new Name(name), + Optional.of(addTime), + new Description(description), + new Location(address), + new UniqueTagList(tagSet) + ); + isExecutedBefore = false; + } + + /** + * rangeTask + */ + public AddCommand(String name, String date, String startTime, String endTime, String description, String address, Set tags) + throws IllegalValueException { + final Set tagSet = new HashSet<>(); + assert !CollectionUtil.isAnyNull(date, startTime, endTime); + for (String tagName : tags) { + tagSet.add(new Tag(tagName)); + } + Time addTime = new Time(date, startTime, endTime); + this.toAdd = new Task( + new Name(name), + Optional.of(addTime), + new Description(description), + new Location(address), + new UniqueTagList(tagSet) + ); + isExecutedBefore = false; + } + + /** + * Events + */ + public AddCommand(String name, String startDate, String startTime, String endDate, String endTime, String description, String address, Set tags) + throws IllegalValueException { + final Set tagSet = new HashSet<>(); + assert !CollectionUtil.isAnyNull(startDate, startTime, endDate, endTime); + for (String tagName : tags) { + tagSet.add(new Tag(tagName)); + } + Time addTime = new Time(startDate, startTime, endDate, endTime); + this.toAdd = new Task( + new Name(name), + Optional.of(addTime), + new Description(description), + new Location(address), + new UniqueTagList(tagSet) + ); + isExecutedBefore = false; + } + @Override + public CommandResult execute() { + assert model != null; + assert undoRedoManager != null; + + try { + model.addTask(toAdd); + isExecutedBefore = pushCmdToUndo(isExecutedBefore); + return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd)); + } catch (UniqueTaskList.DuplicateTaskException e) { + indicateAttemptToExecuteIncorrectCommand(); + return new CommandResult(MESSAGE_DUPLICATE_TASK); + } + + } + + @Override + public CommandResult unexecute() { + int toRemove; + + assert model != null; + assert undoRedoManager != null; + + toRemove = model.getToDo().getTaskList().indexOf(toAdd); + UnmodifiableObservableList lastShownList = model.getFilteredTaskList(); + ReadOnlyTask taskToDelete = lastShownList.get(toRemove); + + try { + model.deleteTask(taskToDelete); + } catch (TaskNotFoundException pnfe) { + assert false : "The target task cannot be missing"; + } + + return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd)); + } + + @Override + public boolean pushCmdToUndo(boolean isExecuted) { + if (!isExecuted){ + undoRedoManager.addToUndo(this); + } + return true; + } +} +``` +###### \java\seedu\address\logic\commands\DoneCommand.java +``` java +/** + * Toggles the Task status from incomplete to complete and vice-versa + * + */ +public class DoneCommand extends Command implements Undoable { + + public static final String COMMAND_WORD = "done"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Changes the status of the selected task between completed and incomplete.\n" + + "Parameters: INDEX (must be a positive integer)\n" + + "Example: " + COMMAND_WORD + " 1"; + + public static final String MESSAGE_DONE_TASK_SUCCESS = "Task %1s status has been changed to %1s."; + + public final int targetIndex; + private boolean isExecutedBefore; + private ReadOnlyTask taskToMark; + + public DoneCommand(int targetIndex) { + this.targetIndex = targetIndex; + isExecutedBefore = false; + } + + @Override + public CommandResult execute() { + + UnmodifiableObservableList lastShownList = model.getFilteredTaskList(); + if (lastShownList.size() < targetIndex) { + indicateAttemptToExecuteIncorrectCommand(); + return new CommandResult(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX); + } + taskToMark = lastShownList.get(targetIndex - 1); + try { + model.markTask(taskToMark); + } catch (TaskNotFoundException tnfe) { + assert false : "The target cannot be missing."; + } + isExecutedBefore = pushCmdToUndo(isExecutedBefore); + return new CommandResult(String.format(MESSAGE_DONE_TASK_SUCCESS, taskToMark.getName(), + taskToMark.getCompleted() ? "Completed" : "Incomplete")); + } + + @Override + public CommandResult unexecute() { + assert model != null; + assert undoRedoManager != null; + + try { + model.markTask(taskToMark); + } catch (TaskNotFoundException tnfe) { + assert false : "The target cannot be missing."; + } + return new CommandResult(String.format(MESSAGE_DONE_TASK_SUCCESS, taskToMark.getName(), + taskToMark.getCompleted() ? "Completed" : "Incomplete")); + } + + @Override + public boolean pushCmdToUndo(boolean isExecuted) { + if (!isExecuted){ + undoRedoManager.addToUndo(this); + } + return true; + } + +} +``` +###### \java\seedu\address\logic\commands\EditCommand.java +``` java + /** + * Updates the task back to its original form by deleting the edited task + * and restoring the original state. + */ + public CommandResult unexecute() { + int toRemove; + toRemove = model.getToDo().getTaskList().indexOf(editedTask); + UnmodifiableObservableList lastShownList = model.getFilteredTaskList(); + ReadOnlyTask taskToDelete = lastShownList.get(toRemove); + + try { + model.deleteTask(taskToDelete); + model.addTask((Task) taskToEdit); + } catch (TaskNotFoundException pnfe) { + assert false : "The target task cannot be missing"; + } catch (UniqueTaskList.DuplicateTaskException e) { + assert false: "impossible for task to be missing"; + } + return new CommandResult(String.format(MESSAGE_SUCCESS, editedTask)); + } + + @Override + public boolean pushCmdToUndo(boolean isExecuted) { + if (!isExecuted) { + undoRedoManager.addToUndo(this); + } + return true; + } +``` +###### \java\seedu\address\logic\commands\RedoCommand.java +``` java +/** + * Reverse a undo command + * + */ +public class RedoCommand extends Command { + + public static final String COMMAND_WORD = "redo"; + + public static final String MESSAGE_SUCCESS = "Reversed your undo action successfully: "; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Reverses your last undo " + + "action executed in SmartyDo. \n" + + "Example: " + "add " + + "CS2103 t;10-12-16 d;finish the project a;COM1-1-1 t/friends t/owesMoney \n" + + "undo \n" + COMMAND_WORD; + + public static final String MESSAGE_NO_UNDO_COMMAND = "There was no undo command executed recently. "; + + Command lastCommand; + + public RedoCommand() {} + + @Override + public CommandResult execute() { + String lastUndoMessage; + assert model != null; + assert undoRedoManager != null; + + try { + lastCommand = undoRedoManager.getRedo().pop(); + assert lastCommand instanceof Undoable; + undoRedoManager.transferToUndo(lastCommand); + lastUndoMessage = lastCommand.execute().feedbackToUser; + return new CommandResult(MESSAGE_SUCCESS + System.lineSeparator() + lastUndoMessage); + }catch (EmptyStackException ese) { + return new CommandResult(MESSAGE_NO_UNDO_COMMAND + System.lineSeparator() + MESSAGE_USAGE); + } + } +} +``` +###### \java\seedu\address\logic\commands\Undoable.java +``` java +public interface Undoable { + + public CommandResult unexecute(); + + /** + * Push command to undo stack if not executed before. + * @param undoable command has not been executed + * successfully before. + * @return true + */ + public boolean pushCmdToUndo(boolean isExecuted); +} +``` +###### \java\seedu\address\logic\commands\UndoCommand.java +``` java +/* + * Undo a undoable command recently executed. + */ +public class UndoCommand extends Command { + + public static final String COMMAND_WORD = "undo"; + + public static final String MESSAGE_SUCCESS = "Undone your previous action successfully: "; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Reverse your last undoable " + + "action executed in SmartyDo. \n" + + "Example: " + "add " + + "John Doe t/9876 d/johnd's description a/311, Clementi Ave 2, #02-25 t/friends t/owesMoney \n" + + COMMAND_WORD; + + + public static final String MESSAGE_NO_UNDOABLE_COMMAND = "There was no undoable command executed recently. \n" + + MESSAGE_USAGE; + + public UndoCommand() {} + + @Override + public CommandResult execute() { + String lastUndoableMessage; + Command lastCommand; + + assert model != null; + assert undoRedoManager != null; + + try { + lastCommand = undoRedoManager.getUndo().pop(); + assert lastCommand instanceof Undoable; + undoRedoManager.transferToRedo(lastCommand); + lastUndoableMessage = ((Undoable) lastCommand).unexecute().feedbackToUser; + return new CommandResult(MESSAGE_SUCCESS + System.lineSeparator() + lastUndoableMessage); + }catch (EmptyStackException ese) { + return new CommandResult(MESSAGE_NO_UNDOABLE_COMMAND); + } + } +} +``` +###### \java\seedu\address\logic\parser\Parser.java +``` java + /** + * Regex validation for time format duplicated from Time class. + * + */ + public static final String TIME_VALIDATION_FORMAT = "((1[012]|0?[1-9])[:.]?[0-5][0-9]([aApP][mM]))|" + + "(([01]\\d|2[0-3])[:.]?([0-5]\\d))"; + + /** + * Regex validation for date format duplicated from Time class. + * + */ + public static final String DATE_VALIDATION_FORMAT = "(?:(?:31(\\/|-|\\.)(?:0?[13578]|1[02]|" + + "(?:JAN|MAR|MAY|JUL|AUG|OCT|DEC)))\\1|(?:(?:29|30)(\\/|-|\\.)(?:0?[1,3-9]|1[0-2]|" + + "(?:JAN|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$|^" + + "(?:29(\\/|-|\\.)(?:0?2|(?:Feb))\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|" + + "(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\\d|2[0-8])(\\/|-|\\.)(?:(?:0?[1-9]|" + + "(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP))|(?:1[0-2]|(?:OCT|NOV|DEC)))" + + "\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})"; + + public static final String DATE_TIME_VALIDATION_FORMAT = DATE_VALIDATION_FORMAT + +"(\\s("+TIME_VALIDATION_FORMAT+")(\\s("+TIME_VALIDATION_FORMAT+"))?)?"; + + public static final String MESSAGE_DATE_TIME_CONSTRAINTS = "Task Dates and Time should be in valid UK-format " + + "Date [Optional]Time [Optional]Time \n" + + "DD/MMM/YYYY or DD/MM/YYYY or DD.MM.YYYY or DD.MMM.YYY or DD-MM-YYYY or DD-MMM-YYYY \n" + + "12Hour format with AM/PM required or 24Hour format without AM/PM \n" + + "eg: 10-12-2012 09:00AM 11:59PM"; + + enum TaskType {UNTIMED, DEADLINE, TIMERANGE, EVENT} + + public static final int TASK_DATE_ONLY = 0; + public static final int TASK_START_TIME = 1; + public static final int TASK_END_TIME = 2; + public static final int EVENT_END_DATE = 2; + public static final int EVENT_END_TIME = 3; +``` +###### \java\seedu\address\logic\parser\Parser.java +``` java + /** + * Parses arguments in the context of the add task command. + * + * case 0: no date and time , i.e no args for time found + * case 1: date only + * case 2: date and startTime + * case 3: date and startTime endTime + * + * @param args full command args string + * @return the prepared command + */ + private Command prepareAdd(String args){ + String[] dateTimeArgs = null; + TaskType taskType; + + ArgumentTokenizer argsTokenizer = new ArgumentTokenizer(namePrefix, datePrefix, descriptionPrefix, + locationPrefix, tagsPrefix); + argsTokenizer.tokenize(args); + + try { + Optional taskName = getTaskNameFromArgs(argsTokenizer); + if (!taskName.isPresent()) { + return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); + } + Optional validateDateTimeArgs = argsTokenizer.getValue(datePrefix); + if(validateDateTimeArgs.isPresent()) { + dateTimeArgs = prepareAddTimeArgs(validateDateTimeArgs.get().toUpperCase()); + if(!isValidDateTimeFormat(dateTimeArgs)) + throw new IllegalValueException(MESSAGE_DATE_TIME_CONSTRAINTS); + + taskType = TaskType.values()[(dateTimeArgs.length-1)]; + }else { + taskType = TaskType.values()[TASK_DATE_ONLY]; + } + + switch (taskType) { + case UNTIMED: + return new AddCommand( + taskName.get(), + validateDateTimeArgs.isPresent() ? dateTimeArgs[TASK_DATE_ONLY] : null, + getPrefixValueElseBlank(argsTokenizer,descriptionPrefix), + getPrefixValueElseBlank(argsTokenizer,locationPrefix), + toSet(argsTokenizer.getAllValues(tagsPrefix)) + ); + case DEADLINE: + assert dateTimeArgs != null; + return new AddCommand( + taskName.get(), + dateTimeArgs[TASK_DATE_ONLY], dateTimeArgs[TASK_START_TIME], + getPrefixValueElseBlank(argsTokenizer,descriptionPrefix), + getPrefixValueElseBlank(argsTokenizer,locationPrefix), + toSet(argsTokenizer.getAllValues(tagsPrefix)) + ); + case TIMERANGE: + assert dateTimeArgs != null; + return new AddCommand( + taskName.get(), + dateTimeArgs[TASK_DATE_ONLY], dateTimeArgs[TASK_START_TIME], + dateTimeArgs[TASK_END_TIME], + getPrefixValueElseBlank(argsTokenizer,descriptionPrefix), + getPrefixValueElseBlank(argsTokenizer,locationPrefix), + toSet(argsTokenizer.getAllValues(tagsPrefix)) + ); + case EVENT: + assert dateTimeArgs != null; + return new AddCommand( + taskName.get(), + dateTimeArgs[TASK_DATE_ONLY], dateTimeArgs[TASK_START_TIME], + dateTimeArgs[EVENT_END_DATE], dateTimeArgs[EVENT_END_TIME], + getPrefixValueElseBlank(argsTokenizer,descriptionPrefix), + getPrefixValueElseBlank(argsTokenizer,locationPrefix), + toSet(argsTokenizer.getAllValues(tagsPrefix)) + ); + default: + assert false: "Not suppose to happen."; + } + + } catch (IllegalValueException ive) { + return new IncorrectCommand(ive.getMessage()); + } + return null; + } + + private boolean isValidDateTimeFormat(String[] dateTimeArgs) { + int args = dateTimeArgs.length-1; // adjust for Array and eNum count from 0. + TaskType taskType = TaskType.values()[args]; + + switch (taskType) { + case EVENT: + if(!isValidDate(dateTimeArgs[EVENT_END_DATE])) { + return false; + } + if(!isValidTime(dateTimeArgs[EVENT_END_TIME])){ + return false; + } + case TIMERANGE: + if(!isValidTime(dateTimeArgs[TASK_END_TIME]) && taskType == TaskType.TIMERANGE) { + return false; + } + case DEADLINE: + if(!isValidTime(dateTimeArgs[TASK_START_TIME])) { + return false; + } + case UNTIMED: + if (!isValidDate(dateTimeArgs[TASK_DATE_ONLY])) { + return false; + } + break; + default: + return false; //no. of arguments > expected arguments + } + return true; + } + + private boolean isValidTime(String time) { + if(time.matches(TIME_VALIDATION_FORMAT)) { + return true; + } + return false; + } + + private boolean isValidDate(String date) { + if(date.matches(DATE_VALIDATION_FORMAT)) { + return true; + } + return false; + } +``` +###### \java\seedu\address\logic\undoredomanager\UndoRedoManager.java +``` java +/** + * Stack containers for undo and redo commands. + * Undoable commands that are successfully executed will be added to the undoStack. + * Each time an undoable command is added to the undoStack, the redoStack will be cleared. + */ +public class UndoRedoManager { + + public static final int STACK_LIMIT = 10; + + FixedStack undoStack; + FixedStack redoStack; + + public UndoRedoManager() { + undoStack = new FixedStack(STACK_LIMIT); + redoStack = new FixedStack(STACK_LIMIT); + } + + public FixedStack getUndo() { + return undoStack; + } + + public FixedStack getRedo() { + return redoStack; + } + + /** + * Pushes the command to the undoStack if successfully executed + * @param command successfully executed + * @return command added to UndoStack + */ + public void addToUndo(Command command) { + undoStack.push(command); + redoStack.clear(); + } + + public void transferToRedo(Command command) { + redoStack.push(command); + } + + public void transferToUndo(Command command) { + undoStack.push(command); + } + + public void resetData() { + undoStack.clear(); + redoStack.clear(); + } +} +``` +###### \java\seedu\address\model\task\Time.java +``` java +/** + * Represents a Task's Date in the SmartyDo. + * Guarantees: immutable; is valid as declared in {@link #isCorrectConstructor(String)} + */ +public class Time implements Comparable