From 2ca33c9f324a0d82278eec79407ec6f03b795968 Mon Sep 17 00:00:00 2001 From: notbingsu Date: Wed, 1 Feb 2023 00:16:46 +0800 Subject: [PATCH 01/15] no message --- src/main/java/Duke.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 5d313334c..4c1841ab2 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,3 +1,5 @@ +import java.util.Scanner; + public class Duke { public static void main(String[] args) { String logo = " ____ _ \n" @@ -6,5 +8,10 @@ public static void main(String[] args) { + "| |_| | |_| | < __/\n" + "|____/ \\__,_|_|\\_\\___|\n"; System.out.println("Hello from\n" + logo); + + System.out.println("Hello! I'm Duke"); + System.out.println("What can I do for you?"); + + System.out.println("Bye. Hope to see you again soon!"); } } From d0702bc6f0fd50f66b62094ae4e5a5914e3d66cc Mon Sep 17 00:00:00 2001 From: notbingsu Date: Wed, 1 Feb 2023 00:17:56 +0800 Subject: [PATCH 02/15] level-1, greet, echo, exit --- src/main/java/Duke.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 4c1841ab2..8b7a44eed 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -11,7 +11,12 @@ public static void main(String[] args) { System.out.println("Hello! I'm Duke"); System.out.println("What can I do for you?"); - + Scanner userInput = new Scanner(System.in); //create Scanner object + String inputCommand = userInput.nextLine(); //read user input + while (!inputCommand.equals("bye")){ + System.out.println(inputCommand); + inputCommand = userInput.nextLine(); + } System.out.println("Bye. Hope to see you again soon!"); } } From bb6a8d2383e0eb456ef81370496dbf4e5a715f20 Mon Sep 17 00:00:00 2001 From: notbingsu Date: Thu, 2 Feb 2023 21:15:12 +0800 Subject: [PATCH 03/15] level2, add, list --- src/main/java/Duke.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 8b7a44eed..2e95346f9 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,3 +1,5 @@ +import java.util.ArrayList; +import java.util.List; import java.util.Scanner; public class Duke { @@ -13,9 +15,19 @@ public static void main(String[] args) { System.out.println("What can I do for you?"); Scanner userInput = new Scanner(System.in); //create Scanner object String inputCommand = userInput.nextLine(); //read user input + List allInputs = new ArrayList(); while (!inputCommand.equals("bye")){ - System.out.println(inputCommand); + if (inputCommand.equals("list")){ + for (int i = 0; i < allInputs.size(); i ++){ + System.out.println(i + ". " + allInputs.get(i)); + } + } + else { + System.out.println("added: " + inputCommand); + allInputs.add(inputCommand); + } inputCommand = userInput.nextLine(); + } System.out.println("Bye. Hope to see you again soon!"); } From e7a02853fea4e7e8c059fdf37fab58ba93c910d1 Mon Sep 17 00:00:00 2001 From: notbingsu Date: Fri, 3 Feb 2023 00:28:24 +0800 Subject: [PATCH 04/15] level-3, mark as done --- src/main/java/Duke.java | 44 ++++++++++++++++++----------------------- src/main/java/Main.java | 31 +++++++++++++++++++++++++++++ src/main/java/Task.java | 31 +++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 25 deletions(-) create mode 100644 src/main/java/Main.java create mode 100644 src/main/java/Task.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 2e95346f9..8ae24b829 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,34 +1,28 @@ import java.util.ArrayList; import java.util.List; -import java.util.Scanner; + public class Duke { - public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); + private List taskList = new ArrayList(); + public void addTask(String taskName){ + Task t = new Task(taskName); + taskList.add(t); + System.out.printf(String.format("added: %s\n", taskName)); + } - System.out.println("Hello! I'm Duke"); - System.out.println("What can I do for you?"); - Scanner userInput = new Scanner(System.in); //create Scanner object - String inputCommand = userInput.nextLine(); //read user input - List allInputs = new ArrayList(); - while (!inputCommand.equals("bye")){ - if (inputCommand.equals("list")){ - for (int i = 0; i < allInputs.size(); i ++){ - System.out.println(i + ". " + allInputs.get(i)); - } - } - else { - System.out.println("added: " + inputCommand); - allInputs.add(inputCommand); - } - inputCommand = userInput.nextLine(); + public void changeTaskState(boolean doneState, Integer index){ + index --; + if (doneState){ + taskList.get(index).markAsDone(); + } + else{ + taskList.get(index).markAsUndone(); + } + } + public void list(){ + for (int i = 0; i < taskList.size(); i ++){ + System.out.printf(String.format("%d.%s\n", i + 1, taskList.get(i).toString())); } - System.out.println("Bye. Hope to see you again soon!"); } } diff --git a/src/main/java/Main.java b/src/main/java/Main.java new file mode 100644 index 000000000..df2ec708b --- /dev/null +++ b/src/main/java/Main.java @@ -0,0 +1,31 @@ +import java.util.Scanner; +public class Main { + public static void main(String[] args) { + + String logo = " ____ _ \n" + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; + System.out.println("Hello from\n" + logo); + + System.out.println("Hello! I'm Duke"); + System.out.println("What can I do for you?"); + Duke Duke = new Duke(); + Scanner userInput = new Scanner(System.in); //create Scanner object + String inputCommand = userInput.nextLine(); //read user input + while (!inputCommand.equals("bye")){ + if (inputCommand.equals("list")){ + Duke.list(); + } else if (inputCommand.split(" ")[0].equals("mark")) { + Duke.changeTaskState(true, Integer.parseInt(inputCommand.split(" ")[1])); + } else if (inputCommand.split(" ")[0].equals("unmark")) { + Duke.changeTaskState(false, Integer.parseInt(inputCommand.split(" ")[1])); + } else{ + Duke.addTask(inputCommand); + } + inputCommand = userInput.nextLine(); + } + System.out.println("Bye. Hope to see you again soon!"); + } +} diff --git a/src/main/java/Task.java b/src/main/java/Task.java new file mode 100644 index 000000000..2f796a1ed --- /dev/null +++ b/src/main/java/Task.java @@ -0,0 +1,31 @@ +public class Task { + protected String description; + protected boolean isDone; + + public Task(String description) { + this.description = description; + this.isDone = false; + } + + public String getStatusIcon() { + return (isDone ? "X" : " "); // mark done task with X + } + + @Override + public String toString(){ + return String.format("[%s] %s", this.getStatusIcon(), this.description); + } + + public void markAsDone(){ + this.isDone = true; + System.out.println("Nice! I've marked this task as done:"); + System.out.println(this.toString()); + } + + public void markAsUndone(){ + this.isDone = false; + System.out.println("OK, I've marked this task as not done yet:"); + System.out.println(this.toString()); + } + //... +} \ No newline at end of file From 7c0bb17b026d1dbfc4323de8017b42a5997cb45c Mon Sep 17 00:00:00 2001 From: notbingsu Date: Thu, 9 Feb 2023 22:11:13 +0800 Subject: [PATCH 05/15] lvl-4 --- src/main/java/Deadline.java | 17 +++++++++ src/main/java/Duke.java | 72 ++++++++++++++++++++++++++++++------- src/main/java/Event.java | 18 ++++++++++ src/main/java/Main.java | 58 ++++++++++++++++++------------ src/main/java/Task.java | 17 ++++----- src/main/java/Todo.java | 10 ++++++ 6 files changed, 149 insertions(+), 43 deletions(-) create mode 100644 src/main/java/Deadline.java create mode 100644 src/main/java/Event.java create mode 100644 src/main/java/Todo.java diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java new file mode 100644 index 000000000..00cf67525 --- /dev/null +++ b/src/main/java/Deadline.java @@ -0,0 +1,17 @@ +public class Deadline extends Task { + public String due; + public String[] info; + public String deadlineName; + + public Deadline(String description) { + super(description); + this.info = this.description.split("/by", 2); + this.deadlineName = info[0]; + this.due = info[1]; + } + + @Override + public String toString() { + return ("[D][" + super.getStatusIcon() + "] " + this.deadlineName) + " (by: " + this.due + ")"; + } +} diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 8ae24b829..dd48d9c21 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,28 +1,74 @@ import java.util.ArrayList; import java.util.List; - public class Duke { - private List taskList = new ArrayList(); - public void addTask(String taskName){ - Task t = new Task(taskName); + + private List taskList = new ArrayList(); + + public void greet() { + String logo = " ____ _ \n" + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; + System.out.println("Hello from\n" + logo); + + System.out.println("Hello! I'm Duke"); + System.out.println("What can I do for you?"); + } + + // public void addTask(String taskName){ + // Task t = new Task(taskName); + // taskList.add(t); + // System.out.printf( + // "Got it. I've added this task:\n" + + // String.format("added: %s\n", taskName) + + // ); + // } + + public void addEvent(String taskName) { + Event t = new Event(taskName); taskList.add(t); - System.out.printf(String.format("added: %s\n", taskName)); + System.out.printf( + "Got it. I've added this task:\n" + + t.toString() + + String.format("\nNow you have %d tasks in the list.\n", taskList.size())); } - public void changeTaskState(boolean doneState, Integer index){ - index --; - if (doneState){ + public void addTodo(String taskName) { + Todo t = new Todo(taskName); + taskList.add(t); + System.out.printf( + "Got it. I've added this task:\n" + + t.toString() + + String.format("\nNow you have %d tasks in the list.\n", taskList.size())); + } + + public void addDeadline(String taskName) { + Deadline t = new Deadline(taskName); + taskList.add(t); + System.out.printf( + "Got it. I've added this task:\n" + + t.toString() + + String.format("\nNow you have %d tasks in the list.\n", taskList.size())); + } + + public void changeTaskState(boolean doneState, Integer index) { + index--; + if (doneState) { taskList.get(index).markAsDone(); - } - else{ + } else { taskList.get(index).markAsUndone(); } } - public void list(){ - for (int i = 0; i < taskList.size(); i ++){ - System.out.printf(String.format("%d.%s\n", i + 1, taskList.get(i).toString())); + public void list() { + System.out.println("Here are the tasks in your list:"); + Integer i = 0; + for (Task task : taskList) { + System.out.printf(String.format("%d.%s\n", i + 1, task.toString())); + i++; } } } diff --git a/src/main/java/Event.java b/src/main/java/Event.java new file mode 100644 index 000000000..c242eb997 --- /dev/null +++ b/src/main/java/Event.java @@ -0,0 +1,18 @@ +public class Event extends Task { + public String startTime, endTime, eventName; + public String[] info; + + public Event(String description) { + super(description); + this.info = this.description.split("/from", 2); + this.eventName = info[0]; + this.startTime = info[1].split("/to", 2)[0]; + this.endTime = info[1].split("/to", 2)[1]; + } + + @Override + public String toString() { + return ("[E][" + super.getStatusIcon() + "] " + this.eventName) + + " (from: " + this.startTime + " to: " + this.endTime + ")"; + } +} diff --git a/src/main/java/Main.java b/src/main/java/Main.java index df2ec708b..1e7e7f7a1 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,31 +1,45 @@ import java.util.Scanner; + public class Main { public static void main(String[] args) { - - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - - System.out.println("Hello! I'm Duke"); - System.out.println("What can I do for you?"); Duke Duke = new Duke(); - Scanner userInput = new Scanner(System.in); //create Scanner object - String inputCommand = userInput.nextLine(); //read user input - while (!inputCommand.equals("bye")){ - if (inputCommand.equals("list")){ - Duke.list(); - } else if (inputCommand.split(" ")[0].equals("mark")) { - Duke.changeTaskState(true, Integer.parseInt(inputCommand.split(" ")[1])); - } else if (inputCommand.split(" ")[0].equals("unmark")) { - Duke.changeTaskState(false, Integer.parseInt(inputCommand.split(" ")[1])); - } else{ - Duke.addTask(inputCommand); - } + Duke.greet(); + Scanner userInput = new Scanner(System.in); // create Scanner object + String inputCommand; // read user input + String[] commandPhrase; + String command, phrase; + while (true) { inputCommand = userInput.nextLine(); + commandPhrase = inputCommand.split(" ", 2); + command = commandPhrase[0]; + if (commandPhrase.length < 2) { + + if (command.equals("bye")) { + break; + } + if (command.equals("list")) { + Duke.list(); + } + } else { + phrase = commandPhrase[1]; + if (command.equals("mark")) { + Duke.changeTaskState(true, Integer.parseInt(phrase)); + } + if (command.equals("unmark")) { + Duke.changeTaskState(false, Integer.parseInt(phrase)); + } + if (command.equals("event")) { + Duke.addEvent(phrase); + } + if (command.equals("todo")) { + Duke.addTodo(phrase); + } + if (command.equals("deadline")) { + Duke.addDeadline(phrase); + } + } } + userInput.close(); System.out.println("Bye. Hope to see you again soon!"); } } diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 2f796a1ed..b43c80be5 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -11,21 +11,22 @@ public String getStatusIcon() { return (isDone ? "X" : " "); // mark done task with X } - @Override - public String toString(){ - return String.format("[%s] %s", this.getStatusIcon(), this.description); - } - - public void markAsDone(){ + public void markAsDone() { this.isDone = true; System.out.println("Nice! I've marked this task as done:"); System.out.println(this.toString()); } - public void markAsUndone(){ + public void markAsUndone() { this.isDone = false; System.out.println("OK, I've marked this task as not done yet:"); System.out.println(this.toString()); } - //... + + @Override + public String toString() { + return String.format("[%s] %s", this.getStatusIcon(), this.description); + } + + // ... } \ No newline at end of file diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java new file mode 100644 index 000000000..117af94fc --- /dev/null +++ b/src/main/java/Todo.java @@ -0,0 +1,10 @@ +public class Todo extends Task { + public Todo(String description) { + super(description); + } + + @Override + public String toString() { + return ("[T][" + super.getStatusIcon() + "] " + super.description); + } +} From 1de07122ccea1ee579094560df30e079039a37ca Mon Sep 17 00:00:00 2001 From: notbingsu Date: Thu, 9 Feb 2023 22:27:29 +0800 Subject: [PATCH 06/15] lvl 5 --- src/main/java/Duke.java | 26 +++++++++++++++++--------- src/main/java/Main.java | 21 ++++++++++----------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index dd48d9c21..6548fc6c2 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -55,20 +55,28 @@ public void addDeadline(String taskName) { } public void changeTaskState(boolean doneState, Integer index) { - index--; - if (doneState) { - taskList.get(index).markAsDone(); + if (index > taskList.size()) { + System.out.println("Please input valid task number!"); } else { - taskList.get(index).markAsUndone(); + index--; + if (doneState) { + taskList.get(index).markAsDone(); + } else { + taskList.get(index).markAsUndone(); + } } } public void list() { - System.out.println("Here are the tasks in your list:"); - Integer i = 0; - for (Task task : taskList) { - System.out.printf(String.format("%d.%s\n", i + 1, task.toString())); - i++; + if (taskList.size() == 0) { + System.out.println("Task list is empty."); + } else { + System.out.println("Here are the tasks in your list:"); + Integer i = 0; + for (Task task : taskList) { + System.out.printf(String.format("%d.%s\n", i + 1, task.toString())); + i++; + } } } } diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 1e7e7f7a1..a41c7fb5d 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -13,31 +13,30 @@ public static void main(String[] args) { commandPhrase = inputCommand.split(" ", 2); command = commandPhrase[0]; if (commandPhrase.length < 2) { - if (command.equals("bye")) { break; - } - if (command.equals("list")) { + } else if (command.equals("list")) { Duke.list(); + } else { + System.out.println("Invalid command"); } } else { phrase = commandPhrase[1]; if (command.equals("mark")) { Duke.changeTaskState(true, Integer.parseInt(phrase)); - } - if (command.equals("unmark")) { + } else if (command.equals("unmark")) { Duke.changeTaskState(false, Integer.parseInt(phrase)); - } - if (command.equals("event")) { + } else if (command.equals("event")) { Duke.addEvent(phrase); - } - if (command.equals("todo")) { + } else if (command.equals("todo")) { Duke.addTodo(phrase); - } - if (command.equals("deadline")) { + } else if (command.equals("deadline")) { Duke.addDeadline(phrase); + } else { + System.out.println("Invalid command"); } } + System.out.println("------------------------------------"); } userInput.close(); System.out.println("Bye. Hope to see you again soon!"); From b1a4f2f05978bdbe13ef7d32331a67d23c4e5108 Mon Sep 17 00:00:00 2001 From: notbingsu Date: Thu, 16 Feb 2023 15:49:05 +0800 Subject: [PATCH 07/15] level-6, delete --- duke.txt | 0 src/main/java/Deadline.java | 5 +++ src/main/java/Duke.java | 73 +++++++++++++++++++++++++++++++++++++ src/main/java/Event.java | 5 +++ src/main/java/Main.java | 3 ++ src/main/java/Task.java | 4 ++ src/main/java/Todo.java | 5 +++ 7 files changed, 95 insertions(+) create mode 100644 duke.txt diff --git a/duke.txt b/duke.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index 00cf67525..4c8955629 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -10,6 +10,11 @@ public Deadline(String description) { this.due = info[1]; } + @Override + public String fileFormat() { + return (String.format("D|%b|%s by %s", super.isDone, this.deadlineName, this.due)); + } + @Override public String toString() { return ("[D][" + super.getStatusIcon() + "] " + this.deadlineName) + " (by: " + this.due + ")"; diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 6548fc6c2..a715421ed 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,9 +1,14 @@ import java.util.ArrayList; import java.util.List; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Scanner; public class Duke { private List taskList = new ArrayList(); + private static String fileName = "duke.txt"; public void greet() { String logo = " ____ _ \n" @@ -14,6 +19,7 @@ public void greet() { System.out.println("Hello from\n" + logo); System.out.println("Hello! I'm Duke"); + pullFileData(); System.out.println("What can I do for you?"); } @@ -67,6 +73,18 @@ public void changeTaskState(boolean doneState, Integer index) { } } + public void delete(int index) { + if (index > taskList.size()) { + System.out.println("Please input valid task number!"); + } else { + index--; + System.out.printf("Noted. I've removed this task:" + + taskList.get(index).toString()); + taskList.remove(index); + System.out.println(String.format("\nNow you have %d tasks in the list.\n", taskList.size())); + } + } + public void list() { if (taskList.size() == 0) { System.out.println("Task list is empty."); @@ -79,4 +97,59 @@ public void list() { } } } + + private void pullFileData() { + File file = new File(fileName); + String data; + try { + if (!file.createNewFile()) { + Scanner fileData = new Scanner(file); + while (fileData.hasNext()) { + data = fileData.nextLine(); + String[] inputArgs = data.split("|"); + addFileData(inputArgs); + } + fileData.close(); + } + } catch (IOException e) { + System.out.print("\nError getting file data"); + } + System.out.println("These are the tasks from your file:\n"); + list(); + } + + private void addFileData(String[] inputArgs) { + Task newTask; + String command = inputArgs[0]; + boolean taskStatus = Boolean.parseBoolean(inputArgs[1]); + switch (command) { + case "T": + newTask = new Todo(inputArgs[2]); + break; + case "D": + newTask = new Deadline(inputArgs[2]); + break; + case "E": + newTask = new Event(inputArgs[2]); + break; + default: + throw new IllegalStateException("File contents are invalid"); + } + if (taskStatus) { + newTask.markAsDone(); + } + taskList.add(newTask); + } + + public void saveToFile() { + try { + FileWriter fWriter = new FileWriter(fileName); + for (Task task : taskList) { + fWriter.write(task.fileFormat()); + } + fWriter.close(); + } catch (IOException e) { + System.out.print("IOException Error: data not saved to file\n"); + } + } } diff --git a/src/main/java/Event.java b/src/main/java/Event.java index c242eb997..1f5c53bd9 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -10,6 +10,11 @@ public Event(String description) { this.endTime = info[1].split("/to", 2)[1]; } + @Override + public String fileFormat() { + return (String.format("E|%b|%s /from %s /to %s", super.isDone, this.eventName, this.startTime, this.endTime)); + } + @Override public String toString() { return ("[E][" + super.getStatusIcon() + "] " + this.eventName) + diff --git a/src/main/java/Main.java b/src/main/java/Main.java index a41c7fb5d..c8716d312 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -32,10 +32,13 @@ public static void main(String[] args) { Duke.addTodo(phrase); } else if (command.equals("deadline")) { Duke.addDeadline(phrase); + } else if (command.equals("delete")) { + Duke.delete(Integer.parseInt(phrase)); } else { System.out.println("Invalid command"); } } + Duke.saveToFile(); System.out.println("------------------------------------"); } userInput.close(); diff --git a/src/main/java/Task.java b/src/main/java/Task.java index b43c80be5..5248c41e7 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -23,6 +23,10 @@ public void markAsUndone() { System.out.println(this.toString()); } + public String fileFormat() { + return (String.format(" |%b|%s", this.isDone, this.description)); + } + @Override public String toString() { return String.format("[%s] %s", this.getStatusIcon(), this.description); diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java index 117af94fc..fd4b0e9c0 100644 --- a/src/main/java/Todo.java +++ b/src/main/java/Todo.java @@ -7,4 +7,9 @@ public Todo(String description) { public String toString() { return ("[T][" + super.getStatusIcon() + "] " + super.description); } + + @Override + public String fileFormat() { + return (String.format("T|%b|%s", super.isDone, this.description)); + } } From 4d2a3938edb1e778c793696de5c0530c9d66a8cd Mon Sep 17 00:00:00 2001 From: notbingsu Date: Tue, 28 Feb 2023 15:54:32 +0800 Subject: [PATCH 08/15] A-jar --- ip.jar | Bin 0 -> 7621 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ip.jar diff --git a/ip.jar b/ip.jar new file mode 100644 index 0000000000000000000000000000000000000000..81eeb1ecea44e4d76068e993b15a5dfa02bf380e GIT binary patch literal 7621 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%0D*P%)-_~=h>izCaqPYq-&=C* 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 literal 0 HcmV?d00001 From a236c3b0022bf3f68c093af1cb8b5aabb0abeb13 Mon Sep 17 00:00:00 2001 From: notbingsu Date: Tue, 28 Feb 2023 17:48:17 +0800 Subject: [PATCH 09/15] A-moreOOP --- src/main/java/Duke.java | 147 +++--------------------------------- src/main/java/Main.java | 19 +++-- src/main/java/Storage.java | 28 +++++++ src/main/java/TaskList.java | 119 +++++++++++++++++++++++++++++ src/main/java/UI.java | 17 +++++ 5 files changed, 182 insertions(+), 148 deletions(-) create mode 100644 src/main/java/Storage.java create mode 100644 src/main/java/TaskList.java create mode 100644 src/main/java/UI.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index a715421ed..09041e46d 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,26 +1,16 @@ -import java.util.ArrayList; -import java.util.List; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Scanner; - public class Duke { - private List taskList = new ArrayList(); private static String fileName = "duke.txt"; + private Storage storage; + private UI ui; + public TaskList tasks; - public void greet() { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - - System.out.println("Hello! I'm Duke"); - pullFileData(); - System.out.println("What can I do for you?"); + public Duke() { + ui = new UI(); + ui.greet(); + storage = new Storage(fileName); + tasks = new TaskList(); + tasks.Tasklist(storage.load()); } // public void addTask(String taskName){ @@ -33,123 +23,4 @@ public void greet() { // ); // } - public void addEvent(String taskName) { - Event t = new Event(taskName); - taskList.add(t); - System.out.printf( - "Got it. I've added this task:\n" + - t.toString() + - String.format("\nNow you have %d tasks in the list.\n", taskList.size())); - } - - public void addTodo(String taskName) { - Todo t = new Todo(taskName); - taskList.add(t); - System.out.printf( - "Got it. I've added this task:\n" + - t.toString() + - String.format("\nNow you have %d tasks in the list.\n", taskList.size())); - } - - public void addDeadline(String taskName) { - Deadline t = new Deadline(taskName); - taskList.add(t); - System.out.printf( - "Got it. I've added this task:\n" + - t.toString() + - String.format("\nNow you have %d tasks in the list.\n", taskList.size())); - } - - public void changeTaskState(boolean doneState, Integer index) { - if (index > taskList.size()) { - System.out.println("Please input valid task number!"); - } else { - index--; - if (doneState) { - taskList.get(index).markAsDone(); - } else { - taskList.get(index).markAsUndone(); - } - } - } - - public void delete(int index) { - if (index > taskList.size()) { - System.out.println("Please input valid task number!"); - } else { - index--; - System.out.printf("Noted. I've removed this task:" + - taskList.get(index).toString()); - taskList.remove(index); - System.out.println(String.format("\nNow you have %d tasks in the list.\n", taskList.size())); - } - } - - public void list() { - if (taskList.size() == 0) { - System.out.println("Task list is empty."); - } else { - System.out.println("Here are the tasks in your list:"); - Integer i = 0; - for (Task task : taskList) { - System.out.printf(String.format("%d.%s\n", i + 1, task.toString())); - i++; - } - } - } - - private void pullFileData() { - File file = new File(fileName); - String data; - try { - if (!file.createNewFile()) { - Scanner fileData = new Scanner(file); - while (fileData.hasNext()) { - data = fileData.nextLine(); - String[] inputArgs = data.split("|"); - addFileData(inputArgs); - } - fileData.close(); - } - } catch (IOException e) { - System.out.print("\nError getting file data"); - } - System.out.println("These are the tasks from your file:\n"); - list(); - } - - private void addFileData(String[] inputArgs) { - Task newTask; - String command = inputArgs[0]; - boolean taskStatus = Boolean.parseBoolean(inputArgs[1]); - switch (command) { - case "T": - newTask = new Todo(inputArgs[2]); - break; - case "D": - newTask = new Deadline(inputArgs[2]); - break; - case "E": - newTask = new Event(inputArgs[2]); - break; - default: - throw new IllegalStateException("File contents are invalid"); - } - if (taskStatus) { - newTask.markAsDone(); - } - taskList.add(newTask); - } - - public void saveToFile() { - try { - FileWriter fWriter = new FileWriter(fileName); - for (Task task : taskList) { - fWriter.write(task.fileFormat()); - } - fWriter.close(); - } catch (IOException e) { - System.out.print("IOException Error: data not saved to file\n"); - } - } } diff --git a/src/main/java/Main.java b/src/main/java/Main.java index c8716d312..5746117d0 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -3,7 +3,6 @@ public class Main { public static void main(String[] args) { Duke Duke = new Duke(); - Duke.greet(); Scanner userInput = new Scanner(System.in); // create Scanner object String inputCommand; // read user input String[] commandPhrase; @@ -16,30 +15,30 @@ public static void main(String[] args) { if (command.equals("bye")) { break; } else if (command.equals("list")) { - Duke.list(); + Duke.tasks.list(); } else { System.out.println("Invalid command"); } } else { phrase = commandPhrase[1]; if (command.equals("mark")) { - Duke.changeTaskState(true, Integer.parseInt(phrase)); + Duke.tasks.changeTaskState(true, Integer.parseInt(phrase)); } else if (command.equals("unmark")) { - Duke.changeTaskState(false, Integer.parseInt(phrase)); + Duke.tasks.changeTaskState(false, Integer.parseInt(phrase)); } else if (command.equals("event")) { - Duke.addEvent(phrase); + Duke.tasks.addEvent(phrase); } else if (command.equals("todo")) { - Duke.addTodo(phrase); + Duke.tasks.addTodo(phrase); } else if (command.equals("deadline")) { - Duke.addDeadline(phrase); + Duke.tasks.addDeadline(phrase); } else if (command.equals("delete")) { - Duke.delete(Integer.parseInt(phrase)); + Duke.tasks.delete(Integer.parseInt(phrase)); } else { System.out.println("Invalid command"); } } - Duke.saveToFile(); - System.out.println("------------------------------------"); + Storage.saveToFile(); + UI.horizontalLine(); } userInput.close(); System.out.println("Bye. Hope to see you again soon!"); diff --git a/src/main/java/Storage.java b/src/main/java/Storage.java new file mode 100644 index 000000000..0c3a48435 --- /dev/null +++ b/src/main/java/Storage.java @@ -0,0 +1,28 @@ +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +public class Storage { + protected static String fileName; + + public Storage(String inputFileName) { + fileName = inputFileName; + } + + public File load() { + File file = new File(fileName); + return file; + } + + public static void saveToFile() { + try { + FileWriter fWriter = new FileWriter(fileName); + for (Task task : TaskList.returnTaskList()) { + fWriter.write(task.fileFormat()); + } + fWriter.close(); + } catch (IOException e) { + System.out.print("IOException Error: data not saved to file\n"); + } + } +} diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java new file mode 100644 index 000000000..8a33d929e --- /dev/null +++ b/src/main/java/TaskList.java @@ -0,0 +1,119 @@ +import java.util.ArrayList; +import java.util.List; +import java.io.File; +import java.util.Scanner; +import java.io.IOException; + +public class TaskList { + private static List taskList = new ArrayList(); + + public void Tasklist(File file) { + String data; + try { + if (!file.createNewFile()) { + Scanner fileData = new Scanner(file); + while (fileData.hasNext()) { + data = fileData.nextLine(); + String[] inputArgs = data.split("|"); + addFileData(inputArgs); + } + fileData.close(); + } + } catch (IOException e) { + System.out.print("\nError getting file data"); + } + System.out.println("These are the tasks from your file:\n"); + } + + private static void addFileData(String[] inputArgs) { + Task newTask; + String command = inputArgs[0]; + boolean taskStatus = Boolean.parseBoolean(inputArgs[1]); + switch (command) { + case "T": + newTask = new Todo(inputArgs[2]); + break; + case "D": + newTask = new Deadline(inputArgs[2]); + break; + case "E": + newTask = new Event(inputArgs[2]); + break; + default: + throw new IllegalStateException("File contents are invalid"); + } + if (taskStatus) { + newTask.markAsDone(); + } + taskList.add(newTask); + } + + public static List returnTaskList() { + return taskList; + } + + public void addEvent(String taskName) { + Event t = new Event(taskName); + taskList.add(t); + System.out.printf( + "Got it. I've added this task:\n" + + t.toString() + + String.format("\nNow you have %d tasks in the list.\n", taskList.size())); + } + + public void addTodo(String taskName) { + Todo t = new Todo(taskName); + taskList.add(t); + System.out.printf( + "Got it. I've added this task:\n" + + t.toString() + + String.format("\nNow you have %d tasks in the list.\n", taskList.size())); + } + + public void addDeadline(String taskName) { + Deadline t = new Deadline(taskName); + taskList.add(t); + System.out.printf( + "Got it. I've added this task:\n" + + t.toString() + + String.format("\nNow you have %d tasks in the list.\n", taskList.size())); + } + + public void changeTaskState(boolean doneState, Integer index) { + if (index > taskList.size()) { + System.out.println("Please input valid task number!"); + } else { + index--; + if (doneState) { + taskList.get(index).markAsDone(); + } else { + taskList.get(index).markAsUndone(); + } + } + } + + public void delete(int index) { + if (index > taskList.size()) { + System.out.println("Please input valid task number!"); + } else { + index--; + System.out.printf("Noted. I've removed this task:" + + taskList.get(index).toString()); + taskList.remove(index); + System.out.println(String.format("\nNow you have %d tasks in the list.\n", taskList.size())); + } + } + + public void list() { + if (taskList.size() == 0) { + System.out.println("Task list is empty."); + } else { + System.out.println("Here are the tasks in your list:"); + Integer i = 0; + for (Task task : taskList) { + System.out.printf(String.format("%d.%s\n", i + 1, task.toString())); + i++; + } + } + } +} diff --git a/src/main/java/UI.java b/src/main/java/UI.java new file mode 100644 index 000000000..0acb918af --- /dev/null +++ b/src/main/java/UI.java @@ -0,0 +1,17 @@ +public class UI { + public void greet() { + String logo = " ____ _ \n" + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; + System.out.println("Hello from\n" + logo); + + System.out.println("Hello! I'm Duke"); + System.out.println("What can I do for you?"); + } + + public static void horizontalLine() { + System.out.println("------------------------------------"); + } +} From 139839d396acbccabe8c0ebeeebcebdea4c39d4a Mon Sep 17 00:00:00 2001 From: notbingsu Date: Thu, 2 Mar 2023 22:58:34 +0800 Subject: [PATCH 10/15] level-8, dates and times, overdue list --- src/main/java/Deadline.java | 12 +++++++++--- src/main/java/TaskList.java | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index 4c8955629..974888550 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -1,5 +1,10 @@ +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; +//import java.time.temporal.ChronoUnit; + public class Deadline extends Task { - public String due; + public LocalDate due; public String[] info; public String deadlineName; @@ -7,12 +12,13 @@ public Deadline(String description) { super(description); this.info = this.description.split("/by", 2); this.deadlineName = info[0]; - this.due = info[1]; + this.due = LocalDate.parse(info[1]); } @Override public String fileFormat() { - return (String.format("D|%b|%s by %s", super.isDone, this.deadlineName, this.due)); + return (String.format("D|%b|%s by %s", super.isDone, this.deadlineName, + due.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)))); } @Override diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index 8a33d929e..ad3198dd2 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -116,4 +116,19 @@ public void list() { } } } + + public void listOverdue() { + if (taskList.size() == 0) { + System.out.println("Task list is empty."); + } else { + System.out.println("Here are the overdue deadlines in your list:"); + Integer i = 0; + for (Task task : taskList) { + if (task instanceof Deadline & ((Deadline) task).isOverdue) { + System.out.printf(String.format("%d.%s\n", i + 1, task.toString())); + i++; + } + } + } + } } From ca892092e584a1e57fba29c8b699fc859a3d44dc Mon Sep 17 00:00:00 2001 From: notbingsu Date: Fri, 3 Mar 2023 01:09:23 +0800 Subject: [PATCH 11/15] level-9, find --- src/main/java/Deadline.java | 2 ++ src/main/java/Main.java | 3 +++ src/main/java/TaskList.java | 15 +++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index 974888550..813e108a7 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -7,12 +7,14 @@ public class Deadline extends Task { public LocalDate due; public String[] info; public String deadlineName; + public boolean isOverdue; public Deadline(String description) { super(description); this.info = this.description.split("/by", 2); this.deadlineName = info[0]; this.due = LocalDate.parse(info[1]); + this.isOverdue = due.isAfter(LocalDate.now()); } @Override diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 5746117d0..430b55f0f 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -33,6 +33,9 @@ public static void main(String[] args) { Duke.tasks.addDeadline(phrase); } else if (command.equals("delete")) { Duke.tasks.delete(Integer.parseInt(phrase)); + + } else if (command.equals("find")) { + Duke.tasks.find(phrase); } else { System.out.println("Invalid command"); } diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index ad3198dd2..dc5921dab 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -131,4 +131,19 @@ public void listOverdue() { } } } + + public void find(String keyword) { + if (taskList.size() == 0) { + System.out.println("Task list is empty."); + } else { + System.out.println("Here are the matching tasks in your list:"); + Integer i = 0; + for (Task task : taskList) { + if (task.description.contains(keyword)) { + System.out.printf(String.format("%d.%s\n", i + 1, task.toString())); + i++; + } + } + } + } } From ae6010a2d2dad24db2f80b52b78cf7ae2b480f48 Mon Sep 17 00:00:00 2001 From: notbingsu Date: Fri, 3 Mar 2023 02:24:16 +0800 Subject: [PATCH 12/15] Javadoc of methods and classes --- src/main/java/Deadline.java | 4 ++++ src/main/java/Duke.java | 4 ++++ src/main/java/Event.java | 4 ++++ src/main/java/Main.java | 6 ++++++ src/main/java/Storage.java | 14 ++++++++++++++ src/main/java/Task.java | 4 ++++ src/main/java/TaskList.java | 28 ++++++++++++++++++++++++++++ src/main/java/Todo.java | 4 ++++ src/main/java/UI.java | 6 ++++++ 9 files changed, 74 insertions(+) diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index 813e108a7..4c1d6a322 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -3,6 +3,10 @@ import java.time.format.FormatStyle; //import java.time.temporal.ChronoUnit; +/* + * Sub-class of super-class Task, represents a task that has a deadline, + * Contains attributes due, info, deadline name and evaluates attribute whether Deadline task is overdue + */ public class Deadline extends Task { public LocalDate due; public String[] info; diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 09041e46d..0ea914d0e 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,3 +1,7 @@ +/* + * Duke is an instance of the bot which has several subclasses, + * storage for file management, ui for communicating with user for input/output, tasklist for managing tasks and task-related commands + */ public class Duke { private static String fileName = "duke.txt"; diff --git a/src/main/java/Event.java b/src/main/java/Event.java index 1f5c53bd9..7be1b8b4e 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -1,3 +1,7 @@ +/* + * Sub-class of super-class Task, represents a task that is an event, + * Contains attributes event name, start and end time + */ public class Event extends Task { public String startTime, endTime, eventName; public String[] info; diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 430b55f0f..ea8317f27 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,5 +1,11 @@ import java.util.Scanner; +/* + * Initialises Duke class + * If earlier written file exists, displays files + * Continuously promtps user for input until specified terminating input is received + * List of inputs include bye, list, mark, unmark, event, todo, deadline, delete, find + */ public class Main { public static void main(String[] args) { Duke Duke = new Duke(); diff --git a/src/main/java/Storage.java b/src/main/java/Storage.java index 0c3a48435..aa972e87e 100644 --- a/src/main/java/Storage.java +++ b/src/main/java/Storage.java @@ -2,6 +2,9 @@ import java.io.FileWriter; import java.io.IOException; +/* + * Storage class handles all file methods of Duke, it only has the attribute fileName + */ public class Storage { protected static String fileName; @@ -9,11 +12,22 @@ public Storage(String inputFileName) { fileName = inputFileName; } + /* + * Loads file from location specified by fileName + * + * @param none + * + * @return File object file from the location + */ public File load() { File file = new File(fileName); return file; } + /* + * Saves file to destination specified by fileName, the same + * location where file is retrieved from + */ public static void saveToFile() { try { FileWriter fWriter = new FileWriter(fileName); diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 5248c41e7..d51c2b50e 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -1,3 +1,7 @@ +/* + * Superclass Task extends to subtasks Deadline, Event and Todo + * Task has 2 attributes, description and isDone, which toggles whether the task is done or not done + */ public class Task { protected String description; protected boolean isDone; diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index dc5921dab..f4084e0d9 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -4,9 +4,22 @@ import java.util.Scanner; import java.io.IOException; +/* + * TaskList is the class of Duke which contains the list of tasks and methods to makes changes to the list + * It contains only the ArrayList taskList + */ public class TaskList { private static List taskList = new ArrayList(); + /* + * Writes file data from file scanned from file to taskList object + * Uses Scanner to read contents from file, splits content into + * String[] + * + * @param File file with contents of previously created tasklist + * + * @throws IOException if file data is not formatted as specified + */ public void Tasklist(File file) { String data; try { @@ -25,6 +38,10 @@ public void Tasklist(File file) { System.out.println("These are the tasks from your file:\n"); } + /* + * Formats file data retrieved by Tasklist, parses String[] and adds them to + * taskList as Todo, Event or Deadline subclasses + */ private static void addFileData(String[] inputArgs) { Task newTask; String command = inputArgs[0]; @@ -104,6 +121,9 @@ public void delete(int index) { } } + /* + * Main list method, lists all contents of tasklist + */ public void list() { if (taskList.size() == 0) { System.out.println("Task list is empty."); @@ -117,6 +137,9 @@ public void list() { } } + /* + * Lists overdue deadline subclass objects in tasklist + */ public void listOverdue() { if (taskList.size() == 0) { System.out.println("Task list is empty."); @@ -132,6 +155,11 @@ public void listOverdue() { } } + /* + * lists all tasks in task list containing keyword + * + * @param keyword to be searched for + */ public void find(String keyword) { if (taskList.size() == 0) { System.out.println("Task list is empty."); diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java index fd4b0e9c0..f4ee7f065 100644 --- a/src/main/java/Todo.java +++ b/src/main/java/Todo.java @@ -1,3 +1,7 @@ +/* + * Sub-class of super-class Task, represents a todo task, + * only inherits task description attribute from parent Task class + */ public class Todo extends Task { public Todo(String description) { super(description); diff --git a/src/main/java/UI.java b/src/main/java/UI.java index 0acb918af..32a6623fc 100644 --- a/src/main/java/UI.java +++ b/src/main/java/UI.java @@ -1,4 +1,10 @@ +/* + * UI class contains methods that interact with user through text + */ public class UI { + /* + * Prints greeting statement and logo to terminal + */ public void greet() { String logo = " ____ _ \n" + "| _ \\ _ _| | _____ \n" From e2c929eeedacefdc033ebedbc69a80e7711775a0 Mon Sep 17 00:00:00 2001 From: notbingsu Date: Tue, 7 Mar 2023 02:20:32 +0800 Subject: [PATCH 13/15] User guide --- docs/README.md | 75 +++++++++++++++++++++++++++++++++-------- src/main/java/Main.java | 4 ++- 2 files changed, 64 insertions(+), 15 deletions(-) diff --git a/docs/README.md b/docs/README.md index 8077118eb..56f00b08d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,29 +1,76 @@ # User Guide -## Features +## Features -### Feature-ABC +Users can add, mark, unmark, list tasks as needed. -Description of the feature. +### Add task -### Feature-XYZ +Users can add new tasks to the list. Tasks have 3 available types, Event, Todo and Deadline -Description of the feature. +Format: `type of task` `name of task` date-attribute of task +Example: deadline do tutorial /by Sunday -## Usage +Expected outcome: +New tasks of correct type and description is added to task list + +### Mark task + +Users can mark tasks as done. + +Format: mark `task index` +Example: mark 3 + +Expected outcome: +[ ] state of task(s) changes to [x] when marked as done. + +### Unmark task + +Users can mark tasks as undone. + +Format: unmark `task index` +Example: mark 3 + +Expected outcome: +[x] state of task(s) changes to [ ] when marked as done. -### `Keyword` - Describe action +### List task(s) -Describe the action and its outcome. +Users can list and view all tasks currently in the task list -Example of usage: +Format: list -`keyword (optional arguments)` +Expected outcome: +If task list is empty, "Tasklist is empty." +Indexed list of `index`, `done state`, `description` + +### List overdue task(s) + +Users can list and view all tasks that are currently overdue in the task list + +Format: list overdue Expected outcome: +If task list is empty, "Tasklist is empty." +Indexed list of overdue tasks `index`, `done state`, `description` + +### Find + +Users can find and list all tasks by inputting keyword to be searched -Description of the outcome. +Format: find `string to be searched` +Example: find food -``` -expected output -``` +Expected outcome: +If task lsit is empty, "Tasklist is empty." +Indexed list of tasks with description containing searched string + +### Delete + +Users can remove tasks from task list +Format: delete `index` +Example: delete 3 + +Expected outcome: +If index out of bounds, "Please input valid task number!" +"Noted. I've removed this task:" `index` diff --git a/src/main/java/Main.java b/src/main/java/Main.java index ea8317f27..ef8631b14 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -39,9 +39,11 @@ public static void main(String[] args) { Duke.tasks.addDeadline(phrase); } else if (command.equals("delete")) { Duke.tasks.delete(Integer.parseInt(phrase)); - } else if (command.equals("find")) { Duke.tasks.find(phrase); + } else if (command.equals("overdue")) { + Duke.tasks.listOverdue(); + ; } else { System.out.println("Invalid command"); } From 4a25668f2c9cbde9591da5558b96e05216b2c9ed Mon Sep 17 00:00:00 2001 From: notbingsu Date: Tue, 21 Mar 2023 04:06:44 +0800 Subject: [PATCH 14/15] revised, bug fixes, overdue feature bug fixes --- docs/README.md | 28 +++++++++++ duke.txt | 1 + ip.jar | Bin 7621 -> 10112 bytes src/main/java/Deadline.java | 37 ++++++++++++-- src/main/java/Duke.java | 10 ++-- src/main/java/Event.java | 2 +- src/main/java/Main.java | 9 ++-- src/main/java/Storage.java | 52 +++++++++++++++++--- src/main/java/TaskList.java | 95 ++++++++++++------------------------ src/main/java/Todo.java | 2 +- src/main/java/UI.java | 4 +- 11 files changed, 153 insertions(+), 87 deletions(-) diff --git a/docs/README.md b/docs/README.md index 56f00b08d..28a158314 100644 --- a/docs/README.md +++ b/docs/README.md @@ -14,6 +14,34 @@ Example: deadline do tutorial /by Sunday Expected outcome: New tasks of correct type and description is added to task list +### Add Todo (task subclass) + +Users can add todo tasks to the list. + +Format: todo `name of task` +Example: todo eat + +Expected: task of type T is added to task list + +### Add Event (task subclass) + +Users can add Events to the list. + +Format: event `name of event` /from `start time` /to `end time` +Example: event eat /from morning /to night + +Expected: task of type E is added to task list + +### Add Deadline (task subclass) + +Users can add Deadline to the list. + +Format: deadline `name of deadline` /by `due date` +Example (correct LocalDate format): deadline return books /by 2022-03-05 +Example (incorrect LocalDate format): deadline return books /by next week + +Expected: task of type D is added to task list, user is alerted if date was not stored as LocalDate format + ### Mark task Users can mark tasks as done. diff --git a/duke.txt b/duke.txt index e69de29bb..e2aae9be5 100644 --- a/duke.txt +++ b/duke.txt @@ -0,0 +1 @@ +D|false|eat /by tmr diff --git a/ip.jar b/ip.jar index 81eeb1ecea44e4d76068e993b15a5dfa02bf380e..042e851eace9df70e61bc8498bbf0085f99baa39 100644 GIT binary patch literal 10112 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 E2Qdr+egFUf literal 7621 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%0D*P%)-_~=h>izCaqPYq-&=C* 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 diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index 4c1d6a322..6efbb53fd 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -9,6 +9,7 @@ */ public class Deadline extends Task { public LocalDate due; + public String dueText; public String[] info; public String deadlineName; public boolean isOverdue; @@ -17,18 +18,44 @@ public Deadline(String description) { super(description); this.info = this.description.split("/by", 2); this.deadlineName = info[0]; - this.due = LocalDate.parse(info[1]); - this.isOverdue = due.isAfter(LocalDate.now()); + this.due = isValid((info[1]).trim()); + if (this.due == null) { + this.dueText = (info[1]).trim(); + System.out.println("Due date is not in yyyy-MM-dd format, will be saved as text"); + } else if (this.due.isBefore(LocalDate.now())) { + this.isOverdue = true; + } + + } + + private LocalDate isValid(String date) { + try { + return LocalDate.parse(date); + } catch (Exception e) { + return null; + } } @Override public String fileFormat() { - return (String.format("D|%b|%s by %s", super.isDone, this.deadlineName, - due.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)))); + DateTimeFormatter yyyyMMdd = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + if (this.due != null) { + return (String.format("D|%b|%s /by %s\n", super.isDone, this.deadlineName, + due.format(yyyyMMdd))); + } else { + return (String.format("D|%b|%s /by %s\n", super.isDone, this.deadlineName, this.dueText)); + } } @Override public String toString() { - return ("[D][" + super.getStatusIcon() + "] " + this.deadlineName) + " (by: " + this.due + ")"; + DateTimeFormatter yyyyMMdd = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + if (this.due != null) { + return ("[D][" + super.getStatusIcon() + "] " + this.deadlineName) + + " (by: " + this.due.format(yyyyMMdd) + ")"; + } else { + return ("[D][" + super.getStatusIcon() + "] " + this.deadlineName) + + " (by: " + this.dueText + ")"; + } } } diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 0ea914d0e..78852b3d1 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -4,17 +4,17 @@ */ public class Duke { - private static String fileName = "duke.txt"; - private Storage storage; + private String fileName = "duke.txt"; + public Storage storage; private UI ui; public TaskList tasks; public Duke() { ui = new UI(); - ui.greet(); storage = new Storage(fileName); - tasks = new TaskList(); - tasks.Tasklist(storage.load()); + this.tasks = new TaskList(); + storage.load(tasks); + ui.greet(tasks); } // public void addTask(String taskName){ diff --git a/src/main/java/Event.java b/src/main/java/Event.java index 7be1b8b4e..8da2927df 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -16,7 +16,7 @@ public Event(String description) { @Override public String fileFormat() { - return (String.format("E|%b|%s /from %s /to %s", super.isDone, this.eventName, this.startTime, this.endTime)); + return (String.format("E|%b|%s /from %s /to %s\n", super.isDone, this.eventName, this.startTime, this.endTime)); } @Override diff --git a/src/main/java/Main.java b/src/main/java/Main.java index ef8631b14..fe0329cbb 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -20,8 +20,12 @@ public static void main(String[] args) { if (commandPhrase.length < 2) { if (command.equals("bye")) { break; + } else if (command.equals("clear")) { + Duke.tasks.clearTaskList(); } else if (command.equals("list")) { Duke.tasks.list(); + } else if (command.equals("overdue")) { + Duke.tasks.listOverdue(); } else { System.out.println("Invalid command"); } @@ -41,14 +45,11 @@ public static void main(String[] args) { Duke.tasks.delete(Integer.parseInt(phrase)); } else if (command.equals("find")) { Duke.tasks.find(phrase); - } else if (command.equals("overdue")) { - Duke.tasks.listOverdue(); - ; } else { System.out.println("Invalid command"); } } - Storage.saveToFile(); + Duke.storage.saveToFile(Duke.tasks); UI.horizontalLine(); } userInput.close(); diff --git a/src/main/java/Storage.java b/src/main/java/Storage.java index aa972e87e..bd59f55e4 100644 --- a/src/main/java/Storage.java +++ b/src/main/java/Storage.java @@ -1,15 +1,17 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.util.Scanner; +import java.util.ArrayList; /* * Storage class handles all file methods of Duke, it only has the attribute fileName */ public class Storage { - protected static String fileName; + private String fileName; public Storage(String inputFileName) { - fileName = inputFileName; + this.fileName = inputFileName; } /* @@ -19,19 +21,57 @@ public Storage(String inputFileName) { * * @return File object file from the location */ - public File load() { + public void load(TaskList taskList) { File file = new File(fileName); - return file; + String data; + try { + if (!file.createNewFile()) { + Scanner fileData = new Scanner(file); + while (fileData.hasNext()) { + data = fileData.nextLine(); + String[] inputArgs = data.split("\\|"); + addFileData(inputArgs, taskList); + for (String arg : inputArgs) { + System.out.print(arg + " "); + } + } + } + } catch (IOException e) { + System.out.print("\nError getting file data"); + } + } + + public void addFileData(String[] inputArgs, TaskList taskList) { + Task newTask; + String command = inputArgs[0]; + boolean taskStatus = Boolean.parseBoolean(inputArgs[1]); + switch (command) { + case "T": + newTask = new Todo(inputArgs[2]); + break; + case "D": + newTask = new Deadline(inputArgs[2]); + break; + case "E": + newTask = new Event(inputArgs[2]); + break; + default: + throw new IllegalStateException("File contents are invalid"); + } + if (taskStatus) { + newTask.markAsDone(); + } + taskList.returnTaskList().add(newTask); } /* * Saves file to destination specified by fileName, the same * location where file is retrieved from */ - public static void saveToFile() { + public void saveToFile(TaskList taskList) { try { FileWriter fWriter = new FileWriter(fileName); - for (Task task : TaskList.returnTaskList()) { + for (Task task : taskList.returnTaskList()) { fWriter.write(task.fileFormat()); } fWriter.close(); diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index f4084e0d9..6f1a59492 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -6,13 +6,13 @@ /* * TaskList is the class of Duke which contains the list of tasks and methods to makes changes to the list - * It contains only the ArrayList taskList + * It contains only the ArrayList tasks */ public class TaskList { - private static List taskList = new ArrayList(); + private List tasks = new ArrayList(); /* - * Writes file data from file scanned from file to taskList object + * Writes file data from file scanned from file to tasks object * Uses Scanner to read contents from file, splits content into * String[] * @@ -20,104 +20,73 @@ public class TaskList { * * @throws IOException if file data is not formatted as specified */ - public void Tasklist(File file) { - String data; - try { - if (!file.createNewFile()) { - Scanner fileData = new Scanner(file); - while (fileData.hasNext()) { - data = fileData.nextLine(); - String[] inputArgs = data.split("|"); - addFileData(inputArgs); - } - fileData.close(); - } - } catch (IOException e) { - System.out.print("\nError getting file data"); - } - System.out.println("These are the tasks from your file:\n"); + public void Tasklist() { + this.tasks = new ArrayList(); } /* * Formats file data retrieved by Tasklist, parses String[] and adds them to - * taskList as Todo, Event or Deadline subclasses + * tasks as Todo, Event or Deadline subclasses */ - private static void addFileData(String[] inputArgs) { - Task newTask; - String command = inputArgs[0]; - boolean taskStatus = Boolean.parseBoolean(inputArgs[1]); - switch (command) { - case "T": - newTask = new Todo(inputArgs[2]); - break; - case "D": - newTask = new Deadline(inputArgs[2]); - break; - case "E": - newTask = new Event(inputArgs[2]); - break; - default: - throw new IllegalStateException("File contents are invalid"); - } - if (taskStatus) { - newTask.markAsDone(); - } - taskList.add(newTask); + + public List returnTaskList() { + return tasks; } - public static List returnTaskList() { - return taskList; + public void clearTaskList() { + tasks.clear(); + System.out.println("Task list cleared!"); } public void addEvent(String taskName) { Event t = new Event(taskName); - taskList.add(t); + tasks.add(t); System.out.printf( "Got it. I've added this task:\n" + t.toString() + - String.format("\nNow you have %d tasks in the list.\n", taskList.size())); + String.format("\nNow you have %d tasks in the list.\n", tasks.size())); } public void addTodo(String taskName) { Todo t = new Todo(taskName); - taskList.add(t); + tasks.add(t); System.out.printf( "Got it. I've added this task:\n" + t.toString() + - String.format("\nNow you have %d tasks in the list.\n", taskList.size())); + String.format("\nNow you have %d tasks in the list.\n", tasks.size())); } public void addDeadline(String taskName) { Deadline t = new Deadline(taskName); - taskList.add(t); + tasks.add(t); System.out.printf( "Got it. I've added this task:\n" + t.toString() + - String.format("\nNow you have %d tasks in the list.\n", taskList.size())); + String.format("\nNow you have %d tasks in the list.\n", tasks.size())); } public void changeTaskState(boolean doneState, Integer index) { - if (index > taskList.size()) { + if (index > tasks.size() || index < 1) { System.out.println("Please input valid task number!"); } else { index--; if (doneState) { - taskList.get(index).markAsDone(); + tasks.get(index).markAsDone(); } else { - taskList.get(index).markAsUndone(); + tasks.get(index).markAsUndone(); } } } public void delete(int index) { - if (index > taskList.size()) { + if (index > tasks.size() || index < 1) { System.out.println("Please input valid task number!"); } else { index--; System.out.printf("Noted. I've removed this task:" + - taskList.get(index).toString()); - taskList.remove(index); - System.out.println(String.format("\nNow you have %d tasks in the list.\n", taskList.size())); + tasks.get(index).toString()); + tasks.remove(index); + System.out.println(String.format("\nNow you have %d tasks in the list.\n", tasks.size())); } } @@ -125,12 +94,12 @@ public void delete(int index) { * Main list method, lists all contents of tasklist */ public void list() { - if (taskList.size() == 0) { + if (tasks.size() == 0) { System.out.println("Task list is empty."); } else { System.out.println("Here are the tasks in your list:"); Integer i = 0; - for (Task task : taskList) { + for (Task task : tasks) { System.out.printf(String.format("%d.%s\n", i + 1, task.toString())); i++; } @@ -141,13 +110,13 @@ public void list() { * Lists overdue deadline subclass objects in tasklist */ public void listOverdue() { - if (taskList.size() == 0) { + if (tasks.size() == 0) { System.out.println("Task list is empty."); } else { System.out.println("Here are the overdue deadlines in your list:"); Integer i = 0; - for (Task task : taskList) { - if (task instanceof Deadline & ((Deadline) task).isOverdue) { + for (Task task : tasks) { + if (task instanceof Deadline && ((Deadline) task).isOverdue) { System.out.printf(String.format("%d.%s\n", i + 1, task.toString())); i++; } @@ -161,12 +130,12 @@ public void listOverdue() { * @param keyword to be searched for */ public void find(String keyword) { - if (taskList.size() == 0) { + if (tasks.size() == 0) { System.out.println("Task list is empty."); } else { System.out.println("Here are the matching tasks in your list:"); Integer i = 0; - for (Task task : taskList) { + for (Task task : tasks) { if (task.description.contains(keyword)) { System.out.printf(String.format("%d.%s\n", i + 1, task.toString())); i++; diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java index f4ee7f065..c236f72a3 100644 --- a/src/main/java/Todo.java +++ b/src/main/java/Todo.java @@ -14,6 +14,6 @@ public String toString() { @Override public String fileFormat() { - return (String.format("T|%b|%s", super.isDone, this.description)); + return (String.format("T|%b|%s\n", super.isDone, this.description)); } } diff --git a/src/main/java/UI.java b/src/main/java/UI.java index 32a6623fc..17134312f 100644 --- a/src/main/java/UI.java +++ b/src/main/java/UI.java @@ -5,15 +5,15 @@ public class UI { /* * Prints greeting statement and logo to terminal */ - public void greet() { + public void greet(TaskList taskList) { String logo = " ____ _ \n" + "| _ \\ _ _| | _____ \n" + "| | | | | | | |/ / _ \\\n" + "| |_| | |_| | < __/\n" + "|____/ \\__,_|_|\\_\\___|\n"; System.out.println("Hello from\n" + logo); - System.out.println("Hello! I'm Duke"); + taskList.list(); System.out.println("What can I do for you?"); } From 6b122784fe97ca7ea3cc8f95efea4b6dce4daa13 Mon Sep 17 00:00:00 2001 From: notbingsu Date: Tue, 21 Mar 2023 04:10:38 +0800 Subject: [PATCH 15/15] updated jar --- ip.jar | Bin 10112 -> 10802 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/ip.jar b/ip.jar index 042e851eace9df70e61bc8498bbf0085f99baa39..0f2f09b552762ef1e3410933231ea848f095abb9 100644 GIT binary patch delta 9387 zcmZX4Wl$YU7cIfv{owAd2X`m92X}Xe3GNU$KyW8G1PCrcgF|qF!%1+0Yal#sy{dQb zSFis}*VNRW>FM38d#$zKziraN&`^Pc$A>{iMut(K_DRKXfor1jNe!U{l5~yz@O1J2 zs^{9yaS1;hCaD5?sZRC5UQy_iNG>zH?pppYk0D<> z(J=P;Q%s*46u((Eyppxskv$v!NIY%WS>9GBB)ho$U=0y|DJX3LJ@i0UdIWD}1tY8u z+)B;xxj!wm%26M7&C6n?o2#AtN2KCg|oTZ(DlMrx{sawT)&n6ewNSDe~#;80T~^GytLli?9hFP2&0^nDH) zyn!9`O+xq^efdBQOz_xtJN`gNOj>J&63aQrM(GuV_qd z)LUR2NrIwJJNmoI`G@#}3r5hqmv3CroZq&-4dY2&wP zd8X^$lrmGP==gDaEVr-raP8y5crE+kXr3Yas4@Rx=1&>anw^%6yhxV)-|5yXW8RVk z(a_nP(Hq=rMsX{V%V2|Y;!Ub87E>}v)>7Y(Bc~k!)Ev!G=uc2iSnZKNn!ZrR=4AN? z#>cUj!>Je`+tTWtRkD}gp9H@@ArYna*MB@P_BsW~SvNnF7v)}=%vn@b%eqMHcT66l z@9|BdI=d>_iOr;bsu}!-al6ocxbSl&QPR!R@wAqIctG95JH4N)1Vh63LUi?^wX_S5 zz~(fwuS!74Fi4wkz|k&Bti};CW1RN~E(MCp58F@-)L9gGd3>F6p7LcgOxnQ=vH|*TpU=aE1jUJa%D?lBy@ zgSX0+HXJoyCSe8nlzzkM4UZ~ldhWQGChArrd}NqiC^OD->wzosfa&A0?<22VIl;Cb z&=UOzh-R4a_(efI%vyNN;0dIiZHJ19xnt$dA5u2b&#vi?B-5Yhu5V5cs&LIwlL(tA zn2{rWELyofTiJN*j_jv&XY%-x4BfKK1)F|zC+7@}FaS42dTrsA;&FPY#hB6`oD%+R zv&1UQmpK^bc2*!1IY$LqqjtF`F>-1*we3&>9Ov-V!*=nTUzG##z<=c^$VnsR`JF$p zQAXK158Jw0!c7prn@o_qWckZs;`n$e>))GV_L$Z6OkFVh-EcTz=LVZoc?}`aOLtT= z){FEM*+d?|JL}RwY|qOw_?BDBg7TF*qn-2_VVO~6jPN5h8U#m6-l9n*A8Wy*`7^p3 zaG|LcQ9R@b>lbCC?xEIP1Sb?LCH@XhXn?O3*SCX265pzFz>Og>>?w(sl#{nOu;%dI z>`SfpQ%iE;6G_Y1&}oo?;@04rPj~M9hlESzSxUhJE|_6pygYe^h*H79y>7tKAjIM$ zMfuG^!&AVz@yrTcQ7UvrBnaU;k{gH%*3KBA0W$aIQ1Q?h~ z6d0I)QIq(KH^dp9958;1Cq*nazt(!Jv+AiigogjYH)_e)vg8|4Mx=EFRuqG%`dTq2 z+lI9W{}b}x#JH9?hQBaC`o$#SU<8)P)&qyvbhaDt@^FFH$J%}U0cSKME6)i_IBY!o zv1B!s6l1M0(5}-BA-;lPF6KxYZDAnScZ9)~FPL^a$tACn8dxj;%o|f{%MjhYbMeMw zv-;w}pbskrS(>+%jc_w3webwTDarO@=@~TaHdRiyBymlSO)Egsm_5ir1=}EVv~+t1 zvm*s7xVGqM{EklfTx`7})yap_$^XEB;zAD!Oia~xwNvjDA6P)ZFU}8@GlrBZ>*3zA z7;y}+j|rCi05+4L>*n_pFi{t7kSmph>X*GvLTTQ)7)U~ada@3uavR~D?t*Td$Ab^I zodl@947+pDi#(LEfG(uR&7}EfJi8qk$Q$yjVVoMe`Iauv?OS4yf6lxkY1A6o41%qG zH#PBH1PO~&oxrfxIUXw`?|QyvhWjbqeRMeqg=*up{+H?LCHytE`m43S$>h#GFYsry+-9_+iGVl%%xxEq+i}Mm7?=Rq z|IV#^tv4hFQ5H_%kPb49$PRSUz#|q{3Y!trB-i|KowYweZyYFSZLm4c>B!Z6x5nk? zgE*3Pt@Q&=8V=Yu>WomI23J$T zW|x9c=_2Xrh{Fw+cdLw1rIEe7jl)KV<#g66BCo7nr@I>h*0O3agcjXDA(Ck%-&4JYOE}hZ`ZV2|h#(sf zQ_D0;JNUh)rmMQ9gWayqGCTMoBYfF_HpHk|No<^Jv1+ZpEEr(%d}5a|XQbXCA5$r7 z|K-KER-~ugP8dTuI?Y$1MKI}w)8yE465s21-oO@Q=9g2LLdUQ4VKZAYH82_*N)DA9 zOIfhTkBF@N<#6)phkiA(hRL`pMJXfXA#Bq?)I0L8Oyc+FGOJpci1nYeX+M6}C%&spzoix@fHFM7XWGGYy`Z6$ zuS{5ZZWB)^7$o%+hk3c1*hA??j$K5jFM>#u&o2_ci~wE$a_Kc^R=K~tIG}8L?F&3& z{gb@qS?Za4uZfHM3Qqq5(>E#~J(&MA)Yrb6g@Y@Hm9vGHmyfQJJ4g;c#6=~iQ8bx+ zLb=v?blQ?RAs-`e#bQDp-t)wKBn~e#vAk8Zk*_pSUY%^97ih4EfvGUj8IGdSP>$Ew zQPhoRWpp(Wb}wgAya=?$%gqv2eF=TJ+xl}iWxTZk^F4u+Zvh1!QFUSo8{1ykMLkz6 zV1D`rJ-INGQGx}ypP{^3hnto~AhF3ZQEh=MRR{0h9HYfY2&1=iX}PLtj;c1AFY!uT zSDe4CLwwA@Ar7uX%};Keo|QTaBHFw`^y{iQfrpWON%9~Ah$yqqt~gu}_T0t$_j{@; zg2tJsz^0RVA$Ya&C!$k3%lsQSqzmj)_wmiAcy#W*4)0^d#(b^YFWGHP7m3 z3+ig<$l&DYXBFd~o7*uz-Zt@YikU@|ZoY{JE(jd&Ll9L1 zwCQI&rpN{z6tR{Sqo3Idme0vLnm>dQozs9CtkoxQ_KV7+rL}i`LDdttJf@51s12vH z>0!${lha<~}W=<@bIj#E{(8#G5bwn2XO zbNnjk+7pv;G4ahBcpxfXesjX-i^?4uUfz@Rjl^1;Pf|%^uH_)|?Ut~|BSnwB%Lb3- zL0xwY*KX8jr$X{QiJuV|_CL2OQQTcF8|m%q$?N~5v2?^Y9@~?2jdRu0^7tYEvo!|7 zpF86DW7@v>BGwoz6U8DNwcR0Dg@O7fgb2}EU283`=p$K5l5*?*esY*^TQMCLBY0A; z1;l;b5WZq}0phpj2ok3Kf0tx*MNRte8YRtx%wnZwdcX6~!A7cwHW|v5nPj%B-4yddGi|;#7 zN%w;peR~OKd6&<%el4jn{Pr0RPEghT5crkqqwr0?=K-4xyvl5{-V$Fp#}|(@g~kME zBjtq0`#iqFI_}y&=33b|HQN^aZfm5bpM)CTBAv-HZjKlonZz{Q6F*LO&&$ zr4G5R#7f*7Av+VQe3q+~Y&+O>Y9ufo#_UCYUSY<(Bv&k!E1PAF7P?KbYTIJN8#m^T z_H$1ac}G^l{ zcq-!alkzJNw;}%*j7?g+A%~b0fRCO_5NMb{%u0ncpjlb+8={nwtQM|u^63J$;OK`B z=8PVnZNfLoc*1+;p;>I~}0D$1gybE08G&_bw-IlI3otAs^|=Pk^@1@94E6J2Wq zGK;*lhOJh2v&}WxBD{B-!u#vl&qrThp2+$HJyc5MB-J15?WTUWJmO(8AE26CoxbWDSS|qznT@5Iz7AJp@j9}xh@HOk5^-$ zQw>|H|BdH@z2Zz0`=KwByTZI;{DEXGx5?HM{2{l|laXyk^EsM(yU24{Tn-t%*QX_AXzFmDm*b7veLK7xfsQ8suv+u&gvJ&sMFcKL(4qX$k&`O)|D+A)m^ZkfRhA`=J-ANW<)Y zclri1Bi}@i`eR=y0|guc?S7rfkAf_Mm5#u-K06pLFqvTr*l5tA_pvp%cns0p(kMp5 zCGV&%dO#M<(+i4nT_S+xZsp#X-*E(DvW4odQrInqfSo0og{P(t!|+vPTt&M7PluXx znnepycJ~zS-GF+c!sd`d4rq1wuAwC-cgy(M!O*DmH;%_-V+|C(b0RLi_M$So7Gl8$ z0+Lh1sq*@1aNViZvG;g@OQ$Smpch;IErvhi$4o&5+0(_~dSyT@<42jB&2+M{+`Bkj zl5g+SHFpi+nuXZ8+f0~OpQ)Fpe(3c_M)0zIE%}vk5`FqYMli1o62=Q)5{lh-@Nqu? zlVOyO;>Rqa&&Z<4GFwZSwR)DX<*_H&ffEDjiBYV=0BzhYT5E0BC4P4b?zl7Fq0cTh zUTkV`MCph0mtcU$jn&jl=UE@VwN8j)>eq=ds{&ncSDYHL1a2&|{4Pn`wwDXDYk==M zv&O3WQr|=@Nqb_UVt4f}9xq-)74P>^U@NTiRsBv^QqSO*w(~7Tw#&l@^i?#(!|zVqHX zdwWFB^rQ2798;0;>9z8zI}!Lud^p#{!u@0y7YxkDy~Qyc5`%WtwBNBPtE}W~_Qd-0 zX!Ktg6vdNQZ64IKbVB-N*;cgW0Jbdk)(~-GSMqd%llT^&(J<=+Jkc+a3UiI$)zH~@ zC9f}7Fm*lJ<7X4JyhoGIMOpx6x2l>JEY?^$I1_BK=^fDI*pTRib6S^Xm$IjzB>GW- z3o!Eh}zS}~y7I5%eGV=u?dCH2&RFcTlqJ2XO2~8-@ z4X-d?bZB0-Jfn9$>l^P-DOL&;zknWT#GSJMY9DJlc#qjTp_veBU&9?$6!{@5Rn~|H z?5H|uzeTaD(ZgkiA1~E#9HZcL*ZNslCb7%iu^b~n~>0cEvInKKDx;gsyf`g8H6U`2K0}C zz#j>2A7iZ~GCE@JF}BeucDZ{#-ecj;hqMpnUhAUopmN@BSxRg&+!By2oaE0{f8De` z>$H_S$lPs=+BCXgeabnDvOU&n_K9L?XbZ2s+`@i>xoZC=Oinnn6bb9 zwu*`RDTC>9&Anu{cuDT+SCq{Wf-Gn?rntkxo7l0xw&c#sV2X0rlndy&Qs@#nba_E& zzswy5PbeHp+8A>jz=tEUx)3BGK5Qp@A{AKesEWylzfqEUAYCNiD7YBFlcd;AO zi5Ofs&LHtx6EsPHkbmX9)KClF$a{}OedjmoeL`8Erl{Tx5f}HDrgAyVmti#Km#cJ& zY-~hvIOMcruH4KEJb&kWMtWusFbe#=sHiAC1$l(a$-e8o>)Frq>v+170RFPRA8fBE zRhDsIP@a)J{Zc_&WHC>`>f{5^*Xfiv`CrDz29P?6g3CJab)86N)P0p+C@_3zeQ9h0 zNc8PjG+Wm}8DT+>2YPEx70wNBWqh30vZDJ?7&*{&tRmvT#9#r(m8RB*_G2S7p71b4 z=gNra4{@Xmjw{41+LlbbBFyWWPCR2WGMbFG^doG`nOnWw+iGh=PO`w&WMFWnQm>P} zI|5F{Wdi!#YHPu2z0WrqX^^FoMaKj3%{`y*v4488ieDD;VA1>WF3duy=43H?(iFBb zF>a?4grKTq2z8Ev=g6x1GQzTY0Br$l?T-Q~BNUwi;!L&yma)Z0?CK&UbXo2)D~-Xu7G6ZH0!8HIAubNCH-@a) zID^`xtu2`NG8Y@8P?E$WVrF*CsQDo|E}0hXWD%!E@njuyK}~8<#_$mYf!B4Hhk;mo z5kd3juNn7*vNm8FXNh6hTur@9d=htaQY*g>JxeN+?9*SUM-& z7TB4OuO~WIu*^NBeQAb>J10iHkz~I)&JMDg7u6r-Ah}>mac^xituOLj%bLu#vQ+=X zqsU^#BO%pJ>T70hSB}6d@$q6{GB>{_%3XOXpTQ8``2;|3nhcd5jb>M?YRE`-N+b6p z%^E>t=w(s}<96!c9hqk&AG4(3%(-vk%N4#F*2zO7tGV3a{m#)$d8%W=wVsJ;B9wSQ zl1uVs@99DxM5ILBhKTIU77KFjq8`EX_u5nqdn>ucBFWCPPW^nWf zYZoL6xB!3MYqIjM2x+9c%c+C)+MVtGj=3^_!Td9(`+I}uzD+F{X)7ZzXrM)OBx6HE z)EX%`=&e|9iZM8}&(r9u=7FS%aD%z;nghVpSY0GEbTQ+i)=Ky9($LvCPqTf+ zvyiAwJTv+(7U`<;Kx3)ZymOjz<G}z;{7WKwI6eIARhs-JGAEN8qRWgyL6aGpQ7i znZN6^Y_LAa_=(+5)?_MHNA+5<`Z3WU%g;nz!77q*Xvo2MX*~LgoG>+Lc4(qC=LKY6 znFa`Q6oS82V@HnpZ7x35Rg@Q+k{0H!>YKMpNDkhk3WU6$I%7R!e{#|AIKtVUP6~GY z^)Y)bLgBMoeq#@I!&-{IaArT_=ZFH4gx#ztArbqA%hcam7oGMQ;{2z6jSoH2MMgHx zET~%A$a4lTUTK@2>~w-#BNcq>Qrh-gJgdO?VT(pu&q`v59F9y>?7P@|oGoghLy2pc zl%zAWemf+agXBL#I#DXGkpU-VNAnBT^oB5r5Rcr*73RgcGO4ZrW?nTC$n3c?p8SH#nJ&( zoCgF;c>uk*o+>mcA?TO)GPDw-TQahDLa7o`kuh<3ci=4~d(cqo+xI3+KeaPHFw%Mc zvHD;ZVE?n{Nle*0L^d=Lxsc`(`g$Gx6WjfQM^&gf3dy=jeTmqb1HwnO5QM%;_B>&( z%SW({)Ub`vd$VfiX&`~zEGjG&CxDQ$nse&CkBy%rU5@L_()g+q?DH(K@);(1S0b9L z%`vyhKs%!BntvO(Ok}M}B&}dMcWiX8@$ON3l~)=n8PHC+ZX@l@hHAvifmxQI6(_b` zJZCm~-rmZ(Jv^`cxYYV2ry{pZ+X1r>_K#C9`8}=t^{37r?*7qS1H#%iG<38(A-bj2iFM;j`N$*OEsP}HbWC?C~c?Hy^)3IQ|=y2;SbovHZSWO(~xC;qgRFHYr~bF8c+yA2w^~bye2xF z*HJ1=aqpEa-r7e>Uy_X>T_t2?{W-eq7aWC%hU$Zq>F#Pr)iA5E|E^o5_v~Z!yk?oY zT{bwXMT$gz%&WqrK%aTWN9(IpfU8!)vf`r;W~ZPK`DWx`+N)B>>aQ|3U(eHHZ~&1D zF8XH7+W=W}eoLuc`OTXNd)5iLO@XtxYM!4h) z_AB{r#{Ta~;vXsBoywTZ^KLqycRw%4?&azE0@Mc<;Fl$~{E%G8>PfI zZa1Ie0dmZlB(`eIUMK0Oy2(vZ{|EtN@Pdf z?8Jvy>mg#oRpGNIEV?0F!{_>)8(?lQRJFSwvC3Dv86BjrTCADP7d&i!aG6+r62#u< zR5S6mQpHT0$$Cr%|0qsN9sscAlJtyYzoQK$u)-Z|F(vdB*+=RoeE{1st6*qyaT7HS zEw;x+R9U37i$||Z?lIPOwg^d93-w)+xElH~sJqGOG8 zpN&PWsu*`)hq@kHW4j)b?23-nwF@hFmFXyUcP#1ASC3=;2amCSIs&J z?!U8SU*Zkvr6C2h4c+D?vH!NJIgR) zj(dEFzw9#$kI{jRqwGtOo)juB|ALiRp8vz`_m7Jiv#n4V|M$9Z?_l5M(!-I26^p%; zo<)Z0_-vk>RC&^T@4}UpYGV1GU$})kDmqVKQw%Z$i5(CC#NH8#J+2GBI^8>Gk;+v2 zM@^Kj4<3DYm|04`5nyh=W*z*4s&C4g=YPAqc9!opiVE=e+f>of7RnXqM7-Gy)OwvO z-Y=(5EsR^;FYGJEOcATstyZM7{`@7Z2gxVvI1NytsA?5U>;9B6jQkBfv4FJi(Lzj< z9|X-R+VhD3#>u_3eTwqiJh17Hm1>`iX8Y3nhRl*tm}}mGqzp701YKySx81fRe)4%aTY;$`Ah_A+b~=<4^O7!TF>S3J=vL9k)}PGj!JB6HgWT zP_Ky+qEDhF=FR6P$<;3inKLD-;vbC7``TJN)H4(Ug0~LjWa~Wc5YOiTHBeiCFc0+@ z!*A5YuWL7WhPSkaX#}KE$-jzSYdr$UiQXJrldS0K^K;H;ha({R`j7?BY3{~!hcF=L zvOghdCi`r}P8`YgsW>=iW(tc= zTi;v&p}RUDM3L#jvG53v{bepu_K@OtMH1Uw%JYX3>x+Z-4A_nAro4lTDp|d1 z(g>xl&5tGPqslB|53f})NXSInI03G&Daitl^G{B`fyIaUe}yp+Zh9Ha*UA{Ze@$RW zI6Vi|tNW|>U+?fAljYy`83FR0p4jjed-VS6(V+eN#A~nkmG#K^+PHfEUt{LKFaF2E z`LCY%ztQ_pAyN#)RIk#a-hbH>#{Wc@#)bqifDB%Vl%9uttmTi_@rk{vlm8njk_ZMy z$HL3$|Nnwl-lg|nK*ju@;2ETl69zJaf5!LU_58oVcW7RNyIH&a|G{5ZyWYP)9R}tV TwExq%=pp8eq=*ZQ|J?gOH5_6_ delta 8732 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