From 070e1ef589603a272c77bf1bd4ba414298591609 Mon Sep 17 00:00:00 2001 From: Geinzit Date: Thu, 1 Feb 2024 20:54:31 +0800 Subject: [PATCH 01/19] Add Level-0 Increment: Rename, Greet, Exit. --- src/main/java/Duke.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 5d313334c..86de1de0b 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,10 +1,7 @@ public class Duke { public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); + String botName = "Huan"; + System.out.println("Hello! I'm " + botName + ", a chat bot"); + System.out.println("Bye! See ya!"); } } From 708a5848d14a27989ecfd80b8c7424728a70ef9f Mon Sep 17 00:00:00 2001 From: Geinzit Date: Fri, 2 Feb 2024 17:15:59 +0800 Subject: [PATCH 02/19] Add feature: bot echoes all input commands, exits when received 'bye' command --- src/main/java/Duke.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 86de1de0b..d77deba0d 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,7 +1,20 @@ +import java.util.Scanner; public class Duke { public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + String botName = "Huan"; System.out.println("Hello! I'm " + botName + ", a chat bot"); - System.out.println("Bye! See ya!"); + while(true) { + System.out.println("-------------------------"); + String userInput = scanner.nextLine(); + + if(userInput.equalsIgnoreCase("bye")) { + System.out.println("Bye! See ya!"); + break; + } + + System.out.println(userInput); + } } } From 19f083fa5d6f1ed7e8926bdda56681dfe8d41c53 Mon Sep 17 00:00:00 2001 From: Geinzit Date: Thu, 8 Feb 2024 13:23:28 +0800 Subject: [PATCH 03/19] Add feature to store past commands and list stored commands --- src/main/java/Duke.java | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index d77deba0d..9b6ee96e4 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,5 +1,21 @@ import java.util.Scanner; +import java.util.ArrayList; +import java.util.List; public class Duke { + private static List commandHistory = new ArrayList<>(); + + public static void storeCommand(String command) { + commandHistory.add(command); + } + + public static void printHistory() { + int cnt = 0; + for (String command: commandHistory) { + cnt += 1; + System.out.printf(cnt + ". " + command + "%n"); + } + } + public static void main(String[] args) { Scanner scanner = new Scanner(System.in); @@ -9,12 +25,15 @@ public static void main(String[] args) { System.out.println("-------------------------"); String userInput = scanner.nextLine(); - if(userInput.equalsIgnoreCase("bye")) { + if (userInput.equalsIgnoreCase("bye")) { System.out.println("Bye! See ya!"); break; + } else if (userInput.equalsIgnoreCase("list")) { + printHistory(); + } else { + storeCommand(userInput); + System.out.println("added: " + userInput); } - - System.out.println(userInput); } } } From d23eea281f3b57be5b7f0531186b6553c534aacd Mon Sep 17 00:00:00 2001 From: Geinzit Date: Thu, 8 Feb 2024 15:18:09 +0800 Subject: [PATCH 04/19] Add separate class for tasks. Improve variable naming. Check code to comply with coding standard. --- src/main/java/Duke.java | 72 ++++++++++++++++++++++++++++++----------- src/main/java/Task.java | 33 +++++++++++++++++++ 2 files changed, 87 insertions(+), 18 deletions(-) create mode 100644 src/main/java/Task.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 9b6ee96e4..142458972 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -2,38 +2,74 @@ import java.util.ArrayList; import java.util.List; public class Duke { - private static List commandHistory = new ArrayList<>(); + private static List tasks = new ArrayList<>(); - public static void storeCommand(String command) { - commandHistory.add(command); + public static Boolean isIndexValid(int index) { + return index >= 1 && index <= tasks.size(); + } + public static void addTask(String taskName) { + Task newTask = new Task(taskName, false); + tasks.add(newTask); + System.out.println("Added task with name: " + taskName); } - public static void printHistory() { + public static void listTasks() { int cnt = 0; - for (String command: commandHistory) { + for (Task task : tasks) { cnt += 1; - System.out.printf(cnt + ". " + command + "%n"); + System.out.printf(cnt + ". "); + task.printTask(); } } + public static void readProcessCommand() { - public static void main(String[] args) { Scanner scanner = new Scanner(System.in); - - String botName = "Huan"; - System.out.println("Hello! I'm " + botName + ", a chat bot"); while(true) { System.out.println("-------------------------"); - String userInput = scanner.nextLine(); - - if (userInput.equalsIgnoreCase("bye")) { + String inputCommand = scanner.nextLine(); + String[] words = inputCommand.split(" "); + String firstWord = words[0]; + switch (firstWord) { + case ("bye"): System.out.println("Bye! See ya!"); + return; + case ("list"): + listTasks(); + break; + case ("mark"): + int markIndex = Integer.parseInt(words[1]); + if (!isIndexValid(markIndex)) { + System.out.println("Invalid task index!"); + } + else { + tasks.get(markIndex - 1).setIsDone(true); + System.out.println("Set task number " + markIndex + ": " + tasks.get(markIndex - 1).getName() + " as done."); + } + break; + case ("unmark"): + int unmarkIndex = Integer.parseInt(words[1]); + if (!isIndexValid(unmarkIndex)) { + System.out.println("Invalid task index!"); + } + else { + tasks.get(unmarkIndex - 1).setIsDone(false); + System.out.println("Set task number " + unmarkIndex + ": " + tasks.get(unmarkIndex - 1).getName() + " as not done."); + } + break; + default: + addTask(inputCommand); break; - } else if (userInput.equalsIgnoreCase("list")) { - printHistory(); - } else { - storeCommand(userInput); - System.out.println("added: " + userInput); } + + + } } + + public static void main(String[] args) { + String botName = "Huan"; + System.out.println("Hello! I'm " + botName + ", a chat bot"); + + readProcessCommand(); + } } diff --git a/src/main/java/Task.java b/src/main/java/Task.java new file mode 100644 index 000000000..a6b385ef9 --- /dev/null +++ b/src/main/java/Task.java @@ -0,0 +1,33 @@ +public class Task { + private String name; + private Boolean isDone; + + public void setName(String name) { + this.name = name; + } + + public void setIsDone(Boolean isDone) { + this.isDone = isDone; + } + + public String getName() { + return name; + } + + public Boolean getIsDone() { + return isDone; + } + + public void printTask() { + System.out.println("[" + (isDone ? "X" : " ") + "] " + name); + } + public Task() { + setName("task"); + setIsDone(false); + } + + public Task(String name, Boolean isDone) { + setName(name); + setIsDone(isDone); + } +} From ddc34765277a9697d5d53530a54e29c1e2766039 Mon Sep 17 00:00:00 2001 From: Geinzit Date: Thu, 8 Feb 2024 18:22:20 +0800 Subject: [PATCH 05/19] Add 3 new types of Task class using inheritance. --- src/main/java/DeadlineTask.java | 48 +++++++++++++++++++++++++ src/main/java/Duke.java | 56 ++++++++++++++++++++++++----- src/main/java/EventTask.java | 63 +++++++++++++++++++++++++++++++++ src/main/java/Task.java | 17 +++++++++ src/main/java/TodoTask.java | 9 +++++ 5 files changed, 184 insertions(+), 9 deletions(-) create mode 100644 src/main/java/DeadlineTask.java create mode 100644 src/main/java/EventTask.java create mode 100644 src/main/java/TodoTask.java diff --git a/src/main/java/DeadlineTask.java b/src/main/java/DeadlineTask.java new file mode 100644 index 000000000..3367dbaec --- /dev/null +++ b/src/main/java/DeadlineTask.java @@ -0,0 +1,48 @@ +import java.util.Objects; + +public class DeadlineTask extends Task{ + private String ddlTime; + public DeadlineTask(String nameWithDate, Boolean isDone) { + StringBuilder ddlTime = new StringBuilder(); + StringBuilder name = new StringBuilder(); + String[] words = nameWithDate.split(" "); + /* + state: + 0 means currently concatenating name + 1 means currently concatenating ddlTime + */ + int state = 0; + for(String word : words) { + if (Objects.equals(word, "/by")) { + state += 1; + } + else { + switch (state) { + case (0): + name.append((name.length() == 0) ? "" : " ").append(word); + break; + case (1): + ddlTime.append((ddlTime.length() == 0 ? "" : " ")).append(word); + break; + } + } + } + setName(name.toString()); + setIsDone(isDone); + setTaskType(3); + this.ddlTime = ddlTime.toString(); + } + + public void printTask() { + System.out.println("[D][" + (getIsDone() ? "X" : " ") + "] " + getName() + " (by: " + ddlTime + ")"); + } + + public String getDdlTime() { + return ddlTime; + } + + public void setDdlTime(String ddlTime) { + this.ddlTime = ddlTime; + } + +} diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 142458972..15adf63d5 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -7,18 +7,34 @@ public class Duke { public static Boolean isIndexValid(int index) { return index >= 1 && index <= tasks.size(); } - public static void addTask(String taskName) { - Task newTask = new Task(taskName, false); + public static void addTask(Task newTask) { tasks.add(newTask); - System.out.println("Added task with name: " + taskName); } public static void listTasks() { int cnt = 0; + System.out.println("You have a total of " + tasks.size() + " tasks."); for (Task task : tasks) { cnt += 1; System.out.printf(cnt + ". "); - task.printTask(); + + switch (task.getTaskType()) { + case (1): + TodoTask todoTask = (TodoTask)task; + todoTask.printTask(); + break; + case (2): + EventTask eventTask = (EventTask)task; + eventTask.printTask(); + break; + case (3): + DeadlineTask deadlineTask = (DeadlineTask)task; + deadlineTask.printTask(); + break; + default: + task.printTask(); + break; + } } } public static void readProcessCommand() { @@ -29,6 +45,13 @@ public static void readProcessCommand() { String inputCommand = scanner.nextLine(); String[] words = inputCommand.split(" "); String firstWord = words[0]; + String suffixWord; + if(words.length > 1) { + suffixWord = inputCommand.substring(words[0].length() + 1); + } + else { + suffixWord = ""; + } switch (firstWord) { case ("bye"): System.out.println("Bye! See ya!"); @@ -37,7 +60,7 @@ public static void readProcessCommand() { listTasks(); break; case ("mark"): - int markIndex = Integer.parseInt(words[1]); + int markIndex = Integer.parseInt(suffixWord); if (!isIndexValid(markIndex)) { System.out.println("Invalid task index!"); } @@ -47,7 +70,7 @@ public static void readProcessCommand() { } break; case ("unmark"): - int unmarkIndex = Integer.parseInt(words[1]); + int unmarkIndex = Integer.parseInt(suffixWord); if (!isIndexValid(unmarkIndex)) { System.out.println("Invalid task index!"); } @@ -56,13 +79,28 @@ public static void readProcessCommand() { System.out.println("Set task number " + unmarkIndex + ": " + tasks.get(unmarkIndex - 1).getName() + " as not done."); } break; + case ("todo"): + TodoTask todoTask = new TodoTask(suffixWord, false); + addTask(todoTask); + System.out.println("Added todo type task with name: " + todoTask.getName()); + break; + case ("event"): + EventTask eventTask = new EventTask(suffixWord, false); + addTask(eventTask); + System.out.println("Added event type task with name: " + eventTask.getName()); + break; + case ("deadline"): + DeadlineTask deadlineTask = new DeadlineTask(suffixWord, false); + addTask(deadlineTask); + System.out.println("Added deadline type task with name: " + deadlineTask.getName()); + break; default: - addTask(inputCommand); + Task task = new Task(inputCommand, false); + addTask(task); + System.out.println("Added task with name: " + task.getName()); break; } - - } } diff --git a/src/main/java/EventTask.java b/src/main/java/EventTask.java new file mode 100644 index 000000000..1f5d2de12 --- /dev/null +++ b/src/main/java/EventTask.java @@ -0,0 +1,63 @@ +import java.util.Objects; + +public class EventTask extends Task{ + private String startTime, endTime; + public EventTask(String nameWithDates, Boolean isDone) { + StringBuilder startTime = new StringBuilder(); + StringBuilder endTime = new StringBuilder(); + StringBuilder name = new StringBuilder(); + String[] words = nameWithDates.split(" "); + /* + state: + 0 means currently concatenating name + 1 means currently concatenating startTime + 2 means currently concatenating endTime + */ + int state = 0; + for(String word : words) { + if (Objects.equals(word, "/from")) { + state += 1; + } + else if (Objects.equals(word, "/to")) { + state += 1; + } + else { + switch (state) { + case (0): + name.append((name.length() == 0) ? "" : " ").append(word); + break; + case (1): + startTime.append((startTime.length() == 0 ? "" : " ")).append(word); + break; + case (2): + endTime.append((endTime.length() == 0 ? "" : " ")).append(word); + break; + } + } + } + setName(name.toString()); + setIsDone(isDone); + setTaskType(2); + this.startTime = startTime.toString(); + this.endTime = endTime.toString(); + } + public void printTask() { + System.out.println("[E][" + (getIsDone() ? "X" : " ") + "] " + getName() + " (from: " + startTime + " to: " + endTime + ")"); + } + + public void setStartTime(String startTime) { + this.startTime = startTime; + } + + public String getStartTime() { + return startTime; + } + + public void setEndTime(String endTime) { + this.endTime = endTime; + } + + public String getEndTime() { + return endTime; + } +} diff --git a/src/main/java/Task.java b/src/main/java/Task.java index a6b385ef9..8798b8855 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -1,6 +1,14 @@ public class Task { private String name; private Boolean isDone; + /** + * used for casting back types + * 0 for no specific types + * 1 for Todo types + * 2 for Event types + * 3 for Deadline types + */ + private int taskType; public void setName(String name) { this.name = name; @@ -10,6 +18,10 @@ public void setIsDone(Boolean isDone) { this.isDone = isDone; } + public void setTaskType(int taskType) { + this.taskType = taskType; + } + public String getName() { return name; } @@ -18,12 +30,17 @@ public Boolean getIsDone() { return isDone; } + public int getTaskType() { + return taskType; + } + public void printTask() { System.out.println("[" + (isDone ? "X" : " ") + "] " + name); } public Task() { setName("task"); setIsDone(false); + taskType = 0; } public Task(String name, Boolean isDone) { diff --git a/src/main/java/TodoTask.java b/src/main/java/TodoTask.java new file mode 100644 index 000000000..264e3a958 --- /dev/null +++ b/src/main/java/TodoTask.java @@ -0,0 +1,9 @@ +public class TodoTask extends Task{ + public TodoTask(String name, Boolean isDone) { + super(name, isDone); + setTaskType(1); + } + public void printTask() { + System.out.println("[T][" + (getIsDone() ? "X" : " ") + "] " + getName()); + } +} From ce45d70529cf02c575ff030b07f1b1f9d5c7e73d Mon Sep 17 00:00:00 2001 From: Geinzit Date: Wed, 14 Feb 2024 19:44:16 +0800 Subject: [PATCH 06/19] Add input file and expected result file for IO redirection testing --- text-ui-test/EXPECTED.TXT | 31 ++++++++++++++++++++++++------- text-ui-test/input.txt | 9 +++++++++ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 657e74f6e..8c8cd4202 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,7 +1,24 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| - +Hello! I'm Huan, a chat bot +------------------------- +Added todo type task with name: read book +------------------------- +Added deadline type task with name: return book +------------------------- +Added event type task with name: project meeting +------------------------- +Set task number 1: read book as done. +------------------------- +Added todo type task with name: join sports club +------------------------- +Added todo type task with name: borrow book +------------------------- +Set task number 4: join sports club as done. +------------------------- +You have a total of 5 tasks. +1. [T][X] read book +2. [D][ ] return book (by: June 6th) +3. [E][ ] project meeting (from: Aug 6th 2pm to: 4pm) +4. [T][X] join sports club +5. [T][ ] borrow book +------------------------- +Bye! See ya! diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e69de29bb..13601e3f9 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -0,0 +1,9 @@ +todo read book +deadline return book /by June 6th +event project meeting /from Aug 6th 2pm /to 4pm +mark 1 +todo join sports club +todo borrow book +mark 4 +list +bye From fb1d2b4a87f8b7928b6e9479029a5811318264de Mon Sep 17 00:00:00 2001 From: Geinzit Date: Sun, 18 Feb 2024 20:37:38 +0800 Subject: [PATCH 07/19] Add input error detection and response for all current commands. --- src/main/java/DeadlineTask.java | 5 ++- src/main/java/Duke.java | 71 ++++++++++++++++++++++----------- src/main/java/EventTask.java | 5 ++- 3 files changed, 56 insertions(+), 25 deletions(-) diff --git a/src/main/java/DeadlineTask.java b/src/main/java/DeadlineTask.java index 3367dbaec..0c948ca86 100644 --- a/src/main/java/DeadlineTask.java +++ b/src/main/java/DeadlineTask.java @@ -2,7 +2,7 @@ public class DeadlineTask extends Task{ private String ddlTime; - public DeadlineTask(String nameWithDate, Boolean isDone) { + public DeadlineTask(String nameWithDate, Boolean isDone) throws Exception{ StringBuilder ddlTime = new StringBuilder(); StringBuilder name = new StringBuilder(); String[] words = nameWithDate.split(" "); @@ -27,6 +27,9 @@ public DeadlineTask(String nameWithDate, Boolean isDone) { } } } + if(state != 1 || name.toString().isEmpty() || isDone.toString().isEmpty()) { + throw new Exception(); + } setName(name.toString()); setIsDone(isDone); setTaskType(3); diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 15adf63d5..b9c734176 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -54,50 +54,75 @@ public static void readProcessCommand() { } switch (firstWord) { case ("bye"): + if(!suffixWord.isEmpty()) { + System.out.println("Invalid format! Should be 'bye'"); + break; + } System.out.println("Bye! See ya!"); return; case ("list"): + if(!suffixWord.isEmpty()) { + System.out.println("Invalid format! Should be 'list'."); + break; + } listTasks(); break; case ("mark"): - int markIndex = Integer.parseInt(suffixWord); - if (!isIndexValid(markIndex)) { - System.out.println("Invalid task index!"); - } - else { - tasks.get(markIndex - 1).setIsDone(true); - System.out.println("Set task number " + markIndex + ": " + tasks.get(markIndex - 1).getName() + " as done."); + try { + int markIndex = Integer.parseInt(suffixWord); + if (!isIndexValid(markIndex)) { + System.out.println("Invalid task index!"); + } else { + tasks.get(markIndex - 1).setIsDone(true); + System.out.println("Set task number " + markIndex + ": " + tasks.get(markIndex - 1).getName() + " as done."); + } + } catch (Exception e){ + System.out.println("Incorrect format! Should be 'mark *n', where n is the index of the task you wish to mark as finished."); } break; case ("unmark"): - int unmarkIndex = Integer.parseInt(suffixWord); - if (!isIndexValid(unmarkIndex)) { - System.out.println("Invalid task index!"); - } - else { - tasks.get(unmarkIndex - 1).setIsDone(false); - System.out.println("Set task number " + unmarkIndex + ": " + tasks.get(unmarkIndex - 1).getName() + " as not done."); + try { + int unmarkIndex = Integer.parseInt(suffixWord); + if (!isIndexValid(unmarkIndex)) { + System.out.println("Invalid task index!"); + } else { + tasks.get(unmarkIndex - 1).setIsDone(false); + System.out.println("Set task number " + unmarkIndex + ": " + tasks.get(unmarkIndex - 1).getName() + " as not done."); + } + } catch (Exception e){ + System.out.println("Incorrect format! Should be 'unmark *n', where n is the index of the task you wish to mark as unfinished."); } break; case ("todo"): + if(suffixWord.isEmpty()) { + System.out.println("Incorrect format! Should be 'todo *task_name'."); + break; + } TodoTask todoTask = new TodoTask(suffixWord, false); addTask(todoTask); System.out.println("Added todo type task with name: " + todoTask.getName()); break; case ("event"): - EventTask eventTask = new EventTask(suffixWord, false); - addTask(eventTask); - System.out.println("Added event type task with name: " + eventTask.getName()); + try { + EventTask eventTask = new EventTask(suffixWord, false); + addTask(eventTask); + System.out.println("Added event type task with name: " + eventTask.getName()); + } catch (Exception e) { + System.out.println("Incorrect format! Should be 'event *event_name /from *start_time /to *end_time'."); + } break; case ("deadline"): - DeadlineTask deadlineTask = new DeadlineTask(suffixWord, false); - addTask(deadlineTask); - System.out.println("Added deadline type task with name: " + deadlineTask.getName()); + try { + DeadlineTask deadlineTask = new DeadlineTask(suffixWord, false); + addTask(deadlineTask); + System.out.println("Added deadline type task with name: " + deadlineTask.getName()); + } catch (Exception e) { + System.out.println("Incorrect format! Should be 'deadline *task_name /by *deadline_time'"); + } break; + default: - Task task = new Task(inputCommand, false); - addTask(task); - System.out.println("Added task with name: " + task.getName()); + System.out.println("Unrecognized command, please try again!"); break; } diff --git a/src/main/java/EventTask.java b/src/main/java/EventTask.java index 1f5d2de12..0137f793c 100644 --- a/src/main/java/EventTask.java +++ b/src/main/java/EventTask.java @@ -2,7 +2,7 @@ public class EventTask extends Task{ private String startTime, endTime; - public EventTask(String nameWithDates, Boolean isDone) { + public EventTask(String nameWithDates, Boolean isDone) throws Exception { StringBuilder startTime = new StringBuilder(); StringBuilder endTime = new StringBuilder(); StringBuilder name = new StringBuilder(); @@ -35,6 +35,9 @@ else if (Objects.equals(word, "/to")) { } } } + if(state != 2 || name.toString().isEmpty() || startTime.toString().isEmpty() || endTime.toString().isEmpty()) { + throw new Exception(); + } setName(name.toString()); setIsDone(isDone); setTaskType(2); From dc155ec2771f4517bacc5d988ce8d61952ecf25b Mon Sep 17 00:00:00 2001 From: Geinzit Date: Sun, 18 Feb 2024 21:02:25 +0800 Subject: [PATCH 08/19] Organize classes into separate packages. Rename files to match the bot's name. --- src/main/java/{Duke.java => huan/main/Huan.java} | 6 +++++- src/main/java/{ => huan/task}/DeadlineTask.java | 2 ++ src/main/java/{ => huan/task}/EventTask.java | 2 ++ src/main/java/{ => huan/task}/Task.java | 1 + src/main/java/{ => huan/task}/TodoTask.java | 2 ++ 5 files changed, 12 insertions(+), 1 deletion(-) rename src/main/java/{Duke.java => huan/main/Huan.java} (98%) rename src/main/java/{ => huan/task}/DeadlineTask.java (98%) rename src/main/java/{ => huan/task}/EventTask.java (99%) rename src/main/java/{ => huan/task}/Task.java (98%) rename src/main/java/{ => huan/task}/TodoTask.java (93%) diff --git a/src/main/java/Duke.java b/src/main/java/huan/main/Huan.java similarity index 98% rename from src/main/java/Duke.java rename to src/main/java/huan/main/Huan.java index b9c734176..526c792c8 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/huan/main/Huan.java @@ -1,7 +1,11 @@ +package huan.main; + +import huan.task.*; + import java.util.Scanner; import java.util.ArrayList; import java.util.List; -public class Duke { +public class Huan { private static List tasks = new ArrayList<>(); public static Boolean isIndexValid(int index) { diff --git a/src/main/java/DeadlineTask.java b/src/main/java/huan/task/DeadlineTask.java similarity index 98% rename from src/main/java/DeadlineTask.java rename to src/main/java/huan/task/DeadlineTask.java index 0c948ca86..a8e3667c8 100644 --- a/src/main/java/DeadlineTask.java +++ b/src/main/java/huan/task/DeadlineTask.java @@ -1,3 +1,5 @@ +package huan.task; + import java.util.Objects; public class DeadlineTask extends Task{ diff --git a/src/main/java/EventTask.java b/src/main/java/huan/task/EventTask.java similarity index 99% rename from src/main/java/EventTask.java rename to src/main/java/huan/task/EventTask.java index 0137f793c..d321e9520 100644 --- a/src/main/java/EventTask.java +++ b/src/main/java/huan/task/EventTask.java @@ -1,3 +1,5 @@ +package huan.task; + import java.util.Objects; public class EventTask extends Task{ diff --git a/src/main/java/Task.java b/src/main/java/huan/task/Task.java similarity index 98% rename from src/main/java/Task.java rename to src/main/java/huan/task/Task.java index 8798b8855..f65583c8d 100644 --- a/src/main/java/Task.java +++ b/src/main/java/huan/task/Task.java @@ -1,3 +1,4 @@ +package huan.task; public class Task { private String name; private Boolean isDone; diff --git a/src/main/java/TodoTask.java b/src/main/java/huan/task/TodoTask.java similarity index 93% rename from src/main/java/TodoTask.java rename to src/main/java/huan/task/TodoTask.java index 264e3a958..46c9f8e9f 100644 --- a/src/main/java/TodoTask.java +++ b/src/main/java/huan/task/TodoTask.java @@ -1,3 +1,5 @@ +package huan.task; + public class TodoTask extends Task{ public TodoTask(String name, Boolean isDone) { super(name, isDone); From 5bba707bfa052c445d89d6b74739963da2c74c1a Mon Sep 17 00:00:00 2001 From: Geinzit Date: Thu, 22 Feb 2024 01:49:08 +0800 Subject: [PATCH 09/19] Add delete task via index feature. --- src/main/java/huan/main/Huan.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/huan/main/Huan.java b/src/main/java/huan/main/Huan.java index 526c792c8..9d6065802 100644 --- a/src/main/java/huan/main/Huan.java +++ b/src/main/java/huan/main/Huan.java @@ -124,7 +124,21 @@ public static void readProcessCommand() { System.out.println("Incorrect format! Should be 'deadline *task_name /by *deadline_time'"); } break; + case ("delete"): + try { + int deleteIndex = Integer.parseInt(suffixWord); + if (!isIndexValid(deleteIndex)) { + System.out.println("Invalid task index!"); + } else { + tasks.get(deleteIndex - 1).setIsDone(true); + System.out.println("Removed task number " + deleteIndex + ": " + tasks.get(deleteIndex - 1).getName()); + tasks.remove(deleteIndex - 1); + } + } catch (Exception e){ + System.out.println("Incorrect format! Should be 'delete *n', where n is the index of the task you wish to delete."); + } + break; default: System.out.println("Unrecognized command, please try again!"); break; From a8a99b1d399c6a0ec514c59deb8bc3beb6ccb240 Mon Sep 17 00:00:00 2001 From: Geinzit Date: Thu, 22 Feb 2024 03:00:34 +0800 Subject: [PATCH 10/19] Add task save and load to hard drive function. --- src/main/java/huan/main/Huan.java | 66 ++++++++++++++++++++++- src/main/java/huan/task/DeadlineTask.java | 5 ++ src/main/java/huan/task/EventTask.java | 5 ++ src/main/java/huan/task/Task.java | 5 ++ src/main/java/huan/task/TodoTask.java | 7 +++ 5 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/main/java/huan/main/Huan.java b/src/main/java/huan/main/Huan.java index 526c792c8..2f95f140c 100644 --- a/src/main/java/huan/main/Huan.java +++ b/src/main/java/huan/main/Huan.java @@ -5,9 +5,15 @@ import java.util.Scanner; import java.util.ArrayList; import java.util.List; +import java.io.IOException; +import java.io.FileReader; +import java.io.BufferedReader; +import java.io.FileWriter; +import java.io.BufferedWriter; public class Huan { private static List tasks = new ArrayList<>(); + private static String taskFile = "tasklist.txt"; public static Boolean isIndexValid(int index) { return index >= 1 && index <= tasks.size(); } @@ -41,7 +47,44 @@ public static void listTasks() { } } } - public static void readProcessCommand() { + + public static void writeTasks() { + try { + BufferedWriter writer = new BufferedWriter(new FileWriter(taskFile)); + for (Task task : tasks) { + writer.write(task.writeLine()); + writer.newLine(); + } + writer.flush(); + }catch (IOException e) { + e.printStackTrace(); + } + } + + public static void processLine(String line) throws Exception{ + String[] words = line.split(" "); + String suffixWord = line.substring(words[0].length() + 1); + + if (words[0].length() != 2 || (words[0].charAt(1) != 'T' && words[0].charAt(1) != 'F')) { + throw new Exception(); + } + + switch (words[0].charAt(0)) { + case ('T'): + addTask(new TodoTask(suffixWord, words[0].charAt(1) == 'T')); + break; + case ('D'): + addTask(new DeadlineTask(suffixWord, words[0].charAt(1) == 'T')); + break; + case ('E'): + addTask(new EventTask(suffixWord, words[0].charAt(1) == 'T')); + break; + default: + throw new Exception(); + } + } + + public static void readProcessCommands() { Scanner scanner = new Scanner(System.in); while(true) { @@ -79,6 +122,7 @@ public static void readProcessCommand() { } else { tasks.get(markIndex - 1).setIsDone(true); System.out.println("Set task number " + markIndex + ": " + tasks.get(markIndex - 1).getName() + " as done."); + writeTasks(); } } catch (Exception e){ System.out.println("Incorrect format! Should be 'mark *n', where n is the index of the task you wish to mark as finished."); @@ -92,6 +136,7 @@ public static void readProcessCommand() { } else { tasks.get(unmarkIndex - 1).setIsDone(false); System.out.println("Set task number " + unmarkIndex + ": " + tasks.get(unmarkIndex - 1).getName() + " as not done."); + writeTasks(); } } catch (Exception e){ System.out.println("Incorrect format! Should be 'unmark *n', where n is the index of the task you wish to mark as unfinished."); @@ -105,12 +150,14 @@ public static void readProcessCommand() { TodoTask todoTask = new TodoTask(suffixWord, false); addTask(todoTask); System.out.println("Added todo type task with name: " + todoTask.getName()); + writeTasks(); break; case ("event"): try { EventTask eventTask = new EventTask(suffixWord, false); addTask(eventTask); System.out.println("Added event type task with name: " + eventTask.getName()); + writeTasks(); } catch (Exception e) { System.out.println("Incorrect format! Should be 'event *event_name /from *start_time /to *end_time'."); } @@ -120,6 +167,7 @@ public static void readProcessCommand() { DeadlineTask deadlineTask = new DeadlineTask(suffixWord, false); addTask(deadlineTask); System.out.println("Added deadline type task with name: " + deadlineTask.getName()); + writeTasks(); } catch (Exception e) { System.out.println("Incorrect format! Should be 'deadline *task_name /by *deadline_time'"); } @@ -137,6 +185,20 @@ public static void main(String[] args) { String botName = "Huan"; System.out.println("Hello! I'm " + botName + ", a chat bot"); - readProcessCommand(); + try (BufferedReader reader= new BufferedReader(new FileReader(taskFile))){ + String line; + try { + while ((line = reader.readLine()) != null) { + processLine(line); + } + } catch (Exception e) { + System.out.println("Corrupt task save file"); + tasks.clear(); + } + + } catch (IOException e) { + tasks.clear(); + } + readProcessCommands(); } } diff --git a/src/main/java/huan/task/DeadlineTask.java b/src/main/java/huan/task/DeadlineTask.java index a8e3667c8..f8da07600 100644 --- a/src/main/java/huan/task/DeadlineTask.java +++ b/src/main/java/huan/task/DeadlineTask.java @@ -38,10 +38,15 @@ public DeadlineTask(String nameWithDate, Boolean isDone) throws Exception{ this.ddlTime = ddlTime.toString(); } + @Override public void printTask() { System.out.println("[D][" + (getIsDone() ? "X" : " ") + "] " + getName() + " (by: " + ddlTime + ")"); } + @Override + public String writeLine() { + return "D" + (getIsDone() ? "T" : "F") + " " + getName() + " /by " + ddlTime; + } public String getDdlTime() { return ddlTime; } diff --git a/src/main/java/huan/task/EventTask.java b/src/main/java/huan/task/EventTask.java index d321e9520..eac86ca08 100644 --- a/src/main/java/huan/task/EventTask.java +++ b/src/main/java/huan/task/EventTask.java @@ -50,6 +50,11 @@ public void printTask() { System.out.println("[E][" + (getIsDone() ? "X" : " ") + "] " + getName() + " (from: " + startTime + " to: " + endTime + ")"); } + @Override + public String writeLine() { + return "E" + (getIsDone() ? "T" : "F") + " " + getName() + " /from " + startTime + " /to " + endTime; + } + public void setStartTime(String startTime) { this.startTime = startTime; } diff --git a/src/main/java/huan/task/Task.java b/src/main/java/huan/task/Task.java index f65583c8d..48d39fa30 100644 --- a/src/main/java/huan/task/Task.java +++ b/src/main/java/huan/task/Task.java @@ -38,6 +38,11 @@ public int getTaskType() { public void printTask() { System.out.println("[" + (isDone ? "X" : " ") + "] " + name); } + + public String writeLine() { + return null; + } + public Task() { setName("task"); setIsDone(false); diff --git a/src/main/java/huan/task/TodoTask.java b/src/main/java/huan/task/TodoTask.java index 46c9f8e9f..1d828ab5a 100644 --- a/src/main/java/huan/task/TodoTask.java +++ b/src/main/java/huan/task/TodoTask.java @@ -5,7 +5,14 @@ public TodoTask(String name, Boolean isDone) { super(name, isDone); setTaskType(1); } + + @Override public void printTask() { System.out.println("[T][" + (getIsDone() ? "X" : " ") + "] " + getName()); } + + @Override + public String writeLine() { + return "T" + (getIsDone() ? "T" : "F") + " " + getName(); + } } From ad834e9e6ab6d2b0af67737fe2346c36ad494137 Mon Sep 17 00:00:00 2001 From: Geinzit Date: Thu, 22 Feb 2024 13:17:57 +0800 Subject: [PATCH 11/19] Bugfix: write task to hard drive after deleting. --- src/main/java/huan/main/Huan.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/huan/main/Huan.java b/src/main/java/huan/main/Huan.java index 00d071768..a106b2fb0 100644 --- a/src/main/java/huan/main/Huan.java +++ b/src/main/java/huan/main/Huan.java @@ -181,7 +181,7 @@ public static void readProcessCommands() { tasks.get(deleteIndex - 1).setIsDone(true); System.out.println("Removed task number " + deleteIndex + ": " + tasks.get(deleteIndex - 1).getName()); tasks.remove(deleteIndex - 1); - + writeTasks(); } } catch (Exception e){ System.out.println("Incorrect format! Should be 'delete *n', where n is the index of the task you wish to delete."); From ff9c3868fa075a19ba838c561d65924882f0dba4 Mon Sep 17 00:00:00 2001 From: Geinzit Date: Wed, 6 Mar 2024 19:05:59 +0800 Subject: [PATCH 12/19] Add more OOP elements: separate class for UI, Storage, Parsing, and TaskList --- src/main/java/huan/main/Huan.java | 209 +-------------------- src/main/java/huan/main/Parser.java | 211 ++++++++++++++++++++++ src/main/java/huan/main/Storage.java | 66 +++++++ src/main/java/huan/main/TaskList.java | 31 ++++ src/main/java/huan/main/UI.java | 57 ++++++ src/main/java/huan/task/DeadlineTask.java | 35 +--- src/main/java/huan/task/EventTask.java | 46 +---- 7 files changed, 379 insertions(+), 276 deletions(-) create mode 100644 src/main/java/huan/main/Parser.java create mode 100644 src/main/java/huan/main/Storage.java create mode 100644 src/main/java/huan/main/TaskList.java create mode 100644 src/main/java/huan/main/UI.java diff --git a/src/main/java/huan/main/Huan.java b/src/main/java/huan/main/Huan.java index a106b2fb0..37337fbde 100644 --- a/src/main/java/huan/main/Huan.java +++ b/src/main/java/huan/main/Huan.java @@ -1,218 +1,17 @@ package huan.main; - import huan.task.*; -import java.util.Scanner; import java.util.ArrayList; import java.util.List; -import java.io.IOException; -import java.io.FileReader; -import java.io.BufferedReader; -import java.io.FileWriter; -import java.io.BufferedWriter; public class Huan { - private static List tasks = new ArrayList<>(); - - private static String taskFile = "tasklist.txt"; - public static Boolean isIndexValid(int index) { - return index >= 1 && index <= tasks.size(); - } - public static void addTask(Task newTask) { - tasks.add(newTask); - } - - public static void listTasks() { - int cnt = 0; - System.out.println("You have a total of " + tasks.size() + " tasks."); - for (Task task : tasks) { - cnt += 1; - System.out.printf(cnt + ". "); - - switch (task.getTaskType()) { - case (1): - TodoTask todoTask = (TodoTask)task; - todoTask.printTask(); - break; - case (2): - EventTask eventTask = (EventTask)task; - eventTask.printTask(); - break; - case (3): - DeadlineTask deadlineTask = (DeadlineTask)task; - deadlineTask.printTask(); - break; - default: - task.printTask(); - break; - } - } - } - - public static void writeTasks() { - try { - BufferedWriter writer = new BufferedWriter(new FileWriter(taskFile)); - for (Task task : tasks) { - writer.write(task.writeLine()); - writer.newLine(); - } - writer.flush(); - }catch (IOException e) { - e.printStackTrace(); - } - } - - public static void processLine(String line) throws Exception{ - String[] words = line.split(" "); - String suffixWord = line.substring(words[0].length() + 1); - - if (words[0].length() != 2 || (words[0].charAt(1) != 'T' && words[0].charAt(1) != 'F')) { - throw new Exception(); - } - - switch (words[0].charAt(0)) { - case ('T'): - addTask(new TodoTask(suffixWord, words[0].charAt(1) == 'T')); - break; - case ('D'): - addTask(new DeadlineTask(suffixWord, words[0].charAt(1) == 'T')); - break; - case ('E'): - addTask(new EventTask(suffixWord, words[0].charAt(1) == 'T')); - break; - default: - throw new Exception(); - } - } - - public static void readProcessCommands() { - - Scanner scanner = new Scanner(System.in); - while(true) { - System.out.println("-------------------------"); - String inputCommand = scanner.nextLine(); - String[] words = inputCommand.split(" "); - String firstWord = words[0]; - String suffixWord; - if(words.length > 1) { - suffixWord = inputCommand.substring(words[0].length() + 1); - } - else { - suffixWord = ""; - } - switch (firstWord) { - case ("bye"): - if(!suffixWord.isEmpty()) { - System.out.println("Invalid format! Should be 'bye'"); - break; - } - System.out.println("Bye! See ya!"); - return; - case ("list"): - if(!suffixWord.isEmpty()) { - System.out.println("Invalid format! Should be 'list'."); - break; - } - listTasks(); - break; - case ("mark"): - try { - int markIndex = Integer.parseInt(suffixWord); - if (!isIndexValid(markIndex)) { - System.out.println("Invalid task index!"); - } else { - tasks.get(markIndex - 1).setIsDone(true); - System.out.println("Set task number " + markIndex + ": " + tasks.get(markIndex - 1).getName() + " as done."); - writeTasks(); - } - } catch (Exception e){ - System.out.println("Incorrect format! Should be 'mark *n', where n is the index of the task you wish to mark as finished."); - } - break; - case ("unmark"): - try { - int unmarkIndex = Integer.parseInt(suffixWord); - if (!isIndexValid(unmarkIndex)) { - System.out.println("Invalid task index!"); - } else { - tasks.get(unmarkIndex - 1).setIsDone(false); - System.out.println("Set task number " + unmarkIndex + ": " + tasks.get(unmarkIndex - 1).getName() + " as not done."); - writeTasks(); - } - } catch (Exception e){ - System.out.println("Incorrect format! Should be 'unmark *n', where n is the index of the task you wish to mark as unfinished."); - } - break; - case ("todo"): - if(suffixWord.isEmpty()) { - System.out.println("Incorrect format! Should be 'todo *task_name'."); - break; - } - TodoTask todoTask = new TodoTask(suffixWord, false); - addTask(todoTask); - System.out.println("Added todo type task with name: " + todoTask.getName()); - writeTasks(); - break; - case ("event"): - try { - EventTask eventTask = new EventTask(suffixWord, false); - addTask(eventTask); - System.out.println("Added event type task with name: " + eventTask.getName()); - writeTasks(); - } catch (Exception e) { - System.out.println("Incorrect format! Should be 'event *event_name /from *start_time /to *end_time'."); - } - break; - case ("deadline"): - try { - DeadlineTask deadlineTask = new DeadlineTask(suffixWord, false); - addTask(deadlineTask); - System.out.println("Added deadline type task with name: " + deadlineTask.getName()); - writeTasks(); - } catch (Exception e) { - System.out.println("Incorrect format! Should be 'deadline *task_name /by *deadline_time'"); - } - break; - case ("delete"): - try { - int deleteIndex = Integer.parseInt(suffixWord); - if (!isIndexValid(deleteIndex)) { - System.out.println("Invalid task index!"); - } else { - tasks.get(deleteIndex - 1).setIsDone(true); - System.out.println("Removed task number " + deleteIndex + ": " + tasks.get(deleteIndex - 1).getName()); - tasks.remove(deleteIndex - 1); - writeTasks(); - } - } catch (Exception e){ - System.out.println("Incorrect format! Should be 'delete *n', where n is the index of the task you wish to delete."); - } - break; - default: - System.out.println("Unrecognized command, please try again!"); - break; - } - - } - } public static void main(String[] args) { String botName = "Huan"; - System.out.println("Hello! I'm " + botName + ", a chat bot"); + UI.displayWelcomeMessage(); - try (BufferedReader reader= new BufferedReader(new FileReader(taskFile))){ - String line; - try { - while ((line = reader.readLine()) != null) { - processLine(line); - } - } catch (Exception e) { - System.out.println("Corrupt task save file"); - tasks.clear(); - } + Storage.readFile(); - } catch (IOException e) { - tasks.clear(); - } - readProcessCommands(); + Parser.parseCommands(); } + } diff --git a/src/main/java/huan/main/Parser.java b/src/main/java/huan/main/Parser.java new file mode 100644 index 000000000..6abbfc573 --- /dev/null +++ b/src/main/java/huan/main/Parser.java @@ -0,0 +1,211 @@ +package huan.main; +import huan.task.*; + +import java.util.Objects; +import java.util.Scanner; + +public class Parser { + public static void parseCommands() { + + Scanner scanner = new Scanner(System.in); + while(true) { + UI.displaySeparator(); + + String inputCommand = scanner.nextLine(); + String[] words = inputCommand.split(" "); + String firstWord = words[0]; + String suffixWord; + if(words.length > 1) { + suffixWord = inputCommand.substring(words[0].length() + 1); + } + else { + suffixWord = ""; + } + + + switch (firstWord) { + case ("bye"): + if(!suffixWord.isEmpty()) { + UI.displayFormatError("'bye'"); + break; + } + UI.displayByeMessage(); + return; + case ("list"): + if(!suffixWord.isEmpty()) { + UI.displayFormatError("'list'"); + break; + } + TaskList.listTasks(); + break; + case ("mark"): + try { + int markIndex = Integer.parseInt(suffixWord); + if (!TaskList.isIndexValid(markIndex)) { + UI.displayIndexError(); + } else { + TaskList.tasks.get(markIndex - 1).setIsDone(true); + + UI.displayMarkTaskSuccess(markIndex); + + Storage.writeFile(); + } + } catch (Exception e){ + UI.displayFormatError("'mark *n', where n is the index of the task you wish to mark as finished"); + } + break; + case ("unmark"): + try { + int unmarkIndex = Integer.parseInt(suffixWord); + if (!TaskList.isIndexValid(unmarkIndex)) { + UI.displayIndexError(); + } else { + TaskList.tasks.get(unmarkIndex - 1).setIsDone(false); + + UI.displayUnmarkTaskSuccess(unmarkIndex); + + Storage.writeFile(); + } + } catch (Exception e){ + UI.displayFormatError("'unmark *n', where n is the index of the task you wish to mark as unfinished."); + } + break; + case ("todo"): + if(suffixWord.isEmpty()) { + UI.displayFormatError("'todo *task_name'"); + break; + } + TodoTask todoTask = parseTodoTask(suffixWord, false); + TaskList.addTask(todoTask); + + UI.displayAddTodoSuccess(todoTask.getName()); + + Storage.writeFile(); + break; + case ("event"): + try { + EventTask eventTask = parseEventTask(suffixWord, false); + TaskList.addTask(eventTask); + + UI.displayAddEventSuccess(eventTask.getName()); + + Storage.writeFile(); + } catch (Exception e) { + UI.displayFormatError("'event *event_name /from *start_time /to *end_time'"); + } + break; + case ("deadline"): + try { + DeadlineTask deadlineTask = parseDeadlineTask(suffixWord, false); + + TaskList.addTask(deadlineTask); + + UI.displayAddDeadlineSuccess(deadlineTask.getName()); + + Storage.writeFile(); + } catch (Exception e) { + UI.displayFormatError("'deadline *task_name /by *deadline_time'"); + } + break; + case ("delete"): + try { + int deleteIndex = Integer.parseInt(suffixWord); + if (!TaskList.isIndexValid(deleteIndex)) { + UI.displayIndexError(); + } else { + TaskList.tasks.get(deleteIndex - 1).setIsDone(true); + + UI.displayDeleteTaskSuccess(deleteIndex); + + TaskList.tasks.remove(deleteIndex - 1); + + Storage.writeFile(); + } + } catch (Exception e) { + UI.displayFormatError("'delete *n', where n is the index of the task you wish to delete."); + } + break; + default: + UI.displayUnrecognizedMessage(); + break; + } + + } + } + + public static TodoTask parseTodoTask(String suffixWord, Boolean isDone) { + return new TodoTask(suffixWord, isDone); + } + + public static DeadlineTask parseDeadlineTask(String suffixWord, Boolean isDone) throws Exception{ + StringBuilder ddlTime = new StringBuilder(); + StringBuilder name = new StringBuilder(); + String[] words = suffixWord.split(" "); + /* + state: + 0 means currently concatenating name + 1 means currently concatenating ddlTime + */ + int state = 0; + for(String word : words) { + if (Objects.equals(word, "/by")) { + state += 1; + } + else { + switch (state) { + case (0): + name.append((name.length() == 0) ? "" : " ").append(word); + break; + case (1): + ddlTime.append((ddlTime.length() == 0 ? "" : " ")).append(word); + break; + } + } + } + if(state != 1 || name.toString().isEmpty() || ddlTime.toString().isEmpty()) { + throw new Exception(); + } + + return new DeadlineTask(name.toString(), ddlTime.toString(), isDone); + } + + public static EventTask parseEventTask(String suffixWord, Boolean isDone) throws Exception{ + StringBuilder startTime = new StringBuilder(); + StringBuilder endTime = new StringBuilder(); + StringBuilder name = new StringBuilder(); + String[] words = suffixWord.split(" "); + /* + state: + 0 means currently concatenating name + 1 means currently concatenating startTime + 2 means currently concatenating endTime + */ + int state = 0; + for(String word : words) { + if (Objects.equals(word, "/from")) { + state += 1; + } + else if (Objects.equals(word, "/to")) { + state += 1; + } + else { + switch (state) { + case (0): + name.append((name.length() == 0) ? "" : " ").append(word); + break; + case (1): + startTime.append((startTime.length() == 0 ? "" : " ")).append(word); + break; + case (2): + endTime.append((endTime.length() == 0 ? "" : " ")).append(word); + break; + } + } + } + if(state != 2 || name.toString().isEmpty() || startTime.toString().isEmpty() || endTime.toString().isEmpty()) { + throw new Exception(); + } + + return new EventTask(name.toString(), startTime.toString(), endTime.toString(), isDone); + } +} diff --git a/src/main/java/huan/main/Storage.java b/src/main/java/huan/main/Storage.java new file mode 100644 index 000000000..4474675c8 --- /dev/null +++ b/src/main/java/huan/main/Storage.java @@ -0,0 +1,66 @@ +package huan.main; + +import huan.task.DeadlineTask; +import huan.task.EventTask; +import huan.task.Task; +import huan.task.TodoTask; + +import java.io.IOException; +import java.io.FileReader; +import java.io.BufferedReader; +import java.io.FileWriter; +import java.io.BufferedWriter; +public class Storage { + private static String taskFile = "tasklist.txt"; + + public static void processLine(String line) throws Exception{ + String[] words = line.split(" "); + String suffixWord = line.substring(words[0].length() + 1); + + if (words[0].length() != 2 || (words[0].charAt(1) != 'T' && words[0].charAt(1) != 'F')) { + throw new Exception(); + } + + switch (words[0].charAt(0)) { + case ('T'): + TaskList.addTask(Parser.parseTodoTask(suffixWord, words[0].charAt(1) == 'T')); + break; + case ('D'): + TaskList.addTask(Parser.parseDeadlineTask(suffixWord, words[0].charAt(1) == 'T')); + break; + case ('E'): + TaskList.addTask(Parser.parseEventTask(suffixWord, words[0].charAt(1) == 'T')); + break; + default: + throw new Exception(); + } + } + + public static void readFile() { + try (BufferedReader reader= new BufferedReader(new FileReader(taskFile))){ + String line; + try { + while ((line = reader.readLine()) != null) { + processLine(line); + } + } catch (Exception e) { + TaskList.clearTasks(); + } + } catch (IOException e) { + TaskList.clearTasks(); + } + } + + public static void writeFile() { + try { + BufferedWriter writer = new BufferedWriter(new FileWriter(taskFile)); + for (Task task : TaskList.tasks) { + writer.write(task.writeLine()); + writer.newLine(); + } + writer.flush(); + }catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/huan/main/TaskList.java b/src/main/java/huan/main/TaskList.java new file mode 100644 index 000000000..71e44a9c5 --- /dev/null +++ b/src/main/java/huan/main/TaskList.java @@ -0,0 +1,31 @@ +package huan.main; + +import huan.task.Task; + +import java.util.ArrayList; +import java.util.List; +public class TaskList { + public static List tasks = new ArrayList<>(); + + public static Boolean isIndexValid(int index) { + return index >= 1 && index <= tasks.size(); + } + public static void addTask(Task newTask) { + tasks.add(newTask); + } + + public static void clearTasks() { + tasks.clear(); + } + + public static void listTasks() { + int cnt = 0; + System.out.println("You have a total of " + tasks.size() + " tasks."); + for (Task task : tasks) { + cnt += 1; + System.out.printf(cnt + ". "); + + task.printTask(); + } + } +} diff --git a/src/main/java/huan/main/UI.java b/src/main/java/huan/main/UI.java new file mode 100644 index 000000000..03de169db --- /dev/null +++ b/src/main/java/huan/main/UI.java @@ -0,0 +1,57 @@ +package huan.main; + +public class UI { + private static String botName = "Huan"; + + public static void displayWelcomeMessage() { + System.out.println("Hello! I'm " + botName + ", a chat bot"); + } + + public static void displayListTask() { + System.out.println("You have a total of " + TaskList.tasks.size() + " tasks."); + } + + public static void displaySeparator() { + System.out.println("-------------------------"); + } + + public static void displayFormatError(String correctFormat) { + System.out.println("Invalid format! Should be " + correctFormat); + } + + public static void displayUnrecognizedMessage() { + System.out.println("Unrecognized command, please try again!"); + } + + public static void displayAddTodoSuccess(String taskName) { + System.out.println("Added todo type task with name: " + taskName); + } + + public static void displayAddEventSuccess(String taskName) { + System.out.println("Added event type task with name: " + taskName); + } + + public static void displayAddDeadlineSuccess(String taskName) { + System.out.println("Added deadline type task with name: " + taskName); + } + + public static void displayDeleteTaskSuccess(int deleteIndex) { + System.out.println("Removed task number " + deleteIndex + ": " + TaskList.tasks.get(deleteIndex - 1).getName()); + } + + public static void displayMarkTaskSuccess(int markIndex) { + System.out.println("Set task number " + markIndex + ": " + TaskList.tasks.get(markIndex - 1).getName() + " as done."); + } + + public static void displayUnmarkTaskSuccess(int unmarkIndex) { + System.out.println("Set task number " + unmarkIndex + ": " + TaskList.tasks.get(unmarkIndex - 1).getName() + " as not done."); + } + + public static void displayIndexError() { + System.out.println("Invalid task index!"); + } + + public static void displayByeMessage() { + System.out.println("Bye! See ya!"); + } +} diff --git a/src/main/java/huan/task/DeadlineTask.java b/src/main/java/huan/task/DeadlineTask.java index f8da07600..f1c0d785c 100644 --- a/src/main/java/huan/task/DeadlineTask.java +++ b/src/main/java/huan/task/DeadlineTask.java @@ -4,38 +4,11 @@ public class DeadlineTask extends Task{ private String ddlTime; - public DeadlineTask(String nameWithDate, Boolean isDone) throws Exception{ - StringBuilder ddlTime = new StringBuilder(); - StringBuilder name = new StringBuilder(); - String[] words = nameWithDate.split(" "); - /* - state: - 0 means currently concatenating name - 1 means currently concatenating ddlTime - */ - int state = 0; - for(String word : words) { - if (Objects.equals(word, "/by")) { - state += 1; - } - else { - switch (state) { - case (0): - name.append((name.length() == 0) ? "" : " ").append(word); - break; - case (1): - ddlTime.append((ddlTime.length() == 0 ? "" : " ")).append(word); - break; - } - } - } - if(state != 1 || name.toString().isEmpty() || isDone.toString().isEmpty()) { - throw new Exception(); - } - setName(name.toString()); + + public DeadlineTask(String name, String ddlTime, Boolean isDone) { + setName(name); + this.ddlTime = ddlTime; setIsDone(isDone); - setTaskType(3); - this.ddlTime = ddlTime.toString(); } @Override diff --git a/src/main/java/huan/task/EventTask.java b/src/main/java/huan/task/EventTask.java index eac86ca08..5eedb32ba 100644 --- a/src/main/java/huan/task/EventTask.java +++ b/src/main/java/huan/task/EventTask.java @@ -4,48 +4,14 @@ public class EventTask extends Task{ private String startTime, endTime; - public EventTask(String nameWithDates, Boolean isDone) throws Exception { - StringBuilder startTime = new StringBuilder(); - StringBuilder endTime = new StringBuilder(); - StringBuilder name = new StringBuilder(); - String[] words = nameWithDates.split(" "); - /* - state: - 0 means currently concatenating name - 1 means currently concatenating startTime - 2 means currently concatenating endTime - */ - int state = 0; - for(String word : words) { - if (Objects.equals(word, "/from")) { - state += 1; - } - else if (Objects.equals(word, "/to")) { - state += 1; - } - else { - switch (state) { - case (0): - name.append((name.length() == 0) ? "" : " ").append(word); - break; - case (1): - startTime.append((startTime.length() == 0 ? "" : " ")).append(word); - break; - case (2): - endTime.append((endTime.length() == 0 ? "" : " ")).append(word); - break; - } - } - } - if(state != 2 || name.toString().isEmpty() || startTime.toString().isEmpty() || endTime.toString().isEmpty()) { - throw new Exception(); - } - setName(name.toString()); + + public EventTask(String name, String startTime, String endTime, Boolean isDone) { + setName(name); + this.startTime = startTime; + this.endTime = endTime; setIsDone(isDone); - setTaskType(2); - this.startTime = startTime.toString(); - this.endTime = endTime.toString(); } + public void printTask() { System.out.println("[E][" + (getIsDone() ? "X" : " ") + "] " + getName() + " (from: " + startTime + " to: " + endTime + ")"); } From eb072c633018d57f9b7f3687df6e720aae47c896 Mon Sep 17 00:00:00 2001 From: Geinzit Date: Wed, 6 Mar 2024 20:21:17 +0800 Subject: [PATCH 13/19] Add date time recognition in DeadlineTasks, and a command for filtering deadline tasks before a specific time. --- src/main/java/huan/main/Huan.java | 3 -- src/main/java/huan/main/Parser.java | 16 +++++++++- src/main/java/huan/main/TaskList.java | 10 ------ src/main/java/huan/main/UI.java | 38 +++++++++++++++++++++++ src/main/java/huan/task/DeadlineTask.java | 23 ++++++++++++-- src/main/java/huan/task/EventTask.java | 1 + 6 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/main/java/huan/main/Huan.java b/src/main/java/huan/main/Huan.java index 37337fbde..47e24867e 100644 --- a/src/main/java/huan/main/Huan.java +++ b/src/main/java/huan/main/Huan.java @@ -1,8 +1,5 @@ package huan.main; -import huan.task.*; -import java.util.ArrayList; -import java.util.List; public class Huan { public static void main(String[] args) { diff --git a/src/main/java/huan/main/Parser.java b/src/main/java/huan/main/Parser.java index 6abbfc573..5d45f7545 100644 --- a/src/main/java/huan/main/Parser.java +++ b/src/main/java/huan/main/Parser.java @@ -4,6 +4,9 @@ import java.util.Objects; import java.util.Scanner; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; public class Parser { public static void parseCommands() { @@ -36,7 +39,7 @@ public static void parseCommands() { UI.displayFormatError("'list'"); break; } - TaskList.listTasks(); + UI.listTasks(); break; case ("mark"): try { @@ -125,6 +128,17 @@ public static void parseCommands() { UI.displayFormatError("'delete *n', where n is the index of the task you wish to delete."); } break; + case ("list_deadline"): + try { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + LocalDateTime dateTime = LocalDateTime.parse(suffixWord, formatter); + + UI.listTaskBeforeDateTime(dateTime); + } catch(DateTimeParseException e) { + UI.displayFormatError("'list_deadline yyyy-MM-dd HH:mm:ss'"); + } + break; default: UI.displayUnrecognizedMessage(); break; diff --git a/src/main/java/huan/main/TaskList.java b/src/main/java/huan/main/TaskList.java index 71e44a9c5..a53288719 100644 --- a/src/main/java/huan/main/TaskList.java +++ b/src/main/java/huan/main/TaskList.java @@ -18,14 +18,4 @@ public static void clearTasks() { tasks.clear(); } - public static void listTasks() { - int cnt = 0; - System.out.println("You have a total of " + tasks.size() + " tasks."); - for (Task task : tasks) { - cnt += 1; - System.out.printf(cnt + ". "); - - task.printTask(); - } - } } diff --git a/src/main/java/huan/main/UI.java b/src/main/java/huan/main/UI.java index 03de169db..cd8db3504 100644 --- a/src/main/java/huan/main/UI.java +++ b/src/main/java/huan/main/UI.java @@ -1,5 +1,10 @@ package huan.main; +import huan.task.DeadlineTask; +import huan.task.Task; + +import java.time.LocalDateTime; + public class UI { private static String botName = "Huan"; @@ -54,4 +59,37 @@ public static void displayIndexError() { public static void displayByeMessage() { System.out.println("Bye! See ya!"); } + + public static void displayDateTimeParseSuccess() { + System.out.println("Parsing dateTime success!"); + } + + public static void displayDateTimeParseError() { + System.out.println("Parsing dateTime failed, Use format 'yyyy-mm-dd HH:mm:ss'"); + } + + public static void listTasks() { + int cnt = 0; + System.out.println("You have a total of " + TaskList.tasks.size() + " tasks."); + for (Task task : TaskList.tasks) { + cnt += 1; + System.out.printf(cnt + ". "); + + task.printTask(); + } + } + + public static void listTaskBeforeDateTime(LocalDateTime dateTime) { + int cnt = 0; + for (Task task : TaskList.tasks) { + if (task.getTaskType() == 3) { + DeadlineTask ddlTask = (DeadlineTask)task; + if(ddlTask.isBefore(dateTime)) { + cnt += 1; + ddlTask.printTask(); + } + } + } + System.out.println("You have a total of " + cnt + " deadlines before " + dateTime); + } } diff --git a/src/main/java/huan/task/DeadlineTask.java b/src/main/java/huan/task/DeadlineTask.java index f1c0d785c..10287a462 100644 --- a/src/main/java/huan/task/DeadlineTask.java +++ b/src/main/java/huan/task/DeadlineTask.java @@ -1,14 +1,31 @@ package huan.task; -import java.util.Objects; - +import huan.main.UI; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; public class DeadlineTask extends Task{ private String ddlTime; - + private LocalDateTime dateTime; public DeadlineTask(String name, String ddlTime, Boolean isDone) { setName(name); this.ddlTime = ddlTime; setIsDone(isDone); + setTaskType(3); + + try { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + dateTime = LocalDateTime.parse(ddlTime, formatter); + UI.displayDateTimeParseSuccess(); + + } catch(DateTimeParseException e) { + dateTime = null; + UI.displayDateTimeParseError(); + } + } + + public Boolean isBefore(LocalDateTime dateTime) { + return this.dateTime.isBefore(dateTime); } @Override diff --git a/src/main/java/huan/task/EventTask.java b/src/main/java/huan/task/EventTask.java index 5eedb32ba..337051366 100644 --- a/src/main/java/huan/task/EventTask.java +++ b/src/main/java/huan/task/EventTask.java @@ -10,6 +10,7 @@ public EventTask(String name, String startTime, String endTime, Boolean isDone) this.startTime = startTime; this.endTime = endTime; setIsDone(isDone); + setTaskType(2); } public void printTask() { From f8a7df625dfd3fc8fa7e6fb5f52761fe11d9eb89 Mon Sep 17 00:00:00 2001 From: Geinzit Date: Wed, 6 Mar 2024 20:39:21 +0800 Subject: [PATCH 14/19] Add 'find' feature that allows filtering tasks by matching names --- src/main/java/huan/main/Huan.java | 4 ---- src/main/java/huan/main/Parser.java | 7 +++++++ src/main/java/huan/main/UI.java | 13 +++++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/main/java/huan/main/Huan.java b/src/main/java/huan/main/Huan.java index 37337fbde..10e07bca0 100644 --- a/src/main/java/huan/main/Huan.java +++ b/src/main/java/huan/main/Huan.java @@ -1,8 +1,4 @@ package huan.main; -import huan.task.*; - -import java.util.ArrayList; -import java.util.List; public class Huan { public static void main(String[] args) { diff --git a/src/main/java/huan/main/Parser.java b/src/main/java/huan/main/Parser.java index 6abbfc573..50b026334 100644 --- a/src/main/java/huan/main/Parser.java +++ b/src/main/java/huan/main/Parser.java @@ -125,6 +125,13 @@ public static void parseCommands() { UI.displayFormatError("'delete *n', where n is the index of the task you wish to delete."); } break; + case ("find"): + if(!suffixWord.isEmpty()) { + UI.displayMatchingTasks(suffixWord); + } else { + UI.displayFormatError("'find *keyword'"); + } + break; default: UI.displayUnrecognizedMessage(); break; diff --git a/src/main/java/huan/main/UI.java b/src/main/java/huan/main/UI.java index 03de169db..564023f24 100644 --- a/src/main/java/huan/main/UI.java +++ b/src/main/java/huan/main/UI.java @@ -1,5 +1,7 @@ package huan.main; +import huan.task.Task; + public class UI { private static String botName = "Huan"; @@ -54,4 +56,15 @@ public static void displayIndexError() { public static void displayByeMessage() { System.out.println("Bye! See ya!"); } + + public static void displayMatchingTasks(String keyword) { + int cnt = 0; + for (Task task : TaskList.tasks) { + if (task.getName().toLowerCase().contains(keyword.toLowerCase())) { + cnt += 1; + task.printTask(); + } + } + System.out.println("Found " + cnt + " matching tasks."); + } } From d370e77126620821f23dc934044171418eb11f31 Mon Sep 17 00:00:00 2001 From: Geinzit Date: Wed, 6 Mar 2024 21:57:54 +0800 Subject: [PATCH 15/19] Add Javadoc Comments. --- src/main/java/huan/main/Huan.java | 9 +++- src/main/java/huan/main/Parser.java | 27 ++++++++++ src/main/java/huan/main/Storage.java | 18 +++++-- src/main/java/huan/main/TaskList.java | 17 ++++++ src/main/java/huan/main/UI.java | 66 +++++++++++++++++++++-- src/main/java/huan/task/DeadlineTask.java | 32 +++++++++++ src/main/java/huan/task/EventTask.java | 35 +++++++++++- src/main/java/huan/task/Task.java | 51 +++++++++++++++--- src/main/java/huan/task/TodoTask.java | 15 ++++++ 9 files changed, 251 insertions(+), 19 deletions(-) diff --git a/src/main/java/huan/main/Huan.java b/src/main/java/huan/main/Huan.java index 47e24867e..4451e06fd 100644 --- a/src/main/java/huan/main/Huan.java +++ b/src/main/java/huan/main/Huan.java @@ -1,9 +1,14 @@ package huan.main; +/** + * Main Class + */ public class Huan { - + /** + * Main function + * @param args unused + */ public static void main(String[] args) { - String botName = "Huan"; UI.displayWelcomeMessage(); Storage.readFile(); diff --git a/src/main/java/huan/main/Parser.java b/src/main/java/huan/main/Parser.java index 9b8197368..3bb64b390 100644 --- a/src/main/java/huan/main/Parser.java +++ b/src/main/java/huan/main/Parser.java @@ -7,7 +7,14 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; + +/** + * Class for parsing all user commands + */ public class Parser { + /** + * Method for parsing command inputs + */ public static void parseCommands() { Scanner scanner = new Scanner(System.in); @@ -154,10 +161,23 @@ public static void parseCommands() { } } + /** + * Method for parsing a TodoTask from the command + * @param suffixWord the command-string to be parsed + * @param isDone whether the task is marked as finished + * @return a parsed TodoTask type object + */ public static TodoTask parseTodoTask(String suffixWord, Boolean isDone) { return new TodoTask(suffixWord, isDone); } + /** + * Method for parsing a DeadlineTask from the command + * @param suffixWord the command-string to be parsed + * @param isDone whether the task is marked as finished + * @return a parsed DeadlineTask type object + * @throws Exception detect whether the command format is incorrect + */ public static DeadlineTask parseDeadlineTask(String suffixWord, Boolean isDone) throws Exception{ StringBuilder ddlTime = new StringBuilder(); StringBuilder name = new StringBuilder(); @@ -190,6 +210,13 @@ public static DeadlineTask parseDeadlineTask(String suffixWord, Boolean isDone) return new DeadlineTask(name.toString(), ddlTime.toString(), isDone); } + /** + * Method for parsing a EventTask from the command + * @param suffixWord the command-string to be parsed + * @param isDone whether the task is marked as finished + * @return a parsed EventTask type object + * @throws Exception detect whether the command format is incorrect + */ public static EventTask parseEventTask(String suffixWord, Boolean isDone) throws Exception{ StringBuilder startTime = new StringBuilder(); StringBuilder endTime = new StringBuilder(); diff --git a/src/main/java/huan/main/Storage.java b/src/main/java/huan/main/Storage.java index 4474675c8..cbbb74ea4 100644 --- a/src/main/java/huan/main/Storage.java +++ b/src/main/java/huan/main/Storage.java @@ -1,18 +1,24 @@ package huan.main; -import huan.task.DeadlineTask; -import huan.task.EventTask; import huan.task.Task; -import huan.task.TodoTask; import java.io.IOException; import java.io.FileReader; import java.io.BufferedReader; import java.io.FileWriter; import java.io.BufferedWriter; + +/** + * Class for reading & writing input/output to file + */ public class Storage { private static String taskFile = "tasklist.txt"; + /** + * Method for processing a line of input + * @param line the line to be processed + * @throws Exception exception is thrown whenever the input format is corrupt. + */ public static void processLine(String line) throws Exception{ String[] words = line.split(" "); String suffixWord = line.substring(words[0].length() + 1); @@ -36,6 +42,9 @@ public static void processLine(String line) throws Exception{ } } + /** + * Method for reading the input file + */ public static void readFile() { try (BufferedReader reader= new BufferedReader(new FileReader(taskFile))){ String line; @@ -51,6 +60,9 @@ public static void readFile() { } } + /** + * Method for writing the current task list to the file + */ public static void writeFile() { try { BufferedWriter writer = new BufferedWriter(new FileWriter(taskFile)); diff --git a/src/main/java/huan/main/TaskList.java b/src/main/java/huan/main/TaskList.java index a53288719..957b30e5e 100644 --- a/src/main/java/huan/main/TaskList.java +++ b/src/main/java/huan/main/TaskList.java @@ -4,16 +4,33 @@ import java.util.ArrayList; import java.util.List; + +/** + * Class for storing the list of tasks, include methods for checking index validity, adding task and clear entire list + */ public class TaskList { public static List tasks = new ArrayList<>(); + /** + * Method for checking whether the given index is valid + * @param index the given index, can used for either marking, unmarking, and deleting the indexed tasks + * @return whether the index in within range of the list + */ public static Boolean isIndexValid(int index) { return index >= 1 && index <= tasks.size(); } + + /** + * Method for adding a task to the List + * @param newTask the task to be added + */ public static void addTask(Task newTask) { tasks.add(newTask); } + /** + * Method for clearing the list, in case of corrupt or empty input + */ public static void clearTasks() { tasks.clear(); } diff --git a/src/main/java/huan/main/UI.java b/src/main/java/huan/main/UI.java index 5a23d5224..d6d59a81a 100644 --- a/src/main/java/huan/main/UI.java +++ b/src/main/java/huan/main/UI.java @@ -8,58 +8,101 @@ public class UI { private static String botName = "Huan"; + /** + * Display welcome message + */ public static void displayWelcomeMessage() { System.out.println("Hello! I'm " + botName + ", a chat bot"); } - public static void displayListTask() { - System.out.println("You have a total of " + TaskList.tasks.size() + " tasks."); - } - + /** + * Display a separator line + */ public static void displaySeparator() { System.out.println("-------------------------"); } + /** + * Display a message to inform format error, and show the correct format + * @param correctFormat the correct format, as well as any neccessary information + */ public static void displayFormatError(String correctFormat) { System.out.println("Invalid format! Should be " + correctFormat); } + /** + * Display a message informing an unrecognized message + */ public static void displayUnrecognizedMessage() { System.out.println("Unrecognized command, please try again!"); } + /** + * Display a message informing success adding a new TodoTask + * @param taskName name of the task + */ public static void displayAddTodoSuccess(String taskName) { System.out.println("Added todo type task with name: " + taskName); } + /** + * Display a message informing success adding a new EventTask + * @param taskName name of the task + */ public static void displayAddEventSuccess(String taskName) { System.out.println("Added event type task with name: " + taskName); } + /** + * Display a message informing success adding a new DeadlineTask + * @param taskName + */ public static void displayAddDeadlineSuccess(String taskName) { System.out.println("Added deadline type task with name: " + taskName); } + /** + * Display a message informing success deleting a new task + * @param deleteIndex index of the to-be-deleted task + */ public static void displayDeleteTaskSuccess(int deleteIndex) { System.out.println("Removed task number " + deleteIndex + ": " + TaskList.tasks.get(deleteIndex - 1).getName()); } + /** + * Display a message informing success marking a Task as completed + * @param markIndex index of the to-be-marked task + */ public static void displayMarkTaskSuccess(int markIndex) { System.out.println("Set task number " + markIndex + ": " + TaskList.tasks.get(markIndex - 1).getName() + " as done."); } + /** + * Display a message informing success unmarking a Task as completed + * @param unmarkIndex index of the to-be-unmarked task + */ public static void displayUnmarkTaskSuccess(int unmarkIndex) { System.out.println("Set task number " + unmarkIndex + ": " + TaskList.tasks.get(unmarkIndex - 1).getName() + " as not done."); } + /** + * Display a message informing the index input is incorrect + */ public static void displayIndexError() { System.out.println("Invalid task index!"); } + /** + * Display a goodbye message + */ public static void displayByeMessage() { System.out.println("Bye! See ya!"); } + /** + * Show the matching tasks in the list, with a given keyword + * @param keyword the keyword for matching + */ public static void displayMatchingTasks(String keyword) { int cnt = 0; for (Task task : TaskList.tasks) { @@ -70,15 +113,24 @@ public static void displayMatchingTasks(String keyword) { } System.out.println("Found " + cnt + " matching tasks."); } - + + /** + * Display a message informing success in parsing a LocalDateTime + */ public static void displayDateTimeParseSuccess() { System.out.println("Parsing dateTime success!"); } + /** + * Display a message informing failure in parsing a LocalDateTime + */ public static void displayDateTimeParseError() { System.out.println("Parsing dateTime failed, Use format 'yyyy-mm-dd HH:mm:ss'"); } + /** + * List all tasks in the List + */ public static void listTasks() { int cnt = 0; System.out.println("You have a total of " + TaskList.tasks.size() + " tasks."); @@ -90,6 +142,10 @@ public static void listTasks() { } } + /** + * List all DeadlineTasks before the given date time + * @param dateTime the given datetime + */ public static void listTaskBeforeDateTime(LocalDateTime dateTime) { int cnt = 0; for (Task task : TaskList.tasks) { diff --git a/src/main/java/huan/task/DeadlineTask.java b/src/main/java/huan/task/DeadlineTask.java index 10287a462..b9dcff5cb 100644 --- a/src/main/java/huan/task/DeadlineTask.java +++ b/src/main/java/huan/task/DeadlineTask.java @@ -4,9 +4,20 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; + +/** + * Class for tasks with a specific deadline + */ public class DeadlineTask extends Task{ private String ddlTime; private LocalDateTime dateTime; + + /** + * Contructor method for DeadlineTask + * @param name task name + * @param ddlTime the time of the deadline + * @param isDone whether the task is marked as finished + */ public DeadlineTask(String name, String ddlTime, Boolean isDone) { setName(name); this.ddlTime = ddlTime; @@ -24,23 +35,44 @@ public DeadlineTask(String name, String ddlTime, Boolean isDone) { } } + /** + * Method for checking whether the deadline is before a specific time + * @param dateTime the given time + * @return whether the deadline is before a specific time + */ public Boolean isBefore(LocalDateTime dateTime) { return this.dateTime.isBefore(dateTime); } + /** + * Method for printing an DeadlineTask + */ @Override public void printTask() { System.out.println("[D][" + (getIsDone() ? "X" : " ") + "] " + getName() + " (by: " + ddlTime + ")"); } + /** + * Method for writing the DeadlineTask to file + * @return the line to be written to ile + */ @Override public String writeLine() { return "D" + (getIsDone() ? "T" : "F") + " " + getName() + " /by " + ddlTime; } + + /** + * Get method for the ddlTime attribute + * @return the ddlTime attribute + */ public String getDdlTime() { return ddlTime; } + /** + * Set method for the ddlTime attribute + * @param ddlTime the ddlTime attribute + */ public void setDdlTime(String ddlTime) { this.ddlTime = ddlTime; } diff --git a/src/main/java/huan/task/EventTask.java b/src/main/java/huan/task/EventTask.java index 337051366..62563d46f 100644 --- a/src/main/java/huan/task/EventTask.java +++ b/src/main/java/huan/task/EventTask.java @@ -1,10 +1,18 @@ package huan.task; -import java.util.Objects; - +/** + * Class for a task representing an event + */ public class EventTask extends Task{ private String startTime, endTime; + /** + * Constructor class for an EventTask + * @param name the name of the Task + * @param startTime the start date of the event + * @param endTime the end date of the event + * @param isDone whether the task is marked as finished + */ public EventTask(String name, String startTime, String endTime, Boolean isDone) { setName(name); this.startTime = startTime; @@ -13,27 +21,50 @@ public EventTask(String name, String startTime, String endTime, Boolean isDone) setTaskType(2); } + /** + * Method for printing the Task + */ public void printTask() { System.out.println("[E][" + (getIsDone() ? "X" : " ") + "] " + getName() + " (from: " + startTime + " to: " + endTime + ")"); } + /** + * Method for writing the Task to file + * @return the line to be written to file + */ @Override public String writeLine() { return "E" + (getIsDone() ? "T" : "F") + " " + getName() + " /from " + startTime + " /to " + endTime; } + /** + * Set method for the start date + * @param startTime the start date + */ public void setStartTime(String startTime) { this.startTime = startTime; } + /** + * Get method for the start date + * @return the start date + */ public String getStartTime() { return startTime; } + /** + * Set method for the end date + * @param endTime the end date + */ public void setEndTime(String endTime) { this.endTime = endTime; } + /** + * Get method for the end date + * @return the end date + */ public String getEndTime() { return endTime; } diff --git a/src/main/java/huan/task/Task.java b/src/main/java/huan/task/Task.java index 48d39fa30..025ec7c8f 100644 --- a/src/main/java/huan/task/Task.java +++ b/src/main/java/huan/task/Task.java @@ -1,54 +1,91 @@ package huan.task; + +/** + * Class for a regular task + */ public class Task { private String name; private Boolean isDone; - /** - * used for casting back types - * 0 for no specific types - * 1 for Todo types - * 2 for Event types - * 3 for Deadline types - */ + private int taskType; + /** + * Set method for task name + * @param name the task name + */ public void setName(String name) { this.name = name; } + /** + * Set method for isDone + * @param isDone whether the task is marked as finished + */ public void setIsDone(Boolean isDone) { this.isDone = isDone; } + /** + * Set method for task type + * @param taskType the type of task, 1 for TodoTask, 2 for EventTask, 3 for Deadline Task. Used for recasting + */ public void setTaskType(int taskType) { this.taskType = taskType; } + /** + * Get method for task name + * @return the task name + */ public String getName() { return name; } + /** + * Get method for isDone + * @return whether the task is marked as finished + */ public Boolean getIsDone() { return isDone; } + /** + * Get method for taskType + * @return the type the type of task, 1 for TodoTask, 2 for EventTask, 3 for Deadline Task. + */ public int getTaskType() { return taskType; } + /** + * Method for printing a task. Will be overridden by other classes + */ public void printTask() { System.out.println("[" + (isDone ? "X" : " ") + "] " + name); } + /** + * Method for writing the line. Will be overridden by other classes + * @return nothing + */ public String writeLine() { return null; } + /** + * Default Constructor class for Task + */ public Task() { setName("task"); setIsDone(false); taskType = 0; } + /** + * Constructor class for Task + * @param name the task name + * @param isDone whether the task will be marked as finished + */ public Task(String name, Boolean isDone) { setName(name); setIsDone(isDone); diff --git a/src/main/java/huan/task/TodoTask.java b/src/main/java/huan/task/TodoTask.java index 1d828ab5a..066cba385 100644 --- a/src/main/java/huan/task/TodoTask.java +++ b/src/main/java/huan/task/TodoTask.java @@ -1,16 +1,31 @@ package huan.task; +/** + * Class for a regular todo Task + */ public class TodoTask extends Task{ + /** + * Contructor method for TodoTask + * @param name name of task + * @param isDone whether the task is marked as finished + */ public TodoTask(String name, Boolean isDone) { super(name, isDone); setTaskType(1); } + /** + * Method for printing the TodoTask + */ @Override public void printTask() { System.out.println("[T][" + (getIsDone() ? "X" : " ") + "] " + getName()); } + /** + * Method for writing the Task to file + * @return the line to be written on the file + */ @Override public String writeLine() { return "T" + (getIsDone() ? "T" : "F") + " " + getName(); From 16fbedf3ccde2f95e5f62209e1733cd63dbf8bf7 Mon Sep 17 00:00:00 2001 From: HeinzHuang <99856638+Geinzit@users.noreply.github.com> Date: Wed, 6 Mar 2024 22:11:10 +0800 Subject: [PATCH 16/19] Update README.md --- README.md | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 8715d4d91..57c966a67 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,18 @@ -# Duke project template +# Huan +A simple, easy to use chatbot for task managing. -This is a project template for a greenfield Java project. It's named after the Java mascot _Duke_. Given below are instructions on how to use it. +Its name's Huan. -## Setting up in Intellij +## Features -Prerequisites: JDK 11, update Intellij to the most recent version. +### Simple, easy to use interface -1. Open Intellij (if you are not in the welcome screen, click `File` > `Close Project` to close the existing project first) -1. Open the project into Intellij as follows: - 1. Click `Open`. - 1. Select the project directory, and click `OK`. - 1. If there are any further prompts, accept the defaults. -1. Configure the project to use **JDK 11** (not other versions) as explained in [here](https://www.jetbrains.com/help/idea/sdk.html#set-up-jdk).
- In the same dialog, set the **Project language level** field to the `SDK default` option. -3. After that, locate the `src/main/java/Duke.java` file, right-click it, and choose `Run Duke.main()` (if the code editor is showing compile errors, try restarting the IDE). If the setup is correct, you should see something like the below as the output: - ``` - Hello from - ____ _ - | _ \ _ _| | _____ - | | | | | | | |/ / _ \ - | |_| | |_| | < __/ - |____/ \__,_|_|\_\___| - ``` +Huan's a bot of few words, but the meaning always gets across + +### Supports multiple types of tasks + +currently have 3 types: + +- todo-tasks, which can be marked as finished or unfinished. +- EventTasks, for representing your future events, have a start time and an end time, can also be marked as finished or unfinished +- DeadlineTasks, for tasks with specific deadlines, comes with an additional datetime field which can be used for organizing your deadlines From dc722b0730763a8693f74f3defbe28cc6972969e Mon Sep 17 00:00:00 2001 From: HeinzHuang <99856638+Geinzit@users.noreply.github.com> Date: Wed, 6 Mar 2024 22:14:26 +0800 Subject: [PATCH 17/19] Update README.md --- README.md | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/README.md b/README.md index 57c966a67..2ca9a54d8 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,4 @@ # Huan A simple, easy to use chatbot for task managing. -Its name's Huan. - -## Features - -### Simple, easy to use interface - -Huan's a bot of few words, but the meaning always gets across - -### Supports multiple types of tasks - -currently have 3 types: - -- todo-tasks, which can be marked as finished or unfinished. -- EventTasks, for representing your future events, have a start time and an end time, can also be marked as finished or unfinished -- DeadlineTasks, for tasks with specific deadlines, comes with an additional datetime field which can be used for organizing your deadlines +Its name's Huan, btw From 2bb555069e949be0ff9c87f2c357f847e5fd5166 Mon Sep 17 00:00:00 2001 From: HeinzHuang <99856638+Geinzit@users.noreply.github.com> Date: Wed, 6 Mar 2024 22:31:24 +0800 Subject: [PATCH 18/19] Update README.md --- docs/README.md | 88 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 27 deletions(-) diff --git a/docs/README.md b/docs/README.md index 8077118eb..f73aae35b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,29 +1,63 @@ # User Guide -## 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 -``` +## Features + +### Simple, easy to use interface + +Huan's a bot of few words, but the meaning always gets across + +### Supports multiple types of tasks + +currently have 3 types: + +- todo-tasks, which can be marked as finished or unfinished. +- EventTasks, for representing your future events, have a start time and an end time, can also be marked as finished or unfinished +- DeadlineTasks, for tasks with specific deadlines, comes with an additional datetime field which can be used for organizing your deadlines + +### data persistence through file storage + +All changes to the task list will be saved on your computer, and will be safely loaded next time when launching the chatbot. + +So there's no data loss between different instances of launching. + +### find tasks via name + +supports task-filtering using names + +### filter deadline tasks before a specific time + +find all deadlines before a specific time with special formatting + +## Commands + +- bye + - safely quit the chatbot +- list + - list all the tasks you currently have +- todo *taskName + - add a todo type task to your list, taskname can have in-between spaces + - e.g. `todo do homework` +- event *taskname /from *starttime /to *endtime + - add a event type task to your list, taskname, starttime, endtime can have in-between spaces + - e.g. `event concert with gf /from 3pm /to 6pm` +- deadline *task /by *ddltime + - add a deadline type task to your list, taskname, ddltime can have in-between spaces + - ddltime can be formatted in a special way to support date time tracking, format is "yyyy-MM-dd HH:mm:ss" + - e.g. "deadline 2113 gp /by 2024-03-08 23:59:59" or "deadline book report /by tonight" +- mark *index + - mark the n-th task in the list as completed + - use `list` to check for index if not certain + - e.g. `mark 3` +- unmark *index + - unmark the n-th task in the list + - e.g. `unmark 2` +- delete *index + - remove the n-th task from the list + - e.g. `delete 6` +- find *name + - list all tasks with tasknames containing *name + - e.g. `find book` +- list_deadline *datetime + - list all deadline tasks before a given time + - all time must be correctly formatted("yyyy-MM-dd HH:mm:ss") + - only deadline tasks with correctly formatted datetime values will be listed From 38f1745348721b6428f7064cef993c1de1f66960 Mon Sep 17 00:00:00 2001 From: Geinzit Date: Wed, 6 Mar 2024 22:34:57 +0800 Subject: [PATCH 19/19] Fix typos. Ignore unparsable DeadlineTasks in 'list_deadline' --- src/main/java/huan/main/TaskList.java | 2 +- src/main/java/huan/main/UI.java | 2 +- src/main/java/huan/task/DeadlineTask.java | 5 ++++- src/main/java/huan/task/Task.java | 2 +- src/main/java/huan/task/TodoTask.java | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/huan/main/TaskList.java b/src/main/java/huan/main/TaskList.java index 957b30e5e..e36de91e8 100644 --- a/src/main/java/huan/main/TaskList.java +++ b/src/main/java/huan/main/TaskList.java @@ -13,7 +13,7 @@ public class TaskList { /** * Method for checking whether the given index is valid - * @param index the given index, can used for either marking, unmarking, and deleting the indexed tasks + * @param index the given index, can be used for either marking, unmarking, and deleting the indexed tasks * @return whether the index in within range of the list */ public static Boolean isIndexValid(int index) { diff --git a/src/main/java/huan/main/UI.java b/src/main/java/huan/main/UI.java index d6d59a81a..68293b84e 100644 --- a/src/main/java/huan/main/UI.java +++ b/src/main/java/huan/main/UI.java @@ -24,7 +24,7 @@ public static void displaySeparator() { /** * Display a message to inform format error, and show the correct format - * @param correctFormat the correct format, as well as any neccessary information + * @param correctFormat the correct format, as well as any necessary information */ public static void displayFormatError(String correctFormat) { System.out.println("Invalid format! Should be " + correctFormat); diff --git a/src/main/java/huan/task/DeadlineTask.java b/src/main/java/huan/task/DeadlineTask.java index b9dcff5cb..9067d583b 100644 --- a/src/main/java/huan/task/DeadlineTask.java +++ b/src/main/java/huan/task/DeadlineTask.java @@ -13,7 +13,7 @@ public class DeadlineTask extends Task{ private LocalDateTime dateTime; /** - * Contructor method for DeadlineTask + * Constructor method for DeadlineTask * @param name task name * @param ddlTime the time of the deadline * @param isDone whether the task is marked as finished @@ -41,6 +41,9 @@ public DeadlineTask(String name, String ddlTime, Boolean isDone) { * @return whether the deadline is before a specific time */ public Boolean isBefore(LocalDateTime dateTime) { + if (this.dateTime == null) { + return false; + } return this.dateTime.isBefore(dateTime); } diff --git a/src/main/java/huan/task/Task.java b/src/main/java/huan/task/Task.java index 025ec7c8f..369910360 100644 --- a/src/main/java/huan/task/Task.java +++ b/src/main/java/huan/task/Task.java @@ -51,7 +51,7 @@ public Boolean getIsDone() { /** * Get method for taskType - * @return the type the type of task, 1 for TodoTask, 2 for EventTask, 3 for Deadline Task. + * @return the type of task, 1 for TodoTask, 2 for EventTask, 3 for Deadline Task. */ public int getTaskType() { return taskType; diff --git a/src/main/java/huan/task/TodoTask.java b/src/main/java/huan/task/TodoTask.java index 066cba385..e3dd283e9 100644 --- a/src/main/java/huan/task/TodoTask.java +++ b/src/main/java/huan/task/TodoTask.java @@ -5,7 +5,7 @@ */ public class TodoTask extends Task{ /** - * Contructor method for TodoTask + * Constructor method for TodoTask * @param name name of task * @param isDone whether the task is marked as finished */