diff --git a/README.md b/README.md
index 8715d4d91..1dc652b1d 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,431 @@
-# Duke project template
-
-This is a project template for a greenfield Java project. It's named after the Java mascot _Duke_. Given below are instructions on how to use it.
-
-## Setting up in Intellij
-
-Prerequisites: JDK 11, update Intellij to the most recent version.
-
-1. Open Intellij (if you are not in the welcome screen, click `File` > `Close Project` to close the existing project first)
-1. Open the project into Intellij as follows:
- 1. Click `Open`.
- 1. Select the project directory, and click `OK`.
- 1. If there are any further prompts, accept the defaults.
-1. Configure the project to use **JDK 11** (not other versions) as explained in [here](https://www.jetbrains.com/help/idea/sdk.html#set-up-jdk).
- In the same dialog, set the **Project language level** field to the `SDK default` option.
-3. After that, locate the `src/main/java/Duke.java` file, right-click it, and choose `Run Duke.main()` (if the code editor is showing compile errors, try restarting the IDE). If the setup is correct, you should see something like the below as the output:
- ```
- Hello from
- ____ _
- | _ \ _ _| | _____
- | | | | | | | |/ / _ \
- | |_| | |_| | < __/
- |____/ \__,_|_|\_\___|
- ```
+# User Guide of Duke
+
+## Outline
+* [Outline](#outline)
+* [Introduction](#introduction)
+* [Setup Guide](#setup-guide)
+* [Features](#features)
+ * [Task Type](#task-type)
+ * [Event](#event)
+ * [Deadline](#deadline)
+ * [Todo](#todo)
+ * [Add](#features-add)
+ * [Delete](#features-delete)
+ * [Mark/Unmark](#features-markunmark)
+ * [Search](#features-search)
+ * [List](#features-list)
+* [Tutorial](#tutorial)
+ * [Exit](#tutorial-exit)
+ * [Add Event](#tutorial-add-event)
+ * [Add Deadline](#tutorial-add-deadline)
+ * [Add Todo](#tutorial-add-todo)
+ * [Delete Task](#tutorial-delete-task)
+ * [Mark/Unmark Task](#tutorial-markunmark-task)
+ * [Find Task](#tutorial-find-task)
+ * [List Task](#tutorial-list-task)
+* [Command Summary](#command-summary)
+* [Trouble Shooting](#trouble-shooting)
+* [Demo](#demo)
+---
+
+## Introduction
+Duke is a flexible command line based task manager that helps you to manage your todo task, event task and deadline task. You can follow this guide to explore more features about duke.
+
+---
+
+## Setup Guide
+Prerequisite: JDK 11
+1. Please ensure that JDK 11 is installed before running Duke. You can check it in terminal by typing
+ ````shell
+ java -v
+ ````
+ and you should see something similar as following:
+ ````shell
+ openjdk version "11.0.13" 2021-10-19 LTS
+ OpenJDK Runtime Environment Corretto-11.0.13.8.1 (build 11.0.13+8-LTS)
+ OpenJDK 64-Bit Server VM Corretto-11.0.13.8.1 (build 11.0.13+8-LTS, mixed mode)
+ ````
+2. Download the latest release. You can use command to download it or simply download it from the website:
+ ````shell
+ https://github.com/hlwang56/ip/releases/download/v2.0/ip.jar
+ ````
+3. Open a terminal in the folder when the jar file is placed and run following command
+ ````shell
+ java -jar ip.jar
+ ````
+
+---
+
+## Features
+
+### Task Type
+There are three types of task that are acceptable by duke:
+* #### Event
+ *Event* is a task type that contains task name and event time. It has marked with *E* when displaying on the interface.
+ ````text
+ [E][ ](at: )
+ ````
+* #### Deadline
+ *Deadline* is also a task type that contains task name and deadline time. It has marked with *D* when displaying on the interface
+ ````text
+ [D][ ](by: )
+ ````
+* #### Todo
+ *Todo* is another task type that only contains task name. It has marked with *T* when displaying on the interface.
+ ````text
+ [T][ ]
+ ````
+
+---
+
+### Features: Add
+You can add any todo task, event task and deadline task without limit in numbers. All the tasks are marked as undone initially like following:
+````text
+[Task Type][Task Status]
+````
+Check [Tutorial](#tutorial) or [Command Summary](#command-summary) for adding command usage.
+
+---
+
+### Features: Delete
+You can delete any task from the list by giving the index of the task you want to delete.
+
+Check [Tutorial](#tutorial-delete-task) or [Command Summary](#command-summary) for delete command usage.
+
+---
+
+### Features: Mark/Unmark
+You can mark any task in the list as done or undone by giving the index of the task you want to mark/unmark. The marked task will display *X* on the second column when displaying on the interface, like following example:
+
+````text
+[Task Type][X] //this is a marked task
+````
+Check [Tutorial](#tutorial-markunmark-task) or [Command Summary](#command-summary) for marking/unmarking command usage.
+
+---
+
+### Features: Search
+You can use keywords to find all the task that have relevant task name to the given keyword.
+
+Check [Tutorial](#tutorial-find-task) or [Command Summary](#command-summary) for searching command usage.
+
+---
+
+### Features: List
+You can list all the task that duke has stored. Check [Tutorial](#tutorial-list-task) or [Command Summary](#command-summary) for searching command usage.
+
+---
+
+### Features: Save
+All the tasks that duke has will be saved to an external file. Don't worry if you exit the program without saving file! Duke will save it after every operation. Next time when you start the program again, you could see the tasks from the last use.
+
+---
+## Tutorial
+#### Tutorial: Exit
+Use following command to exit the program:
+````text
+Bye
+````
+
+---
+
+### Tutorial: Add Event
+Type following command in the console by replacing and with your own task information:
+````text
+Event /at
+````
+You will get following message if the action is success.
+````text
+ψ(._. )> Got it. I've added this task:
+[E][ ](at: )
+Now you have tasks in your list.
+````
+
+---
+
+### Tutorial: Add Deadline
+Type following command in the console by replacing and with your own task information:
+````text
+Deadline /by
+````
+You will get following message if the action is success.
+````text
+ψ(._. )> Got it. I've added this task:
+[D][ ](by: )
+Now you have tasks in your list.
+````
+
+---
+
+### Tutorial: Add Todo
+Type following command in the console by replacing and with your own task information:
+````shell
+Todo
+````
+You will get following message if the action is success.
+````text
+ψ(._. )> Got it. I've added this task:
+[T][ ]
+Now you have tasks in your list.
+````
+***IMPORTANT NOTE***
+
+Please use acceptable time format when entering time. Acceptable time formats are following:
+````text
+y-M-d H:m
+y/M/d H:m
+d-M-y H:m
+d/M/y H:m
+y-M-d
+y/M/d
+d-M-y
+d/M/y
+(y -> year, M -> month, d -> day, H -> hour, m -> minute)
+There's no requirement for the number of digit but please ensure that the date and the time is valid.
+````
+
+---
+
+### Tutorial: List Task
+Use following command to list all the task:
+````text
+list
+````
+You should see following message if there's any task in the list:
+````text
+o(≧v≦)o Here are the tasks in your list:
+1. [Task Type][Status]()
+2. [Task Type][Status]()
+3. ...
+````
+Otherwise
+````text
+The list is empty currently ( ̄3 ̄)a
+````
+***IMPORTANT NOTE***
+
+Please use the index from listing task for deleting and marking/unmarking task!
+
+---
+
+### Tutorial: Delete Task
+Type following command by replacing to the index of the task that you would like to delete:
+````text
+delete
+````
+You will get following message if the action is success.
+````text
+ψ(._. )> Okay! I've deleted this task:
+[Type of Task][Status of Task]()
+Now you have tasks in your list.
+````
+***IMPORTANT NOTE***
+
+For the index of the task, please refer to the index when listing all the tasks. The index may change after adding task or deleting task. **Be aware that this action cannot be retrieved!**
+
+---
+
+### Tutorial: Mark/Unmark Task
+To mark a task in the list, type following command by replacing to the index of the task that you would like to delete:
+````text
+mark
+````
+You will get following message if the action is success.
+````text
+ψ(._. )> Okay! I've deleted this task:
+[Type of Task][X]()
+````
+Use following command to unmark a task in the list:
+````text
+unmark
+````
+You will get following message if the action is success.
+````text
+ψ(._. )> Okay! I've deleted this task:
+[Type of Task][ ]()
+````
+***IMPORTANT NOTE***
+
+For the index of the task, please refer to the index when listing all the tasks. The index may change after adding task or deleting task.
+
+---
+
+### Tutorial: Find Task
+Use following command to find a task that match the keyword from the list:
+````text
+find
+````
+Duke will list all the tasks that match the keyword (if there's any!)
+````TEXT
+o(≧v≦)o Here are the matching tasks in your list:
+1. [Task Type][Status]()
+2. [Task Type][Status]()
+3. ...
+...
+````
+If there's no task which matches to the keyword, duke will print following message on the interface:
+````TEXT
+( ̄ε ̄;) Sorry, I can't find any result from the list.
+````
+***IMPORTANT NOTE***
+
+**Please do not refer to this index when deleting or marking/unmarking task.** This index is only for your reference about how many matching task in the list.
+
+Duke only supports to find matching task according to the keyword and task name. **Searching by time is not supported currently.**
+
+---
+
+## Command Summary
+**add todo**
+
+`todo `
+
+**add event**
+
+`event /at `
+
+**add deadline**
+
+`deadline /by `
+
+**mark**
+
+`mark `
+
+**unmark**
+
+`unmark `
+
+**find**
+
+`find `
+
+**delete**
+
+`delete `
+
+**list**
+
+`list`
+
+**exit**
+
+`bye`
+
+---
+
+## Trouble Shooting
+**Q**: What should I do if the program reports loading error?
+
+**A**: The external file for saving and loading is broken. In this case you need to reinstall the programme.
+
+**Q**: What is acceptable time format?
+
+**A**: The acceptable time formats are following:
+````text
+y-M-d H:m
+y/M/d H:m
+d-M-y H:m
+d/M/y H:m
+y-M-d
+y/M/d
+d-M-y
+d/M/y
+(y -> year, M -> month, d -> day, H -> hour, m -> minute)
+````
+There's no requirement for the number of digit but please ensure that the date and the time are valid.
+
+**Q**: What if I accidentally delete a task that I want to keep?
+
+**A**: Delete action cannot be retrieved. You can add it again, but the tasks will have different index.
+
+**TIPS**: Always list all the task before deleting and marking/unmarking.
+
+## Demo
+````text
+Hello! I'm Duke :P
+What can I do for you?
+-------------------------------------
+list
+The list is empty currently ( ̄3 ̄)a
+-------------------------------------
+deadline CS2113 Quiz /by 2019/06/20 23:59
+ψ(._. )> Got it. I've added this task:
+[D][ ]CS2113 Quiz (by: Jun. 20 2019 23:59)
+Now you have 1 tasks in your list.
+-------------------------------------
+event MA2101 Quiz /at 2019-6-30
+ψ(._. )> Got it. I've added this task:
+[E][ ]MA2101 Quiz (at: Jun. 30 2019)
+Now you have 2 tasks in your list.
+-------------------------------------
+todo Homework
+ψ(._. )> Got it. I've added this task:
+[T][ ]Homework
+Now you have 3 tasks in your list.
+-------------------------------------
+list
+o(≧v≦)o Here are the tasks in your list:
+1. [D][ ]CS2113 Quiz (by: Jun. 20 2019 23:59)
+2. [E][ ]MA2101 Quiz (at: Jun. 30 2019)
+3. [T][ ]Homework
+-------------------------------------
+mark 1
+ψ(._. )> Nice! I've marked this task as done:
+[D][X]CS2113 Quiz (by: Jun. 20 2019 23:59)
+-------------------------------------
+mark 2
+ψ(._. )> Nice! I've marked this task as done:
+[E][X]MA2101 Quiz (at: Jun. 30 2019)
+-------------------------------------
+list
+o(≧v≦)o Here are the tasks in your list:
+1. [D][X]CS2113 Quiz (by: Jun. 20 2019 23:59)
+2. [E][X]MA2101 Quiz (at: Jun. 30 2019)
+3. [T][ ]Homework
+-------------------------------------
+unmark 2
+ψ(._. )> OK, I've marked this task as not done yet:
+[E][ ]MA2101 Quiz (at: Jun. 30 2019)
+-------------------------------------
+list
+o(≧v≦)o Here are the tasks in your list:
+1. [D][X]CS2113 Quiz (by: Jun. 20 2019 23:59)
+2. [E][ ]MA2101 Quiz (at: Jun. 30 2019)
+3. [T][ ]Homework
+-------------------------------------
+find Quiz
+o(≧v≦)o Here are the matching tasks in your list:
+1. [D][X]CS2113 Quiz (by: Jun. 20 2019 23:59)
+2. [E][ ]MA2101 Quiz (at: Jun. 30 2019)
+-------------------------------------
+deadline CS2106 midterm /at 2019-4-31
+The format is incorrect! Can you please check your input again? ●ω●
+-------------------------------------
+deadline CS2106 midterm /by 2019-4-31
+The time format is incorrect! Can you please check your input again? ( ̄~ ̄;) You can check the manual to find out acceptable time format!
+-------------------------------------
+deadline CS2106 midterm /by 2019-4-30 25:61
+The time format is incorrect! Can you please check your input again? ( ̄~ ̄;) You can check the manual to find out acceptable time format!
+-------------------------------------
+deadline CS2106 midterm /by 2019-4-30 2:3
+ψ(._. )> Got it. I've added this task:
+[D][ ]CS2106 midterm (by: Apr. 30 2019 02:03)
+Now you have 4 tasks in your list.
+-------------------------------------
+list
+o(≧v≦)o Here are the tasks in your list:
+1. [D][ ]CS2113 Quiz (by: Jun. 20 2019 23:59)
+2. [E][ ]MA2101 Quiz (at: Jun. 30 2019)
+3. [T][ ]Homework
+4. [D][ ]CS2106 midterm (by: Apr. 30 2019 02:03)
+-------------------------------------
+delete 4
+ψ(._. )> Okay! I've deleted this task:
+[D][ ]CS2106 midterm (by: Apr. 30 2019 02:03)
+Now you have 3 tasks in your list.
+-------------------------------------
+bye
+Bye. Hope to see you again soon! ;)
+-------------------------------------
+````
\ No newline at end of file
diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
new file mode 100644
index 000000000..502fbd3a5
--- /dev/null
+++ b/config/checkstyle/checkstyle.xml
@@ -0,0 +1,398 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data/duke.txt b/data/duke.txt
new file mode 100644
index 000000000..d116fb41e
--- /dev/null
+++ b/data/duke.txt
@@ -0,0 +1 @@
+[T][X]j
diff --git a/docs/README.md b/docs/README.md
index 8077118eb..b8dd57ea7 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,29 +1,433 @@
-# User Guide
+# User Guide of Duke
-## Features
+## Outline
+* [Outline](#outline)
+* [Introduction](#introduction)
+* [Setup Guide](#setup-guide)
+* [Features](#features)
+ * [Task Type](#task-type)
+ * [Event](#event)
+ * [Deadline](#deadline)
+ * [Todo](#todo)
+ * [Add](#features-add)
+ * [Delete](#features-delete)
+ * [Mark/Unmark](#features-markunmark)
+ * [Search](#features-search)
+ * [List](#features-list)
+* [Tutorial](#tutorial)
+ * [Exit](#tutorial-exit)
+ * [Add Event](#tutorial-add-event)
+ * [Add Deadline](#tutorial-add-deadline)
+ * [Add Todo](#tutorial-add-todo)
+ * [Delete Task](#tutorial-delete-task)
+ * [Mark/Unmark Task](#tutorial-markunmark-task)
+ * [Find Task](#tutorial-find-task)
+ * [List Task](#tutorial-list-task)
+* [Command Summary](#command-summary)
+* [Trouble Shooting](#trouble-shooting)
+* [Demo](#demo)
-### Feature-ABC
+---
-Description of the feature.
+## Introduction
+Duke is a flexible command line based task manager that helps you to manage your todo task, event task and deadline task. You can follow this guide to explore more features about duke.
-### Feature-XYZ
+---
-Description of the feature.
+## Setup Guide
+Prerequisite: JDK 11
+1. Please ensure that JDK 11 is installed before running Duke. You can check it in terminal by typing
+ ````shell
+ java -version
+ ````
+ and you should see something similar as following:
+ ````shell
+ openjdk version "11.0.13" 2021-10-19 LTS
+ OpenJDK Runtime Environment Corretto-11.0.13.8.1 (build 11.0.13+8-LTS)
+ OpenJDK 64-Bit Server VM Corretto-11.0.13.8.1 (build 11.0.13+8-LTS, mixed mode)
+ ````
+2. Download the latest release. You can use command to download it or simply download it from the website:
+ ````shell
+ https://github.com/hlwang56/ip/releases/download/v2.0/ip.jar
+ ````
+3. Open a terminal in the folder where the jar file is placed and run following command
+ ````shell
+ java -jar ip.jar
+ ````
-## Usage
+---
-### `Keyword` - Describe action
+## Features
-Describe the action and its outcome.
+### Task Type
+There are three types of task that are acceptable by duke:
+* #### Event
+ *Event* is a task type that contains task name and event time. It has marked with *E* when displaying on the interface.
+ ````text
+ [E][ ](at: )
+ ````
+* #### Deadline
+ *Deadline* is also a task type that contains task name and deadline time. It has marked with *D* when displaying on the interface
+ ````text
+ [D][ ](by: )
+ ````
+* #### Todo
+ *Todo* is another task type that only contains task name. It has marked with *T* when displaying on the interface.
+ ````text
+ [T][ ]
+ ````
-Example of usage:
+---
-`keyword (optional arguments)`
+### Features: Add
+You can add any todo task, event task and deadline task without limit in numbers. All the tasks are marked as undone initially like following:
+````text
+[Task Type][Task Status]
+````
+Check [Tutorial](#tutorial) or [Command Summary](#command-summary) for adding command usage.
-Expected outcome:
+---
-Description of the outcome.
+### Features: Delete
+You can delete any task from the list by giving the index of the task you want to delete.
-```
-expected output
-```
+Check [Tutorial](#tutorial-delete-task) or [Command Summary](#command-summary) for delete command usage.
+
+---
+
+### Features: Mark/Unmark
+You can mark any task in the list as done or undone by giving the index of the task you want to mark/unmark. The marked task will display *X* on the second column when displaying on the interface, like following example:
+
+````text
+[Task Type][X] //this is a marked task
+````
+Check [Tutorial](#tutorial-markunmark-task) or [Command Summary](#command-summary) for marking/unmarking command usage.
+
+---
+
+### Features: Search
+You can use keywords to find all the task that have relevant task name to the given keyword.
+
+Check [Tutorial](#tutorial-find-task) or [Command Summary](#command-summary) for searching command usage.
+
+---
+
+### Features: List
+You can list all the task that duke has stored. Check [Tutorial](#tutorial-list-task) or [Command Summary](#command-summary) for searching command usage.
+
+---
+
+### Features: Save
+All the tasks that duke has will be saved to an external file. Don't worry if you exit the program without saving file! Duke will save it after every operation. Next time when you start the program again, you could see the tasks from the last use.
+
+---
+## Tutorial
+#### Tutorial: Exit
+Use following command to exit the program:
+````text
+Bye
+````
+
+---
+
+### Tutorial: Add Event
+Type following command in the console by replacing and with your own task information:
+````text
+Event /at
+````
+You will get following message if the action is success.
+````text
+ψ(._. )> Got it. I've added this task:
+[E][ ](at: )
+Now you have tasks in your list.
+````
+
+---
+
+### Tutorial: Add Deadline
+Type following command in the console by replacing and with your own task information:
+````text
+Deadline /by
+````
+You will get following message if the action is success.
+````text
+ψ(._. )> Got it. I've added this task:
+[D][ ](by: )
+Now you have tasks in your list.
+````
+
+---
+
+### Tutorial: Add Todo
+Type following command in the console by replacing and with your own task information:
+````shell
+Todo
+````
+You will get following message if the action is success.
+````text
+ψ(._. )> Got it. I've added this task:
+[T][ ]
+Now you have tasks in your list.
+````
+***IMPORTANT NOTE***
+
+Please use acceptable time format when entering time. Acceptable time formats are following:
+````text
+y-M-d H:m
+y/M/d H:m
+d-M-y H:m
+d/M/y H:m
+y-M-d
+y/M/d
+d-M-y
+d/M/y
+(y -> year, M -> month, d -> day, H -> hour, m -> minute)
+There's no requirement for the number of digit but please ensure that the date and the time is valid.
+````
+
+---
+
+### Tutorial: List Task
+Use following command to list all the task:
+````text
+list
+````
+You should see following message if there's any task in the list:
+````text
+o(≧v≦)o Here are the tasks in your list:
+1. [Task Type][Status]()
+2. [Task Type][Status]()
+3. ...
+````
+Otherwise
+````text
+The list is empty currently ( ̄3 ̄)a
+````
+***IMPORTANT NOTE***
+
+Please use the index from listing task for deleting and marking/unmarking task!
+
+---
+
+### Tutorial: Delete Task
+Type following command by replacing to the index of the task that you would like to delete:
+````text
+delete
+````
+You will get following message if the action is success.
+````text
+ψ(._. )> Okay! I've deleted this task:
+[Type of Task][Status of Task]()
+Now you have tasks in your list.
+````
+***IMPORTANT NOTE***
+
+For the index of the task, please refer to the index when listing all the tasks. The index may change after adding task or deleting task. **Be aware that this action cannot be retrieved!**
+
+---
+
+### Tutorial: Mark/Unmark Task
+To mark a task in the list, type following command by replacing to the index of the task that you would like to delete:
+````text
+mark
+````
+You will get following message if the action is success.
+````text
+ψ(._. )> Okay! I've deleted this task:
+[Type of Task][X]()
+````
+Use following command to unmark a task in the list:
+````text
+unmark
+````
+You will get following message if the action is success.
+````text
+ψ(._. )> Okay! I've deleted this task:
+[Type of Task][ ]()
+````
+***IMPORTANT NOTE***
+
+For the index of the task, please refer to the index when listing all the tasks. The index may change after adding task or deleting task.
+
+---
+
+### Tutorial: Find Task
+Use following command to find a task that match the keyword from the list:
+````text
+find
+````
+Duke will list all the tasks that match the keyword (if there's any!)
+````TEXT
+o(≧v≦)o Here are the matching tasks in your list:
+1. [Task Type][Status]()
+2. [Task Type][Status]()
+3. ...
+...
+````
+If there's no task which matches to the keyword, duke will print following message on the interface:
+````TEXT
+( ̄ε ̄;) Sorry, I can't find any result from the list.
+````
+***IMPORTANT NOTE***
+
+**Please do not refer to this index when deleting or marking/unmarking task.** This index is only for your reference about how many matching task in the list.
+
+Duke only supports to find matching task according to the keyword and task name. **Searching by time is not supported currently.**
+
+---
+
+## Command Summary
+**add todo**
+
+`todo `
+
+**add event**
+
+`event /at `
+
+**add deadline**
+
+`deadline /by `
+
+**mark**
+
+`mark `
+
+**unmark**
+
+`unmark `
+
+**find**
+
+`find `
+
+**delete**
+
+`delete `
+
+**list**
+
+`list`
+
+**exit**
+
+`bye`
+
+---
+
+## Trouble Shooting
+**Q**: What should I do if the program reports loading error?
+
+**A**: The external file for saving and loading is broken. In this case you need to reinstall the programme.
+
+**Q**: What is acceptable time format?
+
+**A**: The acceptable time formats are following:
+````text
+y-M-d H:m
+y/M/d H:m
+d-M-y H:m
+d/M/y H:m
+y-M-d
+y/M/d
+d-M-y
+d/M/y
+(y -> year, M -> month, d -> day, H -> hour, m -> minute)
+````
+There's no requirement for the number of digit but please ensure that the date and the time are valid.
+
+**Q**: What if I accidentally delete a task that I want to keep?
+
+**A**: Delete action cannot be retrieved. You can add it again, but the tasks will have different index.
+
+**TIPS**: Always list all the task before deleting and marking/unmarking.
+
+---
+## Demo
+````text
+Hello! I'm Duke :P
+What can I do for you?
+-------------------------------------
+list
+The list is empty currently ( ̄3 ̄)a
+-------------------------------------
+deadline CS2113 Quiz /by 2019/06/20 23:59
+ψ(._. )> Got it. I've added this task:
+[D][ ]CS2113 Quiz (by: Jun. 20 2019 23:59)
+Now you have 1 tasks in your list.
+-------------------------------------
+event MA2101 Quiz /at 2019-6-30
+ψ(._. )> Got it. I've added this task:
+[E][ ]MA2101 Quiz (at: Jun. 30 2019)
+Now you have 2 tasks in your list.
+-------------------------------------
+todo Homework
+ψ(._. )> Got it. I've added this task:
+[T][ ]Homework
+Now you have 3 tasks in your list.
+-------------------------------------
+list
+o(≧v≦)o Here are the tasks in your list:
+1. [D][ ]CS2113 Quiz (by: Jun. 20 2019 23:59)
+2. [E][ ]MA2101 Quiz (at: Jun. 30 2019)
+3. [T][ ]Homework
+-------------------------------------
+mark 1
+ψ(._. )> Nice! I've marked this task as done:
+[D][X]CS2113 Quiz (by: Jun. 20 2019 23:59)
+-------------------------------------
+mark 2
+ψ(._. )> Nice! I've marked this task as done:
+[E][X]MA2101 Quiz (at: Jun. 30 2019)
+-------------------------------------
+list
+o(≧v≦)o Here are the tasks in your list:
+1. [D][X]CS2113 Quiz (by: Jun. 20 2019 23:59)
+2. [E][X]MA2101 Quiz (at: Jun. 30 2019)
+3. [T][ ]Homework
+-------------------------------------
+unmark 2
+ψ(._. )> OK, I've marked this task as not done yet:
+[E][ ]MA2101 Quiz (at: Jun. 30 2019)
+-------------------------------------
+list
+o(≧v≦)o Here are the tasks in your list:
+1. [D][X]CS2113 Quiz (by: Jun. 20 2019 23:59)
+2. [E][ ]MA2101 Quiz (at: Jun. 30 2019)
+3. [T][ ]Homework
+-------------------------------------
+find Quiz
+o(≧v≦)o Here are the matching tasks in your list:
+1. [D][X]CS2113 Quiz (by: Jun. 20 2019 23:59)
+2. [E][ ]MA2101 Quiz (at: Jun. 30 2019)
+-------------------------------------
+deadline CS2106 midterm /at 2019-4-31
+The format is incorrect! Can you please check your input again? ●ω●
+-------------------------------------
+deadline CS2106 midterm /by 2019-4-31
+The time format is incorrect! Can you please check your input again? ( ̄~ ̄;) You can check the manual to find out acceptable time format!
+-------------------------------------
+deadline CS2106 midterm /by 2019-4-30 25:61
+The time format is incorrect! Can you please check your input again? ( ̄~ ̄;) You can check the manual to find out acceptable time format!
+-------------------------------------
+deadline CS2106 midterm /by 2019-4-30 2:3
+ψ(._. )> Got it. I've added this task:
+[D][ ]CS2106 midterm (by: Apr. 30 2019 02:03)
+Now you have 4 tasks in your list.
+-------------------------------------
+list
+o(≧v≦)o Here are the tasks in your list:
+1. [D][ ]CS2113 Quiz (by: Jun. 20 2019 23:59)
+2. [E][ ]MA2101 Quiz (at: Jun. 30 2019)
+3. [T][ ]Homework
+4. [D][ ]CS2106 midterm (by: Apr. 30 2019 02:03)
+-------------------------------------
+delete 4
+ψ(._. )> Okay! I've deleted this task:
+[D][ ]CS2106 midterm (by: Apr. 30 2019 02:03)
+Now you have 3 tasks in your list.
+-------------------------------------
+bye
+Bye. Hope to see you again soon! ;)
+-------------------------------------
+````
diff --git a/docs/_config.yml b/docs/_config.yml
new file mode 100644
index 000000000..c74188174
--- /dev/null
+++ b/docs/_config.yml
@@ -0,0 +1 @@
+theme: jekyll-theme-slate
\ No newline at end of file
diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index 5d313334c..8b678f98e 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -1,10 +1,19 @@
+import controller.Controller;
+
public class Duke {
- public static void main(String[] args) {
- String logo = " ____ _ \n"
- + "| _ \\ _ _| | _____ \n"
- + "| | | | | | | |/ / _ \\\n"
- + "| |_| | |_| | < __/\n"
- + "|____/ \\__,_|_|\\_\\___|\n";
- System.out.println("Hello from\n" + logo);
+ /**
+ * Run program
+ * @param args input from user
+ * @throws Exception if there's any unacceptable condition
+ */
+ public static void main(String[] args) throws Exception {
+ Controller bot = new Controller();
+ bot.greet();
+ bot.createFile();
+ bot.loadTask();
+ while (true) {
+ //opens a new session for receiving instruction
+ bot.listen();
+ }
}
}
diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..d2ffd5b4d
--- /dev/null
+++ b/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: Duke
+
diff --git a/src/main/java/UI/Chatbox.java b/src/main/java/UI/Chatbox.java
new file mode 100644
index 000000000..5cc92230d
--- /dev/null
+++ b/src/main/java/UI/Chatbox.java
@@ -0,0 +1,24 @@
+package UI;
+
+/**
+ * Create a chatbox for each message
+ */
+public class Chatbox {
+ //border of the chatbox
+ protected static final String HORIZON_LINE = "-------------------------------------";
+ private String content = "";
+
+ /**
+ * Initialize a chatbox
+ */
+ public void chatboxPrinter() {
+ System.out.println(content);
+ System.out.println(HORIZON_LINE);
+ }
+
+ public void setContent(String input) {
+ this.content = input;
+ }
+
+
+}
diff --git a/src/main/java/UI/UI.java b/src/main/java/UI/UI.java
new file mode 100644
index 000000000..6594c61c5
--- /dev/null
+++ b/src/main/java/UI/UI.java
@@ -0,0 +1,42 @@
+package UI;
+
+/**
+ * Create a UI for displaying message
+ */
+public class UI {
+ protected static final String HELLO_WORDS = "Hello! I'm Duke :P\nWhat can I do for you?";
+ protected static final String GOODBYE_WORDS = "Bye. Hope to see you again soon! ;)";
+ private Chatbox chatbox;
+
+ /**
+ * Initialize a UI
+ */
+ public UI() {
+ chatbox = new Chatbox();
+ }
+
+ /**
+ * Print greeting message
+ */
+ public void greet() {
+ chatbox.setContent(HELLO_WORDS);
+ chatbox.chatboxPrinter();
+ }
+
+ /**
+ * Print goodbye message
+ */
+ public void goodbye() {
+ chatbox.setContent(GOODBYE_WORDS);
+ chatbox.chatboxPrinter();
+ }
+
+ /**
+ * Prints message from other classes
+ * @param message the message that is returned from other function or classes
+ */
+ public void printMsg(String message) {
+ chatbox.setContent(message);
+ chatbox.chatboxPrinter();
+ }
+}
diff --git a/src/main/java/controller/Command.java b/src/main/java/controller/Command.java
new file mode 100644
index 000000000..399c60266
--- /dev/null
+++ b/src/main/java/controller/Command.java
@@ -0,0 +1,147 @@
+package controller;
+
+import exceptions.DukeExceptions;
+import exceptions.IllegalFormatException;
+import exceptions.IllegalTimeFormatException;
+import exceptions.KeywordLossException;
+import exceptions.TaskNameLossException;
+import time.Time;
+
+public class Command {
+ protected static final String ADD_EVENT = "event";
+ protected static final String ADD_DEADLINE = "deadline";
+ protected static final String ADD_TODO = "todo";
+ protected static final String UPDATE = "update";
+ protected static final String SEARCH = "find";
+ protected static final String EVENT = "event ";
+ protected static final String TODO = "todo ";
+ protected static final String DEADLINE = "deadline ";
+ protected String taskName;
+ protected String dateString;
+ protected String rawInput;
+ protected String[] parsedInput;
+ private Time timeChecker;
+
+ /**
+ * Create a new instruction executor
+ * @param parsedInput the array of the instruction after splitting by space;
+ * @param rawInput the instruction that user given from the command line.
+ */
+ public Command(String[] parsedInput, String rawInput) {
+ this.rawInput = rawInput;
+ this.parsedInput = parsedInput;
+ }
+
+ /**
+ * decomposes the instruction from user and store the information separately
+ * @param instruction the instruction from user after analysed by Operation Analyst
+ * @throws DukeExceptions if the instruction has incorrect format
+ */
+ public void decomposeInstruction(String instruction) throws DukeExceptions {
+ switch (instruction) {
+ case ADD_EVENT:
+ decomposeAddWithTime("/at ", EVENT);
+ break;
+ case ADD_DEADLINE:
+ decomposeAddWithTime("/by ", DEADLINE);
+ break;
+ case ADD_TODO:
+ decomposeAddWithoutTime(TODO);
+ break;
+ case SEARCH:
+ decomposeSearchByDescription();
+ break;
+ case UPDATE:
+ decomposeUpdateDelete();
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Decompose the instruction of adding task with time, and store the
+ * task name and date in taskName and dateString for further access
+ * @param regex the keyword for decomposition. For adding event,
+ * the regex is "/at ", and for adding deadline, the
+ * regex is "/by"
+ * @param taskType the type of task that need to be added
+ * @throws DukeExceptions if the task name is loss, wrong instruction
+ * formatting or wrong time formatting
+ */
+ public void decomposeAddWithTime(String regex, String taskType) throws DukeExceptions {
+ String[] parsedInputByTime;
+ parsedInputByTime = rawInput.split(regex);
+ try {
+ this.taskName = parsedInputByTime[0].replace(taskType, "");
+ } catch (Exception e) {
+ throw new TaskNameLossException();
+ }
+ try {
+ timeChecker = new Time(parsedInputByTime[1]);
+ timeChecker.check();
+ this.dateString = timeChecker.getDateString();
+ } catch (IndexOutOfBoundsException e) {
+ throw new IllegalFormatException();
+ } catch (Exception e) {
+ throw new IllegalTimeFormatException();
+ }
+ }
+
+ /**
+ * Decompose the instruction of searching task by task description,
+ * and store the key information in taskName for further access
+ * @throws DukeExceptions if the keyword is loss
+ */
+ public void decomposeSearchByDescription() throws DukeExceptions {
+ String[] parseInputByKeywords;
+ parseInputByKeywords = rawInput.split(" ", 2);
+ try {
+ this.taskName = parseInputByKeywords[1];
+ } catch (IndexOutOfBoundsException e) {
+ throw new KeywordLossException();
+ }
+ }
+
+ /**
+ * Decomposes decompose the instruction of adding task without time
+ * @param taskType the type of task that is going to be added
+ * @throws DukeExceptions if the task name is loss
+ */
+ public void decomposeAddWithoutTime(String taskType) throws DukeExceptions {
+ try {
+ this.taskName = this.rawInput.replace(taskType, "");
+ } catch (Exception e) {
+ throw new TaskNameLossException();
+ }
+ }
+
+ /**
+ * Decomposes the instruction for marking/unmarking and deleting task
+ * @throws DukeExceptions if the format of instruction is wrong
+ */
+ public void decomposeUpdateDelete() throws DukeExceptions {
+ try {
+ this.taskName = this.parsedInput[1];
+ } catch (IndexOutOfBoundsException e) {
+ throw new IllegalFormatException();
+ }
+ }
+
+ /**
+ * Access and return the date stored in dateString in string format
+ * @return the date in string format
+ */
+ public String getDateString() {
+ return dateString;
+ }
+
+ /**
+ * Access and return the information in taskName
+ * @return the information stored in taskName in String format
+ */
+ public String getTaskName() {
+ return taskName;
+ }
+
+}
diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java
new file mode 100644
index 000000000..05d616eaa
--- /dev/null
+++ b/src/main/java/controller/Controller.java
@@ -0,0 +1,124 @@
+package controller;
+
+import java.util.Scanner;
+
+import UI.UI;
+import exceptions.DukeExceptions;
+import exceptions.IllegalInstructionException;
+import exceptions.TaskIndexLossException;
+import tasks.TaskManager;
+
+public class Controller {
+ protected static final String MARK_TASK_COMMAND = "mark";
+ protected static final String UNMARK_TASK_COMMAND = "unmark";
+ protected static final String DELETE_TASK_COMMAND = "delete";
+ protected static final String ADD_TODO_TASK_COMMAND = "todo";
+ protected static final String ADD_EVENT_TASK_COMMAND = "event";
+ protected static final String ADD_DEADLINE_TASK_COMMAND = "deadline";
+ protected static final String LIST_TASKS_COMMAND = "list";
+ protected static final String EXIT_COMMAND = "bye";
+ protected static final String SEARCH_COMMAND = "find";
+ protected String recvMsg;
+ protected String replyMsg;
+ private TaskManager manager = new TaskManager();
+ private OperationAnalyst analyst;
+ private UI userInterface = new UI();
+
+ /**
+ * Prints greeting msg on the interface
+ */
+ public void greet() {
+ userInterface.greet();
+ }
+
+ /**
+ * Prints goodbye msg on the interface and exits
+ */
+ public void bye() {
+ userInterface.goodbye();
+ System.exit(0);
+ }
+
+ /**
+ * Checks if the input to indicate the index of the task for operation is a number
+ * @param indexOfTask is the index of the task in String format
+ * @return the index of the task in Integer format
+ * @throws DukeExceptions if the input is not a number
+ */
+ private int parseInt(String indexOfTask) throws DukeExceptions {
+ try {
+ int index = Integer.parseInt(indexOfTask);
+ return index;
+ } catch (NumberFormatException e) {
+ throw new TaskIndexLossException();
+ }
+ }
+
+ /**
+ * Calls task manager to create a new file for saving task
+ * @throws DukeExceptions if the creation is failed
+ */
+ public void createFile() throws DukeExceptions {
+ manager.createFile();
+ }
+
+ /**
+ * Calls task manager to load tasks from the file
+ * @throws DukeExceptions if the loading action is failed
+ */
+ public void loadTask() throws DukeExceptions {
+ manager.loadTask();
+ }
+
+ /**
+ * listen to the instruction from user and do operation after user open a session
+ * @throws DukeExceptions if it is failed to operate the instruction user given
+ */
+ public void listen() throws DukeExceptions {
+ Scanner msg = new Scanner(System.in);
+ this.recvMsg = msg.nextLine();
+ int indexOfTask;
+ try {
+ analyst = new OperationAnalyst(this.recvMsg);
+ String command = analyst.getCommand();
+ switch (command) {
+ case EXIT_COMMAND:
+ this.bye();
+ break;
+ case LIST_TASKS_COMMAND:
+ this.replyMsg = manager.listTask();
+ break;
+ case MARK_TASK_COMMAND:
+ indexOfTask = parseInt(analyst.taskName);
+ this.replyMsg = manager.markTask(indexOfTask);
+ break;
+ case UNMARK_TASK_COMMAND:
+ indexOfTask = parseInt(analyst.taskName);
+ this.replyMsg = manager.unmarkTask(indexOfTask);
+ break;
+ case ADD_DEADLINE_TASK_COMMAND:
+ this.replyMsg = manager.addDeadline(analyst.taskName, analyst.time);
+ break;
+ case ADD_EVENT_TASK_COMMAND:
+ this.replyMsg = manager.addEvent(analyst.taskName, analyst.time);
+ break;
+ case ADD_TODO_TASK_COMMAND:
+ this.replyMsg = manager.addToDo(analyst.taskName);
+ break;
+ case DELETE_TASK_COMMAND:
+ indexOfTask = parseInt(analyst.taskName);
+ this.replyMsg = manager.deleteTask(indexOfTask);
+ break;
+ case SEARCH_COMMAND:
+ this.replyMsg = manager.searchTask(analyst.taskName);
+ break;
+ default:
+ throw new IllegalInstructionException();
+ }
+ userInterface.printMsg(replyMsg);
+ manager.saveTask();
+ } catch (DukeExceptions e) {
+ userInterface.printMsg(e.toString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/controller/OperationAnalyst.java b/src/main/java/controller/OperationAnalyst.java
new file mode 100644
index 000000000..879a033d7
--- /dev/null
+++ b/src/main/java/controller/OperationAnalyst.java
@@ -0,0 +1,103 @@
+package controller;
+
+import java.util.Locale;
+
+import exceptions.DukeExceptions;
+
+public class OperationAnalyst {
+ protected static final String MARK_TASK_COMMAND = "mark";
+ protected static final String UNMARK_TASK_COMMAND = "unmark";
+ protected static final String DELETE_TASK_COMMAND = "delete";
+ protected static final String ADD_TODO_TASK_COMMAND = "todo";
+ protected static final String ADD_EVENT_TASK_COMMAND = "event";
+ protected static final String ADD_DEADLINE_TASK_COMMAND = "deadline";
+ protected static final String LIST_TASKS_COMMAND = "list";
+ protected static final String EXIT_COMMAND = "bye";
+ protected static final String SEARCH_COMMAND = "find";
+ protected static final String UPDATE = "update";
+ //the key information array after splitting raw input
+ protected String[] keyInfo;
+ //the raw input from user
+ protected String rawInput;
+ //the information of task time
+ protected String time;
+ //the information of task description
+ protected String taskName;
+ //the instruction after standardizing
+ protected String instruction;
+ private Command command;
+
+ /**
+ * Compute and parse the instruction into several parts and store them in different
+ * format into different parameters.
+ * @param input the raw input that user type in the command line
+ * @throws DukeExceptions if there's any unacceptable condition exist while
+ * parsing the instruction
+ */
+ public OperationAnalyst(String input) throws DukeExceptions {
+ //split the raw input into several keywords
+ this.keyInfo = input.split(" ");
+ this.rawInput = input;
+ //Standardize the instruction
+ this.instruction = keyInfo[0].toLowerCase(Locale.ROOT);
+ //Create a command for further parsing
+ command = new Command(keyInfo, rawInput);
+ parseInstruction();
+ }
+
+ /**
+ * @return the command, whether it is deadline, todo, event,
+ * list, mark, unmark, delete or find
+ */
+ public String getCommand() {
+ return this.instruction;
+ }
+
+ /**
+ * Parses the command and store the task name, index of task and time
+ * in different parameters.
+ * @throws DukeExceptions if there's unacceptable condition exist
+ */
+ public void parseInstruction() throws DukeExceptions {
+ switch (this.instruction) {
+ case ADD_DEADLINE_TASK_COMMAND:
+ command.decomposeInstruction(ADD_DEADLINE_TASK_COMMAND);
+ this.time = command.getDateString();
+ this.taskName = command.getTaskName();
+ break;
+ case ADD_EVENT_TASK_COMMAND:
+ command.decomposeInstruction(ADD_EVENT_TASK_COMMAND);
+ this.time = command.getDateString();
+ this.taskName = command.getTaskName();
+ break;
+ case ADD_TODO_TASK_COMMAND:
+ command.decomposeInstruction(ADD_TODO_TASK_COMMAND);
+ this.taskName = command.getTaskName();
+ break;
+ case MARK_TASK_COMMAND:
+ case UNMARK_TASK_COMMAND:
+ case DELETE_TASK_COMMAND:
+ command.decomposeInstruction(UPDATE);
+ this.taskName = command.getTaskName();
+ break;
+ case SEARCH_COMMAND:
+ command.decomposeInstruction(SEARCH_COMMAND);
+ this.taskName = command.getTaskName();
+ break;
+ case LIST_TASKS_COMMAND:
+ case EXIT_COMMAND:
+ break;
+ default:
+ this.taskName = rawInput;
+ }
+
+ }
+
+ /**
+ * Returns the information stored in time
+ * @return the date in string format
+ */
+ public String getTime() {
+ return this.time;
+ }
+}
diff --git a/src/main/java/exceptions/CreatingFileException.java b/src/main/java/exceptions/CreatingFileException.java
new file mode 100644
index 000000000..ddc76150b
--- /dev/null
+++ b/src/main/java/exceptions/CreatingFileException.java
@@ -0,0 +1,11 @@
+package exceptions;
+
+public class CreatingFileException extends DukeExceptions {
+ protected static final String CREATING_FILE_ERROR_MSG =
+ "Sorry, there's something wrong when creating file, please try again later QnQ";
+
+ @Override
+ public String toString() {
+ return CREATING_FILE_ERROR_MSG;
+ }
+}
diff --git a/src/main/java/exceptions/DukeExceptions.java b/src/main/java/exceptions/DukeExceptions.java
new file mode 100644
index 000000000..d8de7361a
--- /dev/null
+++ b/src/main/java/exceptions/DukeExceptions.java
@@ -0,0 +1,7 @@
+package exceptions;
+
+/**
+ * DukeException is the super class of all possible exceptions in Duke
+ */
+public abstract class DukeExceptions extends Exception {
+}
diff --git a/src/main/java/exceptions/EmptyListException.java b/src/main/java/exceptions/EmptyListException.java
new file mode 100644
index 000000000..a68d96a08
--- /dev/null
+++ b/src/main/java/exceptions/EmptyListException.java
@@ -0,0 +1,11 @@
+package exceptions;
+
+public class EmptyListException extends DukeExceptions {
+ protected static final String EMPTY_LIST_ERROR_MSG = "The list is empty currently ( ̄3 ̄)a";
+
+ @Override
+ public String toString(){
+ return EMPTY_LIST_ERROR_MSG;
+ }
+
+}
diff --git a/src/main/java/exceptions/IllegalFormatException.java b/src/main/java/exceptions/IllegalFormatException.java
new file mode 100644
index 000000000..cd57ac25d
--- /dev/null
+++ b/src/main/java/exceptions/IllegalFormatException.java
@@ -0,0 +1,11 @@
+package exceptions;
+
+public class IllegalFormatException extends DukeExceptions {
+ protected static final String FORMAT_ERROR_MSG =
+ "The format is incorrect! Can you please check your input again? ●ω●";
+
+ @Override
+ public String toString() {
+ return FORMAT_ERROR_MSG;
+ }
+}
diff --git a/src/main/java/exceptions/IllegalIndexException.java b/src/main/java/exceptions/IllegalIndexException.java
new file mode 100644
index 000000000..48ab30903
--- /dev/null
+++ b/src/main/java/exceptions/IllegalIndexException.java
@@ -0,0 +1,11 @@
+package exceptions;
+
+public class IllegalIndexException extends DukeExceptions {
+ protected static final String ILLEGAL_INDEX_ERROR_MSG = "I can't find the task from the list (°ー°〃) Please check your index again";
+
+ @Override
+ public String toString(){
+ return ILLEGAL_INDEX_ERROR_MSG;
+ }
+
+}
diff --git a/src/main/java/exceptions/IllegalInstructionException.java b/src/main/java/exceptions/IllegalInstructionException.java
new file mode 100644
index 000000000..1428b057c
--- /dev/null
+++ b/src/main/java/exceptions/IllegalInstructionException.java
@@ -0,0 +1,11 @@
+package exceptions;
+
+public class IllegalInstructionException extends DukeExceptions {
+ protected static final String INSTRUCTION_ERROR_MSG =
+ "…(⊙_⊙;)… Sorry I can't understand. Please check the user guide for acceptable instructions";
+
+ @Override
+ public String toString() {
+ return INSTRUCTION_ERROR_MSG;
+ }
+}
diff --git a/src/main/java/exceptions/IllegalReadingAction.java b/src/main/java/exceptions/IllegalReadingAction.java
new file mode 100644
index 000000000..18ba951cc
--- /dev/null
+++ b/src/main/java/exceptions/IllegalReadingAction.java
@@ -0,0 +1,11 @@
+package exceptions;
+
+public class IllegalReadingAction extends DukeExceptions {
+ protected static final String READING_FILE_ERROR_MSG =
+ "Sorry, there's something wrong when loading task, please try again later QnQ";
+
+ @Override
+ public String toString() {
+ return READING_FILE_ERROR_MSG;
+ }
+}
diff --git a/src/main/java/exceptions/IllegalSavingAction.java b/src/main/java/exceptions/IllegalSavingAction.java
new file mode 100644
index 000000000..e83f96bbd
--- /dev/null
+++ b/src/main/java/exceptions/IllegalSavingAction.java
@@ -0,0 +1,11 @@
+package exceptions;
+
+public class IllegalSavingAction extends DukeExceptions {
+ protected static final String SAVING_FILE_ERROR_MSG =
+ "Sorry, there's something wrong when saving task, please try again later QnQ";
+
+ @Override
+ public String toString() {
+ return SAVING_FILE_ERROR_MSG;
+ }
+}
diff --git a/src/main/java/exceptions/IllegalTimeFormatException.java b/src/main/java/exceptions/IllegalTimeFormatException.java
new file mode 100644
index 000000000..b573525a5
--- /dev/null
+++ b/src/main/java/exceptions/IllegalTimeFormatException.java
@@ -0,0 +1,12 @@
+package exceptions;
+
+public class IllegalTimeFormatException extends DukeExceptions {
+ protected static final String FORMAT_ERROR_MSG =
+ "The time format is incorrect! Can you please check your input again? ( ̄~ ̄;) " +
+ "You can check the manual to find out acceptable time format!";
+
+ @Override
+ public String toString() {
+ return FORMAT_ERROR_MSG;
+ }
+}
diff --git a/src/main/java/exceptions/KeywordLossException.java b/src/main/java/exceptions/KeywordLossException.java
new file mode 100644
index 000000000..505587370
--- /dev/null
+++ b/src/main/java/exceptions/KeywordLossException.java
@@ -0,0 +1,11 @@
+package exceptions;
+
+public class KeywordLossException extends DukeExceptions {
+ protected static final String KEYWORD_LOSS_ERROR_MSG =
+ "Did you specify the keyword?∑(っ °Д °;)っ";
+
+ @Override
+ public String toString() {
+ return KEYWORD_LOSS_ERROR_MSG;
+ }
+}
diff --git a/src/main/java/exceptions/TaskIndexLossException.java b/src/main/java/exceptions/TaskIndexLossException.java
new file mode 100644
index 000000000..cb9c52f4b
--- /dev/null
+++ b/src/main/java/exceptions/TaskIndexLossException.java
@@ -0,0 +1,11 @@
+package exceptions;
+
+public class TaskIndexLossException extends DukeExceptions {
+ protected static final String INDEX_LOSS_ERROR_MSG =
+ "Did you specify the index?∑(っ °Д °;)っ";
+
+ @Override
+ public String toString() {
+ return INDEX_LOSS_ERROR_MSG;
+ }
+}
diff --git a/src/main/java/exceptions/TaskNameLossException.java b/src/main/java/exceptions/TaskNameLossException.java
new file mode 100644
index 000000000..0254d272e
--- /dev/null
+++ b/src/main/java/exceptions/TaskNameLossException.java
@@ -0,0 +1,11 @@
+package exceptions;
+
+public class TaskNameLossException extends DukeExceptions {
+ protected static final String INDEX_LOSS_ERROR_MSG =
+ "Did you specify the name of the task?∑(っ °Д °;)っ";
+
+ @Override
+ public String toString() {
+ return INDEX_LOSS_ERROR_MSG;
+ }
+}
diff --git a/src/main/java/tasks/Deadline.java b/src/main/java/tasks/Deadline.java
new file mode 100644
index 000000000..b753cb3ef
--- /dev/null
+++ b/src/main/java/tasks/Deadline.java
@@ -0,0 +1,34 @@
+package tasks;
+
+import java.util.Date;
+
+import time.Time;
+
+public class Deadline extends Task {
+ protected Date by;
+ protected String byString;
+ private Time timeConverter;
+
+ /**
+ * Initializes a deadline task by given task name and deadline
+ * @param name the name of the task
+ * @param byString the deadline of the task in String format
+ */
+ public Deadline(String name, String byString) {
+ super(name);
+ this.byString = byString;
+ timeConverter = new Time(byString);
+ by = timeConverter.getNewDate();
+ setListName();
+ }
+
+ @Override
+ public void setListName() {
+ if (!isDone) {
+ this.listName = "[D]" + this.unmarkedStatus + this.taskName + "(by: " + byString + ")";
+ } else {
+ this.listName = "[D]" + this.markedStatus + this.taskName + "(by: " + byString + ")";
+ }
+ }
+
+}
diff --git a/src/main/java/tasks/Event.java b/src/main/java/tasks/Event.java
new file mode 100644
index 000000000..ee656c4a8
--- /dev/null
+++ b/src/main/java/tasks/Event.java
@@ -0,0 +1,35 @@
+package tasks;
+
+import java.util.Date;
+
+import time.Time;
+
+public class Event extends Task {
+ protected Date at;
+ protected String atString;
+ private Time timeConverter;
+
+ /**
+ * Initializes an event task by given task name and event time
+ * @param name the name of the event task
+ * @param atString the time of the task in String format
+ */
+ public Event(String name, String atString) {
+ super(name);
+ this.atString = atString;
+ timeConverter = new Time(atString);
+ at = timeConverter.getNewDate();
+ setListName();
+ }
+
+ @Override
+ public void setListName() {
+ if (!isDone) {
+ this.listName = "[E]" + this.unmarkedStatus + this.taskName + "(at: " + atString + ")";
+ } else {
+ this.listName = "[E]" + this.markedStatus + this.taskName + "(at: " + atString + ")";
+ }
+ }
+
+
+}
diff --git a/src/main/java/tasks/Storage.java b/src/main/java/tasks/Storage.java
new file mode 100644
index 000000000..9dfffd1a7
--- /dev/null
+++ b/src/main/java/tasks/Storage.java
@@ -0,0 +1,198 @@
+package tasks;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.util.ArrayList;
+
+import exceptions.CreatingFileException;
+import exceptions.DukeExceptions;
+import exceptions.IllegalReadingAction;
+import exceptions.IllegalSavingAction;
+import time.Time;
+
+public class Storage {
+ protected static final String FILE_NAME = "data/duke.txt";
+ protected static final String DONE = "X";
+ protected static final String TODO = "T";
+ protected static final String EVENT = "E";
+ protected static final String DEADLINE = "D";
+ private static final ArrayList Tasks = new ArrayList<>();
+ private Time timeChecker;
+ private TaskManager manager;
+
+ public int getSize() {
+ return Tasks.size();
+ }
+
+ /**
+ * Adds a new task to the array list
+ * @param newTask a task object
+ */
+ public void add(Task newTask) {
+ Tasks.add(newTask);
+ }
+ public Task get(int indexOfTask) {
+ return Tasks.get(indexOfTask);
+ }
+
+ /**
+ * Deletes a task from the list
+ * @param indexOfTask the index of the task that needs to be deleted
+ */
+ public void remove(int indexOfTask) {
+ Tasks.remove(indexOfTask);
+ }
+
+ /**
+ * Writes and saves the tasks to an external file
+ * @throws DukeExceptions if the action fails
+ */
+ public void saveTask() throws DukeExceptions {
+ StringBuilder content = new StringBuilder();
+ for (Task task : Tasks) {
+ content.append(task.getListName());
+ content.append("\n");
+ }
+ try {
+ File file = new File(FILE_NAME);
+ FileWriter writeStream = new FileWriter(file);
+ writeStream.write(content.toString());
+ writeStream.close();
+ } catch (Exception e) {
+ throw new IllegalSavingAction();
+ }
+ }
+
+ /**
+ * Parses the input from loading task and rejects redundant characters for further loading action
+ * @param listName the raw input of task from the external file
+ * @return the array of key information of task
+ */
+ public String[] parseInput(String listName) {
+ String info = listName.replaceAll("]", "\\|");
+ info = info.replaceAll("\\[", "");
+ info = info.replaceAll("\\(", "\\|");
+ info = info.replaceAll("\\)", "");
+ String[] parsedInput = info.split("\\|");
+ return parsedInput;
+ }
+
+ /**
+ * Checks the status of the task and mark when loading
+ * @param task The task that is going to be added to the list
+ * @param status the status of task from the external file
+ */
+ public void mark(Task task, String status) {
+ if (status.equals(DONE)) {
+ task.mark();
+ }
+ }
+
+ /**
+ * Loads tasks from external file
+ * @throws DukeExceptions if the action fails
+ */
+ public void loadTask() throws DukeExceptions {
+ //Reads input from external file line by line (task by task)
+ try (BufferedReader loadData = new BufferedReader(new FileReader(FILE_NAME))) {
+ String listName;
+ while ((listName = loadData.readLine()) != null) {
+ //parses input into key information array
+ String[] keyInfo = this.parseInput(listName);
+ //imports task according to the information
+ importTask(keyInfo);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new IllegalReadingAction();
+ }
+
+ }
+
+ /**
+ * Imports tasks according to the key information array
+ * @param keyInfo the key information array from parsing input from external file
+ * @throws DukeExceptions if the action fails
+ */
+ private void importTask(String[] keyInfo) throws DukeExceptions {
+ switch (keyInfo[0]) {
+ case TODO:
+ importTodoTask(keyInfo);
+ break;
+ case EVENT:
+ importEvent(keyInfo);
+ break;
+ case DEADLINE:
+ importDeadline(keyInfo);
+ break;
+ default:
+ throw new IllegalReadingAction();
+ }
+ }
+
+ /**
+ * Imports deadline task according to the key information array
+ * @param keyInfo the key information array from parsing input from external file
+ * @throws DukeExceptions if time converting fails
+ */
+ private void importDeadline(String[] keyInfo) throws DukeExceptions {
+ String oldTimeString;
+ String newTimeString;
+ oldTimeString = keyInfo[3].replace("by: ", "");
+ timeChecker = new Time(oldTimeString);
+ timeChecker.check();
+ newTimeString = timeChecker.getDateString();
+ Deadline newDeadline = new Deadline(keyInfo[2], newTimeString);
+ Tasks.add(newDeadline);
+ mark(newDeadline, keyInfo[1]);
+ }
+
+ /**
+ * Imports event task according to the key information array
+ * @param keyInfo the key information array from parsing input from external file
+ * @throws DukeExceptions if time converting fails
+ */
+ private void importEvent(String[] keyInfo) throws DukeExceptions {
+ String newTimeString;
+ String oldTimeString;
+ oldTimeString = keyInfo[3].replace("at: ", "");
+ timeChecker = new Time(oldTimeString);
+ timeChecker.check();
+ newTimeString = timeChecker.getDateString();
+ Event newEvent = new Event(keyInfo[2], newTimeString);
+ Tasks.add(newEvent);
+ mark(newEvent, keyInfo[1]);
+ }
+
+ /**
+ * Imports todo task according to the key information array
+ * @param keyInfo the key information array from parsing input from external file
+ */
+ private void importTodoTask(String[] keyInfo) {
+ ToDo newToDo = new ToDo(keyInfo[2]);
+ Tasks.add(newToDo);
+ mark(newToDo, keyInfo[1]);
+ }
+
+ /**
+ * Creates a external file for saving and loading task
+ * @throws DukeExceptions if the action fails
+ */
+ public void createFile() throws DukeExceptions {
+ try {
+ File file = new File(FILE_NAME);
+ if (!file.exists()) {
+ File dir = new File(file.getParent());
+ dir.mkdirs();
+ file.createNewFile();
+ }
+ } catch (Exception e) {
+ throw new CreatingFileException();
+ }
+ }
+
+}
+
+
diff --git a/src/main/java/tasks/Task.java b/src/main/java/tasks/Task.java
new file mode 100644
index 000000000..fe0d4582d
--- /dev/null
+++ b/src/main/java/tasks/Task.java
@@ -0,0 +1,52 @@
+package tasks;
+
+public class Task {
+ protected String unmarkedStatus = "[ ]";
+ protected String markedStatus = "[X]";
+ protected String taskName; //the name of the task
+ protected boolean isDone = false;
+ protected String listName; //the name of the task that appears when listing and searching
+
+ /**
+ * Initialize a task object
+ * @param name the name of the task
+ */
+ public Task(String name) {
+ this.taskName = name;
+ this.isDone = false;
+ setListName();
+ }
+
+ public String getTaskName() {
+ return this.taskName;
+ }
+
+ public void setListName() {
+ if (!isDone) {
+ this.listName = this.unmarkedStatus + this.taskName;
+ } else {
+ this.listName = this.markedStatus + this.taskName;
+ }
+ }
+
+ public String getListName() {
+ return this.listName;
+ }
+
+ /**
+ * Marks task as done and change list name
+ */
+ public void mark() {
+ this.isDone = true;
+ this.setListName();
+ }
+
+ /**
+ * Marks tasks as undone and change list name
+ */
+ public void unmark() {
+ this.isDone = false;
+ this.setListName();
+ }
+
+}
diff --git a/src/main/java/tasks/TaskManager.java b/src/main/java/tasks/TaskManager.java
new file mode 100644
index 000000000..416696bf8
--- /dev/null
+++ b/src/main/java/tasks/TaskManager.java
@@ -0,0 +1,209 @@
+package tasks;
+
+import exceptions.DukeExceptions;
+import exceptions.EmptyListException;
+import exceptions.IllegalIndexException;
+
+public class TaskManager {
+ //response messages of different action
+ protected static final String ADD_RESPONSE = "ψ(._. )> Got it. I've added this task:\n";
+ protected static final String MARK_RESPONSE = "ψ(._. )> Nice! I've marked this task as done:\n";
+ protected static final String UNMARK_RESPONSE = "ψ(._. )> OK, I've marked this task as not done yet:\n";
+ protected static final String LIST_RESPONSE = "o(≧v≦)o Here are the tasks in your list:\n";
+ protected static final String DELETE_RESPONSE = "ψ(._. )> Okay! I've deleted this task:\n";
+ protected static final String NOT_FOUND_RESPONSE = "( ̄ε ̄;) Sorry, I can't find any result from the list.";
+ protected static final String FOUND_RESPONSE = "o(≧v≦)o Here are the matching tasks in your list:";
+ private Storage tasks = new Storage();
+ /**
+ * Generates a message that contains the number of tasks in the list currently
+ * @return the message that contains the number of tasks in the list
+ */
+ public String taskNumberMsg() {
+ int taskNumber = tasks.getSize();
+ StringBuilder content = new StringBuilder();
+ content.append("Now you have ").append(taskNumber).append(" tasks in your list.");
+ return content.toString();
+ }
+
+ /**
+ * Saves the tasks in the list to the external file
+ * @throws DukeExceptions if the action fails
+ */
+ public void saveTask() throws DukeExceptions {
+ tasks.saveTask();
+ }
+
+ /**
+ * Loads the tasks to the arraylist from external file
+ * @throws DukeExceptions if the action fails
+ */
+ public void loadTask() throws DukeExceptions {
+ tasks.loadTask();
+ }
+
+ /**
+ * Creates an external file for saving and loading task if there's no such file in to correspond folder
+ * @throws DukeExceptions if the action fails
+ */
+ public void createFile() throws DukeExceptions {
+ tasks.createFile();
+ }
+ /**
+ * Adds a deadline task to the list
+ * @param name refers to the name of the task
+ * @param by refers to the deadline of the task
+ * @return content.toString() the message that is going to display on the user interface, contains the
+ * response of successful action, information of the new task and the number of task in the list after
+ * adding.
+ */
+ public String addDeadline(String name, String by) {
+ Deadline newDeadline = new Deadline(name, by);
+ tasks.add(newDeadline);
+ return ADD_RESPONSE + newDeadline.getListName()
+ + "\n" + this.taskNumberMsg();
+ }
+
+ /**
+ * Adds an event task to the list
+ * @param name refers to the name of the task
+ * @param at refers to the happening time of the event
+ * @return content.toString() the message that is going to display on the user interface, contains the
+ * response of successful action, information of the new task and the number of task in the list after
+ * adding.
+ */
+ public String addEvent(String name, String at) {
+ StringBuilder content = new StringBuilder(ADD_RESPONSE);
+ Event newEvent = new Event(name, at);
+ tasks.add(newEvent);
+ content.append(newEvent.getListName()).append("\n").append(this.taskNumberMsg());
+ return content.toString();
+ }
+
+ /**
+ * Adds a todo task to the list
+ * @param name refers to the name of the todo task
+ * @return content.toString() the message that is going to display on the user interface, contains the
+ * response of successful action, information of the new task and the number of task in the list after
+ * adding.
+ */
+ public String addToDo(String name) {
+ StringBuilder content = new StringBuilder(ADD_RESPONSE);
+ ToDo newToDo = new ToDo(name);
+ tasks.add(newToDo);
+ content.append(newToDo.getListName()).append("\n").append(this.taskNumberMsg());
+ return content.toString();
+ }
+
+ /**
+ * Lists all tasks in the list with adding time order
+ * @return content.toString() the message that is going to display on the user interface, contains the
+ * response of successful action and the information of the all the task in the list.
+ * @throws DukeExceptions if there's no task in the list currently
+ */
+ public String listTask() throws DukeExceptions {
+ //checks if there's any task in the list, otherwise throws an exception
+ if (tasks.getSize() == 0) {
+ throw new EmptyListException();
+ } else {
+ StringBuilder content = new StringBuilder(LIST_RESPONSE);
+ for (int i = 0; i < tasks.getSize(); i++) {
+ String index = String.valueOf(i + 1);
+ String name = index + ". " + tasks.get(i).getListName();
+ content.append(name);
+ if (i < tasks.getSize() - 1) {
+ content.append("\n");
+ }
+ }
+ return content.toString();
+ }
+
+ }
+
+ /**
+ * Marks specific task in the list as done
+ * @param indexOfTask refers to the indexOfTask of the task in adding time order
+ */
+ public String markTask(int indexOfTask) throws DukeExceptions {
+ if (isOutOfBoundary(indexOfTask)) {
+ throw new IllegalIndexException();
+ } else {
+ tasks.get(indexOfTask - 1).mark();
+ return MARK_RESPONSE + tasks.get(indexOfTask - 1).listName;
+ }
+ }
+
+ /**
+ * Unmarks specific task in the list as undone
+ * @param indexOfTask refers to the indexOfTask of the task in adding time order
+ */
+ public String unmarkTask(int indexOfTask) throws DukeExceptions {
+ //Checks whether the given task index is out of the range
+ if (isOutOfBoundary(indexOfTask)) {
+ throw new IllegalIndexException();
+ } else {
+ tasks.get(indexOfTask - 1).unmark();
+ return UNMARK_RESPONSE + tasks.get(indexOfTask - 1).listName;
+
+ }
+ }
+
+ /**
+ * Checks whether the given task index is out of the range
+ * @param indexOfTask the index of the task that need to be checked
+ * @return True if the index is out of boundaries
+ */
+ private boolean isOutOfBoundary(int indexOfTask) {
+ return indexOfTask < 1 || indexOfTask > tasks.getSize();
+ }
+
+ /**
+ * Delete the specific task by given index
+ * @param indexOfTask the index of the task that need to be deleted
+ * @return content.toString() the message that is going to display on the user interface, contains the
+ * response of successful action, information of the deleted task and the number of task in the list after
+ * deleting.
+ * @throws DukeExceptions if the task is not appeared in the list
+ */
+ public String deleteTask(int indexOfTask) throws DukeExceptions {
+ //Checks whether the given task index is out of the range
+ if (isOutOfBoundary(indexOfTask)) {
+ throw new IllegalIndexException();
+ } else {
+ String content = DELETE_RESPONSE + tasks.get(indexOfTask - 1).listName;
+ tasks.remove(indexOfTask - 1);
+ content += "\n" + this.taskNumberMsg();
+ return content;
+ }
+ }
+
+ /**
+ * Searches the matching tasks and lists them by the keyword given by user
+ * @param keywords the keyword given by user
+ * @return content.toString() the message that is going to display on the user interface, contains the
+ * response of successful action and the information of the matching tasks.
+ * @throws DukeExceptions if the list is empty
+ */
+ public String searchTask(String keywords) throws DukeExceptions {
+ //checks if there's any task in the list, otherwise throws an exception
+ if (tasks.getSize() == 0) {
+ throw new EmptyListException();
+ } else {
+ StringBuilder content = new StringBuilder();
+ int count = 0; //count if there's any matching task
+ for (int i = 0; i < tasks.getSize(); i++) {
+ if (tasks.get(i).getTaskName().contains(keywords)) {
+ content.append("\n");
+ String index = String.valueOf(count + 1);
+ String name = index + ". " + tasks.get(i).getListName();
+ content.append(name);
+ count++;
+ }
+ }
+ if (count == 0) {
+ return NOT_FOUND_RESPONSE;
+ }
+ return FOUND_RESPONSE + content;
+ }
+ }
+
+}
diff --git a/src/main/java/tasks/ToDo.java b/src/main/java/tasks/ToDo.java
new file mode 100644
index 000000000..591a09fcf
--- /dev/null
+++ b/src/main/java/tasks/ToDo.java
@@ -0,0 +1,21 @@
+package tasks;
+
+public class ToDo extends Task {
+
+ /**
+ * Initializes a todo task by given task name
+ * @param name the name of the todo task
+ */
+ public ToDo(String name) {
+ super(name);
+ }
+
+ @Override
+ public void setListName() {
+ if (!isDone) {
+ this.listName = "[T]" + this.unmarkedStatus + this.taskName;
+ } else {
+ this.listName = "[T]" + this.markedStatus + this.taskName;
+ }
+ }
+}
diff --git a/src/main/java/time/DateFormatChecker.java b/src/main/java/time/DateFormatChecker.java
new file mode 100644
index 000000000..f4fab5b46
--- /dev/null
+++ b/src/main/java/time/DateFormatChecker.java
@@ -0,0 +1,40 @@
+package time;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Check the format of the input date and convert to standart format date string
+ */
+public class DateFormatChecker extends Time {
+ //Standard format for printing task information
+ private static final SimpleDateFormat stdFormatter = new SimpleDateFormat("MMM dd yyyy");
+ //Acceptable format for time converting
+ private static final List formatStrings =
+ Arrays.asList("M/d/y", "M-d-y", "y-M-d", "y/M/d", "MMM dd yyyy", "M/d", "M-d", "d/M", "d-M");
+ /**
+ * Initializes a checker to check whether the date string is in acceptable format
+ * @param date the string of date
+ */
+ public DateFormatChecker(String date) {
+ super(date);
+ //Try to convert the date to check if the time is in any of the acceptable formats
+ for (String formatString : formatStrings) {
+ try {
+ SimpleDateFormat formatter = new SimpleDateFormat(formatString);
+ formatter.setLenient(false);
+ newDate = formatter.parse(date);
+ dateString = stdFormatter.format(newDate);
+ isValidDate = true;
+ break;
+ } catch (ParseException e) {
+ //Time is not in this format if the exception is caught. Try next one to see if it is in
+ //acceptable format
+ }
+ }
+ }
+
+}
+
diff --git a/src/main/java/time/DateTimeFormatChecker.java b/src/main/java/time/DateTimeFormatChecker.java
new file mode 100644
index 000000000..64195c513
--- /dev/null
+++ b/src/main/java/time/DateTimeFormatChecker.java
@@ -0,0 +1,39 @@
+package time;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Check the format of the input date and time and convert to standart format date string
+ */
+public class DateTimeFormatChecker extends Time {
+ private static final List formatStrings =
+ Arrays.asList("M/d/y H:m", "M/d/y H", "M-d-y H:m", "y-M-d H:m", "y/M/d H:m", "MMM dd yyyy H:m",
+ "M/d H:m", "M-d H:m", "d/M H:m", "d-M H:m");
+
+ private static final SimpleDateFormat stdFormatter = new SimpleDateFormat("MMM dd yyyy HH:mm");
+
+ /**
+ * Initializes a checker to check whether the date with time string is in acceptable format
+ * @param date the string of date with time
+ */
+ public DateTimeFormatChecker(String date) {
+ super(date);
+ for (String formatString: formatStrings) {
+ try {
+ SimpleDateFormat formatter = new SimpleDateFormat(formatString);
+ formatter.setLenient(false);
+ newDate = formatter.parse(date);
+ dateString = stdFormatter.format(newDate);
+ isValidTime = true;
+ break;
+ } catch (ParseException e) {
+ //Time is not in this format if the exception is caught. Try next one to see if it is in
+ //acceptable format
+ }
+ }
+ }
+}
+
diff --git a/src/main/java/time/Time.java b/src/main/java/time/Time.java
new file mode 100644
index 000000000..148e6d656
--- /dev/null
+++ b/src/main/java/time/Time.java
@@ -0,0 +1,51 @@
+package time;
+
+import java.util.Date;
+
+import exceptions.DukeExceptions;
+import exceptions.IllegalTimeFormatException;
+
+public class Time {
+ protected static boolean isValidDate;
+ protected static boolean isValidTime;
+ protected static Date newDate;
+ protected static String dateString;
+ protected boolean isValid;
+ protected String oldDate;
+ private DateTimeFormatChecker checkTime;
+ private DateFormatChecker checkDate;
+
+ /**
+ * Initializes a time object for time format checking and converting
+ * @param date the date for checking and converting in String format
+ */
+ public Time(String date) {
+ oldDate = date;
+ isValidDate = false;
+ isValidTime = false;
+ isValid = false;
+ }
+
+ /**
+ * Checks whether the string is a date without time or a date with time
+ * @throws DukeExceptions if the string fails in checking
+ */
+ public void check() throws DukeExceptions {
+ if (oldDate.contains(":")) { //the string contains time, may be a date with time
+ checkTime = new DateTimeFormatChecker(oldDate);
+ } else { //the string does not contain time, may be a date without time
+ checkDate = new DateFormatChecker(oldDate);
+ }
+ //throws exceptions if the string is neither date with time nor date without time
+ if (!isValidTime && !isValidDate) {
+ throw new IllegalTimeFormatException();
+ }
+ }
+
+ public Date getNewDate() {
+ return newDate;
+ }
+ public String getDateString() {
+ return dateString;
+ }
+}
diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT
index 657e74f6e..8113a1947 100644
--- a/text-ui-test/EXPECTED.TXT
+++ b/text-ui-test/EXPECTED.TXT
@@ -1,7 +1,67 @@
-Hello from
- ____ _
-| _ \ _ _| | _____
-| | | | | | | |/ / _ \
-| |_| | |_| | < __/
-|____/ \__,_|_|\_\___|
-
+Hello! I'm Duke :P
+What can I do for you?
+-------------------------------------
+The list is empty currently ( ̄3 ̄)a
+-------------------------------------
+ψ(._. )> Got it. I've added this task:
+[D][ ]CS2113 Quiz (by: Jun. 20 2019 23:59)
+Now you have 1 tasks in your list.
+-------------------------------------
+ψ(._. )> Got it. I've added this task:
+[E][ ]MA2101 Quiz (at: Jun. 30 2019)
+Now you have 2 tasks in your list.
+-------------------------------------
+ψ(._. )> Got it. I've added this task:
+[T][ ]Homework
+Now you have 3 tasks in your list.
+-------------------------------------
+o(≧v≦)o Here are the tasks in your list:
+1. [D][ ]CS2113 Quiz (by: Jun. 20 2019 23:59)
+2. [E][ ]MA2101 Quiz (at: Jun. 30 2019)
+3. [T][ ]Homework
+-------------------------------------
+ψ(._. )> Nice! I've marked this task as done:
+[D][X]CS2113 Quiz (by: Jun. 20 2019 23:59)
+-------------------------------------
+ψ(._. )> Nice! I've marked this task as done:
+[E][X]MA2101 Quiz (at: Jun. 30 2019)
+-------------------------------------
+o(≧v≦)o Here are the tasks in your list:
+1. [D][X]CS2113 Quiz (by: Jun. 20 2019 23:59)
+2. [E][X]MA2101 Quiz (at: Jun. 30 2019)
+3. [T][ ]Homework
+-------------------------------------
+ψ(._. )> OK, I've marked this task as not done yet:
+[E][ ]MA2101 Quiz (at: Jun. 30 2019)
+-------------------------------------
+o(≧v≦)o Here are the tasks in your list:
+1. [D][X]CS2113 Quiz (by: Jun. 20 2019 23:59)
+2. [E][ ]MA2101 Quiz (at: Jun. 30 2019)
+3. [T][ ]Homework
+-------------------------------------
+o(≧v≦)o Here are the matching tasks in your list:
+1. [D][X]CS2113 Quiz (by: Jun. 20 2019 23:59)
+2. [E][ ]MA2101 Quiz (at: Jun. 30 2019)
+-------------------------------------
+The format is incorrect! Can you please check your input again? ●ω●
+-------------------------------------
+The time format is incorrect! Can you please check your input again? ( ̄~ ̄;) You can check the manual to find out acceptable time format!
+-------------------------------------
+The time format is incorrect! Can you please check your input again? ( ̄~ ̄;) You can check the manual to find out acceptable time format!
+-------------------------------------
+ψ(._. )> Got it. I've added this task:
+[D][ ]CS2106 midterm (by: Apr. 30 2019 02:03)
+Now you have 4 tasks in your list.
+-------------------------------------
+o(≧v≦)o Here are the tasks in your list:
+1. [D][ ]CS2113 Quiz (by: Jun. 20 2019 23:59)
+2. [E][ ]MA2101 Quiz (at: Jun. 30 2019)
+3. [T][ ]Homework
+4. [D][ ]CS2106 midterm (by: Apr. 30 2019 02:03)
+-------------------------------------
+ψ(._. )> Okay! I've deleted this task:
+[D][ ]CS2106 midterm (by: Apr. 30 2019 02:03)
+Now you have 3 tasks in your list.
+-------------------------------------
+Bye. Hope to see you again soon! ;)
+-------------------------------------
\ No newline at end of file
diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt
index e69de29bb..e7f29b2f3 100644
--- a/text-ui-test/input.txt
+++ b/text-ui-test/input.txt
@@ -0,0 +1,16 @@
+list
+deadline CS2113 Quiz /by 2019/06/20 23:59
+event MA2101 Quiz /at 2019-6-30
+todo Homework
+list
+mark 1
+mark 2
+list
+unmark 2
+list
+find Quiz
+deadline CS2106 midterm /at 2019-4-31
+deadline CS2106 midterm /by 2019-4-31
+deadline CS2106 midterm /by 2019-4-30 25:61
+deadline CS2106 midterm /by 2019-4-30 2:3
+bye
\ No newline at end of file
diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat
index 087374464..843446f1a 100644
--- a/text-ui-test/runtest.bat
+++ b/text-ui-test/runtest.bat
@@ -14,7 +14,7 @@ IF ERRORLEVEL 1 (
)
REM no error here, errorlevel == 0
-REM run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT
+REM run the program, feed controller from input.txt file and redirect the output to the ACTUAL.TXT
java -classpath ..\bin Duke < input.txt > ACTUAL.TXT
REM compare the output to the expected output
diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh
index c9ec87003..09773a4f8 100644
--- a/text-ui-test/runtest.sh
+++ b/text-ui-test/runtest.sh
@@ -22,12 +22,8 @@ fi
# run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT
java -classpath ../bin Duke < input.txt > ACTUAL.TXT
-# convert to UNIX format
-cp EXPECTED.TXT EXPECTED-UNIX.TXT
-dos2unix ACTUAL.TXT EXPECTED-UNIX.TXT
-
# compare the output to the expected output
-diff ACTUAL.TXT EXPECTED-UNIX.TXT
+diff ACTUAL.TXT EXPECTED.TXT
if [ $? -eq 0 ]
then
echo "Test result: PASSED"