From 7faa1cb6252a3d11347155913a847707a411833b Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Thu, 26 Jan 2023 13:12:38 +0800 Subject: [PATCH 01/19] Add HinaBot.java --- src/main/java/HinaBot.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/HinaBot.java diff --git a/src/main/java/HinaBot.java b/src/main/java/HinaBot.java new file mode 100644 index 000000000..2752a8b83 --- /dev/null +++ b/src/main/java/HinaBot.java @@ -0,0 +1,7 @@ +public class HinaBot { + public static void main(String[] args) { + System.out.println("Hello master!"); + System.out.println("What are your orders?"); + System.out.println("Goodbye master, let's meet again soon..."); + } +} From 0e9f1534c5bc0d08f0ce942ed132daee54465a38 Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Fri, 27 Jan 2023 19:08:56 +0800 Subject: [PATCH 02/19] Refactor greeting message and add handleCommand method to echo user input --- src/main/java/HinaBot.java | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/HinaBot.java b/src/main/java/HinaBot.java index 2752a8b83..3701b2d8f 100644 --- a/src/main/java/HinaBot.java +++ b/src/main/java/HinaBot.java @@ -1,7 +1,28 @@ +import java.util.Scanner; + public class HinaBot { public static void main(String[] args) { + String line; + Scanner in = new Scanner(System.in); + showGreeting(); + while (true) { + line = in.nextLine(); + handleCommand(line); + } + } + + private static void showGreeting() { System.out.println("Hello master!"); System.out.println("What are your orders?"); - System.out.println("Goodbye master, let's meet again soon..."); + } + + public static void handleCommand(String command) { + if (!command.equalsIgnoreCase("bye")) { + System.out.println(command); + } + else { + System.out.println("Goodbye master, let's meet again soon..."); + System.exit(0); + } } } From 565a8e1d9f254770df775de2bdab9b0c2871768a Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Wed, 1 Feb 2023 00:59:47 +0800 Subject: [PATCH 03/19] Add code for adding items to a list and printing the list --- src/main/java/HinaBot.java | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/main/java/HinaBot.java b/src/main/java/HinaBot.java index 3701b2d8f..f402b37cf 100644 --- a/src/main/java/HinaBot.java +++ b/src/main/java/HinaBot.java @@ -1,6 +1,8 @@ import java.util.Scanner; public class HinaBot { + protected static String[] taskList = new String[100]; + protected static int taskCount = 0; public static void main(String[] args) { String line; Scanner in = new Scanner(System.in); @@ -17,12 +19,28 @@ private static void showGreeting() { } public static void handleCommand(String command) { - if (!command.equalsIgnoreCase("bye")) { - System.out.println(command); - } - else { + if (command.equalsIgnoreCase("bye")) { System.out.println("Goodbye master, let's meet again soon..."); System.exit(0); } + else if (command.equalsIgnoreCase("list")) { + listTasks(); + } + else { + addTask(command); + } + } + + public static void addTask(String task) { + taskList[taskCount] = task; + taskCount++; + System.out.println("added: " + task); + } + + public static void listTasks() { + for (int i = 0; i < taskCount; i++) { + System.out.print(i + 1); + System.out.println(". " + taskList[i]); + } } } From 3d008904c5a9b3e4a48676ea05530a729c3b7db7 Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Wed, 1 Feb 2023 13:36:30 +0800 Subject: [PATCH 04/19] Add Task class, add code to mark and unmark tasks --- src/main/java/HinaBot.java | 38 +++++++++++++++++++++++++++++++++----- src/main/java/Task.java | 24 ++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 src/main/java/Task.java diff --git a/src/main/java/HinaBot.java b/src/main/java/HinaBot.java index f402b37cf..b1f524aa0 100644 --- a/src/main/java/HinaBot.java +++ b/src/main/java/HinaBot.java @@ -1,7 +1,7 @@ import java.util.Scanner; public class HinaBot { - protected static String[] taskList = new String[100]; + protected static Task[] taskList = new Task[100]; protected static int taskCount = 0; public static void main(String[] args) { String line; @@ -26,21 +26,49 @@ public static void handleCommand(String command) { else if (command.equalsIgnoreCase("list")) { listTasks(); } + else if (command.split(" ")[0].equalsIgnoreCase("mark")) { + int taskIndex = Integer.parseInt(command.split(" ")[1]); + markTask(taskIndex); + } + else if (command.split(" ")[0].equalsIgnoreCase("unmark")) { + int taskIndex = Integer.parseInt(command.split(" ")[1]); + unmarkTask(taskIndex); + } else { addTask(command); } } - public static void addTask(String task) { - taskList[taskCount] = task; + public static void addTask(String description) { + Task newTask = new Task(description); + taskList[taskCount] = newTask; taskCount++; - System.out.println("added: " + task); + System.out.println("added: " + description); } public static void listTasks() { for (int i = 0; i < taskCount; i++) { System.out.print(i + 1); - System.out.println(". " + taskList[i]); + System.out.print(". "); + if (taskList[i].isDone()) { + System.out.print("[X] "); + } + else { + System.out.print("[ ] "); + } + System.out.println(taskList[i].getDescription()); } } + + public static void markTask(int taskIndex) { + taskList[taskIndex - 1].setDone(true); + System.out.println("Roger that! This task is marked as done: "); + System.out.println("[X] " + taskList[taskIndex - 1].getDescription()); + } + + public static void unmarkTask(int taskIndex) { + taskList[taskIndex - 1].setDone(false); + System.out.println("Roger that! This task is marked as done: "); + System.out.println("[ ] " + taskList[taskIndex - 1].getDescription()); + } } diff --git a/src/main/java/Task.java b/src/main/java/Task.java new file mode 100644 index 000000000..3ba3b3f86 --- /dev/null +++ b/src/main/java/Task.java @@ -0,0 +1,24 @@ +public class Task { + private String description; + private boolean isDone; + public boolean isDone() { + return isDone; + } + + public void setDone(boolean done) { + isDone = done; + } + + public Task(String description) { + this.description = description; + isDone = false; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} From 7e758c3a91d41d43006c379c502de1ceb83a4e1f Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Wed, 1 Feb 2023 18:57:03 +0800 Subject: [PATCH 05/19] Add support for todo, deadline and event task types. --- src/main/java/Deadline.java | 18 +++++++++++++ src/main/java/Event.java | 20 ++++++++++++++ src/main/java/HinaBot.java | 52 +++++++++++++++++++++++++++---------- src/main/java/Task.java | 11 ++++++++ 4 files changed, 88 insertions(+), 13 deletions(-) create mode 100644 src/main/java/Deadline.java create mode 100644 src/main/java/Event.java diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java new file mode 100644 index 000000000..fda0ccdf0 --- /dev/null +++ b/src/main/java/Deadline.java @@ -0,0 +1,18 @@ +public class Deadline extends Task{ + private String by; + public Deadline(String description, String by) { + super(description); + this.by = by; + } + + public String toString() { + String mark; + if (super.isDone()) { + mark = "X"; + } + else { + mark = " "; + } + return String.format("[D][%s] %s (by: %s)", mark, super.getDescription(), by); + } +} diff --git a/src/main/java/Event.java b/src/main/java/Event.java new file mode 100644 index 000000000..6fad02ec3 --- /dev/null +++ b/src/main/java/Event.java @@ -0,0 +1,20 @@ +public class Event extends Task { + private String from; + private String to; + public Event(String description, String from, String to) { + super(description); + this.from = from; + this.to = to; + } + + public String toString() { + String mark; + if (super.isDone()) { + mark = "X"; + } + else { + mark = " "; + } + return String.format("[D][%s] %s(from: %s to: %s)", mark, super.getDescription(), from, to); + } +} diff --git a/src/main/java/HinaBot.java b/src/main/java/HinaBot.java index b1f524aa0..b3274e8dc 100644 --- a/src/main/java/HinaBot.java +++ b/src/main/java/HinaBot.java @@ -34,8 +34,14 @@ else if (command.split(" ")[0].equalsIgnoreCase("unmark")) { int taskIndex = Integer.parseInt(command.split(" ")[1]); unmarkTask(taskIndex); } - else { - addTask(command); + else if (command.split(" ")[0].equalsIgnoreCase("todo")){ + addTask(command.substring(5)); + } + else if (command.split(" ")[0].equalsIgnoreCase("deadline")) { + addDeadline(command.substring(9)); + } + else if (command.split(" ")[0].equalsIgnoreCase("event")) { + addEvent(command.substring(6)); } } @@ -43,32 +49,52 @@ public static void addTask(String description) { Task newTask = new Task(description); taskList[taskCount] = newTask; taskCount++; - System.out.println("added: " + description); + System.out.println("Noted! This task has been added:"); + System.out.println(newTask.toString()); + getTaskCount(); } public static void listTasks() { for (int i = 0; i < taskCount; i++) { System.out.print(i + 1); System.out.print(". "); - if (taskList[i].isDone()) { - System.out.print("[X] "); - } - else { - System.out.print("[ ] "); - } - System.out.println(taskList[i].getDescription()); + System.out.println(taskList[i].toString()); } } public static void markTask(int taskIndex) { taskList[taskIndex - 1].setDone(true); System.out.println("Roger that! This task is marked as done: "); - System.out.println("[X] " + taskList[taskIndex - 1].getDescription()); + System.out.println(taskList[taskIndex - 1].toString()); } public static void unmarkTask(int taskIndex) { taskList[taskIndex - 1].setDone(false); - System.out.println("Roger that! This task is marked as done: "); - System.out.println("[ ] " + taskList[taskIndex - 1].getDescription()); + System.out.println("Roger that! This task is marked as not done: "); + System.out.println(taskList[taskIndex - 1].toString()); + } + + public static void addDeadline(String deadline) { + String[] details = deadline.split("/"); + Deadline newDeadline = new Deadline(details[0], details[1].substring(3)); + taskList[taskCount] = newDeadline; + taskCount++; + System.out.println("Noted! This task has been added:"); + System.out.println(newDeadline.toString()); + getTaskCount(); + } + + public static void addEvent(String event) { + String[] details = event.split("/"); + Event newEvent = new Event(details[0], details[1].substring(5).trim(), details[2].substring(3)); + taskList[taskCount] = newEvent; + taskCount++; + System.out.println("Noted! This task has been added:"); + System.out.println(newEvent.toString()); + getTaskCount(); + } + + public static void getTaskCount() { + System.out.printf("There are %d items on your list.\n", taskCount); } } diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 3ba3b3f86..6f46de7d6 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -21,4 +21,15 @@ public String getDescription() { public void setDescription(String description) { this.description = description; } + + public String toString() { + String mark; + if (isDone) { + mark = "X"; + } + else { + mark = " "; + } + return String.format("[T][%s] %s", mark, description); + } } From e13adce876dd1afb739f20e74b37949de3718fce Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Wed, 1 Feb 2023 19:14:31 +0800 Subject: [PATCH 06/19] no message --- src/main/java/HinaBot.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/HinaBot.java b/src/main/java/HinaBot.java index b1f524aa0..546b492cf 100644 --- a/src/main/java/HinaBot.java +++ b/src/main/java/HinaBot.java @@ -68,7 +68,11 @@ public static void markTask(int taskIndex) { public static void unmarkTask(int taskIndex) { taskList[taskIndex - 1].setDone(false); +<<<<<<< HEAD System.out.println("Roger that! This task is marked as done: "); +======= + System.out.println("Roger that! This task is marked as not done: "); +>>>>>>> bab6548 (Add Task class, add code to mark and unmark tasks) System.out.println("[ ] " + taskList[taskIndex - 1].getDescription()); } } From c47e25350ddbd40400100ae31ab71339eec5c901 Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Wed, 1 Feb 2023 19:24:45 +0800 Subject: [PATCH 07/19] Resolved error resulting from RCS mistake --- src/main/java/HinaBot.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/java/HinaBot.java b/src/main/java/HinaBot.java index 0b2e934f4..b3274e8dc 100644 --- a/src/main/java/HinaBot.java +++ b/src/main/java/HinaBot.java @@ -70,14 +70,6 @@ public static void markTask(int taskIndex) { public static void unmarkTask(int taskIndex) { taskList[taskIndex - 1].setDone(false); -<<<<<<< HEAD -<<<<<<< HEAD - System.out.println("Roger that! This task is marked as done: "); -======= - System.out.println("Roger that! This task is marked as not done: "); ->>>>>>> bab6548 (Add Task class, add code to mark and unmark tasks) - System.out.println("[ ] " + taskList[taskIndex - 1].getDescription()); -======= System.out.println("Roger that! This task is marked as not done: "); System.out.println(taskList[taskIndex - 1].toString()); } @@ -104,6 +96,5 @@ public static void addEvent(String event) { public static void getTaskCount() { System.out.printf("There are %d items on your list.\n", taskCount); ->>>>>>> 7e758c3a91d41d43006c379c502de1ceb83a4e1f } } From e40dfd028f52eaf0caf260edeb9ae74d7d91d409 Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Tue, 14 Feb 2023 22:25:44 +0800 Subject: [PATCH 08/19] Add code to handle unknown command, insufficient detail exceptions. --- src/main/java/HinaBot.java | 65 +++++++++++++++++++------------- src/main/java/HinaException.java | 2 + 2 files changed, 40 insertions(+), 27 deletions(-) create mode 100644 src/main/java/HinaException.java diff --git a/src/main/java/HinaBot.java b/src/main/java/HinaBot.java index b3274e8dc..5d76f260c 100644 --- a/src/main/java/HinaBot.java +++ b/src/main/java/HinaBot.java @@ -3,13 +3,20 @@ public class HinaBot { protected static Task[] taskList = new Task[100]; protected static int taskCount = 0; + public static void main(String[] args) { String line; Scanner in = new Scanner(System.in); showGreeting(); while (true) { - line = in.nextLine(); - handleCommand(line); + try { + line = in.nextLine(); + handleCommand(line); + } catch (HinaException cmdException) { + System.out.println(">.< Hina does not recognise this command!"); + } catch (StringIndexOutOfBoundsException argException) { + System.out.println("@_@ Please give Hina more details!"); + } } } @@ -18,30 +25,26 @@ private static void showGreeting() { System.out.println("What are your orders?"); } - public static void handleCommand(String command) { + public static void handleCommand(String command) throws HinaException { if (command.equalsIgnoreCase("bye")) { System.out.println("Goodbye master, let's meet again soon..."); System.exit(0); - } - else if (command.equalsIgnoreCase("list")) { + } else if (command.equalsIgnoreCase("list")) { listTasks(); - } - else if (command.split(" ")[0].equalsIgnoreCase("mark")) { + } else if (command.split(" ")[0].equalsIgnoreCase("mark")) { int taskIndex = Integer.parseInt(command.split(" ")[1]); markTask(taskIndex); - } - else if (command.split(" ")[0].equalsIgnoreCase("unmark")) { + } else if (command.split(" ")[0].equalsIgnoreCase("unmark")) { int taskIndex = Integer.parseInt(command.split(" ")[1]); unmarkTask(taskIndex); - } - else if (command.split(" ")[0].equalsIgnoreCase("todo")){ + } else if (command.split(" ")[0].equalsIgnoreCase("todo")) { addTask(command.substring(5)); - } - else if (command.split(" ")[0].equalsIgnoreCase("deadline")) { + } else if (command.split(" ")[0].equalsIgnoreCase("deadline")) { addDeadline(command.substring(9)); - } - else if (command.split(" ")[0].equalsIgnoreCase("event")) { + } else if (command.split(" ")[0].equalsIgnoreCase("event")) { addEvent(command.substring(6)); + } else { + throw new HinaException(); } } @@ -76,22 +79,30 @@ public static void unmarkTask(int taskIndex) { public static void addDeadline(String deadline) { String[] details = deadline.split("/"); - Deadline newDeadline = new Deadline(details[0], details[1].substring(3)); - taskList[taskCount] = newDeadline; - taskCount++; - System.out.println("Noted! This task has been added:"); - System.out.println(newDeadline.toString()); - getTaskCount(); + if (details.length < 2) { + System.out.println("Hina needs to know the deadline for this task!"); + } else { + Deadline newDeadline = new Deadline(details[0], details[1].substring(3)); + taskList[taskCount] = newDeadline; + taskCount++; + System.out.println("Noted! This task has been added:"); + System.out.println(newDeadline.toString()); + getTaskCount(); + } } public static void addEvent(String event) { String[] details = event.split("/"); - Event newEvent = new Event(details[0], details[1].substring(5).trim(), details[2].substring(3)); - taskList[taskCount] = newEvent; - taskCount++; - System.out.println("Noted! This task has been added:"); - System.out.println(newEvent.toString()); - getTaskCount(); + if (details.length < 3) { + System.out.println("Please tell Hina when this event starts and ends!"); + } else { + Event newEvent = new Event(details[0], details[1].substring(5).trim(), details[2].substring(3)); + taskList[taskCount] = newEvent; + taskCount++; + System.out.println("Noted! This task has been added:"); + System.out.println(newEvent.toString()); + getTaskCount(); + } } public static void getTaskCount() { diff --git a/src/main/java/HinaException.java b/src/main/java/HinaException.java new file mode 100644 index 000000000..5153cd620 --- /dev/null +++ b/src/main/java/HinaException.java @@ -0,0 +1,2 @@ +public class HinaException extends Throwable { +} From 367c9fd385f0692527100ad6d284759ea3e52dbe Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Tue, 14 Feb 2023 22:39:51 +0800 Subject: [PATCH 09/19] Divide classes into packages --- src/main/java/{ => hina}/HinaBot.java | 7 +++++++ src/main/java/{ => hina/exceptions}/HinaException.java | 2 ++ src/main/java/{ => hina/task}/Deadline.java | 6 +++++- src/main/java/{ => hina/task}/Event.java | 4 ++++ src/main/java/{ => hina/task}/Task.java | 2 ++ 5 files changed, 20 insertions(+), 1 deletion(-) rename src/main/java/{ => hina}/HinaBot.java (97%) rename src/main/java/{ => hina/exceptions}/HinaException.java (65%) rename src/main/java/{ => hina/task}/Deadline.java (82%) rename src/main/java/{ => hina/task}/Event.java (91%) rename src/main/java/{ => hina/task}/Task.java (97%) diff --git a/src/main/java/HinaBot.java b/src/main/java/hina/HinaBot.java similarity index 97% rename from src/main/java/HinaBot.java rename to src/main/java/hina/HinaBot.java index 5d76f260c..33870c7e3 100644 --- a/src/main/java/HinaBot.java +++ b/src/main/java/hina/HinaBot.java @@ -1,3 +1,10 @@ +package hina; + +import hina.exceptions.HinaException; +import hina.task.Deadline; +import hina.task.Event; +import hina.task.Task; + import java.util.Scanner; public class HinaBot { diff --git a/src/main/java/HinaException.java b/src/main/java/hina/exceptions/HinaException.java similarity index 65% rename from src/main/java/HinaException.java rename to src/main/java/hina/exceptions/HinaException.java index 5153cd620..f0c448cb4 100644 --- a/src/main/java/HinaException.java +++ b/src/main/java/hina/exceptions/HinaException.java @@ -1,2 +1,4 @@ +package hina.exceptions; + public class HinaException extends Throwable { } diff --git a/src/main/java/Deadline.java b/src/main/java/hina/task/Deadline.java similarity index 82% rename from src/main/java/Deadline.java rename to src/main/java/hina/task/Deadline.java index fda0ccdf0..b2d1a00a0 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/hina/task/Deadline.java @@ -1,4 +1,8 @@ -public class Deadline extends Task{ +package hina.task; + +import hina.task.Task; + +public class Deadline extends Task { private String by; public Deadline(String description, String by) { super(description); diff --git a/src/main/java/Event.java b/src/main/java/hina/task/Event.java similarity index 91% rename from src/main/java/Event.java rename to src/main/java/hina/task/Event.java index 6fad02ec3..71ed40cb1 100644 --- a/src/main/java/Event.java +++ b/src/main/java/hina/task/Event.java @@ -1,3 +1,7 @@ +package hina.task; + +import hina.task.Task; + public class Event extends Task { private String from; private String to; diff --git a/src/main/java/Task.java b/src/main/java/hina/task/Task.java similarity index 97% rename from src/main/java/Task.java rename to src/main/java/hina/task/Task.java index 6f46de7d6..905c97199 100644 --- a/src/main/java/Task.java +++ b/src/main/java/hina/task/Task.java @@ -1,3 +1,5 @@ +package hina.task; + public class Task { private String description; private boolean isDone; From 65eef30fc562ac5f2799f22b465f3c88354a3128 Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Wed, 1 Mar 2023 00:41:03 +0800 Subject: [PATCH 10/19] Add method to delete tasks, fixed coding standard violations, change access levels in Task class --- src/main/java/hina/HinaBot.java | 40 ++++++++++++++++----------- src/main/java/hina/task/Deadline.java | 3 +- src/main/java/hina/task/Event.java | 11 ++++++-- src/main/java/hina/task/Task.java | 7 ++--- 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/main/java/hina/HinaBot.java b/src/main/java/hina/HinaBot.java index 33870c7e3..ddbde5e16 100644 --- a/src/main/java/hina/HinaBot.java +++ b/src/main/java/hina/HinaBot.java @@ -5,16 +5,17 @@ import hina.task.Event; import hina.task.Task; + +import java.util.ArrayList; import java.util.Scanner; + public class HinaBot { - protected static Task[] taskList = new Task[100]; - protected static int taskCount = 0; + protected static ArrayList taskList = new ArrayList(); public static void main(String[] args) { String line; Scanner in = new Scanner(System.in); - showGreeting(); while (true) { try { line = in.nextLine(); @@ -50,6 +51,9 @@ public static void handleCommand(String command) throws HinaException { addDeadline(command.substring(9)); } else if (command.split(" ")[0].equalsIgnoreCase("event")) { addEvent(command.substring(6)); + } else if (command.split(" ")[0].equalsIgnoreCase("delete")) { + int taskIndex = Integer.parseInt(command.split(" ")[1]); + deleteTask(taskIndex); } else { throw new HinaException(); } @@ -57,31 +61,31 @@ public static void handleCommand(String command) throws HinaException { public static void addTask(String description) { Task newTask = new Task(description); - taskList[taskCount] = newTask; - taskCount++; + taskList.add(newTask); System.out.println("Noted! This task has been added:"); System.out.println(newTask.toString()); getTaskCount(); } public static void listTasks() { - for (int i = 0; i < taskCount; i++) { + for (Task task : taskList) { + int i = taskList.indexOf(task); System.out.print(i + 1); System.out.print(". "); - System.out.println(taskList[i].toString()); + System.out.println(task.toString()); } } public static void markTask(int taskIndex) { - taskList[taskIndex - 1].setDone(true); + taskList.get(taskIndex - 1).setDone(true); System.out.println("Roger that! This task is marked as done: "); - System.out.println(taskList[taskIndex - 1].toString()); + System.out.println(taskList.get(taskIndex - 1).toString()); } public static void unmarkTask(int taskIndex) { - taskList[taskIndex - 1].setDone(false); + taskList.get(taskIndex - 1).setDone(false); System.out.println("Roger that! This task is marked as not done: "); - System.out.println(taskList[taskIndex - 1].toString()); + System.out.println(taskList.get(taskIndex - 1).toString()); } public static void addDeadline(String deadline) { @@ -90,8 +94,7 @@ public static void addDeadline(String deadline) { System.out.println("Hina needs to know the deadline for this task!"); } else { Deadline newDeadline = new Deadline(details[0], details[1].substring(3)); - taskList[taskCount] = newDeadline; - taskCount++; + taskList.add(newDeadline); System.out.println("Noted! This task has been added:"); System.out.println(newDeadline.toString()); getTaskCount(); @@ -104,15 +107,20 @@ public static void addEvent(String event) { System.out.println("Please tell Hina when this event starts and ends!"); } else { Event newEvent = new Event(details[0], details[1].substring(5).trim(), details[2].substring(3)); - taskList[taskCount] = newEvent; - taskCount++; + taskList.add(newEvent); System.out.println("Noted! This task has been added:"); System.out.println(newEvent.toString()); getTaskCount(); } } + public static void deleteTask(int taskIndex) { + System.out.println("Got it! This task will be removed:"); + System.out.println(taskList.get(taskIndex - 1).toString()); + taskList.remove(taskIndex - 1); + } + public static void getTaskCount() { - System.out.printf("There are %d items on your list.\n", taskCount); + System.out.printf("There are %d items on your list.\n", taskList.size()); } } diff --git a/src/main/java/hina/task/Deadline.java b/src/main/java/hina/task/Deadline.java index b2d1a00a0..199e14fe3 100644 --- a/src/main/java/hina/task/Deadline.java +++ b/src/main/java/hina/task/Deadline.java @@ -13,8 +13,7 @@ public String toString() { String mark; if (super.isDone()) { mark = "X"; - } - else { + } else { mark = " "; } return String.format("[D][%s] %s (by: %s)", mark, super.getDescription(), by); diff --git a/src/main/java/hina/task/Event.java b/src/main/java/hina/task/Event.java index 71ed40cb1..c49026ee3 100644 --- a/src/main/java/hina/task/Event.java +++ b/src/main/java/hina/task/Event.java @@ -15,10 +15,17 @@ public String toString() { String mark; if (super.isDone()) { mark = "X"; - } - else { + } else { mark = " "; } return String.format("[D][%s] %s(from: %s to: %s)", mark, super.getDescription(), from, to); } + + public String getFrom() { + return from; + } + + public String getTo() { + return to; + } } diff --git a/src/main/java/hina/task/Task.java b/src/main/java/hina/task/Task.java index 905c97199..0bc39b115 100644 --- a/src/main/java/hina/task/Task.java +++ b/src/main/java/hina/task/Task.java @@ -1,8 +1,8 @@ package hina.task; public class Task { - private String description; - private boolean isDone; + protected String description; + protected boolean isDone; public boolean isDone() { return isDone; } @@ -28,8 +28,7 @@ public String toString() { String mark; if (isDone) { mark = "X"; - } - else { + } else { mark = " "; } return String.format("[T][%s] %s", mark, description); From c890a60644b5e0c08fb3e68f4797d472ff611dba Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Wed, 1 Mar 2023 01:32:37 +0800 Subject: [PATCH 11/19] Add functionality to save task list to a .txt file. --- data/savedlist.txt | 0 src/main/java/hina/HinaBot.java | 125 ++++++++++++++++++++++---- src/main/java/hina/task/Deadline.java | 7 +- src/main/java/hina/task/Event.java | 15 +++- src/main/java/hina/task/Task.java | 11 ++- 5 files changed, 135 insertions(+), 23 deletions(-) create mode 100644 data/savedlist.txt diff --git a/data/savedlist.txt b/data/savedlist.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/main/java/hina/HinaBot.java b/src/main/java/hina/HinaBot.java index 33870c7e3..79e708cbf 100644 --- a/src/main/java/hina/HinaBot.java +++ b/src/main/java/hina/HinaBot.java @@ -5,16 +5,37 @@ import hina.task.Event; import hina.task.Task; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Scanner; +import java.io.File; public class HinaBot { - protected static Task[] taskList = new Task[100]; - protected static int taskCount = 0; + protected static ArrayList taskList = new ArrayList(); public static void main(String[] args) { String line; Scanner in = new Scanner(System.in); showGreeting(); + try { + readSaveFile(); + } catch (FileNotFoundException exception) { + System.out.println("Save file not found! Creating new file..."); + File newFile = new File("data/savedlist.txt"); + try { + Path dataPath = Paths.get("data"); + Files.createDirectory(dataPath); + newFile.createNewFile(); + System.out.println("Save file created!"); + } catch (IOException ioException) { + System.out.println("Ahh! Something went wrong, could not create file!"); + } + } while (true) { try { line = in.nextLine(); @@ -32,6 +53,50 @@ private static void showGreeting() { System.out.println("What are your orders?"); } + public static void readSaveFile() throws FileNotFoundException { + File saveFile = new File("data/savedlist.txt"); + Scanner save = new Scanner(saveFile); + System.out.println("Saved list found, loading saved list..."); + while (save.hasNext()) { + String line = save.nextLine(); + String[] taskDetails = line.split(" / "); + if (taskDetails[0].equals("T")) { + Task savedTask = new Task(taskDetails[2]); + if (taskDetails[1].equals("0")) { + savedTask.setDone(false); + } else { + savedTask.setDone(true); + } + taskList.add(savedTask); + } else if (taskDetails[0].equals("D")) { + Deadline savedDeadline = new Deadline(taskDetails[2], taskDetails[3]); + if (taskDetails[1].equals("0")) { + savedDeadline.setDone(false); + } else { + savedDeadline.setDone(true); + } + taskList.add(savedDeadline); + } else if (taskDetails[0].equals("E")) { + Event savedEvent = new Event(taskDetails[2], taskDetails[3], taskDetails[4]); + if (taskDetails[1].equals("0")) { + savedEvent.setDone(false); + } else { + savedEvent.setDone(true); + } + taskList.add(savedEvent); + } + } + } + + public static void writeToFile() throws IOException { + FileWriter saveFile = new FileWriter("data/savedlist.txt"); + for (Task taskToSave : taskList) { + saveFile.write(taskToSave.toSave()); + saveFile.write("\n"); + } + saveFile.close(); + } + public static void handleCommand(String command) throws HinaException { if (command.equalsIgnoreCase("bye")) { System.out.println("Goodbye master, let's meet again soon..."); @@ -50,6 +115,9 @@ public static void handleCommand(String command) throws HinaException { addDeadline(command.substring(9)); } else if (command.split(" ")[0].equalsIgnoreCase("event")) { addEvent(command.substring(6)); + } else if (command.split(" ")[0].equalsIgnoreCase("delete")) { + int taskIndex = Integer.parseInt(command.split(" ")[1]); + deleteTask(taskIndex); } else { throw new HinaException(); } @@ -57,31 +125,39 @@ public static void handleCommand(String command) throws HinaException { public static void addTask(String description) { Task newTask = new Task(description); - taskList[taskCount] = newTask; - taskCount++; + taskList.add(newTask); System.out.println("Noted! This task has been added:"); System.out.println(newTask.toString()); getTaskCount(); + try { + writeToFile(); + } catch (IOException ioexception) { + System.out.println("Something went wrong, could not save!"); + } } public static void listTasks() { - for (int i = 0; i < taskCount; i++) { + if (taskList.size() == 0) { + System.out.println("There are no items on the list :o"); + } + for (Task task : taskList) { + int i = taskList.indexOf(task); System.out.print(i + 1); System.out.print(". "); - System.out.println(taskList[i].toString()); + System.out.println(task.toString()); } } public static void markTask(int taskIndex) { - taskList[taskIndex - 1].setDone(true); + taskList.get(taskIndex - 1).setDone(true); System.out.println("Roger that! This task is marked as done: "); - System.out.println(taskList[taskIndex - 1].toString()); + System.out.println(taskList.get(taskIndex - 1).toString()); } public static void unmarkTask(int taskIndex) { - taskList[taskIndex - 1].setDone(false); + taskList.get(taskIndex - 1).setDone(false); System.out.println("Roger that! This task is marked as not done: "); - System.out.println(taskList[taskIndex - 1].toString()); + System.out.println(taskList.get(taskIndex - 1).toString()); } public static void addDeadline(String deadline) { @@ -90,11 +166,15 @@ public static void addDeadline(String deadline) { System.out.println("Hina needs to know the deadline for this task!"); } else { Deadline newDeadline = new Deadline(details[0], details[1].substring(3)); - taskList[taskCount] = newDeadline; - taskCount++; + taskList.add(newDeadline); System.out.println("Noted! This task has been added:"); System.out.println(newDeadline.toString()); getTaskCount(); + try { + writeToFile(); + } catch (IOException ioexception) { + System.out.println("Something went wrong, could not save!"); + } } } @@ -104,15 +184,30 @@ public static void addEvent(String event) { System.out.println("Please tell Hina when this event starts and ends!"); } else { Event newEvent = new Event(details[0], details[1].substring(5).trim(), details[2].substring(3)); - taskList[taskCount] = newEvent; - taskCount++; + taskList.add(newEvent); System.out.println("Noted! This task has been added:"); System.out.println(newEvent.toString()); getTaskCount(); + try { + writeToFile(); + } catch (IOException ioexception) { + System.out.println("Something went wrong, could not save!"); + } + } + } + + public static void deleteTask(int taskIndex) { + System.out.println("Got it! This task will be removed:"); + System.out.println(taskList.get(taskIndex - 1).toString()); + taskList.remove(taskIndex - 1); + try { + writeToFile(); + } catch (IOException ioexception) { + System.out.println("Something went wrong, could not save!"); } } public static void getTaskCount() { - System.out.printf("There are %d items on your list.\n", taskCount); + System.out.printf("There are %d items on your list.\n", taskList.size()); } } diff --git a/src/main/java/hina/task/Deadline.java b/src/main/java/hina/task/Deadline.java index b2d1a00a0..71bcb7fbf 100644 --- a/src/main/java/hina/task/Deadline.java +++ b/src/main/java/hina/task/Deadline.java @@ -13,10 +13,13 @@ public String toString() { String mark; if (super.isDone()) { mark = "X"; - } - else { + } else { mark = " "; } return String.format("[D][%s] %s (by: %s)", mark, super.getDescription(), by); } + + public String toSave() { + return String.format("T / %s / %s / %s", isDone? "1" : "0", description, by); + } } diff --git a/src/main/java/hina/task/Event.java b/src/main/java/hina/task/Event.java index 71ed40cb1..9c5d5b23f 100644 --- a/src/main/java/hina/task/Event.java +++ b/src/main/java/hina/task/Event.java @@ -15,10 +15,21 @@ public String toString() { String mark; if (super.isDone()) { mark = "X"; - } - else { + } else { mark = " "; } return String.format("[D][%s] %s(from: %s to: %s)", mark, super.getDescription(), from, to); } + + public String getFrom() { + return from; + } + + public String getTo() { + return to; + } + + public String toSave() { + return String.format("T / %s / %s / %s / %s", isDone? "1" : "0", description, from, to); + } } diff --git a/src/main/java/hina/task/Task.java b/src/main/java/hina/task/Task.java index 905c97199..5d19498d2 100644 --- a/src/main/java/hina/task/Task.java +++ b/src/main/java/hina/task/Task.java @@ -1,8 +1,8 @@ package hina.task; public class Task { - private String description; - private boolean isDone; + protected String description; + protected boolean isDone; public boolean isDone() { return isDone; } @@ -28,10 +28,13 @@ public String toString() { String mark; if (isDone) { mark = "X"; - } - else { + } else { mark = " "; } return String.format("[T][%s] %s", mark, description); } + + public String toSave() { + return String.format("T / %s / %s", isDone? "1" : "0", description); + } } From 3b7e16a607dec2c5cebb122066b084c327c7f148 Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Thu, 2 Mar 2023 02:23:05 +0800 Subject: [PATCH 12/19] Refactor functionality into Parser, Ui, Storage and TaskList classes. Fixed bugs: 1. trailing whitespaces leading to storing blank information in Deadline and Event objects. 2. taskList now saves to the hard disk after marking and unmarking tasks. --- src/main/java/Duke.java | 10 -- src/main/java/hina/HinaBot.java | 214 +++--------------------- src/main/java/hina/helper/Parser.java | 57 +++++++ src/main/java/hina/helper/Storage.java | 72 ++++++++ src/main/java/hina/helper/TaskList.java | 84 ++++++++++ src/main/java/hina/helper/Ui.java | 24 +++ src/main/java/hina/task/Event.java | 2 - 7 files changed, 258 insertions(+), 205 deletions(-) delete mode 100644 src/main/java/Duke.java create mode 100644 src/main/java/hina/helper/Parser.java create mode 100644 src/main/java/hina/helper/Storage.java create mode 100644 src/main/java/hina/helper/TaskList.java create mode 100644 src/main/java/hina/helper/Ui.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java deleted file mode 100644 index 5d313334c..000000000 --- a/src/main/java/Duke.java +++ /dev/null @@ -1,10 +0,0 @@ -public class Duke { - public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - } -} diff --git a/src/main/java/hina/HinaBot.java b/src/main/java/hina/HinaBot.java index 359cd0609..91c356546 100644 --- a/src/main/java/hina/HinaBot.java +++ b/src/main/java/hina/HinaBot.java @@ -1,215 +1,43 @@ package hina; import hina.exceptions.HinaException; -import hina.task.Deadline; -import hina.task.Event; +import hina.helper.Parser; +import hina.helper.Storage; +import hina.helper.TaskList; +import hina.helper.Ui; import hina.task.Task; - import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Scanner; -import java.io.File; public class HinaBot { protected static ArrayList taskList = new ArrayList(); - - public static void main(String[] args) { - String line; - Scanner in = new Scanner(System.in); - showGreeting(); + private static Ui ui; + private static Storage storage; + private static TaskList tasks; + public HinaBot(String savePath, String dataDir) { + ui = new Ui(); + storage = new Storage(); + Ui.showGreeting(); try { - readSaveFile(); + tasks = new TaskList(Storage.readSaveFile(savePath)); } catch (FileNotFoundException exception) { - System.out.println("Save file not found! Creating new file..."); - File newFile = new File("data/savedlist.txt"); - try { - Path dataPath = Paths.get("data"); - Files.createDirectory(dataPath); - newFile.createNewFile(); - System.out.println("Save file created!"); - } catch (IOException ioException) { - System.out.println("Ahh! Something went wrong, could not create file!"); - } + Storage.createSaveFile(savePath, dataDir); } - while (true) { - try { - line = in.nextLine(); - handleCommand(line); - } catch (HinaException cmdException) { - System.out.println(">.< Hina does not recognise this command!"); - } catch (StringIndexOutOfBoundsException argException) { - System.out.println("@_@ Please give Hina more details!"); - } - } - } - - private static void showGreeting() { - System.out.println("Hello master!"); - System.out.println("What are your orders?"); } - public static void readSaveFile() throws FileNotFoundException { - File saveFile = new File("data/savedlist.txt"); - Scanner save = new Scanner(saveFile); - System.out.println("Saved list found, loading saved list..."); - while (save.hasNext()) { - String line = save.nextLine(); - String[] taskDetails = line.split(" / "); - if (taskDetails[0].equals("T")) { - Task savedTask = new Task(taskDetails[2]); - if (taskDetails[1].equals("0")) { - savedTask.setDone(false); - } else { - savedTask.setDone(true); - } - taskList.add(savedTask); - } else if (taskDetails[0].equals("D")) { - Deadline savedDeadline = new Deadline(taskDetails[2], taskDetails[3]); - if (taskDetails[1].equals("0")) { - savedDeadline.setDone(false); - } else { - savedDeadline.setDone(true); - } - taskList.add(savedDeadline); - } else if (taskDetails[0].equals("E")) { - Event savedEvent = new Event(taskDetails[2], taskDetails[3], taskDetails[4]); - if (taskDetails[1].equals("0")) { - savedEvent.setDone(false); - } else { - savedEvent.setDone(true); - } - taskList.add(savedEvent); - } - } - } - - public static void writeToFile() throws IOException { - FileWriter saveFile = new FileWriter("data/savedlist.txt"); - for (Task taskToSave : taskList) { - saveFile.write(taskToSave.toSave()); - saveFile.write("\n"); - } - saveFile.close(); - } - - public static void handleCommand(String command) throws HinaException { - if (command.equalsIgnoreCase("bye")) { - System.out.println("Goodbye master, let's meet again soon..."); - System.exit(0); - } else if (command.equalsIgnoreCase("list")) { - listTasks(); - } else if (command.split(" ")[0].equalsIgnoreCase("mark")) { - int taskIndex = Integer.parseInt(command.split(" ")[1]); - markTask(taskIndex); - } else if (command.split(" ")[0].equalsIgnoreCase("unmark")) { - int taskIndex = Integer.parseInt(command.split(" ")[1]); - unmarkTask(taskIndex); - } else if (command.split(" ")[0].equalsIgnoreCase("todo")) { - addTask(command.substring(5)); - } else if (command.split(" ")[0].equalsIgnoreCase("deadline")) { - addDeadline(command.substring(9)); - } else if (command.split(" ")[0].equalsIgnoreCase("event")) { - addEvent(command.substring(6)); - } else if (command.split(" ")[0].equalsIgnoreCase("delete")) { - int taskIndex = Integer.parseInt(command.split(" ")[1]); - deleteTask(taskIndex); - } else { - throw new HinaException(); - } - } - - public static void addTask(String description) { - Task newTask = new Task(description); - taskList.add(newTask); - System.out.println("Noted! This task has been added:"); - System.out.println(newTask.toString()); - getTaskCount(); - try { - writeToFile(); - } catch (IOException ioexception) { - System.out.println("Something went wrong, could not save!"); - } - } - - public static void listTasks() { - if (taskList.size() == 0) { - System.out.println("There are no items on the list :o"); - } - for (Task task : taskList) { - int i = taskList.indexOf(task); - System.out.print(i + 1); - System.out.print(". "); - System.out.println(task.toString()); - } - } - - public static void markTask(int taskIndex) { - taskList.get(taskIndex - 1).setDone(true); - System.out.println("Roger that! This task is marked as done: "); - System.out.println(taskList.get(taskIndex - 1).toString()); - } - - public static void unmarkTask(int taskIndex) { - taskList.get(taskIndex - 1).setDone(false); - System.out.println("Roger that! This task is marked as not done: "); - System.out.println(taskList.get(taskIndex - 1).toString()); - } - - public static void addDeadline(String deadline) { - String[] details = deadline.split("/"); - if (details.length < 2) { - System.out.println("Hina needs to know the deadline for this task!"); - } else { - Deadline newDeadline = new Deadline(details[0], details[1].substring(3)); - taskList.add(newDeadline); - System.out.println("Noted! This task has been added:"); - System.out.println(newDeadline.toString()); - getTaskCount(); - try { - writeToFile(); - } catch (IOException ioexception) { - System.out.println("Something went wrong, could not save!"); - } - } - } + public static void main(String[] args) { + new HinaBot("data/savedlist.txt", "data"); - public static void addEvent(String event) { - String[] details = event.split("/"); - if (details.length < 3) { - System.out.println("Please tell Hina when this event starts and ends!"); - } else { - Event newEvent = new Event(details[0], details[1].substring(5).trim(), details[2].substring(3)); - taskList.add(newEvent); - System.out.println("Noted! This task has been added:"); - System.out.println(newEvent.toString()); - getTaskCount(); + while (true) { try { - writeToFile(); - } catch (IOException ioexception) { - System.out.println("Something went wrong, could not save!"); + Parser.readCommand(); + } catch (HinaException cmdException) { + Ui.invalidCommandMessage(); + } catch (StringIndexOutOfBoundsException argException) { + Ui.notEnoughDetails(); } } } - - public static void deleteTask(int taskIndex) { - System.out.println("Got it! This task will be removed:"); - System.out.println(taskList.get(taskIndex - 1).toString()); - taskList.remove(taskIndex - 1); - try { - writeToFile(); - } catch (IOException ioexception) { - System.out.println("Something went wrong, could not save!"); - } - } - - public static void getTaskCount() { - System.out.printf("There are %d items on your list.\n", taskList.size()); - } } diff --git a/src/main/java/hina/helper/Parser.java b/src/main/java/hina/helper/Parser.java new file mode 100644 index 000000000..9ebe53348 --- /dev/null +++ b/src/main/java/hina/helper/Parser.java @@ -0,0 +1,57 @@ +package hina.helper; + +import hina.exceptions.HinaException; + +import java.io.IOException; +import java.util.Scanner; + +public class Parser { + public static void readCommand() throws HinaException { + String line; + Scanner in = new Scanner(System.in); + line = in.nextLine().trim(); + if (line.equalsIgnoreCase("bye")) { + Ui.showExitMessage(); + System.exit(0); + } else if (line.equalsIgnoreCase("list")) { + TaskList.listTasks(); + } else if (line.split(" ")[0].equalsIgnoreCase("mark")) { + int taskIndex = Integer.parseInt(line.split(" ")[1]); + TaskList.markTask(taskIndex); + } else if (line.split(" ")[0].equalsIgnoreCase("unmark")) { + int taskIndex = Integer.parseInt(line.split(" ")[1]); + TaskList.unmarkTask(taskIndex); + } else if (line.split(" ")[0].equalsIgnoreCase("todo")) { + TaskList.addTask(line.substring(5)); + try { + Storage.writeToFile(); + } catch (IOException ioexception) { + Ui.couldNotSaveMessage(); + } + } else if (line.split(" ")[0].equalsIgnoreCase("deadline")) { + TaskList.addDeadline(line.substring(9)); + try { + Storage.writeToFile(); + } catch (IOException ioexception) { + Ui.couldNotSaveMessage(); + } + } else if (line.split(" ")[0].equalsIgnoreCase("event")) { + TaskList.addEvent(line.substring(6)); + try { + Storage.writeToFile(); + } catch (IOException ioexception) { + Ui.couldNotSaveMessage(); + } + } else if (line.split(" ")[0].equalsIgnoreCase("delete")) { + int taskIndex = Integer.parseInt(line.split(" ")[1]); + TaskList.deleteTask(taskIndex); + try { + Storage.writeToFile(); + } catch (IOException ioexception) { + Ui.couldNotSaveMessage(); + } + } else { + throw new HinaException(); + } + } +} diff --git a/src/main/java/hina/helper/Storage.java b/src/main/java/hina/helper/Storage.java new file mode 100644 index 000000000..408405df0 --- /dev/null +++ b/src/main/java/hina/helper/Storage.java @@ -0,0 +1,72 @@ +package hina.helper; + +import hina.task.Deadline; +import hina.task.Event; +import hina.task.Task; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Scanner; + +public class Storage { + + public Storage() { + } + + public static ArrayList readSaveFile(String savePath) throws FileNotFoundException { + ArrayList savedList = new ArrayList<>(); + File saveFile = new File(savePath); + Scanner save = new Scanner(saveFile); + System.out.println("Saved list found, loading saved list..."); + while (save.hasNext()) { + String line = save.nextLine(); + String[] taskDetails = line.split(" / "); + switch (taskDetails[0]) { + case "T": + Task savedTask = new Task(taskDetails[2]); + savedTask.setDone(!taskDetails[1].equals("0")); + savedList.add(savedTask); + break; + case "D": + Deadline savedDeadline = new Deadline(taskDetails[2], taskDetails[3]); + savedDeadline.setDone(!taskDetails[1].equals("0")); + savedList.add(savedDeadline); + break; + case "E": + Event savedEvent = new Event(taskDetails[2], taskDetails[3], taskDetails[4]); + savedEvent.setDone(!taskDetails[1].equals("0")); + savedList.add(savedEvent); + break; + } + } + return savedList; + } + + public static void createSaveFile(String savePath, String dataDir) { + System.out.println("Save file not found! Creating new file..."); + File newFile = new File(savePath); + try { + Path dataPath = Paths.get(dataDir); + Files.createDirectory(dataPath); + newFile.createNewFile(); + System.out.println("Save file created!"); + } catch (IOException ioException) { + System.out.println("T.T Ahh! Something went wrong, could not create file!"); + } + } + + public static void writeToFile() throws IOException { + FileWriter saveFile = new FileWriter("data/savedlist.txt"); + for (Task taskToSave : TaskList.getTaskList()) { + saveFile.write(taskToSave.toSave()); + saveFile.write("\n"); + } + saveFile.close(); + } +} diff --git a/src/main/java/hina/helper/TaskList.java b/src/main/java/hina/helper/TaskList.java new file mode 100644 index 000000000..3ffb6e49d --- /dev/null +++ b/src/main/java/hina/helper/TaskList.java @@ -0,0 +1,84 @@ +package hina.helper; + +import hina.task.Deadline; +import hina.task.Event; +import hina.task.Task; + +import java.util.ArrayList; + +public class TaskList { + private static ArrayList taskList; + public TaskList(ArrayList savedList) { + taskList = savedList; + } + + public static ArrayList getTaskList() { + return taskList; + } + + public static void listTasks() { + if (taskList.size() == 0) { + System.out.println("There are no items on the list :o"); + } + for (Task task : taskList) { + int i = taskList.indexOf(task); + System.out.print(i + 1); + System.out.print(". "); + System.out.println(task.toString()); + } + } + public static void getTaskCount() { + System.out.printf("There are %d items on your list.\n", taskList.size()); + } + public static void addTask(String description) { + Task newTask = new Task(description); + taskList.add(newTask); + System.out.println("Noted! This task has been added:"); + System.out.println(newTask.toString()); + getTaskCount(); + } + public static void addDeadline(String deadline) { + String[] details = deadline.split("/by"); + if (details.length < 2) { + System.out.println("Hina needs to know the deadline for this task!"); + } else { + Deadline newDeadline = new Deadline(details[0], details[1]); + taskList.add(newDeadline); + System.out.println("Noted! This task has been added:"); + System.out.println(newDeadline.toString()); + getTaskCount(); + } + } + public static void addEvent(String event) { + String[] details = event.split("/from"); + if (details.length < 2) { + System.out.println("Please tell Hina when this event starts!"); + } else { + if (details[1].split("/to").length < 2) { + System.out.println("Please tell Hina when this event ends!"); + } else { + Event newEvent = new Event(details[0], details[1].split("/to")[0].trim(), details[1].split("/to")[1].trim()); + taskList.add(newEvent); + System.out.println("Noted! This task has been added:"); + System.out.println(newEvent.toString()); + getTaskCount(); + } + } + } + public static void deleteTask(int taskIndex) { + System.out.println("Got it! This task will be removed:"); + System.out.println(taskList.get(taskIndex - 1).toString()); + taskList.remove(taskIndex - 1); + getTaskCount(); + } + public static void markTask(int taskIndex) { + taskList.get(taskIndex - 1).setDone(true); + System.out.println("Roger that! This task is marked as done: "); + System.out.println(taskList.get(taskIndex - 1).toString()); + } + public static void unmarkTask(int taskIndex) { + taskList.get(taskIndex - 1).setDone(false); + System.out.println("Roger that! This task is marked as not done: "); + System.out.println(taskList.get(taskIndex - 1).toString()); + } +} diff --git a/src/main/java/hina/helper/Ui.java b/src/main/java/hina/helper/Ui.java new file mode 100644 index 000000000..65bcf71bc --- /dev/null +++ b/src/main/java/hina/helper/Ui.java @@ -0,0 +1,24 @@ +package hina.helper; + +public class Ui { + public Ui() { + } + + public static void showGreeting() { + System.out.println("Hello master!"); + System.out.println("What are your orders?"); + } + public static void showExitMessage() { + System.out.println("Goodbye master, let's meet again soon..."); + } + public static void invalidCommandMessage() { + System.out.println(">.< Hina does not recognise this command!"); + } + public static void notEnoughDetails() { + System.out.println("@_@ Please give Hina more details!"); + } + public static void couldNotSaveMessage() { + System.out.println("Something went wrong, could not save!"); + } + +} diff --git a/src/main/java/hina/task/Event.java b/src/main/java/hina/task/Event.java index 21f7260c5..058387661 100644 --- a/src/main/java/hina/task/Event.java +++ b/src/main/java/hina/task/Event.java @@ -1,7 +1,5 @@ package hina.task; -import hina.task.Task; - public class Event extends Task { private String from; private String to; From b0dc677ba4321ca28b64b9f6f6d05aae7c3e145f Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Thu, 2 Mar 2023 21:15:33 +0800 Subject: [PATCH 13/19] Add date-time format support --- src/main/java/hina/helper/Storage.java | 14 ++++++--- src/main/java/hina/helper/TaskList.java | 38 ++++++++++++++++++------- src/main/java/hina/helper/Ui.java | 4 ++- src/main/java/hina/task/Deadline.java | 19 +++++++++---- src/main/java/hina/task/Event.java | 28 ++++++++++++------ 5 files changed, 73 insertions(+), 30 deletions(-) diff --git a/src/main/java/hina/helper/Storage.java b/src/main/java/hina/helper/Storage.java index 408405df0..9e7b3a256 100644 --- a/src/main/java/hina/helper/Storage.java +++ b/src/main/java/hina/helper/Storage.java @@ -11,6 +11,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.time.LocalDateTime; +import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Scanner; @@ -34,12 +36,16 @@ public static ArrayList readSaveFile(String savePath) throws FileNotFoundE savedList.add(savedTask); break; case "D": - Deadline savedDeadline = new Deadline(taskDetails[2], taskDetails[3]); - savedDeadline.setDone(!taskDetails[1].equals("0")); - savedList.add(savedDeadline); + try { + Deadline savedDeadline = new Deadline(taskDetails[2], LocalDateTime.parse(taskDetails[3], TaskList.formatter)); + savedDeadline.setDone(!taskDetails[1].equals("0")); + savedList.add(savedDeadline); + } catch (DateTimeParseException e) { + System.out.println(e.getMessage()); + } break; case "E": - Event savedEvent = new Event(taskDetails[2], taskDetails[3], taskDetails[4]); + Event savedEvent = new Event(taskDetails[2], LocalDateTime.parse(taskDetails[3], TaskList.formatter), LocalDateTime.parse(taskDetails[4], TaskList.formatter)); savedEvent.setDone(!taskDetails[1].equals("0")); savedList.add(savedEvent); break; diff --git a/src/main/java/hina/helper/TaskList.java b/src/main/java/hina/helper/TaskList.java index 3ffb6e49d..2ac410733 100644 --- a/src/main/java/hina/helper/TaskList.java +++ b/src/main/java/hina/helper/TaskList.java @@ -4,10 +4,14 @@ import hina.task.Event; import hina.task.Task; +import java.time.DateTimeException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; public class TaskList { private static ArrayList taskList; + public static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm"); public TaskList(ArrayList savedList) { taskList = savedList; } @@ -42,11 +46,17 @@ public static void addDeadline(String deadline) { if (details.length < 2) { System.out.println("Hina needs to know the deadline for this task!"); } else { - Deadline newDeadline = new Deadline(details[0], details[1]); - taskList.add(newDeadline); - System.out.println("Noted! This task has been added:"); - System.out.println(newDeadline.toString()); - getTaskCount(); + try { + LocalDateTime by = LocalDateTime.parse(details[1].trim(), formatter); + Deadline newDeadline = new Deadline(details[0], by); + taskList.add(newDeadline); + System.out.println("Noted! This task has been added:"); + System.out.println(newDeadline); + getTaskCount(); + + } catch (DateTimeException exception) { + Ui.showDateTimeError(); + } } } public static void addEvent(String event) { @@ -57,11 +67,19 @@ public static void addEvent(String event) { if (details[1].split("/to").length < 2) { System.out.println("Please tell Hina when this event ends!"); } else { - Event newEvent = new Event(details[0], details[1].split("/to")[0].trim(), details[1].split("/to")[1].trim()); - taskList.add(newEvent); - System.out.println("Noted! This task has been added:"); - System.out.println(newEvent.toString()); - getTaskCount(); + try { + LocalDateTime from = LocalDateTime.parse(details[1].split("/to")[0].trim(), formatter); + LocalDateTime to = LocalDateTime.parse(details[1].split("/to")[1].trim(), formatter); + Event newEvent = new Event(details[0], from, to); + taskList.add(newEvent); + System.out.println("Noted! This task has been added:"); + System.out.println(newEvent); + getTaskCount(); + + } catch (DateTimeException exception) { + Ui.showDateTimeError(); + } + } } } diff --git a/src/main/java/hina/helper/Ui.java b/src/main/java/hina/helper/Ui.java index 65bcf71bc..ef88cd0d5 100644 --- a/src/main/java/hina/helper/Ui.java +++ b/src/main/java/hina/helper/Ui.java @@ -20,5 +20,7 @@ public static void notEnoughDetails() { public static void couldNotSaveMessage() { System.out.println("Something went wrong, could not save!"); } - + public static void showDateTimeError() { + System.out.println("Please use dd-MMM-yyyy HH:mm format!"); + } } diff --git a/src/main/java/hina/task/Deadline.java b/src/main/java/hina/task/Deadline.java index 82289a8ff..bc098d8ca 100644 --- a/src/main/java/hina/task/Deadline.java +++ b/src/main/java/hina/task/Deadline.java @@ -1,12 +1,19 @@ package hina.task; -import hina.task.Task; +import java.time.DateTimeException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Date; + +import hina.helper.Ui; public class Deadline extends Task { - private String by; - public Deadline(String description, String by) { + private LocalDateTime by; + String byString; + public Deadline(String description, LocalDateTime by) { super(description); - this.by = by; + this.by = by; + this.byString = this.by.format(DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm")); } public String toString() { @@ -16,10 +23,10 @@ public String toString() { } else { mark = " "; } - return String.format("[D][%s] %s (by: %s)", mark, super.getDescription(), by); + return String.format("[D][%s] %s (by: %s)", mark, super.getDescription(), byString); } public String toSave() { - return String.format("D / %s / %s / %s", isDone? "1" : "0", description, by); + return String.format("D / %s / %s / %s", isDone? "1" : "0", description, byString); } } diff --git a/src/main/java/hina/task/Event.java b/src/main/java/hina/task/Event.java index 058387661..bd652d394 100644 --- a/src/main/java/hina/task/Event.java +++ b/src/main/java/hina/task/Event.java @@ -1,12 +1,22 @@ package hina.task; +import hina.helper.Ui; + +import java.time.DateTimeException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + public class Event extends Task { - private String from; - private String to; - public Event(String description, String from, String to) { + private LocalDateTime from; + private String fromStr; + private LocalDateTime to; + private String toStr; + public Event(String description, LocalDateTime from, LocalDateTime to) { super(description); this.from = from; this.to = to; + this.fromStr = this.from.format(DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm")); + this.toStr = this.to.format(DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm")); } public String toString() { @@ -16,18 +26,18 @@ public String toString() { } else { mark = " "; } - return String.format("[E][%s] %s(from: %s to: %s)", mark, super.getDescription(), from, to); + return String.format("[E][%s] %s(from: %s to: %s)", mark, super.getDescription(), fromStr, toStr); } - public String getFrom() { - return from; + public String getFromStr() { + return fromStr; } - public String getTo() { - return to; + public String getToStr() { + return toStr; } public String toSave() { - return String.format("E / %s / %s / %s / %s", isDone? "1" : "0", description, from, to); + return String.format("E / %s / %s / %s / %s", isDone? "1" : "0", description, fromStr, toStr); } } From 2f02a85109174f4cfa3b83ef5bf35a7aee3d661d Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Thu, 2 Mar 2023 21:35:59 +0800 Subject: [PATCH 14/19] Add method to search for items by matching substrings in Task descriptions in taskList. --- src/main/java/hina/helper/Parser.java | 2 ++ src/main/java/hina/helper/TaskList.java | 20 ++++++++++++++++++++ src/main/java/hina/helper/Ui.java | 7 ++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/main/java/hina/helper/Parser.java b/src/main/java/hina/helper/Parser.java index 9ebe53348..1eaf3e711 100644 --- a/src/main/java/hina/helper/Parser.java +++ b/src/main/java/hina/helper/Parser.java @@ -50,6 +50,8 @@ public static void readCommand() throws HinaException { } catch (IOException ioexception) { Ui.couldNotSaveMessage(); } + } else if (line.split(" ")[0].equalsIgnoreCase("find")) { + TaskList.findTask(line); } else { throw new HinaException(); } diff --git a/src/main/java/hina/helper/TaskList.java b/src/main/java/hina/helper/TaskList.java index 3ffb6e49d..3f4c6784c 100644 --- a/src/main/java/hina/helper/TaskList.java +++ b/src/main/java/hina/helper/TaskList.java @@ -81,4 +81,24 @@ public static void unmarkTask(int taskIndex) { System.out.println("Roger that! This task is marked as not done: "); System.out.println(taskList.get(taskIndex - 1).toString()); } + public static void findTask(String line) { + String query = line.substring(4).trim(); + ArrayList matchList = new ArrayList<>(); + for (Task task : taskList) { + if (task.getDescription().contains(query)) { + matchList.add(task); + } + } + if (!matchList.isEmpty()) { + Ui.taskFoundMessage(); + for (Task task : matchList) { + int i = matchList.indexOf(task); + System.out.print(i + 1); + System.out.print(". "); + System.out.println(task.toString()); + } + } else { + Ui.taskNotFoundMessage(); + } + } } diff --git a/src/main/java/hina/helper/Ui.java b/src/main/java/hina/helper/Ui.java index 65bcf71bc..3afa697b8 100644 --- a/src/main/java/hina/helper/Ui.java +++ b/src/main/java/hina/helper/Ui.java @@ -20,5 +20,10 @@ public static void notEnoughDetails() { public static void couldNotSaveMessage() { System.out.println("Something went wrong, could not save!"); } - + public static void taskFoundMessage() { + System.out.println("Found a match! Here are the results master!"); + } + public static void taskNotFoundMessage() { + System.out.println("Hina could not find anything about that in master's list..."); + } } From ecce69f8a562d22375f83c26efc11a60bb077896 Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Thu, 2 Mar 2023 22:02:05 +0800 Subject: [PATCH 15/19] Optimise imports for Deadline and Event classes --- src/main/java/hina/task/Deadline.java | 4 ---- src/main/java/hina/task/Event.java | 3 --- 2 files changed, 7 deletions(-) diff --git a/src/main/java/hina/task/Deadline.java b/src/main/java/hina/task/Deadline.java index bc098d8ca..e479fee79 100644 --- a/src/main/java/hina/task/Deadline.java +++ b/src/main/java/hina/task/Deadline.java @@ -1,11 +1,7 @@ package hina.task; -import java.time.DateTimeException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.Date; - -import hina.helper.Ui; public class Deadline extends Task { private LocalDateTime by; diff --git a/src/main/java/hina/task/Event.java b/src/main/java/hina/task/Event.java index bd652d394..293b7aa34 100644 --- a/src/main/java/hina/task/Event.java +++ b/src/main/java/hina/task/Event.java @@ -1,8 +1,5 @@ package hina.task; -import hina.helper.Ui; - -import java.time.DateTimeException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; From 019af43b060cd229b9596d0d5af9fae1cfe1d805 Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Fri, 3 Mar 2023 13:08:17 +0800 Subject: [PATCH 16/19] Add JavaDoc comments for multiple classes and methods. Refactor some command-line message outputs to methods in Ui class. --- src/main/java/hina/HinaBot.java | 12 +++-- src/main/java/hina/helper/Parser.java | 10 ++++ src/main/java/hina/helper/Storage.java | 39 ++++++++++++--- src/main/java/hina/helper/TaskList.java | 64 ++++++++++++++++++++++--- src/main/java/hina/helper/Ui.java | 27 +++++++++++ src/main/java/hina/task/Deadline.java | 13 +++++ src/main/java/hina/task/Event.java | 14 ++++++ src/main/java/hina/task/Task.java | 43 +++++++++++++++++ 8 files changed, 204 insertions(+), 18 deletions(-) diff --git a/src/main/java/hina/HinaBot.java b/src/main/java/hina/HinaBot.java index 91c356546..7d794f1c8 100644 --- a/src/main/java/hina/HinaBot.java +++ b/src/main/java/hina/HinaBot.java @@ -5,17 +5,21 @@ import hina.helper.Storage; import hina.helper.TaskList; import hina.helper.Ui; -import hina.task.Task; import java.io.FileNotFoundException; -import java.util.ArrayList; - public class HinaBot { - protected static ArrayList taskList = new ArrayList(); private static Ui ui; private static Storage storage; private static TaskList tasks; + + /** + * Class constructor specifying the path to a file containing save data. Tries to + * access the save file and attempts to create a new one if it does not exist. + * + * @param savePath path to the save file. + * @param dataDir directory the save file is stored in. + */ public HinaBot(String savePath, String dataDir) { ui = new Ui(); storage = new Storage(); diff --git a/src/main/java/hina/helper/Parser.java b/src/main/java/hina/helper/Parser.java index 1eaf3e711..26e7180f1 100644 --- a/src/main/java/hina/helper/Parser.java +++ b/src/main/java/hina/helper/Parser.java @@ -5,7 +5,17 @@ import java.io.IOException; import java.util.Scanner; +/** + * Contains methods to process user input. + */ public class Parser { + /** + * Reads a user input from the command line and determines if it was a command. + * If the input was a recognised command, handle it respectively, else throws + * a HinaException. + * + * @throws HinaException If the input is not recognised as a valid command. + */ public static void readCommand() throws HinaException { String line; Scanner in = new Scanner(System.in); diff --git a/src/main/java/hina/helper/Storage.java b/src/main/java/hina/helper/Storage.java index 9e7b3a256..23983cad3 100644 --- a/src/main/java/hina/helper/Storage.java +++ b/src/main/java/hina/helper/Storage.java @@ -17,15 +17,25 @@ import java.util.Scanner; public class Storage { - + /** + * Class constructor. + */ public Storage() { } + /** + * Returns an ArrayList containing Task objects from a .txt save file + * at a specified path on the hard disk. + * + * @param savePath relative path to the save file. + * @return the ArrayList of saved Task elements. + * @throws FileNotFoundException If the file could not be found at the specified path. + */ public static ArrayList readSaveFile(String savePath) throws FileNotFoundException { ArrayList savedList = new ArrayList<>(); File saveFile = new File(savePath); Scanner save = new Scanner(saveFile); - System.out.println("Saved list found, loading saved list..."); + Ui.saveFound(); while (save.hasNext()) { String line = save.nextLine(); String[] taskDetails = line.split(" / "); @@ -37,7 +47,8 @@ public static ArrayList readSaveFile(String savePath) throws FileNotFoundE break; case "D": try { - Deadline savedDeadline = new Deadline(taskDetails[2], LocalDateTime.parse(taskDetails[3], TaskList.formatter)); + Deadline savedDeadline = new Deadline(taskDetails[2], + LocalDateTime.parse(taskDetails[3], TaskList.formatter)); savedDeadline.setDone(!taskDetails[1].equals("0")); savedList.add(savedDeadline); } catch (DateTimeParseException e) { @@ -45,7 +56,8 @@ public static ArrayList readSaveFile(String savePath) throws FileNotFoundE } break; case "E": - Event savedEvent = new Event(taskDetails[2], LocalDateTime.parse(taskDetails[3], TaskList.formatter), LocalDateTime.parse(taskDetails[4], TaskList.formatter)); + Event savedEvent = new Event(taskDetails[2], LocalDateTime.parse(taskDetails[3], TaskList.formatter), + LocalDateTime.parse(taskDetails[4], TaskList.formatter)); savedEvent.setDone(!taskDetails[1].equals("0")); savedList.add(savedEvent); break; @@ -54,19 +66,32 @@ public static ArrayList readSaveFile(String savePath) throws FileNotFoundE return savedList; } + /** + * Creates a new .txt file at the specified path. If the directory does not exist, + * creates a new one. + * + * @param savePath relative path to the new file. + * @param dataDir relative path to the new file's directory. + */ public static void createSaveFile(String savePath, String dataDir) { - System.out.println("Save file not found! Creating new file..."); + Ui.saveNotFound(); File newFile = new File(savePath); try { Path dataPath = Paths.get(dataDir); Files.createDirectory(dataPath); newFile.createNewFile(); - System.out.println("Save file created!"); + Ui.saveCreated(); } catch (IOException ioException) { - System.out.println("T.T Ahh! Something went wrong, could not create file!"); + Ui.fileCreateError(); } } + /** + * Prints all the formatted Task objects in the TaskList on separate lines + * into a .txt file on the hard disk. + * + * @throws IOException If the file could not be written to. + */ public static void writeToFile() throws IOException { FileWriter saveFile = new FileWriter("data/savedlist.txt"); for (Task taskToSave : TaskList.getTaskList()) { diff --git a/src/main/java/hina/helper/TaskList.java b/src/main/java/hina/helper/TaskList.java index 9099ad82f..f3a36435a 100644 --- a/src/main/java/hina/helper/TaskList.java +++ b/src/main/java/hina/helper/TaskList.java @@ -11,18 +11,38 @@ public class TaskList { private static ArrayList taskList; + + /** + * Specifies the date-time format to be used. + */ public static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm"); + + /** + * Class constructor with a taskList initialised with the Task elements of + * another ArrayList. + * + * @param savedList the list from which elements are initialised. + */ public TaskList(ArrayList savedList) { taskList = savedList; } + /** + * Returns an ArrayList containing the Task elements currently stored in + * the taskList. + * + * @return the ArrayList of Task objects. + */ public static ArrayList getTaskList() { return taskList; } + /** + * Prints line-by-line the data of the Task objects stored in the taskList. + */ public static void listTasks() { if (taskList.size() == 0) { - System.out.println("There are no items on the list :o"); + Ui.emptyListMessage(); } for (Task task : taskList) { int i = taskList.indexOf(task); @@ -31,16 +51,32 @@ public static void listTasks() { System.out.println(task.toString()); } } + + /** + * Prints the number of elements in the taskList. + */ public static void getTaskCount() { System.out.printf("There are %d items on your list.\n", taskList.size()); } + + /** + * Adds a Task object to the taskList. + * + * @param description the description of the Task. + */ public static void addTask(String description) { Task newTask = new Task(description); taskList.add(newTask); - System.out.println("Noted! This task has been added:"); - System.out.println(newTask.toString()); + Ui.taskAdded(newTask); getTaskCount(); } + + /** + * Adds a Deadline object to the taskList. + * + * @param deadline a String specifying the description of the Deadline and + * the do-by date and time. + */ public static void addDeadline(String deadline) { String[] details = deadline.split("/by"); if (details.length < 2) { @@ -50,8 +86,7 @@ public static void addDeadline(String deadline) { LocalDateTime by = LocalDateTime.parse(details[1].trim(), formatter); Deadline newDeadline = new Deadline(details[0], by); taskList.add(newDeadline); - System.out.println("Noted! This task has been added:"); - System.out.println(newDeadline); + Ui.taskAdded(newDeadline); getTaskCount(); } catch (DateTimeException exception) { @@ -59,6 +94,13 @@ public static void addDeadline(String deadline) { } } } + + /** + * Adds an Event object to the taskList. + * + * @param event a String specifying the description of the Event and + * the start and end time. + */ public static void addEvent(String event) { String[] details = event.split("/from"); if (details.length < 2) { @@ -72,8 +114,7 @@ public static void addEvent(String event) { LocalDateTime to = LocalDateTime.parse(details[1].split("/to")[1].trim(), formatter); Event newEvent = new Event(details[0], from, to); taskList.add(newEvent); - System.out.println("Noted! This task has been added:"); - System.out.println(newEvent); + Ui.taskAdded(newEvent); getTaskCount(); } catch (DateTimeException exception) { @@ -99,6 +140,15 @@ public static void unmarkTask(int taskIndex) { System.out.println("Roger that! This task is marked as not done: "); System.out.println(taskList.get(taskIndex - 1).toString()); } + + /** + * Determines, ignoring and trailing and leading whitespaces, if any of the + * Task descriptions contain the exact query substring. Prints + * the Task data of those that do and prints a message if none are + * found. + * + * @param line the query substring. + */ public static void findTask(String line) { String query = line.substring(4).trim(); ArrayList matchList = new ArrayList<>(); diff --git a/src/main/java/hina/helper/Ui.java b/src/main/java/hina/helper/Ui.java index 353b6b2f1..ba755e7cf 100644 --- a/src/main/java/hina/helper/Ui.java +++ b/src/main/java/hina/helper/Ui.java @@ -1,6 +1,14 @@ package hina.helper; +import hina.task.Task; + +/** + * Contains methods to print messages to the user. + */ public class Ui { + /** + * Class constructor. + */ public Ui() { } @@ -29,4 +37,23 @@ public static void taskNotFoundMessage() { public static void showDateTimeError() { System.out.println("Please use dd-MMM-yyyy HH:mm format!"); } + public static void emptyListMessage() { + System.out.println("There are no items on the list :o"); + } + public static void taskAdded(Task task) { + System.out.println("Noted! This task has been added:"); + System.out.println(task); + } + public static void saveFound() { + System.out.println("Saved list found, loading saved list..."); + } + public static void saveNotFound() { + System.out.println("Save file not found! Creating new file..."); + } + public static void saveCreated() { + System.out.println("Save file created!"); + } + public static void fileCreateError() { + System.out.println("T.T Ahh! Something went wrong, could not create file!"); + } } diff --git a/src/main/java/hina/task/Deadline.java b/src/main/java/hina/task/Deadline.java index e479fee79..0a347be81 100644 --- a/src/main/java/hina/task/Deadline.java +++ b/src/main/java/hina/task/Deadline.java @@ -3,15 +3,27 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +/** + * Represents a Task on a to-do list with a deadline. + */ public class Deadline extends Task { private LocalDateTime by; String byString; + + /** + * Class constructor specifying this Deadline's description and + * due date. + * + * @param description description of this Deadline. + * @param by LocalDateTime object specifying the due date. + */ public Deadline(String description, LocalDateTime by) { super(description); this.by = by; this.byString = this.by.format(DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm")); } + @Override public String toString() { String mark; if (super.isDone()) { @@ -22,6 +34,7 @@ public String toString() { return String.format("[D][%s] %s (by: %s)", mark, super.getDescription(), byString); } + @Override public String toSave() { return String.format("D / %s / %s / %s", isDone? "1" : "0", description, byString); } diff --git a/src/main/java/hina/task/Event.java b/src/main/java/hina/task/Event.java index 293b7aa34..ba8fca8ec 100644 --- a/src/main/java/hina/task/Event.java +++ b/src/main/java/hina/task/Event.java @@ -3,11 +3,23 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +/** + * Represents an event on a to-do list that has start and end dates and times. + */ public class Event extends Task { private LocalDateTime from; private String fromStr; private LocalDateTime to; private String toStr; + + /** + * Class constructor specifying this Event's description, start and end + * time. + * + * @param description description of this Event. + * @param from LocalDateTime object specifying the start time. + * @param to LocalDateTime object specifying the end time. + */ public Event(String description, LocalDateTime from, LocalDateTime to) { super(description); this.from = from; @@ -16,6 +28,7 @@ public Event(String description, LocalDateTime from, LocalDateTime to) { this.toStr = this.to.format(DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm")); } + @Override public String toString() { String mark; if (super.isDone()) { @@ -34,6 +47,7 @@ public String getToStr() { return toStr; } + @Override public String toSave() { return String.format("E / %s / %s / %s / %s", isDone? "1" : "0", description, fromStr, toStr); } diff --git a/src/main/java/hina/task/Task.java b/src/main/java/hina/task/Task.java index 5d19498d2..479603fcb 100644 --- a/src/main/java/hina/task/Task.java +++ b/src/main/java/hina/task/Task.java @@ -1,29 +1,65 @@ package hina.task; +/** + * Represents a task on a to-do list that can be set as done or undone. + * + */ public class Task { protected String description; protected boolean isDone; + + /** + * Returns done status of the Task. + * + * @return done status. + */ public boolean isDone() { return isDone; } + /** + * Sets the done status of the Task. + * + * @param done status to set the done status to. + */ public void setDone(boolean done) { isDone = done; } + /** + * Class constructor specifying this Task's description. + * + * @param description name of this Task. + */ public Task(String description) { this.description = description; isDone = false; } + /** + * Returns the description of this Task. + * + * @return description of this Task. + */ public String getDescription() { return description; } + /** + * Sets the description of this Task. + * + * @param description new description of this task. + */ public void setDescription(String description) { this.description = description; } + /** + * Returns a formatted string with the type, isDone status + * and description of this Task. + * + * @return the formatted string. + */ public String toString() { String mark; if (isDone) { @@ -34,6 +70,13 @@ public String toString() { return String.format("[T][%s] %s", mark, description); } + /** + * Returns a formatted string with the type, a number representing the isDone + * status ('0' for false, '1' for true), and description of the Task + * for saving to the hard disk. + * + * @return the formatted string. + */ public String toSave() { return String.format("T / %s / %s", isDone? "1" : "0", description); } From 5a621ecead36ac6f478458eac0718de747ebb3be Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Fri, 3 Mar 2023 14:48:34 +0800 Subject: [PATCH 17/19] Updated user guide, changed find method to print the index of matching Tasks in the TaskList --- docs/README.md | 169 ++++++++++++++++++++++-- src/main/java/hina/helper/TaskList.java | 17 +-- 2 files changed, 169 insertions(+), 17 deletions(-) diff --git a/docs/README.md b/docs/README.md index 8077118eb..20c60ecc4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,29 +1,180 @@ # User Guide +Welcome to the HinaBot User Guide! HinaBot is a personal assistant program that helps you +maintain a to-do list. + ## Features -### Feature-ABC +### Support for multiple task types + +HinaBot supports 3 different types of items on a to-do list: regular tasks, deadlines (tasks which have a due-date), +and events (which have a start and end date). + +### Search function -Description of the feature. +HinaBot allows you to search your to-do list for tasks that contain a particular substring, making it easier to keep +track of large numbers of tasks. -### Feature-XYZ +### Delete and mark functions -Description of the feature. +HinaBot allows you to mark tasks as done or not done and also supports deletion of a task. + +### Save and load function +All changes you make to your to-do list are stored locally, meaning you can pick up right where you left off. ## Usage -### `Keyword` - Describe action +### `todo` - Add a regular task to the to-do list -Describe the action and its outcome. +Adds a regular task (no due date) to the to-do list. By default, the task is set as not done. Example of usage: -`keyword (optional arguments)` +`todo buy milk` + +Expected outcome: + +The task is added to your to-do list and HinaBot announces how many tasks are currently on your list + +``` +Noted! This task has been added: +[T][ ] buy milk +There are 1 items on your list. +``` +### `deadline` - Add a deadline to the to-do list + +Adds a deadline (with a do-by date in dd-MMM-yyyy HH:mm format) to the to-do list. By default, the task is set as not done. + +Example of usage: + +`deadline Assignment 1 /by 04-Apr-2023 23:59` Expected outcome: -Description of the outcome. +The deadline is added to your to-do list and HinaBot announces how many tasks are currently on your list + +``` +Noted! This task has been added: +[D][ ] Assignment 1 (by: 04-Apr-2023 23:59) +There are 2 items on your list +``` +### `event` - Add an event to the to-do list + +Adds an event (with start and end times in dd-MMM-yyyy HH:mm format) to the to-do list. By default, the task is set as not done. + +Example of usage: + +`event Midterms /from 03-Mar-2023 13:00 /to 03-Mar-2023 17:30` + +Expected outcome: + +The deadline is added to your to-do list and HinaBot announces how many tasks are currently on your list + +``` +Noted! This task has been added: +[E][ ] Midterms (from: 03-Mar-2023 13:00 to: 03-Mar-2023 17:30) +There are 2 items on your list +``` +### `list` - Lists all tasks in the to-do list + +Prints a list of all tasks in the to-do list including the task type and done status. + +Example of usage: + +`list` + +Expected outcome: + +The deadline is added to your to-do list and HinaBot announces how many tasks are currently on your list + +``` +1. [T][ ] buy milk +2. [D][ ] Assignment 1 (by: 04-Apr-2023 23:59) +3. [E][ ] Midterms (from: 03-Mar-2023 13:00 to: 03-Mar-2023 17:30) +``` +### `mark` - Marks a task as done + +Marks an item by its index on the to-do list as done. This is indicated by an 'X' in the checkbox next to +its description. + +Example of usage: + +`mark 1` + +Expected outcome: +An acknowledgement message and an 'X' is printed in the checkbox next to item 1 on the to-do list. ``` -expected output +Roger that! This task is marked as done: +[T][X] buy milk ``` + +### `unmark` - Marks a task as not done + +Marks an item by its index on the to-do list as not done. This is indicated by a blank checkbox next to +its description. + +Example of usage: + +`unmark 1` + +Expected outcome: + +An acknowledgement message and a blank checkbox is printed next to item 1 on the to-do list. +``` +Roger that! This task is marked as not done: +[T][ ] buy milk +``` + +### `delete` - Remove a task from the to-do list + +Removes the item at the specified index from the to-do list. + +Example of usage: + +`delete 3` + +Expected outcome: + +An acknowledgement message and the description of the task being removed is shown, followed by an announcement +of the size of the remaining list. +``` +Got it! This task will be removed: +[E][ ] Midterms (from: 03-Mar-2023 13:00 to: 03-Mar-2023 17:30) +There are 2 items on your list. +``` + +### `find` - Search for a task + +Searches the to-do list for all tasks with a description containing the substring provided by the user. + +Example of usage: + +`find buy` + +Expected outcome: + +Any matching tasks, along with their index on the list, are printed. + +``` +Found a match! Here are the results master! +1. [T][ ] buy milk +``` + +### `bye` - Exits the program + +Terminates the program and prints a goodbye message. + +Example of usage: + +`bye` + +Expected outcome: + +The program exits with code 0 and a goodbye message is shown. + +``` +Goodbye master, let's meet again soon... + +Process finished with exit code 0 +``` \ No newline at end of file diff --git a/src/main/java/hina/helper/TaskList.java b/src/main/java/hina/helper/TaskList.java index f3a36435a..0806fc5df 100644 --- a/src/main/java/hina/helper/TaskList.java +++ b/src/main/java/hina/helper/TaskList.java @@ -151,19 +151,20 @@ public static void unmarkTask(int taskIndex) { */ public static void findTask(String line) { String query = line.substring(4).trim(); - ArrayList matchList = new ArrayList<>(); + boolean matchFound = false; + ArrayList matchList = new ArrayList<>(); for (Task task : taskList) { if (task.getDescription().contains(query)) { - matchList.add(task); + int i = taskList.indexOf(task); + String match = String.format("%d. %s", i + 1, task); + matchList.add(match); + matchFound = true; } } - if (!matchList.isEmpty()) { + if (matchFound) { Ui.taskFoundMessage(); - for (Task task : matchList) { - int i = matchList.indexOf(task); - System.out.print(i + 1); - System.out.print(". "); - System.out.println(task.toString()); + for (String task : matchList) { + System.out.println(task); } } else { Ui.taskNotFoundMessage(); From 29dcae7f9bbf6ec7a58f7bfeab4bf0d00eb827b0 Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Fri, 17 Mar 2023 17:56:12 +0800 Subject: [PATCH 18/19] Fix bugs involving invalid inputs for mark, unmark and delete methods --- src/main/java/hina/helper/Parser.java | 26 ++++++++++++++++--- src/main/java/hina/helper/Storage.java | 6 ++--- src/main/java/hina/helper/TaskList.java | 33 +++++++++++++++++-------- src/main/java/hina/helper/Ui.java | 3 +++ 4 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/main/java/hina/helper/Parser.java b/src/main/java/hina/helper/Parser.java index 26e7180f1..4f7c52dc7 100644 --- a/src/main/java/hina/helper/Parser.java +++ b/src/main/java/hina/helper/Parser.java @@ -26,11 +26,25 @@ public static void readCommand() throws HinaException { } else if (line.equalsIgnoreCase("list")) { TaskList.listTasks(); } else if (line.split(" ")[0].equalsIgnoreCase("mark")) { - int taskIndex = Integer.parseInt(line.split(" ")[1]); - TaskList.markTask(taskIndex); + try { + int taskIndex = Integer.parseInt(line.split(" ")[1]); + TaskList.markTask(taskIndex); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { + Ui.invalidNumberMessage(); + } + try { + Storage.writeToFile(); + } catch (IOException ioexception) { + Ui.couldNotSaveMessage(); + } } else if (line.split(" ")[0].equalsIgnoreCase("unmark")) { int taskIndex = Integer.parseInt(line.split(" ")[1]); TaskList.unmarkTask(taskIndex); + try { + Storage.writeToFile(); + } catch (IOException ioexception) { + Ui.couldNotSaveMessage(); + } } else if (line.split(" ")[0].equalsIgnoreCase("todo")) { TaskList.addTask(line.substring(5)); try { @@ -53,8 +67,12 @@ public static void readCommand() throws HinaException { Ui.couldNotSaveMessage(); } } else if (line.split(" ")[0].equalsIgnoreCase("delete")) { - int taskIndex = Integer.parseInt(line.split(" ")[1]); - TaskList.deleteTask(taskIndex); + try { + int taskIndex = Integer.parseInt(line.split(" ")[1]); + TaskList.deleteTask(taskIndex); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { + Ui.invalidNumberMessage(); + } try { Storage.writeToFile(); } catch (IOException ioexception) { diff --git a/src/main/java/hina/helper/Storage.java b/src/main/java/hina/helper/Storage.java index 23983cad3..ff1868b4c 100644 --- a/src/main/java/hina/helper/Storage.java +++ b/src/main/java/hina/helper/Storage.java @@ -42,14 +42,14 @@ public static ArrayList readSaveFile(String savePath) throws FileNotFoundE switch (taskDetails[0]) { case "T": Task savedTask = new Task(taskDetails[2]); - savedTask.setDone(!taskDetails[1].equals("0")); + savedTask.setDone(!taskDetails[1].contains("0")); savedList.add(savedTask); break; case "D": try { Deadline savedDeadline = new Deadline(taskDetails[2], LocalDateTime.parse(taskDetails[3], TaskList.formatter)); - savedDeadline.setDone(!taskDetails[1].equals("0")); + savedDeadline.setDone(!taskDetails[1].contains("0")); savedList.add(savedDeadline); } catch (DateTimeParseException e) { System.out.println(e.getMessage()); @@ -58,7 +58,7 @@ public static ArrayList readSaveFile(String savePath) throws FileNotFoundE case "E": Event savedEvent = new Event(taskDetails[2], LocalDateTime.parse(taskDetails[3], TaskList.formatter), LocalDateTime.parse(taskDetails[4], TaskList.formatter)); - savedEvent.setDone(!taskDetails[1].equals("0")); + savedEvent.setDone(!taskDetails[1].contains("0")); savedList.add(savedEvent); break; } diff --git a/src/main/java/hina/helper/TaskList.java b/src/main/java/hina/helper/TaskList.java index 0806fc5df..e6ff96180 100644 --- a/src/main/java/hina/helper/TaskList.java +++ b/src/main/java/hina/helper/TaskList.java @@ -125,20 +125,33 @@ public static void addEvent(String event) { } } public static void deleteTask(int taskIndex) { - System.out.println("Got it! This task will be removed:"); - System.out.println(taskList.get(taskIndex - 1).toString()); - taskList.remove(taskIndex - 1); - getTaskCount(); + try { + Task toDelete = taskList.get(taskIndex - 1); + System.out.println("Got it! This task will be removed:"); + System.out.println(toDelete); + taskList.remove(taskIndex - 1); + getTaskCount(); + } catch (IndexOutOfBoundsException e) { + Ui.invalidNumberMessage(); + } } public static void markTask(int taskIndex) { - taskList.get(taskIndex - 1).setDone(true); - System.out.println("Roger that! This task is marked as done: "); - System.out.println(taskList.get(taskIndex - 1).toString()); + try { + taskList.get(taskIndex - 1).setDone(true); + System.out.println("Roger that! This task is marked as done: "); + System.out.println(taskList.get(taskIndex - 1).toString()); + } catch (IndexOutOfBoundsException e) { + Ui.invalidNumberMessage(); + } } public static void unmarkTask(int taskIndex) { - taskList.get(taskIndex - 1).setDone(false); - System.out.println("Roger that! This task is marked as not done: "); - System.out.println(taskList.get(taskIndex - 1).toString()); + try { + taskList.get(taskIndex - 1).setDone(false); + System.out.println("Roger that! This task is marked as not done: "); + System.out.println(taskList.get(taskIndex - 1).toString()); + } catch (IndexOutOfBoundsException e) { + Ui.invalidNumberMessage(); + } } /** diff --git a/src/main/java/hina/helper/Ui.java b/src/main/java/hina/helper/Ui.java index ba755e7cf..d6264a961 100644 --- a/src/main/java/hina/helper/Ui.java +++ b/src/main/java/hina/helper/Ui.java @@ -56,4 +56,7 @@ public static void saveCreated() { public static void fileCreateError() { System.out.println("T.T Ahh! Something went wrong, could not create file!"); } + public static void invalidNumberMessage() { + System.out.println("That's not a valid number!"); + } } From d20746113b5032165f93d5d599fc4f9769ed9b22 Mon Sep 17 00:00:00 2001 From: waiter-palypoo Date: Fri, 17 Mar 2023 18:09:35 +0800 Subject: [PATCH 19/19] Build jar file --- src/main/java/META-INF/MANIFEST.MF | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/main/java/META-INF/MANIFEST.MF diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 000000000..d83708e47 --- /dev/null +++ b/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: hina.HinaBot +