diff --git a/README.md b/README.md
index 8715d4d91..6095ffb21 100644
--- a/README.md
+++ b/README.md
@@ -21,4 +21,8 @@ Prerequisites: JDK 11, update Intellij to the most recent version.
| | | | | | | |/ / _ \
| |_| | |_| | < __/
|____/ \__,_|_|\_\___|
+
+
```
+
+wang silang
diff --git a/docs/README.md b/docs/README.md
index 8077118eb..c5818a880 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,29 +1,171 @@
-# User Guide
+# Duke: Your Personal Agenda Assistant 📑
-## Features
+Duke is a Java personal agenda keeper. He is smart enough to assist in your daily activity planning. Below are his functionalities:
-### Feature-ABC
+1. [Add Task](#add)
+ 1. [Todo](#t)
+ 2. [Event](#e)
+ 3. [Deadline](#d)
+2. [Mark/Unmark Task](#mum)
+ 1. [Mark Task](#mt)
+ 2. [Unmark Task](#u)
+3. [Delete Task](#dt)
+4. [List Task](#lt)
+5. [Find Task](#ft)
+6. [Exit](#end)
+--------------------------------------------------------------------
+# NOTE:
+* Follow the input format as mentioned below to avoid errors.
+--------------------------------------------------------------------
-Description of the feature.
+# 1. Add Task
-### Feature-XYZ
+You can add 3 types of tasks, Todos, Events and Deadlines.
-Description of the feature.
+## 1.1. Todo
+* COMMAND: todo {task}
-## Usage
-### `Keyword` - Describe action
+Input:
-Describe the action and its outcome.
+```todo return book```
-Example of usage:
+Output:
+```
+As per requested Sire, this task has been added to your calendar.
+[T][ ] return book
+You now have 7 items left
+```
+
+
+## 1.2. Event
+* COMMAND: event {task} \from {string} \to {string}
+
+Input:
+
+```event meeting with friend /from 4pm /to 6pm```
+
+Output:
+```
+As per requested Sire, this task has been added to your calendar.
+[E][ ] meeting with friend (from: 4pm to: 6pm)
+You now have 8 items left
+```
+
+## 1.3. Deadline
+* Command: deadline {task} \by {string}
+
+Input:
+
+```deadline finish CS2113 assignment/by Sunday```
+
+Output:
+```
+As per requested Sire, this task has been added to your calendar.
+[D][ ] finish CS2113 assignmen (by: Sunday)
+You now have 9 items left
+```
+
+
+# 2. Mark/Unmark Task
+
+Mark the task at the index keyed in by users as done, or unmark it as unfinished.
+For index of all current tasks, please see [List Task](#lt).
+
+## 2.1. Mark Task
+* COMMAND: mark {enter task_index}
+
+Input:
+
+```mark 1```
+
+Output:
+
+```
+Sir, your task has been marked as completed.
+[T][X] Finish CS2113 iP
+```
+
+## 2.2. Unmark Task
+* COMMAND: unmark {enter task_index}
+
+Input:
+
+```unmark 2```
+
+Output:
+
+```
+Sir, your task has been unmarked as requested.
+[T][ ] sleep
+```
+
+# 3. Delete Task
+
+Delete task at keyed in index as follows:
+
+* COMMAND: delete {enter task_index}
+
+Input:
+
+```delete 1```
+
+Output:
+
+```
+Sire, I have removed this task from your schedule
+[T][X] Finish CS2113 iP
+You now have 8 items left
+```
+
+# 4. List Task
+
+List all tasks in the list as follows:
+
+* COMMAND: list
+
+Input:
+
+```list```
-`keyword (optional arguments)`
+Output:
-Expected outcome:
+```
+Your current list of items as requested, sir.
+1.[T][ ] sleep
+2.[E][ ] project meeting (from: Mon 2pm to: 4pm)
+3.[T][ ] return book
+4.[E][ ] meeting with friend (from: 4pm to: 6pm)
+```
+
+# 5. Find Task
+
+Find the desired tasks by keying in a term they contain as follows:
-Description of the outcome.
+* COMMAND: find {keyword}
+Input:
+
+```find friend```
+
+Output:
```
-expected output
+Here are the matching items Sire:
+[E][ ] meeting with friend (from: 4pm to: 6pm)
```
+
+
+# 6. Exit
+
+Exit the program as follows:
+
+Input:
+
+```bye```
+
+Output:
+```
+Glad I could be of help!
+```
+
+# End of user guide
diff --git a/src/.idea/workspace.xml b/src/.idea/workspace.xml
new file mode 100644
index 000000000..a4dceeceb
--- /dev/null
+++ b/src/.idea/workspace.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "keyToString": {
+ "RunOnceActivity.OpenProjectViewOnStart": "true",
+ "RunOnceActivity.ShowReadmeOnStart": "true",
+ "WebServerToolWindowFactoryState": "false",
+ "last_opened_file_path": "/Users/wangsilang/Desktop/Codes/CS2113/iP/ip/src",
+ "node.js.detected.package.eslint": "true",
+ "node.js.detected.package.tslint": "true",
+ "node.js.selected.package.eslint": "(autodetect)",
+ "node.js.selected.package.tslint": "(autodetect)",
+ "vue.rearranger.settings.migration": "true"
+ }
+}
+
+
+
+
+ 1676455852136
+
+
+ 1676455852136
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
deleted file mode 100644
index 5d313334c..000000000
--- a/src/main/java/Duke.java
+++ /dev/null
@@ -1,10 +0,0 @@
-public class Duke {
- public static void main(String[] args) {
- String logo = " ____ _ \n"
- + "| _ \\ _ _| | _____ \n"
- + "| | | | | | | |/ / _ \\\n"
- + "| |_| | |_| | < __/\n"
- + "|____/ \\__,_|_|\\_\\___|\n";
- System.out.println("Hello from\n" + logo);
- }
-}
diff --git a/src/main/java/Duke/Duke.java b/src/main/java/Duke/Duke.java
new file mode 100644
index 000000000..0d358eaff
--- /dev/null
+++ b/src/main/java/Duke/Duke.java
@@ -0,0 +1,46 @@
+package Duke;
+
+public class Duke {
+ private Ui ui;
+ private Storage storage;
+ private TaskList tasklist;
+ private Parser parser;
+ private final int PARSERINDEX = 1;
+
+ public Duke(String filePath) {
+ ui = new Ui();
+ storage = new Storage();
+ tasklist = new TaskList(filePath);
+ parser = new Parser();
+ }
+
+ public void run() {
+ ui.greet();
+ while (parser.getIsRunning()) {
+ String commandToBeParsed = ui.readCommand();
+ String commandParsed = parser.parseCommand(commandToBeParsed);
+ if (commandParsed.startsWith("B")) { // bye from user, terminate program
+ parser.setIsRunning(false);
+ } else if (commandParsed.startsWith("L")) { // print list
+ tasklist.printCurrentList();
+ } else if (commandParsed.startsWith("F")) { // find tasks in list
+ tasklist.printTasksFound(commandParsed.substring(PARSERINDEX));
+ } else if (commandParsed.startsWith("M")) { // mark task
+ tasklist.mark(commandParsed.substring(PARSERINDEX));
+ } else if (commandParsed.startsWith("U")) { // unmark task
+ tasklist.unmark(commandParsed.substring(PARSERINDEX));
+ } else if (commandParsed.startsWith("D")) { // delete task
+ tasklist.delete(commandParsed.substring(PARSERINDEX));
+ } else if (commandParsed.startsWith("XNC")) { // null command error
+ ui.printErrorMessage("Sire, I am not trained to understand gibberish.");
+ } else { // task keyed in by users
+ tasklist.addTask(commandParsed.substring(PARSERINDEX));
+ }
+ }
+ ui.bye();
+ }
+
+ public static void main(String[] args) {
+ new Duke("dukeData.txt").run();
+ }
+}
diff --git a/src/main/java/Duke/Exception/EmptyDeadlineException.java b/src/main/java/Duke/Exception/EmptyDeadlineException.java
new file mode 100644
index 000000000..9dfeae63b
--- /dev/null
+++ b/src/main/java/Duke/Exception/EmptyDeadlineException.java
@@ -0,0 +1,4 @@
+package Duke.Exception;
+
+public class EmptyDeadlineException extends Exception {
+}
diff --git a/src/main/java/Duke/Exception/EmptyEventsException.java b/src/main/java/Duke/Exception/EmptyEventsException.java
new file mode 100644
index 000000000..be113f705
--- /dev/null
+++ b/src/main/java/Duke/Exception/EmptyEventsException.java
@@ -0,0 +1,4 @@
+package Duke.Exception;
+
+public class EmptyEventsException extends Exception {
+}
diff --git a/src/main/java/Duke/Exception/EmptyToDoException.java b/src/main/java/Duke/Exception/EmptyToDoException.java
new file mode 100644
index 000000000..502c680e1
--- /dev/null
+++ b/src/main/java/Duke/Exception/EmptyToDoException.java
@@ -0,0 +1,4 @@
+package Duke.Exception;
+
+public class EmptyToDoException extends Exception {
+}
diff --git a/src/main/java/Duke/Exception/NullCommandException.java b/src/main/java/Duke/Exception/NullCommandException.java
new file mode 100644
index 000000000..3e080511a
--- /dev/null
+++ b/src/main/java/Duke/Exception/NullCommandException.java
@@ -0,0 +1,4 @@
+package Duke.Exception;
+
+public class NullCommandException extends Exception {
+}
diff --git a/src/main/java/Duke/Parser.java b/src/main/java/Duke/Parser.java
new file mode 100644
index 000000000..4a63ee71b
--- /dev/null
+++ b/src/main/java/Duke/Parser.java
@@ -0,0 +1,65 @@
+package Duke;
+
+import Duke.Exception.NullCommandException;
+import Duke.Task.Task;
+
+public class Parser {
+ private boolean isRunning = true;
+
+ /**
+ * Parse the input from user to determine what to do with the given input by appending
+ * a characteristic letter in front.
+ *
+ * @param line input from user to be parsed.
+ * @return a string of user's input with characteristic letter appended to the front.
+ * @throws NullCommandException If input is in invalid format.
+ */
+ public String parseCommand(String line) {
+ if (line.equals("bye")) {
+ return "B";
+ } else if (line.equals("list")) {
+ return "L";
+ } else if (line.startsWith("mark")) {
+ return "M" + line;
+ } else if (line.startsWith("unmark")) {
+ return "U" + line;
+ } else if (line.startsWith("delete")) {
+ return "D" + line;
+ } else if (line.startsWith("find")) {
+ return "F" + line;
+ } else {
+ try {
+ Task newTask = new Task(line);
+ if (line.startsWith("todo")) {
+ return "T" + line;
+ } else if (line.startsWith("deadline")) {
+ return "A" + line;
+ } else if (line.startsWith("event")) {
+ return "E" + line;
+ } else {
+ throw new NullCommandException();
+ }
+ } catch (NullCommandException e) {
+ return "XNC";
+ }
+ }
+ }
+
+ /**
+ * Gets the boolean value of parser object, for termination check of program
+ *
+ * @return boolean value of isRunning.
+ */
+ public boolean getIsRunning() {
+ return this.isRunning;
+ }
+
+ /**
+ * Sets the boolean value of parser object, to terminate the program
+ *
+ * @param bool boolean value of parser object to be set.
+ */
+ public void setIsRunning(boolean bool) {
+ this.isRunning = bool;
+ }
+}
diff --git a/src/main/java/Duke/Storage.java b/src/main/java/Duke/Storage.java
new file mode 100644
index 000000000..22caa1c9d
--- /dev/null
+++ b/src/main/java/Duke/Storage.java
@@ -0,0 +1,133 @@
+package Duke;
+
+import Duke.Exception.EmptyDeadlineException;
+import Duke.Exception.EmptyEventsException;
+import Duke.Exception.EmptyToDoException;
+import Duke.Task.Deadlines;
+import Duke.Task.Events;
+import Duke.Task.Task;
+import Duke.Task.ToDos;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+public class Storage {
+ private static final int BRACKETSKIP_INDEX = 7;
+ private static final int FIRSTBRACKET_FRONT = 0;
+ private static final int FIRSTBRACKET_BACK = 3;
+ private static final int SECONDBRACKET_FRONT = 3;
+ private static final int SECONDBRACKET_BACK = 6;
+
+
+ private static void writeToFile(String filePath, String textToAdd) throws IOException {
+ FileWriter fw = new FileWriter(filePath);
+ fw.write(textToAdd);
+ fw.close();
+ }
+
+ /**
+ * Write the data to the default file location
+ *
+ * @param taskToBeStored info to be written to the file.
+ * @throws IOException If default file location is invalid.
+ */
+ public static void dukeDataStorage(String taskToBeStored) {
+ File f = new File("dukeData.txt");
+ try {
+ if (!f.exists()) {
+ f.createNewFile();
+ }
+ writeToFile("dukeData.txt", taskToBeStored);
+ } catch (IOException e) {
+ System.out.println("File creation of writing invalid");
+ }
+ }
+
+ /**
+ * Parse data stored in file into String object.
+ *
+ * @param filePath file path of data file to be read.
+ * @return String object representing all the data in the data file.
+ * @throws FileNotFoundException If file path is invalid.
+ */
+ public static String parseFileContentsToString(String filePath) throws FileNotFoundException {
+ File f = new File(filePath); // create a File for the given file path
+ String fileContent = "";
+ if (!f.exists()) { // for first log in, there is no file
+ return fileContent;
+ }
+ Scanner s = new Scanner(f); // create a Scanner using the File as the source
+ while (s.hasNext()) {
+ String taskStored = s.nextLine();
+ fileContent = fileContent + taskStored + System.lineSeparator();
+ }
+ return fileContent;
+ }
+
+ /**
+ * Parse data stored in an arraylist to a single String object to be stored in data file. Used
+ * in writing to data file.
+ *
+ * @param list arraylist to be parsed.
+ * @return String object representing all the data in the data file.
+ */
+ public static String arraylistToStringConverter(ArrayList list) {
+ String output = "";
+ for (Task t : list) {
+ output = output + t.toString() + System.lineSeparator();
+ }
+ return output;
+ }
+
+ /**
+ * Parse data stored as a single String object into an arrayList. Used in reading from data file.
+ *
+ * @param fileContent a String object representing data in the file.
+ * @return arraylist which stores all the tasks stored in file as elements.
+ * @throws EmptyDeadlineException If task read is empty.
+ * @throws EmptyToDoException If task read is empty.
+ * @throws EmptyEventsException If task read is empty.
+ */
+ public static ArrayList stringToArraylistConverter(String fileContent) {
+ ArrayList list = new ArrayList<>();
+ if (fileContent.equals("")) {
+ return list;
+ }
+ String[] bufferArray = fileContent.split(System.lineSeparator());
+ for (String t : bufferArray) {
+ Task task = new Task(t);
+ try {
+ if (t.substring(FIRSTBRACKET_FRONT, FIRSTBRACKET_BACK).equals("[T]")) {
+ String todoDetail = "todo " + t.substring(BRACKETSKIP_INDEX);
+ task = new ToDos(todoDetail);
+ task.setMark(t.substring(SECONDBRACKET_FRONT, SECONDBRACKET_BACK));
+ } else if (t.substring(FIRSTBRACKET_FRONT, FIRSTBRACKET_BACK).equals("[D]")) {
+ String deadlineDetail = "deadline " + t.substring(BRACKETSKIP_INDEX, t.indexOf("(")) + "/" +
+ t.substring(t.indexOf("(") + 1, t.indexOf(")"));
+ task = new Deadlines(deadlineDetail);
+ task.setMark(t.substring(SECONDBRACKET_FRONT, SECONDBRACKET_BACK));
+ } else {
+ String eventDetail = "event " + t.substring(BRACKETSKIP_INDEX, t.indexOf("(")) + "/" +
+ t.substring(t.indexOf("(") + 1, t.indexOf("to")) + "/" +
+ t.substring(t.indexOf("to"), t.indexOf(")"));
+ eventDetail = eventDetail.replace(":", "");
+ task = new Events(eventDetail);
+ task.setMark(t.substring(SECONDBRACKET_FRONT, SECONDBRACKET_BACK));
+ }
+ } catch (EmptyToDoException e) {
+ System.out.println("Corrupt todo detected, it is empty");
+ } catch (EmptyDeadlineException e) {
+ System.out.println("Corrupt Deadline detected, it is empty");
+ } catch (EmptyEventsException e) {
+ System.out.println("Corrupt Events detected, it is empty");
+ }
+ list.add(task);
+ }
+ return list;
+ }
+}
+
diff --git a/src/main/java/Duke/Task/Deadlines.java b/src/main/java/Duke/Task/Deadlines.java
new file mode 100644
index 000000000..78835cf91
--- /dev/null
+++ b/src/main/java/Duke/Task/Deadlines.java
@@ -0,0 +1,44 @@
+package Duke.Task;
+
+import Duke.Exception.EmptyDeadlineException;
+import Duke.Task.Task;
+
+public class Deadlines extends Task {
+ private static final int DEADLINE_INDEX = 9;
+ private static final int COLON_INDEX = 2;
+ private String endTime;
+ private String taskLabel = "[D]";
+
+ /**
+ * Represents a Deadlines object which is identified by the type D. Contains description and deadline info.
+ */
+ public Deadlines(String input) throws EmptyDeadlineException {
+ super(input.substring(DEADLINE_INDEX, input.indexOf('/') - 1)); // Sanitize input by removing "deadline" at the start
+ super.setTaskLabel(taskLabel);
+ endTime = "(" + getEndTime(input) + ")";
+ if (input.substring(DEADLINE_INDEX, input.indexOf('/') - 1).isEmpty()) {
+ throw new EmptyDeadlineException();
+ }
+ }
+
+ // Method of StringBuffer operation taken from
+ // https://www.geeksforgeeks.org/insert-a-string-into-another-string-in-java/
+ /**
+ * Returns the deadline of the task.
+ *
+ * @param input user input to be parsed.
+ * @return deadline of the tasked from parsing.
+ */
+ @Override
+ public String getEndTime(String input) {
+ String deadline = input.substring(input.indexOf('/') + 1); // endTime of task is the string after '/'
+ StringBuffer deadlineCorrectFormat = new StringBuffer(deadline); // convert to StringBuffer for inserting ':'
+ deadlineCorrectFormat.insert(COLON_INDEX, ":");
+ return deadlineCorrectFormat.toString();
+ }
+
+ @Override
+ public String toString() {
+ return this.taskLabel + this.mark + " " + this.description + " " + this.endTime;
+ }
+}
diff --git a/src/main/java/Duke/Task/Events.java b/src/main/java/Duke/Task/Events.java
new file mode 100644
index 000000000..7fbd77d5d
--- /dev/null
+++ b/src/main/java/Duke/Task/Events.java
@@ -0,0 +1,63 @@
+package Duke.Task;
+
+import Duke.Exception.EmptyEventsException;
+
+public class Events extends Task {
+ private static final int EVENT_INDEX = 6;
+ private static final int FIRST_COLON_INDEX = 4;
+ private static final int SECOND_COLON_INDEX = 2;
+ private String timeLine;
+ private String taskLabel = "[E]";
+ /**
+ * Represents an Events object which is identified by the type E. Contains description, start time
+ * and end time.
+ */
+ public Events(String input) throws EmptyEventsException {
+ super(input.substring(EVENT_INDEX, input.indexOf('/') - 1));
+ super.setTaskLabel(taskLabel);
+ timeLine = "(" + getStartTime(input) + getEndTime(input) + ")";
+ if (input.substring(EVENT_INDEX, input.indexOf('/') - 1).isEmpty()) {
+ throw new EmptyEventsException();
+ }
+ }
+
+ public String[] splitInput(String input) {
+ String[] inputAfterSplit = input.split("/", 3); // split twice to generate three strings
+ return inputAfterSplit;
+ }
+
+ /**
+ * Returns the starting time of the task.
+ *
+ * @param input user input to be parsed.
+ * @return starting time of the tasked from parsing.
+ */
+ @Override
+ public String getStartTime(String input) {
+ String[] inputAfterSplit = splitInput(input);
+ String startTime = inputAfterSplit[1];
+ StringBuffer startTimeCorrectFormat = new StringBuffer(startTime);
+ startTimeCorrectFormat.insert(FIRST_COLON_INDEX, ":");
+ return startTimeCorrectFormat.toString();
+ }
+
+ /**
+ * Returns the ending time of the task.
+ *
+ * @param input user input to be parsed.
+ * @return ending time of the tasked from parsing.
+ */
+ @Override
+ public String getEndTime(String input) {
+ String[] inputAfterSplit = splitInput(input);
+ String startTime = inputAfterSplit[2];
+ StringBuffer endTimeCorrectFormat = new StringBuffer(startTime); // convert to StringBuffer for inserting ':'
+ endTimeCorrectFormat.insert(SECOND_COLON_INDEX, ":");
+ return endTimeCorrectFormat.toString();
+ }
+
+ @Override
+ public String toString() {
+ return this.taskLabel + this.mark + " " + this.description + " " + this.timeLine;
+ }
+}
diff --git a/src/main/java/Duke/Task/Task.java b/src/main/java/Duke/Task/Task.java
new file mode 100644
index 000000000..38729d433
--- /dev/null
+++ b/src/main/java/Duke/Task/Task.java
@@ -0,0 +1,49 @@
+package Duke.Task;
+
+/**
+ * Represents a Task object which is identified by the type of task it is (taskLabel), its content (description)
+ * and whether it is completed or not (mark).
+ */
+public class Task {
+ protected String taskLabel;
+ protected String description;
+ protected String mark;
+
+ public Task(String input) {
+ this.description = input;
+ this.taskLabel = "To be replaced by labels";
+ this.mark = "[ ]";
+ }
+
+ public String getTaskLabel() {
+ return taskLabel;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getStartTime(String input) {
+ return "To be overridden by subclass' methods";
+ }
+
+ public String getEndTime(String input) {
+ return "To be overridden by subclass' methods";
+ }
+
+ public void setTaskLabel(String taskLabel) {
+ this.taskLabel = taskLabel;
+ }
+
+ public void markTask() {
+ this.mark = "[X]";
+ }
+
+ public void unmarkTask() {
+ this.mark = "[ ]";
+ }
+
+ public void setMark(String mark) {
+ this.mark = mark;
+ }
+}
diff --git a/src/main/java/Duke/Task/ToDos.java b/src/main/java/Duke/Task/ToDos.java
new file mode 100644
index 000000000..8a06b2588
--- /dev/null
+++ b/src/main/java/Duke/Task/ToDos.java
@@ -0,0 +1,24 @@
+package Duke.Task;
+
+import Duke.Exception.EmptyToDoException;
+import Duke.Ui;
+
+/**
+ * Represents a ToDos object which is identified by the type of task T. Contains only description.
+ */
+public class ToDos extends Task {
+ private static final int TODOS_INDEX = 5;
+ private String taskLabel = "[T]";
+
+ public ToDos(String input) throws EmptyToDoException {
+ super(input.substring(TODOS_INDEX)); // for ToDos tasks, description = input
+ super.setTaskLabel(taskLabel);
+ if (input.substring(TODOS_INDEX).isEmpty()) {
+ throw new EmptyToDoException();
+ }
+ }
+ @Override
+ public String toString() {
+ return this.taskLabel + this.mark + " " + this.description;
+ }
+}
diff --git a/src/main/java/Duke/TaskList.java b/src/main/java/Duke/TaskList.java
new file mode 100644
index 000000000..9c8995967
--- /dev/null
+++ b/src/main/java/Duke/TaskList.java
@@ -0,0 +1,129 @@
+package Duke;
+
+import Duke.Exception.EmptyDeadlineException;
+import Duke.Exception.EmptyEventsException;
+import Duke.Exception.EmptyToDoException;
+import Duke.Exception.NullCommandException;
+import Duke.Task.Deadlines;
+import Duke.Task.Events;
+import Duke.Task.Task;
+import Duke.Task.ToDos;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+
+public class TaskList {
+ private static final int MARK_INDEX = 5;
+ private static final int UNMARK_INDEX = 7;
+ private static final int DELETE_INDEX = 7;
+
+ private static final int FIND_INDEX = 5;
+ public static ArrayList list;
+
+ /**
+ * Represents an arraylist of Task objects that can be modified.
+ */
+ public TaskList(String filepath) {
+ try {
+ list = Storage.stringToArraylistConverter(Storage.parseFileContentsToString(filepath));
+ } catch (FileNotFoundException e) {
+ System.out.println("Illegal file path");
+ }
+ }
+
+ /**
+ * Adds a Task object to the TaskList.
+ *
+ * @param line input from user indicating the task to be added.
+ * @throws EmptyToDoException If line is empty.
+ * @throws EmptyDeadlineException If line is empty.
+ * @throws EmptyEventsException If line is empty.
+ * @throws IndexOutOfBoundsException If line's input format violates that of Deadlines or Events object.
+ */
+ public void addTask(String line) {
+ Ui.addTaskSuccess();
+ try {
+ Task newTask = new Task(line);
+ if (line.startsWith("todo")) {
+ newTask = new ToDos(line);
+ } else if (line.startsWith("deadline")) {
+ newTask = new Deadlines(line);
+ } else if (line.startsWith("event")) {
+ newTask = new Events(line);
+ }
+ this.list.add(newTask);
+ Ui.printTask(newTask);
+ Ui.printListSize(this.list);
+ Storage.dukeDataStorage(Storage.arraylistToStringConverter(this.list));
+ } catch (EmptyToDoException e) {
+ System.out.println("Sire, you have yet to tell me what is it you want to do.");
+ } catch (EmptyDeadlineException e) {
+ System.out.println("Sire, what is it that is due your specified time?");
+ } catch (EmptyEventsException e) {
+ System.out.println("Sire, your event is unclear. Please specify.");
+ } catch (StringIndexOutOfBoundsException e) {
+ System.out.println("Don't hold back Sire. I am here to serve.");
+ }
+ }
+
+ /**
+ * Deletes the Task object from the TaskList.
+ *
+ * @param task input from user indicating the task to be deleted.
+ */
+ public void delete(String task) {
+ String indexOfTask = task.substring(DELETE_INDEX);
+ Ui.deleteSuccess(this.list, indexOfTask);
+ this.list.remove(Integer.parseInt(indexOfTask) - 1);
+ Ui.printListSize(this.list);
+ Storage.dukeDataStorage(Storage.arraylistToStringConverter(this.list));
+ }
+
+ /**
+ * Marks the Task object in the TaskList as done.
+ *
+ * @param task input from user indicating the task to be marked.
+ */
+ public void mark(String task) {
+ String indexOfTask = task.substring(MARK_INDEX); // get the number of task to be marked
+ Task taskToBeMarked = this.list.get(Integer.parseInt(indexOfTask) - 1); // convert from 1-based to 0-based
+ taskToBeMarked.markTask();
+ Ui.markSuccess(list, indexOfTask);
+ Storage.dukeDataStorage(Storage.arraylistToStringConverter(this.list));
+ }
+
+ /**
+ * Unmarks the Task object in the TaskList as undone.
+ *
+ * @param task input from user indicating the task to be unmarked.
+ */
+ public void unmark(String task) {
+ String indexOfTask = task.substring(UNMARK_INDEX);
+ Task taskToBeUnmarked = this.list.get(Integer.parseInt(indexOfTask) - 1);
+ taskToBeUnmarked.unmarkTask();
+ Ui.unmarkSuccess(list, indexOfTask);
+ Storage.dukeDataStorage(Storage.arraylistToStringConverter(this.list));
+ }
+
+ /**
+ * Prints the Task object in the TaskList.
+ *
+ * @param task task object to be printed.
+ */
+ public void printTasksFound (String task) {
+ String taskToBeFound = task.substring(FIND_INDEX);
+ Ui.findSuccess();
+ for (int i = 0; i < this.list.size(); ++i) {
+ if (this.list.get(i).getDescription().contains(taskToBeFound)) {
+ Ui.printTask(this.list.get(i));
+ }
+ }
+ }
+
+ /**
+ * Prints the current TaskList.
+ */
+ public void printCurrentList() {
+ Ui.printCurrentList(this.list);
+ }
+}
diff --git a/src/main/java/Duke/Ui.java b/src/main/java/Duke/Ui.java
new file mode 100644
index 000000000..aeff93d2d
--- /dev/null
+++ b/src/main/java/Duke/Ui.java
@@ -0,0 +1,110 @@
+package Duke;
+
+import Duke.Task.Task;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+
+public class Ui {
+ private Scanner scanner;
+ public Ui() {
+ this.scanner = new Scanner(System.in);
+ }
+
+ public void greet() {
+ String logo = " ____ _ \n"
+ + "| _ \\ _ _| | _____ \n"
+ + "| | | | | | | |/ / _ \\\n"
+ + "| |_| | |_| | < __/\n"
+ + "|____/ \\__,_|_|\\_\\___|\n";
+ System.out.println("Hello from\n" + logo);
+ try {
+ printFileContents("dukeData.txt");
+ } catch (FileNotFoundException e) {
+ printErrorMessage("File not found");
+ }
+ System.out.println("How may I be of service today?");
+ }
+
+ public void bye() {
+ System.out.println("Glad I could be of help!");
+ }
+
+ public String readCommand() {
+ return scanner.nextLine();
+ }
+
+ public static void addTaskSuccess() {
+ System.out.println("As per requested Sire, this task has been added to your calendar.");
+ }
+
+ public static void printTask(Task task) {
+ System.out.println(task);
+ }
+
+ public static void markSuccess(ArrayList list, String indexOfTask) {
+ System.out.println("Sir, your task has been marked as completed.");
+ System.out.println(list.get(Integer.parseInt(indexOfTask) - 1));
+ }
+
+ public static void unmarkSuccess(ArrayList list, String indexOfTask) {
+ System.out.println("Sir, your task has been unmarked as requested.");
+ System.out.println(list.get(Integer.parseInt(indexOfTask) - 1));
+ }
+
+ public static void deleteSuccess(ArrayList list, String indexOfTask) {
+ System.out.println("Sire, I have removed this task from your schedule");
+ System.out.println(list.get(Integer.parseInt(indexOfTask) - 1));
+ }
+
+ public static void findSuccess() {
+ System.out.println("Here are the matching items Sire:");
+ }
+
+ /**
+ * Prints out the number of elements in the list.
+ *
+ * @param list arraylist whose number of elements is to be printed out.
+ */
+ public static void printListSize(ArrayList list) {
+ System.out.println("You now have " + list.size() + " items left");
+ }
+
+ /**
+ * Prints out all tasks currently in the list.
+ *
+ * @param list arraylist whose elements are to be printed out.
+ */
+ public static void printCurrentList(ArrayList list) {
+ System.out.println("Your current list of items as requested, sir.");
+ for (int i = 0; i < list.size(); ++i) {
+ System.out.println((i + 1) + "." + list.get(i));
+ }
+ }
+
+ /**
+ * Prints out all tasks saved in the data file.
+ *
+ * @param filePath file path of the data file whose content is to be printed out.
+ * @throws FileNotFoundException If file path is invalid.
+ */
+ public void printFileContents(String filePath) throws FileNotFoundException {
+ File f = new File(filePath); // create a File for the given file path
+ if (!f.exists()) { // for first log in, there is no file
+ return;
+ }
+ System.out.println("Good day sire, I have listed down your current plan below for you:");
+ Scanner s = new Scanner(f); // create a Scanner using the File as the source
+ while (s.hasNext()) {
+ String taskStored = s.nextLine();
+ System.out.println(taskStored);
+ }
+ }
+ public void printErrorMessage(String errorMessage) {
+ System.out.println(errorMessage);
+ }
+}
+
diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..76381b309
--- /dev/null
+++ b/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: Duke.Duke
+
diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT
index 657e74f6e..15687aa33 100644
--- a/text-ui-test/EXPECTED.TXT
+++ b/text-ui-test/EXPECTED.TXT
@@ -5,3 +5,5 @@ Hello from
| |_| | |_| | < __/
|____/ \__,_|_|\_\___|
+How may I be of service?
+Glad I could be of help!
diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt
index e69de29bb..441df48b6 100644
--- a/text-ui-test/input.txt
+++ b/text-ui-test/input.txt
@@ -0,0 +1,2 @@
+todo CS2113 assignment
+bye
\ No newline at end of file