From 3174bce0d90e390ca7a047411b9f91bae3340dbe Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Tue, 5 Sep 2023 20:32:30 +0800
Subject: [PATCH 01/20] Level 0. Rename, Greet, Exit

---
 src/main/java/Duke.java | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index 5d313334c..3cf79732d 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -1,10 +1,12 @@
 public class Duke {
     public static void main(String[] args) {
-        String logo = " ____        _        \n"
-                + "|  _ \\ _   _| | _____ \n"
-                + "| | | | | | | |/ / _ \\\n"
-                + "| |_| | |_| |   <  __/\n"
-                + "|____/ \\__,_|_|\\_\\___|\n";
-        System.out.println("Hello from\n" + logo);
+        String intro = "Hello! I'm Wenny!\n"
+                        + "How may I help you?\n";
+        System.out.println(intro);
+
+        bye();
+    }
+    public static void bye() {
+        System.out.println("Bye. Hope to see you again soon!");
     }
 }

From 3015c0c66abaa07acf1c910baf8cc70628f3bd08 Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Tue, 5 Sep 2023 20:47:19 +0800
Subject: [PATCH 02/20] Level 1. Echo

---
 src/main/java/Duke.java | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index 3cf79732d..1580d6dd4 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -1,12 +1,20 @@
+import java.util.Scanner;
 public class Duke {
     public static void main(String[] args) {
         String intro = "Hello! I'm Wenny!\n"
                         + "How may I help you?\n";
         System.out.println(intro);
-
-        bye();
+        while (true) {
+            Scanner scanner = new Scanner(System.in);
+            String userInput = scanner.nextLine();
+            System.out.println(userInput);
+            if (userInput.equals("bye")) {
+                bye();
+            }
+        }
     }
     public static void bye() {
         System.out.println("Bye. Hope to see you again soon!");
+        System.exit(0);
     }
 }

From f21bf134b9d9e6ddc462559bab3df1c91b589e92 Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Tue, 5 Sep 2023 21:25:28 +0800
Subject: [PATCH 03/20] Renamed Duke. Added greetings.

---
 src/main/java/Duke.java |  8 +++++++-
 src/main/java/List.java | 25 +++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 1 deletion(-)
 create mode 100644 src/main/java/List.java

diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index 1580d6dd4..edc326408 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -1,15 +1,20 @@
 import java.util.Scanner;
 public class Duke {
     public static void main(String[] args) {
+        // Greetings
         String intro = "Hello! I'm Wenny!\n"
                         + "How may I help you?\n";
         System.out.println(intro);
+        List list = new List();
         while (true) {
             Scanner scanner = new Scanner(System.in);
             String userInput = scanner.nextLine();
-            System.out.println(userInput);
             if (userInput.equals("bye")) {
                 bye();
+            } else if (userInput.equals("list")) {
+                list.print_list();
+            } else {
+                list.add_to_list(userInput);
             }
         }
     }
@@ -17,4 +22,5 @@ public static void bye() {
         System.out.println("Bye. Hope to see you again soon!");
         System.exit(0);
     }
+
 }
diff --git a/src/main/java/List.java b/src/main/java/List.java
new file mode 100644
index 000000000..fa482158f
--- /dev/null
+++ b/src/main/java/List.java
@@ -0,0 +1,25 @@
+public class List {
+    private String[] list;
+    private int counter;
+
+    public List() {
+        this.list = new String[100];
+        this.counter = 0;
+    }
+
+    public void print_list() {
+        if (this.counter == 0) {
+            System.out.println("No Entry");
+            return;
+        }
+        for (int i=0; i<this.counter; i++) {
+            System.out.println((i+1) + ". " + this.list[i]);
+        }
+    }
+
+    public void add_to_list(String arg) {
+        this.list[this.counter] = arg;
+        this.counter++;
+        System.out.println("added: " + arg);
+    }
+}

From 46b895f34772ae0839484d5bbd5f717f60e4f172 Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Wed, 6 Sep 2023 00:12:53 +0800
Subject: [PATCH 04/20] Renamed list as tasks. Added isDone flag and
 markAsDone, markAsUndone functions.

---
 src/main/java/Duke.java | 13 ++++++++++---
 src/main/java/List.java | 25 ------------------------
 src/main/java/Task.java | 43 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 53 insertions(+), 28 deletions(-)
 delete mode 100644 src/main/java/List.java
 create mode 100644 src/main/java/Task.java

diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index edc326408..44cc575b9 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -5,16 +5,23 @@ public static void main(String[] args) {
         String intro = "Hello! I'm Wenny!\n"
                         + "How may I help you?\n";
         System.out.println(intro);
-        List list = new List();
+        Task tasks = new Task();
         while (true) {
             Scanner scanner = new Scanner(System.in);
             String userInput = scanner.nextLine();
             if (userInput.equals("bye")) {
                 bye();
             } else if (userInput.equals("list")) {
-                list.print_list();
+                tasks.print_tasks();
             } else {
-                list.add_to_list(userInput);
+                String[] substr = userInput.split("\\s+");
+                if (substr[0].equals("mark")) {
+                    tasks.markAsDone(Integer.parseInt(substr[1]));
+                } else if (substr[0].equals("unmark")) {
+                    tasks.markAsUndone(Integer.parseInt(substr[1]));
+                } else {
+                    tasks.add_to_tasks(userInput);
+                }
             }
         }
     }
diff --git a/src/main/java/List.java b/src/main/java/List.java
deleted file mode 100644
index fa482158f..000000000
--- a/src/main/java/List.java
+++ /dev/null
@@ -1,25 +0,0 @@
-public class List {
-    private String[] list;
-    private int counter;
-
-    public List() {
-        this.list = new String[100];
-        this.counter = 0;
-    }
-
-    public void print_list() {
-        if (this.counter == 0) {
-            System.out.println("No Entry");
-            return;
-        }
-        for (int i=0; i<this.counter; i++) {
-            System.out.println((i+1) + ". " + this.list[i]);
-        }
-    }
-
-    public void add_to_list(String arg) {
-        this.list[this.counter] = arg;
-        this.counter++;
-        System.out.println("added: " + arg);
-    }
-}
diff --git a/src/main/java/Task.java b/src/main/java/Task.java
new file mode 100644
index 000000000..2ab22e3de
--- /dev/null
+++ b/src/main/java/Task.java
@@ -0,0 +1,43 @@
+public class Task {
+    private String[] tasks;
+    private int taskCount;
+    private boolean[] isDone;
+    public Task() {
+        this.tasks = new String[100];
+        this.taskCount = 0;
+        this.isDone = new boolean[100]; // False by default
+    }
+
+    public void print_tasks() {
+        if (this.taskCount == 0) {
+            System.out.println("No Entry");
+            return;
+        }
+        for (int i = 0; i<this.taskCount; i++) {
+            System.out.print((i+1) + ".");
+            if (isDone[i]) {
+                System.out.print("[X] ");
+            } else {
+                System.out.print("[ ] ");
+            }
+            System.out.println(this.tasks[i]);
+        }
+    }
+
+    public void add_to_tasks(String details) {
+        this.tasks[this.taskCount] = details;
+        this.taskCount++;
+        System.out.println("added: " + details);
+    }
+    public void markAsDone(int number) {
+        isDone[number-1] = true;
+        System.out.println("Nice! I've market this task as done:");
+        System.out.println("[X] " + tasks[number-1]);
+    }
+
+    public void markAsUndone(int number) {
+        isDone[number-1] = false;
+        System.out.println("Nice! I've market this task as not done yet:");
+        System.out.println("[ ] " + tasks[number-1]);
+    }
+}

From bbc2effa6f923ab5548ed334d6792457138e10b0 Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Thu, 7 Sep 2023 01:10:56 +0800
Subject: [PATCH 05/20] Add ToDos, Events, Deadlines

ToDos, Events, Deadlines are created as a subclass of Task.

Moved addToTask and printTask from Task class to Main program.
---
 src/main/java/Deadlines.java | 18 +++++++
 src/main/java/Duke.java      | 92 ++++++++++++++++++++++++++++++------
 src/main/java/Events.java    | 31 ++++++++++++
 src/main/java/Task.java      | 55 +++++++++------------
 src/main/java/ToDos.java     | 10 ++++
 src/main/java/Type.java      |  3 ++
 6 files changed, 161 insertions(+), 48 deletions(-)
 create mode 100644 src/main/java/Deadlines.java
 create mode 100644 src/main/java/Events.java
 create mode 100644 src/main/java/ToDos.java
 create mode 100644 src/main/java/Type.java

