diff --git a/README.md b/README.md
index 8715d4d91..db4a5e14b 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,131 @@
-# 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 for chatbot "Apple"
+
+Chatbot Apple is an app to manage tasks, optimised for use through a Command Line Interface (CLI).
+
+## Quick Start
+1. Ensure Java 11 or above is installed in your computer
+2. Download `ip.jar` from [here](https://github.com/hongyijie06/ip/releases/tag/A-Jar)
+3. Open a command terminal, `cd` into the folder with the jar file and use the `java -jar ip.jar` command to run the application.
+
+A CLI similar to the picture below should appear in a few seconds. Note how the app returns the path to which the list of tasks is saved on the local computer.
+
+4. Type the command into the command line and press Enter to execute it. e.g. typing list and pressing Enter will list the current tasks.
+Some example commands you can try:
+
+- `todo tutorial`: Adds task "tutorial" to the list
+- `deadline return book by 4pm`: Adds task "return book" nd deadline "4pm" to the list
+- `list`: Lists all tasks
+- `bye`: Exits the app
+
+5. Refer to the Features below for more details on each command.
+
+## Features
+
+[!NOTE]
+> Words in `UPPER_CASE` are parameters to be supplied by the user. e.g. in `delete INDEX`, `INDEX` is a parameter which can be used as `delete 3`
+
+## Listing tasks: `list`
+Lists all tasks in the task list.
+
+Format: `list`
+
+## Add tasks
+### Add todo : `todo`
+Adds task of type todo to the list of tasks
+
+Format: `todo DESCRIPTION`
+
+Examples:
+- `todo tutorial` Adds task `tutorial` to the list of tasks
+- `todo watch lecture` Adds task `watch lecture` to the list of tasks
+
+ADD PIC HERE
+
+### Add deadline: `deadline`
+Adds task of type deadline to the list of tasks
+
+Format: `deadline DESCRIPTION by DEADLINE`
+
+Examples:
+- `deadline return book by 4pm` Adds task `return book` with deadline `4pm` to the list of tasks
+- `deadline submit report by 7pm` Adds task `submit report` with deadline `7pm` to the list of tasks
+
+ADD PIC HERE
+
+### Add event: `event`
+Adds task of type event to the list of tasks
+
+Format: `event DESCRIPTION from START to END`
+
+Examples:
+- `event Math exam from 2pm to 4pm` Adds task `Math exam` with timeline `2pm` to `4pm` to the list of tasks
+- `event project group meeting from 11am to 1pm` Adds task `project group meeting` with timeline `11am` to `1pm` to the list of tasks
+
+ADD PIC HERE
+
+## Delete tasks: `delete`
+Deletes task from the list of tasks
+
+Format: `delete INDEX`
+
+- Deletes task at the specified `INDEX`.
+- The index refers to the index of the task in the list of tasks.
+- The index must be a positive integer.
+
+Examples:
+- `delete 3` Deletes third task in the list
+- `delete 5` Deletes fifth task in the list
+
+## Mark tasks as done: `mark`
+Marks tasks as completed
+
+Format: `mark INDEX`
+
+- Marks task as done at the specified `INDEX`.
+- The index refers to the index of the task in the list of tasks.
+- The index must be a positive integer.
+
+Examples:
+- `mark 1` Marks first task in the list as done
+- `mark 6` Marks sixth task in the list as done
+
+## Unmark tasks: `unmark`
+Marks tasks as undone
+
+Format: `unmark INDEX`
+
+- Marks task as not done at the specified `INDEX`.
+- The index refers to the index of the task in the list of tasks.
+- The index must be a positive integer.
+
+Examples:
+- `unmark 1` Marks first task in the list as notdone
+- `unmark 2` Marks second task in the list as not done
+
+## Find Keywords: `find`
+Filters list of tasks to those containing the keyword the user wants to find
+
+Format: `find KEYWORD`
+
+Examples:
+- `find book` CLI returns a list with all the tasks with the `KEYWORD` `book`.
+- `find tutorial` CLI returns a list with all the tasks with the `KEYWORD` `tutorial`.
+
+## Exit app: `bye`
+Exits the chatbot
+
+Format: `bye`
+
+## Command Summary
+
+| Command | Format, Examples |
+| ------- | --------------- |
+| `list` | `list` |
+| `todo` | `todo DESCRIPTION` e.g. `todo tutorial` |
+| `deadline` | `deadline DESCRIPTION by DEADLINE` e.g. `deadline return book by 4pm` |
+| `event` | `event DESCRIPTION from START to END` e.g. `event Math exam from 2pm to 4pm` |
+| `delete` | `delete INDEX` e.g. `delete 3` |
+| `mark` | `mark INDEX` e.g. `mark 2` |
+| `unmark` | `unmark INDEX` e.g. `unmark 1` |
+| `find` | `find KEYWORD` e.g. `find book` |
+| `bye` | `bye` |
\ No newline at end of file
diff --git a/docs/README.md b/docs/README.md
index 8077118eb..096fe006d 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,29 +1,122 @@
-# User Guide
+# User Guide for chatbot "Apple"
-## Features
+Chatbot Apple is an app to manage tasks, optimised for use through a Command Line Interface (CLI).
-### Feature-ABC
+## Quick Start
+1. Ensure Java 11 or above is installed in your computer
+2. Download `ip.jar` from [here](https://github.com/hongyijie06/ip/releases/tag/A-Release)
+3. Open a command terminal, `cd` into the folder with the jar file and use the `java -jar ip.jar` command to run the application.
+4. Type the command into the command line and press Enter to execute it. e.g. typing list and pressing Enter will list the current tasks.
+ Some example commands you can try:
-Description of the feature.
+ - `todo tutorial`: Adds task "tutorial" to the list
+ - `deadline return book by 4pm`: Adds task "return book" nd deadline "4pm" to the list
+ - `list`: Lists all tasks
+ - `bye`: Exits the app
-### Feature-XYZ
+5. Refer to the Features below for more details on each command.
-Description of the feature.
+## Features
-## Usage
+[!NOTE]
+> Words in `UPPER_CASE` are parameters to be supplied by the user. e.g. in `delete INDEX`, `INDEX` is a parameter which can be used as `delete 3`
-### `Keyword` - Describe action
+## Add tasks
+### Add todo : `todo`
+Adds task of type todo to the list of tasks
-Describe the action and its outcome.
+Format: `todo DESCRIPTION`
-Example of usage:
+Examples:
+- `todo tutorial` Adds task `tutorial` to the list of tasks
+- `todo watch lecture` Adds task `watch lecture` to the list of tasks
-`keyword (optional arguments)`
+### Add deadline: `deadline`
+Adds task of type deadline to the list of tasks
-Expected outcome:
+Format: `deadline DESCRIPTION by DEADLINE`
-Description of the outcome.
+Examples:
+- `deadline return book by 4pm` Adds task `return book` with deadline `4pm` to the list of tasks
+- `deadline submit group report by 7pm` Adds task `submit group report` with deadline `7pm` to the list of tasks
-```
-expected output
-```
+### Add event: `event`
+Adds task of type event to the list of tasks
+
+Format: `event DESCRIPTION from START to END`
+
+Examples:
+- `event Math exam from 2pm to 4pm` Adds task `Math exam` with timeline `2pm` to `4pm` to the list of tasks
+- `event project group meeting from 11am to 1pm` Adds task `project group meeting` with timeline `11am` to `1pm` to the list of tasks
+
+## Listing tasks: `list`
+Lists all tasks in the task list.
+
+Format: `list`
+
+## Mark tasks as done: `mark`
+Marks tasks as completed
+
+Format: `mark INDEX`
+
+- Marks task as done at the specified `INDEX`.
+- The index refers to the index of the task in the list of tasks.
+- The index must be a positive integer.
+
+Examples:
+- `mark 1` Marks first task in the list as done
+- `mark 3` Marks sixth task in the list as done
+
+## Unmark tasks: `unmark`
+Marks tasks as undone
+
+Format: `unmark INDEX`
+
+- Marks task as not done at the specified `INDEX`.
+- The index refers to the index of the task in the list of tasks.
+- The index must be a positive integer.
+
+Examples:
+- `unmark 1` Marks first task in the list as not done
+- `unmark 2` Marks second task in the list as not done
+
+## Find Keywords: `find`
+Filters list of tasks to those containing the keyword the user wants to find
+
+Format: `find KEYWORD`
+
+Examples:
+- `find book` CLI returns a list with all the tasks with the `KEYWORD` `book`.
+- `find group` CLI returns a list with all the tasks with the `KEYWORD` `group`.
+
+## Delete tasks: `delete`
+Deletes task from the list of tasks
+
+Format: `delete INDEX`
+
+- Deletes task at the specified `INDEX`.
+- The index refers to the index of the task in the list of tasks.
+- The index must be a positive integer.
+
+Examples:
+- `delete 3` Deletes third task in the list
+- `delete 5` Deletes fifth task in the list
+
+## Exit app: `bye`
+Exits the chatbot
+
+Format: `bye`
+
+## Command Summary
+
+| Command | Format, Examples |
+| ------- | --------------- |
+| `todo` | `todo DESCRIPTION` e.g. `todo tutorial` |
+| `deadline` | `deadline DESCRIPTION by DEADLINE` e.g. `deadline return book by 4pm` |
+| `event` | `event DESCRIPTION from START to END` e.g. `event Math exam from 2pm to 4pm` |
+| `list` | `list` |
+| `mark` | `mark INDEX` e.g. `mark 2` |
+| `unmark` | `unmark INDEX` e.g. `unmark 1` |
+| `find` | `find KEYWORD` e.g. `find book` |
+| `delete` | `delete INDEX` e.g. `delete 3` |
+| `bye` | `bye` |
\ No newline at end of file
diff --git a/production/main/CreateFile.class b/production/main/CreateFile.class
new file mode 100644
index 000000000..1e7af2c53
Binary files /dev/null and b/production/main/CreateFile.class differ
diff --git a/production/main/Deadline.class b/production/main/Deadline.class
new file mode 100644
index 000000000..a306b63f8
Binary files /dev/null and b/production/main/Deadline.class differ
diff --git a/production/main/Duke.class b/production/main/Duke.class
new file mode 100644
index 000000000..c9293f48a
Binary files /dev/null and b/production/main/Duke.class differ
diff --git a/production/main/EmptyLineException.class b/production/main/EmptyLineException.class
new file mode 100644
index 000000000..c25befa72
Binary files /dev/null and b/production/main/EmptyLineException.class differ
diff --git a/production/main/Event.class b/production/main/Event.class
new file mode 100644
index 000000000..6c21ce09f
Binary files /dev/null and b/production/main/Event.class differ
diff --git a/production/main/ManageInputs.class b/production/main/ManageInputs.class
new file mode 100644
index 000000000..ba19acc4b
Binary files /dev/null and b/production/main/ManageInputs.class differ
diff --git a/production/main/ReadFileContents.class b/production/main/ReadFileContents.class
new file mode 100644
index 000000000..acca04e15
Binary files /dev/null and b/production/main/ReadFileContents.class differ
diff --git a/production/main/Task.class b/production/main/Task.class
new file mode 100644
index 000000000..668ea5de9
Binary files /dev/null and b/production/main/Task.class differ
diff --git a/production/main/Todo.class b/production/main/Todo.class
new file mode 100644
index 000000000..849ca63fa
Binary files /dev/null and b/production/main/Todo.class differ
diff --git a/production/main/UnexpectedCommandException.class b/production/main/UnexpectedCommandException.class
new file mode 100644
index 000000000..6c0d54dfe
Binary files /dev/null and b/production/main/UnexpectedCommandException.class differ
diff --git a/src/.idea/.gitignore b/src/.idea/.gitignore
new file mode 100644
index 000000000..13566b81b
--- /dev/null
+++ b/src/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/src/.idea/.name b/src/.idea/.name
new file mode 100644
index 000000000..305fff84b
--- /dev/null
+++ b/src/.idea/.name
@@ -0,0 +1 @@
+Task.class
\ No newline at end of file
diff --git a/src/.idea/misc.xml b/src/.idea/misc.xml
new file mode 100644
index 000000000..e0844bc7b
--- /dev/null
+++ b/src/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/.idea/modules.xml b/src/.idea/modules.xml
new file mode 100644
index 000000000..b8cce4602
--- /dev/null
+++ b/src/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/.idea/vcs.xml b/src/.idea/vcs.xml
new file mode 100644
index 000000000..6c0b86358
--- /dev/null
+++ b/src/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/TaskList.txt b/src/TaskList.txt
new file mode 100644
index 000000000..74091fd17
--- /dev/null
+++ b/src/TaskList.txt
@@ -0,0 +1,16 @@
+[T][0] hike
+[T][0] run
+[D][0] tut (by: 5)
+[E][0] he (from: 5 to: 6)
+[T][0] jump
+[T][0] go
+[D][0] hop (by: 4)
+[E][0] he (from: 4 to: 5)
+[D][0] b (by: 4)
+[E][0] go (from: 4 to: 454)
+[T][0] ds
+[D][0] kj (by: 4)
+[T][0] he
+[E][0] f (from: 4 to: 5)
+[D][0] sd (by: 5)
+[D][0] hsd (by: 343354535)
diff --git a/src/main/java/CreateFile.java b/src/main/java/CreateFile.java
new file mode 100644
index 000000000..8162aba93
--- /dev/null
+++ b/src/main/java/CreateFile.java
@@ -0,0 +1,33 @@
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * creates local TaskList.txt file on the local machine
+ */
+public class CreateFile {
+ protected static Ui ui;
+ public static void CreateFile() {
+ File file = new File("TaskList.txt");
+ String errorDescription;
+ String fileStatus;
+
+ if (!file.exists()) {
+ try {
+ if (file.createNewFile()) {
+ fileStatus = "File created";
+ System.out.println(fileStatus + ": " + file.getAbsolutePath());
+ } else {
+ errorDescription = "File creation failed.";
+ ui.errorMessage(errorDescription);
+ }
+ } catch (IOException e) {
+ errorDescription = "An I/O error occurred.";
+ ui.errorMessage(errorDescription);
+ e.printStackTrace();
+ }
+ } else {
+ fileStatus = "File already exists";
+ System.out.println(fileStatus + ": " + file.getAbsolutePath());
+ }
+ }
+}
diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java
new file mode 100644
index 000000000..c85aa1cf8
--- /dev/null
+++ b/src/main/java/Deadline.java
@@ -0,0 +1,16 @@
+/**
+ * child class of Task to handle deadlines
+ */
+public class Deadline extends Task {
+ protected String by;
+
+ public Deadline(String description, String by) {
+ super(description);
+ this.by = by;
+ }
+
+ @Override
+ public String toString() {
+ return "[D]" + super.toString() + " (by: " + by + ")";
+ }
+}
diff --git a/src/main/java/Duke.class b/src/main/java/Duke.class
new file mode 100644
index 000000000..76684001f
Binary files /dev/null and b/src/main/java/Duke.class differ
diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index 5d313334c..df9a9300c 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -1,10 +1,60 @@
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.sql.Array;
+import java.util.Scanner;
+import java.util.ArrayList;
+
public class Duke {
- public static void main(String[] args) {
- String logo = " ____ _ \n"
- + "| _ \\ _ _| | _____ \n"
- + "| | | | | | | |/ / _ \\\n"
- + "| |_| | |_| | < __/\n"
- + "|____/ \\__,_|_|\\_\\___|\n";
- System.out.println("Hello from\n" + logo);
+
+ /**
+ * lists tasks saved in the local TaskList.txt file
+ * @param filePath the path to the local TaskList.txt file
+ * @throws FileNotFoundException exception when local TaskList.txt file does not exist
+ */
+ private static void printFileContents (String filePath) throws FileNotFoundException {
+ File f = new File(filePath); // create a File for the given file path
+ Scanner s = new Scanner(f); // create a Scanner using the File as the source
+ while (s.hasNext()) {
+ System.out.println(s.nextLine());
+ }
+ }
+
+ private static Ui ui;
+ public static void main (String[] args) throws UnexpectedCommandException, EmptyLineException, IOException, FileNotFoundException {
+ ArrayList tasks = new ArrayList();
+ String errorDescription;
+ int index = 0;//number of items in the list
+ String line = " ";
+ File file = new File("TaskList.txt");
+
+ ui = new Ui();
+ ui.sayHi();
+ try {
+ System.out.println("Here are the items in your task list: ");
+ printFileContents("TaskList.txt");
+ } catch (FileNotFoundException e) {
+ errorDescription = "File not found";
+ ui.errorMessage(errorDescription);
+ }
+
+ if (!file.exists()) {
+ try {
+ if (file.createNewFile()) {
+ System.out.println("File created: " + file.getAbsolutePath());
+ } else {
+ errorDescription = "File creation failed.";
+ ui.errorMessage(errorDescription);
+ }
+ } catch (IOException e) {
+ errorDescription = "An I/O error occurred.";
+ ui.errorMessage(errorDescription);
+ e.printStackTrace();
+ }
+ } else {
+ System.out.println("File already exists: " + file.getAbsolutePath());
+ }
+
+ new Parser(tasks, index, line);
}
}
diff --git a/src/main/java/EmptyLineException.java b/src/main/java/EmptyLineException.java
new file mode 100644
index 000000000..5348ca427
--- /dev/null
+++ b/src/main/java/EmptyLineException.java
@@ -0,0 +1,3 @@
+public class EmptyLineException extends Exception {
+
+}
diff --git a/src/main/java/Event.java b/src/main/java/Event.java
new file mode 100644
index 000000000..7c94810a5
--- /dev/null
+++ b/src/main/java/Event.java
@@ -0,0 +1,18 @@
+/**
+ * child class of Task to handle events
+ */
+public class Event extends Task {
+ protected String from;
+ protected String to;
+
+ public Event(String description, String from, String to){
+ super(description);
+ this.from = from;
+ this.to = to;
+ }
+
+ @Override
+ public String toString() {
+ return "[E]" + super.toString() + " (from: " + from + " to: " + to + ")";
+ }
+}
diff --git a/src/main/java/Parser.java b/src/main/java/Parser.java
new file mode 100644
index 000000000..fe92bb35b
--- /dev/null
+++ b/src/main/java/Parser.java
@@ -0,0 +1,226 @@
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+/**
+ * deals with making sense of the user command
+ */
+public class Parser {
+ private static Ui ui;
+ private static Storage storage;
+ private static TaskList tasklist;
+
+ /**
+ * marks task as done
+ * @param inputs the array of words the user input
+ * @param tasks the array of tasks
+ * @param index the number of tasks in the array of tasks
+ * @param isValidCommand boolean is true if the command from the user is a valid action
+ * @throws IOException exception when there is an I/O error
+ */
+ private void dealWithMark (String[] inputs, ArrayList tasks, int index, boolean isValidCommand) throws IOException {
+ isValidCommand = true;
+ String errorDescription;
+
+ try {
+ int markIdx = Integer.parseInt(inputs[1]) - 1; //index to mark as done
+ tasks.get(markIdx).markAsDone();
+ System.out.println("Nice! I've marked this task as done: ");
+ System.out.println(tasks.get(markIdx));
+ storage.saveToFile(tasks, index);
+ } catch (IndexOutOfBoundsException e) {
+ errorDescription = "did not indicate which task to mark";
+ ui.errorMessage(errorDescription);
+ }
+ }
+
+ /**
+ * marks task as undone
+ * @param inputs the array of words input by the user
+ * @param tasks the array of tasks
+ * @param index the number of tasks in the array of tasks
+ * @param isValidCommand boolean is true if the command from the user is a valid action
+ * @throws IOException exception when there is an I/O error
+ */
+ private void dealWithUnmark (String[] inputs, ArrayList tasks, int index, boolean isValidCommand) throws IOException {
+ isValidCommand = true;
+ String errorDescription;
+
+ try {
+ int unmarkIdx = Integer.parseInt(inputs[1]) - 1; //index of task to unmark
+ tasks.get(unmarkIdx).unmarkDone();
+ System.out.println("OK, I've marked this task as not done yet: ");
+ System.out.println(tasks.get(unmarkIdx));
+ storage.saveToFile(tasks, index);
+ } catch (IndexOutOfBoundsException e) {
+ errorDescription = "did not indicate which task to unmark";
+ ui.errorMessage(errorDescription);
+ }
+ }
+
+ /**
+ * lists tasks
+ * @param tasks the array of tasks
+ * @param index the number of tasks in the array of tasks
+ * @param isValidCommand boolean is true if the command from the user is a valid action
+ */
+ private void listTasks (ArrayList tasks, int index, boolean isValidCommand) {
+ isValidCommand = true;
+ System.out.println("Here are the tasks in your list: ");
+
+ for (int taskNumber = 0; taskNumber < index; taskNumber++) {
+ System.out.println((taskNumber + 1) + ". " + tasks.get(taskNumber));
+ }
+ }
+
+ /**
+ * deletes task
+ * @param tasks the array of tasks
+ * @param inputs the array of words input by the user
+ * @param index the number of tasks in the array of tasks
+ * @param isValidCommand boolean is true if the command from the user is a valid action
+ * @return the number of tasks in the array of tasks after deletion
+ * @throws UnexpectedCommandException exception when the format or details of the tasks are not followed and provided respectively
+ * @throws IOException exception when there is an I/O error
+ */
+ private int deleteTask (ArrayList tasks, String[] inputs, int index, boolean isValidCommand) throws UnexpectedCommandException, IOException {
+ isValidCommand = true;
+ Storage.fillFileContents(tasks, "TaskList.txt", index);
+ TaskList.dealWithDelete(inputs, inputs[1], tasks);
+ index--;
+ System.out.println("Now you have " + index + " tasks in the list.");
+ storage.saveToFile(tasks, index);
+ return index;
+ }
+
+ /**
+ * filters tasks with the keyword input by the user
+ * @param findInput the keyword the user is looking for
+ * @param tasks the array of tasks
+ * @param index the number of tasks in the array of tasks
+ */
+ private void dealWithFind (String findInput, ArrayList tasks, int index) {
+ ArrayList matchingTasks = new ArrayList();
+ int matchingTasksIndex = 1;
+ System.out.println("Here are the matching tasks in your list: ");
+ for (int taskNumber = 0; taskNumber < index; taskNumber ++){
+ String taskString = tasks.get(taskNumber).toString();
+ if (taskString.contains(findInput)) {
+ System.out.print(matchingTasksIndex + ". ");
+ matchingTasks.add(tasks.get(taskNumber));
+ System.out.println(matchingTasks.get(matchingTasksIndex - 1));
+ matchingTasksIndex ++;
+ }
+ }
+ }
+
+
+ private void handleUnexpectedCommand (boolean isValidCommand) throws UnexpectedCommandException {
+ if (!isValidCommand) {
+ throw new UnexpectedCommandException();
+ }
+ }
+
+ private void handleEmptyInput (String line) throws EmptyLineException {
+ if (line.isEmpty()) {
+ throw new EmptyLineException();
+ }
+ }
+
+ /**
+ * handles the different commands input by the user
+ * @param tasks the array of tasks
+ * @param index the number of tasks in the array of tasks
+ * @param line the user input
+ * @throws IOException exception when there is an I/O error
+ * @throws IndexOutOfBoundsException exception when there is missing required details in the input
+ * @throws UnexpectedCommandException exception when the format or details of the tasks are not followed and provided respectively
+ */
+ public Parser (ArrayList tasks, int index, String line) throws IOException, IndexOutOfBoundsException, UnexpectedCommandException {
+ boolean isInTxt = true;
+ index = Storage.fillFileContents(tasks, "TaskList.txt", index);
+ isInTxt = false;
+ ui = new Ui();
+ String errorDescription;
+
+ while (!line.equals("bye")) {
+ ui.readCommand();
+ Boolean isValidCommand = false;
+ Scanner input = new Scanner(System.in);
+ line = input.nextLine();
+
+ Task t = new Task(line);
+ String[] inputs = line.split(" ");
+
+ final String commandType = inputs[0];
+
+ if (commandType.equals("mark")) {//mark as done
+ dealWithMark(inputs, tasks, index, isValidCommand);
+ Storage.saveToFile(tasks, index);
+ } else if (commandType.equals("unmark")) {//unmark done
+ dealWithUnmark(inputs, tasks, index, isValidCommand);
+ Storage.saveToFile(tasks, index);
+ } else if (line.equals("list")) {//lists tasks
+ listTasks(tasks, index, isValidCommand);
+ } else if (line.equals("bye")) {//exit chat
+ isValidCommand = true;
+ Storage.saveToFile(tasks, index);
+ break;
+ } else if (commandType.equals("event") || commandType.equals("todo") || commandType.equals("deadline")) {//add items
+ try {
+ if (commandType.equals("event")) {
+ isValidCommand = true;
+ TaskList.dealWithEvent(tasks, index, line, isInTxt);
+ Storage.writeToFile("TaskList.txt", tasks.get(index));
+ System.out.println("Got it. I've added this task: ");
+ System.out.println(tasks.get(index));
+ index++;
+ } else if (commandType.equals("deadline")) {
+ isValidCommand = true;
+ TaskList.dealWithDeadline(tasks, index, line, isInTxt);
+ Storage.writeToFile("TaskList.txt", tasks.get(index));
+ System.out.println("Got it. I've added this task: ");
+ System.out.println(tasks.get(index));
+ index++;
+ } else {
+ isValidCommand = true;
+ TaskList.dealWithTodo(tasks, index, line, isInTxt);
+ Storage.writeToFile("TaskList.txt", tasks.get(index));
+ System.out.println("Got it. I've added this task: ");
+ System.out.println(tasks.get(index));
+ index++;
+ }
+ } catch (IOException | UnexpectedCommandException | IndexOutOfBoundsException e) {
+ }
+ System.out.println("Now you have " + index + " tasks in the list.");
+
+ } else if (commandType.equals("delete")) {
+ try {
+ index = deleteTask(tasks, inputs, index, isValidCommand);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ errorDescription = "please specify which task you want to delete";
+ ui.errorMessage(errorDescription);
+ }
+ } else if (commandType.equals("find")) {
+ try {
+ dealWithFind(inputs[1], tasks, index);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ errorDescription = "please state what you would like to find";
+ ui.errorMessage(errorDescription);
+ }
+ } else {
+ try {
+ handleEmptyInput(line);
+ handleUnexpectedCommand(isValidCommand);
+ } catch (UnexpectedCommandException e) {
+ errorDescription = "Please enter a valid command";
+ ui.errorMessage(errorDescription);
+ } catch (EmptyLineException e) {
+ errorDescription = "No input detected. Please enter a task";
+ ui.errorMessage(errorDescription);
+ }
+ }
+ }
+ ui.sayBye();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ReadFileContents.java b/src/main/java/ReadFileContents.java
new file mode 100644
index 000000000..0a797b2c7
--- /dev/null
+++ b/src/main/java/ReadFileContents.java
@@ -0,0 +1,28 @@
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Scanner;
+
+/**
+ * prints TaskList.txt file contents
+ */
+public class ReadFileContents {
+ private static Ui ui;
+
+ private static void printFileContents (String filePath) throws FileNotFoundException {
+ File file = new File(filePath);
+ Scanner taskString = new Scanner(file); //reads tasks from TaskList.txt file
+ while (taskString.hasNext()) {
+ System.out.println(taskString.nextLine());
+ }
+ }
+
+ public static void main(String[] args) {
+ try {
+ printFileContents("TaskList.txt");
+ } catch (FileNotFoundException e) {
+ new CreateFile();
+ String errorDescription = "File not found";
+ ui.errorMessage(errorDescription);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/Storage.java b/src/main/java/Storage.java
new file mode 100644
index 000000000..e40b26e1e
--- /dev/null
+++ b/src/main/java/Storage.java
@@ -0,0 +1,64 @@
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+/**
+ * deals with loading tasks from the file and saving tasks in the file
+ */
+public class Storage {
+ /**
+ * loads ArrayList tasks with tasks saved on TaskList.txt
+ * @param tasks contains the list of tasks
+ * @param filePath the path to TaskList.txt saved on the local machine
+ * @param index the number of tasks saved in TaskList.txt
+ * @return index the number of tasks saved in TaskList.txt
+ * @throws IOException exception when local TaskList.txt file does not exist
+ * @throws UnexpectedCommandException exception when the format or details of the tasks are not followed and provided respectively
+ */
+ public static int fillFileContents (ArrayList tasks, String filePath, int index) throws IOException, UnexpectedCommandException {//updates index
+ File f = new File(filePath); // create a File for the given file path
+ Scanner taskLine = new Scanner(f); // create a Scanner using the File as the source
+
+ while (taskLine.hasNext()) {
+ String sLine = taskLine.nextLine();
+
+ if (sLine.contains("[E]")) {
+ TaskList.dealWithEvent(tasks, index, sLine, true);
+ } else if (sLine.contains("[D]")) {
+ TaskList.dealWithDeadline(tasks, index, sLine, true);
+ } else if (sLine.contains("[T]")) {
+ TaskList.dealWithTodo(tasks, index, sLine, true);
+ }
+ index++;
+ }
+ boolean isInTxt = false;
+ return index;
+ }
+
+ /**
+ * saves the updated tasks list onto TaskList.txt in the local machine
+ * @param tasks the array of tasks
+ * @param index the nymber of tasks in array of tasks
+ * @throws IOException exception when there is an I/O error
+ */
+ protected static void saveToFile (ArrayList tasks, int index) throws IOException {
+ new FileWriter("TaskList.txt", false).close();
+ for (int TaskIndex = 0; TaskIndex < index; TaskIndex ++) {
+ writeToFile("TaskList.txt", tasks.get(TaskIndex));
+ }
+ }
+
+ /**
+ * adds additional tasks into TaskList.txt
+ * @param filePath the path to TaskList.txt saved on the local machine
+ * @param textToAdd the new task to add
+ * @throws IOException exception when there is an I/O error
+ */
+ static void writeToFile (String filePath, Task textToAdd) throws IOException {
+ FileWriter fw = new FileWriter(filePath, true);
+ fw.write(textToAdd + "\n");
+ fw.close();
+ }
+}
diff --git a/src/main/java/Task.java b/src/main/java/Task.java
new file mode 100644
index 000000000..11b9b77da
--- /dev/null
+++ b/src/main/java/Task.java
@@ -0,0 +1,29 @@
+/**
+ * variables and functions that children classes of tasks inherit
+ * children classes in this chatbot include event, deadline and todo
+ */
+public class Task {
+ protected String description;
+ protected boolean isDone;
+ public Task(String description) {
+ this.description = description;
+ this.isDone = false;
+ }
+
+ public String getStatusIcon() {
+ return (isDone ? "1" : "0"); // mark done task with X
+ }
+
+ public void markAsDone() {
+ this.isDone = true;
+ }
+
+ public void unmarkDone() {
+ this.isDone = false;
+ }
+
+ public String toString(){
+ return "[" + getStatusIcon() + "]" + description;
+ }
+}
+
diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java
new file mode 100644
index 000000000..398f411e6
--- /dev/null
+++ b/src/main/java/TaskList.java
@@ -0,0 +1,198 @@
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * contains the task list and operations to add or delete tasks
+ */
+public class TaskList {
+ protected static Ui ui;
+ protected static ArrayList tasks;
+ public TaskList(){
+ this.tasks = tasks;
+ }
+
+ /**
+ * adds event to array of tasks
+ * @param tasks the array of tasks
+ * @param index the number of tasks in the array of tasks
+ * @param line the input string from the user
+ * @param isInTxt true if ArrayList tasks is being loaded from TaskList.txt
+ * @throws UnexpectedCommandException exception when the format or details of the tasks are not followed and provided respectively
+ * @throws IOException exception when there is an I/O error
+ */
+ public static void dealWithEvent (ArrayList tasks, int index, String line, boolean isInTxt) throws UnexpectedCommandException, IOException {
+ int indexTo = line.lastIndexOf("to");
+ int indexFrom = line.indexOf("from");
+ String from;
+ String to;
+ String description;
+ String errorDescription;
+
+ final int LENGTHOFFROM = 5; //length of "from "
+ final int LENGTHOFTO = 3;
+ final int EVENTCOMMANDLENGTH = 6;//length of "event "
+
+ final int FROMLENGTHCOLON = 6;//length of "from: "
+ final int TOLENGTHCOLON = 4;
+ final int STATUSLENGTH = 5;//length of "[E][ ]"
+
+ if ((indexTo == -1) || (indexFrom == -1)) { //invalid format
+ errorDescription = "Invalid format! Enter event in the format: event (description) from (start) to (end)";
+ ui.errorMessage(errorDescription);
+ throw new UnexpectedCommandException();
+ }
+ try {//timeline not specified/ both not specified
+ from = line.substring(indexFrom + LENGTHOFFROM, indexTo - 1);
+ to = line.substring(indexTo + LENGTHOFTO);
+ } catch (IndexOutOfBoundsException e) {
+ try {
+ description = line.substring(EVENTCOMMANDLENGTH, indexFrom - 1);
+ } catch (IndexOutOfBoundsException f) {
+ errorDescription = "event description and timeline not specified";
+ ui.errorMessage(errorDescription);
+ throw new UnexpectedCommandException();
+ }
+ errorDescription = "event timeline not specified";
+ ui.errorMessage(errorDescription);
+ throw new UnexpectedCommandException();
+ }
+ try {//description not specified
+ description = line.substring(EVENTCOMMANDLENGTH, indexFrom - 1);
+ } catch (IndexOutOfBoundsException e) {
+ errorDescription = "event description not specified";
+ ui.errorMessage(errorDescription);
+ throw new UnexpectedCommandException();
+ }
+ if (!isInTxt) {
+ from = line.substring(indexFrom + LENGTHOFFROM, indexTo - 1);
+ to = line.substring(indexTo + LENGTHOFTO);
+ description = line.substring(STATUSLENGTH, indexFrom - 1);
+ } else {
+ from = line.substring(indexFrom + FROMLENGTHCOLON, indexTo - 1);
+ to = line.substring(indexTo + TOLENGTHCOLON, line.length() - 1);
+ description = line.substring(EVENTCOMMANDLENGTH, indexFrom - 1);
+ }
+ tasks.add(index, new Event(description, from, to));
+ final int STATUSINDEX = 4;
+ if (isInTxt){
+ char[] charArray = line.toCharArray();
+ if (charArray[STATUSINDEX] == '1'){
+ tasks.get(index).markAsDone();
+ } else{
+ tasks.get(index).unmarkDone();
+ }
+ }
+ }
+
+ /**
+ * adds deadline to array of tasks
+ * @param tasks the array of tasks
+ * @param index the number of tasks in the array of tasks
+ * @param line the input string from the user
+ * @param isInTxt true if ArrayList tasks is being loaded from TaskList.txt
+ * @throws UnexpectedCommandException exception when the format or details of the tasks are not followed and provided respectively
+ * @throws IOException exception when there is an I/O error
+ */
+ public static void dealWithDeadline (ArrayList tasks, int index, String line, boolean isInTxt) throws UnexpectedCommandException, IOException {
+ int indexBy = line.indexOf("by");
+ int space = line.indexOf(" ");
+ String by;
+ String description;
+ String errorDescription;
+
+ final int LENGTHFBY = 3;//length of "by "
+ final int BYLENGTHCOLON = 4; //length of "by: "
+
+ if (indexBy == -1) {//invalid format
+ errorDescription = "Invalid format! Enter deadline in the format: deadline (description) by (deadline)";
+ ui.errorMessage(errorDescription);
+ throw new UnexpectedCommandException();
+ }
+ try {//deadline / both not specified
+ by = line.substring(indexBy + LENGTHFBY);
+ } catch (IndexOutOfBoundsException e) {
+ try {
+ description = line.substring(space + 1, indexBy - 1);
+ } catch (IndexOutOfBoundsException f) {
+ errorDescription = "deadline description and deadline not specified";
+ ui.errorMessage(errorDescription);
+ throw new UnexpectedCommandException();
+ }
+ errorDescription = "deadline not specified";
+ ui.errorMessage(errorDescription);
+ throw new UnexpectedCommandException();
+ }
+ try {//deadline not specified
+ description = line.substring(space + 1, indexBy - 1);
+ } catch (IndexOutOfBoundsException e) {
+ errorDescription = "deadline description not specified";
+ ui.errorMessage(errorDescription);
+ throw new UnexpectedCommandException();
+ }
+ if (!isInTxt) {
+ description = line.substring(space, indexBy - 1);
+ by = line.substring(indexBy + LENGTHFBY);
+ } else {
+ description = line.substring(space, indexBy - 1);
+ by = line.substring(indexBy + BYLENGTHCOLON, line.length() - 1);
+ }
+
+ tasks.add(index, new Deadline(description, by));
+ if (isInTxt) {
+ final int STATUSINDEX = 4;
+ char[] charArray = line.toCharArray();
+ if (charArray[STATUSINDEX] == '1'){
+ tasks.get(index).markAsDone();
+ } else {
+ tasks.get(index).unmarkDone();
+ }
+ }
+ }
+
+ /**
+ * adds todo to array of tasks
+ * @param tasks the array of tasks
+ * @param index the number of tasks in the array of tasks
+ * @param line the input string from the user
+ * @param isInTxt true if ArrayList tasks is being loaded from TaskList.txt
+ * @throws UnexpectedCommandException exception when the format or details of the tasks are not followed and provided respectively
+ * @throws IOException exception when there is an I/O error
+ */
+ public static void dealWithTodo (ArrayList tasks, int index, String line, boolean isInTxt) throws UnexpectedCommandException, IOException {
+ int indexSpace = line.indexOf(" ");
+ final int STATUSINDEX = 4;
+ String errorDescription;
+
+ if (indexSpace == -1) {
+ errorDescription = "todo description not specified";
+ ui.errorMessage(errorDescription);
+ throw new UnexpectedCommandException();
+ }
+
+ String description = line.substring(indexSpace);
+ tasks.add(index, new Todo(description));
+ if (isInTxt) {
+ char[] charArray = line.toCharArray();
+ if (charArray[STATUSINDEX] == '1') {
+ tasks.get(index).markAsDone();
+ } else {
+ tasks.get(index).unmarkDone();
+ }
+ }
+ }
+
+ /**
+ * deletes item from array of tasks
+ * @param inputs the array of words input by the user
+ * @param ListIndex the string containing the task number to delete
+ * @param tasks the array of tasks
+ */
+ public static void dealWithDelete (String[] inputs, String ListIndex, ArrayList tasks) {
+ if (inputs[0].equals("delete")) {
+ int deleteIdx = Integer.parseInt(ListIndex) - 1; //index of task to delete
+ System.out.println("Noted. I've removed this task: ");
+ System.out.println(tasks.get(deleteIdx));
+ tasks.remove(deleteIdx);
+ }
+ }
+}
diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java
new file mode 100644
index 000000000..50d8abdcd
--- /dev/null
+++ b/src/main/java/Todo.java
@@ -0,0 +1,14 @@
+/**
+ * child class of Task to handle todos
+ */
+public class Todo extends Task {
+
+ public Todo (String description){
+ super(description);
+ }
+ @Override
+ public String toString() {
+ return "[T]" + super.toString();
+ }
+
+}
diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java
new file mode 100644
index 000000000..1e0a62a5b
--- /dev/null
+++ b/src/main/java/Ui.java
@@ -0,0 +1,22 @@
+/**
+ * deals with interactions with the user
+ */
+
+public class Ui {
+ public void sayHi() {
+ System.out.println("Hello! I'm Apple");
+ System.out.println("What can I do for you?");
+ }
+
+ public void readCommand() {
+ System.out.print("Enter your command: ");
+ }
+
+ public static void errorMessage (String message) {
+ System.out.println(message);
+ }
+
+ public void sayBye() {
+ System.out.println("Bye. Hope to see you again soon!");
+ }
+}
diff --git a/src/main/java/UnexpectedCommandException.java b/src/main/java/UnexpectedCommandException.java
new file mode 100644
index 000000000..0b8f65fcf
--- /dev/null
+++ b/src/main/java/UnexpectedCommandException.java
@@ -0,0 +1,3 @@
+public class UnexpectedCommandException extends Exception {
+
+}
diff --git a/src/out/production/ip/Deadline.class b/src/out/production/ip/Deadline.class
new file mode 100644
index 000000000..a306b63f8
Binary files /dev/null and b/src/out/production/ip/Deadline.class differ
diff --git a/src/out/production/ip/Duke.class b/src/out/production/ip/Duke.class
new file mode 100644
index 000000000..9e185ddde
Binary files /dev/null and b/src/out/production/ip/Duke.class differ
diff --git a/src/out/production/ip/EmptyLineException.class b/src/out/production/ip/EmptyLineException.class
new file mode 100644
index 000000000..c25befa72
Binary files /dev/null and b/src/out/production/ip/EmptyLineException.class differ
diff --git a/src/out/production/ip/Event.class b/src/out/production/ip/Event.class
new file mode 100644
index 000000000..6c21ce09f
Binary files /dev/null and b/src/out/production/ip/Event.class differ
diff --git a/src/out/production/ip/ManageInputs.class b/src/out/production/ip/ManageInputs.class
new file mode 100644
index 000000000..3e38f8aa6
Binary files /dev/null and b/src/out/production/ip/ManageInputs.class differ
diff --git a/src/out/production/ip/Task.class b/src/out/production/ip/Task.class
new file mode 100644
index 000000000..3a2f54fde
Binary files /dev/null and b/src/out/production/ip/Task.class differ
diff --git a/src/out/production/ip/Todo.class b/src/out/production/ip/Todo.class
new file mode 100644
index 000000000..849ca63fa
Binary files /dev/null and b/src/out/production/ip/Todo.class differ
diff --git a/src/out/production/ip/UnexpectedCommandException.class b/src/out/production/ip/UnexpectedCommandException.class
new file mode 100644
index 000000000..6c0d54dfe
Binary files /dev/null and b/src/out/production/ip/UnexpectedCommandException.class differ