diff --git a/src/main/java/Deadlines.java b/src/main/java/Deadlines.java
new file mode 100644
index 000000000..d07873fdd
--- /dev/null
+++ b/src/main/java/Deadlines.java
@@ -0,0 +1,18 @@
+public class Deadlines extends Task {
+    String by;
+    public Deadlines(String description, String by) {
+        super(description);
+        this.by = by;
+    }
+    public String getBy() {
+        return by;
+    }
+    public void setBy(String by) {
+        this.by = by;
+    }
+    public String toString() {
+        return "[D]" + super.toString() + " (by: " + by + ")";
+    }
+
+
+}
diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index 44cc575b9..b945a6b4d 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -1,27 +1,89 @@
 import java.util.Scanner;
 public class Duke {
+    private static Task[] tasks = new Task[100];
+    private static int taskCount = 0;
+
+    public static void addToTasks(String description, Type type) {
+        switch (type) {
+        case TODO:
+            tasks[taskCount] = new ToDos(description);
+            break;
+        case DEADLINE:
+            int i = description.indexOf("/");
+            String by = description.substring(i+4);
+            description = description.substring(0, i).trim();
+            tasks[taskCount] = new Deadlines(description, by);
+            break;
+        case EVENT:
+            int j = description.indexOf("/");
+            int k = description.indexOf("/", j+1);
+            String from = description.substring(j+6, k).trim();
+            String to = description.substring(k+4);
+            description = description.substring(0, j).trim();
+            tasks[taskCount] = new Events(description, from, to);
+            break;
+        }
+        taskCount++;
+        System.out.println("\tGot it. I've added this task:");
+        System.out.println("\t" + tasks[taskCount-1]);
+        System.out.println("\tNow you have " + taskCount + " task(s) in the list.");
+    }
+    public static void printTasks() {
+        if (taskCount == 0) {
+            System.out.println("\tYou do not have any task in the list.");
+            return;
+        }
+        System.out.println("\tHere are the tasks in your list:");
+        for (int i=0; i<taskCount; i++) {
+            System.out.print("\t");
+            System.out.print(i+1 + ".");
+            System.out.println(tasks[i]);
+        }
+    }
+    public static void markAsDone(int number) {
+        tasks[number-1].setDone(true);
+        System.out.println("\tNice! I've marked this task as done:");
+        System.out.println("\t" + tasks[number-1]);
+    }
+    public static void markAsUndone(int number) {
+        tasks[number-1].setDone(false);
+        System.out.println("\tNice! I've marked this task as not done yet:");
+        System.out.println("\t" + tasks[number-1]);
+    }
+
     public static void main(String[] args) {
         // Greetings
-        String intro = "Hello! I'm Wenny!\n"
-                        + "How may I help you?\n";
+        String intro = "~~~~~~~~~~~~~~~~~~~\n"
+                        + "Hello! I'm Wenny!\n"
+                        + "How may I help you?\n"
+                        + "~~~~~~~~~~~~~~~~~~~";
         System.out.println(intro);
-        Task tasks = new Task();
         while (true) {
             Scanner scanner = new Scanner(System.in);
             String userInput = scanner.nextLine();
-            if (userInput.equals("bye")) {
+            String[] substr = userInput.split("\\s+");
+            switch (substr[0]) {
+            case "bye":
                 bye();
-            } else if (userInput.equals("list")) {
-                tasks.print_tasks();
-            } else {
-                String[] substr = userInput.split("\\s+");
-                if (substr[0].equals("mark")) {
-                    tasks.markAsDone(Integer.parseInt(substr[1]));
-                } else if (substr[0].equals("unmark")) {
-                    tasks.markAsUndone(Integer.parseInt(substr[1]));
-                } else {
-                    tasks.add_to_tasks(userInput);
-                }
+                break;
+            case "list":
+                printTasks();
+                break;
+            case "mark":
+                markAsDone(Integer.parseInt(substr[1]));
+                break;
+            case "unmark":
+                markAsUndone(Integer.parseInt(substr[1]));
+                break;
+            case "todo":
+                addToTasks(userInput.substring(5), Type.TODO);
+                break;
+            case "deadline":
+                addToTasks(userInput.substring(9), Type.DEADLINE);
+                break;
+            case "event":
+                addToTasks(userInput.substring(6), Type.EVENT);
+                break;
             }
         }
     }
diff --git a/src/main/java/Events.java b/src/main/java/Events.java
new file mode 100644
index 000000000..a6c20c8da
--- /dev/null
+++ b/src/main/java/Events.java
@@ -0,0 +1,31 @@
+public class Events extends Task {
+    String from;
+    String to;
+
+    public Events(String description, String from, String to) {
+        super(description);
+        setFrom(from);
+        setTo(to);
+    }
+
+    public String getFrom() {
+        return from;
+    }
+
+    public void setFrom(String from) {
+        this.from = from;
+    }
+
+    public String getTo() {
+        return to;
+    }
+
+    public void setTo(String to) {
+        this.to = to;
+    }
+
+    public String toString() {
+        return "[E]" + super.toString() + " (from: " + from + ", to: " + to + ")";
+    }
+}
+
diff --git a/src/main/java/Task.java b/src/main/java/Task.java
index 2ab22e3de..9c2a8716c 100644
--- a/src/main/java/Task.java
+++ b/src/main/java/Task.java
@@ -1,43 +1,32 @@
 public class Task {
-    private String[] tasks;
-    private int taskCount;
-    private boolean[] isDone;
-    public Task() {
-        this.tasks = new String[100];
-        this.taskCount = 0;
-        this.isDone = new boolean[100]; // False by default
+    private String description;
+    private boolean isDone;
+    public Task(String description) {
+        setDescription(description);
+        setDone(false);
     }
 
-    public void print_tasks() {
-        if (this.taskCount == 0) {
-            System.out.println("No Entry");
-            return;
-        }
-        for (int i = 0; i<this.taskCount; i++) {
-            System.out.print((i+1) + ".");
-            if (isDone[i]) {
-                System.out.print("[X] ");
-            } else {
-                System.out.print("[ ] ");
-            }
-            System.out.println(this.tasks[i]);
-        }
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
     }
 
-    public void add_to_tasks(String details) {
-        this.tasks[this.taskCount] = details;
-        this.taskCount++;
-        System.out.println("added: " + details);
+    public boolean isDone() {
+        return isDone;
     }
-    public void markAsDone(int number) {
-        isDone[number-1] = true;
-        System.out.println("Nice! I've market this task as done:");
-        System.out.println("[X] " + tasks[number-1]);
+
+    public void setDone(boolean done) {
+        isDone = done;
     }
 
-    public void markAsUndone(int number) {
-        isDone[number-1] = false;
-        System.out.println("Nice! I've market this task as not done yet:");
-        System.out.println("[ ] " + tasks[number-1]);
+    public String toString() {
+        String temp = "[ ]";
+        if (isDone) {
+            temp = "[X]";
+        }
+        return temp + " " + description;
     }
 }
diff --git a/src/main/java/ToDos.java b/src/main/java/ToDos.java
new file mode 100644
index 000000000..7aac2e775
--- /dev/null
+++ b/src/main/java/ToDos.java
@@ -0,0 +1,10 @@
+public class ToDos extends Task {
+
+    public ToDos(String description) {
+        super(description);
+    }
+
+    public String toString() {
+        return "[T]" + super.toString();
+    }
+}
diff --git a/src/main/java/Type.java b/src/main/java/Type.java
new file mode 100644
index 000000000..39d0667be
--- /dev/null
+++ b/src/main/java/Type.java
@@ -0,0 +1,3 @@
+public enum Type {
+    TODO, DEADLINE, EVENT
+}

From aa3631e6cd4e528c82d125bdcc299d5f508a25f7 Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Wed, 13 Sep 2023 15:13:57 +0800
Subject: [PATCH 06/20] Make changes to various variable name

---
 src/main/java/Duke.java | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index b945a6b4d..2b3c965b5 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -9,17 +9,17 @@ public static void addToTasks(String description, Type type) {
             tasks[taskCount] = new ToDos(description);
             break;
         case DEADLINE:
-            int i = description.indexOf("/");
-            String by = description.substring(i+4);
-            description = description.substring(0, i).trim();
+            String[] deadlineTokens = description.split("/by");
+            description = deadlineTokens[0].trim();
+            String by = deadlineTokens[1].trim();
             tasks[taskCount] = new Deadlines(description, by);
             break;
         case EVENT:
-            int j = description.indexOf("/");
-            int k = description.indexOf("/", j+1);
-            String from = description.substring(j+6, k).trim();
-            String to = description.substring(k+4);
-            description = description.substring(0, j).trim();
+            String[] eventTokens = description.split("/from");
+            description = eventTokens[0].trim();
+            eventTokens = eventTokens[1].split("/to");
+            String from = eventTokens[0].trim();
+            String to = eventTokens[1].trim();
             tasks[taskCount] = new Events(description, from, to);
             break;
         }
@@ -64,7 +64,7 @@ public static void main(String[] args) {
             String[] substr = userInput.split("\\s+");
             switch (substr[0]) {
             case "bye":
-                bye();
+                printByeMessage();
                 break;
             case "list":
                 printTasks();
@@ -84,10 +84,12 @@ public static void main(String[] args) {
             case "event":
                 addToTasks(userInput.substring(6), Type.EVENT);
                 break;
+            default:
+                System.out.println("\tInvalid input, please try again");
             }
         }
     }
-    public static void bye() {
+    public static void printByeMessage() {
         System.out.println("Bye. Hope to see you again soon!");
         System.exit(0);
     }

From 2e8d61b993b9164318c618422d2e99bef2e6b156 Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Sat, 30 Sep 2023 02:28:20 +0800
Subject: [PATCH 07/20] Add Exceptions

---
 src/main/java/Deadlines.java |  2 +
 src/main/java/Duke.java      | 84 +++++++++++++++++++++++++-----------
 src/main/java/Events.java    |  2 +-
 src/main/java/Task.java      |  9 ++--
 src/main/java/ToDos.java     |  1 +
 5 files changed, 67 insertions(+), 31 deletions(-)

diff --git a/src/main/java/Deadlines.java b/src/main/java/Deadlines.java
index d07873fdd..b0a6dbd51 100644
--- a/src/main/java/Deadlines.java
+++ b/src/main/java/Deadlines.java
@@ -10,6 +10,8 @@ public String getBy() {
     public void setBy(String by) {
         this.by = by;
     }
+
+    @Override
     public String toString() {
         return "[D]" + super.toString() + " (by: " + by + ")";
     }
diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index 2b3c965b5..8b996b10f 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -1,3 +1,4 @@
+import javax.sound.midi.SysexMessage;
 import java.util.Scanner;
 public class Duke {
     private static Task[] tasks = new Task[100];
@@ -9,19 +10,29 @@ public static void addToTasks(String description, Type type) {
             tasks[taskCount] = new ToDos(description);
             break;
         case DEADLINE:
-            String[] deadlineTokens = description.split("/by");
-            description = deadlineTokens[0].trim();
-            String by = deadlineTokens[1].trim();
-            tasks[taskCount] = new Deadlines(description, by);
-            break;
+            try {
+                String[] deadlineTokens = description.split("/by");
+                description = deadlineTokens[0].trim();
+                String by = deadlineTokens[1].trim();
+                tasks[taskCount] = new Deadlines(description, by);
+                break;
+            } catch (IndexOutOfBoundsException e) {
+                System.out.println("\t/by could not be found");
+                return;
+            }
         case EVENT:
-            String[] eventTokens = description.split("/from");
-            description = eventTokens[0].trim();
-            eventTokens = eventTokens[1].split("/to");
-            String from = eventTokens[0].trim();
-            String to = eventTokens[1].trim();
-            tasks[taskCount] = new Events(description, from, to);
-            break;
+            try {
+                String[] eventTokens = description.split("/from");
+                description = eventTokens[0].trim();
+                eventTokens = eventTokens[1].split("/to");
+                String from = eventTokens[0].trim();
+                String to = eventTokens[1].trim();
+                tasks[taskCount] = new Events(description, from, to);
+                break;
+            } catch (IndexOutOfBoundsException e) {
+                System.out.println("\tBoth /from and /to are required");
+                return;
+            }
         }
         taskCount++;
         System.out.println("\tGot it. I've added this task:");
@@ -41,14 +52,22 @@ public static void printTasks() {
         }
     }
     public static void markAsDone(int number) {
-        tasks[number-1].setDone(true);
-        System.out.println("\tNice! I've marked this task as done:");
-        System.out.println("\t" + tasks[number-1]);
+        try {
+            tasks[number-1].setDone(true);
+            System.out.println("\tNice! I've marked this task as done:");
+            System.out.println("\t" + tasks[number-1]);
+        } catch (NullPointerException e) {
+            System.out.println("\tOops! task " + number + " does not exist");
+        }
     }
     public static void markAsUndone(int number) {
-        tasks[number-1].setDone(false);
-        System.out.println("\tNice! I've marked this task as not done yet:");
-        System.out.println("\t" + tasks[number-1]);
+        try {
+            tasks[number - 1].setDone(false);
+            System.out.println("\tNice! I've marked this task as not done yet:");
+            System.out.println("\t" + tasks[number - 1]);
+        } catch (NullPointerException e) {
+            System.out.println("\tOops! task " + number + " does not exist");
+        }
     }
 
     public static void main(String[] args) {
@@ -61,7 +80,7 @@ public static void main(String[] args) {
         while (true) {
             Scanner scanner = new Scanner(System.in);
             String userInput = scanner.nextLine();
-            String[] substr = userInput.split("\\s+");
+            String[] substr = userInput.split("\\s+", 2);
             switch (substr[0]) {
             case "bye":
                 printByeMessage();
@@ -76,14 +95,29 @@ public static void main(String[] args) {
                 markAsUndone(Integer.parseInt(substr[1]));
                 break;
             case "todo":
-                addToTasks(userInput.substring(5), Type.TODO);
-                break;
+                try {
+                    addToTasks(substr[1], Type.TODO);
+                    break;
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    System.out.println("\tDescription of a todo cannot be empty");
+                    break;
+                }
             case "deadline":
-                addToTasks(userInput.substring(9), Type.DEADLINE);
-                break;
+                try {
+                    addToTasks(substr[1], Type.DEADLINE);
+                    break;
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    System.out.println("\tDescription of a deadline cannot be empty");
+                    break;
+                }
             case "event":
-                addToTasks(userInput.substring(6), Type.EVENT);
-                break;
+                try {
+                    addToTasks(substr[1], Type.EVENT);
+                    break;
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    System.out.println("\tDescription of a event cannot be empty");
+                    break;
+                }
             default:
                 System.out.println("\tInvalid input, please try again");
             }
diff --git a/src/main/java/Events.java b/src/main/java/Events.java
index a6c20c8da..61a153ce4 100644
--- a/src/main/java/Events.java
+++ b/src/main/java/Events.java
@@ -23,7 +23,7 @@ public String getTo() {
     public void setTo(String to) {
         this.to = to;
     }
-
+    @Override
     public String toString() {
         return "[E]" + super.toString() + " (from: " + from + ", to: " + to + ")";
     }
diff --git a/src/main/java/Task.java b/src/main/java/Task.java
index 9c2a8716c..d7b6f7c1f 100644
--- a/src/main/java/Task.java
+++ b/src/main/java/Task.java
@@ -22,11 +22,10 @@ public void setDone(boolean done) {
         isDone = done;
     }
 
+    private String getStatus() {
+        return isDone() ? "[X]" : "[ ]";
+    }
     public String toString() {
-        String temp = "[ ]";
-        if (isDone) {
-            temp = "[X]";
-        }
-        return temp + " " + description;
+        return getStatus() + " " + description;
     }
 }
diff --git a/src/main/java/ToDos.java b/src/main/java/ToDos.java
index 7aac2e775..379202e57 100644
--- a/src/main/java/ToDos.java
+++ b/src/main/java/ToDos.java
@@ -4,6 +4,7 @@ public ToDos(String description) {
         super(description);
     }
 
+    @Override
     public String toString() {
         return "[T]" + super.toString();
     }

From 4f314bf1868b6730af810560c7d36d7099fddd6d Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Sat, 30 Sep 2023 02:29:52 +0800
Subject: [PATCH 08/20] Revert "Add Exceptions"

This reverts commit 2e8d61b993b9164318c618422d2e99bef2e6b156.
---
 src/main/java/Deadlines.java |  2 -
 src/main/java/Duke.java      | 84 +++++++++++-------------------------
 src/main/java/Events.java    |  2 +-
 src/main/java/Task.java      |  9 ++--
 src/main/java/ToDos.java     |  1 -
 5 files changed, 31 insertions(+), 67 deletions(-)

diff --git a/src/main/java/Deadlines.java b/src/main/java/Deadlines.java
index b0a6dbd51..d07873fdd 100644
--- a/src/main/java/Deadlines.java
+++ b/src/main/java/Deadlines.java
@@ -10,8 +10,6 @@ public String getBy() {
     public void setBy(String by) {
         this.by = by;
     }
-
-    @Override
     public String toString() {
         return "[D]" + super.toString() + " (by: " + by + ")";
     }
diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index 8b996b10f..2b3c965b5 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -1,4 +1,3 @@
-import javax.sound.midi.SysexMessage;
 import java.util.Scanner;
 public class Duke {
     private static Task[] tasks = new Task[100];
@@ -10,29 +9,19 @@ public static void addToTasks(String description, Type type) {
             tasks[taskCount] = new ToDos(description);
             break;
         case DEADLINE:
-            try {
-                String[] deadlineTokens = description.split("/by");
-                description = deadlineTokens[0].trim();
-                String by = deadlineTokens[1].trim();
-                tasks[taskCount] = new Deadlines(description, by);
-                break;
-            } catch (IndexOutOfBoundsException e) {
-                System.out.println("\t/by could not be found");
-                return;
-            }
+            String[] deadlineTokens = description.split("/by");
+            description = deadlineTokens[0].trim();
+            String by = deadlineTokens[1].trim();
+            tasks[taskCount] = new Deadlines(description, by);
+            break;
         case EVENT:
-            try {
-                String[] eventTokens = description.split("/from");
-                description = eventTokens[0].trim();
-                eventTokens = eventTokens[1].split("/to");
-                String from = eventTokens[0].trim();
-                String to = eventTokens[1].trim();
-                tasks[taskCount] = new Events(description, from, to);
-                break;
-            } catch (IndexOutOfBoundsException e) {
-                System.out.println("\tBoth /from and /to are required");
-                return;
-            }
+            String[] eventTokens = description.split("/from");
+            description = eventTokens[0].trim();
+            eventTokens = eventTokens[1].split("/to");
+            String from = eventTokens[0].trim();
+            String to = eventTokens[1].trim();
+            tasks[taskCount] = new Events(description, from, to);
+            break;
         }
         taskCount++;
         System.out.println("\tGot it. I've added this task:");
@@ -52,22 +41,14 @@ public static void printTasks() {
         }
     }
     public static void markAsDone(int number) {
-        try {
-            tasks[number-1].setDone(true);
-            System.out.println("\tNice! I've marked this task as done:");
-            System.out.println("\t" + tasks[number-1]);
-        } catch (NullPointerException e) {
-            System.out.println("\tOops! task " + number + " does not exist");
-        }
+        tasks[number-1].setDone(true);
+        System.out.println("\tNice! I've marked this task as done:");
+        System.out.println("\t" + tasks[number-1]);
     }
     public static void markAsUndone(int number) {
-        try {
-            tasks[number - 1].setDone(false);
-            System.out.println("\tNice! I've marked this task as not done yet:");
-            System.out.println("\t" + tasks[number - 1]);
-        } catch (NullPointerException e) {
-            System.out.println("\tOops! task " + number + " does not exist");
-        }
+        tasks[number-1].setDone(false);
+        System.out.println("\tNice! I've marked this task as not done yet:");
+        System.out.println("\t" + tasks[number-1]);
     }
 
     public static void main(String[] args) {
@@ -80,7 +61,7 @@ public static void main(String[] args) {
         while (true) {
             Scanner scanner = new Scanner(System.in);
             String userInput = scanner.nextLine();
-            String[] substr = userInput.split("\\s+", 2);
+            String[] substr = userInput.split("\\s+");
             switch (substr[0]) {
             case "bye":
                 printByeMessage();
@@ -95,29 +76,14 @@ public static void main(String[] args) {
                 markAsUndone(Integer.parseInt(substr[1]));
                 break;
             case "todo":
-                try {
-                    addToTasks(substr[1], Type.TODO);
-                    break;
-                } catch (ArrayIndexOutOfBoundsException e) {
-                    System.out.println("\tDescription of a todo cannot be empty");
-                    break;
-                }
+                addToTasks(userInput.substring(5), Type.TODO);
+                break;
             case "deadline":
-                try {
-                    addToTasks(substr[1], Type.DEADLINE);
-                    break;
-                } catch (ArrayIndexOutOfBoundsException e) {
-                    System.out.println("\tDescription of a deadline cannot be empty");
-                    break;
-                }
+                addToTasks(userInput.substring(9), Type.DEADLINE);
+                break;
             case "event":
-                try {
-                    addToTasks(substr[1], Type.EVENT);
-                    break;
-                } catch (ArrayIndexOutOfBoundsException e) {
-                    System.out.println("\tDescription of a event cannot be empty");
-                    break;
-                }
+                addToTasks(userInput.substring(6), Type.EVENT);
+                break;
             default:
                 System.out.println("\tInvalid input, please try again");
             }
diff --git a/src/main/java/Events.java b/src/main/java/Events.java
index 61a153ce4..a6c20c8da 100644
--- a/src/main/java/Events.java
+++ b/src/main/java/Events.java
@@ -23,7 +23,7 @@ public String getTo() {
     public void setTo(String to) {
         this.to = to;
     }
-    @Override
+
     public String toString() {
         return "[E]" + super.toString() + " (from: " + from + ", to: " + to + ")";
     }
diff --git a/src/main/java/Task.java b/src/main/java/Task.java
index d7b6f7c1f..9c2a8716c 100644
--- a/src/main/java/Task.java
+++ b/src/main/java/Task.java
@@ -22,10 +22,11 @@ public void setDone(boolean done) {
         isDone = done;
     }
 
-    private String getStatus() {
-        return isDone() ? "[X]" : "[ ]";
-    }
     public String toString() {
-        return getStatus() + " " + description;
+        String temp = "[ ]";
+        if (isDone) {
+            temp = "[X]";
+        }
+        return temp + " " + description;
     }
 }
diff --git a/src/main/java/ToDos.java b/src/main/java/ToDos.java
index 379202e57..7aac2e775 100644
--- a/src/main/java/ToDos.java
+++ b/src/main/java/ToDos.java
@@ -4,7 +4,6 @@ public ToDos(String description) {
         super(description);
     }
 
-    @Override
     public String toString() {
         return "[T]" + super.toString();
     }

From 226c2292a934e23e524f1dbccbe4f3b3e772853b Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Sat, 30 Sep 2023 02:37:14 +0800
Subject: [PATCH 09/20] Handled exceptions

---
 src/main/java/Duke.java | 90 ++++++++++++++++++++++++++++-------------
 1 file changed, 62 insertions(+), 28 deletions(-)

diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index 2b3c965b5..a70583927 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -1,3 +1,4 @@
+import javax.sound.midi.SysexMessage;
 import java.util.Scanner;
 public class Duke {
     private static Task[] tasks = new Task[100];
@@ -9,19 +10,29 @@ public static void addToTasks(String description, Type type) {
             tasks[taskCount] = new ToDos(description);
             break;
         case DEADLINE:
-            String[] deadlineTokens = description.split("/by");
-            description = deadlineTokens[0].trim();
-            String by = deadlineTokens[1].trim();
-            tasks[taskCount] = new Deadlines(description, by);
-            break;
+            try {
+                String[] deadlineTokens = description.split("/by");
+                description = deadlineTokens[0].trim();
+                String by = deadlineTokens[1].trim();
+                tasks[taskCount] = new Deadlines(description, by);
+                break;
+            } catch (IndexOutOfBoundsException e) {
+                System.out.println("\t/by could not be found");
+                return;
+            }
         case EVENT:
-            String[] eventTokens = description.split("/from");
-            description = eventTokens[0].trim();
-            eventTokens = eventTokens[1].split("/to");
-            String from = eventTokens[0].trim();
-            String to = eventTokens[1].trim();
-            tasks[taskCount] = new Events(description, from, to);
-            break;
+            try {
+                String[] eventTokens = description.split("/from");
+                description = eventTokens[0].trim();
+                eventTokens = eventTokens[1].split("/to");
+                String from = eventTokens[0].trim();
+                String to = eventTokens[1].trim();
+                tasks[taskCount] = new Events(description, from, to);
+                break;
+            } catch (IndexOutOfBoundsException e) {
+                System.out.println("\tBoth /from and /to are required");
+                return;
+            }
         }
         taskCount++;
         System.out.println("\tGot it. I've added this task:");
@@ -41,27 +52,35 @@ public static void printTasks() {
         }
     }
     public static void markAsDone(int number) {
-        tasks[number-1].setDone(true);
-        System.out.println("\tNice! I've marked this task as done:");
-        System.out.println("\t" + tasks[number-1]);
+        try {
+            tasks[number-1].setDone(true);
+            System.out.println("\tNice! I've marked this task as done:");
+            System.out.println("\t" + tasks[number-1]);
+        } catch (NullPointerException e) {
+            System.out.println("\tOops! task " + number + " does not exist");
+        }
     }
     public static void markAsUndone(int number) {
-        tasks[number-1].setDone(false);
-        System.out.println("\tNice! I've marked this task as not done yet:");
-        System.out.println("\t" + tasks[number-1]);
+        try {
+            tasks[number - 1].setDone(false);
+            System.out.println("\tNice! I've marked this task as not done yet:");
+            System.out.println("\t" + tasks[number - 1]);
+        } catch (NullPointerException e) {
+            System.out.println("\tOops! task " + number + " does not exist");
+        }
     }
 
     public static void main(String[] args) {
         // Greetings
         String intro = "~~~~~~~~~~~~~~~~~~~\n"
-                        + "Hello! I'm Wenny!\n"
-                        + "How may I help you?\n"
-                        + "~~~~~~~~~~~~~~~~~~~";
+                + "Hello! I'm Wenny!\n"
+                + "How may I help you?\n"
+                + "~~~~~~~~~~~~~~~~~~~";
         System.out.println(intro);
         while (true) {
             Scanner scanner = new Scanner(System.in);
             String userInput = scanner.nextLine();
-            String[] substr = userInput.split("\\s+");
+            String[] substr = userInput.split("\\s+", 2);
             switch (substr[0]) {
             case "bye":
                 printByeMessage();
@@ -76,14 +95,29 @@ public static void main(String[] args) {
                 markAsUndone(Integer.parseInt(substr[1]));
                 break;
             case "todo":
-                addToTasks(userInput.substring(5), Type.TODO);
-                break;
+                try {
+                    addToTasks(substr[1], Type.TODO);
+                    break;
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    System.out.println("\tDescription of a todo cannot be empty");
+                    break;
+                }
             case "deadline":
-                addToTasks(userInput.substring(9), Type.DEADLINE);
-                break;
+                try {
+                    addToTasks(substr[1], Type.DEADLINE);
+                    break;
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    System.out.println("\tDescription of a deadline cannot be empty");
+                    break;
+                }
             case "event":
-                addToTasks(userInput.substring(6), Type.EVENT);
-                break;
+                try {
+                    addToTasks(substr[1], Type.EVENT);
+                    break;
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    System.out.println("\tDescription of a event cannot be empty");
+                    break;
+                }
             default:
                 System.out.println("\tInvalid input, please try again");
             }

From 111b4d19a35204cc53bd1340b67467c9c24a3ada Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Sat, 30 Sep 2023 03:17:39 +0800
Subject: [PATCH 10/20] Add support for deleting tasks from the list

---
 src/main/java/Duke.java | 44 ++++++++++++++++++++++++++++-------------
 1 file changed, 30 insertions(+), 14 deletions(-)

diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index a70583927..d1acc5fbd 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -1,20 +1,21 @@
 import javax.sound.midi.SysexMessage;
+import java.util.ArrayList;
 import java.util.Scanner;
 public class Duke {
-    private static Task[] tasks = new Task[100];
+    private static ArrayList<Task> tasks = new ArrayList<>();
     private static int taskCount = 0;
 
     public static void addToTasks(String description, Type type) {
         switch (type) {
         case TODO:
-            tasks[taskCount] = new ToDos(description);
+            tasks.add(new ToDos(description));
             break;
         case DEADLINE:
             try {
                 String[] deadlineTokens = description.split("/by");
                 description = deadlineTokens[0].trim();
                 String by = deadlineTokens[1].trim();
-                tasks[taskCount] = new Deadlines(description, by);
+                tasks.add(new Deadlines(description, by));
                 break;
             } catch (IndexOutOfBoundsException e) {
                 System.out.println("\t/by could not be found");
@@ -27,7 +28,7 @@ public static void addToTasks(String description, Type type) {
                 eventTokens = eventTokens[1].split("/to");
                 String from = eventTokens[0].trim();
                 String to = eventTokens[1].trim();
-                tasks[taskCount] = new Events(description, from, to);
+                tasks.add(new Events(description, from, to));
                 break;
             } catch (IndexOutOfBoundsException e) {
                 System.out.println("\tBoth /from and /to are required");
@@ -36,7 +37,7 @@ public static void addToTasks(String description, Type type) {
         }
         taskCount++;
         System.out.println("\tGot it. I've added this task:");
-        System.out.println("\t" + tasks[taskCount-1]);
+        System.out.println("\t" + tasks.get(taskCount-1));
         System.out.println("\tNow you have " + taskCount + " task(s) in the list.");
     }
     public static void printTasks() {
@@ -48,24 +49,36 @@ public static void printTasks() {
         for (int i=0; i<taskCount; i++) {
             System.out.print("\t");
             System.out.print(i+1 + ".");
-            System.out.println(tasks[i]);
+            System.out.println(tasks.get(i));
         }
     }
     public static void markAsDone(int number) {
         try {
-            tasks[number-1].setDone(true);
+            tasks.get(number-1).setDone(true);
             System.out.println("\tNice! I've marked this task as done:");
-            System.out.println("\t" + tasks[number-1]);
-        } catch (NullPointerException e) {
+            System.out.println("\t" + tasks.get(number-1));
+        } catch (NullPointerException | IndexOutOfBoundsException e) {
             System.out.println("\tOops! task " + number + " does not exist");
         }
     }
     public static void markAsUndone(int number) {
         try {
-            tasks[number - 1].setDone(false);
-            System.out.println("\tNice! I've marked this task as not done yet:");
-            System.out.println("\t" + tasks[number - 1]);
-        } catch (NullPointerException e) {
+            tasks.get(number-1).setDone(false);
+            System.out.println("\tNice! I've marked this task as undone:");
+            System.out.println("\t" + tasks.get(number-1));
+        } catch (NullPointerException | IndexOutOfBoundsException e) {
+            System.out.println("\tOops! task " + number + " does not exist");
+        }
+    }
+
+    public static void deleteTask(int number) {
+        try {
+            System.out.println("\tNoted. I've removed this task:");
+            System.out.println("\t" + tasks.get(number-1));
+            tasks.remove(number-1);
+            taskCount--;
+            System.out.println("\tNow you have " + taskCount + " task(s) in the list.");
+        } catch (NullPointerException | IndexOutOfBoundsException e) {
             System.out.println("\tOops! task " + number + " does not exist");
         }
     }
@@ -118,13 +131,16 @@ public static void main(String[] args) {
                     System.out.println("\tDescription of a event cannot be empty");
                     break;
                 }
+            case "delete":
+                deleteTask(Integer.parseInt(substr[1]));
+                break;
             default:
                 System.out.println("\tInvalid input, please try again");
             }
         }
     }
     public static void printByeMessage() {
-        System.out.println("Bye. Hope to see you again soon!");
+        System.out.println("\tBye. Hope to see you again soon!");
         System.exit(0);
     }
 

From 798021e5d18aa7be2371d5deef51ef5342c52887 Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Tue, 3 Oct 2023 19:29:45 +0800
Subject: [PATCH 11/20] Add DataManager to save tasks to a text file

---
 src/main/java/DataManager.java | 96 ++++++++++++++++++++++++++++++++++
 src/main/java/Deadlines.java   |  8 ++-
 src/main/java/Duke.java        | 46 ++++++++++------
 src/main/java/Events.java      |  7 +++
 src/main/java/Task.java        |  4 ++
 src/main/java/ToDos.java       |  5 ++
 6 files changed, 148 insertions(+), 18 deletions(-)
 create mode 100644 src/main/java/DataManager.java

diff --git a/src/main/java/DataManager.java b/src/main/java/DataManager.java
new file mode 100644
index 000000000..72937f452
--- /dev/null
+++ b/src/main/java/DataManager.java
@@ -0,0 +1,96 @@
+import com.sun.source.tree.AnnotationTree;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Scanner;
+public class DataManager {
+    private String filePath;
+
+    public DataManager(String filePath) {
+         this.filePath = filePath;
+    }
+
+    public ArrayList<Task> loadData(){
+        ArrayList<Task> allTasks = new ArrayList<Task>();
+        try {
+            File f = new File(filePath);
+            Scanner s = new Scanner(f);
+            while (s.hasNext()) {
+                String line = s.nextLine();
+                String[] lineTokens = line.split("\\|", 3);
+                String taskType = lineTokens[0].trim();
+                String completionStatus = lineTokens[1].trim();
+                String description = lineTokens[2].trim();
+                switch (taskType) {
+                case "T":
+                    ToDos todo = new ToDos(description);
+                    allTasks.add(todo);
+                    if (completionStatus.equals("1")) {
+                        todo.setDone(true);
+                    }
+                    break;
+                case "D":
+                    String[] deadlineTokens = description.split("\\|");
+                    description = deadlineTokens[0].trim();
+                    String by = deadlineTokens[1].trim();
+                    Deadlines deadline = new Deadlines(description, by);
+                    allTasks.add(deadline);
+                    if (completionStatus.equals("1")) {
+                        deadline.setDone(true);
+                    }
+                    break;
+                case "E":
+                    String[] eventTokens = description.split("\\|");
+                    description = eventTokens[0].trim();
+                    String from = eventTokens[1].trim();
+                    String to = eventTokens[2].trim();
+                    Events event = new Events(description, from, to);
+                    allTasks.add(event);
+                    if (completionStatus.equals("1")) {
+                        event.setDone(true);
+                    }
+                    break;
+                default:
+                    System.out.println("\tUnknown task encountered. Skipping");
+                    break;
+                }
+            }
+        } catch (FileNotFoundException | ArrayIndexOutOfBoundsException e) {
+            System.out.println("\tFailed to read line");
+        }
+        return allTasks;
+    }
+
+    public void save(ArrayList<Task> tasks) {
+        try {
+            createFile();
+            FileWriter fw = new FileWriter(filePath);
+            for (Task task : tasks) {
+                fw.write(task.toSave() + "\n");
+            }
+            fw.close();
+        } catch (IOException e) {
+            System.out.println("An error has occurred while saving");
+        }
+    }
+
+    public void createFile() {
+        try {
+            File f = new File(filePath);
+            if (f.exists()) {
+                return;
+            }
+            if (!f.getParentFile().exists()) {
+                f.getParentFile().mkdirs();
+            }
+            f.createNewFile();
+        } catch (IOException e) {
+            System.out.println("Cannot create file; reason: " + e.getMessage());
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/Deadlines.java b/src/main/java/Deadlines.java
index d07873fdd..cd29e0e85 100644
--- a/src/main/java/Deadlines.java
+++ b/src/main/java/Deadlines.java
@@ -10,9 +10,15 @@ public String getBy() {
     public void setBy(String by) {
         this.by = by;
     }
+
+    @Override
     public String toString() {
         return "[D]" + super.toString() + " (by: " + by + ")";
     }
 
-
+    @Override
+    public String toSave() {
+        return "D | " + (this.isDone() ? "1" : "0") + " | " + this.getDescription()
+                + " | " + this.getBy();
+    }
 }
diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index a70583927..7bfff9c5f 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -1,20 +1,23 @@
-import javax.sound.midi.SysexMessage;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Scanner;
+import java.io.File;
 public class Duke {
-    private static Task[] tasks = new Task[100];
-    private static int taskCount = 0;
+    private static ArrayList<Task> tasks = new ArrayList<Task>();
 
     public static void addToTasks(String description, Type type) {
         switch (type) {
         case TODO:
-            tasks[taskCount] = new ToDos(description);
+            tasks.add(new ToDos(description));
             break;
         case DEADLINE:
             try {
                 String[] deadlineTokens = description.split("/by");
                 description = deadlineTokens[0].trim();
                 String by = deadlineTokens[1].trim();
-                tasks[taskCount] = new Deadlines(description, by);
+                tasks.add(new Deadlines(description, by));
                 break;
             } catch (IndexOutOfBoundsException e) {
                 System.out.println("\t/by could not be found");
@@ -27,49 +30,50 @@ public static void addToTasks(String description, Type type) {
                 eventTokens = eventTokens[1].split("/to");
                 String from = eventTokens[0].trim();
                 String to = eventTokens[1].trim();
-                tasks[taskCount] = new Events(description, from, to);
+                tasks.add(new Events(description, from, to));
                 break;
             } catch (IndexOutOfBoundsException e) {
                 System.out.println("\tBoth /from and /to are required");
                 return;
             }
         }
-        taskCount++;
         System.out.println("\tGot it. I've added this task:");
-        System.out.println("\t" + tasks[taskCount-1]);
-        System.out.println("\tNow you have " + taskCount + " task(s) in the list.");
+        System.out.println("\t" + tasks.get(tasks.size()-1));
+        System.out.println("\tNow you have " + tasks.size() + " task(s) in the list.");
+        //Append to file
     }
     public static void printTasks() {
-        if (taskCount == 0) {
+        if (tasks.isEmpty()) {
             System.out.println("\tYou do not have any task in the list.");
             return;
         }
         System.out.println("\tHere are the tasks in your list:");
-        for (int i=0; i<taskCount; i++) {
+        for (int i=0; i<tasks.size(); i++) {
             System.out.print("\t");
             System.out.print(i+1 + ".");
-            System.out.println(tasks[i]);
+            System.out.println(tasks.get(i));
         }
     }
     public static void markAsDone(int number) {
         try {
-            tasks[number-1].setDone(true);
+            tasks.get(number - 1).setDone(true);
             System.out.println("\tNice! I've marked this task as done:");
-            System.out.println("\t" + tasks[number-1]);
+            System.out.println("\t" + tasks.get(number - 1));
         } catch (NullPointerException e) {
             System.out.println("\tOops! task " + number + " does not exist");
         }
     }
     public static void markAsUndone(int number) {
         try {
-            tasks[number - 1].setDone(false);
+            tasks.get(number - 1).setDone(false);
             System.out.println("\tNice! I've marked this task as not done yet:");
-            System.out.println("\t" + tasks[number - 1]);
+            System.out.println("\t" + tasks.get(number - 1));
         } catch (NullPointerException e) {
             System.out.println("\tOops! task " + number + " does not exist");
         }
     }
 
+
     public static void main(String[] args) {
         // Greetings
         String intro = "~~~~~~~~~~~~~~~~~~~\n"
@@ -77,6 +81,9 @@ public static void main(String[] args) {
                 + "How may I help you?\n"
                 + "~~~~~~~~~~~~~~~~~~~";
         System.out.println(intro);
+        DataManager dataManager = new DataManager("./data/data.txt");
+        tasks = dataManager.loadData();
+
         while (true) {
             Scanner scanner = new Scanner(System.in);
             String userInput = scanner.nextLine();
@@ -90,13 +97,16 @@ public static void main(String[] args) {
                 break;
             case "mark":
                 markAsDone(Integer.parseInt(substr[1]));
+                dataManager.save(tasks);
                 break;
             case "unmark":
                 markAsUndone(Integer.parseInt(substr[1]));
+                dataManager.save(tasks);
                 break;
             case "todo":
                 try {
                     addToTasks(substr[1], Type.TODO);
+                    dataManager.save(tasks);
                     break;
                 } catch (ArrayIndexOutOfBoundsException e) {
                     System.out.println("\tDescription of a todo cannot be empty");
@@ -105,6 +115,7 @@ public static void main(String[] args) {
             case "deadline":
                 try {
                     addToTasks(substr[1], Type.DEADLINE);
+                    dataManager.save(tasks);
                     break;
                 } catch (ArrayIndexOutOfBoundsException e) {
                     System.out.println("\tDescription of a deadline cannot be empty");
@@ -113,6 +124,7 @@ public static void main(String[] args) {
             case "event":
                 try {
                     addToTasks(substr[1], Type.EVENT);
+                    dataManager.save(tasks);
                     break;
                 } catch (ArrayIndexOutOfBoundsException e) {
                     System.out.println("\tDescription of a event cannot be empty");
@@ -124,7 +136,7 @@ public static void main(String[] args) {
         }
     }
     public static void printByeMessage() {
-        System.out.println("Bye. Hope to see you again soon!");
+        System.out.println("\tBye. Hope to see you again soon!");
         System.exit(0);
     }
 
diff --git a/src/main/java/Events.java b/src/main/java/Events.java
index a6c20c8da..c1ed504a4 100644
--- a/src/main/java/Events.java
+++ b/src/main/java/Events.java
@@ -24,8 +24,15 @@ public void setTo(String to) {
         this.to = to;
     }
 
+    @Override
     public String toString() {
         return "[E]" + super.toString() + " (from: " + from + ", to: " + to + ")";
     }
+
+    @Override
+    public String toSave() {
+        return "E | " + (this.isDone() ? "1" : "0") + " | " + this.getDescription()
+                + " | " + this.getFrom() + " | " + this.getTo();
+    }
 }
 
diff --git a/src/main/java/Task.java b/src/main/java/Task.java
index 9c2a8716c..ff4cdd94e 100644
--- a/src/main/java/Task.java
+++ b/src/main/java/Task.java
@@ -29,4 +29,8 @@ public String toString() {
         }
         return temp + " " + description;
     }
+
+    public String toSave() {
+        return null;
+    }
 }
diff --git a/src/main/java/ToDos.java b/src/main/java/ToDos.java
index 7aac2e775..f070b3545 100644
--- a/src/main/java/ToDos.java
+++ b/src/main/java/ToDos.java
@@ -7,4 +7,9 @@ public ToDos(String description) {
     public String toString() {
         return "[T]" + super.toString();
     }
+
+    @Override
+    public String toSave() {
+        return "T | " + (this.isDone() ? "1" : "0") + " | " + this.getDescription();
+    }
 }

From 7beac69d24604af8fae512a84070cdb5e2d12bc9 Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Wed, 4 Oct 2023 14:00:39 +0800
Subject: [PATCH 12/20] Divide code into smaller objects

Create TaskList, Parser, Ui and Storage to split the code in Duke into different objects
---
 src/main/java/Command.java                    |  86 +++++++++
 .../java/{Deadlines.java => Deadline.java}    |   4 +-
 src/main/java/Duke.java                       | 167 +++---------------
 src/main/java/DukeException.java              |  12 ++
 src/main/java/{Events.java => Event.java}     |   4 +-
 src/main/java/META-INF/MANIFEST.MF            |   3 +
 src/main/java/Parser.java                     |  15 ++
 .../java/{DataManager.java => Storage.java}   |  31 ++--
 src/main/java/TaskList.java                   |  89 ++++++++++
 src/main/java/{ToDos.java => ToDo.java}       |   4 +-
 src/main/java/Ui.java                         |  89 ++++++++++
 11 files changed, 342 insertions(+), 162 deletions(-)
 create mode 100644 src/main/java/Command.java
 rename src/main/java/{Deadlines.java => Deadline.java} (83%)
 create mode 100644 src/main/java/DukeException.java
 rename src/main/java/{Events.java => Event.java} (87%)
 create mode 100644 src/main/java/META-INF/MANIFEST.MF
 create mode 100644 src/main/java/Parser.java
 rename src/main/java/{DataManager.java => Storage.java} (75%)
 create mode 100644 src/main/java/TaskList.java
 rename src/main/java/{ToDos.java => ToDo.java} (77%)
 create mode 100644 src/main/java/Ui.java

diff --git a/src/main/java/Command.java b/src/main/java/Command.java
new file mode 100644
index 000000000..50c99ea19
--- /dev/null
+++ b/src/main/java/Command.java
@@ -0,0 +1,86 @@
+public class Command {
+
+    private String command;
+    private String arg;
+    private boolean isExit;
+    public Command(String command, String arg) {
+        this.command = command;
+        this.arg = arg;
+        this.isExit = false;
+    }
+
+    public void setExit(boolean exit) {
+        isExit = exit;
+    }
+
+    public boolean isExit() {
+        return isExit;
+    }
+    public void execute(TaskList taskList, Ui ui, Storage storage) throws DukeException{
+        switch(this.command) {
+        case "bye":
+            setExit(true);
+            ui.showByeMessage();
+            break;
+        case "list":
+            ui.showTasks(taskList);
+            break;
+        case "mark":
+            try {
+                taskList.markTask(this.arg, true);
+                storage.save(taskList);
+                ui.showMark(taskList, this.arg, true);
+            } catch (DukeException e) {
+                ui.showError(e);
+            }
+            break;
+        case "unmark":
+            try {
+                taskList.markTask(this.arg, false);
+                storage.save(taskList);
+                ui.showMark(taskList, this.arg, false);
+            } catch (DukeException e) {
+                ui.showError(e);
+            }
+            break;
+        case "todo":
+            try {
+                taskList.addTodo(this.arg);
+                storage.save(taskList);
+                ui.showAddTask(taskList);
+            } catch (DukeException e) {
+                ui.showError(e);
+            }
+            break;
+        case "deadline":
+            try {
+                taskList.addDeadline(this.arg);
+                storage.save(taskList);
+                ui.showAddTask(taskList);
+            } catch (DukeException e) {
+                ui.showError(e);
+            }
+            break;
+        case "event":
+            try {
+                taskList.addEvent(this.arg);
+                storage.save(taskList);
+                ui.showAddTask(taskList);
+            } catch (DukeException e) {
+                ui.showError(e);
+            }
+            break;
+        case "delete":
+            try {
+                Task removedTask = taskList.deleteTask(taskList, this.arg);
+                storage.save(taskList);
+                ui.showDeleteTask(taskList, removedTask);
+            } catch (DukeException e) {
+                ui.showError(e);
+            }
+            break;
+        default:
+            throw new DukeException("Invalid input, please try again");
+        }
+    }
+}
diff --git a/src/main/java/Deadlines.java b/src/main/java/Deadline.java
similarity index 83%
rename from src/main/java/Deadlines.java
rename to src/main/java/Deadline.java
index cd29e0e85..060990d6d 100644
--- a/src/main/java/Deadlines.java
+++ b/src/main/java/Deadline.java
@@ -1,6 +1,6 @@
-public class Deadlines extends Task {
+public class Deadline extends Task {
     String by;
-    public Deadlines(String description, String by) {
+    public Deadline(String description, String by) {
         super(description);
         this.by = by;
     }
diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index f69cb3a05..1435577aa 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -1,154 +1,41 @@
 import java.util.ArrayList;
 import java.util.Scanner;
-import java.io.File;
+
 public class Duke {
-    private static ArrayList<Task> tasks = new ArrayList<Task>();
 
-    public static void addToTasks(String description, Type type) {
-        switch (type) {
-        case TODO:
-            tasks.add(new ToDos(description));
-            break;
-        case DEADLINE:
-            try {
-                String[] deadlineTokens = description.split("/by");
-                description = deadlineTokens[0].trim();
-                String by = deadlineTokens[1].trim();
-                tasks.add(new Deadlines(description, by));
-                break;
-            } catch (IndexOutOfBoundsException e) {
-                System.out.println("\t/by could not be found");
-                return;
-            }
-        case EVENT:
-            try {
-                String[] eventTokens = description.split("/from");
-                description = eventTokens[0].trim();
-                eventTokens = eventTokens[1].split("/to");
-                String from = eventTokens[0].trim();
-                String to = eventTokens[1].trim();
-                tasks.add(new Events(description, from, to));
-                break;
-            } catch (IndexOutOfBoundsException e) {
-                System.out.println("\tBoth /from and /to are required");
-                return;
-            }
-        }
-        System.out.println("\tGot it. I've added this task:");
-        System.out.println("\t" + tasks.get(tasks.size()-1));
-        System.out.println("\tNow you have " + tasks.size() + " task(s) in the list.");
+    private Storage storage;
+    private TaskList taskList;
+    private Ui ui;
 
-    }
-    public static void printTasks() {
-        if (tasks.isEmpty()) {
-            System.out.println("\tYou do not have any task in the list.");
-            return;
-        }
-        System.out.println("\tHere are the tasks in your list:");
-        for (int i=0; i<tasks.size(); i++) {
-            System.out.print("\t");
-            System.out.print(i+1 + ".");
-            System.out.println(tasks.get(i));
-        }
-    }
-    public static void markAsDone(int number) {
-        try {
-            tasks.get(number-1).setDone(true);
-            System.out.println("\tNice! I've marked this task as done:");
-            System.out.println("\t" + tasks.get(number-1));
-        } catch (NullPointerException | IndexOutOfBoundsException e) {
-            System.out.println("\tOops! task " + number + " does not exist");
-        }
-    }
-    public static void markAsUndone(int number) {
+    public Duke(String filePath) {
+        ui = new Ui();
+        storage = new Storage(filePath);
         try {
-            tasks.get(number-1).setDone(false);
-            System.out.println("\tNice! I've marked this task as undone:");
-            System.out.println("\t" + tasks.get(number-1));
-        } catch (NullPointerException | IndexOutOfBoundsException e) {
-            System.out.println("\tOops! task " + number + " does not exist");
+            taskList = new TaskList(storage.load());
+        } catch (DukeException e) {
+            ui.showError(e);
+            taskList = new TaskList();
         }
     }
-
-    public static void deleteTask(int number) {
-        try {
-            System.out.println("\tNoted. I've removed this task:");
-            System.out.println("\t" + tasks.get(number-1));
-            tasks.remove(number-1);
-            System.out.println("\tNow you have " + tasks.size() + " task(s) in the list.");
-        } catch (NullPointerException | IndexOutOfBoundsException e) {
-            System.out.println("\tOops! task " + number + " does not exist");
-        }
+    public void run() {
+       Parser parser = new Parser();
+       ui.showStartMessage();
+       boolean isExit = false;
+       while (!isExit) {
+           try {
+               String fullCommand = ui.readCommand();
+               Command c = parser.parse(fullCommand);
+               c.execute(taskList, ui, storage);
+               isExit = c.isExit();
+           } catch (DukeException e) {
+               ui.showError(e);
+           }
+       }
+       System.exit(0);
     }
 
-
     public static void main(String[] args) {
-        // Greetings
-        String intro = "~~~~~~~~~~~~~~~~~~~\n"
-                + "Hello! I'm Wenny!\n"
-                + "How may I help you?\n"
-                + "~~~~~~~~~~~~~~~~~~~";
-        System.out.println(intro);
-        DataManager dataManager = new DataManager("./data/data.txt");
-        tasks = dataManager.loadData();
-
-        while (true) {
-            Scanner scanner = new Scanner(System.in);
-            String userInput = scanner.nextLine();
-            String[] substr = userInput.split("\\s+", 2);
-            switch (substr[0]) {
-            case "bye":
-                printByeMessage();
-                break;
-            case "list":
-                printTasks();
-                break;
-            case "mark":
-                markAsDone(Integer.parseInt(substr[1]));
-                dataManager.save(tasks);
-                break;
-            case "unmark":
-                markAsUndone(Integer.parseInt(substr[1]));
-                dataManager.save(tasks);
-                break;
-            case "todo":
-                try {
-                    addToTasks(substr[1], Type.TODO);
-                    dataManager.save(tasks);
-                    break;
-                } catch (ArrayIndexOutOfBoundsException e) {
-                    System.out.println("\tDescription of a todo cannot be empty");
-                    break;
-                }
-            case "deadline":
-                try {
-                    addToTasks(substr[1], Type.DEADLINE);
-                    dataManager.save(tasks);
-                    break;
-                } catch (ArrayIndexOutOfBoundsException e) {
-                    System.out.println("\tDescription of a deadline cannot be empty");
-                    break;
-                }
-            case "event":
-                try {
-                    addToTasks(substr[1], Type.EVENT);
-                    dataManager.save(tasks);
-                    break;
-                } catch (ArrayIndexOutOfBoundsException e) {
-                    System.out.println("\tDescription of a event cannot be empty");
-                    break;
-                }
-            case "delete":
-                deleteTask(Integer.parseInt(substr[1]));
-                break;
-            default:
-                System.out.println("\tInvalid input, please try again");
-            }
-        }
-    }
-    public static void printByeMessage() {
-        System.out.println("\tBye. Hope to see you again soon!");
-        System.exit(0);
+        new Duke("./data/data.txt").run();
     }
 
 }
diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java
new file mode 100644
index 000000000..97be7674c
--- /dev/null
+++ b/src/main/java/DukeException.java
@@ -0,0 +1,12 @@
+public class DukeException extends Exception{
+    String errorMessage;
+    public DukeException(String errorMessage) {
+        this.errorMessage = errorMessage;
+    }
+
+    @Override
+    public String toString() {
+        return errorMessage;
+    }
+
+}
diff --git a/src/main/java/Events.java b/src/main/java/Event.java
similarity index 87%
rename from src/main/java/Events.java
rename to src/main/java/Event.java
index c1ed504a4..33005e625 100644
--- a/src/main/java/Events.java
+++ b/src/main/java/Event.java
@@ -1,8 +1,8 @@
-public class Events extends Task {
+public class Event extends Task {
     String from;
     String to;
 
-    public Events(String description, String from, String to) {
+    public Event(String description, String from, String to) {
         super(description);
         setFrom(from);
         setTo(to);
diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..9f37e4e0a
--- /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/Parser.java b/src/main/java/Parser.java
new file mode 100644
index 000000000..a1cf67983
--- /dev/null
+++ b/src/main/java/Parser.java
@@ -0,0 +1,15 @@
+import java.util.Scanner;
+
+public class Parser {
+
+    public Parser() {
+    }
+
+    public Command parse(String fullCommand) {
+        String[] substr = fullCommand.split("\\s+", 2);
+        if (substr.length == 1) {
+            return new Command(substr[0], null);
+        }
+        return new Command(substr[0], substr[1]);
+    }
+}
diff --git a/src/main/java/DataManager.java b/src/main/java/Storage.java
similarity index 75%
rename from src/main/java/DataManager.java
rename to src/main/java/Storage.java
index 72937f452..63ed1e2b6 100644
--- a/src/main/java/DataManager.java
+++ b/src/main/java/Storage.java
@@ -1,21 +1,17 @@
-import com.sun.source.tree.AnnotationTree;
-
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Scanner;
-public class DataManager {
+public class Storage {
     private String filePath;
 
-    public DataManager(String filePath) {
+    public Storage(String filePath) {
          this.filePath = filePath;
     }
 
-    public ArrayList<Task> loadData(){
+    public ArrayList<Task> load() throws DukeException {
         ArrayList<Task> allTasks = new ArrayList<Task>();
         try {
             File f = new File(filePath);
@@ -28,7 +24,7 @@ public ArrayList<Task> loadData(){
                 String description = lineTokens[2].trim();
                 switch (taskType) {
                 case "T":
-                    ToDos todo = new ToDos(description);
+                    ToDo todo = new ToDo(description);
                     allTasks.add(todo);
                     if (completionStatus.equals("1")) {
                         todo.setDone(true);
@@ -38,7 +34,7 @@ public ArrayList<Task> loadData(){
                     String[] deadlineTokens = description.split("\\|");
                     description = deadlineTokens[0].trim();
                     String by = deadlineTokens[1].trim();
-                    Deadlines deadline = new Deadlines(description, by);
+                    Deadline deadline = new Deadline(description, by);
                     allTasks.add(deadline);
                     if (completionStatus.equals("1")) {
                         deadline.setDone(true);
@@ -49,7 +45,7 @@ public ArrayList<Task> loadData(){
                     description = eventTokens[0].trim();
                     String from = eventTokens[1].trim();
                     String to = eventTokens[2].trim();
-                    Events event = new Events(description, from, to);
+                    Event event = new Event(description, from, to);
                     allTasks.add(event);
                     if (completionStatus.equals("1")) {
                         event.setDone(true);
@@ -60,13 +56,16 @@ public ArrayList<Task> loadData(){
                     break;
                 }
             }
-        } catch (FileNotFoundException | ArrayIndexOutOfBoundsException e) {
-            System.out.println("\tFailed to read line");
+        } catch (FileNotFoundException e) {
+            throw new DukeException("\tFailed to load file");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            throw new DukeException("\tFile is corrupted");
         }
         return allTasks;
     }
 
-    public void save(ArrayList<Task> tasks) {
+    public void save(TaskList taskList) throws DukeException {
+        ArrayList<Task> tasks = taskList.getTasks();
         try {
             createFile();
             FileWriter fw = new FileWriter(filePath);
@@ -75,11 +74,11 @@ public void save(ArrayList<Task> tasks) {
             }
             fw.close();
         } catch (IOException e) {
-            System.out.println("An error has occurred while saving");
+            throw new DukeException("An error has occurred while saving");
         }
     }
 
-    public void createFile() {
+    public void createFile() throws DukeException {
         try {
             File f = new File(filePath);
             if (f.exists()) {
@@ -90,7 +89,7 @@ public void createFile() {
             }
             f.createNewFile();
         } catch (IOException e) {
-            System.out.println("Cannot create file; reason: " + e.getMessage());
+            throw new DukeException("Cannot create file; reason: " + e.getMessage());
         }
     }
 }
\ No newline at end of file
diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java
new file mode 100644
index 000000000..a22103fb7
--- /dev/null
+++ b/src/main/java/TaskList.java
@@ -0,0 +1,89 @@
+import java.util.ArrayList;
+
+public class TaskList {
+
+    private ArrayList<Task> tasks;
+    public TaskList(ArrayList<Task> tasks) {
+        this.tasks = tasks;
+    }
+    public TaskList() {
+        this.tasks = new ArrayList<Task>();
+    }
+
+    public ArrayList<Task> getTasks() {
+        return tasks;
+    }
+
+    public void add(Task task) {
+        this.tasks.add(task);
+    }
+    public void remove(Task task){
+        this.tasks.remove(task);
+    }
+
+    public void addTodo(String description) throws DukeException {
+        if (description.isBlank()) {
+            throw new DukeException("Description of a todo cannot be empty");
+        }
+        tasks.add(new ToDo(description));
+    }
+
+    public void addDeadline(String description) throws DukeException {
+        if (description.isBlank()) {
+            throw new DukeException("Description of a deadline cannot be empty");
+        }
+        try {
+            String[] deadlineTokens = description.split("/by");
+            description = deadlineTokens[0].trim();
+            String by = deadlineTokens[1].trim();
+            Deadline deadline = new Deadline(description, by);
+            tasks.add(deadline);
+        } catch (ArrayIndexOutOfBoundsException e) {
+            throw new DukeException("Wrong format! Expected format: deadline [task] /by [time]");
+        }
+
+    }
+
+    public void addEvent(String description) throws DukeException {
+        if (description.isBlank()) {
+            throw new DukeException("Description of a event cannot be empty");
+        }
+        try {
+            String[] eventTokens = description.split("/from");
+            description = eventTokens[0].trim();
+            String[] fromAndToTokens = eventTokens[1].split("/to");
+            String from = fromAndToTokens[0].trim();
+            String to = fromAndToTokens[1].trim();
+            Event event = new Event(description, from, to);
+            tasks.add(event);
+        } catch (ArrayIndexOutOfBoundsException e) {
+            throw new DukeException("Wrong format! Expected format: event [task] /from [time] /to [time]");
+        }
+
+    }
+
+    public void markTask(String taskID, boolean isDone) throws DukeException {
+        try {
+            int index = Integer.parseInt(taskID);
+            tasks.get(index-1).setDone(isDone);
+        } catch (NullPointerException | NumberFormatException e) {
+            throw new DukeException("Oops! An integer taskID is expected");
+        } catch (IndexOutOfBoundsException e) {
+            throw new DukeException("Oops! Task " + taskID + " does not exist");
+        }
+    }
+
+    public Task deleteTask(TaskList taskList, String taskID) throws DukeException {
+        ArrayList<Task> tasks = taskList.getTasks();
+        try {
+            int index = Integer.parseInt(taskID);
+            Task removedTask = tasks.get(index-1);
+            tasks.remove(index-1);
+            return removedTask;
+        } catch (NullPointerException | NumberFormatException e) {
+            throw new DukeException("Oops! An integer taskID is expected");
+        } catch (IndexOutOfBoundsException e) {
+            throw new DukeException("Oops! Task " + taskID + " does not exist");
+        }
+    }
+}
diff --git a/src/main/java/ToDos.java b/src/main/java/ToDo.java
similarity index 77%
rename from src/main/java/ToDos.java
rename to src/main/java/ToDo.java
index f070b3545..3e088fa2d 100644
--- a/src/main/java/ToDos.java
+++ b/src/main/java/ToDo.java
@@ -1,6 +1,6 @@
-public class ToDos extends Task {
+public class ToDo extends Task {
 
-    public ToDos(String description) {
+    public ToDo(String description) {
         super(description);
     }
 
diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java
new file mode 100644
index 000000000..84a5f5838
--- /dev/null
+++ b/src/main/java/Ui.java
@@ -0,0 +1,89 @@
+import java.util.ArrayList;
+import java.util.Scanner;
+
+public class Ui {
+    private static final String LINE_DIVIDER = "\t---------------------------------------";
+    protected Scanner scanner;
+
+    public Ui(){
+        this.scanner = new Scanner(System.in);
+    }
+
+    public void showStartMessage() {
+        String intro = "~~~~~~~~~~~~~~~~~~~\n"
+                        + "Hello! I'm Wenny!\n"
+                        + "How may I help you?\n"
+                        + "~~~~~~~~~~~~~~~~~~~";
+        System.out.println(intro);
+    }
+
+    public void showByeMessage() {
+        showLine();
+        System.out.println("\tBye. Hope to see you again soon!");
+        showLine();
+    }
+    public void showTasks(TaskList tasklist) {
+        ArrayList<Task> tasks = tasklist.getTasks();
+        showLine();
+        if (tasks.isEmpty()) {
+            System.out.println("\tYou do not have any task in the list.");
+        } else {
+            System.out.println("\tHere are the tasks in your list:");
+            for (int i = 0; i < tasks.size(); i++) {
+                System.out.print("\t");
+                System.out.print(i + 1 + ".");
+                System.out.println(tasks.get(i));
+            }
+        }
+        showLine();
+    }
+
+    public void showAddTask(TaskList taskList) {
+        ArrayList<Task> tasks = taskList.getTasks();
+        showLine();
+        System.out.println("\tGot it. I've added this task:");
+        System.out.println("\t" + tasks.get(tasks.size()-1));
+        System.out.println("\tNow you have " + tasks.size() + " task(s) in the list.");
+        showLine();
+    }
+
+    public void showDeleteTask(TaskList taskList, Task removedTask) {
+        ArrayList<Task> tasks = taskList.getTasks();
+        showLine();
+        System.out.println("\tNoted. I've removed this task:");
+        System.out.println("\t" + removedTask);
+        System.out.println("\tNow you have " + tasks.size() + " task(s) in the list.");
+        showLine();
+    }
+
+    public void showMark(TaskList taskList, String taskID, boolean isDone) {
+        ArrayList<Task> tasks = taskList.getTasks();
+        int index = Integer.parseInt(taskID);
+        showLine();
+        if (isDone) {
+            System.out.println("\tNice! I've marked this task as done:");
+        } else {
+            System.out.println("\tNice! I've marked this task as undone:");
+        }
+        System.out.println("\t" + tasks.get(index-1));
+        showLine();
+    }
+
+    public void showLine() {
+        System.out.println(LINE_DIVIDER);
+    }
+
+    public void showError(Exception e) {
+        showLine();
+        System.out.println("\t" + e);
+        showLine();
+    }
+
+    public String readCommand() {
+        return scanner.nextLine();
+    }
+
+    public void showDeadlineError() {
+
+    }
+}

From 02762e480467ee3100542897ba56b28a724166f4 Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Wed, 4 Oct 2023 14:19:53 +0800
Subject: [PATCH 13/20] Create find command to match keyword with task

---
 src/main/java/Command.java  | 12 +++++++++++-
 src/main/java/TaskList.java | 20 ++++++++++++++++++--
 src/main/java/Ui.java       | 15 +++++++++++++--
 3 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/src/main/java/Command.java b/src/main/java/Command.java
index 50c99ea19..ebfb526d0 100644
--- a/src/main/java/Command.java
+++ b/src/main/java/Command.java
@@ -1,3 +1,5 @@
+import java.util.ArrayList;
+
 public class Command {
 
     private String command;
@@ -72,13 +74,21 @@ public void execute(TaskList taskList, Ui ui, Storage storage) throws DukeExcept
             break;
         case "delete":
             try {
-                Task removedTask = taskList.deleteTask(taskList, this.arg);
+                Task removedTask = taskList.deleteTask(this.arg);
                 storage.save(taskList);
                 ui.showDeleteTask(taskList, removedTask);
             } catch (DukeException e) {
                 ui.showError(e);
             }
             break;
+        case "find":
+            try {
+                ArrayList<Task> matchingTasks = taskList.find(this.arg);
+                ui.showFind(matchingTasks);
+            } catch (DukeException e) {
+                ui.showError(e);
+            }
+            break;
         default:
             throw new DukeException("Invalid input, please try again");
         }
diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java
index a22103fb7..7a357b632 100644
--- a/src/main/java/TaskList.java
+++ b/src/main/java/TaskList.java
@@ -73,8 +73,7 @@ public void markTask(String taskID, boolean isDone) throws DukeException {
         }
     }
 
-    public Task deleteTask(TaskList taskList, String taskID) throws DukeException {
-        ArrayList<Task> tasks = taskList.getTasks();
+    public Task deleteTask(String taskID) throws DukeException {
         try {
             int index = Integer.parseInt(taskID);
             Task removedTask = tasks.get(index-1);
@@ -86,4 +85,21 @@ public Task deleteTask(TaskList taskList, String taskID) throws DukeException {
             throw new DukeException("Oops! Task " + taskID + " does not exist");
         }
     }
+
+    public ArrayList<Task> find(String keyword) throws DukeException {
+        if (keyword.isBlank()) {
+            throw new DukeException("Keyword cannot be empty");
+        }
+        ArrayList<Task> matchingTasks = new ArrayList<Task>();
+        for (Task task : tasks) {
+            String[] substrs = task.getDescription().split("\\s+");
+            for (String substr : substrs) {
+                if (substr.equals(keyword)) {
+                    matchingTasks.add(task);
+                    break;
+                }
+            }
+        }
+        return matchingTasks;
+    }
 }
diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java
index 84a5f5838..4521bdd75 100644
--- a/src/main/java/Ui.java
+++ b/src/main/java/Ui.java
@@ -83,7 +83,18 @@ public String readCommand() {
         return scanner.nextLine();
     }
 
-    public void showDeadlineError() {
-
+    public void showFind(ArrayList<Task> matchingTasks) {
+        showLine();
+        if (matchingTasks.isEmpty()) {
+            System.out.println("\tKeyword does not match any task in the list.");
+        } else {
+            System.out.println("\tHere are the matching tasks in your list:");
+            for (int i = 0; i < matchingTasks.size(); i++) {
+                System.out.print("\t");
+                System.out.print(i + 1 + ".");
+                System.out.println(matchingTasks.get(i));
+            }
+        }
+        showLine();
     }
 }

From 9df71858e0ab30360995c2f374bb25db813ab53f Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Wed, 4 Oct 2023 16:13:40 +0800
Subject: [PATCH 14/20] Add Javadoc to most of the class

---
 src/main/java/Command.java       | 27 +++++++++++++--
 src/main/java/Deadline.java      | 11 ++++--
 src/main/java/Duke.java          | 19 +++++++++++
 src/main/java/DukeException.java |  7 ++++
 src/main/java/Event.java         | 11 ++++--
 src/main/java/Parser.java        | 11 ++++--
 src/main/java/Storage.java       | 27 +++++++++++++++
 src/main/java/Task.java          | 16 +++++----
 src/main/java/TaskList.java      | 57 ++++++++++++++++++++++++++++++++
 src/main/java/ToDo.java          | 10 +++++-
 src/main/java/Ui.java            |  4 +++
 11 files changed, 185 insertions(+), 15 deletions(-)

diff --git a/src/main/java/Command.java b/src/main/java/Command.java
index ebfb526d0..a1d927d3a 100644
--- a/src/main/java/Command.java
+++ b/src/main/java/Command.java
@@ -1,10 +1,19 @@
 import java.util.ArrayList;
 
+/**
+ * Execute commands from the user.
+ */
 public class Command {
-
     private String command;
     private String arg;
     private boolean isExit;
+
+    /**
+     * Constructor of a Command
+     *
+     * @param command Command to be executed
+     * @param arg Arguments of the given command
+     */
     public Command(String command, String arg) {
         this.command = command;
         this.arg = arg;
@@ -18,6 +27,20 @@ public void setExit(boolean exit) {
     public boolean isExit() {
         return isExit;
     }
+
+    /**
+     * Execute the command given by the user
+     * Each command is handled by its corresponding method in {@code TaskList}. If there
+     * is any changes to the list of tasks, it will be saved into the file through {@code Storage}.
+     * Relevant information will be shown to the user through corresponding methods in {@code Ui}.
+     * A custom exceptions will be thrown if an invalid command is received or an invalid argument of
+     * the respective command.
+     *
+     * @param taskList TaskList object that contains a list of Tasks
+     * @param ui User interface object that handles the printing of information
+     * @param storage Storage object that saves the updated list into filepath
+     * @throws DukeException Custom Exception with customer error message
+     */
     public void execute(TaskList taskList, Ui ui, Storage storage) throws DukeException{
         switch(this.command) {
         case "bye":
@@ -89,7 +112,7 @@ public void execute(TaskList taskList, Ui ui, Storage storage) throws DukeExcept
                 ui.showError(e);
             }
             break;
-        default:
+        default: // Unknown command exception
             throw new DukeException("Invalid input, please try again");
         }
     }
diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java
index 060990d6d..72724cc11 100644
--- a/src/main/java/Deadline.java
+++ b/src/main/java/Deadline.java
@@ -11,14 +11,21 @@ public void setBy(String by) {
         this.by = by;
     }
 
+    /**
+     * Returns the format of the task to be printed out to user
+     * @return String representation of the task
+     */
     @Override
     public String toString() {
         return "[D]" + super.toString() + " (by: " + by + ")";
     }
 
+    /**
+     * Returns the format of the task to be saved into a file
+     * @return String representation of the task
+     */
     @Override
     public String toSave() {
-        return "D | " + (this.isDone() ? "1" : "0") + " | " + this.getDescription()
-                + " | " + this.getBy();
+        return "D | " + super.toSave() + " | " + by;
     }
 }
diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index 1435577aa..fa2208b4b 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -1,12 +1,24 @@
 import java.util.ArrayList;
 import java.util.Scanner;
 
+/**
+ * This is the main program of Duke.
+ * Duke is a chatbot for user track tasks such as todos, deadlines and events.
+ * User can add tasks, mark tasks as done, delete tasks or find tasks based on a keyword.
+ * These tasks are automatically saved in a file in ./data/data.txt whenever an operation
+ * on the TaskList is made. This file will be loaded on future start up of the chatbot
+ *
+ */
 public class Duke {
 
     private Storage storage;
     private TaskList taskList;
     private Ui ui;
 
+    /**
+     * Constructor of Duke. Initialise User interface, Storage and TaskList instances.
+     * @param filePath Path to the file where tasks are to be loaded from and saved to.
+     */
     public Duke(String filePath) {
         ui = new Ui();
         storage = new Storage(filePath);
@@ -17,6 +29,13 @@ public Duke(String filePath) {
             taskList = new TaskList();
         }
     }
+
+    /**
+     * To start up the chatbot.
+     * A greetings will be printed on the command line interface and the chatbot will
+     * await instructions from the user. The chatbot will run until an exit command is received.
+     * Any exception during the operation will produce an error message to notify the user
+     */
     public void run() {
        Parser parser = new Parser();
        ui.showStartMessage();
diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java
index 97be7674c..9e0c7d012 100644
--- a/src/main/java/DukeException.java
+++ b/src/main/java/DukeException.java
@@ -1,9 +1,16 @@
+/**
+ * Custom Exception for Duke
+ */
 public class DukeException extends Exception{
     String errorMessage;
     public DukeException(String errorMessage) {
         this.errorMessage = errorMessage;
     }
 
+    /**
+     * Format error message for printing to command line interface.
+     * @return Return the error message of the specific exception in String format.
+     */
     @Override
     public String toString() {
         return errorMessage;
diff --git a/src/main/java/Event.java b/src/main/java/Event.java
index 33005e625..9e299cfa5 100644
--- a/src/main/java/Event.java
+++ b/src/main/java/Event.java
@@ -24,15 +24,22 @@ public void setTo(String to) {
         this.to = to;
     }
 
+    /**
+     * Returns the format of the task to be printed out to user
+     * @return String representation of the task
+     */
     @Override
     public String toString() {
         return "[E]" + super.toString() + " (from: " + from + ", to: " + to + ")";
     }
 
+    /**
+     * Returns the format of the task to be saved into a file
+     * @return String representation of the task
+     */
     @Override
     public String toSave() {
-        return "E | " + (this.isDone() ? "1" : "0") + " | " + this.getDescription()
-                + " | " + this.getFrom() + " | " + this.getTo();
+        return "E | " + super.toSave() + " | " + from + " | " + to;
     }
 }
 
diff --git a/src/main/java/Parser.java b/src/main/java/Parser.java
index a1cf67983..e9456c55b 100644
--- a/src/main/java/Parser.java
+++ b/src/main/java/Parser.java
@@ -1,10 +1,17 @@
-import java.util.Scanner;
-
+/**
+ * Parser object that handles splitting of command line arguments given by the user.
+ */
 public class Parser {
 
     public Parser() {
     }
 
+    /**
+     * Split user input into command and argument of the command.
+     *
+     * @param fullCommand User input.
+     * @return Return a Command object for execution of the command.
+     */
     public Command parse(String fullCommand) {
         String[] substr = fullCommand.split("\\s+", 2);
         if (substr.length == 1) {
diff --git a/src/main/java/Storage.java b/src/main/java/Storage.java
index 63ed1e2b6..da27b3f12 100644
--- a/src/main/java/Storage.java
+++ b/src/main/java/Storage.java
@@ -4,6 +4,10 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Scanner;
+
+/**
+ * Storage object that handles loading and saving of tasks into specified file
+ */
 public class Storage {
     private String filePath;
 
@@ -11,6 +15,14 @@ public Storage(String filePath) {
          this.filePath = filePath;
     }
 
+    /**
+     * This method attempts to load pre-existing tasks from the file specified by
+     * the filepath. It will read the text file line by line and extract the information
+     * based on a format specified by the program.
+     *
+     * @return A TaskList object that contains the tasks loaded from the file.
+     * @throws DukeException If the file cannot be found or is corrupted.
+     */
     public ArrayList<Task> load() throws DukeException {
         ArrayList<Task> allTasks = new ArrayList<Task>();
         try {
@@ -64,6 +76,16 @@ public ArrayList<Task> load() throws DukeException {
         return allTasks;
     }
 
+    /**
+     *
+     * This method save the tasks in TaskList into the file specified by filepath.
+     * If the file specified by the filepath does not exist, it will create a new file as
+     * specified by the filepath.
+     *
+     * @param taskList TaskList object that contains the tasks.
+     * @throws DukeException If there is an error during the saving process due to corrupted
+     *                       data or invalid input.
+     */
     public void save(TaskList taskList) throws DukeException {
         ArrayList<Task> tasks = taskList.getTasks();
         try {
@@ -78,6 +100,11 @@ public void save(TaskList taskList) throws DukeException {
         }
     }
 
+    /**
+     * This method create the file specified by the filepath.
+     *
+     * @throws DukeException If it fails to create the specified file.
+     */
     public void createFile() throws DukeException {
         try {
             File f = new File(filePath);
diff --git a/src/main/java/Task.java b/src/main/java/Task.java
index ff4cdd94e..4bf169bc8 100644
--- a/src/main/java/Task.java
+++ b/src/main/java/Task.java
@@ -22,15 +22,19 @@ public void setDone(boolean done) {
         isDone = done;
     }
 
+    /**
+     * Returns the format of the task to be printed out to user
+     * @return String representation of the task
+     */
     public String toString() {
-        String temp = "[ ]";
-        if (isDone) {
-            temp = "[X]";
-        }
-        return temp + " " + description;
+        return (isDone ? "[X]" : "[ ]") + " " + description;
     }
 
+    /**
+     * Returns the format of the task to be saved into a file
+     * @return String representation of the task
+     */
     public String toSave() {
-        return null;
+        return (isDone ? "1" : "0") + " | " + description;
     }
 }
diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java
index 7a357b632..e75a4aad3 100644
--- a/src/main/java/TaskList.java
+++ b/src/main/java/TaskList.java
@@ -1,5 +1,8 @@
 import java.util.ArrayList;
 
+/**
+ * A list of tasks.
+ */
 public class TaskList {
 
     private ArrayList<Task> tasks;
@@ -21,6 +24,14 @@ public void remove(Task task){
         this.tasks.remove(task);
     }
 
+    /**
+     * This method attempts to add a Todo task into the TaskList.
+     * It will check whether the description of the task is empty before
+     * creating a ToDo object and add it into the TaskList.
+     *
+     * @param description Details regarding the todo task.
+     * @throws DukeException If the description of the todo task is empty.
+     */
     public void addTodo(String description) throws DukeException {
         if (description.isBlank()) {
             throw new DukeException("Description of a todo cannot be empty");
@@ -28,6 +39,16 @@ public void addTodo(String description) throws DukeException {
         tasks.add(new ToDo(description));
     }
 
+    /**
+     * This method attempts to add a deadline task into the TaskList.
+     * It will check whether the description of the task is empty before
+     * extracting the deadline of the task. It will then create a new Deadline
+     * object and add it into the TaskList.
+     *
+     * @param description Details regarding the deadline task.
+     * @throws DukeException If the description of the deadline task is empty
+     *                       or when the /by keyword is not provided.
+     */
     public void addDeadline(String description) throws DukeException {
         if (description.isBlank()) {
             throw new DukeException("Description of a deadline cannot be empty");
@@ -44,6 +65,16 @@ public void addDeadline(String description) throws DukeException {
 
     }
 
+    /**
+     * This method attempts to add an event task to the TaskList.
+     * It will check whether the description of the task is empty before extracting
+     * the dates/time for from when the event start to when the event ends. It then
+     * creates a Event object and add it into the TaskList.
+     *
+     * @param description Details regarding the Event task.
+     * @throws DukeException If the description of the Event task is empty
+     *                       or when the /from and /to keywords are the provided.
+     */
     public void addEvent(String description) throws DukeException {
         if (description.isBlank()) {
             throw new DukeException("Description of a event cannot be empty");
@@ -62,6 +93,15 @@ public void addEvent(String description) throws DukeException {
 
     }
 
+    /**
+     * This method attempts to mark a task in the TaskList
+     * It will check whether the task index provided by the user is valid before marking the task as
+     * the respective isDone argument.
+     *
+     * @param taskID Index of the task to be marked.
+     * @param isDone True to mark the task as done and False to mark the task as undone.
+     * @throws DukeException if task index is not found or task index in not an int.
+     */
     public void markTask(String taskID, boolean isDone) throws DukeException {
         try {
             int index = Integer.parseInt(taskID);
@@ -73,6 +113,14 @@ public void markTask(String taskID, boolean isDone) throws DukeException {
         }
     }
 
+    /**
+     * This method attempts to delete a task based on the task index from the TaskList
+     * It will check whether the task index provided by the user exist before deleting the task.
+     *
+     * @param taskID Index of task to be deleted.
+     * @return The removed task to be printed by Ui.
+     * @throws DukeException If task index is not an integer or task index does not exist.
+     */
     public Task deleteTask(String taskID) throws DukeException {
         try {
             int index = Integer.parseInt(taskID);
@@ -86,6 +134,15 @@ public Task deleteTask(String taskID) throws DukeException {
         }
     }
 
+    /**
+     * This method attempts to find the tasks with descriptions that matches the keyword provided
+     * It first check if the keyword provided is valid before going through the TaskList. For every
+     * task, it splits the description into substrings and compare word by word with the keyword.
+     *
+     * @param keyword Keyword to be searched for.
+     * @return A list of tasks that matches the keyword for Ui object to print.
+     * @throws DukeException If keyword is not a word or null.
+     */
     public ArrayList<Task> find(String keyword) throws DukeException {
         if (keyword.isBlank()) {
             throw new DukeException("Keyword cannot be empty");
diff --git a/src/main/java/ToDo.java b/src/main/java/ToDo.java
index 3e088fa2d..6bfbf268f 100644
--- a/src/main/java/ToDo.java
+++ b/src/main/java/ToDo.java
@@ -4,12 +4,20 @@ public ToDo(String description) {
         super(description);
     }
 
+    /**
+     * Returns the format of the task to be printed out to user
+     * @return String representation of the task
+     */
     public String toString() {
         return "[T]" + super.toString();
     }
 
+    /**
+     * Returns the format of the task to be saved into a file
+     * @return String representation of the task
+     */
     @Override
     public String toSave() {
-        return "T | " + (this.isDone() ? "1" : "0") + " | " + this.getDescription();
+        return "T | " + super.toSave();
     }
 }
diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java
index 4521bdd75..53cc36564 100644
--- a/src/main/java/Ui.java
+++ b/src/main/java/Ui.java
@@ -1,6 +1,10 @@
 import java.util.ArrayList;
 import java.util.Scanner;
 
+/**
+ * User interface object that handles the format and content of various outputs to the user
+ * through command line interface.
+ */
 public class Ui {
     private static final String LINE_DIVIDER = "\t---------------------------------------";
     protected Scanner scanner;

From e1a286f0c0647a976ab56ad84427000da8ed0202 Mon Sep 17 00:00:00 2001
From: limyuhching <75166212+limyuhching@users.noreply.github.com>
Date: Wed, 4 Oct 2023 17:00:55 +0800
Subject: [PATCH 15/20] Update README.md

---
 docs/README.md | 88 ++++++++++++++++++++++++++++++++++----------------
 1 file changed, 60 insertions(+), 28 deletions(-)

diff --git a/docs/README.md b/docs/README.md
index 8077118eb..d5d8dc137 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,29 +1,61 @@
-# User Guide
-
+# Wenny Task Manager User Guide
+Wenny is your friendly task manager that helps you keep track of your endless numbers of to do tasks, deadlines and events.  
 ## Features 
-
-### Feature-ABC
-
-Description of the feature.
-
-### Feature-XYZ
-
-Description of the feature.
-
-## Usage
-
-### `Keyword` - Describe action
-
-Describe the action and its outcome.
-
-Example of usage: 
-
-`keyword (optional arguments)`
-
-Expected outcome:
-
-Description of the outcome.
-
-```
-expected output
-```
+Notes about the command format:
+1. Words in UPPER_CASE are the parameters to be supplied by the user.
+e.g. in todo DESCRIPTION, DESCRIPTION is a parameter which can be used as todo Homework.
+
+2. Extraneous parameters for commands that do not take in parameters (such as list and bye) will be ignored.
+e.g. if the command specifies list 123, it will be interpreted as list.
+
+### List current tasks `list`
+List all current tasks.
+Format: `list`
+
+### Exit the program `bye`
+Exit the program.
+Format: `bye`
+
+### Add a to-do task `todo`
+Add to-do task into the list.
+Format: `list DESCRIPTION`
+Example:
+- `todo complete week 7 tasks`
+- `todo sleep`
+
+### Add a deadline task `deadline`
+Add a task with a deadline
+Format: `deadline DESCRIPTION /by DEADLINE`
+Example:
+- `deadline complete week 8 tasks /by 12 Oct`
+
+### Add an event task `event`
+Add an event into the task list
+Format: `event DESCRIPTION /from START_TIME /to END_TIME`
+Example:
+- `event IA interview /from 7 Oct 2pm /to 7 Oct 4pm`
+- 
+### Mark a task as done `mark`
+Mark a task on the task list as done
+Format: `mark TASK_NUMBER`
+Exmaple:
+- `mark 1`
+
+### Mark a task as undone `unmark`
+Mark a task on the task list as undone
+Format: `unmark TASK_NUMBER`
+Exmaple:
+- `unmark 1`
+
+
+### Delete a task `delete`
+Delete a task from the task list
+Format: `delete TASK_NUMBER`
+Exmaple:
+- `delete 1`
+
+### Find the tasks that matches a certain keyword `find`
+Find the tasks that matches a certain keyword 
+Format: `find KEYWORD`
+Exmaple:
+- `find John`

From 119b4c951b40d642dba5f029e7725aa747e137e7 Mon Sep 17 00:00:00 2001
From: limyuhching <75166212+limyuhching@users.noreply.github.com>
Date: Wed, 4 Oct 2023 17:12:05 +0800
Subject: [PATCH 16/20] Update README.md

---
 docs/README.md | 83 +++++++++++++++++++++++++++++++-------------------
 1 file changed, 51 insertions(+), 32 deletions(-)

diff --git a/docs/README.md b/docs/README.md
index d5d8dc137..c4a655f89 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -3,59 +3,78 @@ Wenny is your friendly task manager that helps you keep track of your endless nu
 ## Features 
 Notes about the command format:
 1. Words in UPPER_CASE are the parameters to be supplied by the user.
-e.g. in todo DESCRIPTION, DESCRIPTION is a parameter which can be used as todo Homework.
+e.g. in todo DESCRIPTION, DESCRIPTION is a parameter which can be used as `todo Homework`.
 
 2. Extraneous parameters for commands that do not take in parameters (such as list and bye) will be ignored.
-e.g. if the command specifies list 123, it will be interpreted as list.
+e.g. if the command specifies `list 123`, it will be interpreted as list.
+
+## List current tasks `list`
 
-### List current tasks `list`
 List all current tasks.
+
 Format: `list`
 
-### Exit the program `bye`
+## Exit the program `bye`
+
 Exit the program.
+
 Format: `bye`
 
-### Add a to-do task `todo`
+## Add a to-do task `todo`
+
 Add to-do task into the list.
+
 Format: `list DESCRIPTION`
+
 Example:
 - `todo complete week 7 tasks`
 - `todo sleep`
 
-### Add a deadline task `deadline`
-Add a task with a deadline
+
+## Add a deadline task `deadline`
+Add a task with a deadline.
+
 Format: `deadline DESCRIPTION /by DEADLINE`
+
 Example:
-- `deadline complete week 8 tasks /by 12 Oct`
+- `deadline complete week 8 tasks /by 12 Oct`.
+
+
+## Add an event task `event`
+Add an event into the task list.
+
+Format: `event DESCRIPTION /from START_TIME /to END_TIME`.
+
+Example:
+- `event IA interview /from 7 Oct 2pm /to 7 Oct 4pm`.
+  
+## Mark a task as done `mark`
+Mark a task on the task list as done.
+Format: `mark TASK_NUMBER`.
 
-### Add an event task `event`
-Add an event into the task list
-Format: `event DESCRIPTION /from START_TIME /to END_TIME`
 Example:
-- `event IA interview /from 7 Oct 2pm /to 7 Oct 4pm`
-- 
-### Mark a task as done `mark`
-Mark a task on the task list as done
-Format: `mark TASK_NUMBER`
-Exmaple:
 - `mark 1`
 
-### Mark a task as undone `unmark`
-Mark a task on the task list as undone
-Format: `unmark TASK_NUMBER`
-Exmaple:
-- `unmark 1`
+## Mark a task as undone `unmark`
+Mark a task on the task list as undone.
+
+Format: `unmark TASK_NUMBER`.
+
+Example:
+- `unmark 1`.
 
 
-### Delete a task `delete`
-Delete a task from the task list
-Format: `delete TASK_NUMBER`
-Exmaple:
-- `delete 1`
+## Delete a task `delete`
+Delete a task from the task list.
 
-### Find the tasks that matches a certain keyword `find`
-Find the tasks that matches a certain keyword 
-Format: `find KEYWORD`
-Exmaple:
-- `find John`
+Format: `delete TASK_NUMBER`.
+
+Example:
+- `delete 1`.
+
+## Find the tasks that matches a certain keyword `find`
+Find the tasks that matches a certain keyword .
+Format: `find KEYWORD`.
+
+Example:
+- `find John`.

From 0a66c63f37375356e24dea6494321f8bf759cc9b Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Wed, 4 Oct 2023 20:40:44 +0800
Subject: [PATCH 17/20] Minor UI changes

---
 src/main/java/Duke.java     |  2 ++
 src/main/java/Storage.java  |  6 +++---
 src/main/java/TaskList.java |  4 ++--
 src/main/java/Ui.java       | 18 ++++++++++++++----
 4 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index fa2208b4b..74c0df72b 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -22,8 +22,10 @@ public class Duke {
     public Duke(String filePath) {
         ui = new Ui();
         storage = new Storage(filePath);
+        ui.showLoadingFile();
         try {
             taskList = new TaskList(storage.load());
+            ui.showFileLoaded();
         } catch (DukeException e) {
             ui.showError(e);
             taskList = new TaskList();
diff --git a/src/main/java/Storage.java b/src/main/java/Storage.java
index da27b3f12..870b5ac8e 100644
--- a/src/main/java/Storage.java
+++ b/src/main/java/Storage.java
@@ -64,14 +64,14 @@ public ArrayList<Task> load() throws DukeException {
                     }
                     break;
                 default:
-                    System.out.println("\tUnknown task encountered. Skipping");
+                    System.out.println("\tUnknown task encountered. Skipping.");
                     break;
                 }
             }
         } catch (FileNotFoundException e) {
-            throw new DukeException("\tFailed to load file");
+            throw new DukeException("\tFailed to load file: file not found.");
         } catch (ArrayIndexOutOfBoundsException e) {
-            throw new DukeException("\tFile is corrupted");
+            throw new DukeException("\tFailed to load file: file is corrupted.");
         }
         return allTasks;
     }
diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java
index e75a4aad3..f38439456 100644
--- a/src/main/java/TaskList.java
+++ b/src/main/java/TaskList.java
@@ -60,7 +60,7 @@ public void addDeadline(String description) throws DukeException {
             Deadline deadline = new Deadline(description, by);
             tasks.add(deadline);
         } catch (ArrayIndexOutOfBoundsException e) {
-            throw new DukeException("Wrong format! Expected format: deadline [task] /by [time]");
+            throw new DukeException("Wrong format! Expected format: deadline DESCRIPTION /by TIME");
         }
 
     }
@@ -88,7 +88,7 @@ public void addEvent(String description) throws DukeException {
             Event event = new Event(description, from, to);
             tasks.add(event);
         } catch (ArrayIndexOutOfBoundsException e) {
-            throw new DukeException("Wrong format! Expected format: event [task] /from [time] /to [time]");
+            throw new DukeException("Wrong format! Expected format: event DESCRIPTION /from START_TIME /to END_TIME");
         }
 
     }
diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java
index 53cc36564..8d331128e 100644
--- a/src/main/java/Ui.java
+++ b/src/main/java/Ui.java
@@ -13,12 +13,22 @@ public Ui(){
         this.scanner = new Scanner(System.in);
     }
 
+    public void showLoadingFile() {
+        showLine();
+        System.out.println("\tLoading file......");
+        showLine();
+    }
+
+    public void showFileLoaded() {
+        showLine();
+        System.out.println("\tFile has been successfully loaded");
+        showLine();
+    }
     public void showStartMessage() {
-        String intro = "~~~~~~~~~~~~~~~~~~~\n"
-                        + "Hello! I'm Wenny!\n"
-                        + "How may I help you?\n"
-                        + "~~~~~~~~~~~~~~~~~~~";
+        showLine();
+        String intro = "\tHello! I'm Wenny!\n\tHow may I help you?";
         System.out.println(intro);
+        showLine();
     }
 
     public void showByeMessage() {

From 9cfe06ed27f804534c301ccb77b3d0b79db9ec6a Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Wed, 4 Oct 2023 20:44:03 +0800
Subject: [PATCH 18/20] Minor UI changes

---
 src/main/java/Storage.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/main/java/Storage.java b/src/main/java/Storage.java
index 870b5ac8e..ccea9c230 100644
--- a/src/main/java/Storage.java
+++ b/src/main/java/Storage.java
@@ -69,9 +69,9 @@ public ArrayList<Task> load() throws DukeException {
                 }
             }
         } catch (FileNotFoundException e) {
-            throw new DukeException("\tFailed to load file: file not found.");
+            throw new DukeException("Failed to load file: file not found.");
         } catch (ArrayIndexOutOfBoundsException e) {
-            throw new DukeException("\tFailed to load file: file is corrupted.");
+            throw new DukeException("Failed to load file: file is corrupted.");
         }
         return allTasks;
     }

From 96b87277b14e68157ddca3729b0934787410d44c Mon Sep 17 00:00:00 2001
From: Lim Yuh Ching <e0726103@u.nus.edu>
Date: Wed, 4 Oct 2023 21:12:30 +0800
Subject: [PATCH 19/20] Handle exception when argument is missing

---
 src/main/java/Parser.java   |  2 +-
 src/main/java/TaskList.java | 16 +++++++++-------
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/src/main/java/Parser.java b/src/main/java/Parser.java
index e9456c55b..dab652756 100644
--- a/src/main/java/Parser.java
+++ b/src/main/java/Parser.java
@@ -15,7 +15,7 @@ public Parser() {
     public Command parse(String fullCommand) {
         String[] substr = fullCommand.split("\\s+", 2);
         if (substr.length == 1) {
-            return new Command(substr[0], null);
+            return new Command(substr[0], "");
         }
         return new Command(substr[0], substr[1]);
     }
diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java
index f38439456..848e39a8a 100644
--- a/src/main/java/TaskList.java
+++ b/src/main/java/TaskList.java
@@ -33,10 +33,11 @@ public void remove(Task task){
      * @throws DukeException If the description of the todo task is empty.
      */
     public void addTodo(String description) throws DukeException {
-        if (description.isBlank()) {
+        if (description.isBlank()) { // Check if description is empty
             throw new DukeException("Description of a todo cannot be empty");
         }
         tasks.add(new ToDo(description));
+
     }
 
     /**
@@ -50,13 +51,13 @@ public void addTodo(String description) throws DukeException {
      *                       or when the /by keyword is not provided.
      */
     public void addDeadline(String description) throws DukeException {
-        if (description.isBlank()) {
-            throw new DukeException("Description of a deadline cannot be empty");
-        }
         try {
             String[] deadlineTokens = description.split("/by");
             description = deadlineTokens[0].trim();
             String by = deadlineTokens[1].trim();
+            if (description.isBlank() | by.isBlank()) { // Check if description is empty
+                throw new DukeException("Wrong format! Expected format: deadline DESCRIPTION /by TIME");
+            }
             Deadline deadline = new Deadline(description, by);
             tasks.add(deadline);
         } catch (ArrayIndexOutOfBoundsException e) {
@@ -76,15 +77,16 @@ public void addDeadline(String description) throws DukeException {
      *                       or when the /from and /to keywords are the provided.
      */
     public void addEvent(String description) throws DukeException {
-        if (description.isBlank()) {
-            throw new DukeException("Description of a event cannot be empty");
-        }
         try {
             String[] eventTokens = description.split("/from");
             description = eventTokens[0].trim();
             String[] fromAndToTokens = eventTokens[1].split("/to");
             String from = fromAndToTokens[0].trim();
             String to = fromAndToTokens[1].trim();
+            if (description.isBlank() | from.isBlank() | to.isBlank()) { // Check if format is correct
+                throw new DukeException("Wrong format! Expected format: "
+                                         + "event DESCRIPTION /from START_TIME /to END_TIME");
+            }
             Event event = new Event(description, from, to);
             tasks.add(event);
         } catch (ArrayIndexOutOfBoundsException e) {

From 7edd3e731fac8ac7b20930da3690640f9391dcfe Mon Sep 17 00:00:00 2001
From: limyuhching <75166212+limyuhching@users.noreply.github.com>
Date: Sat, 7 Oct 2023 23:29:12 +0800
Subject: [PATCH 20/20] Update README.md

---
 docs/README.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/docs/README.md b/docs/README.md
index c4a655f89..2b1fd3586 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -50,6 +50,7 @@ Example:
   
 ## Mark a task as done `mark`
 Mark a task on the task list as done.
+
 Format: `mark TASK_NUMBER`.
 
 Example:
@@ -74,6 +75,7 @@ Example:
 
 ## Find the tasks that matches a certain keyword `find`
 Find the tasks that matches a certain keyword .
+
 Format: `find KEYWORD`.
 
 Example: