From ec544ea05649fd66108029cc9cccc2bca5283ec1 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 01:37:26 +0800 Subject: [PATCH 01/62] added Format --- src/main/java/Duke.java | 34 +++++++++++++++++++++++++++------ src/main/java/Format.java | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 src/main/java/Format.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 5d313334cc..424b6633cf 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,10 +1,32 @@ +import java.util.Scanner; + public class Duke { + public static int inputHandler(String s) { + String temp = s.toLowerCase(); + if (s.equals("bye")) { + return 0; + } else { + return 1; + } + } + public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); + + Scanner sc = new Scanner(System.in); + System.out.println(Format.LOGO); + System.out.println(Format.greeting); + + while(sc.hasNext()) { + String message = sc.nextLine(); + int type = inputHandler(message); + if (type == 0) { + break; + } else { + System.out.println(Format.chatBox(message)); + } + + } + + System.out.println(Format.farewell); } } diff --git a/src/main/java/Format.java b/src/main/java/Format.java new file mode 100644 index 0000000000..c426ac733a --- /dev/null +++ b/src/main/java/Format.java @@ -0,0 +1,40 @@ +public class Format { + + public static final String SPACE = "\n"; + public static final String UPPER = SPACE + "^".repeat(80) + SPACE.repeat(2); + public static final String LOWER = SPACE.repeat(2) + "_".repeat(80) + SPACE; + + + + public static final String LOGO = " ____ _ \n" + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; + + public static final String farewell = UPPER + + "Good friends never say goodbye. They simply say ‘See you soon'." + + LOWER; + + public static final String greeting = UPPER + + "What's up! This is Duke, what do you want to do today!" + + LOWER; + + public static final String chatBox(String s) { + if (s.length() > 35) { + int mid = s.length() / 2; + return UPPER + " ".repeat(40 - mid / 2) + s.substring(0, mid) + + SPACE + " ".repeat(40 - mid / 2) + s.substring(mid) + LOWER; + } else if (s.length() >= 60) { + return "ERROR! Your command is too long!"; + } else { + return UPPER + " ".repeat(38 - s.length() / 2) + s + LOWER; + } + + } + + + + + +} \ No newline at end of file From 36ea37fade76548a16124f6c0b66586187a63401 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 01:49:03 +0800 Subject: [PATCH 02/62] implement add --- src/main/java/Duke.java | 5 +++-- src/main/java/Task.java | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 src/main/java/Task.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 424b6633cf..8f7f343856 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -18,15 +18,16 @@ public static void main(String[] args) { while(sc.hasNext()) { String message = sc.nextLine(); + Task t = new Task(message); int type = inputHandler(message); if (type == 0) { break; } else { - System.out.println(Format.chatBox(message)); + System.out.println(Format.chatBox("Added: " + message)); } } - + System.out.println(Format.farewell); } } diff --git a/src/main/java/Task.java b/src/main/java/Task.java new file mode 100644 index 0000000000..35eb51befe --- /dev/null +++ b/src/main/java/Task.java @@ -0,0 +1,18 @@ +public class Task { + private static String[] tasks = new String[100]; + private String task; + private static int capacity = 0; + Task(String task) { + this.task = task; + capacity++; + add(task); + } + + private static void add(String s) { + tasks[capacity - 1] = s; + } + + public static String[] getTasks() { + return tasks; + } +} From 00974a0c78b6ed5f3c18318c106a8cd29ad72fb1 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 13:42:41 +0800 Subject: [PATCH 03/62] add Task.java --- src/main/java/Task.java | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 35eb51befe..456951b84a 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -1,18 +1,29 @@ public class Task { - private static String[] tasks = new String[100]; - private String task; + private static Task[] taskList = new Task[100]; + private String taskName; private static int capacity = 0; - Task(String task) { - this.task = task; + private int index; + Task(String taskName) { + this.taskName = taskName; + this.index = capacity + 1; capacity++; - add(task); + add(this); } - private static void add(String s) { - tasks[capacity - 1] = s; + private static void add(Task t) { + taskList[capacity - 1] = t; } - public static String[] getTasks() { - return tasks; + public String getTaskName() { + return taskName; + } + + public Task[] getTaskList() { + return Task.taskList; + } + + @Override + public String toString() { + return String.format("%d. %s", index, taskName); } } From 3ce9d79f0a8e00c31fa967431d17e00453cf967a Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 13:58:08 +0800 Subject: [PATCH 04/62] Complete add and lsit feature --- src/main/java/Duke.java | 11 ++++++++--- src/main/java/Format.java | 29 ++++++++++++++--------------- src/main/java/Task.java | 6 ++++-- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 8f7f343856..ca0a82a131 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -5,8 +5,10 @@ public static int inputHandler(String s) { String temp = s.toLowerCase(); if (s.equals("bye")) { return 0; - } else { + } else if (s.equals("list")) { return 1; + } else { + return 2; } } @@ -18,11 +20,14 @@ public static void main(String[] args) { while(sc.hasNext()) { String message = sc.nextLine(); - Task t = new Task(message); + int type = inputHandler(message); if (type == 0) { break; - } else { + } else if (type == 1) { + Format.LISTING(); + }else { + Task t = new Task(message); System.out.println(Format.chatBox("Added: " + message)); } diff --git a/src/main/java/Format.java b/src/main/java/Format.java index c426ac733a..b13a8e94c0 100644 --- a/src/main/java/Format.java +++ b/src/main/java/Format.java @@ -3,9 +3,6 @@ public class Format { public static final String SPACE = "\n"; public static final String UPPER = SPACE + "^".repeat(80) + SPACE.repeat(2); public static final String LOWER = SPACE.repeat(2) + "_".repeat(80) + SPACE; - - - public static final String LOGO = " ____ _ \n" + "| _ \\ _ _| | _____ \n" + "| | | | | | | |/ / _ \\\n" @@ -13,27 +10,29 @@ public class Format { + "|____/ \\__,_|_|\\_\\___|\n"; public static final String farewell = UPPER - + "Good friends never say goodbye. They simply say ‘See you soon'." + + "I zao liao, don't miss me." + LOWER; - public static final String greeting = UPPER - + "What's up! This is Duke, what do you want to do today!" + + "Awww, need help ah?" + LOWER; public static final String chatBox(String s) { - if (s.length() > 35) { - int mid = s.length() / 2; - return UPPER + " ".repeat(40 - mid / 2) + s.substring(0, mid) - + SPACE + " ".repeat(40 - mid / 2) + s.substring(mid) + LOWER; - } else if (s.length() >= 60) { - return "ERROR! Your command is too long!"; + if (s.length() > 38) { + return "Walao! Your command too long lah!"; } else { - return UPPER + " ".repeat(38 - s.length() / 2) + s + LOWER; + return UPPER + " ".repeat(36 - s.length() / 2) + s + LOWER; } - } - + public static final void LISTING() { + System.out.println(UPPER); + for (Task task : Task.getTaskList()) { + if (task == null) break; + System.out.println(task); + System.out.println(SPACE); + } + System.out.println(LOWER); + } diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 456951b84a..355eeca67c 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -11,14 +11,16 @@ public class Task { } private static void add(Task t) { - taskList[capacity - 1] = t; + if (t.taskName.length() <= 38) { + taskList[capacity - 1] = t; + } } public String getTaskName() { return taskName; } - public Task[] getTaskList() { + public static final Task[] getTaskList() { return Task.taskList; } From 14a32f98c9ddd101f1f7862a7641a688857c7d15 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 15:03:47 +0800 Subject: [PATCH 05/62] Modify Task and complete Done feature --- src/main/java/Duke.java | 49 ++++++++++++++++++++++++--------------- src/main/java/Format.java | 3 +-- src/main/java/Task.java | 18 +++++++++++++- 3 files changed, 48 insertions(+), 22 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index ca0a82a131..33b619b613 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,16 +1,7 @@ import java.util.Scanner; public class Duke { - public static int inputHandler(String s) { - String temp = s.toLowerCase(); - if (s.equals("bye")) { - return 0; - } else if (s.equals("list")) { - return 1; - } else { - return 2; - } - } + public static void main(String[] args) { @@ -20,19 +11,39 @@ public static void main(String[] args) { while(sc.hasNext()) { String message = sc.nextLine(); - - int type = inputHandler(message); - if (type == 0) { + boolean bye = inputHandler(message); + if (bye) { break; - } else if (type == 1) { + } + } + System.out.println(Format.farewell); + } + + public static boolean inputHandler(String message) { + String[] line = message.toLowerCase().split(" "); + String command = line[0]; + if (command.equals("bye")) { + return true; + } else { + if (command.equals("list")) { Format.LISTING(); - }else { - Task t = new Task(message); + } else if (command.equals("done")) { + if (line.length == 2) { + String arg = line[1].replaceAll("[^0-9]", ""); + try { + int num = Integer.parseInt(arg); + Task.done(num); + } catch (NumberFormatException e) { + System.out.println("Please lah, key in number"); + } + } else { + System.out.println("Wrong format liao"); + } + } else { + Task task = new Task(message); System.out.println(Format.chatBox("Added: " + message)); } - + return false; } - - System.out.println(Format.farewell); } } diff --git a/src/main/java/Format.java b/src/main/java/Format.java index b13a8e94c0..7abc2209a2 100644 --- a/src/main/java/Format.java +++ b/src/main/java/Format.java @@ -2,7 +2,7 @@ public class Format { public static final String SPACE = "\n"; public static final String UPPER = SPACE + "^".repeat(80) + SPACE.repeat(2); - public static final String LOWER = SPACE.repeat(2) + "_".repeat(80) + SPACE; + public static final String LOWER = SPACE.repeat(1) + "_".repeat(80) + SPACE; public static final String LOGO = " ____ _ \n" + "| _ \\ _ _| | _____ \n" + "| | | | | | | |/ / _ \\\n" @@ -29,7 +29,6 @@ public static final void LISTING() { for (Task task : Task.getTaskList()) { if (task == null) break; System.out.println(task); - System.out.println(SPACE); } System.out.println(LOWER); } diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 355eeca67c..95d182b2e7 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -3,9 +3,11 @@ public class Task { private String taskName; private static int capacity = 0; private int index; + private String done; Task(String taskName) { this.taskName = taskName; this.index = capacity + 1; + this.done = ""; capacity++; add(this); } @@ -16,6 +18,16 @@ private static void add(Task t) { } } + public static final void done(int i) { + if (taskList[i - 1] != null) { + taskList[i - 1].done = "X"; + System.out.println(Format.UPPER + " ".repeat(10) + "Wah~ You done the task: " + + " ".repeat(10) + taskList[i - 1].toString() + Format.LOWER); + } else { + System.out.println(Format.chatBox("Walao!No such task!")); + } + } + public String getTaskName() { return taskName; } @@ -24,8 +36,12 @@ public static final Task[] getTaskList() { return Task.taskList; } + public String isDone() { + return done; + } + @Override public String toString() { - return String.format("%d. %s", index, taskName); + return String.format("[%s] %d. %s", done, index, taskName); } } From b30b5262f6bfb334f33d9c61511f512fdb394c87 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 15:18:32 +0800 Subject: [PATCH 06/62] implement Todo --- src/main/java/Duke.java | 3 +++ src/main/java/Format.java | 2 +- src/main/java/Task.java | 9 +++++++++ src/main/java/Todo.java | 14 ++++++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/main/java/Todo.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 33b619b613..1684ac261f 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -39,6 +39,9 @@ public static boolean inputHandler(String message) { } else { System.out.println("Wrong format liao"); } + } else if (command.equals("todo")) { + Todo todo = new Todo(message); + System.out.println(Format.chatBox("Added liao: " + todo.toString())); } else { Task task = new Task(message); System.out.println(Format.chatBox("Added: " + message)); diff --git a/src/main/java/Format.java b/src/main/java/Format.java index 7abc2209a2..4e984936ec 100644 --- a/src/main/java/Format.java +++ b/src/main/java/Format.java @@ -17,7 +17,7 @@ public class Format { + LOWER; public static final String chatBox(String s) { - if (s.length() > 38) { + if (s.length() > 50) { return "Walao! Your command too long lah!"; } else { return UPPER + " ".repeat(36 - s.length() / 2) + s + LOWER; diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 95d182b2e7..a68b891715 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -18,6 +18,12 @@ private static void add(Task t) { } } + private static void toDo(Todo t) { + if (t.getTaskName().length() <= 38) { + taskList[capacity - 1] = t; + } + } + public static final void done(int i) { if (taskList[i - 1] != null) { taskList[i - 1].done = "X"; @@ -40,6 +46,9 @@ public String isDone() { return done; } + public int getIndex() { + return index; + } @Override public String toString() { return String.format("[%s] %d. %s", done, index, taskName); diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java new file mode 100644 index 0000000000..f7cef76f29 --- /dev/null +++ b/src/main/java/Todo.java @@ -0,0 +1,14 @@ +public class Todo extends Task{ + + + public Todo(String taskName) { + super(taskName); + + } + + + @Override + public String toString() { + return String.format("[T][%s] %d. %s", super.isDone(), super.getIndex(), super.getTaskName()); + } +} From 80032310afa89953401c9b01d458e4df4cdeeb25 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 16:08:30 +0800 Subject: [PATCH 07/62] fix bug for todo, add Deadline --- src/main/java/Deadlines.java | 16 ++++++++++++++++ src/main/java/Duke.java | 28 ++++++++++++++++++++++++++-- src/main/java/Format.java | 4 ++-- src/main/java/Task.java | 6 ++++++ 4 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 src/main/java/Deadlines.java diff --git a/src/main/java/Deadlines.java b/src/main/java/Deadlines.java new file mode 100644 index 0000000000..c773d2278f --- /dev/null +++ b/src/main/java/Deadlines.java @@ -0,0 +1,16 @@ +public class Deadlines extends Task{ + + private String comments; + + public Deadlines(String taskName, String comments) { + super(taskName); + this.comments = comments; + } + + + @Override + public String toString() { + return String.format("[D][%s] %d. %s ( %s )", super.isDone(), super.getIndex(), + super.getTaskName(), this.comments); + } +} diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 1684ac261f..2f97cc2f1f 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,3 +1,4 @@ +import java.util.Arrays; import java.util.Scanner; public class Duke { @@ -40,8 +41,31 @@ public static boolean inputHandler(String message) { System.out.println("Wrong format liao"); } } else if (command.equals("todo")) { - Todo todo = new Todo(message); - System.out.println(Format.chatBox("Added liao: " + todo.toString())); + if (line.length > 1) { + String msg = message.replaceAll(command, "") + .trim(); + Todo todo = new Todo(msg); + System.out.println(Format.UPPER + "Added liao: " + + todo.toString() + Format.LOWER); + } else { + System.out.println("Wrong format liao"); + } + } else if (command.equals("deadline")) { + if (line.length > 2) { + String[] comments = message.toLowerCase().split("/"); + String msg = comments[0].replaceAll(command, "").trim(); + if (comments.length == 2) { + String comment = comments[1]; + Deadlines deadline = new Deadlines(msg, comment); + System.out.println(Format.UPPER + "Added liao: " + + deadline.toString() + Format.LOWER); + } else { + System.out.println("Wrong format liao, add / at the end for date"); + } + + } else { + System.out.println("Wrong format liao"); + } } else { Task task = new Task(message); System.out.println(Format.chatBox("Added: " + message)); diff --git a/src/main/java/Format.java b/src/main/java/Format.java index 4e984936ec..ba2a92a497 100644 --- a/src/main/java/Format.java +++ b/src/main/java/Format.java @@ -1,8 +1,8 @@ public class Format { public static final String SPACE = "\n"; - public static final String UPPER = SPACE + "^".repeat(80) + SPACE.repeat(2); - public static final String LOWER = SPACE.repeat(1) + "_".repeat(80) + SPACE; + public static final String UPPER = SPACE + "^".repeat(90) + SPACE.repeat(2); + public static final String LOWER = SPACE.repeat(1) + "_".repeat(90) + SPACE; public static final String LOGO = " ____ _ \n" + "| _ \\ _ _| | _____ \n" + "| | | | | | | |/ / _ \\\n" diff --git a/src/main/java/Task.java b/src/main/java/Task.java index a68b891715..25388db204 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -24,6 +24,12 @@ private static void toDo(Todo t) { } } + private static void deadline(Deadlines t) { + if (t.getTaskName().length() <= 38) { + taskList[capacity - 1] = t; + } + } + public static final void done(int i) { if (taskList[i - 1] != null) { taskList[i - 1].done = "X"; From b0b8d22a2a2ecca8813cc54b36d36925ba44264d Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 16:13:31 +0800 Subject: [PATCH 08/62] bug fix for todo,deadline --- src/main/java/Duke.java | 8 ++++++-- src/main/java/Task.java | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 2f97cc2f1f..575e7401c9 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -46,7 +46,9 @@ public static boolean inputHandler(String message) { .trim(); Todo todo = new Todo(msg); System.out.println(Format.UPPER + "Added liao: " - + todo.toString() + Format.LOWER); + + todo.toString() + Format.SPACE + + "You have " + Task.getCapacity() + " tasks in the list!" + + Format.LOWER); } else { System.out.println("Wrong format liao"); } @@ -58,7 +60,9 @@ public static boolean inputHandler(String message) { String comment = comments[1]; Deadlines deadline = new Deadlines(msg, comment); System.out.println(Format.UPPER + "Added liao: " - + deadline.toString() + Format.LOWER); + + deadline.toString() + Format.SPACE + + "You have " + Task.getCapacity() + " tasks in the list!" + + Format.LOWER); } else { System.out.println("Wrong format liao, add / at the end for date"); } diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 25388db204..06d21ddbab 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -55,6 +55,10 @@ public String isDone() { public int getIndex() { return index; } + + public static final int getCapacity() { + return Task.capacity; + } @Override public String toString() { return String.format("[%s] %d. %s", done, index, taskName); From 11f33a3095ef1d343b7edeeb5b03f8dd50de65cf Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 16:33:01 +0800 Subject: [PATCH 09/62] Simplifed code --- src/main/java/Duke.java | 101 +++++++++++++++++++++++--------------- src/main/java/Event.java | 15 ++++++ src/main/java/Format.java | 11 +++++ src/main/java/Task.java | 11 ----- 4 files changed, 87 insertions(+), 51 deletions(-) create mode 100644 src/main/java/Event.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 575e7401c9..f21f29ec6e 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -20,8 +20,63 @@ public static void main(String[] args) { System.out.println(Format.farewell); } + public static void handleDone(String[] line) { + if (line.length == 2) { + String arg = line[1].replaceAll("[^0-9]", ""); + try { + int num = Integer.parseInt(arg); + Task.done(num); + } catch (NumberFormatException e) { + System.out.println("Please lah, key in number"); + } + } else { + Format.WRONGFORMAT(); + } + } + + public static void handleToDo(String[] line, String message) { + if (line.length > 1) { + String msg = message.replaceAll(line[0], "") + .trim(); + Todo todo = new Todo(msg); + System.out.println(Format.biggerBox(todo)); + } else { + Format.WRONGFORMAT(); + } + } + public static void handleDeadline(String[] line, String message) { + if (line.length > 2) { + String[] comments = message.trim().toLowerCase().split("/"); + String msg = comments[0].replaceAll(line[0], "").trim(); + if (comments.length == 2) { + Deadlines deadline = new Deadlines(msg, comments[1]); + System.out.println(Format.biggerBox(deadline)); + } else { + Format.WRONGFORMAT(); + } + + } else { + Format.WRONGFORMAT(); + } + } + + public static void handleEvent(String[] line, String message) { + if (line.length > 2) { + String[] comments = message.trim().toLowerCase().split("/"); + String msg = comments[0].replaceAll(line[0], "").trim(); + if (comments.length == 2) { + Event event = new Event(msg, comments[1]); + System.out.println(Format.biggerBox(event)); + } else { + Format.WRONGFORMAT(); + } + } else { + Format.WRONGFORMAT(); + } + } + public static boolean inputHandler(String message) { - String[] line = message.toLowerCase().split(" "); + String[] line = message.trim().toLowerCase().split(" "); String command = line[0]; if (command.equals("bye")) { return true; @@ -29,47 +84,13 @@ public static boolean inputHandler(String message) { if (command.equals("list")) { Format.LISTING(); } else if (command.equals("done")) { - if (line.length == 2) { - String arg = line[1].replaceAll("[^0-9]", ""); - try { - int num = Integer.parseInt(arg); - Task.done(num); - } catch (NumberFormatException e) { - System.out.println("Please lah, key in number"); - } - } else { - System.out.println("Wrong format liao"); - } + handleDone(line); } else if (command.equals("todo")) { - if (line.length > 1) { - String msg = message.replaceAll(command, "") - .trim(); - Todo todo = new Todo(msg); - System.out.println(Format.UPPER + "Added liao: " - + todo.toString() + Format.SPACE - + "You have " + Task.getCapacity() + " tasks in the list!" - + Format.LOWER); - } else { - System.out.println("Wrong format liao"); - } + handleToDo(line, message); } else if (command.equals("deadline")) { - if (line.length > 2) { - String[] comments = message.toLowerCase().split("/"); - String msg = comments[0].replaceAll(command, "").trim(); - if (comments.length == 2) { - String comment = comments[1]; - Deadlines deadline = new Deadlines(msg, comment); - System.out.println(Format.UPPER + "Added liao: " - + deadline.toString() + Format.SPACE - + "You have " + Task.getCapacity() + " tasks in the list!" - + Format.LOWER); - } else { - System.out.println("Wrong format liao, add / at the end for date"); - } - - } else { - System.out.println("Wrong format liao"); - } + handleDeadline(line, message); + } else if (command.equals("event")){ + handleEvent(line, message); } else { Task task = new Task(message); System.out.println(Format.chatBox("Added: " + message)); diff --git a/src/main/java/Event.java b/src/main/java/Event.java new file mode 100644 index 0000000000..57876f8205 --- /dev/null +++ b/src/main/java/Event.java @@ -0,0 +1,15 @@ +public class Event extends Task{ + private String comments; + + public Event(String taskName, String comments) { + super(taskName); + this.comments = comments; + } + + + @Override + public String toString() { + return String.format("[E][%s] %d. %s ( %s )", super.isDone(), super.getIndex(), + super.getTaskName(), this.comments); + } +} diff --git a/src/main/java/Format.java b/src/main/java/Format.java index ba2a92a497..1efcf8acc1 100644 --- a/src/main/java/Format.java +++ b/src/main/java/Format.java @@ -9,6 +9,10 @@ public class Format { + "| |_| | |_| | < __/\n" + "|____/ \\__,_|_|\\_\\___|\n"; + public static final void WRONGFORMAT() { + System.out.println("Wrong Format Liao"); + } + public static final String farewell = UPPER + "I zao liao, don't miss me." + LOWER; @@ -24,6 +28,13 @@ public static final String chatBox(String s) { } } + public static final String biggerBox(Task t) { + return Format.UPPER + "Added liao: " + + t.toString() + Format.SPACE + + "You have " + Task.getCapacity() + " tasks in the list!" + + Format.LOWER; + } + public static final void LISTING() { System.out.println(UPPER); for (Task task : Task.getTaskList()) { diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 06d21ddbab..4df067a9ab 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -18,17 +18,6 @@ private static void add(Task t) { } } - private static void toDo(Todo t) { - if (t.getTaskName().length() <= 38) { - taskList[capacity - 1] = t; - } - } - - private static void deadline(Deadlines t) { - if (t.getTaskName().length() <= 38) { - taskList[capacity - 1] = t; - } - } public static final void done(int i) { if (taskList[i - 1] != null) { From b78adb134dcc4d0bc9522e1a8874b865b3803e0c Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 16:40:19 +0800 Subject: [PATCH 10/62] Bug fix for not adding event and deadline --- src/main/java/Task.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 4df067a9ab..c188f9fda0 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -13,17 +13,15 @@ public class Task { } private static void add(Task t) { - if (t.taskName.length() <= 38) { - taskList[capacity - 1] = t; - } + taskList[capacity - 1] = t; } public static final void done(int i) { if (taskList[i - 1] != null) { taskList[i - 1].done = "X"; - System.out.println(Format.UPPER + " ".repeat(10) + "Wah~ You done the task: " - + " ".repeat(10) + taskList[i - 1].toString() + Format.LOWER); + System.out.println(Format.UPPER + "Wah~ You done the task: " + + " " + taskList[i - 1].toString() + Format.LOWER); } else { System.out.println(Format.chatBox("Walao!No such task!")); } From 08786b1611386f09778e8c7af1c90bd4ce418b1d Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 17:26:33 +0800 Subject: [PATCH 11/62] Minor bug fix --- text-ui-test/ACTUAL.TXT | 110 ++++++++++++++++++++++++++++++++++++++ text-ui-test/EXPECTED.TXT | 89 ++++++++++++++++++++++++++++-- text-ui-test/input.txt | 17 ++++++ 3 files changed, 213 insertions(+), 3 deletions(-) create mode 100644 text-ui-test/ACTUAL.TXT diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT new file mode 100644 index 0000000000..da4b7fadc5 --- /dev/null +++ b/text-ui-test/ACTUAL.TXT @@ -0,0 +1,110 @@ + ____ _ +| _ \ _ _| | _____ +| | | | | | | |/ / _ \ +| |_| | |_| | < __/ +|____/ \__,_|_|\_\___| + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Awww, need help ah? +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [D][] 1. ( sundayafternoon 3-4 pm ) +You have 1 tasks in the list! +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [T][] 2. read book +You have 2 tasks in the list! +__________________________________________________________________________________________ + +Wrong Format Liao +Wrong Format Liao +Wrong Format Liao + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [D][] 3. study ( sundayafternoon 3-4 pm ) +You have 3 tasks in the list! +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [D][] 4. ( sundayafternoon 3-4 pm ) +You have 4 tasks in the list! +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Wah~ You done the task: [D][X] 1. ( sundayafternoon 3-4 pm ) +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Walao!No such task! +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +[D][X] 1. ( sundayafternoon 3-4 pm ) +[T][] 2. read book +[D][] 3. study ( sundayafternoon 3-4 pm ) +[D][] 4. ( sundayafternoon 3-4 pm ) + +__________________________________________________________________________________________ + +Wrong Format Liao +Wrong Format Liao + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +[D][X] 1. ( sundayafternoon 3-4 pm ) +[T][] 2. read book +[D][] 3. study ( sundayafternoon 3-4 pm ) +[D][] 4. ( sundayafternoon 3-4 pm ) + +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [E][] 5. team project ( friday 3-4 pm .. ) +You have 5 tasks in the list! +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Wah~ You done the task: [D][X] 3. study ( sundayafternoon 3-4 pm ) +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +[D][X] 1. ( sundayafternoon 3-4 pm ) +[T][] 2. read book +[D][X] 3. study ( sundayafternoon 3-4 pm ) +[D][] 4. ( sundayafternoon 3-4 pm ) +[E][] 5. team project ( friday 3-4 pm .. ) + +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +I zao liao, don't miss me. +__________________________________________________________________________________________ + diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 657e74f6e7..d547d510c3 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,7 +1,90 @@ -Hello from - ____ _ -| _ \ _ _| | _____ + ____ _ +| _ \ _ _| | _____ | | | | | | | |/ / _ \ | |_| | |_| | < __/ |____/ \__,_|_|\_\___| + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Awww, need help ah? +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [T][] 1. read book +You have 1 tasks in the list! +__________________________________________________________________________________________ + +Wrong Format Liao +Wrong Format Liao +Wrong Format Liao + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [D][] 2. study ( sundayafternoon 3-4 pm ) +You have 2 tasks in the list! +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Wah~ You done the task: [T][X] 1. read book +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Walao!No such task! +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +[T][X] 1. read book +[D][] 2. study ( sundayafternoon 3-4 pm ) + +__________________________________________________________________________________________ + +Wrong Format Liao +Wrong Format Liao + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +[T][X] 1. read book +[D][] 2. study ( sundayafternoon 3-4 pm ) + +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [E][] 3. team project ( friday 3-4 pm .. ) +You have 3 tasks in the list! +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Wah~ You done the task: [E][X] 3. team project ( friday 3-4 pm .. ) +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +[T][X] 1. read book +[D][] 2. study ( sundayafternoon 3-4 pm ) +[E][X] 3. team project ( friday 3-4 pm .. ) + +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +I zao liao, don't miss me. +__________________________________________________________________________________________ + diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e69de29bb2..43b4a3b0f2 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -0,0 +1,17 @@ +deadline /SundayAfternoon 3-4 pm +todo read book +todo +deadline study +deadline +deadline study /SundayAfternoon 3-4 pm +deadline /SundayAfternoon 3-4 pm +done 1 +done 10 +list +event team project +event +list +event team project /Friday 3-4 pm .. +done 3 +list +bye From 31f4e3a467af6b58dfef9a79f3be1934c8402d7f Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 20:35:21 +0800 Subject: [PATCH 12/62] A-TextUiTesting --- text-ui-test/ACTUAL.TXT | 50 +++++++++++++-------------------------- text-ui-test/EXPECTED.TXT | 6 +++-- 2 files changed, 20 insertions(+), 36 deletions(-) diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index da4b7fadc5..f555eb2e21 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -10,41 +10,29 @@ Awww, need help ah? __________________________________________________________________________________________ +Wrong Format Liao ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Added liao: [D][] 1. ( sundayafternoon 3-4 pm ) +Added liao: [T][] 1. read book You have 1 tasks in the list! __________________________________________________________________________________________ - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Added liao: [T][] 2. read book -You have 2 tasks in the list! -__________________________________________________________________________________________ - Wrong Format Liao Wrong Format Liao Wrong Format Liao ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Added liao: [D][] 3. study ( sundayafternoon 3-4 pm ) -You have 3 tasks in the list! -__________________________________________________________________________________________ - - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Added liao: [D][] 4. ( sundayafternoon 3-4 pm ) -You have 4 tasks in the list! +Added liao: [D][] 2. study ( sundayafternoon 3-4 pm ) +You have 2 tasks in the list! __________________________________________________________________________________________ +Wrong Format Liao ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Wah~ You done the task: [D][X] 1. ( sundayafternoon 3-4 pm ) +Wah~ You done the task: [T][X] 1. read book __________________________________________________________________________________________ @@ -57,10 +45,8 @@ ________________________________________________________________________________ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -[D][X] 1. ( sundayafternoon 3-4 pm ) -[T][] 2. read book -[D][] 3. study ( sundayafternoon 3-4 pm ) -[D][] 4. ( sundayafternoon 3-4 pm ) +[T][X] 1. read book +[D][] 2. study ( sundayafternoon 3-4 pm ) __________________________________________________________________________________________ @@ -70,35 +56,31 @@ Wrong Format Liao ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -[D][X] 1. ( sundayafternoon 3-4 pm ) -[T][] 2. read book -[D][] 3. study ( sundayafternoon 3-4 pm ) -[D][] 4. ( sundayafternoon 3-4 pm ) +[T][X] 1. read book +[D][] 2. study ( sundayafternoon 3-4 pm ) __________________________________________________________________________________________ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Added liao: [E][] 5. team project ( friday 3-4 pm .. ) -You have 5 tasks in the list! +Added liao: [E][] 3. team project ( friday 3-4 pm .. ) +You have 3 tasks in the list! __________________________________________________________________________________________ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Wah~ You done the task: [D][X] 3. study ( sundayafternoon 3-4 pm ) +Wah~ You done the task: [E][X] 3. team project ( friday 3-4 pm .. ) __________________________________________________________________________________________ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -[D][X] 1. ( sundayafternoon 3-4 pm ) -[T][] 2. read book -[D][X] 3. study ( sundayafternoon 3-4 pm ) -[D][] 4. ( sundayafternoon 3-4 pm ) -[E][] 5. team project ( friday 3-4 pm .. ) +[T][X] 1. read book +[D][] 2. study ( sundayafternoon 3-4 pm ) +[E][X] 3. team project ( friday 3-4 pm .. ) __________________________________________________________________________________________ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index d547d510c3..f555eb2e21 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,5 +1,5 @@ - ____ _ -| _ \ _ _| | _____ + ____ _ +| _ \ _ _| | _____ | | | | | | | |/ / _ \ | |_| | |_| | < __/ |____/ \__,_|_|\_\___| @@ -10,6 +10,7 @@ Awww, need help ah? __________________________________________________________________________________________ +Wrong Format Liao ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -27,6 +28,7 @@ Added liao: [D][] 2. study ( sundayafternoon 3-4 pm ) You have 2 tasks in the list! __________________________________________________________________________________________ +Wrong Format Liao ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 41befe9403d2287d296aed498cbcd977eb00d47d Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 21:05:40 +0800 Subject: [PATCH 13/62] Implement exception --- src/main/java/DukeException.java | 2 + text-ui-test/ACTUAL.TXT | 73 -------------------------------- text-ui-test/EXPECTED.TXT | 73 -------------------------------- text-ui-test/input.txt | 1 - 4 files changed, 2 insertions(+), 147 deletions(-) create mode 100644 src/main/java/DukeException.java diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java new file mode 100644 index 0000000000..882a052746 --- /dev/null +++ b/src/main/java/DukeException.java @@ -0,0 +1,2 @@ +package PACKAGE_NAME;public class DukeException { +} diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index f555eb2e21..b646323ab6 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -10,7 +10,6 @@ Awww, need help ah? __________________________________________________________________________________________ -Wrong Format Liao ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,75 +17,3 @@ Added liao: [T][] 1. read book You have 1 tasks in the list! __________________________________________________________________________________________ -Wrong Format Liao -Wrong Format Liao -Wrong Format Liao - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Added liao: [D][] 2. study ( sundayafternoon 3-4 pm ) -You have 2 tasks in the list! -__________________________________________________________________________________________ - -Wrong Format Liao - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Wah~ You done the task: [T][X] 1. read book -__________________________________________________________________________________________ - - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Walao!No such task! -__________________________________________________________________________________________ - - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - -[T][X] 1. read book -[D][] 2. study ( sundayafternoon 3-4 pm ) - -__________________________________________________________________________________________ - -Wrong Format Liao -Wrong Format Liao - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - -[T][X] 1. read book -[D][] 2. study ( sundayafternoon 3-4 pm ) - -__________________________________________________________________________________________ - - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Added liao: [E][] 3. team project ( friday 3-4 pm .. ) -You have 3 tasks in the list! -__________________________________________________________________________________________ - - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Wah~ You done the task: [E][X] 3. team project ( friday 3-4 pm .. ) -__________________________________________________________________________________________ - - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - -[T][X] 1. read book -[D][] 2. study ( sundayafternoon 3-4 pm ) -[E][X] 3. team project ( friday 3-4 pm .. ) - -__________________________________________________________________________________________ - - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -I zao liao, don't miss me. -__________________________________________________________________________________________ - diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index f555eb2e21..b646323ab6 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -10,7 +10,6 @@ Awww, need help ah? __________________________________________________________________________________________ -Wrong Format Liao ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,75 +17,3 @@ Added liao: [T][] 1. read book You have 1 tasks in the list! __________________________________________________________________________________________ -Wrong Format Liao -Wrong Format Liao -Wrong Format Liao - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Added liao: [D][] 2. study ( sundayafternoon 3-4 pm ) -You have 2 tasks in the list! -__________________________________________________________________________________________ - -Wrong Format Liao - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Wah~ You done the task: [T][X] 1. read book -__________________________________________________________________________________________ - - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Walao!No such task! -__________________________________________________________________________________________ - - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - -[T][X] 1. read book -[D][] 2. study ( sundayafternoon 3-4 pm ) - -__________________________________________________________________________________________ - -Wrong Format Liao -Wrong Format Liao - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - -[T][X] 1. read book -[D][] 2. study ( sundayafternoon 3-4 pm ) - -__________________________________________________________________________________________ - - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Added liao: [E][] 3. team project ( friday 3-4 pm .. ) -You have 3 tasks in the list! -__________________________________________________________________________________________ - - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Wah~ You done the task: [E][X] 3. team project ( friday 3-4 pm .. ) -__________________________________________________________________________________________ - - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - -[T][X] 1. read book -[D][] 2. study ( sundayafternoon 3-4 pm ) -[E][X] 3. team project ( friday 3-4 pm .. ) - -__________________________________________________________________________________________ - - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -I zao liao, don't miss me. -__________________________________________________________________________________________ - diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 43b4a3b0f2..d82ad643c5 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,4 +1,3 @@ -deadline /SundayAfternoon 3-4 pm todo read book todo deadline study From f6fb507da62cdbe9ab886e5e2e5014e8703e95a2 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 22:04:31 +0800 Subject: [PATCH 14/62] Add excepetions --- src/main/java/Duke.java | 33 ++++++++++++++++++-------------- src/main/java/DukeException.java | 5 ++++- src/main/java/Format.java | 9 +++++---- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index f21f29ec6e..c02c9663b2 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -4,7 +4,7 @@ public class Duke { - public static void main(String[] args) { + public static void main(String[] args) throws DukeException { Scanner sc = new Scanner(System.in); System.out.println(Format.LOGO); @@ -20,7 +20,7 @@ public static void main(String[] args) { System.out.println(Format.farewell); } - public static void handleDone(String[] line) { + public static void handleDone(String[] line) throws DukeException { if (line.length == 2) { String arg = line[1].replaceAll("[^0-9]", ""); try { @@ -30,52 +30,58 @@ public static void handleDone(String[] line) { System.out.println("Please lah, key in number"); } } else { - Format.WRONGFORMAT(); + throw new DukeException(Format.ARGSERR); } } - public static void handleToDo(String[] line, String message) { + public static void handleToDo(String[] line, String message) throws DukeException { if (line.length > 1) { String msg = message.replaceAll(line[0], "") .trim(); Todo todo = new Todo(msg); System.out.println(Format.biggerBox(todo)); } else { - Format.WRONGFORMAT(); + throw new DukeException(Format.ARGSERR); } } - public static void handleDeadline(String[] line, String message) { + public static void handleDeadline(String[] line, String message) throws DukeException { if (line.length > 2) { String[] comments = message.trim().toLowerCase().split("/"); String msg = comments[0].replaceAll(line[0], "").trim(); if (comments.length == 2) { + if (msg.equals("")) { + throw new DukeException(Format.EMPTYBODY); + } Deadlines deadline = new Deadlines(msg, comments[1]); System.out.println(Format.biggerBox(deadline)); } else { - Format.WRONGFORMAT(); + throw new DukeException(Format.SLASHERR); } } else { - Format.WRONGFORMAT(); + throw new DukeException(Format.MISSINGERR); } } - public static void handleEvent(String[] line, String message) { + public static void handleEvent(String[] line, String message) throws DukeException { if (line.length > 2) { String[] comments = message.trim().toLowerCase().split("/"); String msg = comments[0].replaceAll(line[0], "").trim(); if (comments.length == 2) { + if (msg.equals("")) { + throw new DukeException(Format.EMPTYBODY); + } Event event = new Event(msg, comments[1]); System.out.println(Format.biggerBox(event)); } else { - Format.WRONGFORMAT(); + throw new DukeException(Format.SLASHERR); } } else { - Format.WRONGFORMAT(); + throw new DukeException(Format.MISSINGERR); } } - public static boolean inputHandler(String message) { + public static boolean inputHandler(String message) throws DukeException { String[] line = message.trim().toLowerCase().split(" "); String command = line[0]; if (command.equals("bye")) { @@ -92,8 +98,7 @@ public static boolean inputHandler(String message) { } else if (command.equals("event")){ handleEvent(line, message); } else { - Task task = new Task(message); - System.out.println(Format.chatBox("Added: " + message)); + throw new DukeException(Format.COMMANDERR); } return false; } diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java index 882a052746..50a98b4a04 100644 --- a/src/main/java/DukeException.java +++ b/src/main/java/DukeException.java @@ -1,2 +1,5 @@ -package PACKAGE_NAME;public class DukeException { +public class DukeException extends Exception{ + public DukeException(String msg) { + super(msg); + } } diff --git a/src/main/java/Format.java b/src/main/java/Format.java index 1efcf8acc1..49a0a871c4 100644 --- a/src/main/java/Format.java +++ b/src/main/java/Format.java @@ -9,10 +9,11 @@ public class Format { + "| |_| | |_| | < __/\n" + "|____/ \\__,_|_|\\_\\___|\n"; - public static final void WRONGFORMAT() { - System.out.println("Wrong Format Liao"); - } - + public static final String EMPTYBODY = "Walao!Description empty!"; + public static final String SLASHERR = "Too many / or no /, only 1 / allow for dates and time"; + public static final String ARGSERR = "TOO MANY OR TOO FEW ARGUMENTS"; + public static final String MISSINGERR = "Missing description or dates"; + public static final String COMMANDERR = "I DON'T KNOW WHAT U SAYING"; public static final String farewell = UPPER + "I zao liao, don't miss me." + LOWER; From 5f07877ef8f4a600c33626c3b3f589b898c1f541 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 22:08:02 +0800 Subject: [PATCH 15/62] change structure of taskList from array to arrayList --- src/main/java/Task.java | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/main/java/Task.java b/src/main/java/Task.java index c188f9fda0..49dfccca3b 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -1,5 +1,8 @@ +import java.util.ArrayList; +import java.util.List; + public class Task { - private static Task[] taskList = new Task[100]; + private static List taskList = new ArrayList<>(); private String taskName; private static int capacity = 0; private int index; @@ -13,17 +16,18 @@ public class Task { } private static void add(Task t) { - taskList[capacity - 1] = t; + taskList.add(t); } - public static final void done(int i) { - if (taskList[i - 1] != null) { - taskList[i - 1].done = "X"; + public static final void done(int i) throws DukeException { + try { + Task t = taskList.get(i - 1); + taskList.get(i - 1).done = "X"; System.out.println(Format.UPPER + "Wah~ You done the task: " - + " " + taskList[i - 1].toString() + Format.LOWER); - } else { - System.out.println(Format.chatBox("Walao!No such task!")); + + " " + t.toString() + Format.LOWER); + } catch (IndexOutOfBoundsException err) { + throw new DukeException(Format.chatBox("Walao!No such task!")); } } @@ -31,7 +35,7 @@ public String getTaskName() { return taskName; } - public static final Task[] getTaskList() { + public static final List getTaskList() { return Task.taskList; } From 3b31da6d05d207ea66a49b2e0ea60fefbf8044a2 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 22:44:04 +0800 Subject: [PATCH 16/62] Level-5, implemented Exception --- src/main/java/Duke.java | 42 +++++++++++++++++--------------- src/main/java/DukeException.java | 27 +++++++++++++++++--- src/main/java/Format.java | 6 +---- src/main/java/Task.java | 10 +++++--- 4 files changed, 54 insertions(+), 31 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index c02c9663b2..02f0593ab3 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -4,7 +4,7 @@ public class Duke { - public static void main(String[] args) throws DukeException { + public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println(Format.LOGO); @@ -20,7 +20,7 @@ public static void main(String[] args) throws DukeException { System.out.println(Format.farewell); } - public static void handleDone(String[] line) throws DukeException { + public static void handleDone(String[] line) { if (line.length == 2) { String arg = line[1].replaceAll("[^0-9]", ""); try { @@ -30,58 +30,62 @@ public static void handleDone(String[] line) throws DukeException { System.out.println("Please lah, key in number"); } } else { - throw new DukeException(Format.ARGSERR); + DukeException.argumentErrorException(); } } - public static void handleToDo(String[] line, String message) throws DukeException { + public static void handleToDo(String[] line, String message) { if (line.length > 1) { String msg = message.replaceAll(line[0], "") .trim(); Todo todo = new Todo(msg); System.out.println(Format.biggerBox(todo)); } else { - throw new DukeException(Format.ARGSERR); + DukeException.argumentErrorException(); } } - public static void handleDeadline(String[] line, String message) throws DukeException { + public static void handleDeadline(String[] line, String message) { if (line.length > 2) { String[] comments = message.trim().toLowerCase().split("/"); String msg = comments[0].replaceAll(line[0], "").trim(); if (comments.length == 2) { if (msg.equals("")) { - throw new DukeException(Format.EMPTYBODY); + DukeException.emptyBodyException(); + } else { + Deadlines deadline = new Deadlines(msg, comments[1]); + System.out.println(Format.biggerBox(deadline)); } - Deadlines deadline = new Deadlines(msg, comments[1]); - System.out.println(Format.biggerBox(deadline)); } else { - throw new DukeException(Format.SLASHERR); + DukeException.slashErrorException(); } } else { - throw new DukeException(Format.MISSINGERR); + DukeException.missingArgumentErrorException(); } } - public static void handleEvent(String[] line, String message) throws DukeException { + public static void handleEvent(String[] line, String message) { if (line.length > 2) { String[] comments = message.trim().toLowerCase().split("/"); String msg = comments[0].replaceAll(line[0], "").trim(); if (comments.length == 2) { if (msg.equals("")) { - throw new DukeException(Format.EMPTYBODY); + DukeException.emptyBodyException(); + } else { + Event event = new Event(msg, comments[1]); + System.out.println(Format.biggerBox(event)); } - Event event = new Event(msg, comments[1]); - System.out.println(Format.biggerBox(event)); } else { - throw new DukeException(Format.SLASHERR); + DukeException.slashErrorException(); } } else { - throw new DukeException(Format.MISSINGERR); + DukeException.missingArgumentErrorException(); } } - public static boolean inputHandler(String message) throws DukeException { + + + public static boolean inputHandler(String message) { String[] line = message.trim().toLowerCase().split(" "); String command = line[0]; if (command.equals("bye")) { @@ -98,7 +102,7 @@ public static boolean inputHandler(String message) throws DukeException { } else if (command.equals("event")){ handleEvent(line, message); } else { - throw new DukeException(Format.COMMANDERR); + DukeException.commandErrorException(); } return false; } diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java index 50a98b4a04..d80093204d 100644 --- a/src/main/java/DukeException.java +++ b/src/main/java/DukeException.java @@ -1,5 +1,26 @@ -public class DukeException extends Exception{ - public DukeException(String msg) { - super(msg); +public class DukeException{ + + public static final void emptyBodyException() { + System.out.println("Walao!Description empty!"); + } + + public static final void slashErrorException() { + System.out.println("??? Too many / or no /, only 1 / allow for dates and time"); + } + + public static final void argumentErrorException() { + System.out.println("You put so many/few ARGUMENTS for what"); + } + + public static final void missingArgumentErrorException() { + System.out.println("Fill ur description or date lah"); + } + + public static final void commandErrorException() { + System.out.println("I DON'T KNOW WHAT U SAYING BRO"); + } + + public static final void taskErrorException() { + System.out.println("Walao, no such task"); } } diff --git a/src/main/java/Format.java b/src/main/java/Format.java index 49a0a871c4..38cf8d90d8 100644 --- a/src/main/java/Format.java +++ b/src/main/java/Format.java @@ -9,11 +9,7 @@ public class Format { + "| |_| | |_| | < __/\n" + "|____/ \\__,_|_|\\_\\___|\n"; - public static final String EMPTYBODY = "Walao!Description empty!"; - public static final String SLASHERR = "Too many / or no /, only 1 / allow for dates and time"; - public static final String ARGSERR = "TOO MANY OR TOO FEW ARGUMENTS"; - public static final String MISSINGERR = "Missing description or dates"; - public static final String COMMANDERR = "I DON'T KNOW WHAT U SAYING"; + public static final String farewell = UPPER + "I zao liao, don't miss me." + LOWER; diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 49dfccca3b..4e3d5a95e3 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -10,7 +10,7 @@ public class Task { Task(String taskName) { this.taskName = taskName; this.index = capacity + 1; - this.done = ""; + this.done = " "; capacity++; add(this); } @@ -20,17 +20,19 @@ private static void add(Task t) { } - public static final void done(int i) throws DukeException { + public static final void done(int i) { try { Task t = taskList.get(i - 1); taskList.get(i - 1).done = "X"; System.out.println(Format.UPPER + "Wah~ You done the task: " + " " + t.toString() + Format.LOWER); - } catch (IndexOutOfBoundsException err) { - throw new DukeException(Format.chatBox("Walao!No such task!")); + } catch (IndexOutOfBoundsException e) { + DukeException.taskErrorException(); } } + + public String getTaskName() { return taskName; } From 63040239067dbdd22a59d43cf5d96b6ca09e0315 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 23:17:18 +0800 Subject: [PATCH 17/62] small change to variable name --- src/main/java/Format.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/Format.java b/src/main/java/Format.java index 38cf8d90d8..4a41ce2d2e 100644 --- a/src/main/java/Format.java +++ b/src/main/java/Format.java @@ -1,8 +1,8 @@ public class Format { - public static final String SPACE = "\n"; - public static final String UPPER = SPACE + "^".repeat(90) + SPACE.repeat(2); - public static final String LOWER = SPACE.repeat(1) + "_".repeat(90) + SPACE; + public static final String LINEBREAK = "\n"; + public static final String UPPER = LINEBREAK + "^".repeat(90) + LINEBREAK.repeat(2); + public static final String LOWER = LINEBREAK.repeat(1) + "_".repeat(90) + LINEBREAK; public static final String LOGO = " ____ _ \n" + "| _ \\ _ _| | _____ \n" + "| | | | | | | |/ / _ \\\n" @@ -27,7 +27,7 @@ public static final String chatBox(String s) { public static final String biggerBox(Task t) { return Format.UPPER + "Added liao: " - + t.toString() + Format.SPACE + + t.toString() + Format.LINEBREAK + "You have " + Task.getCapacity() + " tasks in the list!" + Format.LOWER; } From e91d398918573e45003587311d69f2a995bfe68e Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 20 Jan 2021 23:47:38 +0800 Subject: [PATCH 18/62] Added JavacDoc --- src/main/java/Deadlines.java | 9 ++++++ src/main/java/Duke.java | 41 +++++++++++++++++++++++++-- src/main/java/DukeException.java | 27 ++++++++++++++++++ src/main/java/Event.java | 8 ++++++ src/main/java/Format.java | 18 ++++++++++++ src/main/java/Task.java | 48 ++++++++++++++++++++++++++++++-- src/main/java/Todo.java | 8 +++++- 7 files changed, 154 insertions(+), 5 deletions(-) diff --git a/src/main/java/Deadlines.java b/src/main/java/Deadlines.java index c773d2278f..bb45b04cb6 100644 --- a/src/main/java/Deadlines.java +++ b/src/main/java/Deadlines.java @@ -1,7 +1,16 @@ +/** + * sub-class of Task to represents a task with deadline. + */ public class Deadlines extends Task{ private String comments; + /** + * create a deadline task object with given task name and given dates/comments. + * + * @param taskName String representation of the name of the task. + * @param comments String representation of the comments/dates. + */ public Deadlines(String taskName, String comments) { super(taskName); this.comments = comments; diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 02f0593ab3..47a2e6dbaf 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,9 +1,16 @@ import java.util.Arrays; import java.util.Scanner; +/** + * Encapsulates the main class of the Object. + */ public class Duke { - + /** + * Executes the programs. + * + * @param args command line arguments key in by user. + */ public static void main(String[] args) { Scanner sc = new Scanner(System.in); @@ -20,6 +27,11 @@ public static void main(String[] args) { System.out.println(Format.farewell); } + /** + * handle done command key in by user. + * + * @param line String array of the full line key in by user. + */ public static void handleDone(String[] line) { if (line.length == 2) { String arg = line[1].replaceAll("[^0-9]", ""); @@ -34,6 +46,13 @@ public static void handleDone(String[] line) { } } + + /** + * handle todo command key in by user + * + * @param line String array of the full line key in by user. + * @param message the name of the task to be set. + */ public static void handleToDo(String[] line, String message) { if (line.length > 1) { String msg = message.replaceAll(line[0], "") @@ -44,6 +63,13 @@ public static void handleToDo(String[] line, String message) { DukeException.argumentErrorException(); } } + + /** + * handle deadline command user key in. + * + * @param line String array of the full line that user key in. + * @param message String representation of the name of the task key in. + */ public static void handleDeadline(String[] line, String message) { if (line.length > 2) { String[] comments = message.trim().toLowerCase().split("/"); @@ -64,6 +90,12 @@ public static void handleDeadline(String[] line, String message) { } } + /** + * handle event command key in by user. + * + * @param line String array of the full line key in by user. + * @param message String representation of the name of the task key in by user. + */ public static void handleEvent(String[] line, String message) { if (line.length > 2) { String[] comments = message.trim().toLowerCase().split("/"); @@ -84,7 +116,12 @@ public static void handleEvent(String[] line, String message) { } - + /** + * The main handler of all the command. + * + * @param message String representation of the message key in by user. + * @return a boolean to whether to exit the program. + */ public static boolean inputHandler(String message) { String[] line = message.trim().toLowerCase().split(" "); String command = line[0]; diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java index d80093204d..9c3307a8c1 100644 --- a/src/main/java/DukeException.java +++ b/src/main/java/DukeException.java @@ -1,25 +1,52 @@ +/** + * A class that store all the possible display of errorsException in Duke. + */ public class DukeException{ + /** + * display the error message for empty body error. + * + */ public static final void emptyBodyException() { System.out.println("Walao!Description empty!"); } + /** + * display the error message for slash error. + * + */ public static final void slashErrorException() { System.out.println("??? Too many / or no /, only 1 / allow for dates and time"); } + /** + * display the error message for too many argument error. + * + */ public static final void argumentErrorException() { System.out.println("You put so many/few ARGUMENTS for what"); } + /** + * display the error message for missing argument error. + * + */ public static final void missingArgumentErrorException() { System.out.println("Fill ur description or date lah"); } + /** + * display the error message for command error. + * + */ public static final void commandErrorException() { System.out.println("I DON'T KNOW WHAT U SAYING BRO"); } + /** + * display the error message for missing task error. + * + */ public static final void taskErrorException() { System.out.println("Walao, no such task"); } diff --git a/src/main/java/Event.java b/src/main/java/Event.java index 57876f8205..8cd47f648e 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -1,6 +1,14 @@ +/** + * A subclass of Task that represent an event key in by user. + */ public class Event extends Task{ private String comments; + /** + * Create a event Task with given task name and given comments/dates. + * @param taskName name of the task. + * @param comments dates or comments of the user regarding the task. + */ public Event(String taskName, String comments) { super(taskName); this.comments = comments; diff --git a/src/main/java/Format.java b/src/main/java/Format.java index 4a41ce2d2e..58ac026687 100644 --- a/src/main/java/Format.java +++ b/src/main/java/Format.java @@ -1,3 +1,6 @@ +/** + * A class that store all the possible String format for Duke for code simplicity. + */ public class Format { public static final String LINEBREAK = "\n"; @@ -17,6 +20,11 @@ public class Format { + "Awww, need help ah?" + LOWER; + /** + * make a chatBox that wrap a given String. + * @param s the String to be wrapped. + * @return a String with a chatBox wrapped. + */ public static final String chatBox(String s) { if (s.length() > 50) { return "Walao! Your command too long lah!"; @@ -25,6 +33,12 @@ public static final String chatBox(String s) { } } + + /** + * make a Bigger ChatBox that wrap the name of a given Task. + * @param t task to be wrapped. + * @return the String representation of the task name wrapped in a chatBox. + */ public static final String biggerBox(Task t) { return Format.UPPER + "Added liao: " + t.toString() + Format.LINEBREAK @@ -32,6 +46,10 @@ public static final String biggerBox(Task t) { + Format.LOWER; } + /** + * Display all the current task and status store in the tasklist. + * + */ public static final void LISTING() { System.out.println(UPPER); for (Task task : Task.getTaskList()) { diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 4e3d5a95e3..f25c901ea3 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -1,12 +1,21 @@ import java.util.ArrayList; import java.util.List; +/** + * A class that store the task that user key in. + */ public class Task { private static List taskList = new ArrayList<>(); private String taskName; private static int capacity = 0; private int index; private String done; + + /** + * Construct a task object with taskname attached and its index label in the taskList. + * @param taskName name of the task. + */ + Task(String taskName) { this.taskName = taskName; this.index = capacity + 1; @@ -15,11 +24,20 @@ public class Task { add(this); } + /** + * Store the task key in by user in the taskList. + * + * @param t Task key in by user. + */ private static void add(Task t) { taskList.add(t); } - + /** + * Mark a given task as done. + * + * @param i the index label of the Task. + */ public static final void done(int i) { try { Task t = taskList.get(i - 1); @@ -32,26 +50,52 @@ public static final void done(int i) { } - + /** + * Get the name of the task. + * + * @return a String representation of the task name. + */ public String getTaskName() { return taskName; } + /** + * Get the taskList. + * + * @return the List of all tasks stored. + */ + public static final List getTaskList() { return Task.taskList; } + /** + * get the isDone status of the task. + * + * @return a String representation of the isDone status (X for done). + */ public String isDone() { return done; } + /** + * get the index label of the task. + * + * @return the int representation of the index label. + */ public int getIndex() { return index; } + /** + * get the current capacity of the taskList. + * + * @return the int representation of the capacity of the taskList. + */ public static final int getCapacity() { return Task.capacity; } + @Override public String toString() { return String.format("[%s] %d. %s", done, index, taskName); diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java index f7cef76f29..5604984d9e 100644 --- a/src/main/java/Todo.java +++ b/src/main/java/Todo.java @@ -1,6 +1,12 @@ +/** + * A sub-class of Task to represents a toDo task key in by user. + */ public class Todo extends Task{ - + /** + * Create a toDo task with given taskName attached. + * @param taskName name of the task in String. + */ public Todo(String taskName) { super(taskName); From 36a0a9d159cac6dfaf2d25adbbebbddbc7a875aa Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Fri, 22 Jan 2021 20:06:48 +0800 Subject: [PATCH 19/62] Added DukeDriver for simplicity --- src/main/java/Duke.java | 126 +----------------------------- src/main/java/DukeDriver.java | 140 ++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 125 deletions(-) create mode 100644 src/main/java/DukeDriver.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 47a2e6dbaf..63e344e0a4 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -13,135 +13,11 @@ public class Duke { */ public static void main(String[] args) { - Scanner sc = new Scanner(System.in); - System.out.println(Format.LOGO); - System.out.println(Format.greeting); - - while(sc.hasNext()) { - String message = sc.nextLine(); - boolean bye = inputHandler(message); - if (bye) { - break; - } - } - System.out.println(Format.farewell); - } - - /** - * handle done command key in by user. - * - * @param line String array of the full line key in by user. - */ - public static void handleDone(String[] line) { - if (line.length == 2) { - String arg = line[1].replaceAll("[^0-9]", ""); - try { - int num = Integer.parseInt(arg); - Task.done(num); - } catch (NumberFormatException e) { - System.out.println("Please lah, key in number"); - } - } else { - DukeException.argumentErrorException(); - } - } - - - /** - * handle todo command key in by user - * - * @param line String array of the full line key in by user. - * @param message the name of the task to be set. - */ - public static void handleToDo(String[] line, String message) { - if (line.length > 1) { - String msg = message.replaceAll(line[0], "") - .trim(); - Todo todo = new Todo(msg); - System.out.println(Format.biggerBox(todo)); - } else { - DukeException.argumentErrorException(); - } + DukeDriver.executeDuke(); } - /** - * handle deadline command user key in. - * - * @param line String array of the full line that user key in. - * @param message String representation of the name of the task key in. - */ - public static void handleDeadline(String[] line, String message) { - if (line.length > 2) { - String[] comments = message.trim().toLowerCase().split("/"); - String msg = comments[0].replaceAll(line[0], "").trim(); - if (comments.length == 2) { - if (msg.equals("")) { - DukeException.emptyBodyException(); - } else { - Deadlines deadline = new Deadlines(msg, comments[1]); - System.out.println(Format.biggerBox(deadline)); - } - } else { - DukeException.slashErrorException(); - } - } else { - DukeException.missingArgumentErrorException(); - } - } - /** - * handle event command key in by user. - * - * @param line String array of the full line key in by user. - * @param message String representation of the name of the task key in by user. - */ - public static void handleEvent(String[] line, String message) { - if (line.length > 2) { - String[] comments = message.trim().toLowerCase().split("/"); - String msg = comments[0].replaceAll(line[0], "").trim(); - if (comments.length == 2) { - if (msg.equals("")) { - DukeException.emptyBodyException(); - } else { - Event event = new Event(msg, comments[1]); - System.out.println(Format.biggerBox(event)); - } - } else { - DukeException.slashErrorException(); - } - } else { - DukeException.missingArgumentErrorException(); - } - } - /** - * The main handler of all the command. - * - * @param message String representation of the message key in by user. - * @return a boolean to whether to exit the program. - */ - public static boolean inputHandler(String message) { - String[] line = message.trim().toLowerCase().split(" "); - String command = line[0]; - if (command.equals("bye")) { - return true; - } else { - if (command.equals("list")) { - Format.LISTING(); - } else if (command.equals("done")) { - handleDone(line); - } else if (command.equals("todo")) { - handleToDo(line, message); - } else if (command.equals("deadline")) { - handleDeadline(line, message); - } else if (command.equals("event")){ - handleEvent(line, message); - } else { - DukeException.commandErrorException(); - } - return false; - } - } } diff --git a/src/main/java/DukeDriver.java b/src/main/java/DukeDriver.java new file mode 100644 index 0000000000..521945055e --- /dev/null +++ b/src/main/java/DukeDriver.java @@ -0,0 +1,140 @@ +import java.util.Scanner; + +public class DukeDriver { + + public static void executeDuke() { + Scanner sc = new Scanner(System.in); + System.out.println(Format.LOGO); + System.out.println(Format.greeting); + + while(sc.hasNext()) { + String message = sc.nextLine(); + boolean bye = inputHandler(message); + if (bye) { + break; + } + } + System.out.println(Format.farewell); + } + + /** + * handle done command key in by user. + * + * @param line String array of the full line key in by user. + */ + private static final void handleDone(String[] line) { + if (line.length == 2) { + String arg = line[1].replaceAll("[^0-9]", ""); + try { + int num = Integer.parseInt(arg); + Task.done(num); + } catch (NumberFormatException e) { + System.out.println("Please lah, key in number"); + } + } else { + DukeException.argumentErrorException(); + } + } + + /** + * handle todo command key in by user. + * + * @param line String array of the full line key in by user. + * @param message the name of the task to be set. + */ + private static final void handleToDo(String[] line, String message) { + if (line.length > 1) { + String msg = message.replaceAll(line[0], "") + .trim(); + Todo todo = new Todo(msg); + System.out.println(Format.biggerBox(todo)); + } else { + DukeException.argumentErrorException(); + } + } + + /** + * handle deadline command key in by user. + * + * @param line String array of the full line that user key in. + * @param message String representation of the name of the task key in. + */ + private static final void handleDeadline(String[] line, String message) { + if (line.length > 2) { + String[] comments = message.trim().toLowerCase().split("/"); + String msg = comments[0].replaceAll(line[0], "").trim(); + if (comments.length == 2) { + if (msg.equals("")) { + DukeException.emptyBodyException(); + } else { + Deadlines deadline = new Deadlines(msg, comments[1]); + System.out.println(Format.biggerBox(deadline)); + } + } else { + DukeException.slashErrorException(); + } + + } else { + DukeException.missingArgumentErrorException(); + } + } + + /** + * handle event command key in by user. + * + * @param line String array of the full line key in by user. + * @param message String representation of the name of the task key in by user. + */ + private static final void handleEvent(String[] line, String message) { + if (line.length > 2) { + String[] comments = message.trim().toLowerCase().split("/"); + String msg = comments[0].replaceAll(line[0], "").trim(); + if (comments.length == 2) { + if (msg.equals("")) { + DukeException.emptyBodyException(); + } else { + Event event = new Event(msg, comments[1]); + System.out.println(Format.biggerBox(event)); + } + } else { + DukeException.slashErrorException(); + } + } else { + DukeException.missingArgumentErrorException(); + } + } + + + /** + * The main handler of all the command. + * + * @param message String representation of the message key in by user. + * @return a boolean to whether to exit the program. + */ + private static final boolean inputHandler(String message) { + String[] line = message.trim().toLowerCase().split(" "); + String command = line[0]; + if (command.equals("bye")) { + return true; + } else { + if (command.equals("list")) { + Format.LISTING(); + } else if (command.equals("done")) { + handleDone(line); + } else if (command.equals("todo")) { + handleToDo(line, message); + } else if (command.equals("deadline")) { + handleDeadline(line, message); + } else if (command.equals("event")){ + handleEvent(line, message); + } else { + DukeException.commandErrorException(); + } + return false; + } + } + + private static final String extractCommand(String input) { + return input.trim().toLowerCase().split(" ")[0]; + } +} From 200542a5cf60be5dfeeb8829881387ba85498ed4 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Fri, 22 Jan 2021 21:36:08 +0800 Subject: [PATCH 20/62] Simplified Duke driver, modify exceptions and format --- src/main/java/DukeDriver.java | 209 ++++++++++++++++++++----------- src/main/java/DukeException.java | 26 ++-- src/main/java/Format.java | 11 +- src/main/java/Task.java | 1 + 4 files changed, 157 insertions(+), 90 deletions(-) diff --git a/src/main/java/DukeDriver.java b/src/main/java/DukeDriver.java index 521945055e..ac4719cd7f 100644 --- a/src/main/java/DukeDriver.java +++ b/src/main/java/DukeDriver.java @@ -1,11 +1,18 @@ import java.util.Scanner; +/** + * Driver class of Duke that handles the command key in by user and respond. + */ public class DukeDriver { + /** + * Take in user input and execute the Duke program. + * + */ public static void executeDuke() { Scanner sc = new Scanner(System.in); System.out.println(Format.LOGO); - System.out.println(Format.greeting); + System.out.println(Format.GREETING); while(sc.hasNext()) { String message = sc.nextLine(); @@ -14,22 +21,23 @@ public static void executeDuke() { break; } } - System.out.println(Format.farewell); + System.out.println(Format.FAREWELL); } /** - * handle done command key in by user. + * handle done command by marking the task as done. * - * @param line String array of the full line key in by user. + * @param input user input. + * @param command command given by user. */ - private static final void handleDone(String[] line) { - if (line.length == 2) { - String arg = line[1].replaceAll("[^0-9]", ""); + private static final void handleDone(String input, String command) { + String task = extractTask(input, command); + if (task.length() > 0) { try { - int num = Integer.parseInt(arg); + int num = Integer.parseInt(task); Task.done(num); } catch (NumberFormatException e) { - System.out.println("Please lah, key in number"); + DukeException.NumberFormatException(); } } else { DukeException.argumentErrorException(); @@ -37,73 +45,79 @@ private static final void handleDone(String[] line) { } /** - * handle todo command key in by user. + * handle todo command and create a todo task if task is not empty. * - * @param line String array of the full line key in by user. - * @param message the name of the task to be set. + * @param input user input. + * @param command user command. */ - private static final void handleToDo(String[] line, String message) { - if (line.length > 1) { - String msg = message.replaceAll(line[0], "") - .trim(); - Todo todo = new Todo(msg); + private static final void handleToDo(String input, String command) { + String task = extractTask(input, command); + if (!task.equals("")) { + Todo todo = new Todo(task); System.out.println(Format.biggerBox(todo)); } else { - DukeException.argumentErrorException(); + DukeException.emptyTaskException(); } + } /** - * handle deadline command key in by user. + * handle deadline command by creating deadline task if task and date are not empty. * - * @param line String array of the full line that user key in. - * @param message String representation of the name of the task key in. + * @param input user input. + * @param command user command. */ - private static final void handleDeadline(String[] line, String message) { - if (line.length > 2) { - String[] comments = message.trim().toLowerCase().split("/"); - String msg = comments[0].replaceAll(line[0], "").trim(); - if (comments.length == 2) { - if (msg.equals("")) { - DukeException.emptyBodyException(); - } else { - Deadlines deadline = new Deadlines(msg, comments[1]); - System.out.println(Format.biggerBox(deadline)); - } + private static final void handleDeadline(String input, String command) { + String task = extractTask(input, command); + if (task.equals("")) { + DukeException.emptyTaskException(); + } else { + String date = extractDate(input, command); + if (date.equals("")) { + DukeException.missingDateErrorException(); } else { - DukeException.slashErrorException(); + Deadlines deadlines = new Deadlines(task, date); + System.out.println(Format.biggerBox(deadlines)); } - - } else { - DukeException.missingArgumentErrorException(); } } + /** - * handle event command key in by user. + * handle event command by creating event if task and date are not empty. * - * @param line String array of the full line key in by user. - * @param message String representation of the name of the task key in by user. + * @param input user input. + * @param command user command. */ - private static final void handleEvent(String[] line, String message) { - if (line.length > 2) { - String[] comments = message.trim().toLowerCase().split("/"); - String msg = comments[0].replaceAll(line[0], "").trim(); - if (comments.length == 2) { - if (msg.equals("")) { - DukeException.emptyBodyException(); - } else { - Event event = new Event(msg, comments[1]); - System.out.println(Format.biggerBox(event)); - } + private static final void handleEvent(String input, String command) { + String task = extractTask(input, command); + if (task.equals("")) { + DukeException.emptyTaskException(); + } else { + String date = extractDate(input, command); + if (date.equals("")) { + DukeException.missingDateErrorException(); } else { - DukeException.slashErrorException(); + Event event = new Event(task, date); + System.out.println(Format.biggerBox(event)); } - } else { - DukeException.missingArgumentErrorException(); } } + /** + * handle bye command by returning true or false. + * + * @param input user iuput. + * @return a boolean of whether to exit the program. + */ + private static final boolean handleBye(String input) { + if (input.trim().length() > 3) { + DukeException.commandErrorException(); + return false; + } else { + return true; + } + } /** * The main handler of all the command. @@ -112,29 +126,80 @@ private static final void handleEvent(String[] line, String message) { * @return a boolean to whether to exit the program. */ private static final boolean inputHandler(String message) { - String[] line = message.trim().toLowerCase().split(" "); - String command = line[0]; - if (command.equals("bye")) { - return true; - } else { - if (command.equals("list")) { - Format.LISTING(); - } else if (command.equals("done")) { - handleDone(line); - } else if (command.equals("todo")) { - handleToDo(line, message); - } else if (command.equals("deadline")) { - handleDeadline(line, message); - } else if (command.equals("event")){ - handleEvent(line, message); - } else { - DukeException.commandErrorException(); - } - return false; + String command = extractCommand(message); + boolean end = false; + switch (command) { + case "bye": + end = handleBye(message); + break; + case "list": + Format.LISTING(); + break; + case "done": + handleDone(message, command); + break; + case "todo": + handleToDo(message, command); + break; + case "deadline": + handleDeadline(message, command); + break; + case "event": + handleEvent(message, command); + break; + default: + DukeException.commandErrorException(); + break; } + return end; } + + /** + * extract the command key in by user. + * + * @param input the input key in by user. + * @return String representation of the command word of the user input. + */ private static final String extractCommand(String input) { return input.trim().toLowerCase().split(" ")[0]; } + + /** + * extracting task name from user input. + * @param input user input. + * @param command user command. + * @return the task name if there is one and return empty string if task name empty. + */ + private static final String extractTask(String input, String command) { + String body = input.replaceAll(command, "").trim(); + if (command.equals("todo")) { + return body; + } else if (command.equals("done")) { + return body.replaceAll("[^0-9]", ""); + } else { + try { + return body.split("/")[0]; + } catch (ArrayIndexOutOfBoundsException e) { + return ""; + } + } + } + + /** + * extract the date of the task to be done. + * @param input user input. + * @param command user command. + * @return the task date in String and return empty if there is no date. + */ + private static final String extractDate(String input, String command) { + String body = input.replaceAll(command, "").trim(); + String[] parts = body.split("/", 2); + if (parts.length == 2) { + return parts[1]; + } else { + return ""; + } + } + } diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java index 9c3307a8c1..e28c6a65ba 100644 --- a/src/main/java/DukeException.java +++ b/src/main/java/DukeException.java @@ -3,36 +3,33 @@ */ public class DukeException{ - /** - * display the error message for empty body error. - * - */ - public static final void emptyBodyException() { - System.out.println("Walao!Description empty!"); + public static final void NumberFormatException() { + System.out.println(Format.KEYINNUMBER); } /** - * display the error message for slash error. + * display the error message for empty body error. * */ - public static final void slashErrorException() { - System.out.println("??? Too many / or no /, only 1 / allow for dates and time"); + public static final void emptyTaskException() { + System.out.println(Format.EMPTYTASK); } + /** * display the error message for too many argument error. * */ public static final void argumentErrorException() { - System.out.println("You put so many/few ARGUMENTS for what"); + System.out.println(Format.TOOMANYARGUMENTS); } /** * display the error message for missing argument error. * */ - public static final void missingArgumentErrorException() { - System.out.println("Fill ur description or date lah"); + public static final void missingDateErrorException() { + System.out.println(Format.MISSINGDATE); } /** @@ -40,14 +37,13 @@ public static final void missingArgumentErrorException() { * */ public static final void commandErrorException() { - System.out.println("I DON'T KNOW WHAT U SAYING BRO"); + System.out.println(Format.COMMANDERROR); } /** * display the error message for missing task error. * */ - public static final void taskErrorException() { - System.out.println("Walao, no such task"); + public static final void taskErrorException() { System.out.println(Format.TASKERROR); } } diff --git a/src/main/java/Format.java b/src/main/java/Format.java index 58ac026687..ac8a97f3da 100644 --- a/src/main/java/Format.java +++ b/src/main/java/Format.java @@ -12,11 +12,16 @@ public class Format { + "| |_| | |_| | < __/\n" + "|____/ \\__,_|_|\\_\\___|\n"; - - public static final String farewell = UPPER + public static final String KEYINNUMBER = "PLease Lah! Key in number!"; + public static final String EMPTYTASK = "Walao!NO TASK!"; + public static final String TOOMANYARGUMENTS = "You put so many/few ARGUMENTS for what"; + public static final String MISSINGDATE = "Fill ur date lah"; + public static final String COMMANDERROR = "I DON'T KNOW WHAT U SAYING BRO"; + public static final String TASKERROR = "Walao, no such task"; + public static final String FAREWELL = UPPER + "I zao liao, don't miss me." + LOWER; - public static final String greeting = UPPER + public static final String GREETING = UPPER + "Awww, need help ah?" + LOWER; diff --git a/src/main/java/Task.java b/src/main/java/Task.java index f25c901ea3..0cccab5163 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -49,6 +49,7 @@ public static final void done(int i) { } } + /** * Get the name of the task. From c6f0ae8b2cf0b5109007532527394dd21876ccf8 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Fri, 22 Jan 2021 21:53:00 +0800 Subject: [PATCH 21/62] Implemented Delete function --- src/main/java/DukeDriver.java | 19 ++++++++++++++++++- src/main/java/DukeException.java | 3 +-- src/main/java/Task.java | 16 +++++++++++++++- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/main/java/DukeDriver.java b/src/main/java/DukeDriver.java index ac4719cd7f..9b870f2c39 100644 --- a/src/main/java/DukeDriver.java +++ b/src/main/java/DukeDriver.java @@ -119,6 +119,20 @@ private static final boolean handleBye(String input) { } } + private static final void handleDelete(String input, String command) { + String task = extractTask(input, command); + if (task.length() > 0) { + try { + int num = Integer.parseInt(task); + Task.delete(num); + } catch (NumberFormatException e) { + DukeException.NumberFormatException(); + } + } else { + DukeException.argumentErrorException(); + } + } + /** * The main handler of all the command. * @@ -146,6 +160,9 @@ private static final boolean inputHandler(String message) { break; case "event": handleEvent(message, command); + break; + case "delete": + handleDelete(message, command); break; default: DukeException.commandErrorException(); @@ -173,7 +190,7 @@ private static final String extractCommand(String input) { */ private static final String extractTask(String input, String command) { String body = input.replaceAll(command, "").trim(); - if (command.equals("todo")) { + if (command.equals("todo") || command.equals("delete")) { return body; } else if (command.equals("done")) { return body.replaceAll("[^0-9]", ""); diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java index e28c6a65ba..6681db5dae 100644 --- a/src/main/java/DukeException.java +++ b/src/main/java/DukeException.java @@ -44,6 +44,5 @@ public static final void commandErrorException() { * display the error message for missing task error. * */ - public static final void taskErrorException() { System.out.println(Format.TASKERROR); - } + public static final void taskErrorException() { System.out.println(Format.TASKERROR); } } diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 0cccab5163..ac9c61c559 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -49,7 +49,21 @@ public static final void done(int i) { } } - + public static final void delete(int i) { + try { + Task t = taskList.get(i - 1); + taskList.remove(i - 1); + System.out.println(Format.UPPER + "Awww~ You've deleted the task: " + + " " + t.toString() + Format.LOWER); + for (Task task : taskList) { + if (task.index > i) { + task.index--; + } + } + } catch (IndexOutOfBoundsException e) { + DukeException.taskErrorException(); + } + } /** * Get the name of the task. From dd0a77cd199317c5c1bd6f8f24697104f2647465 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Fri, 22 Jan 2021 21:54:40 +0800 Subject: [PATCH 22/62] Javac doc --- src/main/java/DukeDriver.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/DukeDriver.java b/src/main/java/DukeDriver.java index 9b870f2c39..e225df5ce4 100644 --- a/src/main/java/DukeDriver.java +++ b/src/main/java/DukeDriver.java @@ -119,6 +119,12 @@ private static final boolean handleBye(String input) { } } + /** + * handle delete command key in by user by removing the task from the list if there is any. + * + * @param input user input. + * @param command user command. + */ private static final void handleDelete(String input, String command) { String task = extractTask(input, command); if (task.length() > 0) { From 792ef3541a0fe52264d28d979e38f313ed7c7fe7 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Sat, 23 Jan 2021 02:20:39 +0800 Subject: [PATCH 23/62] Allow Storing and loading of tasks, added more Format message, added type property to Task.java --- src/main/java/Deadlines.java | 19 +++++--- src/main/java/DukeDriver.java | 7 +++ src/main/java/DukeException.java | 2 + src/main/java/Event.java | 19 +++++--- src/main/java/Format.java | 27 ++++++++++- src/main/java/Task.java | 38 +++++++++++++++- src/main/java/TaskStorage.java | 78 ++++++++++++++++++++++++++++++++ src/main/java/Todo.java | 10 ++++ 8 files changed, 185 insertions(+), 15 deletions(-) create mode 100644 src/main/java/TaskStorage.java diff --git a/src/main/java/Deadlines.java b/src/main/java/Deadlines.java index bb45b04cb6..8d1b7d10be 100644 --- a/src/main/java/Deadlines.java +++ b/src/main/java/Deadlines.java @@ -3,23 +3,30 @@ */ public class Deadlines extends Task{ - private String comments; + /** * create a deadline task object with given task name and given dates/comments. * * @param taskName String representation of the name of the task. - * @param comments String representation of the comments/dates. + * @param date String representation of the comments/dates. */ - public Deadlines(String taskName, String comments) { - super(taskName); - this.comments = comments; + public Deadlines(String taskName, String date) { + super(taskName, date); + } + + public Deadlines(String taskName, String date, String done) { + super(taskName, date, done); } + @Override + public int getType() { + return 2; + } @Override public String toString() { return String.format("[D][%s] %d. %s ( %s )", super.isDone(), super.getIndex(), - super.getTaskName(), this.comments); + super.getTaskName(), super.getDate()); } } diff --git a/src/main/java/DukeDriver.java b/src/main/java/DukeDriver.java index e225df5ce4..ecf4358cd1 100644 --- a/src/main/java/DukeDriver.java +++ b/src/main/java/DukeDriver.java @@ -14,6 +14,12 @@ public static void executeDuke() { System.out.println(Format.LOGO); System.out.println(Format.GREETING); + System.out.println(Format.LOADFILE); + + Format.SLEEP(); + + TaskStorage.loadFiles(); + while(sc.hasNext()) { String message = sc.nextLine(); boolean bye = inputHandler(message); @@ -151,6 +157,7 @@ private static final boolean inputHandler(String message) { switch (command) { case "bye": end = handleBye(message); + TaskStorage.writeToFiles(Task.getTaskList()); break; case "list": Format.LISTING(); diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java index 6681db5dae..1a74a4fcb4 100644 --- a/src/main/java/DukeException.java +++ b/src/main/java/DukeException.java @@ -45,4 +45,6 @@ public static final void commandErrorException() { * */ public static final void taskErrorException() { System.out.println(Format.TASKERROR); } + + public static final void saveToFileError() { System.out.println(Format.SAVETOFILEERROR);} } diff --git a/src/main/java/Event.java b/src/main/java/Event.java index 8cd47f648e..0f84458663 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -2,22 +2,29 @@ * A subclass of Task that represent an event key in by user. */ public class Event extends Task{ - private String comments; + /** * Create a event Task with given task name and given comments/dates. * @param taskName name of the task. - * @param comments dates or comments of the user regarding the task. + * @param date dates or comments of the user regarding the task. */ - public Event(String taskName, String comments) { - super(taskName); - this.comments = comments; + public Event(String taskName, String date) { + super(taskName, date); + } + + public Event(String taskName, String date, String done) { + super(taskName, date, done); } + @Override + public int getType() { + return 3; + } @Override public String toString() { return String.format("[E][%s] %d. %s ( %s )", super.isDone(), super.getIndex(), - super.getTaskName(), this.comments); + super.getTaskName(), super.getDate()); } } diff --git a/src/main/java/Format.java b/src/main/java/Format.java index ac8a97f3da..54534dc5d6 100644 --- a/src/main/java/Format.java +++ b/src/main/java/Format.java @@ -18,13 +18,20 @@ public class Format { public static final String MISSINGDATE = "Fill ur date lah"; public static final String COMMANDERROR = "I DON'T KNOW WHAT U SAYING BRO"; public static final String TASKERROR = "Walao, no such task"; + public static final String SAVETOFILEERROR = "Huh? Where your file?"; public static final String FAREWELL = UPPER - + "I zao liao, don't miss me." + + "~~~~~~~~ I Zao Liao. Don't Miss Meeeeeee ~~~~~~~~." + LOWER; public static final String GREETING = UPPER - + "Awww, need help ah?" + + "*************** Awww, need help ah? ***************" + LOWER; + public static final String NODIRECTORY = "******* Cannot find your directory eh, " + + "first time ah? Create one for you *******"; + public static final String LOADFILE = "******* Wait ah~ Loading file for you *******"; + public static final String NOFILE = "******* File also don't have ah, nvm I make one for you *******"; + public static final String EMPTYFILE = "******* Awwww~ You don't have any history of tasks *******"; + /** * make a chatBox that wrap a given String. * @param s the String to be wrapped. @@ -64,6 +71,22 @@ public static final void LISTING() { System.out.println(LOWER); } + public static final void DONELOADING() { + System.out.println(UPPER); + for (Task task : Task.getTaskList()) { + if (task == null) break; + System.out.println(task); + } + System.out.println("Sir, here is your past history"); + System.out.println(LOWER); + } + public static final void SLEEP() { + try { + Thread.sleep(1500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } \ No newline at end of file diff --git a/src/main/java/Task.java b/src/main/java/Task.java index ac9c61c559..71fb941f12 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -10,7 +10,7 @@ public class Task { private static int capacity = 0; private int index; private String done; - + private String date; /** * Construct a task object with taskname attached and its index label in the taskList. * @param taskName name of the task. @@ -20,6 +20,34 @@ public class Task { this.taskName = taskName; this.index = capacity + 1; this.done = " "; + this.date = ""; + capacity++; + add(this); + } + + Task(String taskName, String done, boolean check) { + this.taskName = taskName; + this.index = capacity + 1; + this.done = done; + this.date = ""; + capacity++; + add(this); + } + + Task(String taskName, String date) { + this.taskName = taskName; + this.index = capacity + 1; + this.done = " "; + this.date = date; + capacity++; + add(this); + } + + Task(String taskName, String date, String done) { + this.taskName = taskName; + this.index = capacity + 1; + this.done = done; + this.date = date; capacity++; add(this); } @@ -102,6 +130,14 @@ public int getIndex() { return index; } + public int getType() { + return 0; + } + + public String getDate() { + return date; + } + /** * get the current capacity of the taskList. * diff --git a/src/main/java/TaskStorage.java b/src/main/java/TaskStorage.java new file mode 100644 index 0000000000..1ae771ad94 --- /dev/null +++ b/src/main/java/TaskStorage.java @@ -0,0 +1,78 @@ +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +public class TaskStorage { + + public static final String FILEPATH = "data/Duke.txt"; + public static final String DIRECTORY = "data"; + + public static void writeToFiles(List taskList) { + try { + FileWriter fw = new FileWriter(FILEPATH); + for (Task t : taskList) { + fw.write(t.getType() + "@@" + t.isDone() + + "@@" + t.getTaskName() + (t.getDate().equals("") + ? "" : ("@@" + t.getDate())) + System.lineSeparator()); + } + fw.close(); + } catch (IOException err) { + DukeException.saveToFileError(); + } + } + + public static void loadFiles() { + + try { + File directory = new File(DIRECTORY); + if (!directory.exists()) { + System.out.println(Format.NODIRECTORY); + directory.mkdir(); + Format.SLEEP(); + } + + File file = new File(FILEPATH); + if (!file.exists()) { + System.out.println(Format.NOFILE); + file.createNewFile(); + Format.SLEEP(); + } + + if (file.length() == 0) { + Format.SLEEP(); + System.out.println(Format.EMPTYFILE); + return; + } + + restoreTask(file); + + } catch (IOException e) { + System.out.println("Testing"); + } + + } + + public static final void restoreTask(File file) throws IOException { + Scanner sc = new Scanner(file); + + while (sc.hasNext()) { + String[] line = sc.nextLine().split("@@"); + if (line.length == 3) { + Todo t = new Todo(line[2], line[1]); + } else { + int type = Integer.parseInt(line[0]); + String done = line[1]; + String taskName = line[2]; + String date = line[3]; + Task t = type == 2 ? new Deadlines(taskName, date, done) : new Event(taskName, date, done); + } + } + + sc.close(); + Format.DONELOADING(); + + } +} diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java index 5604984d9e..1cbe014b26 100644 --- a/src/main/java/Todo.java +++ b/src/main/java/Todo.java @@ -12,6 +12,16 @@ public Todo(String taskName) { } + public Todo(String taskName, String done) { + super(taskName, done, true); + + } + + @Override + public int getType() { + return 1; + } + @Override public String toString() { From fe6204509fac95d29c6af1d5df23f8dd5903286f Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Sat, 23 Jan 2021 03:35:04 +0800 Subject: [PATCH 24/62] Add in date and time feature, able to recognise yyyy-mm-dd format --- src/main/java/DateAndTime.java | 45 ++++++++++++++++++++++++++++++ src/main/java/Deadlines.java | 21 +++++++++----- src/main/java/DukeException.java | 4 ++- src/main/java/Event.java | 21 +++++++++----- src/main/java/Format.java | 2 +- src/main/java/Task.java | 47 ++++++++++++++++++++++++++++++-- src/main/java/Todo.java | 12 +++++++- 7 files changed, 132 insertions(+), 20 deletions(-) create mode 100644 src/main/java/DateAndTime.java diff --git a/src/main/java/DateAndTime.java b/src/main/java/DateAndTime.java new file mode 100644 index 0000000000..e1040c3281 --- /dev/null +++ b/src/main/java/DateAndTime.java @@ -0,0 +1,45 @@ +import java.time.DateTimeException; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +public class DateAndTime { + + public static final String converter(String date) { + + if (isDashFormat(date)) { + try { + LocalDate d1 = LocalDate.parse(date.trim()); + return d1.format(DateTimeFormatter.ofPattern("MMM d yyyy")); + } catch (DateTimeParseException e) { + return ""; + } + } else { + return ""; + } + } + + + public static final boolean isDashFormat(String date) { + String[] dashFormat = date.toLowerCase().split("-", 3); + for (String s : dashFormat) { + if (!isNumeric(s.trim())) { + return false; + } + } + return true; + } + + public static boolean isNumeric(String strNum) { + if (strNum == null) { + return false; + } + try { + double d = Double.parseDouble(strNum); + } catch (NumberFormatException nfe) { + return false; + } + return true; + } + +} diff --git a/src/main/java/Deadlines.java b/src/main/java/Deadlines.java index bb45b04cb6..dd6e257778 100644 --- a/src/main/java/Deadlines.java +++ b/src/main/java/Deadlines.java @@ -3,23 +3,30 @@ */ public class Deadlines extends Task{ - private String comments; + /** * create a deadline task object with given task name and given dates/comments. * * @param taskName String representation of the name of the task. - * @param comments String representation of the comments/dates. + * @param date String representation of the comments/dates. */ - public Deadlines(String taskName, String comments) { - super(taskName); - this.comments = comments; + public Deadlines(String taskName, String date) { + super(taskName, date); + } + + public Deadlines(String taskName, String date, String done) { + super(taskName, date, done); } + @Override + public int getType() { + return 2; + } @Override public String toString() { return String.format("[D][%s] %d. %s ( %s )", super.isDone(), super.getIndex(), - super.getTaskName(), this.comments); + super.getTaskName(), super.getDate()); } -} +} \ No newline at end of file diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java index 6681db5dae..77a00c55c7 100644 --- a/src/main/java/DukeException.java +++ b/src/main/java/DukeException.java @@ -2,7 +2,9 @@ * A class that store all the possible display of errorsException in Duke. */ public class DukeException{ - + public static final void DATEFORMATEXCEPTION() { + System.out.println(Format.WRONGDATEFORMAT); + } public static final void NumberFormatException() { System.out.println(Format.KEYINNUMBER); } diff --git a/src/main/java/Event.java b/src/main/java/Event.java index 8cd47f648e..0e7eacea7f 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -2,22 +2,29 @@ * A subclass of Task that represent an event key in by user. */ public class Event extends Task{ - private String comments; + /** * Create a event Task with given task name and given comments/dates. * @param taskName name of the task. - * @param comments dates or comments of the user regarding the task. + * @param date dates or comments of the user regarding the task. */ - public Event(String taskName, String comments) { - super(taskName); - this.comments = comments; + public Event(String taskName, String date) { + super(taskName, date); + } + + public Event(String taskName, String date, String done) { + super(taskName, date, done); } + @Override + public int getType() { + return 3; + } @Override public String toString() { return String.format("[E][%s] %d. %s ( %s )", super.isDone(), super.getIndex(), - super.getTaskName(), this.comments); + super.getTaskName(), super.getDate()); } -} +} \ No newline at end of file diff --git a/src/main/java/Format.java b/src/main/java/Format.java index ac8a97f3da..450ec8e0ad 100644 --- a/src/main/java/Format.java +++ b/src/main/java/Format.java @@ -11,7 +11,7 @@ public class Format { + "| | | | | | | |/ / _ \\\n" + "| |_| | |_| | < __/\n" + "|____/ \\__,_|_|\\_\\___|\n"; - + public static final String WRONGDATEFORMAT = "Err, wrong date format.."; public static final String KEYINNUMBER = "PLease Lah! Key in number!"; public static final String EMPTYTASK = "Walao!NO TASK!"; public static final String TOOMANYARGUMENTS = "You put so many/few ARGUMENTS for what"; diff --git a/src/main/java/Task.java b/src/main/java/Task.java index ac9c61c559..02f0bb604c 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -10,7 +10,7 @@ public class Task { private static int capacity = 0; private int index; private String done; - + private String date; /** * Construct a task object with taskname attached and its index label in the taskList. * @param taskName name of the task. @@ -20,6 +20,39 @@ public class Task { this.taskName = taskName; this.index = capacity + 1; this.done = " "; + this.date = ""; + capacity++; + add(this); + } + + Task(String taskName, String done, boolean check) { + this.taskName = taskName; + this.index = capacity + 1; + this.done = done; + this.date = ""; + capacity++; + add(this); + } + + Task(String taskName, String date) { + this.taskName = taskName; + this.index = capacity + 1; + this.done = " "; + if (DateAndTime.converter(date).equals("")) { + DukeException.DATEFORMATEXCEPTION(); + this.date = date; + } else { + this.date = DateAndTime.converter(date); + } + capacity++; + add(this); + } + + Task(String taskName, String date, String done) { + this.taskName = taskName; + this.index = capacity + 1; + this.done = done; + this.date = date; capacity++; add(this); } @@ -54,7 +87,7 @@ public static final void delete(int i) { Task t = taskList.get(i - 1); taskList.remove(i - 1); System.out.println(Format.UPPER + "Awww~ You've deleted the task: " - + " " + t.toString() + Format.LOWER); + + " " + t.toString() + Format.LOWER); for (Task task : taskList) { if (task.index > i) { task.index--; @@ -102,6 +135,14 @@ public int getIndex() { return index; } + public int getType() { + return 0; + } + + public String getDate() { + return date; + } + /** * get the current capacity of the taskList. * @@ -115,4 +156,4 @@ public static final int getCapacity() { public String toString() { return String.format("[%s] %d. %s", done, index, taskName); } -} +} \ No newline at end of file diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java index 5604984d9e..6e8b4c32cf 100644 --- a/src/main/java/Todo.java +++ b/src/main/java/Todo.java @@ -12,9 +12,19 @@ public Todo(String taskName) { } + public Todo(String taskName, String done) { + super(taskName, done, true); + + } + + @Override + public int getType() { + return 1; + } + @Override public String toString() { return String.format("[T][%s] %d. %s", super.isDone(), super.getIndex(), super.getTaskName()); } -} +} \ No newline at end of file From 03cc005e24aed21ca94bb585beceb9bd5a19c5f5 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Sat, 23 Jan 2021 03:46:23 +0800 Subject: [PATCH 25/62] updated text-ui-test with no date/Duke.txt file exists --- data/Duke.txt | 3 ++ text-ui-test/ACTUAL.TXT | 101 ++++++++++++++++++++++++++++++++++++- text-ui-test/EXPECTED.TXT | 101 ++++++++++++++++++++++++++++++++++++- text-ui-test/data/Duke.txt | 5 ++ text-ui-test/input.txt | 21 ++++---- 5 files changed, 216 insertions(+), 15 deletions(-) create mode 100644 data/Duke.txt create mode 100644 text-ui-test/data/Duke.txt diff --git a/data/Duke.txt b/data/Duke.txt new file mode 100644 index 0000000000..d428577e1e --- /dev/null +++ b/data/Duke.txt @@ -0,0 +1,3 @@ +1@@X@@swimming +2@@ @@project @@Oct 22 2020 +1@@ @@homework diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT index b646323ab6..6f4b66597d 100644 --- a/text-ui-test/ACTUAL.TXT +++ b/text-ui-test/ACTUAL.TXT @@ -7,13 +7,110 @@ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Awww, need help ah? +*************** Awww, need help ah? *************** __________________________________________________________________________________________ +******* Wait ah~ Loading file for you ******* +******* Cannot find your directory eh, first time ah? Create one for you ******* +******* File also don't have ah, nvm I make one for you ******* +******* Awwww~ You don't have any history of tasks ******* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Added liao: [T][] 1. read book +Added liao: [T][ ] 1. read book You have 1 tasks in the list! __________________________________________________________________________________________ + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Wah~ You done the task: [T][X] 1. read book +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [T][ ] 2. swimming +You have 2 tasks in the list! +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [D][ ] 3. project ( Oct 22 2020 ) +You have 3 tasks in the list! +__________________________________________________________________________________________ + +Err, wrong date format.. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [D][ ] 4. meeting ( 2021-1-2 ) +You have 4 tasks in the list! +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Wah~ You done the task: [D][X] 3. project ( Oct 22 2020 ) +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +[T][X] 1. read book +[T][ ] 2. swimming +[D][X] 3. project ( Oct 22 2020 ) +[D][ ] 4. meeting ( 2021-1-2 ) + +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [E][ ] 5. project ( Oct 22 2020 ) +You have 5 tasks in the list! +__________________________________________________________________________________________ + +Err, wrong date format.. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [E][ ] 6. project2 ( 2021-1-2 ) +You have 6 tasks in the list! +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Wah~ You done the task: [E][X] 6. project2 ( 2021-1-2 ) +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +[T][X] 1. read book +[T][ ] 2. swimming +[D][X] 3. project ( Oct 22 2020 ) +[D][ ] 4. meeting ( 2021-1-2 ) +[E][ ] 5. project ( Oct 22 2020 ) +[E][X] 6. project2 ( 2021-1-2 ) + +__________________________________________________________________________________________ + +Walao, no such task + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Awww~ You've deleted the task: [E][ ] 5. project ( Oct 22 2020 ) +__________________________________________________________________________________________ + +Walao, no such task + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +~~~~~~~~ I Zao Liao. Don't Miss Meeeeeee ~~~~~~~~. +__________________________________________________________________________________________ + diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index b646323ab6..6f4b66597d 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -7,13 +7,110 @@ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Awww, need help ah? +*************** Awww, need help ah? *************** __________________________________________________________________________________________ +******* Wait ah~ Loading file for you ******* +******* Cannot find your directory eh, first time ah? Create one for you ******* +******* File also don't have ah, nvm I make one for you ******* +******* Awwww~ You don't have any history of tasks ******* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Added liao: [T][] 1. read book +Added liao: [T][ ] 1. read book You have 1 tasks in the list! __________________________________________________________________________________________ + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Wah~ You done the task: [T][X] 1. read book +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [T][ ] 2. swimming +You have 2 tasks in the list! +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [D][ ] 3. project ( Oct 22 2020 ) +You have 3 tasks in the list! +__________________________________________________________________________________________ + +Err, wrong date format.. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [D][ ] 4. meeting ( 2021-1-2 ) +You have 4 tasks in the list! +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Wah~ You done the task: [D][X] 3. project ( Oct 22 2020 ) +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +[T][X] 1. read book +[T][ ] 2. swimming +[D][X] 3. project ( Oct 22 2020 ) +[D][ ] 4. meeting ( 2021-1-2 ) + +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [E][ ] 5. project ( Oct 22 2020 ) +You have 5 tasks in the list! +__________________________________________________________________________________________ + +Err, wrong date format.. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Added liao: [E][ ] 6. project2 ( 2021-1-2 ) +You have 6 tasks in the list! +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Wah~ You done the task: [E][X] 6. project2 ( 2021-1-2 ) +__________________________________________________________________________________________ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +[T][X] 1. read book +[T][ ] 2. swimming +[D][X] 3. project ( Oct 22 2020 ) +[D][ ] 4. meeting ( 2021-1-2 ) +[E][ ] 5. project ( Oct 22 2020 ) +[E][X] 6. project2 ( 2021-1-2 ) + +__________________________________________________________________________________________ + +Walao, no such task + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Awww~ You've deleted the task: [E][ ] 5. project ( Oct 22 2020 ) +__________________________________________________________________________________________ + +Walao, no such task + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +~~~~~~~~ I Zao Liao. Don't Miss Meeeeeee ~~~~~~~~. +__________________________________________________________________________________________ + diff --git a/text-ui-test/data/Duke.txt b/text-ui-test/data/Duke.txt new file mode 100644 index 0000000000..cd5fa6ad45 --- /dev/null +++ b/text-ui-test/data/Duke.txt @@ -0,0 +1,5 @@ +1@@X@@read book +1@@ @@swimming +2@@X@@project @@Oct 22 2020 +2@@ @@meeting @@2021-1-2 +3@@X@@project2 @@2021-1-2 diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index d82ad643c5..eb04cf45fe 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,16 +1,15 @@ todo read book -todo -deadline study -deadline -deadline study /SundayAfternoon 3-4 pm -deadline /SundayAfternoon 3-4 pm done 1 -done 10 -list -event team project -event -list -event team project /Friday 3-4 pm .. +todo swimming +deadline project /2020-10-22 +deadline meeting /2021-1-2 done 3 list +event project /2020-10-22 +event project2 /2021-1-2 +done 6 +list +done 10 +delete 5 +delete 9 bye From 6a15b6c1b8b101660662dda89b49f2e986b25e00 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 27 Jan 2021 16:57:09 +0800 Subject: [PATCH 26/62] Add InputProcessor to process user input and extract data for use --- data/Duke.txt | 3 - src/main/java/DukeDriver.java | 94 +++++++------------------------ src/main/java/InputProcessor.java | 70 +++++++++++++++++++++++ 3 files changed, 91 insertions(+), 76 deletions(-) create mode 100644 src/main/java/InputProcessor.java diff --git a/data/Duke.txt b/data/Duke.txt index d428577e1e..e69de29bb2 100644 --- a/data/Duke.txt +++ b/data/Duke.txt @@ -1,3 +0,0 @@ -1@@X@@swimming -2@@ @@project @@Oct 22 2020 -1@@ @@homework diff --git a/src/main/java/DukeDriver.java b/src/main/java/DukeDriver.java index ecf4358cd1..e7ef27d1cb 100644 --- a/src/main/java/DukeDriver.java +++ b/src/main/java/DukeDriver.java @@ -33,11 +33,9 @@ public static void executeDuke() { /** * handle done command by marking the task as done. * - * @param input user input. - * @param command command given by user. + * @param task name of the user task. */ - private static final void handleDone(String input, String command) { - String task = extractTask(input, command); + private static final void handleDone(String task) { if (task.length() > 0) { try { int num = Integer.parseInt(task); @@ -53,11 +51,9 @@ private static final void handleDone(String input, String command) { /** * handle todo command and create a todo task if task is not empty. * - * @param input user input. - * @param command user command. + * @param task name of the user task. */ - private static final void handleToDo(String input, String command) { - String task = extractTask(input, command); + private static final void handleToDo(String task) { if (!task.equals("")) { Todo todo = new Todo(task); System.out.println(Format.biggerBox(todo)); @@ -70,15 +66,13 @@ private static final void handleToDo(String input, String command) { /** * handle deadline command by creating deadline task if task and date are not empty. * - * @param input user input. - * @param command user command. + * @param task name of the user task. + * @param date date of the task to be done. */ - private static final void handleDeadline(String input, String command) { - String task = extractTask(input, command); + private static final void handleDeadline(String task, String date) { if (task.equals("")) { DukeException.emptyTaskException(); } else { - String date = extractDate(input, command); if (date.equals("")) { DukeException.missingDateErrorException(); } else { @@ -92,15 +86,13 @@ private static final void handleDeadline(String input, String command) { /** * handle event command by creating event if task and date are not empty. * - * @param input user input. - * @param command user command. + * @param task name of the user task. + * @param date date of the task to be done. */ - private static final void handleEvent(String input, String command) { - String task = extractTask(input, command); + private static final void handleEvent(String task, String date) { if (task.equals("")) { DukeException.emptyTaskException(); } else { - String date = extractDate(input, command); if (date.equals("")) { DukeException.missingDateErrorException(); } else { @@ -128,11 +120,9 @@ private static final boolean handleBye(String input) { /** * handle delete command key in by user by removing the task from the list if there is any. * - * @param input user input. - * @param command user command. + * @param task name of the user task. */ - private static final void handleDelete(String input, String command) { - String task = extractTask(input, command); + private static final void handleDelete(String task) { if (task.length() > 0) { try { int num = Integer.parseInt(task); @@ -152,7 +142,10 @@ private static final void handleDelete(String input, String command) { * @return a boolean to whether to exit the program. */ private static final boolean inputHandler(String message) { - String command = extractCommand(message); + InputProcessor ip = new InputProcessor(message); + String command = ip.getCommand(); + String task = ip.getTaskName(); + String date = ip.getDate(); boolean end = false; switch (command) { case "bye": @@ -163,19 +156,19 @@ private static final boolean inputHandler(String message) { Format.LISTING(); break; case "done": - handleDone(message, command); + handleDone(task); break; case "todo": - handleToDo(message, command); + handleToDo(task); break; case "deadline": - handleDeadline(message, command); + handleDeadline(task, date); break; case "event": - handleEvent(message, command); + handleEvent(task, date); break; case "delete": - handleDelete(message, command); + handleDelete(task); break; default: DukeException.commandErrorException(); @@ -185,51 +178,6 @@ private static final boolean inputHandler(String message) { } - /** - * extract the command key in by user. - * - * @param input the input key in by user. - * @return String representation of the command word of the user input. - */ - private static final String extractCommand(String input) { - return input.trim().toLowerCase().split(" ")[0]; - } - /** - * extracting task name from user input. - * @param input user input. - * @param command user command. - * @return the task name if there is one and return empty string if task name empty. - */ - private static final String extractTask(String input, String command) { - String body = input.replaceAll(command, "").trim(); - if (command.equals("todo") || command.equals("delete")) { - return body; - } else if (command.equals("done")) { - return body.replaceAll("[^0-9]", ""); - } else { - try { - return body.split("/")[0]; - } catch (ArrayIndexOutOfBoundsException e) { - return ""; - } - } - } - - /** - * extract the date of the task to be done. - * @param input user input. - * @param command user command. - * @return the task date in String and return empty if there is no date. - */ - private static final String extractDate(String input, String command) { - String body = input.replaceAll(command, "").trim(); - String[] parts = body.split("/", 2); - if (parts.length == 2) { - return parts[1]; - } else { - return ""; - } - } } diff --git a/src/main/java/InputProcessor.java b/src/main/java/InputProcessor.java new file mode 100644 index 0000000000..0145ca4d4d --- /dev/null +++ b/src/main/java/InputProcessor.java @@ -0,0 +1,70 @@ +public class InputProcessor { + private String command; + private String taskName; + private String date; + + public InputProcessor(String input) { + this.command = extractCommand(input); + this.taskName = extractTask(input, command); + this.date = extractDate(input, command); + } + + /** + * extract the command key in by user. + * + * @param input the input key in by user. + * @return String representation of the command word of the user input. + */ + private static final String extractCommand(String input) { + return input.trim().toLowerCase().split(" ")[0]; + } + + /** + * extracting task name from user input. + * @param input user input. + * @param command user command. + * @return the task name if there is one and return empty string if task name empty. + */ + private static final String extractTask(String input, String command) { + String body = input.replaceAll(command, "").trim(); + if (command.equals("todo") || command.equals("delete")) { + return body; + } else if (command.equals("done")) { + return body.replaceAll("[^0-9]", ""); + } else { + try { + return body.split("/")[0]; + } catch (ArrayIndexOutOfBoundsException e) { + return ""; + } + } + } + + /** + * extract the date of the task to be done. + * @param input user input. + * @param command user command. + * @return the task date in String and return empty if there is no date. + */ + private static final String extractDate(String input, String command) { + String body = input.replaceAll(command, "").trim(); + String[] parts = body.split("/", 2); + if (parts.length == 2) { + return parts[1]; + } else { + return ""; + } + } + + public String getCommand() { + return this.command; + } + + public String getTaskName() { + return taskName; + } + + public String getDate() { + return date; + } +} From baecee41cff6997de6eec93301f887149f2d8126 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 27 Jan 2021 17:16:25 +0800 Subject: [PATCH 27/62] Change Format.java to Ui.java, modify Ui --- src/main/java/DukeDriver.java | 18 +++++++------- src/main/java/DukeException.java | 16 ++++++------ src/main/java/Task.java | 6 ++--- src/main/java/TaskStorage.java | 14 +++++------ src/main/java/{Format.java => Ui.java} | 34 ++++++++++++++++---------- 5 files changed, 47 insertions(+), 41 deletions(-) rename src/main/java/{Format.java => Ui.java} (69%) diff --git a/src/main/java/DukeDriver.java b/src/main/java/DukeDriver.java index e7ef27d1cb..e37044fc4c 100644 --- a/src/main/java/DukeDriver.java +++ b/src/main/java/DukeDriver.java @@ -11,12 +11,12 @@ public class DukeDriver { */ public static void executeDuke() { Scanner sc = new Scanner(System.in); - System.out.println(Format.LOGO); - System.out.println(Format.GREETING); + System.out.println(Ui.LOGO); + System.out.println(Ui.GREETING); - System.out.println(Format.LOADFILE); + System.out.println(Ui.LOADFILE); - Format.SLEEP(); + Ui.SLEEP(); TaskStorage.loadFiles(); @@ -27,7 +27,7 @@ public static void executeDuke() { break; } } - System.out.println(Format.FAREWELL); + System.out.println(Ui.FAREWELL); } /** @@ -56,7 +56,7 @@ private static final void handleDone(String task) { private static final void handleToDo(String task) { if (!task.equals("")) { Todo todo = new Todo(task); - System.out.println(Format.biggerBox(todo)); + System.out.println(Ui.biggerBox(todo)); } else { DukeException.emptyTaskException(); } @@ -77,7 +77,7 @@ private static final void handleDeadline(String task, String date) { DukeException.missingDateErrorException(); } else { Deadlines deadlines = new Deadlines(task, date); - System.out.println(Format.biggerBox(deadlines)); + System.out.println(Ui.biggerBox(deadlines)); } } } @@ -97,7 +97,7 @@ private static final void handleEvent(String task, String date) { DukeException.missingDateErrorException(); } else { Event event = new Event(task, date); - System.out.println(Format.biggerBox(event)); + System.out.println(Ui.biggerBox(event)); } } } @@ -153,7 +153,7 @@ private static final boolean inputHandler(String message) { TaskStorage.writeToFiles(Task.getTaskList()); break; case "list": - Format.LISTING(); + Ui.LISTING(); break; case "done": handleDone(task); diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java index c1a89c1410..aeb5b7c8a5 100644 --- a/src/main/java/DukeException.java +++ b/src/main/java/DukeException.java @@ -3,10 +3,10 @@ */ public class DukeException{ public static final void DATEFORMATEXCEPTION() { - System.out.println(Format.WRONGDATEFORMAT); + System.out.println(Ui.WRONGDATEFORMAT); } public static final void NumberFormatException() { - System.out.println(Format.KEYINNUMBER); + System.out.println(Ui.KEYINNUMBER); } /** @@ -14,7 +14,7 @@ public static final void NumberFormatException() { * */ public static final void emptyTaskException() { - System.out.println(Format.EMPTYTASK); + System.out.println(Ui.EMPTYTASK); } @@ -23,7 +23,7 @@ public static final void emptyTaskException() { * */ public static final void argumentErrorException() { - System.out.println(Format.TOOMANYARGUMENTS); + System.out.println(Ui.TOOMANYARGUMENTS); } /** @@ -31,7 +31,7 @@ public static final void argumentErrorException() { * */ public static final void missingDateErrorException() { - System.out.println(Format.MISSINGDATE); + System.out.println(Ui.MISSINGDATE); } /** @@ -39,14 +39,14 @@ public static final void missingDateErrorException() { * */ public static final void commandErrorException() { - System.out.println(Format.COMMANDERROR); + System.out.println(Ui.COMMANDERROR); } /** * display the error message for missing task error. * */ - public static final void taskErrorException() { System.out.println(Format.TASKERROR); } + public static final void taskErrorException() { System.out.println(Ui.TASKERROR); } - public static final void saveToFileError() { System.out.println(Format.SAVETOFILEERROR);} + public static final void saveToFileError() { System.out.println(Ui.SAVETOFILEERROR);} } diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 49b4511e2c..8bde11e250 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -76,8 +76,7 @@ public static final void done(int i) { try { Task t = taskList.get(i - 1); taskList.get(i - 1).done = "X"; - System.out.println(Format.UPPER + "Wah~ You done the task: " - + " " + t.toString() + Format.LOWER); + Ui.doneTask(t); } catch (IndexOutOfBoundsException e) { DukeException.taskErrorException(); } @@ -87,8 +86,7 @@ public static final void delete(int i) { try { Task t = taskList.get(i - 1); taskList.remove(i - 1); - System.out.println(Format.UPPER + "Awww~ You've deleted the task: " - + " " + t.toString() + Format.LOWER); + Ui.deleteTask(t); for (Task task : taskList) { if (task.index > i) { task.index--; diff --git a/src/main/java/TaskStorage.java b/src/main/java/TaskStorage.java index 1ae771ad94..c8b9761861 100644 --- a/src/main/java/TaskStorage.java +++ b/src/main/java/TaskStorage.java @@ -29,21 +29,21 @@ public static void loadFiles() { try { File directory = new File(DIRECTORY); if (!directory.exists()) { - System.out.println(Format.NODIRECTORY); + System.out.println(Ui.NODIRECTORY); directory.mkdir(); - Format.SLEEP(); + Ui.SLEEP(); } File file = new File(FILEPATH); if (!file.exists()) { - System.out.println(Format.NOFILE); + System.out.println(Ui.NOFILE); file.createNewFile(); - Format.SLEEP(); + Ui.SLEEP(); } if (file.length() == 0) { - Format.SLEEP(); - System.out.println(Format.EMPTYFILE); + Ui.SLEEP(); + System.out.println(Ui.EMPTYFILE); return; } @@ -72,7 +72,7 @@ public static final void restoreTask(File file) throws IOException { } sc.close(); - Format.DONELOADING(); + Ui.DONELOADING(); } } diff --git a/src/main/java/Format.java b/src/main/java/Ui.java similarity index 69% rename from src/main/java/Format.java rename to src/main/java/Ui.java index 7f44310dce..7ebb1c27b5 100644 --- a/src/main/java/Format.java +++ b/src/main/java/Ui.java @@ -1,7 +1,7 @@ /** * A class that store all the possible String format for Duke for code simplicity. */ -public class Format { +public class Ui { public static final String LINEBREAK = "\n"; public static final String UPPER = LINEBREAK + "^".repeat(90) + LINEBREAK.repeat(2); @@ -11,26 +11,26 @@ public class Format { + "| | | | | | | |/ / _ \\\n" + "| |_| | |_| | < __/\n" + "|____/ \\__,_|_|\\_\\___|\n"; - public static final String WRONGDATEFORMAT = "Err, wrong date format.."; + public static final String WRONGDATEFORMAT = "Err, wrong date format.. (yyyy-mm-dd)"; public static final String KEYINNUMBER = "PLease Lah! Key in number!"; public static final String EMPTYTASK = "Walao!NO TASK!"; public static final String TOOMANYARGUMENTS = "You put so many/few ARGUMENTS for what"; - public static final String MISSINGDATE = "Fill ur date lah"; + public static final String MISSINGDATE = "Fill ur date lah (add date with / in yyyy-mm-dd format)"; public static final String COMMANDERROR = "I DON'T KNOW WHAT U SAYING BRO"; public static final String TASKERROR = "Walao, no such task"; public static final String SAVETOFILEERROR = "Huh? Where your file?"; public static final String FAREWELL = UPPER - + "~~~~~~~~ I Zao Liao. Don't Miss Meeeeeee ~~~~~~~~." + + "~~~~~~~~~~~ I Zao Liao. Don't Miss Meeeeeee ~~~~~~~~~~~." + LOWER; public static final String GREETING = UPPER - + "*************** Awww, need help ah? ***************" + + "****************** Awww, need help ah? ******************" + LOWER; - public static final String NODIRECTORY = "******* Cannot find your directory eh, " - + "first time ah? Create one for you *******"; - public static final String LOADFILE = "******* Wait ah~ Loading file for you *******"; - public static final String NOFILE = "******* File also don't have ah, nvm I make one for you *******"; - public static final String EMPTYFILE = "******* Awwww~ You don't have any history of tasks *******"; + public static final String NODIRECTORY = "********** Cannot find your directory eh, " + + "first time ah? Create one for you **********\n" ; + public static final String LOADFILE = "********** Wait ah~ Loading file for you **********\n"; + public static final String NOFILE = "********** File also don't have ah, nvm I make one for you **********\n"; + public static final String EMPTYFILE = "********** Awwww~ You don't have any history of tasks **********\n"; /** * make a chatBox that wrap a given String. @@ -45,6 +45,14 @@ public static final String chatBox(String s) { } } + public static final void doneTask(Task t) { + System.out.println(Ui.UPPER + "Wah~ You done the task: " + + " " + t.toString() + Ui.LOWER); + } + public static final void deleteTask(Task t) { + System.out.println(Ui.UPPER + "Awww~ You've deleted the task: " + + " " + t.toString() + Ui.LOWER); + } /** * make a Bigger ChatBox that wrap the name of a given Task. @@ -52,10 +60,10 @@ public static final String chatBox(String s) { * @return the String representation of the task name wrapped in a chatBox. */ public static final String biggerBox(Task t) { - return Format.UPPER + "Added liao: " - + t.toString() + Format.LINEBREAK + return Ui.UPPER + "Added liao: " + + t.toString() + Ui.LINEBREAK + "You have " + Task.getCapacity() + " tasks in the list!" - + Format.LOWER; + + Ui.LOWER; } /** From bd0b35884ec20be4eeddc929f8c9f2c84646904e Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 27 Jan 2021 18:22:12 +0800 Subject: [PATCH 28/62] Add Command and subCommand, rename InputProcessor to Parser --- data/Duke.txt | 2 + src/main/java/AddCommand.java | 71 +++++++++ src/main/java/Command.java | 31 ++++ src/main/java/DeleteCommand.java | 28 ++++ src/main/java/DoneCommand.java | 28 ++++ src/main/java/DukeDriver.java | 138 +----------------- src/main/java/ErrorCommand.java | 8 + src/main/java/ExitCommand.java | 24 +++ src/main/java/ListCommand.java | 8 + .../java/{InputProcessor.java => Parser.java} | 45 ++++-- src/main/java/Task.java | 6 - 11 files changed, 238 insertions(+), 151 deletions(-) create mode 100644 src/main/java/AddCommand.java create mode 100644 src/main/java/Command.java create mode 100644 src/main/java/DeleteCommand.java create mode 100644 src/main/java/DoneCommand.java create mode 100644 src/main/java/ErrorCommand.java create mode 100644 src/main/java/ExitCommand.java create mode 100644 src/main/java/ListCommand.java rename src/main/java/{InputProcessor.java => Parser.java} (61%) diff --git a/data/Duke.txt b/data/Duke.txt index e69de29bb2..a3e5c48f9f 100644 --- a/data/Duke.txt +++ b/data/Duke.txt @@ -0,0 +1,2 @@ +1@@X@@readbook +2@@ @@readbook @@Oct 22 2019 diff --git a/src/main/java/AddCommand.java b/src/main/java/AddCommand.java new file mode 100644 index 0000000000..1d1d41a9b7 --- /dev/null +++ b/src/main/java/AddCommand.java @@ -0,0 +1,71 @@ +public class AddCommand extends Command{ + AddCommand(String instruction, String task, String date) { + super(instruction, task, date, command -> { + if (instruction.equals("todo")) { + return handleToDo(task); + } else if (instruction.equals("deadline")) { + return handleDeadline(task, date); + } else { + return handleEvent(task, date); + } + }); + } + + + /** + * handle todo command and create a todo task if task is not empty. + * + * @param task name of the user task. + */ + private static final Boolean handleToDo(String task) { + if (!task.equals("")) { + Todo todo = new Todo(task); + System.out.println(Ui.biggerBox(todo)); + } else { + DukeException.emptyTaskException(); + } + return false; + + } + + /** + * handle deadline command by creating deadline task if task and date are not empty. + * + * @param task name of the user task. + * @param date date of the task to be done. + */ + private static final Boolean handleDeadline(String task, String date) { + if (task.equals("")) { + DukeException.emptyTaskException(); + } else { + if (date.equals("")) { + DukeException.missingDateErrorException(); + } else { + Deadlines deadlines = new Deadlines(task, date); + System.out.println(Ui.biggerBox(deadlines)); + } + } + return false; + } + + + /** + * handle event command by creating event if task and date are not empty. + * + * @param task name of the user task. + * @param date date of the task to be done. + */ + private static final Boolean handleEvent(String task, String date) { + if (task.equals("")) { + DukeException.emptyTaskException(); + } else { + if (date.equals("")) { + DukeException.missingDateErrorException(); + } else { + Event event = new Event(task, date); + System.out.println(Ui.biggerBox(event)); + } + } + return false; + } +} diff --git a/src/main/java/Command.java b/src/main/java/Command.java new file mode 100644 index 0000000000..cc11be91fe --- /dev/null +++ b/src/main/java/Command.java @@ -0,0 +1,31 @@ +import java.util.function.Function; + +public abstract class Command { + private final String instruction; + private final String task; + private final String date; + private final Function func; + + public Command(String instruction, String task, String date, Function func) { + this.instruction = instruction; + this.task = task; + this.date = date; + this.func = func; + } + + public Boolean execute() { + return func.apply(this); + } + + public String getInstruction() { + return instruction; + } + + public String getTask() { + return task; + } + + public String getDate() { + return date; + } +} diff --git a/src/main/java/DeleteCommand.java b/src/main/java/DeleteCommand.java new file mode 100644 index 0000000000..558cf6903c --- /dev/null +++ b/src/main/java/DeleteCommand.java @@ -0,0 +1,28 @@ +public class DeleteCommand extends Command{ + DeleteCommand(String task, String date) { + super("delete", task, date, command -> { + return handleDelete(task, date); + + }); + } + + + /** + * handle delete command key in by user by removing the task from the list if there is any. + * + * @param task name of the user task. + */ + private static final Boolean handleDelete(String task, String date) { + if (task.length() > 0 && date.equals("")) { + try { + int num = Integer.parseInt(task); + Task.delete(num); + } catch (NumberFormatException e) { + DukeException.NumberFormatException(); + } + } else { + DukeException.argumentErrorException(); + } + return false; + } +} diff --git a/src/main/java/DoneCommand.java b/src/main/java/DoneCommand.java new file mode 100644 index 0000000000..2734e390c0 --- /dev/null +++ b/src/main/java/DoneCommand.java @@ -0,0 +1,28 @@ +public class DoneCommand extends Command{ + DoneCommand(String task, String date) { + super("done", task, date, command -> { + return handleDone(task); + }); + } + + /** + * handle done command by marking the task as done. + * + * @param task name of the user task. + */ + private static final Boolean handleDone(String task) { + if (task.length() > 0) { + try { + int num = Integer.parseInt(task); + Task.done(num); + } catch (NumberFormatException e) { + DukeException.NumberFormatException(); + } + } else { + DukeException.argumentErrorException(); + } + return false; + } + + +} diff --git a/src/main/java/DukeDriver.java b/src/main/java/DukeDriver.java index e37044fc4c..d302287dcc 100644 --- a/src/main/java/DukeDriver.java +++ b/src/main/java/DukeDriver.java @@ -30,110 +30,6 @@ public static void executeDuke() { System.out.println(Ui.FAREWELL); } - /** - * handle done command by marking the task as done. - * - * @param task name of the user task. - */ - private static final void handleDone(String task) { - if (task.length() > 0) { - try { - int num = Integer.parseInt(task); - Task.done(num); - } catch (NumberFormatException e) { - DukeException.NumberFormatException(); - } - } else { - DukeException.argumentErrorException(); - } - } - - /** - * handle todo command and create a todo task if task is not empty. - * - * @param task name of the user task. - */ - private static final void handleToDo(String task) { - if (!task.equals("")) { - Todo todo = new Todo(task); - System.out.println(Ui.biggerBox(todo)); - } else { - DukeException.emptyTaskException(); - } - - } - - /** - * handle deadline command by creating deadline task if task and date are not empty. - * - * @param task name of the user task. - * @param date date of the task to be done. - */ - private static final void handleDeadline(String task, String date) { - if (task.equals("")) { - DukeException.emptyTaskException(); - } else { - if (date.equals("")) { - DukeException.missingDateErrorException(); - } else { - Deadlines deadlines = new Deadlines(task, date); - System.out.println(Ui.biggerBox(deadlines)); - } - } - } - - - /** - * handle event command by creating event if task and date are not empty. - * - * @param task name of the user task. - * @param date date of the task to be done. - */ - private static final void handleEvent(String task, String date) { - if (task.equals("")) { - DukeException.emptyTaskException(); - } else { - if (date.equals("")) { - DukeException.missingDateErrorException(); - } else { - Event event = new Event(task, date); - System.out.println(Ui.biggerBox(event)); - } - } - } - - /** - * handle bye command by returning true or false. - * - * @param input user iuput. - * @return a boolean of whether to exit the program. - */ - private static final boolean handleBye(String input) { - if (input.trim().length() > 3) { - DukeException.commandErrorException(); - return false; - } else { - return true; - } - } - - /** - * handle delete command key in by user by removing the task from the list if there is any. - * - * @param task name of the user task. - */ - private static final void handleDelete(String task) { - if (task.length() > 0) { - try { - int num = Integer.parseInt(task); - Task.delete(num); - } catch (NumberFormatException e) { - DukeException.NumberFormatException(); - } - } else { - DukeException.argumentErrorException(); - } - } /** * The main handler of all the command. @@ -142,38 +38,8 @@ private static final void handleDelete(String task) { * @return a boolean to whether to exit the program. */ private static final boolean inputHandler(String message) { - InputProcessor ip = new InputProcessor(message); - String command = ip.getCommand(); - String task = ip.getTaskName(); - String date = ip.getDate(); - boolean end = false; - switch (command) { - case "bye": - end = handleBye(message); - TaskStorage.writeToFiles(Task.getTaskList()); - break; - case "list": - Ui.LISTING(); - break; - case "done": - handleDone(task); - break; - case "todo": - handleToDo(task); - break; - case "deadline": - handleDeadline(task, date); - break; - case "event": - handleEvent(task, date); - break; - case "delete": - handleDelete(task); - break; - default: - DukeException.commandErrorException(); - break; - } + Command command = new Parser(message).parse(); + Boolean end = command.execute(); return end; } diff --git a/src/main/java/ErrorCommand.java b/src/main/java/ErrorCommand.java new file mode 100644 index 0000000000..61419d12e2 --- /dev/null +++ b/src/main/java/ErrorCommand.java @@ -0,0 +1,8 @@ +public class ErrorCommand extends Command{ + ErrorCommand() { + super("", "", "", command -> { + DukeException.commandErrorException(); + return false; + }); + } +} diff --git a/src/main/java/ExitCommand.java b/src/main/java/ExitCommand.java new file mode 100644 index 0000000000..898637843f --- /dev/null +++ b/src/main/java/ExitCommand.java @@ -0,0 +1,24 @@ +public class ExitCommand extends Command { + ExitCommand(String task, String date) { + super("bye", task, date, command -> { + return handleBye(task, date); + }); + } + + /** + * handle bye command by returning true or false. + * + * @param task name of the user task. + * @param date date of the task that user key in. + * @return a boolean of whether to exit the program. + */ + private static final boolean handleBye(String task, String date) { + if (!task.equals("") || !task.equals("")) { + DukeException.commandErrorException(); + return false; + } else { + return true; + } + } + +} diff --git a/src/main/java/ListCommand.java b/src/main/java/ListCommand.java new file mode 100644 index 0000000000..d12955b32e --- /dev/null +++ b/src/main/java/ListCommand.java @@ -0,0 +1,8 @@ +public class ListCommand extends Command{ + ListCommand() { + super("", "", "", command -> { + Ui.LISTING(); + return false; + }); + } +} diff --git a/src/main/java/InputProcessor.java b/src/main/java/Parser.java similarity index 61% rename from src/main/java/InputProcessor.java rename to src/main/java/Parser.java index 0145ca4d4d..73e1976672 100644 --- a/src/main/java/InputProcessor.java +++ b/src/main/java/Parser.java @@ -1,14 +1,41 @@ -public class InputProcessor { - private String command; +public class Parser { + private String instruction; private String taskName; private String date; - public InputProcessor(String input) { - this.command = extractCommand(input); - this.taskName = extractTask(input, command); - this.date = extractDate(input, command); + public Parser(String input) { + this.instruction = extractCommand(input); + this.taskName = extractTask(input, instruction); + this.date = extractDate(input, instruction); } + public final Command parse() { + Command command; + switch (instruction) { + case "bye": + command = new ExitCommand(taskName, date); + TaskStorage.writeToFiles(Task.getTaskList()); + break; + case "list": + command = new ListCommand(); + break; + case "done": + command = new DoneCommand(taskName, date); + break; + case "todo": case "deadline": case "event": + command = new AddCommand(instruction, taskName, date); + break; + case "delete": + command = new DeleteCommand(taskName, date); + break; + default: + command = new ErrorCommand(); + break; + } + return command; + } + + /** * extract the command key in by user. * @@ -50,14 +77,14 @@ private static final String extractDate(String input, String command) { String body = input.replaceAll(command, "").trim(); String[] parts = body.split("/", 2); if (parts.length == 2) { - return parts[1]; + return DateAndTime.converter(parts[1]); } else { return ""; } } - public String getCommand() { - return this.command; + public String getInstruction() { + return this.instruction; } public String getTaskName() { diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 8bde11e250..9b661478e1 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -41,12 +41,6 @@ public class Task { this.date = date; capacity++; add(this); - if (DateAndTime.converter(date).equals("")) { - DukeException.DATEFORMATEXCEPTION(); - this.date = date; - } else { - this.date = DateAndTime.converter(date); - } } Task(String taskName, String date, String done) { From 5659b8d6bc1a0a813d1ada1687591feab95bee91 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 27 Jan 2021 19:57:26 +0800 Subject: [PATCH 29/62] package the program into command, driver, exceptions, task, ui and utils --- data/Duke.txt | 2 ++ src/main/java/Duke.java | 4 ++-- src/main/java/{ => Duke/command}/AddCommand.java | 10 +++++++++- src/main/java/{ => Duke/command}/Command.java | 2 ++ src/main/java/{ => Duke/command}/DeleteCommand.java | 8 +++++++- src/main/java/{ => Duke/command}/DoneCommand.java | 6 +++++- src/main/java/{ => Duke/command}/ErrorCommand.java | 6 +++++- src/main/java/{ => Duke/command}/ExitCommand.java | 5 ++++- src/main/java/{ => Duke/command}/ListCommand.java | 5 ++++- src/main/java/{ => Duke/driver}/DukeDriver.java | 7 +++++++ .../java/{ => Duke/exceptions}/DukeException.java | 5 +++++ src/main/java/{ => Duke/task}/Deadlines.java | 2 ++ src/main/java/{ => Duke/task}/Event.java | 2 ++ src/main/java/{ => Duke/task}/Task.java | 5 +++++ src/main/java/{ => Duke/task}/Todo.java | 3 +++ src/main/java/{ => Duke/ui}/Ui.java | 3 +++ src/main/java/{ => Duke/utils}/DateAndTime.java | 3 ++- src/main/java/{ => Duke/utils}/Parser.java | 11 +++++++++++ src/main/java/{ => Duke/utils}/TaskStorage.java | 9 ++++++++- 19 files changed, 88 insertions(+), 10 deletions(-) rename src/main/java/{ => Duke/command}/AddCommand.java (88%) rename src/main/java/{ => Duke/command}/Command.java (96%) rename src/main/java/{ => Duke/command}/DeleteCommand.java (82%) rename src/main/java/{ => Duke/command}/DoneCommand.java (80%) rename src/main/java/{ => Duke/command}/ErrorCommand.java (62%) rename src/main/java/{ => Duke/command}/ExitCommand.java (83%) rename src/main/java/{ => Duke/command}/ListCommand.java (64%) rename src/main/java/{ => Duke/driver}/DukeDriver.java (89%) rename src/main/java/{ => Duke/exceptions}/DukeException.java (96%) rename src/main/java/{ => Duke/task}/Deadlines.java (97%) rename src/main/java/{ => Duke/task}/Event.java (97%) rename src/main/java/{ => Duke/task}/Task.java (97%) rename src/main/java/{ => Duke/task}/Todo.java (96%) rename src/main/java/{ => Duke/ui}/Ui.java (98%) rename src/main/java/{ => Duke/utils}/DateAndTime.java (96%) rename src/main/java/{ => Duke/utils}/Parser.java (89%) rename src/main/java/{ => Duke/utils}/TaskStorage.java (90%) diff --git a/data/Duke.txt b/data/Duke.txt index a3e5c48f9f..520a486723 100644 --- a/data/Duke.txt +++ b/data/Duke.txt @@ -1,2 +1,4 @@ 1@@X@@readbook 2@@ @@readbook @@Oct 22 2019 +1@@ @@readbook +2@@X@@swimming @@Oct 22 2019 diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 63e344e0a4..87b98918ac 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,5 +1,5 @@ -import java.util.Arrays; -import java.util.Scanner; +import Duke.driver.DukeDriver; + /** * Encapsulates the main class of the Object. diff --git a/src/main/java/AddCommand.java b/src/main/java/Duke/command/AddCommand.java similarity index 88% rename from src/main/java/AddCommand.java rename to src/main/java/Duke/command/AddCommand.java index 1d1d41a9b7..6740582234 100644 --- a/src/main/java/AddCommand.java +++ b/src/main/java/Duke/command/AddCommand.java @@ -1,5 +1,13 @@ +package Duke.command; + +import Duke.task.Todo; +import Duke.task.Deadlines; +import Duke.task.Event; +import Duke.ui.Ui; +import Duke.exceptions.DukeException; + public class AddCommand extends Command{ - AddCommand(String instruction, String task, String date) { + public AddCommand(String instruction, String task, String date) { super(instruction, task, date, command -> { if (instruction.equals("todo")) { return handleToDo(task); diff --git a/src/main/java/Command.java b/src/main/java/Duke/command/Command.java similarity index 96% rename from src/main/java/Command.java rename to src/main/java/Duke/command/Command.java index cc11be91fe..fe55b80cde 100644 --- a/src/main/java/Command.java +++ b/src/main/java/Duke/command/Command.java @@ -1,3 +1,5 @@ +package Duke.command; + import java.util.function.Function; public abstract class Command { diff --git a/src/main/java/DeleteCommand.java b/src/main/java/Duke/command/DeleteCommand.java similarity index 82% rename from src/main/java/DeleteCommand.java rename to src/main/java/Duke/command/DeleteCommand.java index 558cf6903c..e9fa8a063c 100644 --- a/src/main/java/DeleteCommand.java +++ b/src/main/java/Duke/command/DeleteCommand.java @@ -1,5 +1,11 @@ +package Duke.command; + + +import Duke.task.Task; +import Duke.exceptions.DukeException; + public class DeleteCommand extends Command{ - DeleteCommand(String task, String date) { + public DeleteCommand(String task, String date) { super("delete", task, date, command -> { return handleDelete(task, date); diff --git a/src/main/java/DoneCommand.java b/src/main/java/Duke/command/DoneCommand.java similarity index 80% rename from src/main/java/DoneCommand.java rename to src/main/java/Duke/command/DoneCommand.java index 2734e390c0..1b31e7ee89 100644 --- a/src/main/java/DoneCommand.java +++ b/src/main/java/Duke/command/DoneCommand.java @@ -1,5 +1,9 @@ +package Duke.command; + +import Duke.task.Task; +import Duke.exceptions.DukeException; public class DoneCommand extends Command{ - DoneCommand(String task, String date) { + public DoneCommand(String task, String date) { super("done", task, date, command -> { return handleDone(task); }); diff --git a/src/main/java/ErrorCommand.java b/src/main/java/Duke/command/ErrorCommand.java similarity index 62% rename from src/main/java/ErrorCommand.java rename to src/main/java/Duke/command/ErrorCommand.java index 61419d12e2..8a0f33ab84 100644 --- a/src/main/java/ErrorCommand.java +++ b/src/main/java/Duke/command/ErrorCommand.java @@ -1,5 +1,9 @@ +package Duke.command; + +import Duke.exceptions.DukeException; + public class ErrorCommand extends Command{ - ErrorCommand() { + public ErrorCommand() { super("", "", "", command -> { DukeException.commandErrorException(); return false; diff --git a/src/main/java/ExitCommand.java b/src/main/java/Duke/command/ExitCommand.java similarity index 83% rename from src/main/java/ExitCommand.java rename to src/main/java/Duke/command/ExitCommand.java index 898637843f..dac8c5df70 100644 --- a/src/main/java/ExitCommand.java +++ b/src/main/java/Duke/command/ExitCommand.java @@ -1,5 +1,8 @@ +package Duke.command; + +import Duke.exceptions.DukeException; public class ExitCommand extends Command { - ExitCommand(String task, String date) { + public ExitCommand(String task, String date) { super("bye", task, date, command -> { return handleBye(task, date); }); diff --git a/src/main/java/ListCommand.java b/src/main/java/Duke/command/ListCommand.java similarity index 64% rename from src/main/java/ListCommand.java rename to src/main/java/Duke/command/ListCommand.java index d12955b32e..7cc25f834e 100644 --- a/src/main/java/ListCommand.java +++ b/src/main/java/Duke/command/ListCommand.java @@ -1,5 +1,8 @@ +package Duke.command; + +import Duke.ui.Ui; public class ListCommand extends Command{ - ListCommand() { + public ListCommand() { super("", "", "", command -> { Ui.LISTING(); return false; diff --git a/src/main/java/DukeDriver.java b/src/main/java/Duke/driver/DukeDriver.java similarity index 89% rename from src/main/java/DukeDriver.java rename to src/main/java/Duke/driver/DukeDriver.java index d302287dcc..088b0bb8a0 100644 --- a/src/main/java/DukeDriver.java +++ b/src/main/java/Duke/driver/DukeDriver.java @@ -1,4 +1,11 @@ +package Duke.driver; + import java.util.Scanner; +import Duke.ui.Ui; +import Duke.utils.TaskStorage; +import Duke.command.Command; +import Duke.utils.Parser; + /** * Driver class of Duke that handles the command key in by user and respond. diff --git a/src/main/java/DukeException.java b/src/main/java/Duke/exceptions/DukeException.java similarity index 96% rename from src/main/java/DukeException.java rename to src/main/java/Duke/exceptions/DukeException.java index aeb5b7c8a5..a6823519dd 100644 --- a/src/main/java/DukeException.java +++ b/src/main/java/Duke/exceptions/DukeException.java @@ -1,3 +1,8 @@ +package Duke.exceptions; + +import Duke.ui.Ui; + + /** * A class that store all the possible display of errorsException in Duke. */ diff --git a/src/main/java/Deadlines.java b/src/main/java/Duke/task/Deadlines.java similarity index 97% rename from src/main/java/Deadlines.java rename to src/main/java/Duke/task/Deadlines.java index dd6e257778..77fdcdef48 100644 --- a/src/main/java/Deadlines.java +++ b/src/main/java/Duke/task/Deadlines.java @@ -1,3 +1,5 @@ +package Duke.task; + /** * sub-class of Task to represents a task with deadline. */ diff --git a/src/main/java/Event.java b/src/main/java/Duke/task/Event.java similarity index 97% rename from src/main/java/Event.java rename to src/main/java/Duke/task/Event.java index 0e7eacea7f..752ce20fb7 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Duke/task/Event.java @@ -1,3 +1,5 @@ +package Duke.task; + /** * A subclass of Task that represent an event key in by user. */ diff --git a/src/main/java/Task.java b/src/main/java/Duke/task/Task.java similarity index 97% rename from src/main/java/Task.java rename to src/main/java/Duke/task/Task.java index 9b661478e1..39a755d98b 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Duke/task/Task.java @@ -1,5 +1,10 @@ +package Duke.task; + import java.util.ArrayList; import java.util.List; +import Duke.ui.Ui; +import Duke.exceptions.DukeException; + /** * A class that store the task that user key in. diff --git a/src/main/java/Todo.java b/src/main/java/Duke/task/Todo.java similarity index 96% rename from src/main/java/Todo.java rename to src/main/java/Duke/task/Todo.java index 6e8b4c32cf..c3f28528db 100644 --- a/src/main/java/Todo.java +++ b/src/main/java/Duke/task/Todo.java @@ -1,3 +1,6 @@ +package Duke.task; + + /** * A sub-class of Task to represents a toDo task key in by user. */ diff --git a/src/main/java/Ui.java b/src/main/java/Duke/ui/Ui.java similarity index 98% rename from src/main/java/Ui.java rename to src/main/java/Duke/ui/Ui.java index 7ebb1c27b5..8d3543da59 100644 --- a/src/main/java/Ui.java +++ b/src/main/java/Duke/ui/Ui.java @@ -1,3 +1,6 @@ +package Duke.ui; + +import Duke.task.Task; /** * A class that store all the possible String format for Duke for code simplicity. */ diff --git a/src/main/java/DateAndTime.java b/src/main/java/Duke/utils/DateAndTime.java similarity index 96% rename from src/main/java/DateAndTime.java rename to src/main/java/Duke/utils/DateAndTime.java index e1040c3281..9af275f029 100644 --- a/src/main/java/DateAndTime.java +++ b/src/main/java/Duke/utils/DateAndTime.java @@ -1,4 +1,5 @@ -import java.time.DateTimeException; +package Duke.utils; + import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; diff --git a/src/main/java/Parser.java b/src/main/java/Duke/utils/Parser.java similarity index 89% rename from src/main/java/Parser.java rename to src/main/java/Duke/utils/Parser.java index 73e1976672..ee92cd4a95 100644 --- a/src/main/java/Parser.java +++ b/src/main/java/Duke/utils/Parser.java @@ -1,3 +1,14 @@ +package Duke.utils; + +import Duke.task.Task; +import Duke.command.Command; +import Duke.command.ExitCommand; +import Duke.command.DoneCommand; +import Duke.command.ErrorCommand; +import Duke.command.ListCommand; +import Duke.command.AddCommand; +import Duke.command.DeleteCommand; + public class Parser { private String instruction; private String taskName; diff --git a/src/main/java/TaskStorage.java b/src/main/java/Duke/utils/TaskStorage.java similarity index 90% rename from src/main/java/TaskStorage.java rename to src/main/java/Duke/utils/TaskStorage.java index c8b9761861..737b73e51a 100644 --- a/src/main/java/TaskStorage.java +++ b/src/main/java/Duke/utils/TaskStorage.java @@ -1,7 +1,14 @@ +package Duke.utils; + +import Duke.exceptions.DukeException; +import Duke.ui.Ui; +import Duke.task.Task; +import Duke.task.Todo; +import Duke.task.Deadlines; +import Duke.task.Event; import java.io.File; import java.io.FileWriter; import java.io.IOException; -import java.util.ArrayList; import java.util.List; import java.util.Scanner; From e4b7bbe22fd2bb90fdd58fe3d5612ae6df888019 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Wed, 27 Jan 2021 21:59:25 +0800 Subject: [PATCH 30/62] Move Duke under package duke --- README.md | 4 ++-- src/main/java/{ => duke}/Duke.java | 4 +++- .../{Duke => duke}/command/AddCommand.java | 12 ++++++------ .../java/{Duke => duke}/command/Command.java | 2 +- .../{Duke => duke}/command/DeleteCommand.java | 6 +++--- .../{Duke => duke}/command/DoneCommand.java | 6 +++--- .../{Duke => duke}/command/ErrorCommand.java | 4 ++-- .../{Duke => duke}/command/ExitCommand.java | 4 ++-- .../{Duke => duke}/command/ListCommand.java | 4 ++-- .../java/{Duke => duke}/driver/DukeDriver.java | 10 +++++----- .../exceptions/DukeException.java | 4 ++-- .../java/{Duke => duke}/task/Deadlines.java | 2 +- src/main/java/{Duke => duke}/task/Event.java | 2 +- src/main/java/{Duke => duke}/task/Task.java | 6 +++--- src/main/java/{Duke => duke}/task/Todo.java | 2 +- src/main/java/{Duke => duke}/ui/Ui.java | 4 ++-- .../java/{Duke => duke}/utils/DateAndTime.java | 2 +- src/main/java/{Duke => duke}/utils/Parser.java | 18 +++++++++--------- .../java/{Duke => duke}/utils/TaskStorage.java | 14 +++++++------- text-ui-test/runtest.bat | 2 +- 20 files changed, 57 insertions(+), 55 deletions(-) rename src/main/java/{ => duke}/Duke.java (85%) rename src/main/java/{Duke => duke}/command/AddCommand.java (92%) rename src/main/java/{Duke => duke}/command/Command.java (96%) rename src/main/java/{Duke => duke}/command/DeleteCommand.java (89%) rename src/main/java/{Duke => duke}/command/DoneCommand.java (87%) rename src/main/java/{Duke => duke}/command/ErrorCommand.java (74%) rename src/main/java/{Duke => duke}/command/ExitCommand.java (90%) rename src/main/java/{Duke => duke}/command/ListCommand.java (77%) rename src/main/java/{Duke => duke}/driver/DukeDriver.java (89%) rename src/main/java/{Duke => duke}/exceptions/DukeException.java (96%) rename src/main/java/{Duke => duke}/task/Deadlines.java (97%) rename src/main/java/{Duke => duke}/task/Event.java (97%) rename src/main/java/{Duke => duke}/task/Task.java (97%) rename src/main/java/{Duke => duke}/task/Todo.java (96%) rename src/main/java/{Duke => duke}/ui/Ui.java (99%) rename src/main/java/{Duke => duke}/utils/DateAndTime.java (97%) rename src/main/java/{Duke => duke}/utils/Parser.java (89%) rename src/main/java/{Duke => duke}/utils/TaskStorage.java (90%) diff --git a/README.md b/README.md index 0dd8f7fb21..c233814022 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Duke project template +# duke project template 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. @@ -12,7 +12,7 @@ Prerequisites: JDK 11, update Intellij to the most recent version. 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). -1. After that, locate the `src/main/java/Duke.java` file, right-click it, and choose `Run Duke.main()`. If the setup is correct, you should see something like the below: +1. After that, locate the `src/main/java/duke.java` file, right-click it, and choose `Run duke.main()`. If the setup is correct, you should see something like the below: ``` Hello from ____ _ diff --git a/src/main/java/Duke.java b/src/main/java/duke/Duke.java similarity index 85% rename from src/main/java/Duke.java rename to src/main/java/duke/Duke.java index 87b98918ac..bd2a27a175 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/duke/Duke.java @@ -1,4 +1,6 @@ -import Duke.driver.DukeDriver; +package duke; + +import duke.driver.DukeDriver; /** diff --git a/src/main/java/Duke/command/AddCommand.java b/src/main/java/duke/command/AddCommand.java similarity index 92% rename from src/main/java/Duke/command/AddCommand.java rename to src/main/java/duke/command/AddCommand.java index 6740582234..13ff0e559f 100644 --- a/src/main/java/Duke/command/AddCommand.java +++ b/src/main/java/duke/command/AddCommand.java @@ -1,10 +1,10 @@ -package Duke.command; +package duke.command; -import Duke.task.Todo; -import Duke.task.Deadlines; -import Duke.task.Event; -import Duke.ui.Ui; -import Duke.exceptions.DukeException; +import duke.task.Todo; +import duke.task.Deadlines; +import duke.task.Event; +import duke.ui.Ui; +import duke.exceptions.DukeException; public class AddCommand extends Command{ public AddCommand(String instruction, String task, String date) { diff --git a/src/main/java/Duke/command/Command.java b/src/main/java/duke/command/Command.java similarity index 96% rename from src/main/java/Duke/command/Command.java rename to src/main/java/duke/command/Command.java index fe55b80cde..4c99821ec4 100644 --- a/src/main/java/Duke/command/Command.java +++ b/src/main/java/duke/command/Command.java @@ -1,4 +1,4 @@ -package Duke.command; +package duke.command; import java.util.function.Function; diff --git a/src/main/java/Duke/command/DeleteCommand.java b/src/main/java/duke/command/DeleteCommand.java similarity index 89% rename from src/main/java/Duke/command/DeleteCommand.java rename to src/main/java/duke/command/DeleteCommand.java index e9fa8a063c..a69d0f986a 100644 --- a/src/main/java/Duke/command/DeleteCommand.java +++ b/src/main/java/duke/command/DeleteCommand.java @@ -1,8 +1,8 @@ -package Duke.command; +package duke.command; -import Duke.task.Task; -import Duke.exceptions.DukeException; +import duke.task.Task; +import duke.exceptions.DukeException; public class DeleteCommand extends Command{ public DeleteCommand(String task, String date) { diff --git a/src/main/java/Duke/command/DoneCommand.java b/src/main/java/duke/command/DoneCommand.java similarity index 87% rename from src/main/java/Duke/command/DoneCommand.java rename to src/main/java/duke/command/DoneCommand.java index 1b31e7ee89..aa87d01f5a 100644 --- a/src/main/java/Duke/command/DoneCommand.java +++ b/src/main/java/duke/command/DoneCommand.java @@ -1,7 +1,7 @@ -package Duke.command; +package duke.command; -import Duke.task.Task; -import Duke.exceptions.DukeException; +import duke.task.Task; +import duke.exceptions.DukeException; public class DoneCommand extends Command{ public DoneCommand(String task, String date) { super("done", task, date, command -> { diff --git a/src/main/java/Duke/command/ErrorCommand.java b/src/main/java/duke/command/ErrorCommand.java similarity index 74% rename from src/main/java/Duke/command/ErrorCommand.java rename to src/main/java/duke/command/ErrorCommand.java index 8a0f33ab84..a7ec291f79 100644 --- a/src/main/java/Duke/command/ErrorCommand.java +++ b/src/main/java/duke/command/ErrorCommand.java @@ -1,6 +1,6 @@ -package Duke.command; +package duke.command; -import Duke.exceptions.DukeException; +import duke.exceptions.DukeException; public class ErrorCommand extends Command{ public ErrorCommand() { diff --git a/src/main/java/Duke/command/ExitCommand.java b/src/main/java/duke/command/ExitCommand.java similarity index 90% rename from src/main/java/Duke/command/ExitCommand.java rename to src/main/java/duke/command/ExitCommand.java index dac8c5df70..d4061663c9 100644 --- a/src/main/java/Duke/command/ExitCommand.java +++ b/src/main/java/duke/command/ExitCommand.java @@ -1,6 +1,6 @@ -package Duke.command; +package duke.command; -import Duke.exceptions.DukeException; +import duke.exceptions.DukeException; public class ExitCommand extends Command { public ExitCommand(String task, String date) { super("bye", task, date, command -> { diff --git a/src/main/java/Duke/command/ListCommand.java b/src/main/java/duke/command/ListCommand.java similarity index 77% rename from src/main/java/Duke/command/ListCommand.java rename to src/main/java/duke/command/ListCommand.java index 7cc25f834e..3ce7467fda 100644 --- a/src/main/java/Duke/command/ListCommand.java +++ b/src/main/java/duke/command/ListCommand.java @@ -1,6 +1,6 @@ -package Duke.command; +package duke.command; -import Duke.ui.Ui; +import duke.ui.Ui; public class ListCommand extends Command{ public ListCommand() { super("", "", "", command -> { diff --git a/src/main/java/Duke/driver/DukeDriver.java b/src/main/java/duke/driver/DukeDriver.java similarity index 89% rename from src/main/java/Duke/driver/DukeDriver.java rename to src/main/java/duke/driver/DukeDriver.java index 088b0bb8a0..5ca02a20b3 100644 --- a/src/main/java/Duke/driver/DukeDriver.java +++ b/src/main/java/duke/driver/DukeDriver.java @@ -1,10 +1,10 @@ -package Duke.driver; +package duke.driver; import java.util.Scanner; -import Duke.ui.Ui; -import Duke.utils.TaskStorage; -import Duke.command.Command; -import Duke.utils.Parser; +import duke.ui.Ui; +import duke.utils.TaskStorage; +import duke.command.Command; +import duke.utils.Parser; /** diff --git a/src/main/java/Duke/exceptions/DukeException.java b/src/main/java/duke/exceptions/DukeException.java similarity index 96% rename from src/main/java/Duke/exceptions/DukeException.java rename to src/main/java/duke/exceptions/DukeException.java index a6823519dd..48fa25b0cc 100644 --- a/src/main/java/Duke/exceptions/DukeException.java +++ b/src/main/java/duke/exceptions/DukeException.java @@ -1,6 +1,6 @@ -package Duke.exceptions; +package duke.exceptions; -import Duke.ui.Ui; +import duke.ui.Ui; /** diff --git a/src/main/java/Duke/task/Deadlines.java b/src/main/java/duke/task/Deadlines.java similarity index 97% rename from src/main/java/Duke/task/Deadlines.java rename to src/main/java/duke/task/Deadlines.java index 77fdcdef48..e3ac727afd 100644 --- a/src/main/java/Duke/task/Deadlines.java +++ b/src/main/java/duke/task/Deadlines.java @@ -1,4 +1,4 @@ -package Duke.task; +package duke.task; /** * sub-class of Task to represents a task with deadline. diff --git a/src/main/java/Duke/task/Event.java b/src/main/java/duke/task/Event.java similarity index 97% rename from src/main/java/Duke/task/Event.java rename to src/main/java/duke/task/Event.java index 752ce20fb7..d269b15e8a 100644 --- a/src/main/java/Duke/task/Event.java +++ b/src/main/java/duke/task/Event.java @@ -1,4 +1,4 @@ -package Duke.task; +package duke.task; /** * A subclass of Task that represent an event key in by user. diff --git a/src/main/java/Duke/task/Task.java b/src/main/java/duke/task/Task.java similarity index 97% rename from src/main/java/Duke/task/Task.java rename to src/main/java/duke/task/Task.java index 39a755d98b..424e1b74d3 100644 --- a/src/main/java/Duke/task/Task.java +++ b/src/main/java/duke/task/Task.java @@ -1,9 +1,9 @@ -package Duke.task; +package duke.task; import java.util.ArrayList; import java.util.List; -import Duke.ui.Ui; -import Duke.exceptions.DukeException; +import duke.ui.Ui; +import duke.exceptions.DukeException; /** diff --git a/src/main/java/Duke/task/Todo.java b/src/main/java/duke/task/Todo.java similarity index 96% rename from src/main/java/Duke/task/Todo.java rename to src/main/java/duke/task/Todo.java index c3f28528db..3a585f8311 100644 --- a/src/main/java/Duke/task/Todo.java +++ b/src/main/java/duke/task/Todo.java @@ -1,4 +1,4 @@ -package Duke.task; +package duke.task; /** diff --git a/src/main/java/Duke/ui/Ui.java b/src/main/java/duke/ui/Ui.java similarity index 99% rename from src/main/java/Duke/ui/Ui.java rename to src/main/java/duke/ui/Ui.java index 8d3543da59..3d67ad69a7 100644 --- a/src/main/java/Duke/ui/Ui.java +++ b/src/main/java/duke/ui/Ui.java @@ -1,6 +1,6 @@ -package Duke.ui; +package duke.ui; -import Duke.task.Task; +import duke.task.Task; /** * A class that store all the possible String format for Duke for code simplicity. */ diff --git a/src/main/java/Duke/utils/DateAndTime.java b/src/main/java/duke/utils/DateAndTime.java similarity index 97% rename from src/main/java/Duke/utils/DateAndTime.java rename to src/main/java/duke/utils/DateAndTime.java index 9af275f029..25b071c525 100644 --- a/src/main/java/Duke/utils/DateAndTime.java +++ b/src/main/java/duke/utils/DateAndTime.java @@ -1,4 +1,4 @@ -package Duke.utils; +package duke.utils; import java.time.LocalDate; import java.time.format.DateTimeFormatter; diff --git a/src/main/java/Duke/utils/Parser.java b/src/main/java/duke/utils/Parser.java similarity index 89% rename from src/main/java/Duke/utils/Parser.java rename to src/main/java/duke/utils/Parser.java index ee92cd4a95..1a7f6a9c15 100644 --- a/src/main/java/Duke/utils/Parser.java +++ b/src/main/java/duke/utils/Parser.java @@ -1,13 +1,13 @@ -package Duke.utils; +package duke.utils; -import Duke.task.Task; -import Duke.command.Command; -import Duke.command.ExitCommand; -import Duke.command.DoneCommand; -import Duke.command.ErrorCommand; -import Duke.command.ListCommand; -import Duke.command.AddCommand; -import Duke.command.DeleteCommand; +import duke.task.Task; +import duke.command.Command; +import duke.command.ExitCommand; +import duke.command.DoneCommand; +import duke.command.ErrorCommand; +import duke.command.ListCommand; +import duke.command.AddCommand; +import duke.command.DeleteCommand; public class Parser { private String instruction; diff --git a/src/main/java/Duke/utils/TaskStorage.java b/src/main/java/duke/utils/TaskStorage.java similarity index 90% rename from src/main/java/Duke/utils/TaskStorage.java rename to src/main/java/duke/utils/TaskStorage.java index 737b73e51a..3d21001105 100644 --- a/src/main/java/Duke/utils/TaskStorage.java +++ b/src/main/java/duke/utils/TaskStorage.java @@ -1,11 +1,11 @@ -package Duke.utils; +package duke.utils; -import Duke.exceptions.DukeException; -import Duke.ui.Ui; -import Duke.task.Task; -import Duke.task.Todo; -import Duke.task.Deadlines; -import Duke.task.Event; +import duke.exceptions.DukeException; +import duke.ui.Ui; +import duke.task.Task; +import duke.task.Todo; +import duke.task.Deadlines; +import duke.task.Event; import java.io.File; import java.io.FileWriter; import java.io.IOException; diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index 0873744649..b024e711d1 100644 --- a/text-ui-test/runtest.bat +++ b/text-ui-test/runtest.bat @@ -15,7 +15,7 @@ IF ERRORLEVEL 1 ( REM no error here, errorlevel == 0 REM run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT -java -classpath ..\bin Duke < input.txt > ACTUAL.TXT +java -classpath ..\bin duke < input.txt > ACTUAL.TXT REM compare the output to the expected output FC ACTUAL.TXT EXPECTED.TXT From a65bcf21d429b3a2673821fffd6f336edf0cc2d0 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Fri, 29 Jan 2021 02:16:21 +0800 Subject: [PATCH 31/62] Restructure Duke.exception, add in ParserTest, and new enum class CommandType --- src/.idea/misc.xml | 6 ++ src/.idea/modules.xml | 8 ++ src/.idea/vcs.xml | 6 ++ src/.idea/workspace.xml | 85 ++++++++++++++++++ src/main/.idea/misc.xml | 4 + src/main/.idea/modules.xml | 8 ++ src/main/.idea/vcs.xml | 6 ++ src/main/.idea/workspace.xml | 61 +++++++++++++ src/main/java/.idea/misc.xml | 6 ++ src/main/java/.idea/workspace.xml | 78 ++++++++++++++++ src/main/java/duke/command/AddCommand.java | 28 +++--- src/main/java/duke/command/DeleteCommand.java | 13 ++- src/main/java/duke/command/DoneCommand.java | 15 +++- src/main/java/duke/command/ErrorCommand.java | 3 - src/main/java/duke/command/ExitCommand.java | 14 ++- .../java/duke/exceptions/DukeException.java | 10 ++- src/main/java/duke/type/CommandType.java | 27 ++++++ src/main/java/duke/ui/Ui.java | 2 + src/main/java/duke/utils/Parser.java | 32 ++++--- .../java/out/production/main/.idea/.gitignore | 3 + .../java/out/production/main/.idea/misc.xml | 6 ++ .../out/production/main/.idea/modules.xml | 8 ++ .../java/out/production/main/.idea/vcs.xml | 6 ++ .../java/out/production/main/duke/Duke.class | Bin 0 -> 424 bytes .../main/duke/command/AddCommand.class | Bin 0 -> 2819 bytes .../main/duke/command/Command.class | Bin 0 -> 1342 bytes .../main/duke/command/DeleteCommand.class | Bin 0 -> 2091 bytes .../main/duke/command/DoneCommand.class | Bin 0 -> 1947 bytes .../main/duke/command/ErrorCommand.class | Bin 0 -> 1246 bytes .../main/duke/command/ExitCommand.class | Bin 0 -> 1742 bytes .../main/duke/command/ListCommand.class | Bin 0 -> 1210 bytes .../main/duke/driver/DukeDriver.class | Bin 0 -> 1619 bytes .../main/duke/exceptions/DukeException.class | Bin 0 -> 1314 bytes .../production/main/duke/task/Deadlines.class | Bin 0 -> 1061 bytes .../out/production/main/duke/task/Event.class | Bin 0 -> 1049 bytes .../out/production/main/duke/task/Task.class | Bin 0 -> 3236 bytes .../out/production/main/duke/task/Todo.class | Bin 0 -> 983 bytes .../java/out/production/main/duke/ui/Ui.class | Bin 0 -> 4596 bytes .../main/duke/utils/DateAndTime.class | Bin 0 -> 1696 bytes .../production/main/duke/utils/Parser.class | Bin 0 -> 2984 bytes .../main/duke/utils/TaskStorage.class | Bin 0 -> 3972 bytes src/main/out/production/main/duke/Duke.class | Bin 0 -> 424 bytes .../main/duke/command/AddCommand.class | Bin 0 -> 2819 bytes .../main/duke/command/Command.class | Bin 0 -> 1342 bytes .../main/duke/command/DeleteCommand.class | Bin 0 -> 2091 bytes .../main/duke/command/DoneCommand.class | Bin 0 -> 1947 bytes .../main/duke/command/ErrorCommand.class | Bin 0 -> 1246 bytes .../main/duke/command/ExitCommand.class | Bin 0 -> 1742 bytes .../main/duke/command/ListCommand.class | Bin 0 -> 1210 bytes .../main/duke/driver/DukeDriver.class | Bin 0 -> 1619 bytes .../main/duke/exceptions/DukeException.class | Bin 0 -> 1314 bytes .../production/main/duke/task/Deadlines.class | Bin 0 -> 1061 bytes .../out/production/main/duke/task/Event.class | Bin 0 -> 1049 bytes .../out/production/main/duke/task/Task.class | Bin 0 -> 3236 bytes .../out/production/main/duke/task/Todo.class | Bin 0 -> 983 bytes src/main/out/production/main/duke/ui/Ui.class | Bin 0 -> 4596 bytes .../main/duke/utils/DateAndTime.class | Bin 0 -> 1696 bytes .../production/main/duke/utils/Parser.class | Bin 0 -> 2984 bytes .../main/duke/utils/TaskStorage.class | Bin 0 -> 3972 bytes src/out/test/test/duke/DukeTest.class | Bin 0 -> 479 bytes src/test/java/duke/utils/ParserTest.java | 33 +++++++ 61 files changed, 429 insertions(+), 39 deletions(-) create mode 100644 src/.idea/misc.xml create mode 100644 src/.idea/modules.xml create mode 100644 src/.idea/vcs.xml create mode 100644 src/.idea/workspace.xml create mode 100644 src/main/.idea/misc.xml create mode 100644 src/main/.idea/modules.xml create mode 100644 src/main/.idea/vcs.xml create mode 100644 src/main/.idea/workspace.xml create mode 100644 src/main/java/.idea/misc.xml create mode 100644 src/main/java/.idea/workspace.xml create mode 100644 src/main/java/duke/type/CommandType.java create mode 100644 src/main/java/out/production/main/.idea/.gitignore create mode 100644 src/main/java/out/production/main/.idea/misc.xml create mode 100644 src/main/java/out/production/main/.idea/modules.xml create mode 100644 src/main/java/out/production/main/.idea/vcs.xml create mode 100644 src/main/java/out/production/main/duke/Duke.class create mode 100644 src/main/java/out/production/main/duke/command/AddCommand.class create mode 100644 src/main/java/out/production/main/duke/command/Command.class create mode 100644 src/main/java/out/production/main/duke/command/DeleteCommand.class create mode 100644 src/main/java/out/production/main/duke/command/DoneCommand.class create mode 100644 src/main/java/out/production/main/duke/command/ErrorCommand.class create mode 100644 src/main/java/out/production/main/duke/command/ExitCommand.class create mode 100644 src/main/java/out/production/main/duke/command/ListCommand.class create mode 100644 src/main/java/out/production/main/duke/driver/DukeDriver.class create mode 100644 src/main/java/out/production/main/duke/exceptions/DukeException.class create mode 100644 src/main/java/out/production/main/duke/task/Deadlines.class create mode 100644 src/main/java/out/production/main/duke/task/Event.class create mode 100644 src/main/java/out/production/main/duke/task/Task.class create mode 100644 src/main/java/out/production/main/duke/task/Todo.class create mode 100644 src/main/java/out/production/main/duke/ui/Ui.class create mode 100644 src/main/java/out/production/main/duke/utils/DateAndTime.class create mode 100644 src/main/java/out/production/main/duke/utils/Parser.class create mode 100644 src/main/java/out/production/main/duke/utils/TaskStorage.class create mode 100644 src/main/out/production/main/duke/Duke.class create mode 100644 src/main/out/production/main/duke/command/AddCommand.class create mode 100644 src/main/out/production/main/duke/command/Command.class create mode 100644 src/main/out/production/main/duke/command/DeleteCommand.class create mode 100644 src/main/out/production/main/duke/command/DoneCommand.class create mode 100644 src/main/out/production/main/duke/command/ErrorCommand.class create mode 100644 src/main/out/production/main/duke/command/ExitCommand.class create mode 100644 src/main/out/production/main/duke/command/ListCommand.class create mode 100644 src/main/out/production/main/duke/driver/DukeDriver.class create mode 100644 src/main/out/production/main/duke/exceptions/DukeException.class create mode 100644 src/main/out/production/main/duke/task/Deadlines.class create mode 100644 src/main/out/production/main/duke/task/Event.class create mode 100644 src/main/out/production/main/duke/task/Task.class create mode 100644 src/main/out/production/main/duke/task/Todo.class create mode 100644 src/main/out/production/main/duke/ui/Ui.class create mode 100644 src/main/out/production/main/duke/utils/DateAndTime.class create mode 100644 src/main/out/production/main/duke/utils/Parser.class create mode 100644 src/main/out/production/main/duke/utils/TaskStorage.class create mode 100644 src/out/test/test/duke/DukeTest.class create mode 100644 src/test/java/duke/utils/ParserTest.java diff --git a/src/.idea/misc.xml b/src/.idea/misc.xml new file mode 100644 index 0000000000..7d862fbd38 --- /dev/null +++ b/src/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/.idea/modules.xml b/src/.idea/modules.xml new file mode 100644 index 0000000000..f669a0e594 --- /dev/null +++ b/src/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/.idea/vcs.xml b/src/.idea/vcs.xml new file mode 100644 index 0000000000..6c0b863585 --- /dev/null +++ b/src/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/.idea/workspace.xml b/src/.idea/workspace.xml new file mode 100644 index 0000000000..aa3c8d9c61 --- /dev/null +++ b/src/.idea/workspace.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1611771282430 + + + + + + + \ No newline at end of file diff --git a/src/main/.idea/misc.xml b/src/main/.idea/misc.xml new file mode 100644 index 0000000000..9f24f5833d --- /dev/null +++ b/src/main/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/main/.idea/modules.xml b/src/main/.idea/modules.xml new file mode 100644 index 0000000000..aaf7df43bd --- /dev/null +++ b/src/main/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/main/.idea/vcs.xml b/src/main/.idea/vcs.xml new file mode 100644 index 0000000000..b2bdec2d71 --- /dev/null +++ b/src/main/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/main/.idea/workspace.xml b/src/main/.idea/workspace.xml new file mode 100644 index 0000000000..600c78ca65 --- /dev/null +++ b/src/main/.idea/workspace.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1611767634287 + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/.idea/misc.xml b/src/main/java/.idea/misc.xml new file mode 100644 index 0000000000..dda71418a5 --- /dev/null +++ b/src/main/java/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/main/java/.idea/workspace.xml b/src/main/java/.idea/workspace.xml new file mode 100644 index 0000000000..9b8aa8fdd9 --- /dev/null +++ b/src/main/java/.idea/workspace.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1611772006855 + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/duke/command/AddCommand.java b/src/main/java/duke/command/AddCommand.java index 13ff0e559f..e067294fae 100644 --- a/src/main/java/duke/command/AddCommand.java +++ b/src/main/java/duke/command/AddCommand.java @@ -9,13 +9,18 @@ public class AddCommand extends Command{ public AddCommand(String instruction, String task, String date) { super(instruction, task, date, command -> { - if (instruction.equals("todo")) { - return handleToDo(task); - } else if (instruction.equals("deadline")) { - return handleDeadline(task, date); - } else { - return handleEvent(task, date); + try { + if (instruction.equals("todo")) { + return handleToDo(task); + } else if (instruction.equals("deadline")) { + return handleDeadline(task, date); + } else { + return handleEvent(task, date); + } + } catch (DukeException e) { + System.out.println(e); } + return false; }); } @@ -25,12 +30,13 @@ public AddCommand(String instruction, String task, String date) { * * @param task name of the user task. */ - private static final Boolean handleToDo(String task) { + private static final Boolean handleToDo(String task) throws DukeException { if (!task.equals("")) { Todo todo = new Todo(task); System.out.println(Ui.biggerBox(todo)); } else { - DukeException.emptyTaskException(); + throw new DukeException(Ui.EMPTYTASK); + } return false; @@ -63,12 +69,12 @@ private static final Boolean handleDeadline(String task, String date) { * @param task name of the user task. * @param date date of the task to be done. */ - private static final Boolean handleEvent(String task, String date) { + private static final Boolean handleEvent(String task, String date) throws DukeException { if (task.equals("")) { - DukeException.emptyTaskException(); + throw new DukeException(Ui.EMPTYTASK); } else { if (date.equals("")) { - DukeException.missingDateErrorException(); + throw new DukeException(Ui.MISSINGDATE); } else { Event event = new Event(task, date); System.out.println(Ui.biggerBox(event)); diff --git a/src/main/java/duke/command/DeleteCommand.java b/src/main/java/duke/command/DeleteCommand.java index a69d0f986a..23f36afa42 100644 --- a/src/main/java/duke/command/DeleteCommand.java +++ b/src/main/java/duke/command/DeleteCommand.java @@ -3,12 +3,17 @@ import duke.task.Task; import duke.exceptions.DukeException; +import duke.ui.Ui; public class DeleteCommand extends Command{ public DeleteCommand(String task, String date) { super("delete", task, date, command -> { - return handleDelete(task, date); - + try { + return handleDelete(task, date); + } catch (DukeException e) { + System.out.println(e.getMessage()); + } + return false; }); } @@ -18,7 +23,7 @@ public DeleteCommand(String task, String date) { * * @param task name of the user task. */ - private static final Boolean handleDelete(String task, String date) { + private static final Boolean handleDelete(String task, String date) throws DukeException { if (task.length() > 0 && date.equals("")) { try { int num = Integer.parseInt(task); @@ -27,7 +32,7 @@ private static final Boolean handleDelete(String task, String date) { DukeException.NumberFormatException(); } } else { - DukeException.argumentErrorException(); + throw new DukeException(Ui.COMMANDERROR); } return false; } diff --git a/src/main/java/duke/command/DoneCommand.java b/src/main/java/duke/command/DoneCommand.java index aa87d01f5a..bd2db03d9f 100644 --- a/src/main/java/duke/command/DoneCommand.java +++ b/src/main/java/duke/command/DoneCommand.java @@ -1,11 +1,18 @@ package duke.command; -import duke.task.Task; import duke.exceptions.DukeException; +import duke.task.Task; +import duke.ui.Ui; + public class DoneCommand extends Command{ public DoneCommand(String task, String date) { super("done", task, date, command -> { - return handleDone(task); + try { + return handleDone(task); + } catch (DukeException e) { + DukeException.argumentErrorException(); + } + return false; }); } @@ -14,7 +21,7 @@ public DoneCommand(String task, String date) { * * @param task name of the user task. */ - private static final Boolean handleDone(String task) { + private static final Boolean handleDone(String task) throws DukeException { if (task.length() > 0) { try { int num = Integer.parseInt(task); @@ -23,7 +30,7 @@ private static final Boolean handleDone(String task) { DukeException.NumberFormatException(); } } else { - DukeException.argumentErrorException(); + throw new DukeException(Ui.TOOMANYARGUMENTS); } return false; } diff --git a/src/main/java/duke/command/ErrorCommand.java b/src/main/java/duke/command/ErrorCommand.java index a7ec291f79..32aa672203 100644 --- a/src/main/java/duke/command/ErrorCommand.java +++ b/src/main/java/duke/command/ErrorCommand.java @@ -1,11 +1,8 @@ package duke.command; -import duke.exceptions.DukeException; - public class ErrorCommand extends Command{ public ErrorCommand() { super("", "", "", command -> { - DukeException.commandErrorException(); return false; }); } diff --git a/src/main/java/duke/command/ExitCommand.java b/src/main/java/duke/command/ExitCommand.java index d4061663c9..6df4be14a1 100644 --- a/src/main/java/duke/command/ExitCommand.java +++ b/src/main/java/duke/command/ExitCommand.java @@ -1,10 +1,17 @@ package duke.command; import duke.exceptions.DukeException; +import duke.ui.Ui; + public class ExitCommand extends Command { public ExitCommand(String task, String date) { super("bye", task, date, command -> { - return handleBye(task, date); + try { + return handleBye(task, date); + } catch (DukeException e) { + DukeException.commandErrorException(); + } + return false; }); } @@ -15,10 +22,9 @@ public ExitCommand(String task, String date) { * @param date date of the task that user key in. * @return a boolean of whether to exit the program. */ - private static final boolean handleBye(String task, String date) { + private static final boolean handleBye(String task, String date) throws DukeException { if (!task.equals("") || !task.equals("")) { - DukeException.commandErrorException(); - return false; + throw new DukeException(Ui.COMMANDERROR); } else { return true; } diff --git a/src/main/java/duke/exceptions/DukeException.java b/src/main/java/duke/exceptions/DukeException.java index 48fa25b0cc..d3e0a5e782 100644 --- a/src/main/java/duke/exceptions/DukeException.java +++ b/src/main/java/duke/exceptions/DukeException.java @@ -6,7 +6,11 @@ /** * A class that store all the possible display of errorsException in Duke. */ -public class DukeException{ +public class DukeException extends Exception{ + public DukeException(String errorMessage) { + super(errorMessage); + } + public static final void DATEFORMATEXCEPTION() { System.out.println(Ui.WRONGDATEFORMAT); } @@ -14,6 +18,10 @@ public static final void NumberFormatException() { System.out.println(Ui.KEYINNUMBER); } + public static final void EmptyCommandException() { + System.out.println(Ui.EMPTYCOMMAND); + } + /** * display the error message for empty body error. * diff --git a/src/main/java/duke/type/CommandType.java b/src/main/java/duke/type/CommandType.java new file mode 100644 index 0000000000..7873598f94 --- /dev/null +++ b/src/main/java/duke/type/CommandType.java @@ -0,0 +1,27 @@ +package duke.type; + +public enum CommandType { + TODO("todo"), + DEADLINE("deadline"), + EVENT("event"), + BYE("bye"), + DONE("done"), + LIST("list"), + DELETE("delete"); + + private String type; + + CommandType(String type) { + this.type = type; + } + + + public static CommandType valueOfType(String type) { + for (CommandType t : values()) { + if (t.type.equals(type)) { + return t; + } + } + return null; + } +} diff --git a/src/main/java/duke/ui/Ui.java b/src/main/java/duke/ui/Ui.java index 3d67ad69a7..b831e45712 100644 --- a/src/main/java/duke/ui/Ui.java +++ b/src/main/java/duke/ui/Ui.java @@ -1,6 +1,7 @@ package duke.ui; import duke.task.Task; + /** * A class that store all the possible String format for Duke for code simplicity. */ @@ -22,6 +23,7 @@ public class Ui { public static final String COMMANDERROR = "I DON'T KNOW WHAT U SAYING BRO"; public static final String TASKERROR = "Walao, no such task"; public static final String SAVETOFILEERROR = "Huh? Where your file?"; + public static final String EMPTYCOMMAND = "Walao, command cannot be empty!"; public static final String FAREWELL = UPPER + "~~~~~~~~~~~ I Zao Liao. Don't Miss Meeeeeee ~~~~~~~~~~~." + LOWER; diff --git a/src/main/java/duke/utils/Parser.java b/src/main/java/duke/utils/Parser.java index 1a7f6a9c15..e3841d5003 100644 --- a/src/main/java/duke/utils/Parser.java +++ b/src/main/java/duke/utils/Parser.java @@ -1,13 +1,9 @@ package duke.utils; +import duke.command.*; +import duke.exceptions.DukeException; import duke.task.Task; -import duke.command.Command; -import duke.command.ExitCommand; -import duke.command.DoneCommand; -import duke.command.ErrorCommand; -import duke.command.ListCommand; -import duke.command.AddCommand; -import duke.command.DeleteCommand; +import duke.ui.Ui; public class Parser { private String instruction; @@ -15,7 +11,12 @@ public class Parser { private String date; public Parser(String input) { - this.instruction = extractCommand(input); + try { + this.instruction = extractInstruction(input); + } catch (DukeException e) { + DukeException.EmptyCommandException(); + this.instruction = ""; + } this.taskName = extractTask(input, instruction); this.date = extractDate(input, instruction); } @@ -53,8 +54,15 @@ public final Command parse() { * @param input the input key in by user. * @return String representation of the command word of the user input. */ - private static final String extractCommand(String input) { - return input.trim().toLowerCase().split(" ")[0]; + static final String extractInstruction(String input) throws DukeException { + + String instruction = input.trim().toLowerCase().split(" ")[0]; + if (instruction.equals("")) { + throw new DukeException(Ui.EMPTYCOMMAND); + } + + return instruction; + } /** @@ -63,7 +71,7 @@ private static final String extractCommand(String input) { * @param command user command. * @return the task name if there is one and return empty string if task name empty. */ - private static final String extractTask(String input, String command) { + static final String extractTask(String input, String command) { String body = input.replaceAll(command, "").trim(); if (command.equals("todo") || command.equals("delete")) { return body; @@ -84,7 +92,7 @@ private static final String extractTask(String input, String command) { * @param command user command. * @return the task date in String and return empty if there is no date. */ - private static final String extractDate(String input, String command) { + static final String extractDate(String input, String command) { String body = input.replaceAll(command, "").trim(); String[] parts = body.split("/", 2); if (parts.length == 2) { diff --git a/src/main/java/out/production/main/.idea/.gitignore b/src/main/java/out/production/main/.idea/.gitignore new file mode 100644 index 0000000000..26d33521af --- /dev/null +++ b/src/main/java/out/production/main/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/src/main/java/out/production/main/.idea/misc.xml b/src/main/java/out/production/main/.idea/misc.xml new file mode 100644 index 0000000000..40674af8d6 --- /dev/null +++ b/src/main/java/out/production/main/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/main/java/out/production/main/.idea/modules.xml b/src/main/java/out/production/main/.idea/modules.xml new file mode 100644 index 0000000000..122a9054e1 --- /dev/null +++ b/src/main/java/out/production/main/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/main/java/out/production/main/.idea/vcs.xml b/src/main/java/out/production/main/.idea/vcs.xml new file mode 100644 index 0000000000..c2365ab11f --- /dev/null +++ b/src/main/java/out/production/main/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/main/java/out/production/main/duke/Duke.class b/src/main/java/out/production/main/duke/Duke.class new file mode 100644 index 0000000000000000000000000000000000000000..fed1d60d5249037ab2eb6e9d06a59801fff61162 GIT binary patch literal 424 zcmZutyH3ME5S(+I7(0f91Ok+F2?dsDjcACdEGUB9P@V0Qx!~B+VMqKH6^Mcl;G+<` z1`!HQx_!*dKC~a7Z|?v?9C@(NabWxCq9-t1%C!s%S?0k_vQ%j;&^y3c z3$6ptN1x@Bta(sDX7pN_U{3M84F&q@Nu^D#7;~^K;I>Lm1?j;VhmcyVq%LXx^e)O27eliCw*b2swb&SYgmCd0 deb(8pa5lAkc96D%@t=Ad`ISP(1t0t!jgsMV^CebE5EG^j0@R{J_61FURzV|Ihm_G|w` z?H}-~?FaSfIsE}W{Y^c6X0tIHrAT{D&hE_JJNG{KxzEhx&%a;%0U(c`Qhaq;NT6Gw zN7ic2roio);yt+`bB=UZbBjUUc31N|v80<$jlgztD-E|C*q)o4j|O=Yy)X>)S?Gr; zu&2^kSGlrRtxC6&D>UB%y%%lQ4n7hn{ZA0vVn~fm7Rnsl@ zbF*yaTx%+jQq@|pxx~ydV`3&)0HU~?PF4NQE9d><|ebO&Mc3z#)9XJH;!1V%&embx!hDz5}?u2JufTJmPS ztr2WhbRVt>^i`rFOcd~`g(4QH!DhHteF7JDR#a?1x0x;AriEKN>_9VYSm{n<#zMYQ zJlQFD6-D}rWdBB^x~%F;a@nCJRrJczDapF6=aI2HShKn5#+nL#lfOKn*{&bd8{z4q zqqId7Wz`*__V}t$7u;s??Z8$s#;(Ocme&_#ElS(pqE>JCn0t#>pKE%QZaY;Q`yTSc zZ}x;@Fw!ksw2sC?A}(dxKScjoSPRd72VZnJB<8y-*WVpu6x$Q4-*ygKiTfogpA zSG@RWQ8U5SQ2G8;(eu_Dwe7Ezj)hB`H5GT?`Nw9;?bpUPTokz=9cR%FR6dECz|nX` ztt%kby~srR>UwMX79^IFXb5DZqqrsH?OSSHb6r(0IMVl(Z-7VnkvHhyib(@M2uy76 z${VdoI}QOI2fR4&8K0kX_B9N2^PS9Oj~(al1?_l-p5JKe!Xlq0-@pKdum?*V zWt#rDjS^>Ei7)V_Ud7QJjnd>7)P@qs&IPtF-BkF{GCkp89rDbxMNLlovliE^O><#+i0ttgYGmU)EoXS!?gOlDG_u%(aC$2MMm zl1W_+XZ=|ccm0We-e|XTgbD=oWxR|3#|AM>&7&m=rIbfW+=oG8f#j+SiYkyIx=5A1D81ERZG7^__dpoO^xd`;RYQ0qA&`M+#{fl7bAf4COQ9wV^qN zJJL=DXO_tsvIn+n^FxMoyVK9%8ger73JOpdYQx~%(oAnWHr%0hG+!ACwmap1U~=1Y z87kdN(jND1cccrNl7bb%A#r1RE)uH>Dq&)1a7!d=3hG#+ikE?FGHlFw0&Y8+$Ov}r zI12OvuA?ENsi1`$46X3YrN@qnIQ2uFp&yqOjVxCBmrQcgdZ$m5Jo1Jlb){>&){9^~u>4bF z;83R0^-RO*8@?^Rqol-N*;9tKWbI<(3g}|80KWYX`u}BuqE*>?W0?V`-s5@=X z5k?PJ@^`qBt--KKaSFHS=8+?@Me%LQyrVTkYg7FMrtZujtGhE4)x8oKS_5U=rJYA}Cfvg|eTjOZh=q~RBy={#ts_1W30)HIQ@p6E zlRha@+9qTND!qly$AlJ4CG{h!>SwH{@C_U9DU%AdWy9TSsAJAnigYmSU^imXXca6O jVv(1@>oIWV7kDobTwDgX62be4;PNtfGZCzX%{}-DwaX${ literal 0 HcmV?d00001 diff --git a/src/main/java/out/production/main/duke/command/DeleteCommand.class b/src/main/java/out/production/main/duke/command/DeleteCommand.class new file mode 100644 index 0000000000000000000000000000000000000000..344677d16c12f00a200729447e0f594b2f0a290a GIT binary patch literal 2091 zcma)7TYD2#6kR6?Ghvw05NV~5-XOHORDw4Y1E{2}L{qAyMn$}wB&X@n$xNI%Q{|`l z;wztT@Phex@CW$$oBZ5!X*;2@_92;b_St*wwb$Nr=C6NV{t2LpZW;*&r7KJ!MV3q{ z9jBl$oZ^Fl`GlcXXgub7ykc^zS7}PeuzJ;_mSSk~q+wRJJ*y)P+p4Tbi>ih+POH## zoPo}8zU%FZO2_W^xz(-I!Y7fqWmty1!_YcW%A+KX3#|1hTKY84A8K&X{H`|XzM^=juHC)6c6*(QVm}5A1h+ns) z=n01*J>ZTjX!{CAq-(LRVF8OOF6&6(3d7kzDaqa4$`<`Gqzd(7OT|@&`9t{oUcW7z zb=&E4x%Nv(41D!9ETf>JsH223!)$;g_D|i)D)r#NndpoK36vn=mhpy;Yd+32cY0o5 zSaQvAZ07(#!*#r=;w>F-ULN*EcMN|Y8B=n{pjpW^{=1GUVfxMW5f0lK@u#ycmxP|Qygmb~(~owGG0(9*BhZPa zF~jZkUMtQomB9Jh6iY>*wXPOs0Eh~WiqTio34>YP#Q(>ZQhZ#Ls!T*I6|&*(`*`2R5SRR zVJTkG{`C{%8ktBwx|43;TODDJx$6p7#g7bEkH|kx zNfm8|x#L~wHVtLRB2i4!hX+W4dPmOfnZ1l&5L)T!Ijmzj%waYSUvBc0On zNBXf}`AWaE9zOI3bo!e*-IJ79E(%l6_+IvQpWS`-ZuQqcul@v3#gBPp7{)rTBZ?## zGcb-E!#MBv?dJ@4%8h6Ih?_Qdx@J>)meZ|PB2geM+uRSFwzOQw+=>@f9eJG5pc^;~ zgJG%@9164T_Iljun6+qT$gNwBCGRt|QXIVQ@-)dQF;rSQ&S6qR!N7SG84CYRf+Dbm z)0GDd*>a_>V+zw6N(L@shT;5Bz3xcS6&^#r&pltzmSH+2W`!|}%Nnj2$Y74)T$s4z z{-L=`194ogS6UjbGF%q=JNr5f2NvX`rldO5E!PJ>ker&vU&K039n>)o{zeTev-v`vcdt1$P*=#Tyr}FJ=w4v5fQV?_iU0B8*ZE1E$&%r9}CCif#oyIHcpGUN{Fh6%6?e3*q?eh zToQKH33?2yPJh}hBs5cNL!c8)$=iq9ydMW**u1yb;Y*JAX=#n&UJ5g#F~*D@zs8Yr zP{raGM-@vqW6+y!;I+k;rN}8Higa7$Ng`rj`qJb5Z6Ocbjz5{h=Q0bgn{TBcL literal 0 HcmV?d00001 diff --git a/src/main/java/out/production/main/duke/command/ErrorCommand.class b/src/main/java/out/production/main/duke/command/ErrorCommand.class new file mode 100644 index 0000000000000000000000000000000000000000..6b3749fc7f2f867f49d35680788623998f5352e7 GIT binary patch literal 1246 zcma)6TT|0O6#kZ$ri5rO0$LTYSg-{pc*9E^9xO0AQ{|ydAAH-UTL`4tPA*mcl|ISv z;16*8O^zpNlyoc%lbP(ElXJfFoo`R}=kK#001Uj&VuArhGSV6*kzttR{l0y|uvo1% zj`)D*3@H)XHKosM1~t_+zsmSg!_46W)A z&F0R5-t=9|IWVs7xqw5hrQ$kr3i28XC^F1PEW{U6^h36uzD=xl{+bN4F~J?zm2SeH zs)kTAm{l;R;U;b|6r$!Mx^Jbl1$P*f0k;FO*JYTiev0KuMi>fiGn7W8h)Vs_BVCsr z!H{cMj`$e#+QQxEZJRvBhBUd|;;t3iu`}%-S{}ol#)XImgJ$zyyTdDv_*~gwSgVdk z$EA&Nbg83Q5b9`r8iU%DfoqCgE2LRSwzD2e#E>U_e9w1z|AX)kWyi~9P*qXGs)98Q z5Ald$>0C|A8AuwHM#P#jc$b^LbZO+Kdr9k8a$@47VS#rvVz%%q4JnU<{^esdlDL1; z7s>Fee;k&)JU6Luj9llo-L!mRQU;(PM_Kc<(}wX_z#^roVIMKpCaob>_7vArr?~Nz_7gbA$P)Hc l0waqh+^3inDpBMzR%i|JACPYy8+eLmu=K=>-C5Qj-+nr|56sL0^>N z!5`rGn;cITAV_7H%p~WWd$#X8IrrC}lb-kRU5)fx^&PsqcxLYF4Y< zsN@R%mmxN*8JhEwp>(a1mz%htB>x3ReTa{BuGnwWAKV_uTmN)&snBR^bliZe4e{y0^+}L0U!U)pCW88sgLF48z*BxVqRwKzhD0 zA5t(+qO5TkgS>9mEmbUPF8E|ULJzx~Ux47z<7VTzBHLU#(V-14*0?XddV~-Y1bFW@&u)ZOJF9dEJ)iZakcD$@70) zSuqS@6?AUf!j`biFm{RlModb0%P@GgE8QnP?HHyO<8;FU5zy=~LGLta9}pu8kep1h z>{NE@#MOR4`bM@UWaur^7v$B31SUxu^8Jy;6loNRyO^eIu9PFG3H|Pk669A&cjNme zQ?1|8_8E#Vd_nveU6G^c5gkUnLMcQ^?m!Bi=%S~G9=Bk(pTH|aD&2f;8HO2>qi9M+ zld?;FP;iO7T|kM+>@jX0WB4m6K9ZQ%r4&MuI7^xcl2RZZ;Gvh~kr(+GPw1;q>{Cko S3U4rvMY70bS;7k5q3Exph|4N@^ zc<=`}{wBwpHY4c>9VRo`-J5gI-gEYDe*HQB3BbfV6)6T3Xpzw|g)GAq@AvIfhUId_ zI_3jzgn_h;Zs@cF={m-4JTWz>xS>GPF%6wzwiBKRqwV&3-02wA(a4Z}FC7`|Ff_{} zHk&(#Mm_MPb7)>aazzc5riNR{Dah-XL4iRVRuM|$vt&@LTD?)*-(yIZBjhaZD45f6 z7xN4=Lv6!qKDe$exI+m8ZinKa%P?2|601)lOa+S!^J7Xa=?DMRW~y#SFyt)hi2bnF z5?+J1Y>E^tx6SP)_hht=gPGt+`V5QKRfHykZu4HN!%L3%TH0dRD362Voz2UNB|Y(R zken(g_Y77 zxYP#LuxQHQUEU5{kJ@Rvmt6f$c0-&r+TbI#k1hO?<+>+fe{zeAB{oj`A_>3#$I+IP zbCU+g%vEmNbr}dV4})PXspz0}EZV`?sl*|&@0o@LJlF9M#XO31#5KneUe)HlFMI{t z46FYcdYLy0-Y_gphSCKb8Hplos?s$FQlQhIE6;F`Ry%a-=?{SXdVxjHInuxnDBp+3 z`}Ec*1IQvrvj;TOM|dn@nbNdKN6fWNW5lJN;b!^_x4+Rmg$oXaxYY!QiWNK}Od6#j bausVdM*NQ{wuvpgz)Ol~6nTZ$c#DO<2H!#W literal 0 HcmV?d00001 diff --git a/src/main/java/out/production/main/duke/driver/DukeDriver.class b/src/main/java/out/production/main/duke/driver/DukeDriver.class new file mode 100644 index 0000000000000000000000000000000000000000..38bad14a36f2e7e000e917a919f24f2360e3ac44 GIT binary patch literal 1619 zcmZ`(+fv(B6kW0bflx@e)0CD&u3%^s(v-G=Bn@B)jkpvOD3sPcwiQsYB}S4nVTS2{ z#u==vRNZx~s%t%UoAHr`P~`cD+Eecs2SVh<7GJgp;vlxl3r?T;S;A6g zYC5(`zCujWD{mPG3fmG}`TS^}OIvyN@&|^2kI}E=6BD0eKttyV^HafU(Dzj6WhG6G zcq~1IalP#c#kvQBCa&PBhUU4IY<6{iaZW==BGPHwW?a{BH&cJax^yEUcYYDJFH1xd z&)l*jp80{;_p73AmtmkixM^ZYrN1#}XS2%&G8oY@YT`3B*^{Wrbcfce40m&pAINP- zLra;^vxE&*3M~`2F-A^1GF)_CGD9qwO||m5iM#lM3_MQTu1D9dq2UiX82A!j>G;~j zJxrYJTMFD4PGHS2qcd?=gXya3c`UtB*$Mtfx=khBeG?C2>1H3TWY@E{t>YV(?7-@hKE}L`Z%sUbO-|<-Q4i;( zQ>;b=>OMny%J<8T^oX*EB^}EqzEkoghbvBP&4PpriS3#!SBcXw?U&eGR8lThD+MQ5 zm4z~AI&8lv%WE=l)wnj<5bd}jStJ}jkds2U)*@6IGv105hH-w=g?)~-O`hJc$P!L6 zcKY1Y`9dy|#oYzDSKCgnsl@!9uNv#Z@k({L(@Y6x+!~jpR#!(B_>&|}>EX}#4x6n5Z z(efG>pB$p2qwffp*&ae9osMg4k8$G|!>v3WNdJS34!t);Y@Q(6Ds8rE^m^Xn;Rf}2bcAVpNQZ7&~JZOt+ca(rYJY zyr~G>`ygDQJ`xzr=8i@{gOM1-6L23Ax6JEZUvUSmWPs2_rRPXUecuzVswO;`CH{4paF&&35ryahw&?%*7!E<1u)cfC-o+ zFdpHaK&%}Gvt5jz?I+Ny1fvVLRmdG_@QA?leuXoi(+aaPbeDIjaH$(OC)~?uFil{z z!E7co)fzR5^b)-mD$$ z;r4l>yl?E(s+ea#!e(#IH(jMmUBZn$-GwJa980qk=~7iv?F{U=UT!$bN6hb zDIJ`Xc~_qbdv#Zt^w|YBB#y1`2d`)yyVvBQ20L)8Rr&DZK?dgW-Gtu=knrW;x`>jF zJHdT;=?9Rn_%i@mT*KqgG>2=VZvad10;M!8U&GffzdWjJSU>)1h7KpRNE;o9<} zK-@4JNnFJ>71wp#z)gYlLZspPav(hc_1qdx<>84y&S)&tql_BkZ|k_jg=`R>Z9K3> zlH&y(cR8+7yl(jvyN?GdiaH)*_phcxgQ=C1u{W~()mCk_uB`dvULI zY1u=^l@kHw?bs%pHk-6Pn2vhVYg@e`MKaBC-x?lSp2PbnsQB+4I+Sg$VAaS=el^@F zA73~ZRY77lb<9(6HEcoq(+3J@{`gO~$<}!4_2oNxttuT$8Gsr^zDG>ZxX)MvM zfjIpEwX|2BL42iU40|-P<3O4cGbq!l5T;=t7244ORPl%)yn0NlSb$xRux*l2=$l5^ z{TbAMxmh}u3%I2)Z_d@`TrJ`f1y4vJPVA@1Mhaz`Sv{8c%wte9HwAiqT(2H}jkp5O zsF$$iF162jW+thAhu(>oW=OR<3Qd^{9>Ap6B{jTY4e literal 0 HcmV?d00001 diff --git a/src/main/java/out/production/main/duke/task/Event.class b/src/main/java/out/production/main/duke/task/Event.class new file mode 100644 index 0000000000000000000000000000000000000000..fc0669944ac3d4819e2626b236433321a838a8fe GIT binary patch literal 1049 zcma))+int36o&r|l$p|zQ=!%a6%Sa3Qt)gH#v9uvB&59<(u9y+46uvS!i*UPqVME| zUeTE71NczJwT2O}?S+u+!)B$1+;tUK|l z5(pRddJH$Qso<7|+qff;T8PwbPxhrNpiIocSRS1UY!vIu^dO_g_?(6bOJGyWYz7QgbsGYReS`m!v=!NG$Gk ze?WihkkIubGxZ8KB=JQA z0R%OKbX1{QV9Q-&&PYrfxrxNU_+2w&3sj%6a+ZBoAQ+7eZ9o_sG(>c4gf6ftTbeQx zwo#l)4Dv@HEZ_T$8B?GxwdyNv7p&YwQd)1)u^C&anK5RKjAbtfh+cV6r(>%;sIqcd zb3TmiJZO>!J9NAzgN3sBoEb)=0Hk=Aj@^#fu+0bsdv!EnA8{JltiaZ2YAv{=gMPn` z7PPuZQ&y1~ZgG&7Y->6pCCQCAh^U5`bQourDiQBkV0+Y;o5NEwHY%;!b#$PU7$!_Q z-X86Zt=A0W5K|kD;0TUtIHu#cL>*CROIG5VMQ}1z$*6{t0{d5q?3LUMlJaW6s)EJ{Lh3PHRZ&I3w%0TX{2APK${i7Rpm*ab%q?6bku*CzSBd>UcxKuP&G~ z`8l$B1m|>|ckr3hrma9p%^n>WaFIwY+bkG%z93K^b(2+0^}2GBc?rE5-q!IBQjEMx z=8B4dHfa?5&3RJBCL@uT(63_vms#|j5^r1a?Q6|s7*_>0j5@5cN5WlGoZg($NJcPFdsC>0@)s%9;J8nQ^l)XpB#*>C9)0=^>+F$!}K}vL~&goQJZ>5r|eu)t9Lo zaa4w^%1oLWt^zSCaPXDPq*Wy@*9TZHk+y=h2(g;-m8rG*wElHo$eG}v)ue4BGu3Cz zx(rljRhQGB91wOF=UC36v(nafp_}xolCw?fR$A3t7>w1jPFS&w)mE{Glh3hYT!mdt zL@)bR0$G^lk$mgn%5&m&ds{SY=N&|}K9iYtmv$tbFBLN8MN1ZagG{AUwjK6yVFq{w zR3jqyAq2+x6+ni6TMu4-%?Tun?n*2{wGH=avQO=6I%ykbrM^G*bWif zVTG;9iBJ)nESxNQ6>=`3N7R;V#VWAXA=&yrKu2kQjDU_4&bvl3T5?l+SJi9+xsi1$!Xo;p!f17p*NhJdBvM3Bv1@?ie%7GiiU zE)VAGOrQAP1e}M%qiL zlXU=wn9y~O+b~CLg#QqZlF%`xc!O!(ruI!s)N2%hkdDT zL)D-1KdG>WOD%sOa9-st@IL0<@+A0F0~~(=?Rx?WD7LGW(DK!`%59(qEZ_rb$)&SP zX#pX!B5j4ww&*Ujdz9X<7_PoN-2DpS1U|$^bRom}vDSW9hV@}Z@?RP#=e%1S-rCdv0-Jxtt&x{7o})R)J3vme1IL-> N8g=CeJdiBm;XlkjU`7A{ literal 0 HcmV?d00001 diff --git a/src/main/java/out/production/main/duke/task/Todo.class b/src/main/java/out/production/main/duke/task/Todo.class new file mode 100644 index 0000000000000000000000000000000000000000..cae2a4c7a3b89bb809b017a1d575799c7aa4fdcc GIT binary patch literal 983 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 literal 0 HcmV?d00001 diff --git a/src/main/java/out/production/main/duke/utils/DateAndTime.class b/src/main/java/out/production/main/duke/utils/DateAndTime.class new file mode 100644 index 0000000000000000000000000000000000000000..b5dfb0babceba28aa3c1fc292fb761c2f7bbded3 GIT binary patch literal 1696 zcmaJ?O>@&$6g|(9Ek{w}VB^#_gg6w4?F8JWlu}I7(wOj38B&~KhIXac3K2L`D#^6n zcc#CgU3NOdCJVYrGc4G4roV$9!K(B;*(6R8^+->8x?ktsd*1cm|2%&Ipn-KA2`Cy= z14*O=rXE>Ota{IKAJ*?~JhD5XKIz&QjsKa1OL5)62l$Z14t9DDyIqM%_Ez=VxE7}Ik%5bnN@GrNr@w9c zPDjTje4^p9flqPe2rZgkf1}54jz?X6vx_BHQ^Qq(*+bUR`G)Ne+H;U18Mfke=`mwE zu02p$x1t!?h(-4;-;w*_M>X7X0)c`V&-(_`=y>iE+m8rvE~XAKO%X_RS-t!S9S#^w zkAm<9_As%JoVk!K?&HKB=AN0^`DeVS zuc1KOvrr=cB}M?JnuZBvNa`Zj5~eVNTokiRy$nx76W3{5;%*f;_{LbciCcW$=B**| zK*L#u<{Xd|OHjX4SvtQ+G}Y{4Y7ZC8h1TMWW#y8ZS7(01$;G_7bR}6#MrfCQMN--Q zNfl3Dzf^Z=HwsYtEpZ5)K#e15k?%{~$)ZSrvjqPY!6aq0A*^v!VWLGW5?}$!Yi5+x zFsb1VFToTFuV^tQ&*2bppG8!tovZyNv9OpQ-+YRcsq7LETTBp>{P!3DJH@QQ38mr; tCG(WkD6OzsRSx!r2;4LsW_aJl8tv&AUmw&g4JCC$LnA@SJ<1Yj{|h`WgKPi* literal 0 HcmV?d00001 diff --git a/src/main/java/out/production/main/duke/utils/Parser.class b/src/main/java/out/production/main/duke/utils/Parser.class new file mode 100644 index 0000000000000000000000000000000000000000..f0d6f99db630360a8a0ac7c7fc0bbbdb2b0cde2c GIT binary patch literal 2984 zcma)8TT>Hf7=FHxurVwms~{fmgd&h=JXC7L(jp+B0j!`^D7H(o!a~U6W`od!t+v+I z+S5fZ>P4r$a;CkZGZmRK<7F@U3p)J;y>h0P&RE;$+bkF$cAA;p?~wQKeDCwV@3+4_ z{pBHmCVUlw4@C<6Dgr1LSU09m>Cu#)9*Oo2j~NL^p!m3%Hl1dHqPqI?Aq25TK}baj zRDtqjcHD?&9W#}Qp3&`$VGFD^rX5>PIIY&igq}_c)YiqHS?zOdGdnQ?)m1-z}+e~$l36&t1hphH_d`h+3< zY*Mi~-%p$F7!vGO71dJMpX5de+p$BzP8GXQvn-Ce6Vv9Xo*8Yml7<_}t|0bsGCbpI z?p0BTddAwglGRfgfr|W7B3U6cA|_Men84nA2p(+(0?Cv(j+YcP zt9Ti&kbc*;j9)ZINXdxd$XT4Q$z`1vdYLp)xz`lJ3A8F`Q_+r-0+o3=CH49o%hpF2 zHT9}(I!3>B(o7i)(RvTxGeh;~6?CpVopj-)Vh9~F*H5n$X=50dL{1^5phsZivKX}_ zlS>laI3q*!szB_2g{V-_6!ZyfUgo0B%OETwBB=hc~iUADD zEU?W9fenixcFWjfPRb3bxFqFD94l^JHSAVB!!&tQK*C;{pR zSDz+`%L0%VMpc-yQbM*dnbH$RODYuvYqEIo(t&-kp&*D(L={*9b13vTI$=!8@|Sk6NMvj+bp_(xRR~fD4zdcSR9uy9DnF%U^|qvw{pJKy zYE8mQPZ_o&`_{6O^P*Ny0{pp}EsL|Lda@J4hTX3Zr>LyOt%ROBuiK_vdz*e|)Rf5? z&&%RmXKZ3*&GclJkqu1BUdc2hQ_JY}n5C$aSZtq_&l4%_bM(Y`w?65*R&bNl7qZ5f z(^o?tasM50diM`o$(bBZN1mnt>k4kO*jd|M`K@}f*k$kJA^5k9H#4Ho%GwD-mM-%z z7m)oj1+bHy)W^H1h;R0O&U~^5yCd5x#~_FV(|pfxWxA5Uo`wey4dHnx_fgsqZul9c z^C-WMip6==eQf#3HS-qVl{5jA!w(Je-l)O`>_!FNcK?$A_TU}7%Tdm*(J^l~yodL5 zZhZ>%{eWndj=Fu#kvVMpk+R?OQD!gSl=H74u07(|f@sYRjzc&!`z^;_G>)F+I3D=b zzRU5}Hvb0AIlxscqV0EA2a350N3;X( zYL~)QbwoSlt~La@DvM|@xU1rI#m&_}&hNFG>?{h=vzR?#Ruq$-$UmDPUXqOxpia#-Eyn+nQAY$w=Ljoo@76_N)~XAc3z8z zXX&;Gl9Xdu%l9VyjxG2TTk(h&>R+t)$Jl`<*d?z_jxm}dHzmjlONUPNT z;THK1D)^96o8^~}my0p#v-P2j#9f%f>)IQ0(2EYq1Nz(p7Q27PT(DA!qHbaj-a(3OVgc2Oa$DH{f z1GN_ZC#aTjD(_V2ZL|D7^3HO{J4;R8S%@+)hsmCO4+GyJw9kKN9+_DQcrg!h#d(21 zFET6x%!ol|z|aynpk@hD%@U+457K%9`vkY?Sb{5o_*;I7ZCCIqG2Nl5T;qsxlnex9 px~`;XIFF)$*9ZhYE2vztQu%U0<hf3vVQ`Gfus*898LB4PLNWjBFu{g`qfgk}(=UM$8b+2%EG{ zx^L;;G>x4$byvE#PFujHb=P!B_kI6E`h9Ncxg!b0(*96=nwj_RyYDXNF7Lha?_0M4 zwBR3MtV5X!p9Vhy3MwxelSVXSSR>J%3m45HS3%%V+Df}e6qMD}_Nxdgh3gYi3o16>Lf6#>{BWO=p~FpW%!pT{~-xm_cX?)~5{Dh_;iV(Y@@3p<;umtWdDI zCcdOJ>1NZ`NK0*hIW{7qqDsRiY*w(rV-eBOc-o;=LD6bZ0oB&j<|TN`u>!rN99ywX zMYV>zaCgz@Wh@HRQNu}?mno0Vos%8gHSEB>3VfDF-c*!b0!fRCowUev)}@=CuVLtT zm4;o|O{pWM+cz~~dQxMuvR6Y5YKdjqX}2vdESFpGS~%-9Gze$8$e{3qF>VUIQA1Sd zBD>vi3F`d{5XJ*|P{l(U9>%MeMK3Rs8qFtiM#fnIb3V2$wdW$tf`b~G(V}4MxG`q7 z+18NZ4y4^tjvUvpT<+boR)|(dEsVoBqT;BARx!0Cmy%PCYmPGuGHJ_9niGZ>x(E~; z7v*gV&ez0N3;h2mg>3L5wur2X4h@}>Z~jY?v66vZ8e)?4{-KQRm?};ws4Av*tf%Ah zkU8O|Z7Ym!BvkZhI4#`Uy}+BrRmV%}MP>yRjxlNW*-{%F*{sddIHN!-$`x`DeM~SZ zh%kDwL0$tIUL#o=FfTK`oe+^cr{NL2mN{hSn4g>TSg`0$vqD_@Wg6qm#77l`^JSNg zo=pewxPpPY#h>10SeEVT!)Ys}PuaPwo=Rs~)pmADH%A*t&pNK|rpHa)7(J@DQK)O` z%us#U&dLUTQB++xj0+f2knYpX>*}LKl7=$m-u^1AEeu*`mHH_ltB^9>|tFh-dPSy2$wZX z;Yn6)))YolDp$eALfI5LCA(S>uO~!(WMY?7@f3NM8e4LR!7_={6}&-uOV zq@-0iVLXScV$d}O2iI_HwLz;Xa%z2)b-5(IW74#E2EBl*f^L^&=5-C9kjyM^?@4sT zdycio5+`VQXDr@v`dD8V&yUrDnQ6r)*>7ZWZ0n)+*qM&DzMeCKEbulvMN);tE0G(& zU}pP_3mH-(aeK(f^c&f<%nL-H%N$d%EuJstm1ij1v*z`!d}ASJRRN8~Gm+_~Kq17H zc^QjG6ZftgzQi*p@4>Qjn`>oemLXc|FD0Fit3eTyKXNPc`_+|Fv#lwI$g_G>M zL#9~B$Vgu(+=?2d@JTvu+pgngjfrm49ko+VMF77H<5&2#ir>iD_*(_LydL3|RN9)f zdB@5ZPX4U!G`xPU;Q7+}C@|)Qb{STR2JBC2x4?`B*|(woz^|Yp|DsQoKs6 z7SU#8GD#k_EkXRAY1Z1R1o1~kN#Tfp{-DLA+;46(gHy8nA^o#I3xPZbKt|J1N!Ds^zC zDk>h}e*wW2i~glWuKyG37X)nXm)FTM`Y%DeNt|yLgQV=B!4lljdGroOlCwB_s%{4T z*HHBm1|yHnz~FRvU=C@Ifq^(1CvruG3>i4Jgn{2DLeE}91;?^E$F&>vbGXD9oD#z8 zgy3oG$D@RLfHySxmU)mTP(?d-6SO_FcrO93A+WVfzXsG}A3<$oJx6hrpd9DHeF_gE zfrl85hbieGWgVup7CeSS7$KMBm+l3j7xVZQXZ76qZH^T31aX_;$U}Y?{CBWZMeiNx zd~Xuin1aMCNGo_VDdc1ylRL_u+ULr`jU z96!R3iKQfMGXi%IQgP)D_Nw^F0_r4xdr9DoKuW&y55$?o3*59Wzbg6oQ|_0>A$jl$ g$LsJj{G8tn9Q}gy-+Avp;7_E5IsY^Mioc`!KVj75KL7v# literal 0 HcmV?d00001 diff --git a/src/main/out/production/main/duke/Duke.class b/src/main/out/production/main/duke/Duke.class new file mode 100644 index 0000000000000000000000000000000000000000..d457857c617efe2a7cab5b9f3692d09bdbf1ab3c GIT binary patch literal 424 zcmZutu};G<5PeS5grzr3}uBEAeK)1Pq0e8rQBt1_82TB>ql zEx0aeDE^0L2xfJwb8#h&XU`~}7?BWNcs}+*?877C*N-k@k`php`BzZ(#sZ?O=YgqYz| dI;PKkg|nUw$O4GSF#a>|VhaP?Kcwhj`wLPQP*nf` literal 0 HcmV?d00001 diff --git a/src/main/out/production/main/duke/command/AddCommand.class b/src/main/out/production/main/duke/command/AddCommand.class new file mode 100644 index 0000000000000000000000000000000000000000..b0937d2b9fb2260177a349c21073aacbe005c6b1 GIT binary patch literal 2819 zcmbVOYgZFj6y28qLxv#wjRX`z8)7n~Uv9`)Xu|aJ?TBvYWqQ5x>kQcSASDi_njHcL?X3a$(s8>#Ju`p){rnFAllVEy=3^a$nCiks z9iQNmhEH{L;Ikwy-1sGrIq&9r7;Rgc} zYZ^)h$}lyo8`x0un+7awY1lSkqhi3pmcXHgiI;RMJ4}OgV=3U)zz9YKy7tsEFpdcW zr!gTg*u+*NJb}KZm52}>RooRg8Q13K+Ll@Jr{WApQ|gA+1oGpp$&H_Axjbyb6U?$-G;awz?g0r+b90 zzA_&L`Kqm5&o?Uq3AfG*)E~mI+`=uEHlIgKSz%OqpjO=~+_nUgYu3hwS-axi7Z{Dm z50j0Rp-HI7CDSPY-)vSut12fpYu9jK-@IQktE!lJg&7vT*}Wlan^~#)yGyhmn@o(W zSb7`0L@Lwpjkl4b89iftt#XG+Ay)K!873FzJUT* zQcg6GSk8{is$C394zI3UmnGk=G4Hx7jgf{QDPqxex9e3FsCmaRYty#$Jd>LK71uPf z7Z!nQK@s;x!-EIEewq$0?N-hB_BUS)T^@Wk&U0jWTH5xa<(pF)ei9hl$4{$x1dblO z565}$2l>_qU-E)AX^79m9Nl3FY-gLvKvEcLpceOV9($T;yq&W3_fFmrXoD`$G)9K*vh%DaHI9TK*Zj zo*?-MozI{ro}v3Owu4C^SF1I`jw zf!w@DPR|kG2Xu9wy^jKDii2@N%OM}cJ{dt%A7P3ieo)Xx2NLPjA);jY|F0<10m{t3 zpqwVk8KRsc%Bw^~F|9z<2?JhRPS5adeom57@Y
<&1};z;TEUC-g48b+p09{Pbw|;b zaP%x%lv39VebYLyd3b7auRFY7Dr(qPQ9@aT%4UvD1yuz*Ds(&$n7`P=M2$c_Yf%KQ zUX;GoT6PfC=oQm%pP zWLf7ELUT<;`vh70fc%4IB195u3Jq*0)s z!V9lmytOaIs}FoY7vIFP{&mRAK{vMd~BeK>juVfL&r@WpD<|G9nX&yxes{hUt1M z+7p)TcRJi_Su4U7Qq+=Jl{h62_Y}jS7-+4M*c%`V;Z_%%0>tYktt-a`iV`bfx1f#AriudvAkx(^Hu)?=)L{-V?vhUt!ohRxpDS z92|Zrcd(~2UIBA$70E(e8AHYw5schecclXrPmc+TkcXl zmzF4Fn)oH+F7?`EHiiSWNSD)nigizlwg?ysT^@vjrvHPbVJY6RI5Db0t*y9A^QCna z(M)U?2VD|cE7ajHn}+y?)<+yIp{IDzjyl4Vt3lug8CWLDG)WBlK6fLrxkIqh{b6a; z@x6%$_}RpHTwu7+KdIyG`*iWt<9?;;=R4e%en1I7)#=Z4G)cg^@9#xjx@y)vPXslW zhoK-n|HaZCu z9nxpmc^GD2y^q8mqfd|e8LevT2~FXWz*Z3M5;(@++i zB=jiG(CA#UACs7(86ojH-XJzLdXq*Ybc4_xlJfsabH!gNKSTZx%vB~%JcIT-rpi6& zH>P_iJjUoo55{9?J)Fw*U_K$JqM9bBxj2Lc8iCvuiGGq+)Y>#TnISjlXmk;?SfG&# zuZ%qH$&+=4T+a~0Eau`PRN_Es3o3D-j1WKpxd%EInu5qH5$tRHkqBt7B^3EK_6X)kjmwU8Aq9Tmd5#n=dCs|Ehk@1TPq^un zO&s~U=XZo!`>iRv%Jwv3q@hG}e?xSW_)SN2c3NWAmA}qjW4N0|(?Dv6X=Mk*69yQ{ zgNz))DAk4+`c1iRYfeikrmkvwG$RoSCCX9-$`{=YsrI~9Fj~M$33q9_SHc%2?&C`n zC-8uyYGM^@9P1_?;t@y9#2g+oTq z;{#hsVg|lJgJC|+-{#J9*;LDErV^E|(Jh9hN;XMpME|mfMYrp`V7Q(>BPrzs5h~lU zc0;$RZ`)c=7If{~8JJYHyt5%Yn2-BZH1G+%&U%qA#_>z?XV+V zwdVVtpMs^LOc-b22f_*E<}Sf1&$8}><69HkcxK`PE;7vYGqv3VkKTiN)Lc}+VplYk z=hN*S@AM^(pNOuy=k14G2D9e6(yuxq2qZlz|D}mZ{Kc*CD0(Y`*%+AdjHPaN0J!y{ zE7Rs5z8N3+er%ed#B)_RPQzAmnd4`Mxg-2!<->6P{dSn9?iryE0+0h03Px!xk@OV9 zqya`3$Jo-9rPmk&{zmRkQVroGjfU2M6U2c2qFjv4aSG!k5fBq7lQX?KO{*bH>DM4} z|2xeZKePB3@_(Sb*u(J3nH~x+F;efL_!5O4j^%nVUXdlIkWSHY4ZB!=mq&Y)=#>vB3+S5_ZMDYRVXyNL=aFG&!aQ!KKK47C+Ezkmfu5i0>)=d6G?%FOy9L H3t0Rg4$Aua literal 0 HcmV?d00001 diff --git a/src/main/out/production/main/duke/command/ErrorCommand.class b/src/main/out/production/main/duke/command/ErrorCommand.class new file mode 100644 index 0000000000000000000000000000000000000000..d3e410704177673dd1dd0d6ef51d26f9d82289fe GIT binary patch literal 1246 zcma)6TT|0e5dIFmq@>ZN6;MP#uwV;HyyB$}4^|kRsq#>!55AqIrw~YUI=NK&SNbHw zgFnFWH#u(FbeaxOoz5h?d%pd)yWi&g`g8shzze+2V75Tkf(iw9R4igi#WL8o$ zrtEaM(=v8lSGv`KQ(@3--f6aY(Gg#Yj~F&fk`2r=v)(H66N!b==pGK}kVb z!v>}mY-)IbhYa&q_Qo(Xb{2J_VhaYtdMVb>e)CwEekI;x6jG4}O(n&>;z1QkG`Ss`YCxB_>o6w)6Xh?;M;UOK>)hPrjv@14G3xFb6^7n?vAQoZx?L)9tC(3hG~ApYX9>~em3>)%VFKDK za+k2O7;wqg5;PWOt<1Xyu2#hUAtImjbSQ*2lRTF zz#|Qh@kB#2o-#new1#JRuHc1+EM_!xqD#R`4YPQ~(0!Tm3?1jT0%|H=;|;?|Se&)O zp3vQFm~^ltEj7oGPSxiduBge>$jfE(h#?p5ak=SysjIGGX11%A?i#k0SquUaee+r< zq5tb#r%Pa^(-Z&uk?xE5Smh=ex-;DLOdhgapC_p})J0j&S;@?k?-$NestX*l;5fDu zT92e;$F^F>KrQmr0XM5+ZJRum+N!6gf}DnVENkdS55r&$!>|r)x^;Qa^<*Tz&2`sy zNcrYcEmQE8h~;g2zglL{RxC?6Ig?i^f_VN8^9=BOOD=mivNGfs*7;b36hBwEaa0!J zwCtN(eG&d49yR|py>p$$Z_F2KAt{-a)PF>l=w_y-jqs+Mf@LVJOHIan*Wvua@(uy!xFt!s$IYe R7OBx4%B6l%i2)4a-d{qX$glta literal 0 HcmV?d00001 diff --git a/src/main/out/production/main/duke/command/ListCommand.class b/src/main/out/production/main/duke/command/ListCommand.class new file mode 100644 index 0000000000000000000000000000000000000000..d7e285b20b3c4ca6628fb2de5c4854fdec6f780e GIT binary patch literal 1210 zcma)6+fvg|6kUg2QbM$$A|fgX7HmO@SG?5W!OozaiSW?c2j5Q9Q#g<&om}ehSNbHw zgCF4dO^!Qln5F|%Co?(wvi929mz-aJ&VB-Tg||7}ERb|Zg@U^(?qNyAGVUu_QLxI8 zeJ33m>@cKCb3<#-jt5m3%f1hHF(P=OTlz4Za29nBRw{zgG1>vESl}`SQwVu z?Q*AWn9>ibL%G7B*}U6o^P(fZ7N0O|md3&7z_NM7``oa(b6~u8U0ZO6f|Zz)VgB+k z2DR>no+Wl=^p$!d_f|y60J0Kc;0GS>eG4>QE2tzZj7=)Cpq^xSuV`of$LG}Gu@G<;5F@~>AJ^Z zkM^hLIKr#i-1i0T+V5lsV!q*2Kho~m!Y>X3C%0uRuyN88N%;Rehbbq=COZ@}SGjH1 zWgsdF-Y~3P=+9;KFf2{RVTG1Sp+6m%qMgrSn%*jDJIIg(=o0U;$b2Jt3L_2$Dat(J$YB=I?UTZd0dfv6 Y=~Rj1Io(Y!a2xZaNBM3MW`Xp@ztdPjZU6uP literal 0 HcmV?d00001 diff --git a/src/main/out/production/main/duke/driver/DukeDriver.class b/src/main/out/production/main/duke/driver/DukeDriver.class new file mode 100644 index 0000000000000000000000000000000000000000..d66aafa8a963daa5f6aff74c5b554e358fc9a394 GIT binary patch literal 1619 zcmZ`(-BKJy7(KlU%rXoR{y|YYY7$s56JkUSBr(83Fw2iD0g33^yE}miyED|xY${Yy zzDJ(G8*k)-P)U^!;GJ*bLs;tRnJpkeXLq{4{`!2seR_WX`_*p%K1apG0Bi#{S}}o} zCQ|rROScSsmcgV+#22k-!Iv4_HaSn3n8qCqyQ_zLCi?M}2HZC=W1pS+3VgPOz>@RcgBPepyvFRN(4$L)jGV zx}m^ezEa`LH1a{_yg@?0!V3A8!SopL>Lv{JyRIbo=FVs}r~Gi6tmw__Kg!1Zb5KE~7|w`v#4%JZCnp!Pzf%6m&{zmbFGdi(Y0f$}O-YLRsV^8_%g=9!go1+k816%EK5{lvKa*v!$(J zS{alS`?lqFu{d7j)^?Fn@z6BzjfFK7EUe?Qz^&}*BR7>BNwxcv%=@as zGm%eNuYBSM^1!dlQ(V@x@CZW&HY{vn$ilbSvhWz+S-6G~3)|XnS5hYrFSJ)x5ITYG z0;7J99}E;N{0L>BWTA{L9!iY9z#xH3XFORcJ$1^_8>+%V7&$fa#r1gf$;rFEy{IWc zS~;r5vm0zs;;ju$_q1Q9!!yHGGV#o?Cyq_Cb80eaUxTVT;D2$AUNZ}8x!n5V@`6Bf zA)m|f)RX!&l|y@7g?oj_58{i^T4k#>t$2@&T@@}n&zTV~BRQM#xX?FIpm${SBCm;< zzrU8-%;ocpw6B}2s~!D6g7?Nvev9}F+qk2;pz~4A*q<=_{FM-}O3CHeP}RDF%lzI9 z@WTb9!5lEe@g1&g&VqAu_9eux6jFGXV@s@T$1r6p0pLBn&s8fvI5qx*&eGJayhdv4 z2OF~$1s;X}-DH-{@&#??4=Nk5Y;KyqIY zWf1cbOKig&kyq&ZDqj=nzmPSM8c4;yM~KzE*>05A{~BFe>`(VGKR#o}=v^8=M&B<) qB+crGn{b11Cio4%c^VnaSVz_^G%?DIdF#-OF^tnv;FH+H^?w0C{cO4b literal 0 HcmV?d00001 diff --git a/src/main/out/production/main/duke/exceptions/DukeException.class b/src/main/out/production/main/duke/exceptions/DukeException.class new file mode 100644 index 0000000000000000000000000000000000000000..e50ef862dad26c446b65ef0d160ccacbbdc4b4d1 GIT binary patch literal 1314 zcmaKr+foxj5I}nn$RC@fQ)AQ^1kDmar2CE4e1&l)up2pyr1kV#N2lEmvNRXGH zAi<&pFCQxEMa!Mp2FRW8_Egpw0%=pUd3^2=f*+S)LmD%+GXyEyJwk}ZJOLt@9NWD z;QWrGl*=!LVsGh2-w%UC!}gt)2sD({txFZp`6W+63dUlvl7yG=ip;|@__}q3TWEzZkYg~~ z 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 literal 0 HcmV?d00001 diff --git a/src/main/out/production/main/duke/task/Todo.class b/src/main/out/production/main/duke/task/Todo.class new file mode 100644 index 0000000000000000000000000000000000000000..ef05e0d7f134a4ef44e0eefcbbc16b8f05fe9f7c GIT binary patch literal 983 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 literal 0 HcmV?d00001 diff --git a/src/main/out/production/main/duke/utils/Parser.class b/src/main/out/production/main/duke/utils/Parser.class new file mode 100644 index 0000000000000000000000000000000000000000..a23b88d425b60c5d3277f493af107d6f668a33ec GIT binary patch literal 2984 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 QY?5aDw Date: Fri, 29 Jan 2021 03:47:41 +0800 Subject: [PATCH 32/62] Pass excepetions handling to Parser, add in more Junit test for Parser --- src/main/java/duke/command/AddCommand.java | 54 +++------ src/main/java/duke/command/DeleteCommand.java | 16 +-- src/main/java/duke/command/DoneCommand.java | 13 +-- src/main/java/duke/command/ExitCommand.java | 18 +-- src/main/java/duke/ui/Ui.java | 14 +-- src/main/java/duke/utils/Parser.java | 105 ++++++++++++------ src/test/java/duke/utils/ParserTest.java | 68 +++++++++++- 7 files changed, 174 insertions(+), 114 deletions(-) diff --git a/src/main/java/duke/command/AddCommand.java b/src/main/java/duke/command/AddCommand.java index e067294fae..d06af73794 100644 --- a/src/main/java/duke/command/AddCommand.java +++ b/src/main/java/duke/command/AddCommand.java @@ -1,26 +1,20 @@ package duke.command; -import duke.task.Todo; import duke.task.Deadlines; import duke.task.Event; +import duke.task.Todo; import duke.ui.Ui; -import duke.exceptions.DukeException; public class AddCommand extends Command{ public AddCommand(String instruction, String task, String date) { super(instruction, task, date, command -> { - try { - if (instruction.equals("todo")) { - return handleToDo(task); - } else if (instruction.equals("deadline")) { - return handleDeadline(task, date); - } else { - return handleEvent(task, date); - } - } catch (DukeException e) { - System.out.println(e); + if (instruction.equals("todo")) { + return handleToDo(task); + } else if (instruction.equals("deadline")) { + return handleDeadline(task, date); + } else { + return handleEvent(task, date); } - return false; }); } @@ -30,13 +24,10 @@ public AddCommand(String instruction, String task, String date) { * * @param task name of the user task. */ - private static final Boolean handleToDo(String task) throws DukeException { + private static final Boolean handleToDo(String task) { if (!task.equals("")) { Todo todo = new Todo(task); System.out.println(Ui.biggerBox(todo)); - } else { - throw new DukeException(Ui.EMPTYTASK); - } return false; @@ -49,16 +40,12 @@ private static final Boolean handleToDo(String task) throws DukeException { * @param date date of the task to be done. */ private static final Boolean handleDeadline(String task, String date) { - if (task.equals("")) { - DukeException.emptyTaskException(); - } else { - if (date.equals("")) { - DukeException.missingDateErrorException(); - } else { - Deadlines deadlines = new Deadlines(task, date); - System.out.println(Ui.biggerBox(deadlines)); - } + + if (!date.equals("")) { + Deadlines deadlines = new Deadlines(task, date); + System.out.println(Ui.biggerBox(deadlines)); } + return false; } @@ -69,16 +56,11 @@ private static final Boolean handleDeadline(String task, String date) { * @param task name of the user task. * @param date date of the task to be done. */ - private static final Boolean handleEvent(String task, String date) throws DukeException { - if (task.equals("")) { - throw new DukeException(Ui.EMPTYTASK); - } else { - if (date.equals("")) { - throw new DukeException(Ui.MISSINGDATE); - } else { - Event event = new Event(task, date); - System.out.println(Ui.biggerBox(event)); - } + private static final Boolean handleEvent(String task, String date) { + if (!task.equals("") && !date.equals("")) { + Event event = new Event(task, date); + System.out.println(Ui.biggerBox(event)); + } return false; } diff --git a/src/main/java/duke/command/DeleteCommand.java b/src/main/java/duke/command/DeleteCommand.java index 23f36afa42..c61d3b2c34 100644 --- a/src/main/java/duke/command/DeleteCommand.java +++ b/src/main/java/duke/command/DeleteCommand.java @@ -1,19 +1,14 @@ package duke.command; -import duke.task.Task; import duke.exceptions.DukeException; -import duke.ui.Ui; +import duke.task.Task; public class DeleteCommand extends Command{ public DeleteCommand(String task, String date) { super("delete", task, date, command -> { - try { - return handleDelete(task, date); - } catch (DukeException e) { - System.out.println(e.getMessage()); - } - return false; + return handleDelete(task, date); + }); } @@ -23,7 +18,7 @@ public DeleteCommand(String task, String date) { * * @param task name of the user task. */ - private static final Boolean handleDelete(String task, String date) throws DukeException { + private static final Boolean handleDelete(String task, String date) { if (task.length() > 0 && date.equals("")) { try { int num = Integer.parseInt(task); @@ -31,9 +26,8 @@ private static final Boolean handleDelete(String task, String date) throws DukeE } catch (NumberFormatException e) { DukeException.NumberFormatException(); } - } else { - throw new DukeException(Ui.COMMANDERROR); } + return false; } } diff --git a/src/main/java/duke/command/DoneCommand.java b/src/main/java/duke/command/DoneCommand.java index bd2db03d9f..ad72a6d116 100644 --- a/src/main/java/duke/command/DoneCommand.java +++ b/src/main/java/duke/command/DoneCommand.java @@ -2,17 +2,12 @@ import duke.exceptions.DukeException; import duke.task.Task; -import duke.ui.Ui; public class DoneCommand extends Command{ public DoneCommand(String task, String date) { super("done", task, date, command -> { - try { - return handleDone(task); - } catch (DukeException e) { - DukeException.argumentErrorException(); - } - return false; + return handleDone(task); + }); } @@ -21,7 +16,7 @@ public DoneCommand(String task, String date) { * * @param task name of the user task. */ - private static final Boolean handleDone(String task) throws DukeException { + private static final Boolean handleDone(String task) { if (task.length() > 0) { try { int num = Integer.parseInt(task); @@ -29,8 +24,6 @@ private static final Boolean handleDone(String task) throws DukeException { } catch (NumberFormatException e) { DukeException.NumberFormatException(); } - } else { - throw new DukeException(Ui.TOOMANYARGUMENTS); } return false; } diff --git a/src/main/java/duke/command/ExitCommand.java b/src/main/java/duke/command/ExitCommand.java index 6df4be14a1..0b9d674337 100644 --- a/src/main/java/duke/command/ExitCommand.java +++ b/src/main/java/duke/command/ExitCommand.java @@ -1,17 +1,10 @@ package duke.command; -import duke.exceptions.DukeException; -import duke.ui.Ui; - public class ExitCommand extends Command { public ExitCommand(String task, String date) { super("bye", task, date, command -> { - try { - return handleBye(task, date); - } catch (DukeException e) { - DukeException.commandErrorException(); - } - return false; + return handleBye(task, date); + }); } @@ -22,12 +15,11 @@ public ExitCommand(String task, String date) { * @param date date of the task that user key in. * @return a boolean of whether to exit the program. */ - private static final boolean handleBye(String task, String date) throws DukeException { - if (!task.equals("") || !task.equals("")) { - throw new DukeException(Ui.COMMANDERROR); - } else { + private static final boolean handleBye(String task, String date) { + if (task.equals("") && date.equals("")) { return true; } + return false; } } diff --git a/src/main/java/duke/ui/Ui.java b/src/main/java/duke/ui/Ui.java index b831e45712..cc1f167d3a 100644 --- a/src/main/java/duke/ui/Ui.java +++ b/src/main/java/duke/ui/Ui.java @@ -15,15 +15,15 @@ public class Ui { + "| | | | | | | |/ / _ \\\n" + "| |_| | |_| | < __/\n" + "|____/ \\__,_|_|\\_\\___|\n"; - public static final String WRONGDATEFORMAT = "Err, wrong date format.. (yyyy-mm-dd)"; - public static final String KEYINNUMBER = "PLease Lah! Key in number!"; - public static final String EMPTYTASK = "Walao!NO TASK!"; + public static final String WRONGDATEFORMAT = "!!!Err, wrong date format.. (yyyy-mm-dd)!!!"; + public static final String KEYINNUMBER = "!!!!!!!PLease Lah! Key in number!!!!!!!!"; + public static final String EMPTYTASK = "!!!!!!!!!Walao!NO TASK!!!!!!!!!!"; public static final String TOOMANYARGUMENTS = "You put so many/few ARGUMENTS for what"; - public static final String MISSINGDATE = "Fill ur date lah (add date with / in yyyy-mm-dd format)"; - public static final String COMMANDERROR = "I DON'T KNOW WHAT U SAYING BRO"; - public static final String TASKERROR = "Walao, no such task"; + public static final String MISSINGDATE = "!!!Fill ur date lah (add date with / in yyyy-mm-dd format)!!!"; + public static final String COMMANDERROR = "!!!!!!!I DON'T KNOW WHAT U SAYING BRO!!!!!!!"; + public static final String TASKERROR = "!!!!!!!!!!Walao, no such task!!!!!!!!!"; public static final String SAVETOFILEERROR = "Huh? Where your file?"; - public static final String EMPTYCOMMAND = "Walao, command cannot be empty!"; + public static final String EMPTYCOMMAND = "!!!Walao, command cannot be empty!!!"; public static final String FAREWELL = UPPER + "~~~~~~~~~~~ I Zao Liao. Don't Miss Meeeeeee ~~~~~~~~~~~." + LOWER; diff --git a/src/main/java/duke/utils/Parser.java b/src/main/java/duke/utils/Parser.java index e3841d5003..9e3713e6b2 100644 --- a/src/main/java/duke/utils/Parser.java +++ b/src/main/java/duke/utils/Parser.java @@ -3,26 +3,43 @@ import duke.command.*; import duke.exceptions.DukeException; import duke.task.Task; +import duke.type.CommandType; import duke.ui.Ui; public class Parser { - private String instruction; - private String taskName; - private String date; + private String input; public Parser(String input) { + this.input = input; + } + + public final Command parse() { + String instruction; + String taskName; + String date; + Command command = new ErrorCommand(); + try { - this.instruction = extractInstruction(input); + instruction = extractInstruction(input); } catch (DukeException e) { - DukeException.EmptyCommandException(); - this.instruction = ""; + System.out.println(e.getMessage()); + return command; + } + + try { + taskName = extractTask(input, instruction); + } catch (DukeException e) { + System.out.println(e.getMessage()); + return command; + } + + try { + date = extractDate(input, instruction); + } catch (DukeException e) { + System.out.println(e.getMessage()); + return command; } - this.taskName = extractTask(input, instruction); - this.date = extractDate(input, instruction); - } - public final Command parse() { - Command command; switch (instruction) { case "bye": command = new ExitCommand(taskName, date); @@ -41,7 +58,6 @@ public final Command parse() { command = new DeleteCommand(taskName, date); break; default: - command = new ErrorCommand(); break; } return command; @@ -57,10 +73,14 @@ public final Command parse() { static final String extractInstruction(String input) throws DukeException { String instruction = input.trim().toLowerCase().split(" ")[0]; - if (instruction.equals("")) { + if (input.replaceAll(" ", "").equals("")) { throw new DukeException(Ui.EMPTYCOMMAND); } + if (CommandType.valueOfType(instruction) == null) { + throw new DukeException(Ui.COMMANDERROR); + } + return instruction; } @@ -71,46 +91,59 @@ static final String extractInstruction(String input) throws DukeException { * @param command user command. * @return the task name if there is one and return empty string if task name empty. */ - static final String extractTask(String input, String command) { + static final String extractTask(String input, String command) throws DukeException { String body = input.replaceAll(command, "").trim(); - if (command.equals("todo") || command.equals("delete")) { - return body; - } else if (command.equals("done")) { - return body.replaceAll("[^0-9]", ""); + if (command.equals("todo")) { + if (body.equals("")) { + throw new DukeException(Ui.EMPTYTASK); + } else { + return body; + } + } else if (command.equals("done") || command.equals("delete")) { + String hasLetter = body.replaceAll("[0-9]", ""); + if (hasLetter.length() > 0) { + throw new DukeException(Ui.KEYINNUMBER); + } else { + return body.replaceAll("[^0-9]", ""); + } + } else if (command.equals("deadline") || command.equals("todo") || command.equals("event")) { + if (body.equals("")) { + throw new DukeException(Ui.EMPTYTASK); + } else { + String task = body.split("/")[0]; + return task; + } } else { - try { - return body.split("/")[0]; - } catch (ArrayIndexOutOfBoundsException e) { - return ""; + if (body.length() > 0) { + throw new DukeException(Ui.COMMANDERROR); } + return ""; } } /** * extract the date of the task to be done. * @param input user input. - * @param command user command. + * @param instruction user command. * @return the task date in String and return empty if there is no date. */ - static final String extractDate(String input, String command) { - String body = input.replaceAll(command, "").trim(); + static final String extractDate(String input, String instruction) throws DukeException { + String body = input.replaceAll(instruction, "").trim(); String[] parts = body.split("/", 2); if (parts.length == 2) { - return DateAndTime.converter(parts[1]); + String date = DateAndTime.converter(parts[1]); + if (date.equals("")) { + throw new DukeException(Ui.WRONGDATEFORMAT); + } + return date; } else { + if (instruction.equals("todo") || instruction.equals("deadline") + || instruction.equals("event")) { + throw new DukeException(Ui.MISSINGDATE); + } return ""; } } - public String getInstruction() { - return this.instruction; - } - public String getTaskName() { - return taskName; - } - - public String getDate() { - return date; - } } diff --git a/src/test/java/duke/utils/ParserTest.java b/src/test/java/duke/utils/ParserTest.java index 10381ea65f..fd6d10176e 100644 --- a/src/test/java/duke/utils/ParserTest.java +++ b/src/test/java/duke/utils/ParserTest.java @@ -25,9 +25,75 @@ void extractInstruction_emptyInstruction_Exception() { } } - + @Test + void extractInstruction_wrongInstruction_Exception() { + try { + String testInput = "ANYHOW"; + String actualInstruction = Parser.extractInstruction(testInput); + fail(); + } catch (DukeException e) { + assertEquals("I DON'T KNOW WHAT U SAYING BRO", e.getMessage()); + } + } + + + @Test + void extractTask() throws DukeException { + String testInput = "deadline project/2019-10-22"; + String actualTask = Parser.extractTask(testInput, "deadline"); + assertEquals("project", actualTask); + } + + @Test + void extractTask_emptyTask_Exception() { + try { + String testInput = "deadline "; + String actualTask = Parser.extractTask(testInput, "deadline"); + fail(); + } catch (DukeException e) { + assertEquals("Walao!NO TASK!", e.getMessage()); + } + } + + @Test + void extractDate() throws DukeException { + String testInput = "deadline project /2019-10-22"; + String actualDate = Parser.extractDate(testInput, "deadline"); + assertEquals("Oct 22 2019", actualDate); + } + + @Test + void extractDate_emptyDate_withoutSlash_Exception() { + try { + String testInput = "deadline project"; + String actualDate = Parser.extractDate(testInput, "deadline"); + fail(); + } catch (DukeException e) { + assertEquals("!!!Fill ur date lah (add date with / in yyyy-mm-dd format)!!!", e.getMessage()); + } + } + @Test + void extractDate_wrongDateFormat_Exception1() { + try { + String testInput = "deadline project/"; + String actualDate = Parser.extractDate(testInput, "deadline"); + fail(); + } catch (DukeException e) { + assertEquals("!!!Err, wrong date format.. (yyyy-mm-dd)!!!", e.getMessage()); + } + } + @Test + void extractDate_wrongDateFormat_Exception2() { + try { + String testInput = "event project/2019"; + String actualDate = Parser.extractDate(testInput, "event"); + fail(); + } catch (DukeException e) { + assertEquals("!!!Err, wrong date format.. (yyyy-mm-dd)!!!", e.getMessage()); + } + } } From bf65adab2a3af0d5e6acadb303694188bd95f173 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Fri, 29 Jan 2021 20:43:02 +0800 Subject: [PATCH 33/62] add DateAndTimeTest TaskStorageTest, TaskTest --- src/main/java/duke/driver/DukeDriver.java | 9 +++--- src/main/java/duke/task/Deadlines.java | 2 +- src/main/java/duke/task/Event.java | 2 +- src/main/java/duke/task/Task.java | 15 ++++++---- src/main/java/duke/task/Todo.java | 2 +- src/main/java/duke/ui/Ui.java | 2 ++ src/main/java/duke/utils/DateAndTime.java | 10 ++++--- src/main/java/duke/utils/Parser.java | 13 ++++----- src/main/java/duke/utils/TaskStorage.java | 28 +++++++++++-------- src/test/data/Duke.txt | 0 src/test/java/duke/task/TaskTest.java | 24 ++++++++++++++++ src/test/java/duke/utils/DateAndTimeTest.java | 25 +++++++++++++++++ src/test/java/duke/utils/ParserTest.java | 8 ++++-- src/test/java/duke/utils/TaskStorageTest.java | 23 +++++++++++++++ 14 files changed, 124 insertions(+), 39 deletions(-) create mode 100644 src/test/data/Duke.txt create mode 100644 src/test/java/duke/task/TaskTest.java create mode 100644 src/test/java/duke/utils/DateAndTimeTest.java create mode 100644 src/test/java/duke/utils/TaskStorageTest.java diff --git a/src/main/java/duke/driver/DukeDriver.java b/src/main/java/duke/driver/DukeDriver.java index 5ca02a20b3..180e3cb112 100644 --- a/src/main/java/duke/driver/DukeDriver.java +++ b/src/main/java/duke/driver/DukeDriver.java @@ -1,10 +1,11 @@ package duke.driver; -import java.util.Scanner; -import duke.ui.Ui; -import duke.utils.TaskStorage; import duke.command.Command; +import duke.ui.Ui; import duke.utils.Parser; +import duke.utils.TaskStorage; + +import java.util.Scanner; /** @@ -21,8 +22,6 @@ public static void executeDuke() { System.out.println(Ui.LOGO); System.out.println(Ui.GREETING); - System.out.println(Ui.LOADFILE); - Ui.SLEEP(); TaskStorage.loadFiles(); diff --git a/src/main/java/duke/task/Deadlines.java b/src/main/java/duke/task/Deadlines.java index e3ac727afd..0227abb7e4 100644 --- a/src/main/java/duke/task/Deadlines.java +++ b/src/main/java/duke/task/Deadlines.java @@ -28,7 +28,7 @@ public int getType() { @Override public String toString() { - return String.format("[D][%s] %d. %s ( %s )", super.isDone(), super.getIndex(), + return String.format("[D][%s] %d. %s ( %s )", super.getDoneStatus(), super.getIndex(), super.getTaskName(), super.getDate()); } } \ No newline at end of file diff --git a/src/main/java/duke/task/Event.java b/src/main/java/duke/task/Event.java index d269b15e8a..f427545ced 100644 --- a/src/main/java/duke/task/Event.java +++ b/src/main/java/duke/task/Event.java @@ -26,7 +26,7 @@ public int getType() { @Override public String toString() { - return String.format("[E][%s] %d. %s ( %s )", super.isDone(), super.getIndex(), + return String.format("[E][%s] %d. %s ( %s )", super.getDoneStatus(), super.getIndex(), super.getTaskName(), super.getDate()); } } \ No newline at end of file diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java index 424e1b74d3..c1e17d767b 100644 --- a/src/main/java/duke/task/Task.java +++ b/src/main/java/duke/task/Task.java @@ -1,9 +1,10 @@ package duke.task; +import duke.exceptions.DukeException; +import duke.ui.Ui; + import java.util.ArrayList; import java.util.List; -import duke.ui.Ui; -import duke.exceptions.DukeException; /** @@ -71,7 +72,7 @@ private static void add(Task t) { * * @param i the index label of the Task. */ - public static final void done(int i) { + public static void done(int i) { try { Task t = taskList.get(i - 1); taskList.get(i - 1).done = "X"; @@ -81,7 +82,7 @@ public static final void done(int i) { } } - public static final void delete(int i) { + public static void delete(int i) { try { Task t = taskList.get(i - 1); taskList.remove(i - 1); @@ -96,6 +97,10 @@ public static final void delete(int i) { } } + public static void clearAllTask() { + taskList.clear(); + } + /** * Get the name of the task. * @@ -120,7 +125,7 @@ public static final List getTaskList() { * * @return a String representation of the isDone status (X for done). */ - public String isDone() { + public String getDoneStatus() { return done; } diff --git a/src/main/java/duke/task/Todo.java b/src/main/java/duke/task/Todo.java index 3a585f8311..67b0c35fc1 100644 --- a/src/main/java/duke/task/Todo.java +++ b/src/main/java/duke/task/Todo.java @@ -28,6 +28,6 @@ public int getType() { @Override public String toString() { - return String.format("[T][%s] %d. %s", super.isDone(), super.getIndex(), super.getTaskName()); + return String.format("[T][%s] %d. %s", super.getDoneStatus(), super.getIndex(), super.getTaskName()); } } \ No newline at end of file diff --git a/src/main/java/duke/ui/Ui.java b/src/main/java/duke/ui/Ui.java index cc1f167d3a..1fe4bd6b4c 100644 --- a/src/main/java/duke/ui/Ui.java +++ b/src/main/java/duke/ui/Ui.java @@ -24,6 +24,7 @@ public class Ui { public static final String TASKERROR = "!!!!!!!!!!Walao, no such task!!!!!!!!!"; public static final String SAVETOFILEERROR = "Huh? Where your file?"; public static final String EMPTYCOMMAND = "!!!Walao, command cannot be empty!!!"; + public static final String SUCCESSFULSAVE = "~~~~~~~~~~~File Saved Successfully!~~~~~~~~~~~~"; public static final String FAREWELL = UPPER + "~~~~~~~~~~~ I Zao Liao. Don't Miss Meeeeeee ~~~~~~~~~~~." + LOWER; @@ -36,6 +37,7 @@ public class Ui { public static final String LOADFILE = "********** Wait ah~ Loading file for you **********\n"; public static final String NOFILE = "********** File also don't have ah, nvm I make one for you **********\n"; public static final String EMPTYFILE = "********** Awwww~ You don't have any history of tasks **********\n"; + public static final String SUCESSFULLOAD = "***********Sir, here is your past history************"; /** * make a chatBox that wrap a given String. diff --git a/src/main/java/duke/utils/DateAndTime.java b/src/main/java/duke/utils/DateAndTime.java index 25b071c525..9eee3ee8bb 100644 --- a/src/main/java/duke/utils/DateAndTime.java +++ b/src/main/java/duke/utils/DateAndTime.java @@ -1,5 +1,7 @@ package duke.utils; +import duke.ui.Ui; + import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; @@ -13,15 +15,15 @@ public static final String converter(String date) { LocalDate d1 = LocalDate.parse(date.trim()); return d1.format(DateTimeFormatter.ofPattern("MMM d yyyy")); } catch (DateTimeParseException e) { - return ""; + return Ui.WRONGDATEFORMAT; } } else { - return ""; + return Ui.WRONGDATEFORMAT; } } - public static final boolean isDashFormat(String date) { + private static final boolean isDashFormat(String date) { String[] dashFormat = date.toLowerCase().split("-", 3); for (String s : dashFormat) { if (!isNumeric(s.trim())) { @@ -31,7 +33,7 @@ public static final boolean isDashFormat(String date) { return true; } - public static boolean isNumeric(String strNum) { + private static boolean isNumeric(String strNum) { if (strNum == null) { return false; } diff --git a/src/main/java/duke/utils/Parser.java b/src/main/java/duke/utils/Parser.java index 9e3713e6b2..d3e175edea 100644 --- a/src/main/java/duke/utils/Parser.java +++ b/src/main/java/duke/utils/Parser.java @@ -2,7 +2,6 @@ import duke.command.*; import duke.exceptions.DukeException; -import duke.task.Task; import duke.type.CommandType; import duke.ui.Ui; @@ -43,7 +42,7 @@ public final Command parse() { switch (instruction) { case "bye": command = new ExitCommand(taskName, date); - TaskStorage.writeToFiles(Task.getTaskList()); + TaskStorage.writeToFiles(); break; case "list": command = new ListCommand(); @@ -70,7 +69,7 @@ public final Command parse() { * @param input the input key in by user. * @return String representation of the command word of the user input. */ - static final String extractInstruction(String input) throws DukeException { + static String extractInstruction(String input) throws DukeException { String instruction = input.trim().toLowerCase().split(" ")[0]; if (input.replaceAll(" ", "").equals("")) { @@ -91,7 +90,7 @@ static final String extractInstruction(String input) throws DukeException { * @param command user command. * @return the task name if there is one and return empty string if task name empty. */ - static final String extractTask(String input, String command) throws DukeException { + static String extractTask(String input, String command) throws DukeException { String body = input.replaceAll(command, "").trim(); if (command.equals("todo")) { if (body.equals("")) { @@ -127,17 +126,17 @@ static final String extractTask(String input, String command) throws DukeExcepti * @param instruction user command. * @return the task date in String and return empty if there is no date. */ - static final String extractDate(String input, String instruction) throws DukeException { + static String extractDate(String input, String instruction) throws DukeException { String body = input.replaceAll(instruction, "").trim(); String[] parts = body.split("/", 2); if (parts.length == 2) { String date = DateAndTime.converter(parts[1]); - if (date.equals("")) { + if (date.equals(Ui.WRONGDATEFORMAT)) { throw new DukeException(Ui.WRONGDATEFORMAT); } return date; } else { - if (instruction.equals("todo") || instruction.equals("deadline") + if (instruction.equals("deadline") || instruction.equals("event")) { throw new DukeException(Ui.MISSINGDATE); } diff --git a/src/main/java/duke/utils/TaskStorage.java b/src/main/java/duke/utils/TaskStorage.java index 3d21001105..5eec70c7cc 100644 --- a/src/main/java/duke/utils/TaskStorage.java +++ b/src/main/java/duke/utils/TaskStorage.java @@ -17,22 +17,26 @@ public class TaskStorage { public static final String FILEPATH = "data/Duke.txt"; public static final String DIRECTORY = "data"; - public static void writeToFiles(List taskList) { + public static String writeToFiles() { + List taskList = Task.getTaskList(); try { FileWriter fw = new FileWriter(FILEPATH); for (Task t : taskList) { - fw.write(t.getType() + "@@" + t.isDone() + String temp = t.getType() + "@@" + t.getDoneStatus() + "@@" + t.getTaskName() + (t.getDate().equals("") - ? "" : ("@@" + t.getDate())) + System.lineSeparator()); + ? "" : ("@@" + t.getDate())) + System.lineSeparator(); + fw.write(temp); } fw.close(); } catch (IOException err) { DukeException.saveToFileError(); } + return Ui.SUCCESSFULSAVE; } - public static void loadFiles() { - + public static String loadFiles() { + String output = Ui.LOADFILE; + System.out.println(output); try { File directory = new File(DIRECTORY); if (!directory.exists()) { @@ -51,35 +55,35 @@ public static void loadFiles() { if (file.length() == 0) { Ui.SLEEP(); System.out.println(Ui.EMPTYFILE); - return; + return Ui.EMPTYFILE; } restoreTask(file); - + Ui.DONELOADING(); } catch (IOException e) { - System.out.println("Testing"); + System.out.println("IO error!: " + e.getMessage()); } + return Ui.SUCESSFULLOAD; } - public static final void restoreTask(File file) throws IOException { + private static final void restoreTask(File file) throws IOException { Scanner sc = new Scanner(file); while (sc.hasNext()) { String[] line = sc.nextLine().split("@@"); if (line.length == 3) { Todo t = new Todo(line[2], line[1]); + } else { int type = Integer.parseInt(line[0]); String done = line[1]; String taskName = line[2]; String date = line[3]; Task t = type == 2 ? new Deadlines(taskName, date, done) : new Event(taskName, date, done); + } } - sc.close(); - Ui.DONELOADING(); - } } diff --git a/src/test/data/Duke.txt b/src/test/data/Duke.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/test/java/duke/task/TaskTest.java b/src/test/java/duke/task/TaskTest.java new file mode 100644 index 0000000000..28f80db1bb --- /dev/null +++ b/src/test/java/duke/task/TaskTest.java @@ -0,0 +1,24 @@ +package duke.task; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class TaskTest { + + @Test + void done() { + Task.clearAllTask(); + Todo task = new Todo("Scratch back", " "); + Task.done(1); + assertEquals("X", task.getDoneStatus()); + } + + @Test + void delete() { + Task.clearAllTask(); + Todo task = new Todo("Scratch back", " "); + Task.delete(1); + assertEquals(0, Task.getTaskList().size()); + } +} \ No newline at end of file diff --git a/src/test/java/duke/utils/DateAndTimeTest.java b/src/test/java/duke/utils/DateAndTimeTest.java new file mode 100644 index 0000000000..2938f8d6cb --- /dev/null +++ b/src/test/java/duke/utils/DateAndTimeTest.java @@ -0,0 +1,25 @@ +package duke.utils; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DateAndTimeTest { + + @Test + void converterTest() { + String date = "2019-10-22"; + String acutalOutput = DateAndTime.converter(date); + String expectedOutput = "Oct 22 2019"; + assertEquals(expectedOutput, acutalOutput); + } + + @Test + void converterTest_WrongDateFormat() { + String date = "2019"; + String acutalOutput = DateAndTime.converter(date); + String expectedOutput = "!!!Err, wrong date format.. (yyyy-mm-dd)!!!"; + assertEquals(expectedOutput, acutalOutput); + } + +} diff --git a/src/test/java/duke/utils/ParserTest.java b/src/test/java/duke/utils/ParserTest.java index fd6d10176e..c75ce385be 100644 --- a/src/test/java/duke/utils/ParserTest.java +++ b/src/test/java/duke/utils/ParserTest.java @@ -7,8 +7,10 @@ import static org.junit.jupiter.api.Assertions.fail; public class ParserTest { + + @Test - void extractInstruction() throws DukeException { + void extractInstructionTest() throws DukeException { String testInput = "todo swimming"; String actualInstruction = Parser.extractInstruction(testInput); assertEquals("todo", actualInstruction); @@ -38,7 +40,7 @@ void extractInstruction_wrongInstruction_Exception() { @Test - void extractTask() throws DukeException { + void extractTaskTest() throws DukeException { String testInput = "deadline project/2019-10-22"; String actualTask = Parser.extractTask(testInput, "deadline"); assertEquals("project", actualTask); @@ -56,7 +58,7 @@ void extractTask_emptyTask_Exception() { } @Test - void extractDate() throws DukeException { + void extractDateTest() throws DukeException { String testInput = "deadline project /2019-10-22"; String actualDate = Parser.extractDate(testInput, "deadline"); assertEquals("Oct 22 2019", actualDate); diff --git a/src/test/java/duke/utils/TaskStorageTest.java b/src/test/java/duke/utils/TaskStorageTest.java new file mode 100644 index 0000000000..46f1153e47 --- /dev/null +++ b/src/test/java/duke/utils/TaskStorageTest.java @@ -0,0 +1,23 @@ +package duke.utils; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class TaskStorageTest { + + @Test + void writeToFilesTest() { + String actualOutput = TaskStorage.writeToFiles(); + String expectedOutput = "~~~~~~~~~~~File Saved Successfully!~~~~~~~~~~~~"; + assertEquals(actualOutput, expectedOutput); + } + + @Test + void loadFilesTest() { + String actualOutput = TaskStorage.loadFiles(); + String expectedOutput = "********** Awwww~ You don't have any history of tasks **********\n";; + assertEquals(actualOutput, expectedOutput); + } + +} From 5343518f6abf8e018dbd65f3cd8879d73ebf97f1 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Sat, 30 Jan 2021 21:48:15 +0800 Subject: [PATCH 34/62] Completed JavaDoc --- src/main/java/META-INF/MANIFEST.MF | 3 ++ src/main/java/duke/command/AddCommand.java | 4 +- src/main/java/duke/command/Command.java | 18 ++++++-- src/main/java/duke/command/DeleteCommand.java | 7 ++- src/main/java/duke/command/DoneCommand.java | 4 +- src/main/java/duke/command/ErrorCommand.java | 3 ++ src/main/java/duke/command/ExitCommand.java | 3 ++ src/main/java/duke/command/ListCommand.java | 4 ++ .../java/duke/exceptions/DukeException.java | 45 +------------------ src/main/java/duke/task/Task.java | 6 ++- src/main/java/duke/type/CommandType.java | 16 ++++++- src/main/java/duke/utils/DateAndTime.java | 9 ++++ src/main/java/duke/utils/Parser.java | 8 ++++ src/main/java/duke/utils/TaskStorage.java | 13 ++++++ 14 files changed, 90 insertions(+), 53 deletions(-) create mode 100644 src/main/java/META-INF/MANIFEST.MF diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..6e864153e8 --- /dev/null +++ b/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: duke.Duke + diff --git a/src/main/java/duke/command/AddCommand.java b/src/main/java/duke/command/AddCommand.java index d06af73794..3457f99ea1 100644 --- a/src/main/java/duke/command/AddCommand.java +++ b/src/main/java/duke/command/AddCommand.java @@ -5,6 +5,9 @@ import duke.task.Todo; import duke.ui.Ui; +/** + * Sub-class of Command that represents and execute the todo, deadline and event instructions of user. + */ public class AddCommand extends Command{ public AddCommand(String instruction, String task, String date) { super(instruction, task, date, command -> { @@ -21,7 +24,6 @@ public AddCommand(String instruction, String task, String date) { /** * handle todo command and create a todo task if task is not empty. - * * @param task name of the user task. */ private static final Boolean handleToDo(String task) { diff --git a/src/main/java/duke/command/Command.java b/src/main/java/duke/command/Command.java index 4c99821ec4..a852eb1973 100644 --- a/src/main/java/duke/command/Command.java +++ b/src/main/java/duke/command/Command.java @@ -2,12 +2,23 @@ import java.util.function.Function; +/** + * This class encapsulates the user instruction,task and date and execute the instruction. + * + */ public abstract class Command { private final String instruction; private final String task; private final String date; private final Function func; + /** + * Create a command with user instruction, task, date and a function to execute the instruction. + * @param instruction user instruction. + * @param task user task. + * @param date date of the task. + * @param func the function takes a command to execute the task and returns a boolean whether to end the program. + */ public Command(String instruction, String task, String date, Function func) { this.instruction = instruction; this.task = task; @@ -15,13 +26,14 @@ public Command(String instruction, String task, String date, Function { @@ -15,8 +18,8 @@ public DeleteCommand(String task, String date) { /** * handle delete command key in by user by removing the task from the list if there is any. - * - * @param task name of the user task. + * @param task user task in String. + * @param date date of the task. */ private static final Boolean handleDelete(String task, String date) { if (task.length() > 0 && date.equals("")) { diff --git a/src/main/java/duke/command/DoneCommand.java b/src/main/java/duke/command/DoneCommand.java index ad72a6d116..e1a6c5899a 100644 --- a/src/main/java/duke/command/DoneCommand.java +++ b/src/main/java/duke/command/DoneCommand.java @@ -3,6 +3,9 @@ import duke.exceptions.DukeException; import duke.task.Task; +/** + * Sub-class of Command that represents and execute the done instruction of user. + */ public class DoneCommand extends Command{ public DoneCommand(String task, String date) { super("done", task, date, command -> { @@ -13,7 +16,6 @@ public DoneCommand(String task, String date) { /** * handle done command by marking the task as done. - * * @param task name of the user task. */ private static final Boolean handleDone(String task) { diff --git a/src/main/java/duke/command/ErrorCommand.java b/src/main/java/duke/command/ErrorCommand.java index 32aa672203..585392f4c7 100644 --- a/src/main/java/duke/command/ErrorCommand.java +++ b/src/main/java/duke/command/ErrorCommand.java @@ -1,5 +1,8 @@ package duke.command; +/** + * Sub-class of Command to represents any error in the instruction of user. + */ public class ErrorCommand extends Command{ public ErrorCommand() { super("", "", "", command -> { diff --git a/src/main/java/duke/command/ExitCommand.java b/src/main/java/duke/command/ExitCommand.java index 0b9d674337..b1bc925b1e 100644 --- a/src/main/java/duke/command/ExitCommand.java +++ b/src/main/java/duke/command/ExitCommand.java @@ -1,5 +1,8 @@ package duke.command; +/** + * Sub-class of command that represents and execute the "bye" instruction of user. + */ public class ExitCommand extends Command { public ExitCommand(String task, String date) { super("bye", task, date, command -> { diff --git a/src/main/java/duke/command/ListCommand.java b/src/main/java/duke/command/ListCommand.java index 3ce7467fda..b7af1d1b9c 100644 --- a/src/main/java/duke/command/ListCommand.java +++ b/src/main/java/duke/command/ListCommand.java @@ -1,6 +1,10 @@ package duke.command; import duke.ui.Ui; + +/** + * Sub-class of Command that represents and execute the "list" instruction of user. + */ public class ListCommand extends Command{ public ListCommand() { super("", "", "", command -> { diff --git a/src/main/java/duke/exceptions/DukeException.java b/src/main/java/duke/exceptions/DukeException.java index d3e0a5e782..a0898b82a9 100644 --- a/src/main/java/duke/exceptions/DukeException.java +++ b/src/main/java/duke/exceptions/DukeException.java @@ -11,54 +11,11 @@ public DukeException(String errorMessage) { super(errorMessage); } - public static final void DATEFORMATEXCEPTION() { - System.out.println(Ui.WRONGDATEFORMAT); - } + public static final void NumberFormatException() { System.out.println(Ui.KEYINNUMBER); } - public static final void EmptyCommandException() { - System.out.println(Ui.EMPTYCOMMAND); - } - - /** - * display the error message for empty body error. - * - */ - public static final void emptyTaskException() { - System.out.println(Ui.EMPTYTASK); - } - - - /** - * display the error message for too many argument error. - * - */ - public static final void argumentErrorException() { - System.out.println(Ui.TOOMANYARGUMENTS); - } - - /** - * display the error message for missing argument error. - * - */ - public static final void missingDateErrorException() { - System.out.println(Ui.MISSINGDATE); - } - - /** - * display the error message for command error. - * - */ - public static final void commandErrorException() { - System.out.println(Ui.COMMANDERROR); - } - - /** - * display the error message for missing task error. - * - */ public static final void taskErrorException() { System.out.println(Ui.TASKERROR); } public static final void saveToFileError() { System.out.println(Ui.SAVETOFILEERROR);} diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java index c1e17d767b..c400386294 100644 --- a/src/main/java/duke/task/Task.java +++ b/src/main/java/duke/task/Task.java @@ -17,11 +17,11 @@ public class Task { private int index; private String done; private String date; + /** * Construct a task object with taskname attached and its index label in the taskList. * @param taskName name of the task. */ - Task(String taskName) { this.taskName = taskName; this.index = capacity + 1; @@ -82,6 +82,10 @@ public static void done(int i) { } } + /** + * Delete a task from the task list with the given index label. + * @param i the index label of the task. + */ public static void delete(int i) { try { Task t = taskList.get(i - 1); diff --git a/src/main/java/duke/type/CommandType.java b/src/main/java/duke/type/CommandType.java index 7873598f94..c79e2fb263 100644 --- a/src/main/java/duke/type/CommandType.java +++ b/src/main/java/duke/type/CommandType.java @@ -1,5 +1,9 @@ package duke.type; +/** + * Encapsulate a CommandType enum class that represents the type of command. + * The class includes seven types: todo, deadline, event, bye, list, delete, done and find. + */ public enum CommandType { TODO("todo"), DEADLINE("deadline"), @@ -11,11 +15,21 @@ public enum CommandType { private String type; + /** + * Construct a CommandType object with a String representation of the type. + * @param type + */ CommandType(String type) { this.type = type; } - + /** + * Gets the CommandType object from a string representation of the type. + * Returns null if no such object exists. + * + * @param type a string representing the type. + * @return an CommandType object of the specified type and null if no such object exists. + */ public static CommandType valueOfType(String type) { for (CommandType t : values()) { if (t.type.equals(type)) { diff --git a/src/main/java/duke/utils/DateAndTime.java b/src/main/java/duke/utils/DateAndTime.java index 9eee3ee8bb..120dbb1248 100644 --- a/src/main/java/duke/utils/DateAndTime.java +++ b/src/main/java/duke/utils/DateAndTime.java @@ -6,8 +6,17 @@ import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +/** + * This class process the date key in by user and convert it to the right format to be use. + */ public class DateAndTime { + /** + * This method convert a yyyy-mm-dd format of date to MMM d yyyy format. + * + * @param date the String representation of date. + * @return MMM d yyyy format of date and return error message if the given date is in wrong format. + */ public static final String converter(String date) { if (isDashFormat(date)) { diff --git a/src/main/java/duke/utils/Parser.java b/src/main/java/duke/utils/Parser.java index d3e175edea..08aa23171f 100644 --- a/src/main/java/duke/utils/Parser.java +++ b/src/main/java/duke/utils/Parser.java @@ -5,6 +5,9 @@ import duke.type.CommandType; import duke.ui.Ui; +/** + * This class extract and process the user input and produce the right command to be executed after parsing. + */ public class Parser { private String input; @@ -12,6 +15,11 @@ public Parser(String input) { this.input = input; } + /** + * This method process all the user input and create respective command to be executed. + * + * @return the respective command to be executed. + */ public final Command parse() { String instruction; String taskName; diff --git a/src/main/java/duke/utils/TaskStorage.java b/src/main/java/duke/utils/TaskStorage.java index 5eec70c7cc..44b99ce3c8 100644 --- a/src/main/java/duke/utils/TaskStorage.java +++ b/src/main/java/duke/utils/TaskStorage.java @@ -12,11 +12,19 @@ import java.util.List; import java.util.Scanner; +/** + * This class handle the saving and loading of the taskList to/from a specific FilePath. + */ public class TaskStorage { public static final String FILEPATH = "data/Duke.txt"; public static final String DIRECTORY = "data"; + /** + * This method write the content of a taskList to data/Duke.txt. + * + * @return A string display of a successful save. + */ public static String writeToFiles() { List taskList = Task.getTaskList(); try { @@ -34,6 +42,11 @@ public static String writeToFiles() { return Ui.SUCCESSFULSAVE; } + /** + * This method load the file from data/Duke.txt and display in a list format when the program starts. + * + * @return the String display of a successful load. + */ public static String loadFiles() { String output = Ui.LOADFILE; System.out.println(output); From 2b27c257c827564df8433d79bf8a5c1276e90a9f Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Sat, 30 Jan 2021 21:51:54 +0800 Subject: [PATCH 35/62] Fix according to java coding standard --- src/main/java/META-INF/MANIFEST.MF | 3 + src/main/java/duke/command/AddCommand.java | 27 +++------ src/main/java/duke/command/Command.java | 6 +- src/main/java/duke/command/DeleteCommand.java | 17 ++---- src/main/java/duke/command/DoneCommand.java | 18 +++--- src/main/java/duke/command/ErrorCommand.java | 5 +- src/main/java/duke/command/ExitCommand.java | 21 ++----- src/main/java/duke/command/ListCommand.java | 2 + src/main/java/duke/driver/DukeDriver.java | 5 +- .../java/duke/exceptions/DukeException.java | 51 ++--------------- src/main/java/duke/task/Task.java | 32 ++++++----- src/main/java/duke/type/CommandType.java | 18 +++++- src/main/java/duke/ui/Ui.java | 55 ++++++++----------- src/main/java/duke/utils/DateAndTime.java | 12 ++-- src/main/java/duke/utils/Parser.java | 40 ++++++++------ src/main/java/duke/utils/TaskStorage.java | 18 +++--- src/test/java/duke/utils/DateAndTimeTest.java | 8 +-- src/test/java/duke/utils/ParserTest.java | 12 ++-- src/test/java/duke/utils/TaskStorageTest.java | 2 +- 19 files changed, 149 insertions(+), 203 deletions(-) create mode 100644 src/main/java/META-INF/MANIFEST.MF diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..6e864153e8 --- /dev/null +++ b/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: duke.Duke + diff --git a/src/main/java/duke/command/AddCommand.java b/src/main/java/duke/command/AddCommand.java index d06af73794..60ebd576ad 100644 --- a/src/main/java/duke/command/AddCommand.java +++ b/src/main/java/duke/command/AddCommand.java @@ -5,6 +5,7 @@ import duke.task.Todo; import duke.ui.Ui; + public class AddCommand extends Command{ public AddCommand(String instruction, String task, String date) { super(instruction, task, date, command -> { @@ -19,12 +20,8 @@ public AddCommand(String instruction, String task, String date) { } - /** - * handle todo command and create a todo task if task is not empty. - * - * @param task name of the user task. - */ - private static final Boolean handleToDo(String task) { + + private static Boolean handleToDo(String task) { if (!task.equals("")) { Todo todo = new Todo(task); System.out.println(Ui.biggerBox(todo)); @@ -33,13 +30,8 @@ private static final Boolean handleToDo(String task) { } - /** - * handle deadline command by creating deadline task if task and date are not empty. - * - * @param task name of the user task. - * @param date date of the task to be done. - */ - private static final Boolean handleDeadline(String task, String date) { + + private static Boolean handleDeadline(String task, String date) { if (!date.equals("")) { Deadlines deadlines = new Deadlines(task, date); @@ -50,13 +42,8 @@ private static final Boolean handleDeadline(String task, String date) { } - /** - * handle event command by creating event if task and date are not empty. - * - * @param task name of the user task. - * @param date date of the task to be done. - */ - private static final Boolean handleEvent(String task, String date) { + + private static Boolean handleEvent(String task, String date) { if (!task.equals("") && !date.equals("")) { Event event = new Event(task, date); System.out.println(Ui.biggerBox(event)); diff --git a/src/main/java/duke/command/Command.java b/src/main/java/duke/command/Command.java index 4c99821ec4..af7087f87a 100644 --- a/src/main/java/duke/command/Command.java +++ b/src/main/java/duke/command/Command.java @@ -2,12 +2,14 @@ import java.util.function.Function; + public abstract class Command { private final String instruction; private final String task; private final String date; private final Function func; + public Command(String instruction, String task, String date, Function func) { this.instruction = instruction; this.task = task; @@ -15,13 +17,11 @@ public Command(String instruction, String task, String date, Function { - return handleDelete(task, date); - }); +public class DeleteCommand extends Command { + + public DeleteCommand(String task, String date) { + super("delete", task, date, command -> handleDelete(task, date)); } - /** - * handle delete command key in by user by removing the task from the list if there is any. - * - * @param task name of the user task. - */ - private static final Boolean handleDelete(String task, String date) { + + private static Boolean handleDelete(String task, String date) { if (task.length() > 0 && date.equals("")) { try { int num = Integer.parseInt(task); diff --git a/src/main/java/duke/command/DoneCommand.java b/src/main/java/duke/command/DoneCommand.java index ad72a6d116..bad56e40a8 100644 --- a/src/main/java/duke/command/DoneCommand.java +++ b/src/main/java/duke/command/DoneCommand.java @@ -3,20 +3,16 @@ import duke.exceptions.DukeException; import duke.task.Task; -public class DoneCommand extends Command{ - public DoneCommand(String task, String date) { - super("done", task, date, command -> { - return handleDone(task); - }); +public class DoneCommand extends Command { + + + public DoneCommand(String task, String date) { + super("done", task, date, command -> handleDone(task)); } - /** - * handle done command by marking the task as done. - * - * @param task name of the user task. - */ - private static final Boolean handleDone(String task) { + + private static Boolean handleDone(String task) { if (task.length() > 0) { try { int num = Integer.parseInt(task); diff --git a/src/main/java/duke/command/ErrorCommand.java b/src/main/java/duke/command/ErrorCommand.java index 32aa672203..3d17a05dca 100644 --- a/src/main/java/duke/command/ErrorCommand.java +++ b/src/main/java/duke/command/ErrorCommand.java @@ -1,9 +1,8 @@ package duke.command; + public class ErrorCommand extends Command{ public ErrorCommand() { - super("", "", "", command -> { - return false; - }); + super("", "", "", command -> false); } } diff --git a/src/main/java/duke/command/ExitCommand.java b/src/main/java/duke/command/ExitCommand.java index 0b9d674337..82f0b33a30 100644 --- a/src/main/java/duke/command/ExitCommand.java +++ b/src/main/java/duke/command/ExitCommand.java @@ -1,25 +1,14 @@ package duke.command; + public class ExitCommand extends Command { public ExitCommand(String task, String date) { - super("bye", task, date, command -> { - return handleBye(task, date); - - }); + super("bye", task, date, command -> handleBye(task, date)); } - /** - * handle bye command by returning true or false. - * - * @param task name of the user task. - * @param date date of the task that user key in. - * @return a boolean of whether to exit the program. - */ - private static final boolean handleBye(String task, String date) { - if (task.equals("") && date.equals("")) { - return true; - } - return false; + + private static boolean handleBye(String task, String date) { + return task.equals("") && date.equals(""); } } diff --git a/src/main/java/duke/command/ListCommand.java b/src/main/java/duke/command/ListCommand.java index 3ce7467fda..f195763d92 100644 --- a/src/main/java/duke/command/ListCommand.java +++ b/src/main/java/duke/command/ListCommand.java @@ -1,6 +1,8 @@ package duke.command; import duke.ui.Ui; + + public class ListCommand extends Command{ public ListCommand() { super("", "", "", command -> { diff --git a/src/main/java/duke/driver/DukeDriver.java b/src/main/java/duke/driver/DukeDriver.java index 180e3cb112..c45b2e0161 100644 --- a/src/main/java/duke/driver/DukeDriver.java +++ b/src/main/java/duke/driver/DukeDriver.java @@ -43,10 +43,9 @@ public static void executeDuke() { * @param message String representation of the message key in by user. * @return a boolean to whether to exit the program. */ - private static final boolean inputHandler(String message) { + private static boolean inputHandler(String message) { Command command = new Parser(message).parse(); - Boolean end = command.execute(); - return end; + return command.execute(); } diff --git a/src/main/java/duke/exceptions/DukeException.java b/src/main/java/duke/exceptions/DukeException.java index d3e0a5e782..6c74111be6 100644 --- a/src/main/java/duke/exceptions/DukeException.java +++ b/src/main/java/duke/exceptions/DukeException.java @@ -11,55 +11,12 @@ public DukeException(String errorMessage) { super(errorMessage); } - public static final void DATEFORMATEXCEPTION() { - System.out.println(Ui.WRONGDATEFORMAT); - } - public static final void NumberFormatException() { - System.out.println(Ui.KEYINNUMBER); - } - - public static final void EmptyCommandException() { - System.out.println(Ui.EMPTYCOMMAND); - } - - /** - * display the error message for empty body error. - * - */ - public static final void emptyTaskException() { - System.out.println(Ui.EMPTYTASK); - } - - - /** - * display the error message for too many argument error. - * - */ - public static final void argumentErrorException() { - System.out.println(Ui.TOOMANYARGUMENTS); - } - - /** - * display the error message for missing argument error. - * - */ - public static final void missingDateErrorException() { - System.out.println(Ui.MISSINGDATE); - } - /** - * display the error message for command error. - * - */ - public static final void commandErrorException() { - System.out.println(Ui.COMMANDERROR); + public static void NumberFormatException() { + System.out.println(Ui.KEY_IN_NUMBER); } - /** - * display the error message for missing task error. - * - */ - public static final void taskErrorException() { System.out.println(Ui.TASKERROR); } + public static void taskErrorException() { System.out.println(Ui.TASK_ERROR); } - public static final void saveToFileError() { System.out.println(Ui.SAVETOFILEERROR);} + public static void saveToFileError() { System.out.println(Ui.SAVE_TO_FILE_ERROR);} } diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java index c1e17d767b..5c40e563d0 100644 --- a/src/main/java/duke/task/Task.java +++ b/src/main/java/duke/task/Task.java @@ -12,20 +12,20 @@ */ public class Task { private static List taskList = new ArrayList<>(); - private String taskName; + private final String taskName; private static int capacity = 0; private int index; - private String done; - private String date; + private String isDone; + private final String date; + /** - * Construct a task object with taskname attached and its index label in the taskList. + * Construct a task object with taskName attached and its index label in the taskList. * @param taskName name of the task. */ - Task(String taskName) { this.taskName = taskName; this.index = capacity + 1; - this.done = " "; + this.isDone = " "; this.date = ""; capacity++; add(this); @@ -34,7 +34,7 @@ public class Task { Task(String taskName, String done, boolean check) { this.taskName = taskName; this.index = capacity + 1; - this.done = done; + this.isDone = done; this.date = ""; capacity++; add(this); @@ -43,7 +43,7 @@ public class Task { Task(String taskName, String date) { this.taskName = taskName; this.index = capacity + 1; - this.done = " "; + this.isDone = " "; this.date = date; capacity++; add(this); @@ -52,7 +52,7 @@ public class Task { Task(String taskName, String date, String done) { this.taskName = taskName; this.index = capacity + 1; - this.done = done; + this.isDone = done; this.date = date; capacity++; add(this); @@ -75,13 +75,17 @@ private static void add(Task t) { public static void done(int i) { try { Task t = taskList.get(i - 1); - taskList.get(i - 1).done = "X"; + taskList.get(i - 1).isDone = "X"; Ui.doneTask(t); } catch (IndexOutOfBoundsException e) { DukeException.taskErrorException(); } } + /** + * Delete a task from the task list with the given index label. + * @param i the index label of the task. + */ public static void delete(int i) { try { Task t = taskList.get(i - 1); @@ -116,7 +120,7 @@ public String getTaskName() { * @return the List of all tasks stored. */ - public static final List getTaskList() { + public static List getTaskList() { return Task.taskList; } @@ -126,7 +130,7 @@ public static final List getTaskList() { * @return a String representation of the isDone status (X for done). */ public String getDoneStatus() { - return done; + return isDone; } /** @@ -151,12 +155,12 @@ public String getDate() { * * @return the int representation of the capacity of the taskList. */ - public static final int getCapacity() { + public static int getCapacity() { return Task.capacity; } @Override public String toString() { - return String.format("[%s] %d. %s", done, index, taskName); + return String.format("[%s] %d. %s", isDone, index, taskName); } } \ No newline at end of file diff --git a/src/main/java/duke/type/CommandType.java b/src/main/java/duke/type/CommandType.java index 7873598f94..2f22eb3c4e 100644 --- a/src/main/java/duke/type/CommandType.java +++ b/src/main/java/duke/type/CommandType.java @@ -1,5 +1,9 @@ package duke.type; +/** + * Encapsulate a CommandType enum class that represents the type of command. + * The class includes seven types: todo, deadline, event, bye, list, delete, done and find. + */ public enum CommandType { TODO("todo"), DEADLINE("deadline"), @@ -9,13 +13,23 @@ public enum CommandType { LIST("list"), DELETE("delete"); - private String type; + private final String type; + /** + * Construct a CommandType object with a String representation of the type. + * @param type String representation of the type. + */ CommandType(String type) { this.type = type; } - + /** + * Gets the CommandType object from a string representation of the type. + * Returns null if no such object exists. + * + * @param type a string representing the type. + * @return an CommandType object of the specified type and null if no such object exists. + */ public static CommandType valueOfType(String type) { for (CommandType t : values()) { if (t.type.equals(type)) { diff --git a/src/main/java/duke/ui/Ui.java b/src/main/java/duke/ui/Ui.java index 1fe4bd6b4c..92762879ff 100644 --- a/src/main/java/duke/ui/Ui.java +++ b/src/main/java/duke/ui/Ui.java @@ -15,16 +15,16 @@ public class Ui { + "| | | | | | | |/ / _ \\\n" + "| |_| | |_| | < __/\n" + "|____/ \\__,_|_|\\_\\___|\n"; - public static final String WRONGDATEFORMAT = "!!!Err, wrong date format.. (yyyy-mm-dd)!!!"; - public static final String KEYINNUMBER = "!!!!!!!PLease Lah! Key in number!!!!!!!!"; - public static final String EMPTYTASK = "!!!!!!!!!Walao!NO TASK!!!!!!!!!!"; - public static final String TOOMANYARGUMENTS = "You put so many/few ARGUMENTS for what"; - public static final String MISSINGDATE = "!!!Fill ur date lah (add date with / in yyyy-mm-dd format)!!!"; - public static final String COMMANDERROR = "!!!!!!!I DON'T KNOW WHAT U SAYING BRO!!!!!!!"; - public static final String TASKERROR = "!!!!!!!!!!Walao, no such task!!!!!!!!!"; - public static final String SAVETOFILEERROR = "Huh? Where your file?"; - public static final String EMPTYCOMMAND = "!!!Walao, command cannot be empty!!!"; - public static final String SUCCESSFULSAVE = "~~~~~~~~~~~File Saved Successfully!~~~~~~~~~~~~"; + + public static final String WRONG_DATE_FORMAT = "!!!Err, wrong date format.. (yyyy-mm-dd)!!!"; + public static final String KEY_IN_NUMBER = "!!!!!!!PLease Lah! Key in number!!!!!!!!"; + public static final String EMPTY_TASK = "!!!!!!!!!Walao!NO TASK!!!!!!!!!!"; + public static final String MISSING_DATE = "!!!Fill ur date lah (add date with / in yyyy-mm-dd format)!!!"; + public static final String COMMAND_ERROR = "!!!!!!!I DON'T KNOW WHAT U SAYING BRO!!!!!!!"; + public static final String TASK_ERROR = "!!!!!!!!!!Walao, no such task!!!!!!!!!"; + public static final String SAVE_TO_FILE_ERROR = "Huh? Where your file?"; + public static final String EMPTY_COMMAND = "!!!Walao, command cannot be empty!!!"; + public static final String SUCCESSFUL_SAVE = "~~~~~~~~~~~File Saved Successfully!~~~~~~~~~~~~"; public static final String FAREWELL = UPPER + "~~~~~~~~~~~ I Zao Liao. Don't Miss Meeeeeee ~~~~~~~~~~~." + LOWER; @@ -32,31 +32,20 @@ public class Ui { + "****************** Awww, need help ah? ******************" + LOWER; - public static final String NODIRECTORY = "********** Cannot find your directory eh, " + public static final String NO_DIRECTORY = "********** Cannot find your directory eh, " + "first time ah? Create one for you **********\n" ; - public static final String LOADFILE = "********** Wait ah~ Loading file for you **********\n"; - public static final String NOFILE = "********** File also don't have ah, nvm I make one for you **********\n"; - public static final String EMPTYFILE = "********** Awwww~ You don't have any history of tasks **********\n"; - public static final String SUCESSFULLOAD = "***********Sir, here is your past history************"; + public static final String LOAD_FILE = "********** Wait ah~ Loading file for you **********\n"; + public static final String NO_FILE = "********** File also don't have ah, nvm I make one for you **********\n"; + public static final String EMPTY_FILE = "********** Awwww~ You don't have any history of tasks **********\n"; + public static final String SUCESSFUL_LOAD = "***********Sir, here is your past history************"; + - /** - * make a chatBox that wrap a given String. - * @param s the String to be wrapped. - * @return a String with a chatBox wrapped. - */ - public static final String chatBox(String s) { - if (s.length() > 50) { - return "Walao! Your command too long lah!"; - } else { - return UPPER + " ".repeat(36 - s.length() / 2) + s + LOWER; - } - } - public static final void doneTask(Task t) { + public static void doneTask(Task t) { System.out.println(Ui.UPPER + "Wah~ You done the task: " + " " + t.toString() + Ui.LOWER); } - public static final void deleteTask(Task t) { + public static void deleteTask(Task t) { System.out.println(Ui.UPPER + "Awww~ You've deleted the task: " + " " + t.toString() + Ui.LOWER); } @@ -66,7 +55,7 @@ public static final void deleteTask(Task t) { * @param t task to be wrapped. * @return the String representation of the task name wrapped in a chatBox. */ - public static final String biggerBox(Task t) { + public static String biggerBox(Task t) { return Ui.UPPER + "Added liao: " + t.toString() + Ui.LINEBREAK + "You have " + Task.getCapacity() + " tasks in the list!" @@ -77,7 +66,7 @@ public static final String biggerBox(Task t) { * Display all the current task and status store in the tasklist. * */ - public static final void LISTING() { + public static void LISTING() { System.out.println(UPPER); for (Task task : Task.getTaskList()) { if (task == null) break; @@ -86,7 +75,7 @@ public static final void LISTING() { System.out.println(LOWER); } - public static final void DONELOADING() { + public static void DONELOADING() { System.out.println(UPPER); for (Task task : Task.getTaskList()) { if (task == null) break; @@ -96,7 +85,7 @@ public static final void DONELOADING() { System.out.println(LOWER); } - public static final void SLEEP() { + public static void SLEEP() { try { Thread.sleep(1500); } catch (InterruptedException e) { diff --git a/src/main/java/duke/utils/DateAndTime.java b/src/main/java/duke/utils/DateAndTime.java index 9eee3ee8bb..bf9963adb2 100644 --- a/src/main/java/duke/utils/DateAndTime.java +++ b/src/main/java/duke/utils/DateAndTime.java @@ -6,24 +6,26 @@ import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; + public class DateAndTime { - public static final String converter(String date) { + + public static String converter(String date) { if (isDashFormat(date)) { try { LocalDate d1 = LocalDate.parse(date.trim()); return d1.format(DateTimeFormatter.ofPattern("MMM d yyyy")); } catch (DateTimeParseException e) { - return Ui.WRONGDATEFORMAT; + return Ui.WRONG_DATE_FORMAT; } } else { - return Ui.WRONGDATEFORMAT; + return Ui.WRONG_DATE_FORMAT; } } - private static final boolean isDashFormat(String date) { + private static boolean isDashFormat(String date) { String[] dashFormat = date.toLowerCase().split("-", 3); for (String s : dashFormat) { if (!isNumeric(s.trim())) { @@ -38,7 +40,7 @@ private static boolean isNumeric(String strNum) { return false; } try { - double d = Double.parseDouble(strNum); + Double.parseDouble(strNum); } catch (NumberFormatException nfe) { return false; } diff --git a/src/main/java/duke/utils/Parser.java b/src/main/java/duke/utils/Parser.java index d3e175edea..af0e9a6513 100644 --- a/src/main/java/duke/utils/Parser.java +++ b/src/main/java/duke/utils/Parser.java @@ -5,13 +5,21 @@ import duke.type.CommandType; import duke.ui.Ui; +/** + * This class extract and process the user input and produce the right command to be executed after parsing. + */ public class Parser { - private String input; + private final String input; public Parser(String input) { this.input = input; } + /** + * This method process all the user input and create respective command to be executed. + * + * @return the respective command to be executed. + */ public final Command parse() { String instruction; String taskName; @@ -73,11 +81,11 @@ static String extractInstruction(String input) throws DukeException { String instruction = input.trim().toLowerCase().split(" ")[0]; if (input.replaceAll(" ", "").equals("")) { - throw new DukeException(Ui.EMPTYCOMMAND); + throw new DukeException(Ui.EMPTY_COMMAND); } if (CommandType.valueOfType(instruction) == null) { - throw new DukeException(Ui.COMMANDERROR); + throw new DukeException(Ui.COMMAND_ERROR); } return instruction; @@ -92,29 +100,29 @@ static String extractInstruction(String input) throws DukeException { */ static String extractTask(String input, String command) throws DukeException { String body = input.replaceAll(command, "").trim(); - if (command.equals("todo")) { + switch (command) { + case "todo": if (body.equals("")) { - throw new DukeException(Ui.EMPTYTASK); + throw new DukeException(Ui.EMPTY_TASK); } else { return body; } - } else if (command.equals("done") || command.equals("delete")) { + case "done": case "delete": String hasLetter = body.replaceAll("[0-9]", ""); if (hasLetter.length() > 0) { - throw new DukeException(Ui.KEYINNUMBER); + throw new DukeException(Ui.KEY_IN_NUMBER); } else { return body.replaceAll("[^0-9]", ""); } - } else if (command.equals("deadline") || command.equals("todo") || command.equals("event")) { + case "deadline": case "event": if (body.equals("")) { - throw new DukeException(Ui.EMPTYTASK); + throw new DukeException(Ui.EMPTY_TASK); } else { - String task = body.split("/")[0]; - return task; + return body.split("/")[0]; } - } else { + default: if (body.length() > 0) { - throw new DukeException(Ui.COMMANDERROR); + throw new DukeException(Ui.COMMAND_ERROR); } return ""; } @@ -131,14 +139,14 @@ static String extractDate(String input, String instruction) throws DukeException String[] parts = body.split("/", 2); if (parts.length == 2) { String date = DateAndTime.converter(parts[1]); - if (date.equals(Ui.WRONGDATEFORMAT)) { - throw new DukeException(Ui.WRONGDATEFORMAT); + if (date.equals(Ui.WRONG_DATE_FORMAT)) { + throw new DukeException(Ui.WRONG_DATE_FORMAT); } return date; } else { if (instruction.equals("deadline") || instruction.equals("event")) { - throw new DukeException(Ui.MISSINGDATE); + throw new DukeException(Ui.MISSING_DATE); } return ""; } diff --git a/src/main/java/duke/utils/TaskStorage.java b/src/main/java/duke/utils/TaskStorage.java index 5eec70c7cc..1ceb992c4e 100644 --- a/src/main/java/duke/utils/TaskStorage.java +++ b/src/main/java/duke/utils/TaskStorage.java @@ -12,6 +12,7 @@ import java.util.List; import java.util.Scanner; + public class TaskStorage { public static final String FILEPATH = "data/Duke.txt"; @@ -31,31 +32,32 @@ public static String writeToFiles() { } catch (IOException err) { DukeException.saveToFileError(); } - return Ui.SUCCESSFULSAVE; + return Ui.SUCCESSFUL_SAVE; } + public static String loadFiles() { - String output = Ui.LOADFILE; + String output = Ui.LOAD_FILE; System.out.println(output); try { File directory = new File(DIRECTORY); if (!directory.exists()) { - System.out.println(Ui.NODIRECTORY); + System.out.println(Ui.NO_DIRECTORY); directory.mkdir(); Ui.SLEEP(); } File file = new File(FILEPATH); if (!file.exists()) { - System.out.println(Ui.NOFILE); + System.out.println(Ui.NO_FILE); file.createNewFile(); Ui.SLEEP(); } if (file.length() == 0) { Ui.SLEEP(); - System.out.println(Ui.EMPTYFILE); - return Ui.EMPTYFILE; + System.out.println(Ui.EMPTY_FILE); + return Ui.EMPTY_FILE; } restoreTask(file); @@ -64,10 +66,10 @@ public static String loadFiles() { System.out.println("IO error!: " + e.getMessage()); } - return Ui.SUCESSFULLOAD; + return Ui.SUCESSFUL_LOAD; } - private static final void restoreTask(File file) throws IOException { + private static void restoreTask(File file) throws IOException { Scanner sc = new Scanner(file); while (sc.hasNext()) { diff --git a/src/test/java/duke/utils/DateAndTimeTest.java b/src/test/java/duke/utils/DateAndTimeTest.java index 2938f8d6cb..2dd25d42fe 100644 --- a/src/test/java/duke/utils/DateAndTimeTest.java +++ b/src/test/java/duke/utils/DateAndTimeTest.java @@ -9,17 +9,17 @@ public class DateAndTimeTest { @Test void converterTest() { String date = "2019-10-22"; - String acutalOutput = DateAndTime.converter(date); + String actualOutput = DateAndTime.converter(date); String expectedOutput = "Oct 22 2019"; - assertEquals(expectedOutput, acutalOutput); + assertEquals(expectedOutput, actualOutput); } @Test void converterTest_WrongDateFormat() { String date = "2019"; - String acutalOutput = DateAndTime.converter(date); + String actualOutput = DateAndTime.converter(date); String expectedOutput = "!!!Err, wrong date format.. (yyyy-mm-dd)!!!"; - assertEquals(expectedOutput, acutalOutput); + assertEquals(expectedOutput, actualOutput); } } diff --git a/src/test/java/duke/utils/ParserTest.java b/src/test/java/duke/utils/ParserTest.java index c75ce385be..7a16f991a8 100644 --- a/src/test/java/duke/utils/ParserTest.java +++ b/src/test/java/duke/utils/ParserTest.java @@ -20,7 +20,7 @@ void extractInstructionTest() throws DukeException { void extractInstruction_emptyInstruction_Exception() { try { String testInput = ""; - String actualInstruction = Parser.extractInstruction(testInput); + Parser.extractInstruction(testInput); fail(); } catch (DukeException e) { assertEquals("Walao, command cannot be empty!", e.getMessage()); @@ -31,7 +31,7 @@ void extractInstruction_emptyInstruction_Exception() { void extractInstruction_wrongInstruction_Exception() { try { String testInput = "ANYHOW"; - String actualInstruction = Parser.extractInstruction(testInput); + Parser.extractInstruction(testInput); fail(); } catch (DukeException e) { assertEquals("I DON'T KNOW WHAT U SAYING BRO", e.getMessage()); @@ -50,7 +50,7 @@ void extractTaskTest() throws DukeException { void extractTask_emptyTask_Exception() { try { String testInput = "deadline "; - String actualTask = Parser.extractTask(testInput, "deadline"); + Parser.extractTask(testInput, "deadline"); fail(); } catch (DukeException e) { assertEquals("Walao!NO TASK!", e.getMessage()); @@ -68,7 +68,7 @@ void extractDateTest() throws DukeException { void extractDate_emptyDate_withoutSlash_Exception() { try { String testInput = "deadline project"; - String actualDate = Parser.extractDate(testInput, "deadline"); + Parser.extractDate(testInput, "deadline"); fail(); } catch (DukeException e) { assertEquals("!!!Fill ur date lah (add date with / in yyyy-mm-dd format)!!!", e.getMessage()); @@ -80,7 +80,7 @@ void extractDate_emptyDate_withoutSlash_Exception() { void extractDate_wrongDateFormat_Exception1() { try { String testInput = "deadline project/"; - String actualDate = Parser.extractDate(testInput, "deadline"); + Parser.extractDate(testInput, "deadline"); fail(); } catch (DukeException e) { assertEquals("!!!Err, wrong date format.. (yyyy-mm-dd)!!!", e.getMessage()); @@ -91,7 +91,7 @@ void extractDate_wrongDateFormat_Exception1() { void extractDate_wrongDateFormat_Exception2() { try { String testInput = "event project/2019"; - String actualDate = Parser.extractDate(testInput, "event"); + Parser.extractDate(testInput, "event"); fail(); } catch (DukeException e) { assertEquals("!!!Err, wrong date format.. (yyyy-mm-dd)!!!", e.getMessage()); diff --git a/src/test/java/duke/utils/TaskStorageTest.java b/src/test/java/duke/utils/TaskStorageTest.java index 46f1153e47..d07c7b1deb 100644 --- a/src/test/java/duke/utils/TaskStorageTest.java +++ b/src/test/java/duke/utils/TaskStorageTest.java @@ -16,7 +16,7 @@ void writeToFilesTest() { @Test void loadFilesTest() { String actualOutput = TaskStorage.loadFiles(); - String expectedOutput = "********** Awwww~ You don't have any history of tasks **********\n";; + String expectedOutput = "********** Awwww~ You don't have any history of tasks **********\n"; assertEquals(actualOutput, expectedOutput); } From 0350ec57374e4c7f254987cc2eeb3425d78fd42e Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Sat, 30 Jan 2021 22:00:18 +0800 Subject: [PATCH 36/62] Implement find function and added TaskList class --- data/Duke.txt | 1 + src/main/java/META-INF/MANIFEST.MF | 3 + src/main/java/duke/command/AddCommand.java | 34 +++---- src/main/java/duke/command/Command.java | 6 +- src/main/java/duke/command/DeleteCommand.java | 21 ++--- src/main/java/duke/command/DoneCommand.java | 22 ++--- src/main/java/duke/command/ErrorCommand.java | 5 +- src/main/java/duke/command/ExitCommand.java | 21 +---- src/main/java/duke/command/FindCommand.java | 15 +++ src/main/java/duke/command/ListCommand.java | 6 +- src/main/java/duke/driver/DukeDriver.java | 5 +- .../java/duke/exceptions/DukeException.java | 51 +---------- src/main/java/duke/task/Task.java | 89 ++++-------------- src/main/java/duke/task/TaskList.java | 91 +++++++++++++++++++ src/main/java/duke/type/CommandType.java | 19 +++- src/main/java/duke/ui/Ui.java | 73 ++++++--------- src/main/java/duke/utils/DateAndTime.java | 12 ++- src/main/java/duke/utils/Parser.java | 43 +++++---- src/main/java/duke/utils/TaskStorage.java | 29 +++--- src/test/java/duke/task/TaskTest.java | 10 +- src/test/java/duke/utils/DateAndTimeTest.java | 8 +- src/test/java/duke/utils/ParserTest.java | 12 +-- src/test/java/duke/utils/TaskStorageTest.java | 2 +- 23 files changed, 288 insertions(+), 290 deletions(-) create mode 100644 src/main/java/META-INF/MANIFEST.MF create mode 100644 src/main/java/duke/command/FindCommand.java create mode 100644 src/main/java/duke/task/TaskList.java diff --git a/data/Duke.txt b/data/Duke.txt index 520a486723..656516ea13 100644 --- a/data/Duke.txt +++ b/data/Duke.txt @@ -2,3 +2,4 @@ 2@@ @@readbook @@Oct 22 2019 1@@ @@readbook 2@@X@@swimming @@Oct 22 2019 +2@@ @@reabook @@Oct 23 2019 diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..6e864153e8 --- /dev/null +++ b/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: duke.Duke + diff --git a/src/main/java/duke/command/AddCommand.java b/src/main/java/duke/command/AddCommand.java index d06af73794..2a0485a026 100644 --- a/src/main/java/duke/command/AddCommand.java +++ b/src/main/java/duke/command/AddCommand.java @@ -1,10 +1,9 @@ package duke.command; -import duke.task.Deadlines; -import duke.task.Event; -import duke.task.Todo; +import duke.task.*; import duke.ui.Ui; + public class AddCommand extends Command{ public AddCommand(String instruction, String task, String date) { super(instruction, task, date, command -> { @@ -19,30 +18,23 @@ public AddCommand(String instruction, String task, String date) { } - /** - * handle todo command and create a todo task if task is not empty. - * - * @param task name of the user task. - */ - private static final Boolean handleToDo(String task) { + + private static Boolean handleToDo(String task) { if (!task.equals("")) { Todo todo = new Todo(task); + TaskList.addTask(todo); System.out.println(Ui.biggerBox(todo)); } return false; } - /** - * handle deadline command by creating deadline task if task and date are not empty. - * - * @param task name of the user task. - * @param date date of the task to be done. - */ - private static final Boolean handleDeadline(String task, String date) { + + private static Boolean handleDeadline(String task, String date) { if (!date.equals("")) { Deadlines deadlines = new Deadlines(task, date); + TaskList.addTask(deadlines); System.out.println(Ui.biggerBox(deadlines)); } @@ -50,15 +42,11 @@ private static final Boolean handleDeadline(String task, String date) { } - /** - * handle event command by creating event if task and date are not empty. - * - * @param task name of the user task. - * @param date date of the task to be done. - */ - private static final Boolean handleEvent(String task, String date) { + + private static Boolean handleEvent(String task, String date) { if (!task.equals("") && !date.equals("")) { Event event = new Event(task, date); + TaskList.addTask(event); System.out.println(Ui.biggerBox(event)); } diff --git a/src/main/java/duke/command/Command.java b/src/main/java/duke/command/Command.java index 4c99821ec4..af7087f87a 100644 --- a/src/main/java/duke/command/Command.java +++ b/src/main/java/duke/command/Command.java @@ -2,12 +2,14 @@ import java.util.function.Function; + public abstract class Command { private final String instruction; private final String task; private final String date; private final Function func; + public Command(String instruction, String task, String date, Function func) { this.instruction = instruction; this.task = task; @@ -15,13 +17,11 @@ public Command(String instruction, String task, String date, Function { - return handleDelete(task, date); - }); +public class DeleteCommand extends Command { + + public DeleteCommand(String task, String date) { + super("delete", task, date, command -> handleDelete(task, date)); } - /** - * handle delete command key in by user by removing the task from the list if there is any. - * - * @param task name of the user task. - */ - private static final Boolean handleDelete(String task, String date) { + + private static Boolean handleDelete(String task, String date) { if (task.length() > 0 && date.equals("")) { try { int num = Integer.parseInt(task); - Task.delete(num); + TaskList.delete(num); } catch (NumberFormatException e) { DukeException.NumberFormatException(); } diff --git a/src/main/java/duke/command/DoneCommand.java b/src/main/java/duke/command/DoneCommand.java index ad72a6d116..e020f6df0d 100644 --- a/src/main/java/duke/command/DoneCommand.java +++ b/src/main/java/duke/command/DoneCommand.java @@ -1,26 +1,22 @@ package duke.command; import duke.exceptions.DukeException; -import duke.task.Task; +import duke.task.TaskList; + + +public class DoneCommand extends Command { -public class DoneCommand extends Command{ - public DoneCommand(String task, String date) { - super("done", task, date, command -> { - return handleDone(task); - }); + public DoneCommand(String task, String date) { + super("done", task, date, command -> handleDone(task)); } - /** - * handle done command by marking the task as done. - * - * @param task name of the user task. - */ - private static final Boolean handleDone(String task) { + + private static Boolean handleDone(String task) { if (task.length() > 0) { try { int num = Integer.parseInt(task); - Task.done(num); + TaskList.done(num); } catch (NumberFormatException e) { DukeException.NumberFormatException(); } diff --git a/src/main/java/duke/command/ErrorCommand.java b/src/main/java/duke/command/ErrorCommand.java index 32aa672203..3d17a05dca 100644 --- a/src/main/java/duke/command/ErrorCommand.java +++ b/src/main/java/duke/command/ErrorCommand.java @@ -1,9 +1,8 @@ package duke.command; + public class ErrorCommand extends Command{ public ErrorCommand() { - super("", "", "", command -> { - return false; - }); + super("", "", "", command -> false); } } diff --git a/src/main/java/duke/command/ExitCommand.java b/src/main/java/duke/command/ExitCommand.java index 0b9d674337..82f0b33a30 100644 --- a/src/main/java/duke/command/ExitCommand.java +++ b/src/main/java/duke/command/ExitCommand.java @@ -1,25 +1,14 @@ package duke.command; + public class ExitCommand extends Command { public ExitCommand(String task, String date) { - super("bye", task, date, command -> { - return handleBye(task, date); - - }); + super("bye", task, date, command -> handleBye(task, date)); } - /** - * handle bye command by returning true or false. - * - * @param task name of the user task. - * @param date date of the task that user key in. - * @return a boolean of whether to exit the program. - */ - private static final boolean handleBye(String task, String date) { - if (task.equals("") && date.equals("")) { - return true; - } - return false; + + private static boolean handleBye(String task, String date) { + return task.equals("") && date.equals(""); } } diff --git a/src/main/java/duke/command/FindCommand.java b/src/main/java/duke/command/FindCommand.java new file mode 100644 index 0000000000..bb77740d90 --- /dev/null +++ b/src/main/java/duke/command/FindCommand.java @@ -0,0 +1,15 @@ +package duke.command; + +import duke.task.TaskList; + +public class FindCommand extends Command { + + public FindCommand(String task, String date) { + super("find", task, date, command -> { + System.out.println(TaskList.find(task)); + return false; + }); + } + + +} diff --git a/src/main/java/duke/command/ListCommand.java b/src/main/java/duke/command/ListCommand.java index 3ce7467fda..ca001c15d0 100644 --- a/src/main/java/duke/command/ListCommand.java +++ b/src/main/java/duke/command/ListCommand.java @@ -1,10 +1,12 @@ package duke.command; -import duke.ui.Ui; +import duke.task.TaskList; + + public class ListCommand extends Command{ public ListCommand() { super("", "", "", command -> { - Ui.LISTING(); + TaskList.listing(); return false; }); } diff --git a/src/main/java/duke/driver/DukeDriver.java b/src/main/java/duke/driver/DukeDriver.java index 180e3cb112..c45b2e0161 100644 --- a/src/main/java/duke/driver/DukeDriver.java +++ b/src/main/java/duke/driver/DukeDriver.java @@ -43,10 +43,9 @@ public static void executeDuke() { * @param message String representation of the message key in by user. * @return a boolean to whether to exit the program. */ - private static final boolean inputHandler(String message) { + private static boolean inputHandler(String message) { Command command = new Parser(message).parse(); - Boolean end = command.execute(); - return end; + return command.execute(); } diff --git a/src/main/java/duke/exceptions/DukeException.java b/src/main/java/duke/exceptions/DukeException.java index d3e0a5e782..6c74111be6 100644 --- a/src/main/java/duke/exceptions/DukeException.java +++ b/src/main/java/duke/exceptions/DukeException.java @@ -11,55 +11,12 @@ public DukeException(String errorMessage) { super(errorMessage); } - public static final void DATEFORMATEXCEPTION() { - System.out.println(Ui.WRONGDATEFORMAT); - } - public static final void NumberFormatException() { - System.out.println(Ui.KEYINNUMBER); - } - - public static final void EmptyCommandException() { - System.out.println(Ui.EMPTYCOMMAND); - } - - /** - * display the error message for empty body error. - * - */ - public static final void emptyTaskException() { - System.out.println(Ui.EMPTYTASK); - } - - - /** - * display the error message for too many argument error. - * - */ - public static final void argumentErrorException() { - System.out.println(Ui.TOOMANYARGUMENTS); - } - - /** - * display the error message for missing argument error. - * - */ - public static final void missingDateErrorException() { - System.out.println(Ui.MISSINGDATE); - } - /** - * display the error message for command error. - * - */ - public static final void commandErrorException() { - System.out.println(Ui.COMMANDERROR); + public static void NumberFormatException() { + System.out.println(Ui.KEY_IN_NUMBER); } - /** - * display the error message for missing task error. - * - */ - public static final void taskErrorException() { System.out.println(Ui.TASKERROR); } + public static void taskErrorException() { System.out.println(Ui.TASK_ERROR); } - public static final void saveToFileError() { System.out.println(Ui.SAVETOFILEERROR);} + public static void saveToFileError() { System.out.println(Ui.SAVE_TO_FILE_ERROR);} } diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java index c1e17d767b..0c825c8f29 100644 --- a/src/main/java/duke/task/Task.java +++ b/src/main/java/duke/task/Task.java @@ -1,105 +1,65 @@ package duke.task; -import duke.exceptions.DukeException; -import duke.ui.Ui; - -import java.util.ArrayList; -import java.util.List; - /** * A class that store the task that user key in. */ public class Task { - private static List taskList = new ArrayList<>(); - private String taskName; + private final String taskName; private static int capacity = 0; private int index; - private String done; - private String date; + private String isDone; + private final String date; + /** - * Construct a task object with taskname attached and its index label in the taskList. + * Construct a task object with taskName attached and its index label in the taskList. * @param taskName name of the task. */ - Task(String taskName) { this.taskName = taskName; this.index = capacity + 1; - this.done = " "; + this.isDone = " "; this.date = ""; capacity++; - add(this); + } Task(String taskName, String done, boolean check) { this.taskName = taskName; this.index = capacity + 1; - this.done = done; + this.isDone = done; this.date = ""; capacity++; - add(this); + } Task(String taskName, String date) { this.taskName = taskName; this.index = capacity + 1; - this.done = " "; + this.isDone = " "; this.date = date; capacity++; - add(this); + } Task(String taskName, String date, String done) { this.taskName = taskName; this.index = capacity + 1; - this.done = done; + this.isDone = done; this.date = date; capacity++; - add(this); } - /** - * Store the task key in by user in the taskList. - * - * @param t Task key in by user. - */ - private static void add(Task t) { - taskList.add(t); - } - /** - * Mark a given task as done. - * - * @param i the index label of the Task. - */ - public static void done(int i) { - try { - Task t = taskList.get(i - 1); - taskList.get(i - 1).done = "X"; - Ui.doneTask(t); - } catch (IndexOutOfBoundsException e) { - DukeException.taskErrorException(); - } + public void changeIndex(int i) { + this.index = i; } - public static void delete(int i) { - try { - Task t = taskList.get(i - 1); - taskList.remove(i - 1); - Ui.deleteTask(t); - for (Task task : taskList) { - if (task.index > i) { - task.index--; - } - } - } catch (IndexOutOfBoundsException e) { - DukeException.taskErrorException(); - } + public void markDone() { + this.isDone = "X"; } - public static void clearAllTask() { - taskList.clear(); - } + /** * Get the name of the task. @@ -110,15 +70,6 @@ public String getTaskName() { return taskName; } - /** - * Get the taskList. - * - * @return the List of all tasks stored. - */ - - public static final List getTaskList() { - return Task.taskList; - } /** * get the isDone status of the task. @@ -126,7 +77,7 @@ public static final List getTaskList() { * @return a String representation of the isDone status (X for done). */ public String getDoneStatus() { - return done; + return isDone; } /** @@ -151,12 +102,12 @@ public String getDate() { * * @return the int representation of the capacity of the taskList. */ - public static final int getCapacity() { + public static int getCapacity() { return Task.capacity; } @Override public String toString() { - return String.format("[%s] %d. %s", done, index, taskName); + return String.format("[%s] %d. %s", isDone, index, taskName); } } \ No newline at end of file diff --git a/src/main/java/duke/task/TaskList.java b/src/main/java/duke/task/TaskList.java new file mode 100644 index 0000000000..08ba3afb0f --- /dev/null +++ b/src/main/java/duke/task/TaskList.java @@ -0,0 +1,91 @@ +package duke.task; + +import duke.exceptions.DukeException; +import duke.ui.Ui; + +import java.util.ArrayList; +import java.util.List; + +public class TaskList { + private static List taskList = new ArrayList<>(); + + private List list; + + public TaskList() { + this.list = new ArrayList<>(); + } + + + + public static void addTask(Task t) { + taskList.add(t); + } + + + public static void done(int i) { + try { + Task t = taskList.get(i - 1); + taskList.get(i - 1).markDone(); + Ui.doneTask(t); + } catch (IndexOutOfBoundsException e) { + DukeException.taskErrorException(); + } + } + + public static String find(String keyword) { + int index = 1; + StringBuilder sb = new StringBuilder(""); + for (Task task : taskList) { + String taskName = task.getTaskName(); + if (taskName.contains(keyword)) { + String prefix = task.toString().substring(0, 6); + sb.append(prefix + " " + index + ". " + task.getTaskName() + task.getDate() + "\n"); + index++; + } + } + if (sb.equals("")) { + sb.append("~~~~~Sorry ah, no match.~~~~~"); + } else { + sb.insert(0, "Here are the matches for your search: \n"); + } + + return sb.toString(); + + } + + + public static void listing() { + System.out.println(Ui.UPPER); + for (Task task : taskList) { + if (task == null) break; + System.out.println(task); + } + System.out.println(Ui.LOWER); + } + + + + public static void delete(int i) { + try { + Task t = taskList.get(i - 1); + taskList.remove(i - 1); + Ui.deleteTask(t); + for (Task task : taskList) { + if (task.getIndex() > i) { + task.changeIndex(task.getIndex() - 1); + } + } + } catch (IndexOutOfBoundsException e) { + DukeException.taskErrorException(); + } + } + + public static void clearAllTask() { + taskList.clear(); + } + + public static List getTaskList() { + return taskList; + } + +} diff --git a/src/main/java/duke/type/CommandType.java b/src/main/java/duke/type/CommandType.java index 7873598f94..4f947428ea 100644 --- a/src/main/java/duke/type/CommandType.java +++ b/src/main/java/duke/type/CommandType.java @@ -1,5 +1,9 @@ package duke.type; +/** + * Encapsulate a CommandType enum class that represents the type of command. + * The class includes seven types: todo, deadline, event, bye, list, delete, done and find. + */ public enum CommandType { TODO("todo"), DEADLINE("deadline"), @@ -7,15 +11,26 @@ public enum CommandType { BYE("bye"), DONE("done"), LIST("list"), + FIND("find"), DELETE("delete"); - private String type; + private final String type; + /** + * Construct a CommandType object with a String representation of the type. + * @param type String representation of the type. + */ CommandType(String type) { this.type = type; } - + /** + * Gets the CommandType object from a string representation of the type. + * Returns null if no such object exists. + * + * @param type a string representing the type. + * @return an CommandType object of the specified type and null if no such object exists. + */ public static CommandType valueOfType(String type) { for (CommandType t : values()) { if (t.type.equals(type)) { diff --git a/src/main/java/duke/ui/Ui.java b/src/main/java/duke/ui/Ui.java index 1fe4bd6b4c..02ecb822c2 100644 --- a/src/main/java/duke/ui/Ui.java +++ b/src/main/java/duke/ui/Ui.java @@ -1,6 +1,7 @@ package duke.ui; import duke.task.Task; +import duke.task.TaskList; /** * A class that store all the possible String format for Duke for code simplicity. @@ -15,16 +16,16 @@ public class Ui { + "| | | | | | | |/ / _ \\\n" + "| |_| | |_| | < __/\n" + "|____/ \\__,_|_|\\_\\___|\n"; - public static final String WRONGDATEFORMAT = "!!!Err, wrong date format.. (yyyy-mm-dd)!!!"; - public static final String KEYINNUMBER = "!!!!!!!PLease Lah! Key in number!!!!!!!!"; - public static final String EMPTYTASK = "!!!!!!!!!Walao!NO TASK!!!!!!!!!!"; - public static final String TOOMANYARGUMENTS = "You put so many/few ARGUMENTS for what"; - public static final String MISSINGDATE = "!!!Fill ur date lah (add date with / in yyyy-mm-dd format)!!!"; - public static final String COMMANDERROR = "!!!!!!!I DON'T KNOW WHAT U SAYING BRO!!!!!!!"; - public static final String TASKERROR = "!!!!!!!!!!Walao, no such task!!!!!!!!!"; - public static final String SAVETOFILEERROR = "Huh? Where your file?"; - public static final String EMPTYCOMMAND = "!!!Walao, command cannot be empty!!!"; - public static final String SUCCESSFULSAVE = "~~~~~~~~~~~File Saved Successfully!~~~~~~~~~~~~"; + + public static final String WRONG_DATE_FORMAT = "!!!Err, wrong date format.. (yyyy-mm-dd)!!!"; + public static final String KEY_IN_NUMBER = "!!!!!!!PLease Lah! Key in number!!!!!!!!"; + public static final String EMPTY_TASK = "!!!!!!!!!Walao!NO TASK!!!!!!!!!!"; + public static final String MISSING_DATE = "!!!Fill ur date lah (add date with / in yyyy-mm-dd format)!!!"; + public static final String COMMAND_ERROR = "!!!!!!!I DON'T KNOW WHAT U SAYING BRO!!!!!!!"; + public static final String TASK_ERROR = "!!!!!!!!!!Walao, no such task!!!!!!!!!"; + public static final String SAVE_TO_FILE_ERROR = "Huh? Where your file?"; + public static final String EMPTY_COMMAND = "!!!Walao, command cannot be empty!!!"; + public static final String SUCCESSFUL_SAVE = "~~~~~~~~~~~File Saved Successfully!~~~~~~~~~~~~"; public static final String FAREWELL = UPPER + "~~~~~~~~~~~ I Zao Liao. Don't Miss Meeeeeee ~~~~~~~~~~~." + LOWER; @@ -32,31 +33,20 @@ public class Ui { + "****************** Awww, need help ah? ******************" + LOWER; - public static final String NODIRECTORY = "********** Cannot find your directory eh, " + public static final String NO_DIRECTORY = "********** Cannot find your directory eh, " + "first time ah? Create one for you **********\n" ; - public static final String LOADFILE = "********** Wait ah~ Loading file for you **********\n"; - public static final String NOFILE = "********** File also don't have ah, nvm I make one for you **********\n"; - public static final String EMPTYFILE = "********** Awwww~ You don't have any history of tasks **********\n"; - public static final String SUCESSFULLOAD = "***********Sir, here is your past history************"; + public static final String LOAD_FILE = "********** Wait ah~ Loading file for you **********\n"; + public static final String NO_FILE = "********** File also don't have ah, nvm I make one for you **********\n"; + public static final String EMPTY_FILE = "********** Awwww~ You don't have any history of tasks **********\n"; + public static final String SUCESSFUL_LOAD = "***********Sir, here is your past history************"; - /** - * make a chatBox that wrap a given String. - * @param s the String to be wrapped. - * @return a String with a chatBox wrapped. - */ - public static final String chatBox(String s) { - if (s.length() > 50) { - return "Walao! Your command too long lah!"; - } else { - return UPPER + " ".repeat(36 - s.length() / 2) + s + LOWER; - } - } - public static final void doneTask(Task t) { + + public static void doneTask(Task t) { System.out.println(Ui.UPPER + "Wah~ You done the task: " + " " + t.toString() + Ui.LOWER); } - public static final void deleteTask(Task t) { + public static void deleteTask(Task t) { System.out.println(Ui.UPPER + "Awww~ You've deleted the task: " + " " + t.toString() + Ui.LOWER); } @@ -66,37 +56,28 @@ public static final void deleteTask(Task t) { * @param t task to be wrapped. * @return the String representation of the task name wrapped in a chatBox. */ - public static final String biggerBox(Task t) { + public static String biggerBox(Task t) { return Ui.UPPER + "Added liao: " + t.toString() + Ui.LINEBREAK + "You have " + Task.getCapacity() + " tasks in the list!" + Ui.LOWER; } - /** - * Display all the current task and status store in the tasklist. - * - */ - public static final void LISTING() { - System.out.println(UPPER); - for (Task task : Task.getTaskList()) { - if (task == null) break; - System.out.println(task); - } - System.out.println(LOWER); - } - public static final void DONELOADING() { + + + public static void DONELOADING() { System.out.println(UPPER); - for (Task task : Task.getTaskList()) { + System.out.println("~~~~~Sir, here is your past history: "); + for (Task task : TaskList.getTaskList()) { if (task == null) break; System.out.println(task); } - System.out.println("Sir, here is your past history"); + System.out.println(LOWER); } - public static final void SLEEP() { + public static void SLEEP() { try { Thread.sleep(1500); } catch (InterruptedException e) { diff --git a/src/main/java/duke/utils/DateAndTime.java b/src/main/java/duke/utils/DateAndTime.java index 9eee3ee8bb..bf9963adb2 100644 --- a/src/main/java/duke/utils/DateAndTime.java +++ b/src/main/java/duke/utils/DateAndTime.java @@ -6,24 +6,26 @@ import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; + public class DateAndTime { - public static final String converter(String date) { + + public static String converter(String date) { if (isDashFormat(date)) { try { LocalDate d1 = LocalDate.parse(date.trim()); return d1.format(DateTimeFormatter.ofPattern("MMM d yyyy")); } catch (DateTimeParseException e) { - return Ui.WRONGDATEFORMAT; + return Ui.WRONG_DATE_FORMAT; } } else { - return Ui.WRONGDATEFORMAT; + return Ui.WRONG_DATE_FORMAT; } } - private static final boolean isDashFormat(String date) { + private static boolean isDashFormat(String date) { String[] dashFormat = date.toLowerCase().split("-", 3); for (String s : dashFormat) { if (!isNumeric(s.trim())) { @@ -38,7 +40,7 @@ private static boolean isNumeric(String strNum) { return false; } try { - double d = Double.parseDouble(strNum); + Double.parseDouble(strNum); } catch (NumberFormatException nfe) { return false; } diff --git a/src/main/java/duke/utils/Parser.java b/src/main/java/duke/utils/Parser.java index d3e175edea..c8d8dcdfb8 100644 --- a/src/main/java/duke/utils/Parser.java +++ b/src/main/java/duke/utils/Parser.java @@ -5,13 +5,21 @@ import duke.type.CommandType; import duke.ui.Ui; +/** + * This class extract and process the user input and produce the right command to be executed after parsing. + */ public class Parser { - private String input; + private final String input; public Parser(String input) { this.input = input; } + /** + * This method process all the user input and create respective command to be executed. + * + * @return the respective command to be executed. + */ public final Command parse() { String instruction; String taskName; @@ -56,6 +64,9 @@ public final Command parse() { case "delete": command = new DeleteCommand(taskName, date); break; + case "find": + command = new FindCommand(taskName, date); + break; default: break; } @@ -73,11 +84,11 @@ static String extractInstruction(String input) throws DukeException { String instruction = input.trim().toLowerCase().split(" ")[0]; if (input.replaceAll(" ", "").equals("")) { - throw new DukeException(Ui.EMPTYCOMMAND); + throw new DukeException(Ui.EMPTY_COMMAND); } if (CommandType.valueOfType(instruction) == null) { - throw new DukeException(Ui.COMMANDERROR); + throw new DukeException(Ui.COMMAND_ERROR); } return instruction; @@ -92,29 +103,29 @@ static String extractInstruction(String input) throws DukeException { */ static String extractTask(String input, String command) throws DukeException { String body = input.replaceAll(command, "").trim(); - if (command.equals("todo")) { + switch (command) { + case "todo": case "find": if (body.equals("")) { - throw new DukeException(Ui.EMPTYTASK); + throw new DukeException(Ui.EMPTY_TASK); } else { return body; } - } else if (command.equals("done") || command.equals("delete")) { + case "done": case "delete": String hasLetter = body.replaceAll("[0-9]", ""); if (hasLetter.length() > 0) { - throw new DukeException(Ui.KEYINNUMBER); + throw new DukeException(Ui.KEY_IN_NUMBER); } else { return body.replaceAll("[^0-9]", ""); } - } else if (command.equals("deadline") || command.equals("todo") || command.equals("event")) { + case "deadline": case "event": if (body.equals("")) { - throw new DukeException(Ui.EMPTYTASK); + throw new DukeException(Ui.EMPTY_TASK); } else { - String task = body.split("/")[0]; - return task; + return body.split("/")[0]; } - } else { + default: if (body.length() > 0) { - throw new DukeException(Ui.COMMANDERROR); + throw new DukeException(Ui.COMMAND_ERROR); } return ""; } @@ -131,14 +142,14 @@ static String extractDate(String input, String instruction) throws DukeException String[] parts = body.split("/", 2); if (parts.length == 2) { String date = DateAndTime.converter(parts[1]); - if (date.equals(Ui.WRONGDATEFORMAT)) { - throw new DukeException(Ui.WRONGDATEFORMAT); + if (date.equals(Ui.WRONG_DATE_FORMAT)) { + throw new DukeException(Ui.WRONG_DATE_FORMAT); } return date; } else { if (instruction.equals("deadline") || instruction.equals("event")) { - throw new DukeException(Ui.MISSINGDATE); + throw new DukeException(Ui.MISSING_DATE); } return ""; } diff --git a/src/main/java/duke/utils/TaskStorage.java b/src/main/java/duke/utils/TaskStorage.java index 5eec70c7cc..6782bff5c3 100644 --- a/src/main/java/duke/utils/TaskStorage.java +++ b/src/main/java/duke/utils/TaskStorage.java @@ -1,24 +1,24 @@ package duke.utils; import duke.exceptions.DukeException; +import duke.task.*; import duke.ui.Ui; -import duke.task.Task; -import duke.task.Todo; -import duke.task.Deadlines; -import duke.task.Event; + import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.List; import java.util.Scanner; + public class TaskStorage { public static final String FILEPATH = "data/Duke.txt"; public static final String DIRECTORY = "data"; + public static String writeToFiles() { - List taskList = Task.getTaskList(); + List taskList = TaskList.getTaskList(); try { FileWriter fw = new FileWriter(FILEPATH); for (Task t : taskList) { @@ -31,31 +31,32 @@ public static String writeToFiles() { } catch (IOException err) { DukeException.saveToFileError(); } - return Ui.SUCCESSFULSAVE; + return Ui.SUCCESSFUL_SAVE; } + public static String loadFiles() { - String output = Ui.LOADFILE; + String output = Ui.LOAD_FILE; System.out.println(output); try { File directory = new File(DIRECTORY); if (!directory.exists()) { - System.out.println(Ui.NODIRECTORY); + System.out.println(Ui.NO_DIRECTORY); directory.mkdir(); Ui.SLEEP(); } File file = new File(FILEPATH); if (!file.exists()) { - System.out.println(Ui.NOFILE); + System.out.println(Ui.NO_FILE); file.createNewFile(); Ui.SLEEP(); } if (file.length() == 0) { Ui.SLEEP(); - System.out.println(Ui.EMPTYFILE); - return Ui.EMPTYFILE; + System.out.println(Ui.EMPTY_FILE); + return Ui.EMPTY_FILE; } restoreTask(file); @@ -64,16 +65,17 @@ public static String loadFiles() { System.out.println("IO error!: " + e.getMessage()); } - return Ui.SUCESSFULLOAD; + return Ui.SUCESSFUL_LOAD; } - private static final void restoreTask(File file) throws IOException { + private static void restoreTask(File file) throws IOException { Scanner sc = new Scanner(file); while (sc.hasNext()) { String[] line = sc.nextLine().split("@@"); if (line.length == 3) { Todo t = new Todo(line[2], line[1]); + TaskList.addTask(t); } else { int type = Integer.parseInt(line[0]); @@ -81,6 +83,7 @@ private static final void restoreTask(File file) throws IOException { String taskName = line[2]; String date = line[3]; Task t = type == 2 ? new Deadlines(taskName, date, done) : new Event(taskName, date, done); + TaskList.addTask(t); } } diff --git a/src/test/java/duke/task/TaskTest.java b/src/test/java/duke/task/TaskTest.java index 28f80db1bb..b68b2724e1 100644 --- a/src/test/java/duke/task/TaskTest.java +++ b/src/test/java/duke/task/TaskTest.java @@ -8,17 +8,17 @@ class TaskTest { @Test void done() { - Task.clearAllTask(); + TaskList.clearAllTask(); Todo task = new Todo("Scratch back", " "); - Task.done(1); + TaskList.done(1); assertEquals("X", task.getDoneStatus()); } @Test void delete() { - Task.clearAllTask(); + TaskList.clearAllTask(); Todo task = new Todo("Scratch back", " "); - Task.delete(1); - assertEquals(0, Task.getTaskList().size()); + TaskList.delete(1); + assertEquals(0, TaskList.getTaskList().size()); } } \ No newline at end of file diff --git a/src/test/java/duke/utils/DateAndTimeTest.java b/src/test/java/duke/utils/DateAndTimeTest.java index 2938f8d6cb..2dd25d42fe 100644 --- a/src/test/java/duke/utils/DateAndTimeTest.java +++ b/src/test/java/duke/utils/DateAndTimeTest.java @@ -9,17 +9,17 @@ public class DateAndTimeTest { @Test void converterTest() { String date = "2019-10-22"; - String acutalOutput = DateAndTime.converter(date); + String actualOutput = DateAndTime.converter(date); String expectedOutput = "Oct 22 2019"; - assertEquals(expectedOutput, acutalOutput); + assertEquals(expectedOutput, actualOutput); } @Test void converterTest_WrongDateFormat() { String date = "2019"; - String acutalOutput = DateAndTime.converter(date); + String actualOutput = DateAndTime.converter(date); String expectedOutput = "!!!Err, wrong date format.. (yyyy-mm-dd)!!!"; - assertEquals(expectedOutput, acutalOutput); + assertEquals(expectedOutput, actualOutput); } } diff --git a/src/test/java/duke/utils/ParserTest.java b/src/test/java/duke/utils/ParserTest.java index c75ce385be..7a16f991a8 100644 --- a/src/test/java/duke/utils/ParserTest.java +++ b/src/test/java/duke/utils/ParserTest.java @@ -20,7 +20,7 @@ void extractInstructionTest() throws DukeException { void extractInstruction_emptyInstruction_Exception() { try { String testInput = ""; - String actualInstruction = Parser.extractInstruction(testInput); + Parser.extractInstruction(testInput); fail(); } catch (DukeException e) { assertEquals("Walao, command cannot be empty!", e.getMessage()); @@ -31,7 +31,7 @@ void extractInstruction_emptyInstruction_Exception() { void extractInstruction_wrongInstruction_Exception() { try { String testInput = "ANYHOW"; - String actualInstruction = Parser.extractInstruction(testInput); + Parser.extractInstruction(testInput); fail(); } catch (DukeException e) { assertEquals("I DON'T KNOW WHAT U SAYING BRO", e.getMessage()); @@ -50,7 +50,7 @@ void extractTaskTest() throws DukeException { void extractTask_emptyTask_Exception() { try { String testInput = "deadline "; - String actualTask = Parser.extractTask(testInput, "deadline"); + Parser.extractTask(testInput, "deadline"); fail(); } catch (DukeException e) { assertEquals("Walao!NO TASK!", e.getMessage()); @@ -68,7 +68,7 @@ void extractDateTest() throws DukeException { void extractDate_emptyDate_withoutSlash_Exception() { try { String testInput = "deadline project"; - String actualDate = Parser.extractDate(testInput, "deadline"); + Parser.extractDate(testInput, "deadline"); fail(); } catch (DukeException e) { assertEquals("!!!Fill ur date lah (add date with / in yyyy-mm-dd format)!!!", e.getMessage()); @@ -80,7 +80,7 @@ void extractDate_emptyDate_withoutSlash_Exception() { void extractDate_wrongDateFormat_Exception1() { try { String testInput = "deadline project/"; - String actualDate = Parser.extractDate(testInput, "deadline"); + Parser.extractDate(testInput, "deadline"); fail(); } catch (DukeException e) { assertEquals("!!!Err, wrong date format.. (yyyy-mm-dd)!!!", e.getMessage()); @@ -91,7 +91,7 @@ void extractDate_wrongDateFormat_Exception1() { void extractDate_wrongDateFormat_Exception2() { try { String testInput = "event project/2019"; - String actualDate = Parser.extractDate(testInput, "event"); + Parser.extractDate(testInput, "event"); fail(); } catch (DukeException e) { assertEquals("!!!Err, wrong date format.. (yyyy-mm-dd)!!!", e.getMessage()); diff --git a/src/test/java/duke/utils/TaskStorageTest.java b/src/test/java/duke/utils/TaskStorageTest.java index 46f1153e47..d07c7b1deb 100644 --- a/src/test/java/duke/utils/TaskStorageTest.java +++ b/src/test/java/duke/utils/TaskStorageTest.java @@ -16,7 +16,7 @@ void writeToFilesTest() { @Test void loadFilesTest() { String actualOutput = TaskStorage.loadFiles(); - String expectedOutput = "********** Awwww~ You don't have any history of tasks **********\n";; + String expectedOutput = "********** Awwww~ You don't have any history of tasks **********\n"; assertEquals(actualOutput, expectedOutput); } From d812a57e1b836cddb8494b3c724cac0ce30a3647 Mon Sep 17 00:00:00 2001 From: Huang Zhenxin Date: Sat, 30 Jan 2021 22:12:34 +0800 Subject: [PATCH 37/62] Fully merge branch-A-CodingStyle --- src/main/java/duke/command/AddCommand.java | 12 +++--------- src/main/java/duke/command/Command.java | 14 +++----------- src/main/java/duke/command/DeleteCommand.java | 13 +------------ src/main/java/duke/command/DoneCommand.java | 17 ++++------------- src/main/java/duke/command/ErrorCommand.java | 5 +---- src/main/java/duke/command/ExitCommand.java | 5 +---- src/main/java/duke/command/ListCommand.java | 5 +---- 7 files changed, 14 insertions(+), 57 deletions(-) diff --git a/src/main/java/duke/command/AddCommand.java b/src/main/java/duke/command/AddCommand.java index 2de0460184..fe6aa62493 100644 --- a/src/main/java/duke/command/AddCommand.java +++ b/src/main/java/duke/command/AddCommand.java @@ -5,13 +5,10 @@ import duke.task.Todo; import duke.ui.Ui; -<<<<<<< HEAD + /** * Sub-class of Command that represents and execute the todo, deadline and event instructions of user. */ -======= - ->>>>>>> branch-A-CodingStandard public class AddCommand extends Command{ public AddCommand(String instruction, String task, String date) { super(instruction, task, date, command -> { @@ -26,16 +23,13 @@ public AddCommand(String instruction, String task, String date) { } -<<<<<<< HEAD + /** * handle todo command and create a todo task if task is not empty. * @param task name of the user task. */ - private static final Boolean handleToDo(String task) { -======= - private static Boolean handleToDo(String task) { ->>>>>>> branch-A-CodingStandard + if (!task.equals("")) { Todo todo = new Todo(task); System.out.println(Ui.biggerBox(todo)); diff --git a/src/main/java/duke/command/Command.java b/src/main/java/duke/command/Command.java index 6ed0386140..e492c4a17d 100644 --- a/src/main/java/duke/command/Command.java +++ b/src/main/java/duke/command/Command.java @@ -1,22 +1,17 @@ package duke.command; import java.util.function.Function; - -<<<<<<< HEAD /** * This class encapsulates the user instruction,task and date and execute the instruction. * */ -======= - ->>>>>>> branch-A-CodingStandard public abstract class Command { private final String instruction; private final String task; private final String date; private final Function func; -<<<<<<< HEAD + /** * Create a command with user instruction, task, date and a function to execute the instruction. * @param instruction user instruction. @@ -24,9 +19,8 @@ public abstract class Command { * @param date date of the task. * @param func the function takes a command to execute the task and returns a boolean whether to end the program. */ -======= ->>>>>>> branch-A-CodingStandard + public Command(String instruction, String task, String date, Function func) { this.instruction = instruction; this.task = task; @@ -34,14 +28,12 @@ public Command(String instruction, String task, String date, Function>>>>>> branch-A-CodingStandard public Boolean execute() { return func.apply(this); } diff --git a/src/main/java/duke/command/DeleteCommand.java b/src/main/java/duke/command/DeleteCommand.java index 02c9ab5a4f..5d424b27ed 100644 --- a/src/main/java/duke/command/DeleteCommand.java +++ b/src/main/java/duke/command/DeleteCommand.java @@ -4,16 +4,9 @@ import duke.exceptions.DukeException; import duke.task.Task; -<<<<<<< HEAD /** * Sub-class of command that only represents and executes a delete instruction of a user. */ -public class DeleteCommand extends Command{ - public DeleteCommand(String task, String date) { - super("delete", task, date, command -> { - return handleDelete(task, date); -======= ->>>>>>> branch-A-CodingStandard public class DeleteCommand extends Command { @@ -22,17 +15,13 @@ public DeleteCommand(String task, String date) { } -<<<<<<< HEAD /** * handle delete command key in by user by removing the task from the list if there is any. * @param task user task in String. * @param date date of the task. */ - private static final Boolean handleDelete(String task, String date) { -======= - private static Boolean handleDelete(String task, String date) { ->>>>>>> branch-A-CodingStandard + if (task.length() > 0 && date.equals("")) { try { int num = Integer.parseInt(task); diff --git a/src/main/java/duke/command/DoneCommand.java b/src/main/java/duke/command/DoneCommand.java index da1a699282..a41cb6f2d3 100644 --- a/src/main/java/duke/command/DoneCommand.java +++ b/src/main/java/duke/command/DoneCommand.java @@ -3,17 +3,11 @@ import duke.exceptions.DukeException; import duke.task.Task; -<<<<<<< HEAD + /** * Sub-class of Command that represents and execute the done instruction of user. + * */ -public class DoneCommand extends Command{ - public DoneCommand(String task, String date) { - super("done", task, date, command -> { - return handleDone(task); -======= ->>>>>>> branch-A-CodingStandard - public class DoneCommand extends Command { @@ -21,16 +15,13 @@ public DoneCommand(String task, String date) { super("done", task, date, command -> handleDone(task)); } -<<<<<<< HEAD + /** * handle done command by marking the task as done. * @param task name of the user task. */ - private static final Boolean handleDone(String task) { -======= - private static Boolean handleDone(String task) { ->>>>>>> branch-A-CodingStandard + if (task.length() > 0) { try { int num = Integer.parseInt(task); diff --git a/src/main/java/duke/command/ErrorCommand.java b/src/main/java/duke/command/ErrorCommand.java index 8a0e26756d..4c23c1f1f5 100644 --- a/src/main/java/duke/command/ErrorCommand.java +++ b/src/main/java/duke/command/ErrorCommand.java @@ -1,12 +1,9 @@ package duke.command; -<<<<<<< HEAD + /** * Sub-class of Command to represents any error in the instruction of user. */ -======= - ->>>>>>> branch-A-CodingStandard public class ErrorCommand extends Command{ public ErrorCommand() { super("", "", "", command -> false); diff --git a/src/main/java/duke/command/ExitCommand.java b/src/main/java/duke/command/ExitCommand.java index ce735f06d8..f14bd2d723 100644 --- a/src/main/java/duke/command/ExitCommand.java +++ b/src/main/java/duke/command/ExitCommand.java @@ -1,12 +1,9 @@ package duke.command; -<<<<<<< HEAD + /** * Sub-class of command that represents and execute the "bye" instruction of user. */ -======= - ->>>>>>> branch-A-CodingStandard public class ExitCommand extends Command { public ExitCommand(String task, String date) { super("bye", task, date, command -> handleBye(task, date)); diff --git a/src/main/java/duke/command/ListCommand.java b/src/main/java/duke/command/ListCommand.java index 8b121c2e19..2b12d16366 100644 --- a/src/main/java/duke/command/ListCommand.java +++ b/src/main/java/duke/command/ListCommand.java @@ -2,13 +2,10 @@ import duke.ui.Ui; -<<<<<<< HEAD + /** * Sub-class of Command that represents and execute the "list" instruction of user. */ -======= - ->>>>>>> branch-A-CodingStandard public class ListCommand extends Command{ public ListCommand() { super("", "", "", command -> { From df155f9805aad4bd88539c62a1d6d8249aecf04d Mon Sep 17 00:00:00 2001 From: Hzxin Date: Mon, 1 Feb 2021 03:13:21 +0800 Subject: [PATCH 38/62] Add gradle support --- build.gradle | 20 +++ data/Duke.txt | 4 - gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 58910 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 185 +++++++++++++++++++++++ gradlew.bat | 104 +++++++++++++ settings.gradle | 2 + src/test/java/duke/task/TaskTest.java | 2 + src/test/java/duke/utils/ParserTest.java | 6 +- 9 files changed, 321 insertions(+), 7 deletions(-) create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000..084a80e6e1 --- /dev/null +++ b/build.gradle @@ -0,0 +1,20 @@ +plugins { + id 'java' +} + +group 'org.example' +version '1.0-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.junit.jupiter:junit-jupiter:5.4.2' + implementation 'org.junit.jupiter:junit-jupiter:5.4.2' + testCompile group: 'junit', name: 'junit', version: '4.12' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/data/Duke.txt b/data/Duke.txt index 06dc130e1c..e69de29bb2 100644 --- a/data/Duke.txt +++ b/data/Duke.txt @@ -1,4 +0,0 @@ -1@@X@@readbook -1@@ @@readbook -2@@X@@swimming @@Oct 22 2019 -2@@ @@reabook @@Oct 23 2019 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..62d4c053550b91381bbd28b1afc82d634bf73a8a GIT binary patch literal 58910 zcma&ObC74zk}X`WF59+k+qTVL*+!RbS9RI8Z5v&-ZFK4Nn|tqzcjwK__x+Iv5xL`> zj94dg?X`0sMHx^qXds{;KY)OMg#H>35XgTVfq6#vc9ww|9) z@UMfwUqk)B9p!}NrNqTlRO#i!ALOPcWo78-=iy}NsAr~T8T0X0%G{DhX~u-yEwc29WQ4D zuv2j{a&j?qB4wgCu`zOXj!~YpTNFg)TWoV>DhYlR^Gp^rkOEluvxkGLB?!{fD!T@( z%3cy>OkhbIKz*R%uoKqrg1%A?)uTZD&~ssOCUBlvZhx7XHQ4b7@`&sPdT475?*zWy z>xq*iK=5G&N6!HiZaD{NSNhWL;+>Quw_#ZqZbyglna!Fqn3N!$L`=;TFPrhodD-Q` z1l*=DP2gKJP@)cwI@-M}?M$$$%u~=vkeC%>cwR$~?y6cXx-M{=wdT4|3X(@)a|KkZ z`w$6CNS@5gWS7s7P86L<=vg$Mxv$?)vMj3`o*7W4U~*Nden}wz=y+QtuMmZ{(Ir1D zGp)ZsNiy{mS}Au5;(fYf93rs^xvi(H;|H8ECYdC`CiC&G`zw?@)#DjMc7j~daL_A$ z7e3nF2$TKlTi=mOftyFBt8*Xju-OY@2k@f3YBM)-v8+5_o}M?7pxlNn)C0Mcd@87?+AA4{Ti2ptnYYKGp`^FhcJLlT%RwP4k$ad!ho}-^vW;s{6hnjD0*c39k zrm@PkI8_p}mnT&5I@=O1^m?g}PN^8O8rB`;t`6H+?Su0IR?;8txBqwK1Au8O3BZAX zNdJB{bpQWR@J|e=Z>XSXV1DB{uhr3pGf_tb)(cAkp)fS7*Qv))&Vkbb+cvG!j}ukd zxt*C8&RN}5ck{jkw0=Q7ldUp0FQ&Pb_$M7a@^nf`8F%$ftu^jEz36d#^M8Ia{VaTy z5(h$I)*l3i!VpPMW+XGgzL~fcN?{~1QWu9!Gu0jOWWE zNW%&&by0DbXL&^)r-A*7R@;T$P}@3eOj#gqJ!uvTqBL5bupU91UK#d|IdxBUZAeh1 z>rAI#*Y4jv>uhOh7`S@mnsl0g@1C;k$Z%!d*n8#_$)l}-1&z2kr@M+xWoKR z!KySy-7h&Bf}02%JeXmQGjO3ntu={K$jy$rFwfSV8!zqAL_*&e2|CJ06`4&0+ceI026REfNT>JzAdwmIlKLEr2? zaZ#d*XFUN*gpzOxq)cysr&#6zNdDDPH% zd8_>3B}uA7;bP4fKVdd~Og@}dW#74ceETOE- zlZgQqQfEc?-5ly(Z5`L_CCM!&Uxk5#wgo=OLs-kFHFG*cTZ)$VE?c_gQUW&*!2@W2 z7Lq&_Kf88OCo?BHCtwe*&fu&8PQ(R5&lnYo8%+U73U)Ec2&|A)Y~m7(^bh299REPe zn#gyaJ4%o4>diN3z%P5&_aFUmlKytY$t21WGwx;3?UC}vlxi-vdEQgsKQ;=#sJ#ll zZeytjOad$kyON4XxC}frS|Ybh`Yq!<(IrlOXP3*q86ImyV*mJyBn$m~?#xp;EplcM z+6sez%+K}Xj3$YN6{}VL;BZ7Fi|iJj-ywlR+AP8lq~mnt5p_%VmN{Sq$L^z!otu_u znVCl@FgcVXo510e@5(wnko%Pv+^r^)GRh;>#Z(|#cLnu_Y$#_xG&nvuT+~gzJsoSi zBvX`|IS~xaold!`P!h(v|=>!5gk)Q+!0R1Ge7!WpRP{*Ajz$oGG$_?Ajvz6F0X?809o`L8prsJ*+LjlGfSziO;+ zv>fyRBVx#oC0jGK8$%$>Z;0+dfn8x;kHFQ?Rpi7(Rc{Uq{63Kgs{IwLV>pDK7yX-2 zls;?`h!I9YQVVbAj7Ok1%Y+F?CJa-Jl>1x#UVL(lpzBBH4(6v0^4 z3Tf`INjml5`F_kZc5M#^J|f%7Hgxg3#o}Zwx%4l9yYG!WaYUA>+dqpRE3nw#YXIX%= ziH3iYO~jr0nP5xp*VIa#-aa;H&%>{mfAPPlh5Fc!N7^{!z$;p-p38aW{gGx z)dFS62;V;%%fKp&i@+5x=Cn7Q>H`NofJGXmNeh{sOL+Nk>bQJJBw3K*H_$}%*xJM=Kh;s#$@RBR z|75|g85da@#qT=pD777m$wI!Q8SC4Yw3(PVU53bzzGq$IdGQoFb-c_(iA_~qD|eAy z@J+2!tc{|!8fF;%6rY9`Q!Kr>MFwEH%TY0y>Q(D}xGVJM{J{aGN0drG&|1xO!Ttdw z-1^gQ&y~KS5SeslMmoA$Wv$ly={f}f9<{Gm!8ycp*D9m*5Ef{ymIq!MU01*)#J1_! zM_i4{LYButqlQ>Q#o{~W!E_#(S=hR}kIrea_67Z5{W>8PD>g$f;dTvlD=X@T$8D0;BWkle@{VTd&D5^)U>(>g(jFt4lRV6A2(Te->ooI{nk-bZ(gwgh zaH4GT^wXPBq^Gcu%xW#S#p_&x)pNla5%S5;*OG_T^PhIIw1gXP&u5c;{^S(AC*+$> z)GuVq(FT@zq9;i{*9lEsNJZ)??BbSc5vF+Kdh-kL@`(`l5tB4P!9Okin2!-T?}(w% zEpbEU67|lU#@>DppToestmu8Ce=gz=e#V+o)v)#e=N`{$MI5P0O)_fHt1@aIC_QCv=FO`Qf=Ga%^_NhqGI)xtN*^1n{ z&vgl|TrKZ3Vam@wE0p{c3xCCAl+RqFEse@r*a<3}wmJl-hoJoN<|O2zcvMRl<#BtZ z#}-bPCv&OTw`GMp&n4tutf|er`@#d~7X+);##YFSJ)BitGALu}-N*DJdCzs(cQ?I- z6u(WAKH^NUCcOtpt5QTsQRJ$}jN28ZsYx+4CrJUQ%egH zo#tMoywhR*oeIkS%}%WUAIbM`D)R6Ya&@sZvvUEM7`fR0Ga03*=qaEGq4G7-+30Ck zRkje{6A{`ebq?2BTFFYnMM$xcQbz0nEGe!s%}O)m={`075R0N9KTZ>vbv2^eml>@}722%!r#6Wto}?vNst? zs`IasBtcROZG9+%rYaZe^=5y3chDzBf>;|5sP0!sP(t^= z^~go8msT@|rp8LJ8km?4l?Hb%o10h7(ixqV65~5Y>n_zG3AMqM3UxUNj6K-FUgMT7 z*Dy2Y8Ws+%`Z*~m9P zCWQ8L^kA2$rf-S@qHow$J86t)hoU#XZ2YK~9GXVR|*`f6`0&8j|ss_Ai-x=_;Df^*&=bW$1nc{Gplm zF}VF`w)`5A;W@KM`@<9Bw_7~?_@b{Z`n_A6c1AG#h#>Z$K>gX6reEZ*bZRjCup|0# zQ{XAb`n^}2cIwLTN%5Ix`PB*H^(|5S{j?BwItu+MS`1)VW=TnUtt6{3J!WR`4b`LW z?AD#ZmoyYpL=903q3LSM=&5eNP^dwTDRD~iP=}FXgZ@2WqfdyPYl$9do?wX{RU*$S zgQ{OqXK-Yuf4+}x6P#A*la&^G2c2TC;aNNZEYuB(f25|5eYi|rd$;i0qk7^3Ri8of ziP~PVT_|4$n!~F-B1_Et<0OJZ*e+MN;5FFH`iec(lHR+O%O%_RQhvbk-NBQ+$)w{D+dlA0jxI;z|P zEKW`!X)${xzi}Ww5G&@g0akBb_F`ziv$u^hs0W&FXuz=Ap>SUMw9=M?X$`lgPRq11 zqq+n44qL;pgGO+*DEc+Euv*j(#%;>p)yqdl`dT+Og zZH?FXXt`<0XL2@PWYp|7DWzFqxLK)yDXae&3P*#+f+E{I&h=$UPj;ey9b`H?qe*Oj zV|-qgI~v%&oh7rzICXfZmg$8$B|zkjliQ=e4jFgYCLR%yi!9gc7>N z&5G#KG&Hr+UEfB;M(M>$Eh}P$)<_IqC_WKOhO4(cY@Gn4XF(#aENkp&D{sMQgrhDT zXClOHrr9|POHqlmm+*L6CK=OENXbZ+kb}t>oRHE2xVW<;VKR@ykYq04LM9L-b;eo& zl!QQo!Sw{_$-qosixZJWhciN>Gbe8|vEVV2l)`#5vKyrXc6E`zmH(76nGRdL)pqLb@j<&&b!qJRLf>d`rdz}^ZSm7E;+XUJ ziy;xY&>LM?MA^v0Fu8{7hvh_ynOls6CI;kQkS2g^OZr70A}PU;i^~b_hUYN1*j-DD zn$lHQG9(lh&sDii)ip*{;Sb_-Anluh`=l~qhqbI+;=ZzpFrRp&T+UICO!OoqX@Xr_ z32iJ`xSpx=lDDB_IG}k+GTYG@K8{rhTS)aoN8D~Xfe?ul&;jv^E;w$nhu-ICs&Q)% zZ=~kPNZP0-A$pB8)!`TEqE`tY3Mx^`%O`?EDiWsZpoP`e-iQ#E>fIyUx8XN0L z@S-NQwc;0HjSZKWDL}Au_Zkbh!juuB&mGL0=nO5)tUd_4scpPy&O7SNS^aRxUy0^< zX}j*jPrLP4Pa0|PL+nrbd4G;YCxCK-=G7TG?dby~``AIHwxqFu^OJhyIUJkO0O<>_ zcpvg5Fk$Wpj}YE3;GxRK67P_Z@1V#+pu>pRj0!mFf(m_WR3w3*oQy$s39~U7Cb}p(N&8SEwt+)@%o-kW9Ck=^?tvC2$b9% ze9(Jn+H`;uAJE|;$Flha?!*lJ0@lKfZM>B|c)3lIAHb;5OEOT(2453m!LgH2AX=jK zQ93An1-#l@I@mwB#pLc;M7=u6V5IgLl>E%gvE|}Hvd4-bE1>gs(P^C}gTv*&t>W#+ zASLRX$y^DD3Jrht zwyt`yuA1j(TcP*0p*Xkv>gh+YTLrcN_HuaRMso~0AJg`^nL#52dGBzY+_7i)Ud#X) zVwg;6$WV20U2uyKt8<)jN#^1>PLg`I`@Mmut*Zy!c!zshSA!e^tWVoKJD%jN&ml#{ z@}B$j=U5J_#rc%T7(DGKF+WwIblEZ;Vq;CsG~OKxhWYGJx#g7fxb-_ya*D0=_Ys#f zhXktl=Vnw#Z_neW>Xe#EXT(4sT^3p6srKby4Ma5LLfh6XrHGFGgM;5Z}jv-T!f~=jT&n>Rk z4U0RT-#2fsYCQhwtW&wNp6T(im4dq>363H^ivz#>Sj;TEKY<)dOQU=g=XsLZhnR>e zd}@p1B;hMsL~QH2Wq>9Zb; zK`0`09fzuYg9MLJe~cdMS6oxoAD{kW3sFAqDxvFM#{GpP^NU@9$d5;w^WgLYknCTN z0)N425mjsJTI@#2kG-kB!({*+S(WZ-{SckG5^OiyP%(6DpRsx60$H8M$V65a_>oME z^T~>oG7r!ew>Y)&^MOBrgc-3PezgTZ2xIhXv%ExMFgSf5dQbD=Kj*!J4k^Xx!Z>AW ziZfvqJvtm|EXYsD%A|;>m1Md}j5f2>kt*gngL=enh<>#5iud0dS1P%u2o+>VQ{U%(nQ_WTySY(s#~~> zrTsvp{lTSup_7*Xq@qgjY@1#bisPCRMMHnOL48qi*jQ0xg~TSW%KMG9zN1(tjXix()2$N}}K$AJ@GUth+AyIhH6Aeh7qDgt#t*`iF5#A&g4+ zWr0$h9Zx6&Uo2!Ztcok($F>4NA<`dS&Js%L+67FT@WmI)z#fF~S75TUut%V($oUHw z$IJsL0X$KfGPZYjB9jaj-LaoDD$OMY4QxuQ&vOGo?-*9@O!Nj>QBSA6n$Lx|^ zky)4+sy{#6)FRqRt6nM9j2Lzba!U;aL%ZcG&ki1=3gFx6(&A3J-oo|S2_`*w9zT)W z4MBOVCp}?4nY)1))SOX#6Zu0fQQ7V{RJq{H)S#;sElY)S)lXTVyUXTepu4N)n85Xo zIpWPT&rgnw$D2Fsut#Xf-hO&6uA0n~a;a3!=_!Tq^TdGE&<*c?1b|PovU}3tfiIUu z){4W|@PY}zJOXkGviCw^x27%K_Fm9GuKVpd{P2>NJlnk^I|h2XW0IO~LTMj>2<;S* zZh2uRNSdJM$U$@=`zz}%;ucRx{aKVxxF7?0hdKh6&GxO6f`l2kFncS3xu0Ly{ew0& zeEP*#lk-8-B$LD(5yj>YFJ{yf5zb41PlW7S{D9zC4Aa4nVdkDNH{UsFJp)q-`9OYt zbOKkigbmm5hF?tttn;S4g^142AF^`kiLUC?e7=*JH%Qe>uW=dB24NQa`;lm5yL>Dyh@HbHy-f%6Vz^ zh&MgwYsh(z#_fhhqY$3*f>Ha}*^cU-r4uTHaT?)~LUj5``FcS46oyoI5F3ZRizVD% zPFY(_S&5GN8$Nl2=+YO6j4d|M6O7CmUyS&}m4LSn6}J`$M0ZzT&Ome)ZbJDFvM&}A zZdhDn(*viM-JHf84$!I(8eakl#zRjJH4qfw8=60 z11Ely^FyXjVvtv48-Fae7p=adlt9_F^j5#ZDf7)n!#j?{W?@j$Pi=k`>Ii>XxrJ?$ z^bhh|X6qC8d{NS4rX5P!%jXy=>(P+r9?W(2)|(=a^s^l~x*^$Enw$~u%WRuRHHFan{X|S;FD(Mr z@r@h^@Bs#C3G;~IJMrERd+D!o?HmFX&#i|~q(7QR3f8QDip?ms6|GV_$86aDb|5pc?_-jo6vmWqYi{P#?{m_AesA4xX zi&ki&lh0yvf*Yw~@jt|r-=zpj!bw<6zI3Aa^Wq{|*WEC}I=O!Re!l~&8|Vu<$yZ1p zs-SlwJD8K!$(WWyhZ+sOqa8cciwvyh%zd`r$u;;fsHn!hub0VU)bUv^QH?x30#;tH zTc_VbZj|prj7)d%ORU;Vs{#ERb>K8>GOLSImnF7JhR|g$7FQTU{(a7RHQ*ii-{U3X z^7+vM0R$8b3k1aSU&kxvVPfOz3~)0O2iTYinV9_5{pF18j4b{o`=@AZIOAwwedB2@ ztXI1F04mg{<>a-gdFoRjq$6#FaevDn$^06L)k%wYq03&ysdXE+LL1#w$rRS1Y;BoS zH1x}{ms>LHWmdtP(ydD!aRdAa(d@csEo z0EF9L>%tppp`CZ2)jVb8AuoYyu;d^wfje6^n6`A?6$&%$p>HcE_De-Zh)%3o5)LDa zskQ}%o7?bg$xUj|n8gN9YB)z!N&-K&!_hVQ?#SFj+MpQA4@4oq!UQ$Vm3B`W_Pq3J z=ngFP4h_y=`Iar<`EESF9){%YZVyJqLPGq07TP7&fSDmnYs2NZQKiR%>){imTBJth zPHr@p>8b+N@~%43rSeNuOz;rgEm?14hNtI|KC6Xz1d?|2J`QS#`OW7gTF_;TPPxu@ z)9J9>3Lx*bc>Ielg|F3cou$O0+<b34_*ZJhpS&$8DP>s%47a)4ZLw`|>s=P_J4u z?I_%AvR_z8of@UYWJV?~c4Yb|A!9n!LEUE6{sn@9+D=0w_-`szJ_T++x3MN$v-)0d zy`?1QG}C^KiNlnJBRZBLr4G~15V3$QqC%1G5b#CEB0VTr#z?Ug%Jyv@a`QqAYUV~^ zw)d|%0g&kl{j#FMdf$cn(~L@8s~6eQ)6{`ik(RI(o9s0g30Li{4YoxcVoYd+LpeLz zai?~r)UcbYr@lv*Z>E%BsvTNd`Sc?}*}>mzJ|cr0Y(6rA7H_6&t>F{{mJ^xovc2a@ zFGGDUcGgI-z6H#o@Gj29C=Uy{wv zQHY2`HZu8+sBQK*_~I-_>fOTKEAQ8_Q~YE$c?cSCxI;vs-JGO`RS464Ft06rpjn+a zqRS0Y3oN(9HCP@{J4mOWqIyD8PirA!pgU^Ne{LHBG;S*bZpx3|JyQDGO&(;Im8!ed zNdpE&?3U?E@O~>`@B;oY>#?gXEDl3pE@J30R1;?QNNxZ?YePc)3=NS>!STCrXu*lM z69WkLB_RBwb1^-zEm*tkcHz3H;?v z;q+x0Jg$|?5;e1-kbJnuT+^$bWnYc~1qnyVTKh*cvM+8yJT-HBs1X@cD;L$su65;i z2c1MxyL~NuZ9+)hF=^-#;dS#lFy^Idcb>AEDXu1!G4Kd8YPy~0lZz$2gbv?su}Zn} zGtIbeYz3X8OA9{sT(aleold_?UEV{hWRl(@)NH6GFH@$<8hUt=dNte%e#Jc>7u9xi zuqv!CRE@!fmZZ}3&@$D>p0z=*dfQ_=IE4bG0hLmT@OP>x$e`qaqf_=#baJ8XPtOpWi%$ep1Y)o2(sR=v)M zt(z*pGS$Z#j_xq_lnCr+x9fwiT?h{NEn#iK(o)G&Xw-#DK?=Ms6T;%&EE${Gq_%99 z6(;P~jPKq9llc+cmI(MKQ6*7PcL)BmoI}MYFO)b3-{j>9FhNdXLR<^mnMP`I7z0v` zj3wxcXAqi4Z0kpeSf>?V_+D}NULgU$DBvZ^=0G8Bypd7P2>;u`yW9`%4~&tzNJpgp zqB+iLIM~IkB;ts!)exn643mAJ8-WlgFE%Rpq!UMYtB?$5QAMm)%PT0$$2{>Yu7&U@ zh}gD^Qdgu){y3ANdB5{75P;lRxSJPSpQPMJOiwmpMdT|?=q;&$aTt|dl~kvS z+*i;6cEQJ1V`R4Fd>-Uzsc=DPQ7A7#VPCIf!R!KK%LM&G%MoZ0{-8&99H!|UW$Ejv zhDLX3ESS6CgWTm#1ZeS2HJb`=UM^gsQ84dQpX(ESWSkjn>O zVxg%`@mh(X9&&wN$lDIc*@>rf?C0AD_mge3f2KkT6kGySOhXqZjtA?5z`vKl_{(5g z&%Y~9p?_DL{+q@siT~*3Q*$nWXQfNN;%s_eHP_A;O`N`SaoB z6xYR;z_;HQ2xAa9xKgx~2f2xEKiEDpGPH1d@||v#f#_Ty6_gY>^oZ#xac?pc-F`@ z*}8sPV@xiz?efDMcmmezYVw~qw=vT;G1xh+xRVBkmN66!u(mRG3G6P#v|;w@anEh7 zCf94arw%YB*=&3=RTqX?z4mID$W*^+&d6qI*LA-yGme;F9+wTsNXNaX~zl2+qIK&D-aeN4lr0+yP;W>|Dh?ms_ogT{DT+ ztXFy*R7j4IX;w@@R9Oct5k2M%&j=c_rWvoul+` z<18FH5D@i$P38W9VU2(EnEvlJ(SHCqTNBa)brkIjGP|jCnK&Qi%97tikU}Y#3L?s! z2ujL%YiHO-#!|g5066V01hgT#>fzls7P>+%D~ogOT&!Whb4iF=CnCto82Yb#b`YoVsj zS2q^W0Rj!RrM@=_GuPQy5*_X@Zmu`TKSbqEOP@;Ga&Rrr>#H@L41@ZX)LAkbo{G8+ z;!5EH6vv-ip0`tLB)xUuOX(*YEDSWf?PIxXe`+_B8=KH#HFCfthu}QJylPMTNmoV; zC63g%?57(&osaH^sxCyI-+gwVB|Xs2TOf=mgUAq?V~N_5!4A=b{AXbDae+yABuuu3B_XSa4~c z1s-OW>!cIkjwJf4ZhvT|*IKaRTU)WAK=G|H#B5#NB9<{*kt?7`+G*-^<)7$Iup@Um z7u*ABkG3F*Foj)W9-I&@BrN8(#$7Hdi`BU#SR1Uz4rh&=Ey!b76Qo?RqBJ!U+rh(1 znw@xw5$)4D8OWtB_^pJO*d~2Mb-f~>I!U#*=Eh*xa6$LX?4Evp4%;ENQR!mF4`f7F zpG!NX=qnCwE8@NAbQV`*?!v0;NJ(| zBip8}VgFVsXFqslXUV>_Z>1gmD(7p#=WACXaB|Y`=Kxa=p@_ALsL&yAJ`*QW^`2@% zW7~Yp(Q@ihmkf{vMF?kqkY%SwG^t&CtfRWZ{syK@W$#DzegcQ1>~r7foTw3^V1)f2Tq_5f$igmfch;8 zT-<)?RKcCdQh6x^mMEOS;4IpQ@F2q-4IC4%*dU@jfHR4UdG>Usw4;7ESpORL|2^#jd+@zxz{(|RV*1WKrw-)ln*8LnxVkKDfGDHA%7`HaiuvhMu%*mY9*Ya{Ti#{DW?i0 zXXsp+Bb(_~wv(3t70QU3a$*<$1&zm1t++x#wDLCRI4K)kU?Vm9n2c0m@TyUV&&l9%}fulj!Z9)&@yIcQ3gX}l0b1LbIh4S z5C*IDrYxR%qm4LVzSk{0;*npO_SocYWbkAjA6(^IAwUnoAzw_Uo}xYFo?Y<-4Zqec z&k7HtVlFGyt_pA&kX%P8PaRD8y!Wsnv}NMLNLy-CHZf(ObmzV|t-iC#@Z9*d-zUsx zxcYWw{H)nYXVdnJu5o-U+fn~W z-$h1ax>h{NlWLA7;;6TcQHA>UJB$KNk74T1xNWh9)kwK~wX0m|Jo_Z;g;>^E4-k4R zRj#pQb-Hg&dAh}*=2;JY*aiNZzT=IU&v|lQY%Q|=^V5pvTR7^t9+@+ST&sr!J1Y9a z514dYZn5rg6@4Cy6P`-?!3Y& z?B*5zw!mTiD2)>f@3XYrW^9V-@%YFkE_;PCyCJ7*?_3cR%tHng9%ZpIU}LJM=a+0s z(SDDLvcVa~b9O!cVL8)Q{d^R^(bbG=Ia$)dVN_tGMee3PMssZ7Z;c^Vg_1CjZYTnq z)wnF8?=-MmqVOMX!iE?YDvHCN?%TQtKJMFHp$~kX4}jZ;EDqP$?jqJZjoa2PM@$uZ zF4}iab1b5ep)L;jdegC3{K4VnCH#OV;pRcSa(&Nm50ze-yZ8*cGv;@+N+A?ncc^2z9~|(xFhwOHmPW@ zR5&)E^YKQj@`g=;zJ_+CLamsPuvppUr$G1#9urUj+p-mPW_QSSHkPMS!52t>Hqy|g z_@Yu3z%|wE=uYq8G>4`Q!4zivS}+}{m5Zjr7kMRGn_p&hNf|pc&f9iQ`^%78rl#~8 z;os@rpMA{ZioY~(Rm!Wf#Wx##A0PthOI341QiJ=G*#}pDAkDm+{0kz&*NB?rC0-)glB{0_Tq*^o zVS1>3REsv*Qb;qg!G^9;VoK)P*?f<*H&4Su1=}bP^Y<2PwFpoqw#up4IgX3L z`w~8jsFCI3k~Y9g(Y9Km`y$0FS5vHb)kb)Jb6q-9MbO{Hbb zxg?IWQ1ZIGgE}wKm{axO6CCh~4DyoFU+i1xn#oyfe+<{>=^B5tm!!*1M?AW8c=6g+%2Ft97_Hq&ZmOGvqGQ!Bn<_Vw`0DRuDoB6q8ME<;oL4kocr8E$NGoLI zXWmI7Af-DR|KJw!vKp2SI4W*x%A%5BgDu%8%Iato+pWo5`vH@!XqC!yK}KLzvfS(q z{!y(S-PKbk!qHsgVyxKsQWk_8HUSSmslUA9nWOjkKn0%cwn%yxnkfxn?Y2rysXKS=t-TeI%DN$sQ{lcD!(s>(4y#CSxZ4R} zFDI^HPC_l?uh_)-^ppeYRkPTPu~V^0Mt}#jrTL1Q(M;qVt4zb(L|J~sxx7Lva9`mh zz!#A9tA*6?q)xThc7(gB2Ryam$YG4qlh00c}r&$y6u zIN#Qxn{7RKJ+_r|1G1KEv!&uKfXpOVZ8tK{M775ws%nDyoZ?bi3NufNbZs)zqXiqc zqOsK@^OnlFMAT&mO3`@3nZP$3lLF;ds|;Z{W(Q-STa2>;)tjhR17OD|G>Q#zJHb*> zMO<{WIgB%_4MG0SQi2;%f0J8l_FH)Lfaa>*GLobD#AeMttYh4Yfg22@q4|Itq};NB z8;o*+@APqy@fPgrc&PTbGEwdEK=(x5K!If@R$NiO^7{#j9{~w=RBG)ZkbOw@$7Nhl zyp{*&QoVBd5lo{iwl2gfyip@}IirZK;ia(&ozNl!-EEYc=QpYH_= zJkv7gA{!n4up6$CrzDJIBAdC7D5D<_VLH*;OYN>_Dx3AT`K4Wyx8Tm{I+xplKP6k7 z2sb!i7)~%R#J0$|hK?~=u~rnH7HCUpsQJujDDE*GD`qrWWog+C+E~GGy|Hp_t4--} zrxtrgnPh}r=9o}P6jpAQuDN}I*GI`8&%Lp-C0IOJt#op)}XSr!ova@w{jG2V=?GXl3zEJJFXg)U3N>BQP z*Lb@%Mx|Tu;|u>$-K(q^-HG!EQ3o93%w(A7@ngGU)HRWoO&&^}U$5x+T&#zri>6ct zXOB#EF-;z3j311K`jrYyv6pOPF=*`SOz!ack=DuEi({UnAkL5H)@R?YbRKAeP|06U z?-Ns0ZxD0h9D8)P66Sq$w-yF+1hEVTaul%&=kKDrQtF<$RnQPZ)ezm1`aHIjAY=!S z`%vboP`?7mItgEo4w50C*}Ycqp9_3ZEr^F1;cEhkb`BNhbc6PvnXu@wi=AoezF4~K zkxx%ps<8zb=wJ+9I8o#do)&{(=yAlNdduaDn!=xGSiuo~fLw~Edw$6;l-qaq#Z7?# zGrdU(Cf-V@$x>O%yRc6!C1Vf`b19ly;=mEu8u9|zitcG^O`lbNh}k=$%a)UHhDwTEKis2yc4rBGR>l*(B$AC7ung&ssaZGkY-h(fpwcPyJSx*9EIJMRKbMP9}$nVrh6$g-Q^5Cw)BeWqb-qi#37ZXKL!GR;ql)~ z@PP*-oP?T|ThqlGKR84zi^CN z4TZ1A)7vL>ivoL2EU_~xl-P{p+sE}9CRwGJDKy{>0KP+gj`H9C+4fUMPnIB1_D`A- z$1`G}g0lQmqMN{Y&8R*$xYUB*V}dQPxGVZQ+rH!DVohIoTbh%#z#Tru%Px@C<=|og zGDDwGq7yz`%^?r~6t&>x*^We^tZ4!E4dhwsht#Pb1kCY{q#Kv;z%Dp#Dq;$vH$-(9 z8S5tutZ}&JM2Iw&Y-7KY4h5BBvS=Ove0#+H2qPdR)WyI zYcj)vB=MA{7T|3Ij_PN@FM@w(C9ANBq&|NoW30ccr~i#)EcH)T^3St~rJ0HKKd4wr z@_+132;Bj+>UC@h)Ap*8B4r5A1lZ!Dh%H7&&hBnlFj@eayk=VD*i5AQc z$uN8YG#PL;cuQa)Hyt-}R?&NAE1QT>svJDKt*)AQOZAJ@ zyxJoBebiobHeFlcLwu_iI&NEZuipnOR;Tn;PbT1Mt-#5v5b*8ULo7m)L-eti=UcGf zRZXidmxeFgY!y80-*PH-*=(-W+fK%KyUKpg$X@tuv``tXj^*4qq@UkW$ZrAo%+hay zU@a?z&2_@y)o@D!_g>NVxFBO!EyB&6Z!nd4=KyDP^hl!*(k{dEF6@NkXztO7gIh zQ&PC+p-8WBv;N(rpfKdF^@Z~|E6pa)M1NBUrCZvLRW$%N%xIbv^uv?=C!=dDVq3%* zgvbEBnG*JB*@vXx8>)7XL*!{1Jh=#2UrByF7U?Rj_}VYw88BwqefT_cCTv8aTrRVjnn z1HNCF=44?*&gs2`vCGJVHX@kO z240eo#z+FhI0=yy6NHQwZs}a+J~4U-6X`@ zZ7j+tb##m`x%J66$a9qXDHG&^kp|GkFFMmjD(Y-k_ClY~N$H|n@NkSDz=gg?*2ga5 z)+f)MEY>2Lp15;~o`t`qj;S>BaE;%dv@Ux11yq}I(k|o&`5UZFUHn}1kE^gIK@qV& z!S2IhyU;->VfA4Qb}m7YnkIa9%z{l~iPWo2YPk-`hy2-Eg=6E$21plQA5W2qMZDFU z-a-@Dndf%#on6chT`dOKnU9}BJo|kJwgGC<^nfo34zOKH96LbWY7@Wc%EoFF=}`VU zksP@wd%@W;-p!e^&-)N7#oR331Q)@9cx=mOoU?_Kih2!Le*8fhsZ8Qvo6t2vt+UOZ zw|mCB*t2%z21YqL>whu!j?s~}-L`OS+jdg1(XnmYw$rg~r(?5Y+qTg`$F}q3J?GtL z@BN&8#`u2RqkdG4yGGTus@7U_%{6C{XAhFE!2SelH?KtMtX@B1GBhEIDL-Bj#~{4! zd}p7!#XE9Lt;sy@p5#Wj*jf8zGv6tTotCR2X$EVOOup;GnRPRVU5A6N@Lh8?eA7k? zn~hz&gY;B0ybSpF?qwQ|sv_yO=8}zeg2$0n3A8KpE@q26)?707pPw?H76lCpjp=5r z6jjp|auXJDnW}uLb6d7rsxekbET9(=zdTqC8(F5@NNqII2+~yB;X5iJNQSiv`#ozm zf&p!;>8xAlwoxUC3DQ#!31ylK%VrcwS<$WeCY4V63V!|221oj+5#r}fGFQ}|uwC0) zNl8(CF}PD`&Sj+p{d!B&&JtC+VuH z#>US`)YQrhb6lIAYb08H22y(?)&L8MIQsA{26X`R5Km{YU)s!x(&gIsjDvq63@X`{ z=7{SiH*_ZsPME#t2m|bS76Uz*z{cpp1m|s}HIX}Ntx#v7Eo!1%G9__4dGSGl`p+xi zZ!VK#Qe;Re=9bqXuW+0DSP{uZ5-QXrNn-7qW19K0qU}OhVru7}3vqsG?#D67 zb}crN;QwsH*vymw(maZr_o|w&@sQki(X+D)gc5Bt&@iXisFG;eH@5d43~Wxq|HO(@ zV-rip4n#PEkHCWCa5d?@cQp^B;I-PzOfag|t-cuvTapQ@MWLmh*41NH`<+A+JGyKX zyYL6Ba7qqa5j@3lOk~`OMO7f0!@FaOeZxkbG@vXP(t3#U*fq8=GAPqUAS>vW2uxMk{a(<0=IxB;# zMW;M+owrHaZBp`3{e@7gJCHP!I(EeyGFF;pdFPdeP+KphrulPSVidmg#!@W`GpD&d z9p6R`dpjaR2E1Eg)Ws{BVCBU9-aCgN57N~uLvQZH`@T+2eOBD%73rr&sV~m#2~IZx zY_8f8O;XLu2~E3JDXnGhFvsyb^>*!D>5EtlKPe%kOLv6*@=Jpci`8h0z?+fbBUg_7 zu6DjqO=$SjAv{|Om5)nz41ZkS4E_|fk%NDY509VV5yNeo%O|sb>7C#wj8mL9cEOFh z>nDz%?vb!h*!0dHdnxDA>97~EoT~!N40>+)G2CeYdOvJr5^VnkGz)et&T9hrD(VAgCAJjQ7V$O?csICB*HFd^k@$M5*v$PZJD-OVL?Ze(U=XGqZPVG8JQ z<~ukO%&%nNXYaaRibq#B1KfW4+XMliC*Tng2G(T1VvP;2K~;b$EAqthc${gjn_P!b zs62UT(->A>!ot}cJXMZHuy)^qfqW~xO-In2);e>Ta{LD6VG2u&UT&a@>r-;4<)cJ9 zjpQThb4^CY)Ev0KR7TBuT#-v}W?Xzj{c7$S5_zJA57Qf=$4^npEjl9clH0=jWO8sX z3Fuu0@S!WY>0XX7arjH`?)I<%2|8HfL!~#c+&!ZVmhbh`wbzy0Ux|Jpy9A{_7GGB0 zadZ48dW0oUwUAHl%|E-Q{gA{z6TXsvU#Hj09<7i)d}wa+Iya)S$CVwG{4LqtB>w%S zKZx(QbV7J9pYt`W4+0~f{hoo5ZG<0O&&5L57oF%hc0xGJ@Zrg_D&lNO=-I^0y#3mxCSZFxN2-tN_mU@7<@PnWG?L5OSqkm8TR!`| zRcTeWH~0z1JY^%!N<(TtxSP5^G9*Vw1wub`tC-F`=U)&sJVfvmh#Pi`*44kSdG};1 zJbHOmy4Ot|%_?@$N?RA9fF?|CywR8Sf(SCN_luM8>(u0NSEbKUy7C(Sk&OuWffj)f za`+mo+kM_8OLuCUiA*CNE|?jra$M=$F3t+h-)?pXz&r^F!ck;r##`)i)t?AWq-9A9 zSY{m~TC1w>HdEaiR*%j)L);H{IULw)uxDO>#+WcBUe^HU)~L|9#0D<*Ld459xTyew zbh5vCg$a>`RCVk)#~ByCv@Ce!nm<#EW|9j><#jQ8JfTmK#~jJ&o0Fs9jz0Ux{svdM4__<1 zrb>H(qBO;v(pXPf5_?XDq!*3KW^4>(XTo=6O2MJdM^N4IIcYn1sZZpnmMAEdt}4SU zPO54j2d|(xJtQ9EX-YrlXU1}6*h{zjn`in-N!Ls}IJsG@X&lfycsoCemt_Ym(PXhv zc*QTnkNIV=Ia%tg%pwJtT^+`v8ng>;2~ps~wdqZSNI7+}-3r+#r6p`8*G;~bVFzg= z!S3&y)#iNSUF6z;%o)%h!ORhE?CUs%g(k2a-d576uOP2@QwG-6LT*G!I$JQLpd`cz z-2=Brr_+z96a0*aIhY2%0(Sz=|D`_v_7h%Yqbw2)8@1DwH4s*A82krEk{ zoa`LbCdS)R?egRWNeHV8KJG0Ypy!#}kslun?67}^+J&02!D??lN~t@;h?GS8#WX`)6yC**~5YNhN_Hj}YG<%2ao^bpD8RpgV|V|GQwlL27B zEuah|)%m1s8C6>FLY0DFe9Ob66fo&b8%iUN=y_Qj;t3WGlNqP9^d#75ftCPA*R4E8 z)SWKBKkEzTr4JqRMEs`)0;x8C35yRAV++n(Cm5++?WB@ya=l8pFL`N0ag`lWhrYo3 zJJ$< zQ*_YAqIGR*;`VzAEx1Pd4b3_oWtdcs7LU2#1#Ls>Ynvd8k^M{Ef?8`RxA3!Th-?ui{_WJvhzY4FiPxA?E4+NFmaC-Uh*a zeLKkkECqy>Qx&1xxEhh8SzMML=8VP}?b*sgT9ypBLF)Zh#w&JzP>ymrM?nnvt!@$2 zh>N$Q>mbPAC2kNd&ab;FkBJ}39s*TYY0=@e?N7GX>wqaM>P=Y12lciUmve_jMF0lY zBfI3U2{33vWo(DiSOc}!5##TDr|dgX1Uojq9!vW3$m#zM_83EGsP6&O`@v-PDdO3P z>#!BEbqpOXd5s?QNnN!p+92SHy{sdpePXHL{d@c6UilT<#~I!tH$S(~o}c#(j<2%! zQvm}MvAj-95Ekx3D4+|e%!?lO(F+DFw9bxb-}rsWQl)b44###eUg4N?N-P(sFH2hF z`{zu?LmAxn2=2wCE8?;%ZDi#Y;Fzp+RnY8fWlzVz_*PDO6?Je&aEmuS>=uCXgdP6r zoc_JB^TA~rU5*geh{G*gl%_HnISMS~^@{@KVC;(aL^ZA-De+1zwUSXgT>OY)W?d6~ z72znET0m`53q%AVUcGraYxIcAB?OZA8AT!uK8jU+=t;WneL~|IeQ>$*dWa#x%rB(+ z5?xEkZ&b{HsZ4Ju9TQ|)c_SIp`7r2qMJgaglfSBHhl)QO1aNtkGr0LUn{@mvAt=}nd7#>7ru}&I)FNsa*x?Oe3-4G`HcaR zJ}c%iKlwh`x)yX1vBB;-Nr=7>$~(u=AuPX2#&Eh~IeFw%afU+U)td0KC!pHd zyn+X$L|(H3uNit-bpn7%G%{&LsAaEfEsD?yM<;U2}WtD4KuVKuX=ec9X zIe*ibp1?$gPL7<0uj*vmj2lWKe`U(f9E{KVbr&q*RsO;O>K{i-7W)8KG5~~uS++56 zm@XGrX@x+lGEjDQJp~XCkEyJG5Y57omJhGN{^2z5lj-()PVR&wWnDk2M?n_TYR(gM zw4kQ|+i}3z6YZq8gVUN}KiYre^sL{ynS}o{z$s&I z{(rWaLXxcQ=MB(Cz7W$??Tn*$1y(7XX)tv;I-{7F$fPB%6YC7>-Dk#=Y8o1=&|>t5 zV_VVts>Eb@)&4%m}!K*WfLoLl|3FW)V~E1Z!yu`Sn+bAP5sRDyu7NEbLt?khAyz-ZyL-}MYb&nQ zU16f@q7E1rh!)d%f^tTHE3cVoa%Xs%rKFc|temN1sa)aSlT*)*4k?Z>b3NP(IRXfq zlB^#G6BDA1%t9^Nw1BD>lBV(0XW5c?l%vyB3)q*;Z5V~SU;HkN;1kA3Nx!$!9wti= zB8>n`gt;VlBt%5xmDxjfl0>`K$fTU-C6_Z;!A_liu0@Os5reMLNk;jrlVF^FbLETI zW+Z_5m|ozNBn7AaQ<&7zk}(jmEdCsPgmo%^GXo>YYt82n&7I-uQ%A;k{nS~VYGDTn zlr3}HbWQG6xu8+bFu^9%%^PYCbkLf=*J|hr>Sw+#l(Y#ZGKDufa#f-f0k-{-XOb4i zwVG1Oa0L2+&(u$S7TvedS<1m45*>a~5tuOZ;3x%!f``{=2QQlJk|b4>NpD4&L+xI+ z+}S(m3}|8|Vv(KYAGyZK5x*sgwOOJklN0jsq|BomM>OuRDVFf_?cMq%B*iQ*&|vS9 zVH7Kh)SjrCBv+FYAE=$0V&NIW=xP>d-s7@wM*sdfjVx6-Y@=~>rz%2L*rKp|*WXIz z*vR^4tV&7MQpS9%{9b*>E9d_ls|toL7J|;srnW{l-}1gP_Qr-bBHt=}PL@WlE|&KH zCUmDLZb%J$ZzNii-5VeygOM?K8e$EcK=z-hIk63o4y63^_*RdaitO^THC{boKstphXZ2Z+&3ToeLQUG(0Frs?b zCxB+65h7R$+LsbmL51Kc)pz_`YpGEzFEclzb=?FJ=>rJwgcp0QH-UuKRS1*yCHsO) z-8t?Zw|6t($Eh&4K+u$I7HqVJBOOFCRcmMMH};RX_b?;rnk`rz@vxT_&|6V@q0~Uk z9ax|!pA@Lwn8h7syrEtDluZ6G!;@=GL> zse#PRQrdDs=qa_v@{Wv(3YjYD0|qocDC;-F~&{oaTP?@pi$n z1L6SlmFU2~%)M^$@C(^cD!y)-2SeHo3t?u3JiN7UBa7E2 z;<+_A$V084@>&u)*C<4h7jw9joHuSpVsy8GZVT;(>lZ(RAr!;)bwM~o__Gm~exd`K zKEgh2)w?ReH&syI`~;Uo4`x4$&X+dYKI{e`dS~bQuS|p zA`P_{QLV3r$*~lb=9vR^H0AxK9_+dmHX}Y} zIV*#65%jRWem5Z($ji{!6ug$En4O*=^CiG=K zp4S?+xE|6!cn$A%XutqNEgUqYY3fw&N(Z6=@W6*bxdp~i_yz5VcgSj=lf-6X1Nz75 z^DabwZ4*70$$8NsEy@U^W67tcy7^lNbu;|kOLcJ40A%J#pZe0d#n zC{)}+p+?8*ftUlxJE*!%$`h~|KZSaCb=jpK3byAcuHk7wk@?YxkT1!|r({P*KY^`u z!hw#`5$JJZGt@nkBK_nwWA31_Q9UGvv9r-{NU<&7HHMQsq=sn@O?e~fwl20tnSBG* zO%4?Ew6`aX=I5lqmy&OkmtU}bH-+zvJ_CFy z_nw#!8Rap5Wcex#5}Ldtqhr_Z$}@jPuYljTosS1+WG+TxZ>dGeT)?ZP3#3>sf#KOG z0)s%{cEHBkS)019}-1A2kd*it>y65-C zh7J9zogM74?PU)0c0YavY7g~%j%yiWEGDb+;Ew5g5Gq@MpVFFBNOpu0x)>Yn>G6uo zKE%z1EhkG_N5$a8f6SRm(25iH#FMeaJ1^TBcBy<04ID47(1(D)q}g=_6#^V@yI?Y&@HUf z`;ojGDdsvRCoTmasXndENqfWkOw=#cV-9*QClpI03)FWcx(m5(P1DW+2-{Hr-`5M{v##Zu-i-9Cvt;V|n)1pR^y ztp3IXzHjYWqabuPqnCY9^^;adc!a%Z35VN~TzwAxq{NU&Kp35m?fw_^D{wzB}4FVXX5Zk@#={6jRh%wx|!eu@Xp;%x+{2;}!&J4X*_SvtkqE#KDIPPn@ z5BE$3uRlb>N<2A$g_cuRQM1T#5ra9u2x9pQuqF1l2#N{Q!jVJ<>HlLeVW|fN|#vqSnRr<0 zTVs=)7d`=EsJXkZLJgv~9JB&ay16xDG6v(J2eZy;U%a@EbAB-=C?PpA9@}?_Yfb&) zBpsih5m1U9Px<+2$TBJ@7s9HW>W){i&XKLZ_{1Wzh-o!l5_S+f$j^RNYo85}uVhN# zq}_mN-d=n{>fZD2Lx$Twd2)}X2ceasu91}n&BS+4U9=Y{aZCgV5# z?z_Hq-knIbgIpnkGzJz-NW*=p?3l(}y3(aPCW=A({g9CpjJfYuZ%#Tz81Y)al?!S~ z9AS5#&nzm*NF?2tCR#|D-EjBWifFR=da6hW^PHTl&km-WI9*F4o>5J{LBSieVk`KO z2(^9R(zC$@g|i3}`mK-qFZ33PD34jd_qOAFj29687wCUy>;(Hwo%Me&c=~)V$ua)V zsaM(aThQ3{TiM~;gTckp)LFvN?%TlO-;$y+YX4i`SU0hbm<})t0zZ!t1=wY&j#N>q zONEHIB^RW6D5N*cq6^+?T}$3m|L{Fe+L!rxJ=KRjlJS~|z-&CC{#CU8`}2|lo~)<| zk?Wi1;Cr;`?02-C_3^gD{|Ryhw!8i?yx5i0v5?p)9wZxSkwn z3C;pz25KR&7{|rc4H)V~y8%+6lX&KN&=^$Wqu+}}n{Y~K4XpI-#O?L=(2qncYNePX zTsB6_3`7q&e0K67=Kg7G=j#?r!j0S^w7;0?CJbB3_C4_8X*Q%F1%cmB{g%XE&|IA7 z(#?AeG{l)s_orNJp!$Q~qGrj*YnuKlV`nVdg4vkTNS~w$4d^Oc3(dxi(W5jq0e>x} z(GN1?u2%Sy;GA|B%Sk)ukr#v*UJU%(BE9X54!&KL9A^&rR%v zIdYt0&D59ggM}CKWyxGS@ z>T#})2Bk8sZMGJYFJtc>D#k0+Rrrs)2DG;(u(DB_v-sVg=GFMlSCx<&RL;BH}d6AG3VqP!JpC0Gv6f8d|+7YRC@g|=N=C2 zo>^0CE0*RW?W))S(N)}NKA)aSwsR{1*rs$(cZIs?nF9)G*bSr%%SZo^YQ|TSz={jX z4Z+(~v_>RH0(|IZ-_D_h@~p_i%k^XEi+CJVC~B zsPir zA0Jm2yIdo4`&I`hd%$Bv=Rq#-#bh{Mxb_{PN%trcf(#J3S1UKDfC1QjH2E;>wUf5= ze8tY9QSYx0J;$JUR-0ar6fuiQTCQP#P|WEq;Ez|*@d?JHu-(?*tTpGHC+=Q%H>&I> z*jC7%nJIy+HeoURWN%3X47UUusY2h7nckRxh8-)J61Zvn@j-uPA@99|y48pO)0XcW zX^d&kW^p7xsvdX?2QZ8cEUbMZ7`&n{%Bo*xgFr4&fd#tHOEboQos~xm8q&W;fqrj} z%KYnnE%R`=`+?lu-O+J9r@+$%YnqYq!SVs>xp;%Q8p^$wA~oynhnvIFp^)Z2CvcyC zIN-_3EUHW}1^VQ0;Oj>q?mkPx$Wj-i7QoXgQ!HyRh6Gj8p~gH22k&nmEqUR^)9qni{%uNeV{&0-H60C zibHZtbV=8=aX!xFvkO}T@lJ_4&ki$d+0ns3FXb+iP-VAVN`B7f-hO)jyh#4#_$XG%Txk6M<+q6D~ zi*UcgRBOoP$7P6RmaPZ2%MG}CMfs=>*~(b97V4+2qdwvwA@>U3QQAA$hiN9zi%Mq{ z*#fH57zUmi)GEefh7@`Uy7?@@=BL7cXbd{O9)*lJh*v!@ z-6}p9u0AreiGauxn7JBEa-2w&d=!*TLJ49`U@D7%2ppIh)ynMaAE2Q4dl@47cNu{9 z&3vT#pG$#%hrXzXsj=&Ss*0;W`Jo^mcy4*L8b^sSi;H{*`zW9xX2HAtQ*sO|x$c6UbRA(7*9=;D~(%wfo(Z6#s$S zuFk`dr%DfVX5KC|Af8@AIr8@OAVj=6iX!~8D_P>p7>s!Hj+X0_t}Y*T4L5V->A@Zx zcm1wN;TNq=h`5W&>z5cNA99U1lY6+!!u$ib|41VMcJk8`+kP{PEOUvc@2@fW(bh5pp6>C3T55@XlpsAd#vn~__3H;Dz2w=t9v&{v*)1m4)vX;4 zX4YAjM66?Z7kD@XX{e`f1t_ZvYyi*puSNhVPq%jeyBteaOHo7vOr8!qqp7wV;)%jtD5>}-a?xavZ;i|2P3~7c)vP2O#Fb`Y&Kce zQNr7%fr4#S)OOV-1piOf7NgQvR{lcvZ*SNbLMq(olrdDC6su;ubp5un!&oT=jVTC3uTw7|r;@&y*s)a<{J zkzG(PApmMCpMmuh6GkM_`AsBE@t~)EDcq1AJ~N@7bqyW_i!mtHGnVgBA`Dxi^P93i z5R;}AQ60wy=Q2GUnSwz+W6C^}qn`S-lY7=J(3#BlOK%pCl=|RVWhC|IDj1E#+|M{TV0vE;vMZLy7KpD1$Yk zi0!9%qy8>CyrcRK`juQ)I};r)5|_<<9x)32b3DT1M`>v^ld!yabX6@ihf`3ZVTgME zfy(l-ocFuZ(L&OM4=1N#Mrrm_<>1DZpoWTO70U8+x4r3BpqH6z@(4~sqv!A9_L}@7 z7o~;|?~s-b?ud&Wx6==9{4uTcS|0-p@dKi0y#tPm2`A!^o3fZ8Uidxq|uz2vxf;wr zM^%#9)h^R&T;}cxVI(XX7kKPEVb);AQO?cFT-ub=%lZPwxefymBk+!H!W(o(>I{jW z$h;xuNUr#^0ivvSB-YEbUqe$GLSGrU$B3q28&oA55l)ChKOrwiTyI~e*uN;^V@g-Dm4d|MK!ol8hoaSB%iOQ#i_@`EYK_9ZEjFZ8Ho7P^er z^2U6ZNQ{*hcEm?R-lK)pD_r(e=Jfe?5VkJ$2~Oq^7YjE^5(6a6Il--j@6dBHx2Ulq z!%hz{d-S~i9Eo~WvQYDt7O7*G9CP#nrKE#DtIEbe_uxptcCSmYZMqT2F}7Kw0AWWC zPjwo0IYZ6klc(h9uL|NY$;{SGm4R8Bt^^q{e#foMxfCSY^-c&IVPl|A_ru!ebwR#7 z3<4+nZL(mEsU}O9e`^XB4^*m)73hd04HH%6ok^!;4|JAENnEr~%s6W~8KWD)3MD*+ zRc46yo<}8|!|yW-+KulE86aB_T4pDgL$XyiRW(OOcnP4|2;v!m2fB7Hw-IkY#wYfF zP4w;k-RInWr4fbz=X$J;z2E8pvAuy9kLJUSl8_USi;rW`kZGF?*Ur%%(t$^{Rg!=v zg;h3@!Q$eTa7S0#APEDHLvK%RCn^o0u!xC1Y0Jg!Baht*a4mmKHy~88md{YmN#x) zBOAp_i-z2h#V~*oO-9k(BizR^l#Vm%uSa^~3337d;f=AhVp?heJ)nlZGm`}D(U^2w z#vC}o1g1h?RAV^90N|Jd@M00PoNUPyA?@HeX0P7`TKSA=*4s@R;Ulo4Ih{W^CD{c8 ze(ipN{CAXP(KHJ7UvpOc@9SUAS^wKo3h-}BDZu}-qjdNlVtp^Z{|CxKOEo?tB}-4; zEXyDzGbXttJ3V$lLo-D?HYwZm7vvwdRo}P#KVF>F|M&eJ44n*ZO~0)#0e0Vy&j00I z{%IrnUvKp70P?>~J^$^0Wo%>le>re2ZSvRfes@dC-*e=DD1-j%<$^~4^4>Id5w^Fr z{RWL>EbUCcyC%1980kOYqZAcgdz5cS8c^7%vvrc@CSPIx;X=RuodO2dxk17|am?HJ@d~Mp_l8H?T;5l0&WGFoTKM{eP!L-a0O8?w zgBPhY78tqf^+xv4#OK2I#0L-cSbEUWH2z+sDur85*!hjEhFfD!i0Eyr-RRLFEm5(n z-RV6Zf_qMxN5S6#8fr9vDL01PxzHr7wgOn%0Htmvk9*gP^Um=n^+7GLs#GmU&a#U^4jr)BkIubQO7oUG!4CneO2Ixa`e~+Jp9m{l6apL8SOqA^ zvrfEUPwnHQ8;yBt!&(hAwASmL?Axitiqvx%KZRRP?tj2521wyxN3ZD9buj4e;2y6U zw=TKh$4%tt(eh|y#*{flUJ5t4VyP*@3af`hyY^YU3LCE3Z|22iRK7M7E;1SZVHbXF zKVw!L?2bS|kl7rN4(*4h2qxyLjWG0vR@`M~QFPsf^KParmCX;Gh4OX6Uy9#4e_%oK zv1DRnfvd$pu(kUoV(MmAc09ckDiuqS$a%!AQ1Z>@DM#}-yAP$l`oV`BDYpkqpk(I|+qk!yoo$TwWr6dRzLy(c zi+qbVlYGz0XUq@;Fm3r~_p%by)S&SVWS+wS0rC9bk^3K^_@6N5|2rtF)wI>WJ=;Fz zn8$h<|Dr%kN|nciMwJAv;_%3XG9sDnO@i&pKVNEfziH_gxKy{l zo`2m4rnUT(qenuq9B0<#Iy(RPxP8R)=5~9wBku=%&EBoZ82x1GlV<>R=hIqf0PK!V zw?{z9e^B`bGyg2nH!^x}06oE%J_JLk)^QyHLipoCs2MWIqc>vaxsJj(=gg1ZSa=u{ zt}od#V;e7sA4S(V9^<^TZ#InyVBFT(V#$fvI7Q+pgsr_2X`N~8)IOZtX}e(Bn(;eF zsNj#qOF_bHl$nw5!ULY{lNx@93Fj}%R@lewUuJ*X*1$K`DNAFpE z7_lPE+!}uZ6c?+6NY1!QREg#iFy=Z!OEW}CXBd~wW|r_9%zkUPR0A3m+@Nk%4p>)F zXVut7$aOZ6`w}%+WV$te6-IX7g2yms@aLygaTlIv3=Jl#Nr}nN zp|vH-3L03#%-1-!mY`1z?+K1E>8K09G~JcxfS)%DZbteGQnQhaCGE2Y<{ut#(k-DL zh&5PLpi9x3$HM82dS!M?(Z zEsqW?dx-K_GMQu5K54pYJD=5+Rn&@bGjB?3$xgYl-|`FElp}?zP&RAd<522c$Rv6} zcM%rYClU%JB#GuS>FNb{P2q*oHy}UcQ-pZ2UlT~zXt5*k-ZalE(`p7<`0n7i(r2k{ zb84&^LA7+aW1Gx5!wK!xTbw0slM?6-i32CaOcLC2B>ZRI16d{&-$QBEu1fKF0dVU>GTP05x2>Tmdy`75Qx! z^IG;HB9V1-D5&&)zjJ&~G}VU1-x7EUlT3QgNT<&eIDUPYey$M|RD6%mVkoDe|;2`8Z+_{0&scCq>Mh3hj|E*|W3;y@{$qhu77D)QJ` znD9C1AHCKSAHQqdWBiP`-cAjq7`V%~JFES1=i-s5h6xVT<50kiAH_dn0KQB4t*=ua zz}F@mcKjhB;^7ka@WbSJFZRPeYI&JFkpJ-!B z!ju#!6IzJ;D@$Qhvz9IGY5!%TD&(db3<*sCpZ?U#1^9RWQ zs*O-)j!E85SMKtoZzE^8{w%E0R0b2lwwSJ%@E}Lou)iLmPQyO=eirG8h#o&E4~eew z;h><=|4m0$`ANTOixHQOGpksXlF0yy17E&JksB4_(vKR5s$Ve+i;gco2}^RRJI+~R zWJ82WGigLIUwP!uSELh3AAs9HmY-kz=_EL-w|9}noKE#(a;QBpEx9 z4BT-zY=6dJT>72Hkz=9J1E=}*MC;zzzUWb@x(Ho8cU_aRZ?fxse5_Ru2YOvcr?kg&pt@v;{ai7G--k$LQtoYj+Wjk+nnZty;XzANsrhoH#7=xVqfPIW(p zX5{YF+5=k4_LBnhLUZxX*O?29olfPS?u*ybhM_y z*XHUqM6OLB#lyTB`v<BZ&YRs$N)S@5Kn_b3;gjz6>fh@^j%y2-ya({>Hd@kv{CZZ2e)tva7gxLLp z`HoGW);eRtov~Ro5tetU2y72~ zQh>D`@dt@s^csdfN-*U&o*)i3c4oBufCa0e|BwT2y%Y~=U7A^ny}tx zHwA>Wm|!SCko~UN?hporyQHRUWl3djIc722EKbTIXQ6>>iC!x+cq^sUxVSj~u)dsY zW8QgfZlE*2Os%=K;_vy3wx{0u!2%A)qEG-$R^`($%AOfnA^LpkB_}Dd7AymC)zSQr z>C&N8V57)aeX8ap!|7vWaK6=-3~ko9meugAlBKYGOjc#36+KJwQKRNa_`W@7;a>ot zdRiJkz?+QgC$b}-Owzuaw3zBVLEugOp6UeMHAKo2$m4w zpw?i%Lft^UtuLI}wd4(-9Z^*lVoa}11~+0|Hs6zAgJ01`dEA&^>Ai=mr0nC%eBd_B zzgv2G_~1c1wr*q@QqVW*Wi1zn=}KCtSwLjwT>ndXE_Xa22HHL_xCDhkM( zhbw+j4uZM|r&3h=Z#YrxGo}GX`)AZyv@7#7+nd-D?BZV>thtc|3jt30j$9{aIw9)v zDY)*fsSLPQTNa&>UL^RWH(vpNXT7HBv@9=*=(Q?3#H*crA2>KYx7Ab?-(HU~a275)MBp~`P)hhzSsbj|d`aBe(L*(;zif{iFJu**ZR zkL-tPyh!#*r-JVQJq>5b0?cCy!uSKef+R=$s3iA7*k*_l&*e!$F zYwGI;=S^0)b`mP8&Ry@{R(dPfykD&?H)na^ihVS7KXkxb36TbGm%X1!QSmbV9^#>A z-%X>wljnTMU0#d;tpw?O1W@{X-k*>aOImeG z#N^x?ehaaQd}ReQykp>i;92q@%$a!y1PNyPYDIvMm& zyYVwn;+0({W@3h(r&i#FuCDE)AC(y&Vu>4?1@j0|CWnhHUx4|zL7cdaA32RSk?wl% zMK^n42@i5AU>f70(huWfOwaucbaToxj%+)7hnG^CjH|O`A}+GHZyQ-X57(WuiyRXV zPf>0N3GJ<2Myg!sE4XJY?Z7@K3ZgHy8f7CS5ton0Eq)Cp`iLROAglnsiEXpnI+S8; zZn>g2VqLxi^p8#F#Laf3<00AcT}Qh&kQnd^28u!9l1m^`lfh9+5$VNv=?(~Gl2wAl zx(w$Z2!_oESg_3Kk0hUsBJ<;OTPyL(?z6xj6LG5|Ic4II*P+_=ac7KRJZ`(k2R$L# zv|oWM@116K7r3^EL*j2ktjEEOY9c!IhnyqD&oy7+645^+@z5Y|;0+dyR2X6^%7GD* zXrbPqTO}O={ z4cGaI#DdpP;5u?lcNb($V`l>H7k7otl_jQFu1hh>=(?CTPN#IPO%O_rlVX}_Nq;L< z@YNiY>-W~&E@=EC5%o_z<^3YEw)i_c|NXxHF{=7U7Ev&C`c^0Z4-LGKXu*Hkk&Av= zG&RAv{cR7o4${k~f{F~J48Ks&o(D@j-PQ2`LL@I~b=ifx3q!p6`d>~Y!<-^mMk3)e zhi1;(YLU5KH}zzZNhl^`0HT(r`5FfmDEzxa zk&J7WQ|!v~TyDWdXQ)!AN_Y%xM*!jv^`s)A`|F%;eGg27KYsrCE2H}7*r)zvum6B{ z$k5Har9pv!dcG%f|3hE(#hFH+12RZPycVi?2y`-9I7JHryMn3 z9Y8?==_(vOAJ7PnT<0&85`_jMD0#ipta~Q3M!q5H1D@Nj-YXI$W%OQplM(GWZ5Lpq z-He6ul|3<;ZQsqs!{Y7x`FV@pOQc4|N;)qgtRe(Uf?|YqZv^$k8On7DJ5>f2%M=TV zw~x}9o=mh$JVF{v4H5Su1pq66+mhTG6?F>Do}x{V(TgFwuLfvNP^ijkrp5#s4UT!~ zEU7pr8aA)2z1zb|X9IpmJykQcqI#(rS|A4&=TtWu@g^;JCN`2kL}%+K!KlgC z>P)v+uCeI{1KZpewf>C=?N7%1e10Y3pQCZST1GT5fVyB1`q)JqCLXM zSN0qlreH1=%Zg-5`(dlfSHI&2?^SQdbEE&W4#%Eve2-EnX>NfboD<2l((>>34lE%) zS6PWibEvuBG7)KQo_`?KHSPk+2P;`}#xEs}0!;yPaTrR#j(2H|#-CbVnTt_?9aG`o z(4IPU*n>`cw2V~HM#O`Z^bv|cK|K};buJ|#{reT8R)f+P2<3$0YGh!lqx3&a_wi2Q zN^U|U$w4NP!Z>5|O)>$GjS5wqL3T8jTn%Vfg3_KnyUM{M`?bm)9oqZP&1w1)o=@+(5eUF@=P~ zk2B5AKxQ96n-6lyjh&xD!gHCzD$}OOdKQQk7LXS-fk2uy#h{ktqDo{o&>O!6%B|)` zg?|JgcH{P*5SoE3(}QyGc=@hqlB5w;bnmF#pL4iH`TSuft$dE5j^qP2S)?)@pjRQZ zBfo6g>c!|bN-Y|(Wah2o61Vd|OtXS?1`Fu&mFZ^yzUd4lgu7V|MRdGj3e#V`=mnk- zZ@LHn?@dDi=I^}R?}mZwduik!hC%=Hcl56u{Wrk1|1SxlgnzG&e7Vzh*wNM(6Y!~m z`cm8Ygc1$@z9u9=m5vs1(XXvH;q16fxyX4&e5dP-{!Kd555FD6G^sOXHyaCLka|8j zKKW^E>}>URx736WWNf?U6Dbd37Va3wQkiE;5F!quSnVKnmaIRl)b5rM_ICu4txs+w zj}nsd0I_VG^<%DMR8Zf}vh}kk;heOQTbl ziEoE;9@FBIfR7OO9y4Pwyz02OeA$n)mESpj zdd=xPwA`nO06uGGsXr4n>Cjot7m^~2X~V4yH&- zv2llS{|und45}Pm1-_W@)a-`vFBpD~>eVP(-rVHIIA|HD@%7>k8JPI-O*<7X{L*Ik zh^K`aEN!BteiRaY82FVo6<^8_22=aDIa8P&2A3V<(BQ;;x8Zs-1WuLRWjQvKv1rd2 zt%+fZ!L|ISVKT?$3iCK#7whp|1ivz1rV*R>yc5dS3kIKy_0`)n*%bfNyw%e7Uo}Mnnf>QwDgeH$X5eg_)!pI4EJjh6?kkG2oc6Af0py z(txE}$ukD|Zn=c+R`Oq;m~CSY{ebu9?!is}01sOK_mB?{lSY33E=!KkKtMeI*FO2b z%95awv9;Z|UDp3xm+aP*5I!R-_M2;GxeCRx3ATS0iF<_Do2Mi)Hk2 zjBF35VB>(oamIYjunu?g0O-?LuOvtfs5F(iiIicbu$HMPPF%F>pE@hIRjzT)>aa=m zwe;H9&+2|S!m74!E3xfO{l3E_ab`Q^tZ4yH9=~o2DUEtEMDqG=&D*8!>?2uao%w`&)THr z^>=L3HJquY>6)>dW4pCWbzrIB+>rdr{s}}cL_?#!sOPztRwPm1B=!jP7lQG|Iy6rP zVqZDNA;xaUx&xUt?Ox|;`9?oz`C0#}mc<1Urs#vTW4wd{1_r`eX=BeSV z_9WV*9mz>PH6b^z{VYQJ1nSTSqOFHE9u>cY)m`Q>=w1NzUShxcHsAxasnF2BG;NQ; zqL1tjLjImz_`q=|bAOr_i5_NEijqYZ^;d5y3ZFj6kCYakJh**N_wbfH;ICXq?-p#r z{{ljNDPSytOaG#7=yPmA&5gyYI%^7pLnMOw-RK}#*dk=@usL;|4US?{@K%7esmc&n z5$D*+l&C9)Bo@$d;Nwipd!68&+NnOj^<~vRcKLX>e03E|;to;$ndgR;9~&S-ly5gf z{rzj+j-g$;O|u?;wwxrEpD=8iFzUHQfl{B>bLHqH(9P zI59SS2PEBE;{zJUlcmf(T4DrcO?XRWR}?fekN<($1&AJTRDyW+D*2(Gyi?Qx-i}gy z&BpIO!NeVdLReO!YgdUfnT}7?5Z#~t5rMWqG+$N2n%5o#Np6ccNly}#IZQsW4?|NV zR9hrcyP(l#A+U4XcQvT;4{#i)dU>HK>aS!k1<3s2LyAhm2(!Nu%vRC9T`_yn9D+r} z1i&U~IcQ?4xhZYyH6WL-f%}qIhZkc&}n2N0PM| z6|XA9d-y;!`D{p;xu*gv7a|zaZ*MiQ)}zPzW4GB0mr)}N-DmB&hl1&x`2@sxN572_ zS)RdJyR%<7kW0v3Q_|57JKy&9tUdbqz}|hwn84}U*0r^jt6Ssrp+#1y=JBcZ+F`f(N?O0XL1OFGN`1-r?S<#t4*C9|y~e)!UYZ zRQ3M8m%~M)VriIvn~XzoP;5qeu(ZI>Y#r zAd)J)G9)*BeE%gmm&M@Olg3DI_zokjh9NvdGbT z+u4(Y&uC6tBBefIg~e=J#8i1Zxr>RT)#rGaB2C71usdsT=}mm`<#WY^6V{L*J6v&l z1^Tkr6-+^PA)yC;s1O^3Q!)Reb=fxs)P~I*?i&j{Vbb(Juc?La;cA5(H7#FKIj0Or zgV0BO{DUs`I9HgQ{-!g@5P^Vr|C4}~w6b=#`Zx0XcVSd?(04HUHwK(gJNafgQNB9Z zCi3TgNXAeJ+x|X|b@27$RxuYYuNSUBqo#uyiH6H(b~K*#!@g__4i%HP5wb<+Q7GSb zTZjJw96htUaGZ89$K_iBo4xEOJ#DT#KRu9ozu!GH0cqR>hP$nk=KXM%Y!(%vWQ#}s zy=O#BZ>xjUejMH^F39Bf0}>D}yiAh^toa-ts#gt6Mk9h1D<9_mGMBhLT0Ce2O3d_U znaTkBaxd-8XgwSp5)x-pqX5=+{cSuk6kyl@k|5DQ!5zLUVV%1X9vjY0gerbuG6nwZu5KDMdq(&UMLZ zy?jW#F6joUtVyz`Y?-#Yc0=i*htOFwQ3`hk$8oq35D}0m$FAOp#UFTV3|U3F>@N?d zeXLZCZjRC($%?dz(41e~)CN10qjh^1CdAcY(<=GMGk@`b1ptA&L*{L@_M{%Vd5b*x#b1(qh=7((<_l%ZUaHtmgq} zjchBdiis{Afxf@3CjPR09E*2#X(`W#-n`~6PcbaL_(^3tfDLk?Nb6CkW9v!v#&pWJ3iV-9hz zngp#Q`w`r~2wt&cQ9#S7z0CA^>Mzm7fpt72g<0y-KT{G~l-@L#edmjZQ}7{*$mLgSdJfS$Ge{hrD=mr;GD)uYq8}xS zT>(w_;}894Kb}(P5~FOpFIEjadhmxD(PsZbKwa-qxVa7Oc7~ebPKMeN(pCRzq8s@l z`|l^*X1eK1+Spz--WkSW_nK`Cs@JmkY4+p=U91nJoy{tSH;TzuIyS)Q_(S@;Iakua zpuDo5W54Mo;jY@Ly1dY)j|+M%$FJ0`C=FW#%UvOd&?p}0QqL20Xt!#pr8ujy6CA-2 zFz6Ex5H1i)c9&HUNwG{8K%FRK7HL$RJwvGakleLLo}tsb>t_nBCIuABNo$G--_j!gV&t8L^4N6wC|aLC)l&w04CD6Vc#h^(YH@Zs4nwUGkhc_-yt{dK zMZ<%$swLmUl8`E~RLihGt@J5v;r;vT&*Q!Cx zZ55-zpb;W7_Q{tf$mQvF61(K>kwTq0x{#Din||)B{+6O#ArLi)kiHWVC4`fOT&B(h zw&YV`J1|^FLx~9Q%r-SFhYl4PywI7sF2Q$>4o50~dfp5nn}XHv-_DM?RGs#+4gM;% znU>k=81G~f6u%^Z{bcX&sUv*h|L+|mNq=W43y@{~C zpL-TW3hYPs0^*OqS#KQwA^CGG_A-6#`_{1LBCD&*3nY0UHWJj1D|VP%oQlFxLllaA zVI@2^)HZ%E*=RbQcFOKIP7?+|_xVK+2oG(t_EGl2y;Ovox zZb^qVpe!4^reKvpIBFzx;Ji=PmrV>uu-Hb>`s?k?YZQ?>av45>i(w0V!|n?AP|v5H zm`e&Tgli#lqGEt?=(?~fy<(%#nDU`O@}Vjib6^rfE2xn;qgU6{u36j_+Km%v*2RLnGpsvS+THbZ>p(B zgb{QvqE?~50pkLP^0(`~K& zjT=2Pt2nSnwmnDFi2>;*C|OM1dY|CAZ5R|%SAuU|5KkjRM!LW_)LC*A zf{f>XaD+;rl6Y>Umr>M8y>lF+=nSxZX_-Z7lkTXyuZ(O6?UHw^q; z&$Zsm4U~}KLWz8>_{p*WQ!OgxT1JC&B&>|+LE3Z2mFNTUho<0u?@r^d=2 z-av!n8r#5M|F%l;=D=S1mGLjgFsiYAOODAR}#e^a8 zfVt$k=_o}kt3PTz?EpLkt54dY}kyd$rU zVqc9SN>0c z753j-gdN~UiW*FUDMOpYEkVzP)}{Ds*3_)ZBi)4v26MQr140|QRqhFoP=a|;C{#KS zD^9b-9HM11W+cb1Y)HAuk<^GUUo(ut!5kILBzAe)Vaxwu4Up!7Ql*#DDu z>EB84&xSrh>0jT!*X81jJQq$CRHqNj29!V3FN9DCx)~bvZbLwSlo3l^zPb1sqBnp) zfZpo|amY^H*I==3#8D%x3>zh#_SBf?r2QrD(Y@El!wa;Ja6G9Y1947P*DC|{9~nO& z*vDnnU!8(cV%HevsraF%Y%2{Z>CL0?64eu9r^t#WjW4~3uw8d}WHzsV%oq-T)Y z0-c!FWX5j1{1##?{aTeCW2b$PEnwe;t`VPCm@sQ`+$$L2=3kBR%2XU1{_|__XJ$xt zibjY2QlDVs)RgHH*kl&+jn*JqquF)k_Ypibo00lcc<2RYqsi-G%}k0r(N97H7JEn7@E3ZTH0JK>d8)E~A-D z!B&z9zJw0Bi^fgQZI%LirYaBKnWBXgc`An*qvO^*$xymqKOp(+3}IsnVhu?YnN7qz zNJxDN-JWd7-vIiv2M9ih>x3gNVY%DzzY~dCnA}76IRl!`VM=6=TYQ=o&uuE8kHqZT zoUNod0v+s9D)7aLJ|hVqL0li1hg)%&MAciI(4YJ=%D4H$fGQ&Lu-?@>>@pEgC;ERrL= zI^cS&3q8fvEGTJZgZwL5j&jp%j9U^Of6pR{wA^u=tVt#yCQepXNIbynGnuWbsC_EE zRyMFq{5DK692-*kyGy~An>AdVR9u___fzmmJ4;^s0yAGgO^h{YFmqJ%ZJ_^0BgCET zE6(B*SzeZ4pAxear^B-YW<%BK->X&Cr`g9_;qH~pCle# zdY|UB5cS<}DFRMO;&czbmV(?vzikf)Ks`d$LL801@HTP5@r><}$xp}+Ip`u_AZ~!K zT}{+R9Wkj}DtC=4QIqJok5(~0Ll&_6PPVQ`hZ+2iX1H{YjI8axG_Bw#QJy`6T>1Nn z%u^l`>XJ{^vX`L0 z1%w-ie!dE|!SP<>#c%ma9)8K4gm=!inHn2U+GR+~ zqZVoa!#aS0SP(|**WfQSe?cA=1|Jwk`UDsny%_y{@AV??N>xWekf>_IZLUEK3{Ksi zWWW$if&Go~@Oz)`#=6t_bNtD$d9FMBN#&97+XKa+K2C@I9xWgTE{?Xnhc9_KKPcujj@NprM@e|KtV_SR+ zSpeJ!1FGJ=Te6={;;+;a46-*DW*FjTnBfeuzI_=I1yk8M(}IwEIGWV0Y~wia;}^dg z{BK#G7^J`SE10z4(_Me=kF&4ld*}wpNs91%2Ute>Om`byv9qgK4VfwPj$`axsiZ)wxS4k4KTLb-d~!7I@^Jq`>?TrixHk|9 zqCX7@sWcVfNP8N;(T>>PJgsklQ#GF>F;fz_Rogh3r!dy*0qMr#>hvSua;$d z3TCZ4tlkyWPTD<=5&*bUck~J;oaIzSQ0E03_2x{?weax^jL3o`ZP#uvK{Z5^%H4b6 z%Kbp6K?>{;8>BnQy64Jy$~DN?l(ufkcs6TpaO&i~dC>0fvi-I^7YT#h?m;TVG|nba%CKRG%}3P*wejg) zI(ow&(5X3HR_xk{jrnkA-hbwxEQh|$CET9Qv6UpM+-bY?E!XVorBvHoU59;q<9$hK z%w5K-SK zWT#1OX__$ceoq0cRt>9|)v}$7{PlfwN}%Wh3rwSl;%JD|k~@IBMd5}JD#TOvp=S57 zae=J#0%+oH`-Av}a(Jqhd4h5~eG5ASOD)DfuqujI6p!;xF_GFcc;hZ9k^a7c%%h(J zhY;n&SyJWxju<+r`;pmAAWJmHDs{)V-x7(0-;E?I9FWK@Z6G+?7Py8uLc2~Fh1^0K zzC*V#P88(6U$XBjLmnahi2C!a+|4a)5Ho5>owQw$jaBm<)H2fR=-B*AI8G@@P-8I8 zHios92Q6Nk-n0;;c|WV$Q);Hu4;+y%C@3alP`cJ2{z~*m-@de%OKVgiWp;4Q)qf9n zJ!vmx(C=_>{+??w{U^Bh|LFJ<6t}Er<-Tu{C{dv8eb(kVQ4!fOuopTo!^x1OrG}0D zR{A#SrmN`=7T29bzQ}bwX8OUufW9d9T4>WY2n15=k3_rfGOp6sK0oj7(0xGaEe+-C zVuWa;hS*MB{^$=0`bWF(h|{}?53{5Wf!1M%YxVw}io4u-G2AYN|FdmhI13HvnoK zNS2fStm=?8ZpKt}v1@Dmz0FD(9pu}N@aDG3BY8y`O*xFsSz9f+Y({hFx;P_h>ER_& z`~{z?_vCNS>agYZI?ry*V96_uh;|EFc0*-x*`$f4A$*==p`TUVG;YDO+I4{gJGrj^ zn?ud(B4BlQr;NN?vaz_7{&(D9mfd z8esj=a4tR-ybJjCMtqV8>zn`r{0g$hwoWRUI3}X5=dofN){;vNoftEwX>2t@nUJro z#%7rpie2eH1sRa9i6TbBA4hLE8SBK@blOs=ouBvk{zFCYn4xY;v3QSM%y6?_+FGDn z4A;m)W?JL!gw^*tRx$gqmBXk&VU=Nh$gYp+Swu!h!+e(26(6*3Q!(!MsrMiLri`S= zKItik^R9g!0q7y$lh+L4zBc-?Fsm8`CX1+f>4GK7^X2#*H|oK}reQnT{Mm|0ar<+S zRc_dM%M?a3bC2ILD`|;6vKA`a3*N~(cjw~Xy`zhuY2s{(7KLB{S>QtR3NBQ3>vd+= z#}Q)AJr7Y_-eV(sMN#x!uGX08oE*g=grB*|bBs}%^3!RVA4f%m3=1f0K=T^}iI&2K zuM2GG5_%+#v-&V>?x4W9wQ|jE2Q7Be8mOyJtZrqn#gXy-1fF1P$C8+We&B*-pi#q5 zETp%H6g+%#sH+L4=ww?-h;MRCd2J9zwQUe4gHAbCbH08gDJY;F6F)HtWCRW1fLR;)ysGZanlz*a+|V&@(ipWdB!tz=m_0 z6F}`d$r%33bw?G*azn*}Z;UMr{z4d9j~s`0*foZkUPwpJsGgoR0aF>&@DC;$A&(av z?b|oo;`_jd>_5nye`DVOcMLr-*Nw&nA z82E8Dw^$Lpso)gEMh?N|Uc^X*NIhg=U%enuzZOGi-xcZRUZmkmq~(cP{S|*+A6P;Q zprIkJkIl51@ng)8cR6QSXJtoa$AzT@*(zN3M+6`BTO~ZMo0`9$s;pg0HE3C;&;D@q zd^0zcpT+jC%&=cYJF+j&uzX87d(gP9&kB9|-zN=69ymQS9_K@h3ph&wD5_!4q@qI@ zBMbd`2JJ2%yNX?`3(u&+nUUJLZ=|{t7^Rpw#v-pqD2_3}UEz!QazhRty%|Q~WCo7$ z+sIugHA%Lmm{lBP#bnu_>G}Ja<*6YOvSC;89z67M%iG0dagOt1HDpDn$<&H0DWxMU zxOYaaks6%R@{`l~zlZ*~2}n53mn2|O&gE+j*^ypbrtBv{xd~G(NF?Z%F3>S6+qcry z?ZdF9R*a;3lqX_!rI(Cov8ER_mOqSn6g&ZU(I|DHo7Jj`GJ}mF;T(vax`2+B8)H_D zD0I;%I?*oGD616DsC#j0x*p+ZpBfd=9gR|TvB)832CRhsW_7g&WI@zp@r7dhg}{+4f=(cO2s+)jg0x(*6|^+6W_=YIfSH0lTcK* z%)LyaOL6em@*-_u)}Swe8rU)~#zT-vNiW(D*~?Zp3NWl1y#fo!3sK-5Ek6F$F5l3| zrFFD~WHz1}WHmzzZ!n&O8rTgfytJG*7iE~0`0;HGXgWTgx@2fD`oodipOM*MOWN-} zJY-^>VMEi8v23ZlOn0NXp{7!QV3F1FY_URZjRKMcY(2PV_ms}EIC^x z=EYB5UUQ{@R~$2Mwiw$_JAcF+szKB*n(`MYpDCl>~ss54uDQ%Xf-8|dgO zY)B_qju=IaShS|XsQo=nSYxV$_vQR@hd~;qW)TEfU|BA0&-JSwO}-a*T;^}l;MgLM zz}CjPlJX|W2vCzm3oHw3vqsRc3RY=2()}iw_k2#eKf&VEP7TQ;(DDzEAUgj!z_h2Br;Z3u=K~LqM6YOrlh)v9`!n|6M-s z?XvA~y<5?WJ{+yM~uPh7uVM&g-(;IC3>uA}ud?B3F zelSyc)Nx>(?F=H88O&_70%{ATsLVTAp88F-`+|egQ7C4rpIgOf;1tU1au+D3 zlz?k$jJtTOrl&B2%}D}8d=+$NINOZjY$lb{O<;oT<zXoAp01KYG$Y4*=)!&4g|FL(!54OhR-?)DXC&VS5E|1HGk8LY;)FRJqnz zb_rV2F7=BGwHgDK&4J3{%&IK~rQx<&Kea|qEre;%A~5YD6x`mo>mdR)l?Nd%T2(5U z_ciT02-zt_*C|vn?BYDuqSFrk3R(4B0M@CRFmG{5sovIq4%8AhjXA5UwRGo)MxZlI zI%vz`v8B+#ff*XtGnciczFG}l(I}{YuCco#2E6|+5WJ|>BSDfz0oT+F z%QI^ixD|^(AN`MS6J$ zXlKNTFhb>KDkJp*4*LaZ2WWA5YR~{`={F^hwXGG*rJYQA7kx|nwnC58!eogSIvy{F zm1C#9@$LhK^Tl>&iM0wsnbG7Y^MnQ=q))MgApj4)DQt!Q5S`h+5a%c7M!m%)?+h65 z0NHDiEM^`W+M4)=q^#sk(g!GTpB}edwIe>FJQ+jAbCo#b zXmtd3raGJNH8vnqMtjem<_)9`gU_-RF&ZK!aIenv7B2Y0rZhon=2yh&VsHzM|`y|0x$Zez$bUg5Nqj?@~^ zPN43MB}q0kF&^=#3C;2T*bDBTyO(+#nZnULkVy0JcGJ36or7yl1wt7HI_>V7>mdud zv2II9P61FyEXZuF$=69dn%Z6F;SOwyGL4D5mKfW)q4l$8yUhv7|>>h_-4T*_CwAyu7;DW}_H zo>N_7Gm6eed=UaiEp_7aZko@CC61@(E1be&5I9TUq%AOJW>s^9w%pR5g2{7HW9qyF zh+ZvX;5}PN0!B4q2FUy+C#w5J?0Tkd&S#~94(AP4%fRb^742pgH7Tb1))siXWXHUT z1Wn5CG&!mGtr#jq6(P#!ck@K+FNprcWP?^wA2>mHA03W?kj>5b|P0ErXS) zg2qDTjQ|grCgYhrH-RapWCvMq5vCaF?{R%*mu}1)UDll~6;}3Q*^QOfj!dlt02lSzK z?+P)02Rrq``NbU3j&s*;<%i4Y>y9NK&=&KsYwvEmf5jwTG6?+Pu1q9M8lLlx)uZZ7 zizhr~e0ktGs-=$li-2jz^_48-jk**y&5u0`B2gc#i$T1~t+AS*kEfR*b{^Ec>2-F~ zKYRl&uQ5yO@EtAZX8ZSqx;8+AKf+CqhlUSpp*VfyBMv+%wxN5GukZEi^_to%MFRc0 zdXqJ*jk?#uYT6EJe446@(f6G4vhnxQP|pGeJ?-#|Ksq?g*ky=}x+Qnx+!<>Y(XStN zQIND`{KU}&l)E*ntI^}kJ=ly8DML{!(58Xk4_bzIc@v~e;>wKl_`7G%pGz~4KH*CTp;_|52)d!+ximd$|8v@zzEq%j68QXkgf$7eM~xdM5q5i z{?qFx_W|eq@L03bWJfjy^z@()-iCjzjREuf zb_a(yTz)ZKWCF%Lp>^2-%Q?*t{06}x#DLN3cO=i>h6#-a`z;<5rBGGM6GA(WqvRcX%Pn?Uvs1#e|ePSNJEC%+X(YI$x)`s$%>O#%}D9dgqWfq4yfVz^%FglokdFR}uJQhx|}_w`9Ulx38Ha>ZslKs58c-@IFI&f;?xM zbK>rKNfPFsf>%+k6%(A6=7Aac^_qrOCNqb3ZVJ;8pt!?1DR*ynJb#@II9h?)xB)A~ zm9Kk)Hy}!Z+W}i6ZJDy+?yY_=#kWrzgV)2eZAx_E=}Nh7*#<&mQz`Umfe$+l^P(xd zN}PA2qII4}ddCU+PN+yxkH%y!Qe(;iH3W%bwM3NKbU_saBo<8x9fGNtTAc_SizU=o zC3n2;c%LoU^j90Sz>B_p--Fzqv7x7*?|~-x{haH8RP)p|^u$}S9pD-}5;88pu0J~9 zj}EC`Q^Fw}`^pvAs4qOIuxKvGN@DUdRQ8p-RXh=3S#<`3{+Qv6&nEm)uV|kRVnu6f zco{(rJaWw(T0PWim?kkj9pJ)ZsUk9)dSNLDHf`y&@wbd;_ita>6RXFJ+8XC*-wsiN z(HR|9IF283fn=DI#3Ze&#y3yS5;!yoIBAH(v}3p5_Zr+F99*%+)cp!Sy8e+lG?dOc zuEz<;3X9Z5kkpL_ZYQa`sioR_@_cG z8tT~GOSTWnO~#?$u)AcaBSaV7P~RT?Nn8(OSL1RmzPWRWQ$K2`6*)+&7^zZBeWzud z*xb3|Fc~|R9eH+lQ#4wF#c;)Gka6lL(63C;>(bZob!i8F-3EhYU3|6-JBC0*5`y0| zBs!Frs=s!Sy0qmQNgIH|F`6(SrD1js2prni_QbG9Sv@^Pu2szR9NZl8GU89gWWvVg z2^-b*t+F{Nt>v?js7hnlC`tRU(an0qQG7;h6T~ z-`vf#R-AE$pzk`M{gCaia}F`->O2)60AuGFAJg> z*O2IZqTx=AzDvC49?A92>bQLdb&32_4>0Bgp0ESXXnd4B)!$t$g{*FG%HYdt3b3a^J9#so%BJMyr2 z{y?rzW!>lr097b9(75#&4&@lkB1vT*w&0E>!dS+a|ZOu6t^zro2tiP)bhcNNxn zbJs3_Fz+?t;4bkd8GfDI7ccJ5zU`Bs~ zN~bci`c`a%DoCMel<-KUCBdZRmew`MbZEPYE|R#|*hhvhyhOL#9Yt7$g_)!X?fK^F z8UDz)(zpsvriJ5aro5>qy`Fnz%;IR$@Kg3Z3EE!fv9CAdrAym6QU82=_$_N5*({_1 z7!-=zy(R{xg9S519S6W{HpJZ8Is|kQ!0?`!vxDggmslD59)>iQ15f z7J8NqdR`9f8H|~iFGNsPV!N)(CC9JRmzL9S}7U-K@`X893f3f<8|8Ls!^eA^#(O6nA+ByFIXcz_WLbfeG|nHJ5_sJJ^gNJ%SI9#XEfNRbzV+!RkI zXS$MOVYb2!0vU}Gt7oUy*|WpF^*orBot~b2J@^be?Gq;U%#am8`PmH-UCFZ&uTJlnetYij0z{K1mmivk$bdPbLodu;-R@@#gAV!=d%(caz$E?r zURX0pqAn7UuF6dULnoF1dZ$WM)tHAM{eZK6DbU1J`V5Dw<;xk}Nl`h+nfMO_Rdv z3SyOMzAbYaD;mkxA7_I_DOs#Bk;e5D%gsS3q)hlmi1w{FsjKNJE22`AjmNiAPRnIc zcIkN25;rOn3FipAFd(PnlK9{03w6Q<(68#1Jw`{axEGQE{Ac>^U$h);h2ADICmaNxrfpb`Jdr*)Y1SicpYKCFv$3vf~;5aW>n^7QGa63MJ z;B1+Z>WQ615R2D8JmmT`T{QcgZ+Kz1hTu{9FOL}Q8+iFx-Vyi}ZVVcGjTe>QfA`7W zFoS__+;E_rQIQxd(Bq4$egKeKsk#-9=&A!)(|hBvydsr5ts0Zjp*%*C0lM2sIOx1s zg$xz?Fh?x!P^!vWa|}^+SY8oZHub7f;E!S&Q;F?dZmvBxuFEISC}$^B_x*N-xRRJh zn4W*ThEWaPD*$KBr8_?}XRhHY7h^U1aN6>m=n~?YJQd8+!Uyq_3^)~4>XjelM&!c9 zCo|0KsGq7!KsZ~9@%G?i>LaU7#uSTMpypocm*oqJHR|wOgVWc7_8PVuuw>x{kEG4T z$p^DV`}jUK39zqFc(d5;N+M!Zd3zhZN&?Ww(<@AV-&f!v$uV>%z+dg9((35o@4rqLvTC-se@hkn^6k7+xHiK-vTRvM8{bCejbU;1@U=*r}GTI?Oc$!b6NRcj83-zF; z=TB#ESDB`F`jf4)z=OS76Se}tQDDHh{VKJk#Ad6FDB_=afpK#pyRkGrk~OuzmQG)} z*$t!nZu$KN&B;|O-aD=H<|n6aGGJZ=K9QFLG0y=Jye_ElJFNZJT;fU8P8CZcLBERjioAOC0Vz_pIXIc};)8HjfPwNy zE!g|lkRv3qpmU?shz(BBt5%TbpJC3HzP9!t7k*Fh48!-HlJ4TTgdCr3rCU!iF}kgu z4Qs;K@XOY~4f~N}Jl8V_mGbwzvNLbl&0e9UG4W;kvjTK|5`-Ld+eQ6YRF`N0ct%u% z^3J_{7r#_W1zm|>IPN!yWCRrN)N!7v`~ptNkIXKipQ6ogFvcnI5ugxdoa{d;uD67g zgo^}QuZRkB540Vc!@c80(wFG=$ct}oHq(#W0+-XX(;Rrt`x=<45X}ficNtI2(&}=~ zb(!}tNz?s`wm{gK?2tdf+OEF;tzx<(3fMd7_tM@Ghs$Z(Os-H(kYq#qB|J-aC9Ku?fsWwJhB36c)A zu|a7ZF?V8X7l2g5~xqZf>2=6Dsi5lfo zKIRL&@MLJyaBE)V_9=pJYu%U2wxR*-(0MI5_|yqP`?h@cks(5LR@XUKLMI_xuVtiu zRvpDS8MyUMRFM6`P+Sjc!A_e^H38Qu7b{b7QZ>NHyA6k-YYygQuW&C_OGO(7V7?}r)zedSVpBI zuk29Z4GW3C0GpfozbZQya454sjt@ndQmsp=DA&@sWw&xmOlDk1JIcMNp~-ES$&A~k zG#W(6hBj?!Fu8Q4WYexoSBa8_5=v20xnx6H?e;$t)5|f&{7=vOye^&3_c-Ug?|a@e z=X`&qT_5B7N9vZoPBhXOTEDV;4&x2Je4}T(UB~O-$D#CjX77$R?RZ*`ed~$G;$4YS z4n*|Pop(!NN79Hk2}U#cfEEwdxM)xQm}$~rV03xc=#U@@Y*}qEmot5KvDb=8{!E-n zl4p?}&g2h^sUGyTcGh=0aQzQb*k;K;dvbeZUgmwEv>%#(EPtj=gHKdi|E8@w+|>KC zxEU>b>P+9Xf}pEyQK(}#QrBG4Jaf!iE!qpMbTu>gb!gtdq<`@xO+roQl+S_7)!G(% zdy)$iGmJ1cwP?F=IyyV1-$|kf|EKM3B@I&lZ%NI@VV;*mQdLWjc#t|Vbk_Q~>&O03 zIcSr$(qLAINj7a z;!||v&1D5SX#X@5jNd}jUsi-CH_Scjyht&}q2p*CJCC-`&NyXf)vD5{e!HO629D-O z%bZelTcq=DoRX>zeWCa^RmR3*{x9;3lZ75M#S)!W0bRIFH#P6b%{|HRSZ5!!I#s)W z_|XXZQ<0_`>b^^0Z>LU64Yg1w)8}#M^9se(OZ9~baZ7fsKFc;EtnB>kesci#>=icG zuHdjax2^=!_(9?0l7;G7^-}9>Y#M zm;9*GT~dBuYWdk49%mZM0=H#FY1)}7NE5DE_vsqrA0`?0R0q535qHjWXcl|gz9Fq$ zMKxgL;68l!gm3y0durIr3LHv~y*ABm` zYhQG0UW#hg@*A{&G!;$FS43}rIF$e6yRdGJWVR<}uuJ_5_8qa3xaHH^!VzUteVp;> z<0`M>3tnY$ZFb$(`0sg93TwGyP;`9UYUWxO&CvAnSzei&ap))NcW;R`tA=y^?mBmG+M*&bqW5kL$V(O;(p)aEk`^ci?2Jwxu>0sy>a7+Wa9t z5#I2o;+gr^9^&km^z7>xJWbN&Ft>Vna34E zI@BBzwX)R}K3SL?)enrDJ45QLt;-7CFJk{`cF3L4Z^CtG_r5)0)HV>BOYPIUh#D%| zYQAu31f{bm-D*`_k7DTTr?Nkw_gY%J1cb2&TdtibY?V=|SSIOlA;|5C!2@?YQ z-$?G0jj^mG|MP>DmbF7}T~C$H6=CpZ~hd zZ1C|xV@=h#^~`3LSCnmI(vZ|5r3>eq5*UB)dhdy``*gKY3Eg%jSK8I-`G+OWWlD)T zt$wSQ=||lSkiKy}YF-k}@W9EiS?)z`hK{R!dd-$BCJvBtAN-yXn3njU$MisEtp!?Q z%Vk-*(wy9dd15(-WFw_&^tT;;IpF?ox1`Qq3-0zVTk+$W_?q}GfAQlPcrB^?&tWSI z2BB!K=sH7FUYmXa_dcV^Z3>5z8}~W{S!$jVR_3hu_|wl2|gmRH8ftn^z@fW75*;-`;wU+fY+BR_yx6BZnE5_Hna({jrPiubRp$jZ=T=t$hx&NeCV1!vuCcl4PJ0p0Fjp>6K} zHkoD1gQk=P2hYcT%)cJ2Q5WuA|5_x+dX0%hnozfTF>$#Wz~X!MY>){H4#fB#7^ID* z1*o2Hzp}?WVs&gbS?Uq(CT0sP+F)u9{xfgg6o_{8J#m;|NeJqDHhb(Q8%z8aM_qeM zn83>d`uDd47WIuKp78JBYo2SYupGcNXIzeou^eMY`@%Bv8elZ>q~3uq#~IX)g%g;h zoUXymEd>|kVsMkyb&1l~lrE-`w(0PObapYa35DJ4Y03Jv_!DKp}0HTbOgZRM=;PSsuAJJJ1 zItc+tu9;ANG;qHaCI|T85!euhFK~VK^G2LZV1+cbzS?>ar@>emg;JTI5VAn1g5U~| zU=p&k0OlSzc$U=s#9_uL3&n|6A1X$XvrE9vFV@`A4G#!D1QcFCeE`F2N(deJx>)*A z$XIW0P~-NbAd=5i6`s<~(vAQX9t$dbVqc5|E|CHRtb$1(l&KSNh_t2#k_l95KnP86 z)ns_DGspv-M0z0#h2a+*oH|{5~j{ zXGD=}cLrBSESQ0u$XmQlFfWMCAWaS;wKK%#aSSYK=qljBiY(s zT$v;We24&$w=avIILsMt0%1fDyah|AlLNg#WL$Lu)tf}YfqO%+pH~QC*bZO4aM*i9 zrPFf|5!hv@XY8CzaFh*Dy9vH|2fKKr(@x}`L#9^*vOae|lk`adG#oZZAyk|TOV8`9L zc-sQu%y1MQes&J?)a1}Zc*>-P!6j-T#75V$lLC!TuMB(!G-+D2;XptUxymSPFI-K&0x}B1?h$ z3-9**-9!);fwyiWB5gS$i;P~c=^}5-6G@{4TWDBRDc6(M|%qa-mS`z`u9kWo{Xl_uc;hXOkRd literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..a4b4429748 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000000..fbd7c51583 --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000000..5093609d51 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,104 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000000..972cd8b6b1 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'ip' + diff --git a/src/test/java/duke/task/TaskTest.java b/src/test/java/duke/task/TaskTest.java index b68b2724e1..e6e257a4e9 100644 --- a/src/test/java/duke/task/TaskTest.java +++ b/src/test/java/duke/task/TaskTest.java @@ -10,6 +10,7 @@ class TaskTest { void done() { TaskList.clearAllTask(); Todo task = new Todo("Scratch back", " "); + TaskList.addTask(task); TaskList.done(1); assertEquals("X", task.getDoneStatus()); } @@ -18,6 +19,7 @@ void done() { void delete() { TaskList.clearAllTask(); Todo task = new Todo("Scratch back", " "); + TaskList.addTask(task); TaskList.delete(1); assertEquals(0, TaskList.getTaskList().size()); } diff --git a/src/test/java/duke/utils/ParserTest.java b/src/test/java/duke/utils/ParserTest.java index 7a16f991a8..4652594c61 100644 --- a/src/test/java/duke/utils/ParserTest.java +++ b/src/test/java/duke/utils/ParserTest.java @@ -23,7 +23,7 @@ void extractInstruction_emptyInstruction_Exception() { Parser.extractInstruction(testInput); fail(); } catch (DukeException e) { - assertEquals("Walao, command cannot be empty!", e.getMessage()); + assertEquals("!!!Walao, command cannot be empty!!!", e.getMessage()); } } @@ -34,7 +34,7 @@ void extractInstruction_wrongInstruction_Exception() { Parser.extractInstruction(testInput); fail(); } catch (DukeException e) { - assertEquals("I DON'T KNOW WHAT U SAYING BRO", e.getMessage()); + assertEquals("!!!!!!!I DON'T KNOW WHAT U SAYING BRO!!!!!!!", e.getMessage()); } } @@ -53,7 +53,7 @@ void extractTask_emptyTask_Exception() { Parser.extractTask(testInput, "deadline"); fail(); } catch (DukeException e) { - assertEquals("Walao!NO TASK!", e.getMessage()); + assertEquals("!!!!!!!!!Walao!NO TASK!!!!!!!!!!", e.getMessage()); } } From 73e10a339a637dbb2f95d8575b3bf86db1c17b1e Mon Sep 17 00:00:00 2001 From: Hzxin Date: Mon, 1 Feb 2021 04:22:14 +0800 Subject: [PATCH 39/62] Change code according to checkstyle --- build.gradle | 5 + config/checkstyle/checkstyle.xml | 403 ++++++++++++++++++ config/checkstyle/suppressions.xml | 10 + src/main/java/duke/Duke.java | 3 - src/main/java/duke/command/AddCommand.java | 117 ++--- src/main/java/duke/command/Command.java | 79 ++-- src/main/java/duke/command/DeleteCommand.java | 48 +-- src/main/java/duke/command/DoneCommand.java | 45 +- src/main/java/duke/command/ErrorCommand.java | 9 +- src/main/java/duke/command/ExitCommand.java | 13 +- src/main/java/duke/command/FindCommand.java | 12 +- src/main/java/duke/command/ListCommand.java | 24 +- src/main/java/duke/driver/DukeDriver.java | 11 +- .../java/duke/exceptions/DukeException.java | 13 +- src/main/java/duke/task/Deadlines.java | 7 +- src/main/java/duke/task/Event.java | 7 +- src/main/java/duke/task/Task.java | 22 +- src/main/java/duke/task/TaskList.java | 181 ++++---- src/main/java/duke/task/Todo.java | 12 +- src/main/java/duke/type/CommandType.java | 63 +-- src/main/java/duke/ui/Ui.java | 58 ++- src/main/java/duke/utils/DateAndTime.java | 87 ++-- src/main/java/duke/utils/Parser.java | 306 ++++++------- src/main/java/duke/utils/TaskStorage.java | 8 +- src/test/java/duke/task/TaskTest.java | 32 +- src/test/java/duke/utils/DateAndTimeTest.java | 31 +- src/test/java/duke/utils/ParserTest.java | 169 ++++---- src/test/java/duke/utils/TaskStorageTest.java | 27 +- 28 files changed, 1129 insertions(+), 673 deletions(-) create mode 100644 config/checkstyle/checkstyle.xml create mode 100644 config/checkstyle/suppressions.xml diff --git a/build.gradle b/build.gradle index 084a80e6e1..1701000c43 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ plugins { id 'java' + id 'checkstyle' } group 'org.example' @@ -17,4 +18,8 @@ dependencies { test { useJUnitPlatform() +} + +checkstyle { + toolVersion = '8.29' } \ No newline at end of file diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml new file mode 100644 index 0000000000..4c001417ae --- /dev/null +++ b/config/checkstyle/checkstyle.xml @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml new file mode 100644 index 0000000000..39efb6e4ac --- /dev/null +++ b/config/checkstyle/suppressions.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java index bd2a27a175..21e6642b0d 100644 --- a/src/main/java/duke/Duke.java +++ b/src/main/java/duke/Duke.java @@ -19,7 +19,4 @@ public static void main(String[] args) { } - - - } diff --git a/src/main/java/duke/command/AddCommand.java b/src/main/java/duke/command/AddCommand.java index f41e9a1b51..7b90f6beff 100644 --- a/src/main/java/duke/command/AddCommand.java +++ b/src/main/java/duke/command/AddCommand.java @@ -1,64 +1,71 @@ package duke.command; -import duke.task.*; +import duke.task.Deadlines; +import duke.task.Event; +import duke.task.TaskList; +import duke.task.Todo; import duke.ui.Ui; - /** * Sub-class of Command that represents and execute the todo, deadline and event instructions of user. */ -public class AddCommand extends Command{ - public AddCommand(String instruction, String task, String date) { - super(instruction, task, date, command -> { - if (instruction.equals("todo")) { - return handleToDo(task); - } else if (instruction.equals("deadline")) { - return handleDeadline(task, date); - } else { - return handleEvent(task, date); - } - }); - } - - - - - /** - * handle todo command and create a todo task if task is not empty. - * @param task name of the user task. - */ - private static Boolean handleToDo(String task) { - if (!task.equals("")) { - Todo todo = new Todo(task); - TaskList.addTask(todo); - System.out.println(Ui.biggerBox(todo)); - } - return false; - - } - - - private static Boolean handleDeadline(String task, String date) { - - if (!date.equals("")) { - Deadlines deadlines = new Deadlines(task, date); - TaskList.addTask(deadlines); - System.out.println(Ui.biggerBox(deadlines)); - } - - return false; - } - - - - private static Boolean handleEvent(String task, String date) { - if (!task.equals("") && !date.equals("")) { - Event event = new Event(task, date); - TaskList.addTask(event); - System.out.println(Ui.biggerBox(event)); - - } - return false; - } +public class AddCommand extends Command { + + /** + * Create a AddCommand object for execution. + * + * @param instruction user instruction. + * @param task task name of the user in String. + * @param date date of the user task to be done. + */ + public AddCommand(String instruction, String task, String date) { + super(instruction, task, date, command -> { + if (instruction.equals("todo")) { + return handleToDo(task); + } else if (instruction.equals("deadline")) { + return handleDeadline(task, date); + } else { + return handleEvent(task, date); + } + }); + } + + + /** + * handle todo command and create a todo task if task is not empty. + * + * @param task name of the user task. + */ + private static Boolean handleToDo(String task) { + if (!task.equals("")) { + Todo todo = new Todo(task); + TaskList.addTask(todo); + System.out.println(Ui.biggerBox(todo)); + } + return false; + + } + + + private static Boolean handleDeadline(String task, String date) { + + if (!date.equals("")) { + Deadlines deadlines = new Deadlines(task, date); + TaskList.addTask(deadlines); + System.out.println(Ui.biggerBox(deadlines)); + } + + return false; + } + + + private static Boolean handleEvent(String task, String date) { + if (!task.equals("") && !date.equals("")) { + Event event = new Event(task, date); + TaskList.addTask(event); + System.out.println(Ui.biggerBox(event)); + } + return false; + } } diff --git a/src/main/java/duke/command/Command.java b/src/main/java/duke/command/Command.java index 532a32116d..09e2532ce1 100644 --- a/src/main/java/duke/command/Command.java +++ b/src/main/java/duke/command/Command.java @@ -4,46 +4,45 @@ /** * This class encapsulates the user instruction,task and date and execute the instruction. - * */ public abstract class Command { - private final String instruction; - private final String task; - private final String date; - private final Function func; - - - - /** - * Create a command with user instruction, task, date and a function to execute the instruction. - * @param instruction user instruction. - * @param task user task. - * @param date date of the task. - * @param func the function takes a command to execute the task and returns a boolean whether to end the program. - */ - public Command(String instruction, String task, String date, Function func) { - this.instruction = instruction; - this.task = task; - this.date = date; - this.func = func; - } - - - - /** - * Execution of a command and return a boolean whether to end the program. - * @return a boolean of whether to end the program. - */ - public Boolean execute() { - return func.apply(this); - } - - - public String getTask() { - return task; - } - - public String getDate() { - return date; - } + private final String instruction; + private final String task; + private final String date; + private final Function func; + + + /** + * Create a command with user instruction, task, date and a function to execute the instruction. + * + * @param instruction user instruction. + * @param task user task. + * @param date date of the task. + * @param func the function takes a command to execute the task and returns a boolean whether to end the program. + */ + public Command(String instruction, String task, String date, Function func) { + this.instruction = instruction; + this.task = task; + this.date = date; + this.func = func; + } + + + /** + * Execution of a command and return a boolean whether to end the program. + * + * @return a boolean of whether to end the program. + */ + public Boolean execute() { + return func.apply(this); + } + + + public String getTask() { + return task; + } + + public String getDate() { + return date; + } } diff --git a/src/main/java/duke/command/DeleteCommand.java b/src/main/java/duke/command/DeleteCommand.java index 25d80d8345..3a9ee7547e 100644 --- a/src/main/java/duke/command/DeleteCommand.java +++ b/src/main/java/duke/command/DeleteCommand.java @@ -12,28 +12,28 @@ public class DeleteCommand extends Command { - public DeleteCommand(String task, String date) { - super("delete", task, date, - command -> handleDelete(task, date)); - } - - - - /** - * handle delete command key in by user by removing the task from the list if there is any. - * @param task user task in String. - * @param date date of the task. - */ - private static Boolean handleDelete(String task, String date) { - if (task.length() > 0 && date.equals("")) { - try { - int num = Integer.parseInt(task); - TaskList.delete(num); - } catch (NumberFormatException e) { - DukeException.NumberFormatException(); - } - } - - return false; - } + public DeleteCommand(String task, String date) { + super("delete", task, date, + command -> handleDelete(task, date)); + } + + + /** + * handle delete command key in by user by removing the task from the list if there is any. + * + * @param task user task in String. + * @param date date of the task. + */ + private static Boolean handleDelete(String task, String date) { + if (task.length() > 0 && date.equals("")) { + try { + int num = Integer.parseInt(task); + TaskList.delete(num); + } catch (NumberFormatException e) { + DukeException.numberFormatException(); + } + } + + return false; + } } diff --git a/src/main/java/duke/command/DoneCommand.java b/src/main/java/duke/command/DoneCommand.java index ae4eedbbd0..8ecdac2425 100644 --- a/src/main/java/duke/command/DoneCommand.java +++ b/src/main/java/duke/command/DoneCommand.java @@ -4,36 +4,33 @@ import duke.task.TaskList; - /** * Sub-class of Command that represents and execute the done instruction of user. - * */ public class DoneCommand extends Command { - - public DoneCommand(String task, String date) { - super("done", task, date, command -> handleDone(task)); - } - - - - /** - * handle done command by marking the task as done. - * @param task name of the user task. - */ - private static Boolean handleDone(String task) { - if (task.length() > 0) { - try { - int num = Integer.parseInt(task); - TaskList.done(num); - } catch (NumberFormatException e) { - DukeException.NumberFormatException(); - } - } - return false; - } + public DoneCommand(String task, String date) { + super("done", task, date, command -> handleDone(task)); + } + + + /** + * handle done command by marking the task as done. + * + * @param task name of the user task. + */ + private static Boolean handleDone(String task) { + if (task.length() > 0) { + try { + int num = Integer.parseInt(task); + TaskList.markDone(num); + } catch (NumberFormatException e) { + DukeException.numberFormatException(); + } + } + return false; + } } diff --git a/src/main/java/duke/command/ErrorCommand.java b/src/main/java/duke/command/ErrorCommand.java index ec9efe3c9b..5f93568394 100644 --- a/src/main/java/duke/command/ErrorCommand.java +++ b/src/main/java/duke/command/ErrorCommand.java @@ -1,12 +1,11 @@ package duke.command; - /** * Sub-class of Command to represents any error in the instruction of user. */ -public class ErrorCommand extends Command{ - public ErrorCommand() { - super("", "", "", command -> false); - } +public class ErrorCommand extends Command { + public ErrorCommand() { + super("", "", "", command -> false); + } } diff --git a/src/main/java/duke/command/ExitCommand.java b/src/main/java/duke/command/ExitCommand.java index 0f546dadd4..9932e7c630 100644 --- a/src/main/java/duke/command/ExitCommand.java +++ b/src/main/java/duke/command/ExitCommand.java @@ -1,18 +1,17 @@ package duke.command; - /** * Sub-class of command that represents and execute the "bye" instruction of user. */ public class ExitCommand extends Command { - public ExitCommand(String task, String date) { - super("bye", task, date, command -> handleBye(task, date)); - } + public ExitCommand(String task, String date) { + super("bye", task, date, command -> handleBye(task, date)); + } - private static boolean handleBye(String task, String date) { - return task.equals("") && date.equals(""); - } + private static boolean handleBye(String task, String date) { + return task.equals("") && date.equals(""); + } } diff --git a/src/main/java/duke/command/FindCommand.java b/src/main/java/duke/command/FindCommand.java index bb77740d90..011daef35d 100644 --- a/src/main/java/duke/command/FindCommand.java +++ b/src/main/java/duke/command/FindCommand.java @@ -4,12 +4,12 @@ public class FindCommand extends Command { - public FindCommand(String task, String date) { - super("find", task, date, command -> { - System.out.println(TaskList.find(task)); - return false; - }); - } + public FindCommand(String task, String date) { + super("find", task, date, command -> { + System.out.println(TaskList.find(task)); + return false; + }); + } } diff --git a/src/main/java/duke/command/ListCommand.java b/src/main/java/duke/command/ListCommand.java index 0f342d72e8..440443db31 100644 --- a/src/main/java/duke/command/ListCommand.java +++ b/src/main/java/duke/command/ListCommand.java @@ -1,18 +1,20 @@ package duke.command; -/** - * Sub-class of Command that represents and execute the "list" instruction of user. - */ import duke.task.TaskList; - -public class ListCommand extends Command{ - public ListCommand() { - super("", "", "", command -> { - TaskList.listing(); - return false; - }); - } +/** + * Sub-class of Command that represents and execute the "list" instruction of user. + */ +public class ListCommand extends Command { + /** + * Create a ListCommand object to carry out listing of tasks. + */ + public ListCommand() { + super("", "", "", command -> { + TaskList.list(); + return false; + }); + } } diff --git a/src/main/java/duke/driver/DukeDriver.java b/src/main/java/duke/driver/DukeDriver.java index c45b2e0161..6bfb49428a 100644 --- a/src/main/java/duke/driver/DukeDriver.java +++ b/src/main/java/duke/driver/DukeDriver.java @@ -1,12 +1,12 @@ package duke.driver; +import java.util.Scanner; + import duke.command.Command; import duke.ui.Ui; import duke.utils.Parser; import duke.utils.TaskStorage; -import java.util.Scanner; - /** * Driver class of Duke that handles the command key in by user and respond. @@ -15,18 +15,17 @@ public class DukeDriver { /** * Take in user input and execute the Duke program. - * */ public static void executeDuke() { Scanner sc = new Scanner(System.in); System.out.println(Ui.LOGO); System.out.println(Ui.GREETING); - Ui.SLEEP(); + Ui.sleep(); TaskStorage.loadFiles(); - while(sc.hasNext()) { + while (sc.hasNext()) { String message = sc.nextLine(); boolean bye = inputHandler(message); if (bye) { @@ -49,6 +48,4 @@ private static boolean inputHandler(String message) { } - - } diff --git a/src/main/java/duke/exceptions/DukeException.java b/src/main/java/duke/exceptions/DukeException.java index a7ed246c10..faef0110f6 100644 --- a/src/main/java/duke/exceptions/DukeException.java +++ b/src/main/java/duke/exceptions/DukeException.java @@ -6,19 +6,22 @@ /** * A class that store all the possible display of errorsException in Duke. */ -public class DukeException extends Exception{ +public class DukeException extends Exception { public DukeException(String errorMessage) { super(errorMessage); } - - public static void NumberFormatException() { + public static void numberFormatException() { System.out.println(Ui.KEY_IN_NUMBER); } - public static void taskErrorException() { System.out.println(Ui.TASK_ERROR); } + public static void taskErrorException() { + System.out.println(Ui.TASK_ERROR); + } - public static void saveToFileError() { System.out.println(Ui.SAVE_TO_FILE_ERROR);} + public static void saveToFileError() { + System.out.println(Ui.SAVE_TO_FILE_ERROR); + } } diff --git a/src/main/java/duke/task/Deadlines.java b/src/main/java/duke/task/Deadlines.java index 0227abb7e4..108ee1abc4 100644 --- a/src/main/java/duke/task/Deadlines.java +++ b/src/main/java/duke/task/Deadlines.java @@ -3,15 +3,14 @@ /** * sub-class of Task to represents a task with deadline. */ -public class Deadlines extends Task{ - +public class Deadlines extends Task { /** * create a deadline task object with given task name and given dates/comments. * * @param taskName String representation of the name of the task. - * @param date String representation of the comments/dates. + * @param date String representation of the comments/dates. */ public Deadlines(String taskName, String date) { super(taskName, date); @@ -29,6 +28,6 @@ public int getType() { @Override public String toString() { return String.format("[D][%s] %d. %s ( %s )", super.getDoneStatus(), super.getIndex(), - super.getTaskName(), super.getDate()); + super.getTaskName(), super.getDate()); } } \ No newline at end of file diff --git a/src/main/java/duke/task/Event.java b/src/main/java/duke/task/Event.java index f427545ced..242450cce4 100644 --- a/src/main/java/duke/task/Event.java +++ b/src/main/java/duke/task/Event.java @@ -3,13 +3,14 @@ /** * A subclass of Task that represent an event key in by user. */ -public class Event extends Task{ +public class Event extends Task { /** * Create a event Task with given task name and given comments/dates. + * * @param taskName name of the task. - * @param date dates or comments of the user regarding the task. + * @param date dates or comments of the user regarding the task. */ public Event(String taskName, String date) { super(taskName, date); @@ -27,6 +28,6 @@ public int getType() { @Override public String toString() { return String.format("[E][%s] %d. %s ( %s )", super.getDoneStatus(), super.getIndex(), - super.getTaskName(), super.getDate()); + super.getTaskName(), super.getDate()); } } \ No newline at end of file diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java index a99899d246..3ad8214078 100644 --- a/src/main/java/duke/task/Task.java +++ b/src/main/java/duke/task/Task.java @@ -5,15 +5,15 @@ * A class that store the task that user key in. */ public class Task { - - private final String taskName; private static int capacity = 0; + private final String taskName; private int index; private String isDone; private final String date; /** * Construct a task object with taskName attached and its index label in the taskList. + * * @param taskName name of the task. */ Task(String taskName) { @@ -25,14 +25,6 @@ public class Task { } - Task(String taskName, String done, boolean check) { - this.taskName = taskName; - this.index = capacity + 1; - this.isDone = done; - this.date = ""; - capacity++; - - } Task(String taskName, String date) { this.taskName = taskName; @@ -40,7 +32,6 @@ public class Task { this.isDone = " "; this.date = date; capacity++; - } Task(String taskName, String date, String done) { @@ -52,18 +43,18 @@ public class Task { } - public void changeIndex(int i) { this.index = i; } + /** + * Mark the task status as done with the notation X. + */ public void markDone() { this.isDone = "X"; - } - /** * Get the name of the task. * @@ -74,7 +65,6 @@ public String getTaskName() { } - /** * get the isDone status of the task. * @@ -114,4 +104,4 @@ public static int getCapacity() { public String toString() { return String.format("[%s] %d. %s", isDone, index, taskName); } -} \ No newline at end of file +} diff --git a/src/main/java/duke/task/TaskList.java b/src/main/java/duke/task/TaskList.java index 08ba3afb0f..932854b30f 100644 --- a/src/main/java/duke/task/TaskList.java +++ b/src/main/java/duke/task/TaskList.java @@ -1,91 +1,108 @@ package duke.task; +import java.util.ArrayList; +import java.util.List; + import duke.exceptions.DukeException; import duke.ui.Ui; -import java.util.ArrayList; -import java.util.List; + public class TaskList { - private static List taskList = new ArrayList<>(); - - private List list; - - public TaskList() { - this.list = new ArrayList<>(); - } - - - - public static void addTask(Task t) { - taskList.add(t); - } - - - public static void done(int i) { - try { - Task t = taskList.get(i - 1); - taskList.get(i - 1).markDone(); - Ui.doneTask(t); - } catch (IndexOutOfBoundsException e) { - DukeException.taskErrorException(); - } - } - - public static String find(String keyword) { - int index = 1; - StringBuilder sb = new StringBuilder(""); - for (Task task : taskList) { - String taskName = task.getTaskName(); - if (taskName.contains(keyword)) { - String prefix = task.toString().substring(0, 6); - sb.append(prefix + " " + index + ". " + task.getTaskName() + task.getDate() + "\n"); - index++; - } - } - if (sb.equals("")) { - sb.append("~~~~~Sorry ah, no match.~~~~~"); - } else { - sb.insert(0, "Here are the matches for your search: \n"); - } - - return sb.toString(); - - } - - - public static void listing() { - System.out.println(Ui.UPPER); - for (Task task : taskList) { - if (task == null) break; - System.out.println(task); - } - System.out.println(Ui.LOWER); - } - - - - public static void delete(int i) { - try { - Task t = taskList.get(i - 1); - taskList.remove(i - 1); - Ui.deleteTask(t); - for (Task task : taskList) { - if (task.getIndex() > i) { - task.changeIndex(task.getIndex() - 1); - } - } - } catch (IndexOutOfBoundsException e) { - DukeException.taskErrorException(); - } - } - - public static void clearAllTask() { - taskList.clear(); - } - - public static List getTaskList() { - return taskList; - } + private static List taskList = new ArrayList<>(); + + private List list; + + public TaskList() { + this.list = new ArrayList<>(); + } + + + public static void addTask(Task t) { + taskList.add(t); + } + + + /** + * This method marks a task in the list as done. + * @param i index labelling of the task in list. + */ + public static void markDone(int i) { + try { + Task t = taskList.get(i - 1); + taskList.get(i - 1).markDone(); + Ui.doneTask(t); + } catch (IndexOutOfBoundsException e) { + DukeException.taskErrorException(); + } + } + + /** + * This method finds all relevant tasks according to the keyword. + * @param keyword keyword that the user want to search. + * @return the matched tasks according to the keyword in String. + */ + public static String find(String keyword) { + int index = 1; + StringBuilder sb = new StringBuilder(""); + for (Task task : taskList) { + String taskName = task.getTaskName(); + if (taskName.contains(keyword)) { + String prefix = task.toString().substring(0, 6); + sb.append(prefix + " " + index + ". " + task.getTaskName() + task.getDate() + "\n"); + index++; + } + } + if (sb.equals("")) { + sb.append("~~~~~Sorry ah, no match.~~~~~"); + } else { + sb.insert(0, "Here are the matches for your search: \n"); + } + + return sb.toString(); + + } + + + /** + * Display all the tasks in the list. + */ + public static void list() { + System.out.println(Ui.UPPER); + for (Task task : taskList) { + if (task == null) { + break; + } + System.out.println(task); + } + System.out.println(Ui.LOWER); + } + + /** + * Delete a task in the task list with the given index. + * @param i the index labelling of the task. + */ + public static void delete(int i) { + try { + Task t = taskList.get(i - 1); + taskList.remove(i - 1); + Ui.deleteTask(t); + for (Task task : taskList) { + if (task.getIndex() > i) { + task.changeIndex(task.getIndex() - 1); + } + } + } catch (IndexOutOfBoundsException e) { + DukeException.taskErrorException(); + } + } + + public static void clearAllTask() { + taskList.clear(); + } + + public static List getTaskList() { + return taskList; + } } diff --git a/src/main/java/duke/task/Todo.java b/src/main/java/duke/task/Todo.java index 67b0c35fc1..d66e1c2c67 100644 --- a/src/main/java/duke/task/Todo.java +++ b/src/main/java/duke/task/Todo.java @@ -4,10 +4,11 @@ /** * A sub-class of Task to represents a toDo task key in by user. */ -public class Todo extends Task{ +public class Todo extends Task { /** - * Create a toDo task with given taskName attached. + * Create a Todo object with given taskName. + * * @param taskName name of the task in String. */ public Todo(String taskName) { @@ -15,6 +16,11 @@ public Todo(String taskName) { } + /** + * Create a Todo object with given taskName and isDone status. + * @param taskName name of the task. + * @param done String representation of the done status. + */ public Todo(String taskName, String done) { super(taskName, done, true); @@ -30,4 +36,4 @@ public int getType() { public String toString() { return String.format("[T][%s] %d. %s", super.getDoneStatus(), super.getIndex(), super.getTaskName()); } -} \ No newline at end of file +} diff --git a/src/main/java/duke/type/CommandType.java b/src/main/java/duke/type/CommandType.java index 04f9410c95..0ee6ff5c08 100644 --- a/src/main/java/duke/type/CommandType.java +++ b/src/main/java/duke/type/CommandType.java @@ -5,39 +5,40 @@ * The class includes seven types: todo, deadline, event, bye, list, delete, done and find. */ public enum CommandType { - TODO("todo"), - DEADLINE("deadline"), - EVENT("event"), - BYE("bye"), - DONE("done"), - LIST("list"), - FIND("find"), - DELETE("delete"); + BYE("bye"), + DEADLINE("deadline"), + DELETE("delete"), + DONE("done"), + EVENT("event"), + FIND("find"), + LIST("list"), + TODO("todo"); - private final String type; + private final String type; - /** - * Construct a CommandType object with a String representation of the type. - * @param type String representation of the type. - */ - CommandType(String type) { - this.type = type; - } + /** + * Construct a CommandType object with a String representation of the type. + * + * @param type String representation of the type. + */ + CommandType(String type) { + this.type = type; + } - /** - * Gets the CommandType object from a string representation of the type. - * Returns null if no such object exists. - * - * @param type a string representing the type. - * @return an CommandType object of the specified type and null if no such object exists. - */ - public static CommandType valueOfType(String type) { - for (CommandType t : values()) { - if (t.type.equals(type)) { - return t; - } - } - return null; - } + /** + * Gets the CommandType object from a string representation of the type. + * Returns null if no such object exists. + * + * @param type a string representing the type. + * @return an CommandType object of the specified type and null if no such object exists. + */ + public static CommandType valueOfType(String type) { + for (CommandType t : values()) { + if (t.type.equals(type)) { + return t; + } + } + return null; + } } diff --git a/src/main/java/duke/ui/Ui.java b/src/main/java/duke/ui/Ui.java index 6bb7e3c232..3a8c048f42 100644 --- a/src/main/java/duke/ui/Ui.java +++ b/src/main/java/duke/ui/Ui.java @@ -12,10 +12,10 @@ public class Ui { public static final String UPPER = LINEBREAK + "^".repeat(90) + LINEBREAK.repeat(2); public static final String LOWER = LINEBREAK.repeat(1) + "_".repeat(90) + LINEBREAK; public static final String LOGO = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; public static final String WRONG_DATE_FORMAT = "!!!Err, wrong date format.. (yyyy-mm-dd)!!!"; public static final String KEY_IN_NUMBER = "!!!!!!!PLease Lah! Key in number!!!!!!!!"; @@ -27,59 +27,77 @@ public class Ui { public static final String EMPTY_COMMAND = "!!!Walao, command cannot be empty!!!"; public static final String SUCCESSFUL_SAVE = "~~~~~~~~~~~File Saved Successfully!~~~~~~~~~~~~"; public static final String FAREWELL = UPPER - + "~~~~~~~~~~~ I Zao Liao. Don't Miss Meeeeeee ~~~~~~~~~~~." - + LOWER; + + "~~~~~~~~~~~ I Zao Liao. Don't Miss Meeeeeee ~~~~~~~~~~~." + + LOWER; public static final String GREETING = UPPER - + "****************** Awww, need help ah? ******************" - + LOWER; + + "****************** Awww, need help ah? ******************" + + LOWER; public static final String NO_DIRECTORY = "********** Cannot find your directory eh, " - + "first time ah? Create one for you **********\n" ; + + "first time ah? Create one for you **********\n"; public static final String LOAD_FILE = "********** Wait ah~ Loading file for you **********\n"; public static final String NO_FILE = "********** File also don't have ah, nvm I make one for you **********\n"; public static final String EMPTY_FILE = "********** Awwww~ You don't have any history of tasks **********\n"; public static final String SUCESSFUL_LOAD = "***********Sir, here is your past history************"; + /** + * Display a message to indicate the given task as done. + * @param t the task to be displayed as done. + */ public static void doneTask(Task t) { System.out.println(Ui.UPPER + "Wah~ You done the task: " - + " " + t.toString() + Ui.LOWER); + + " " + t.toString() + Ui.LOWER); } + + /** + * Display a message to indicate the given task as deleted. + * @param t the task to be displayed as deleted. + */ public static void deleteTask(Task t) { System.out.println(Ui.UPPER + "Awww~ You've deleted the task: " - + " " + t.toString() + Ui.LOWER); + + " " + t.toString() + Ui.LOWER); } /** * make a Bigger ChatBox that wrap the name of a given Task. + * * @param t task to be wrapped. * @return the String representation of the task name wrapped in a chatBox. */ public static String biggerBox(Task t) { return Ui.UPPER + "Added liao: " - + t.toString() + Ui.LINEBREAK - + "You have " + Task.getCapacity() + " tasks in the list!" - + Ui.LOWER; + + t.toString() + Ui.LINEBREAK + + "You have " + Task.getCapacity() + " tasks in the list!" + + Ui.LOWER; } - - public static void DONELOADING() { + /** + * Display the tasks loaded from the data file. + */ + public static void displayTask() { System.out.println(UPPER); System.out.println("~~~~~Sir, here is your past history: "); for (Task task : TaskList.getTaskList()) { - if (task == null) break; + if (task == null) { + break; + } System.out.println(task); } System.out.println(LOWER); } - public static void SLEEP() { + /** + * Set the program to rest for 1 second. + */ + public static void sleep() { try { - Thread.sleep(1500); + Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } -} \ No newline at end of file +} + diff --git a/src/main/java/duke/utils/DateAndTime.java b/src/main/java/duke/utils/DateAndTime.java index b8e272a94e..9b82bd4754 100644 --- a/src/main/java/duke/utils/DateAndTime.java +++ b/src/main/java/duke/utils/DateAndTime.java @@ -1,57 +1,58 @@ package duke.utils; -import duke.ui.Ui; - import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import duke.ui.Ui; + + /** * This class process the date key in by user and convert it to the right format to be use. */ public class DateAndTime { - /** - * This method convert a yyyy-mm-dd format of date to MMM d yyyy format. - * - * @param date the String representation of date. - * @return MMM d yyyy format of date and return error message if the given date is in wrong format. - */ - public static String converter(String date) { - if (isDashFormat(date)) { - try { - LocalDate d1 = LocalDate.parse(date.trim()); - return d1.format(DateTimeFormatter.ofPattern("MMM d yyyy")); - } catch (DateTimeParseException e) { - return Ui.WRONG_DATE_FORMAT; - } - } else { - return Ui.WRONG_DATE_FORMAT; - } - } - - - private static boolean isDashFormat(String date) { - String[] dashFormat = date.toLowerCase().split("-", 3); - for (String s : dashFormat) { - if (!isNumeric(s.trim())) { - return false; - } - } - return true; - } - - private static boolean isNumeric(String strNum) { - if (strNum == null) { - return false; - } - try { - Double.parseDouble(strNum); - } catch (NumberFormatException nfe) { - return false; - } - return true; - } + /** + * This method convert a yyyy-mm-dd format of date to MMM d yyyy format. + * + * @param date the String representation of date. + * @return MMM d yyyy format of date and return error message if the given date is in wrong format. + */ + public static String converter(String date) { + if (isDashFormat(date)) { + try { + LocalDate d1 = LocalDate.parse(date.trim()); + return d1.format(DateTimeFormatter.ofPattern("MMM d yyyy")); + } catch (DateTimeParseException e) { + return Ui.WRONG_DATE_FORMAT; + } + } else { + return Ui.WRONG_DATE_FORMAT; + } + } + + + private static boolean isDashFormat(String date) { + String[] dashFormat = date.toLowerCase().split("-", 3); + for (String s : dashFormat) { + if (!isNumeric(s.trim())) { + return false; + } + } + return true; + } + + private static boolean isNumeric(String strNum) { + if (strNum == null) { + return false; + } + try { + Double.parseDouble(strNum); + } catch (NumberFormatException nfe) { + return false; + } + return true; + } } diff --git a/src/main/java/duke/utils/Parser.java b/src/main/java/duke/utils/Parser.java index c8d8dcdfb8..d545a3e79b 100644 --- a/src/main/java/duke/utils/Parser.java +++ b/src/main/java/duke/utils/Parser.java @@ -1,6 +1,13 @@ package duke.utils; -import duke.command.*; +import duke.command.AddCommand; +import duke.command.Command; +import duke.command.DeleteCommand; +import duke.command.DoneCommand; +import duke.command.ErrorCommand; +import duke.command.ExitCommand; +import duke.command.FindCommand; +import duke.command.ListCommand; import duke.exceptions.DukeException; import duke.type.CommandType; import duke.ui.Ui; @@ -9,151 +16,158 @@ * This class extract and process the user input and produce the right command to be executed after parsing. */ public class Parser { - private final String input; - - public Parser(String input) { - this.input = input; - } - - /** - * This method process all the user input and create respective command to be executed. - * - * @return the respective command to be executed. - */ - public final Command parse() { - String instruction; - String taskName; - String date; - Command command = new ErrorCommand(); - - try { - instruction = extractInstruction(input); - } catch (DukeException e) { - System.out.println(e.getMessage()); - return command; - } - - try { - taskName = extractTask(input, instruction); - } catch (DukeException e) { - System.out.println(e.getMessage()); - return command; - } - - try { - date = extractDate(input, instruction); - } catch (DukeException e) { - System.out.println(e.getMessage()); - return command; - } - - switch (instruction) { - case "bye": - command = new ExitCommand(taskName, date); - TaskStorage.writeToFiles(); - break; - case "list": - command = new ListCommand(); - break; - case "done": - command = new DoneCommand(taskName, date); - break; - case "todo": case "deadline": case "event": - command = new AddCommand(instruction, taskName, date); - break; - case "delete": - command = new DeleteCommand(taskName, date); - break; - case "find": - command = new FindCommand(taskName, date); - break; - default: - break; - } - return command; - } - - - /** - * extract the command key in by user. - * - * @param input the input key in by user. - * @return String representation of the command word of the user input. - */ - static String extractInstruction(String input) throws DukeException { - - String instruction = input.trim().toLowerCase().split(" ")[0]; - if (input.replaceAll(" ", "").equals("")) { - throw new DukeException(Ui.EMPTY_COMMAND); - } - - if (CommandType.valueOfType(instruction) == null) { - throw new DukeException(Ui.COMMAND_ERROR); - } - - return instruction; - - } - - /** - * extracting task name from user input. - * @param input user input. - * @param command user command. - * @return the task name if there is one and return empty string if task name empty. - */ - static String extractTask(String input, String command) throws DukeException { - String body = input.replaceAll(command, "").trim(); - switch (command) { - case "todo": case "find": - if (body.equals("")) { - throw new DukeException(Ui.EMPTY_TASK); - } else { - return body; - } - case "done": case "delete": - String hasLetter = body.replaceAll("[0-9]", ""); - if (hasLetter.length() > 0) { - throw new DukeException(Ui.KEY_IN_NUMBER); - } else { - return body.replaceAll("[^0-9]", ""); - } - case "deadline": case "event": - if (body.equals("")) { - throw new DukeException(Ui.EMPTY_TASK); - } else { - return body.split("/")[0]; - } - default: - if (body.length() > 0) { - throw new DukeException(Ui.COMMAND_ERROR); - } - return ""; - } - } - - /** - * extract the date of the task to be done. - * @param input user input. - * @param instruction user command. - * @return the task date in String and return empty if there is no date. - */ - static String extractDate(String input, String instruction) throws DukeException { - String body = input.replaceAll(instruction, "").trim(); - String[] parts = body.split("/", 2); - if (parts.length == 2) { - String date = DateAndTime.converter(parts[1]); - if (date.equals(Ui.WRONG_DATE_FORMAT)) { - throw new DukeException(Ui.WRONG_DATE_FORMAT); - } - return date; - } else { - if (instruction.equals("deadline") - || instruction.equals("event")) { - throw new DukeException(Ui.MISSING_DATE); - } - return ""; - } - } + private final String input; + + public Parser(String input) { + this.input = input; + } + + /** + * This method process all the user input and create respective command to be executed. + * + * @return the respective command to be executed. + */ + public final Command parse() { + String instruction; + String taskName; + String date; + Command command = new ErrorCommand(); + + try { + instruction = extractInstruction(input); + } catch (DukeException e) { + System.out.println(e.getMessage()); + return command; + } + + try { + taskName = extractTask(input, instruction); + } catch (DukeException e) { + System.out.println(e.getMessage()); + return command; + } + + try { + date = extractDate(input, instruction); + } catch (DukeException e) { + System.out.println(e.getMessage()); + return command; + } + + switch (instruction) { + case "bye": + command = new ExitCommand(taskName, date); + TaskStorage.writeToFiles(); + break; + case "list": + command = new ListCommand(); + break; + case "done": + command = new DoneCommand(taskName, date); + break; + case "todo": + case "deadline": + case "event": + command = new AddCommand(instruction, taskName, date); + break; + case "delete": + command = new DeleteCommand(taskName, date); + break; + case "find": + command = new FindCommand(taskName, date); + break; + default: + break; + } + return command; + } + + + /** + * extract the command key in by user. + * + * @param input the input key in by user. + * @return String representation of the command word of the user input. + */ + static String extractInstruction(String input) throws DukeException { + + String instruction = input.trim().toLowerCase().split(" ")[0]; + if (input.replaceAll(" ", "").equals("")) { + throw new DukeException(Ui.EMPTY_COMMAND); + } + + if (CommandType.valueOfType(instruction) == null) { + throw new DukeException(Ui.COMMAND_ERROR); + } + + return instruction; + + } + + /** + * extracting task name from user input. + * + * @param input user input. + * @param command user command. + * @return the task name if there is one and return empty string if task name empty. + */ + static String extractTask(String input, String command) throws DukeException { + String body = input.replaceAll(command, "").trim(); + switch (command) { + case "todo": + case "find": + if (body.equals("")) { + throw new DukeException(Ui.EMPTY_TASK); + } else { + return body; + } + case "done": + case "delete": + String hasLetter = body.replaceAll("[0-9]", ""); + if (hasLetter.length() > 0) { + throw new DukeException(Ui.KEY_IN_NUMBER); + } else { + return body.replaceAll("[^0-9]", ""); + } + case "deadline": + case "event": + if (body.equals("")) { + throw new DukeException(Ui.EMPTY_TASK); + } else { + return body.split("/")[0]; + } + default: + if (body.length() > 0) { + throw new DukeException(Ui.COMMAND_ERROR); + } + return ""; + } + } + + /** + * extract the date of the task to be done. + * + * @param input user input. + * @param instruction user command. + * @return the task date in String and return empty if there is no date. + */ + static String extractDate(String input, String instruction) throws DukeException { + String body = input.replaceAll(instruction, "").trim(); + String[] parts = body.split("/", 2); + if (parts.length == 2) { + String date = DateAndTime.converter(parts[1]); + if (date.equals(Ui.WRONG_DATE_FORMAT)) { + throw new DukeException(Ui.WRONG_DATE_FORMAT); + } + return date; + } else { + if (instruction.equals("deadline") + || instruction.equals("event")) { + throw new DukeException(Ui.MISSING_DATE); + } + return ""; + } + } } diff --git a/src/main/java/duke/utils/TaskStorage.java b/src/main/java/duke/utils/TaskStorage.java index ada19a2337..4695e6bf55 100644 --- a/src/main/java/duke/utils/TaskStorage.java +++ b/src/main/java/duke/utils/TaskStorage.java @@ -57,24 +57,24 @@ public static String loadFiles() { if (!directory.exists()) { System.out.println(Ui.NO_DIRECTORY); directory.mkdir(); - Ui.SLEEP(); + Ui.sleep(); } File file = new File(FILEPATH); if (!file.exists()) { System.out.println(Ui.NO_FILE); file.createNewFile(); - Ui.SLEEP(); + Ui.sleep(); } if (file.length() == 0) { - Ui.SLEEP(); + Ui.sleep(); System.out.println(Ui.EMPTY_FILE); return Ui.EMPTY_FILE; } restoreTask(file); - Ui.DONELOADING(); + Ui.displayTask(); } catch (IOException e) { System.out.println("IO error!: " + e.getMessage()); } diff --git a/src/test/java/duke/task/TaskTest.java b/src/test/java/duke/task/TaskTest.java index e6e257a4e9..b87bf7cb41 100644 --- a/src/test/java/duke/task/TaskTest.java +++ b/src/test/java/duke/task/TaskTest.java @@ -6,21 +6,21 @@ class TaskTest { - @Test - void done() { - TaskList.clearAllTask(); - Todo task = new Todo("Scratch back", " "); - TaskList.addTask(task); - TaskList.done(1); - assertEquals("X", task.getDoneStatus()); - } + @Test + void done() { + TaskList.clearAllTask(); + Todo task = new Todo("Scratch back", " "); + TaskList.addTask(task); + TaskList.markDone(1); + assertEquals("X", task.getDoneStatus()); + } - @Test - void delete() { - TaskList.clearAllTask(); - Todo task = new Todo("Scratch back", " "); - TaskList.addTask(task); - TaskList.delete(1); - assertEquals(0, TaskList.getTaskList().size()); - } + @Test + void delete() { + TaskList.clearAllTask(); + Todo task = new Todo("Scratch back", " "); + TaskList.addTask(task); + TaskList.delete(1); + assertEquals(0, TaskList.getTaskList().size()); + } } \ No newline at end of file diff --git a/src/test/java/duke/utils/DateAndTimeTest.java b/src/test/java/duke/utils/DateAndTimeTest.java index 2dd25d42fe..5b713b484b 100644 --- a/src/test/java/duke/utils/DateAndTimeTest.java +++ b/src/test/java/duke/utils/DateAndTimeTest.java @@ -1,25 +1,26 @@ package duke.utils; +import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; public class DateAndTimeTest { - @Test - void converterTest() { - String date = "2019-10-22"; - String actualOutput = DateAndTime.converter(date); - String expectedOutput = "Oct 22 2019"; - assertEquals(expectedOutput, actualOutput); - } + @Test + void converterTest() { + String date = "2019-10-22"; + String actualOutput = DateAndTime.converter(date); + String expectedOutput = "Oct 22 2019"; + assertEquals(expectedOutput, actualOutput); + } - @Test - void converterTest_WrongDateFormat() { - String date = "2019"; - String actualOutput = DateAndTime.converter(date); - String expectedOutput = "!!!Err, wrong date format.. (yyyy-mm-dd)!!!"; - assertEquals(expectedOutput, actualOutput); - } + @Test + void converterTest_wrongDateFormat() { + String date = "2019"; + String actualOutput = DateAndTime.converter(date); + String expectedOutput = "!!!Err, wrong date format.. (yyyy-mm-dd)!!!"; + assertEquals(expectedOutput, actualOutput); + } } diff --git a/src/test/java/duke/utils/ParserTest.java b/src/test/java/duke/utils/ParserTest.java index 4652594c61..0b2aa1d05b 100644 --- a/src/test/java/duke/utils/ParserTest.java +++ b/src/test/java/duke/utils/ParserTest.java @@ -1,101 +1,90 @@ package duke.utils; -import duke.exceptions.DukeException; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; -public class ParserTest { - - - @Test - void extractInstructionTest() throws DukeException { - String testInput = "todo swimming"; - String actualInstruction = Parser.extractInstruction(testInput); - assertEquals("todo", actualInstruction); - } - - @Test - void extractInstruction_emptyInstruction_Exception() { - try { - String testInput = ""; - Parser.extractInstruction(testInput); - fail(); - } catch (DukeException e) { - assertEquals("!!!Walao, command cannot be empty!!!", e.getMessage()); - } - } - - @Test - void extractInstruction_wrongInstruction_Exception() { - try { - String testInput = "ANYHOW"; - Parser.extractInstruction(testInput); - fail(); - } catch (DukeException e) { - assertEquals("!!!!!!!I DON'T KNOW WHAT U SAYING BRO!!!!!!!", e.getMessage()); - } - } - - - @Test - void extractTaskTest() throws DukeException { - String testInput = "deadline project/2019-10-22"; - String actualTask = Parser.extractTask(testInput, "deadline"); - assertEquals("project", actualTask); - } - - @Test - void extractTask_emptyTask_Exception() { - try { - String testInput = "deadline "; - Parser.extractTask(testInput, "deadline"); - fail(); - } catch (DukeException e) { - assertEquals("!!!!!!!!!Walao!NO TASK!!!!!!!!!!", e.getMessage()); - } - } - - @Test - void extractDateTest() throws DukeException { - String testInput = "deadline project /2019-10-22"; - String actualDate = Parser.extractDate(testInput, "deadline"); - assertEquals("Oct 22 2019", actualDate); - } +import org.junit.jupiter.api.Test; - @Test - void extractDate_emptyDate_withoutSlash_Exception() { - try { - String testInput = "deadline project"; - Parser.extractDate(testInput, "deadline"); - fail(); - } catch (DukeException e) { - assertEquals("!!!Fill ur date lah (add date with / in yyyy-mm-dd format)!!!", e.getMessage()); - } +import duke.exceptions.DukeException; - } - @Test - void extractDate_wrongDateFormat_Exception1() { - try { - String testInput = "deadline project/"; - Parser.extractDate(testInput, "deadline"); - fail(); - } catch (DukeException e) { - assertEquals("!!!Err, wrong date format.. (yyyy-mm-dd)!!!", e.getMessage()); - } - } +public class ParserTest { - @Test - void extractDate_wrongDateFormat_Exception2() { - try { - String testInput = "event project/2019"; - Parser.extractDate(testInput, "event"); - fail(); - } catch (DukeException e) { - assertEquals("!!!Err, wrong date format.. (yyyy-mm-dd)!!!", e.getMessage()); - } - } + @Test + void extractInstructionTest() throws DukeException { + String testInput = "todo swimming"; + String actualInstruction = Parser.extractInstruction(testInput); + assertEquals("todo", actualInstruction); + } + + @Test + void extractInstruction_emptyInstruction_exception() { + try { + String testInput = ""; + Parser.extractInstruction(testInput); + fail(); + } catch (DukeException e) { + assertEquals("!!!Walao, command cannot be empty!!!", e.getMessage()); + } + } + + @Test + void extractInstruction_wrongInstruction_exception() { + try { + String testInput = "ANYHOW"; + Parser.extractInstruction(testInput); + fail(); + } catch (DukeException e) { + assertEquals("!!!!!!!I DON'T KNOW WHAT U SAYING BRO!!!!!!!", e.getMessage()); + } + } + + + @Test + void extractTaskTest() throws DukeException { + String testInput = "deadline project/2019-10-22"; + String actualTask = Parser.extractTask(testInput, "deadline"); + assertEquals("project", actualTask); + } + + @Test + void extractTask_emptyTask_exception() { + try { + String testInput = "deadline "; + Parser.extractTask(testInput, "deadline"); + fail(); + } catch (DukeException e) { + assertEquals("!!!!!!!!!Walao!NO TASK!!!!!!!!!!", e.getMessage()); + } + } + + @Test + void extractDateTest() throws DukeException { + String testInput = "deadline project /2019-10-22"; + String actualDate = Parser.extractDate(testInput, "deadline"); + assertEquals("Oct 22 2019", actualDate); + } + + @Test + void extractDate_withoutSlash_exception() { + try { + String testInput = "deadline project"; + Parser.extractDate(testInput, "deadline"); + fail(); + } catch (DukeException e) { + assertEquals("!!!Fill ur date lah (add date with / in yyyy-mm-dd format)!!!", e.getMessage()); + } + + } + @Test + void extractDate_wrongDateFormat_exception() { + try { + String testInput = "event project/2019"; + Parser.extractDate(testInput, "event"); + fail(); + } catch (DukeException e) { + assertEquals("!!!Err, wrong date format.. (yyyy-mm-dd)!!!", e.getMessage()); + } + } } diff --git a/src/test/java/duke/utils/TaskStorageTest.java b/src/test/java/duke/utils/TaskStorageTest.java index d07c7b1deb..f9b1d6edb8 100644 --- a/src/test/java/duke/utils/TaskStorageTest.java +++ b/src/test/java/duke/utils/TaskStorageTest.java @@ -1,23 +1,24 @@ package duke.utils; +import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; public class TaskStorageTest { - @Test - void writeToFilesTest() { - String actualOutput = TaskStorage.writeToFiles(); - String expectedOutput = "~~~~~~~~~~~File Saved Successfully!~~~~~~~~~~~~"; - assertEquals(actualOutput, expectedOutput); - } + @Test + void writeToFilesTest() { + String actualOutput = TaskStorage.writeToFiles(); + String expectedOutput = "~~~~~~~~~~~File Saved Successfully!~~~~~~~~~~~~"; + assertEquals(actualOutput, expectedOutput); + } - @Test - void loadFilesTest() { - String actualOutput = TaskStorage.loadFiles(); - String expectedOutput = "********** Awwww~ You don't have any history of tasks **********\n"; - assertEquals(actualOutput, expectedOutput); - } + @Test + void loadFilesTest() { + String actualOutput = TaskStorage.loadFiles(); + String expectedOutput = "********** Awwww~ You don't have any history of tasks **********\n"; + assertEquals(actualOutput, expectedOutput); + } } From aac97e3755d2d4ec55c31e99507009b69fe0a537 Mon Sep 17 00:00:00 2001 From: Hzxin Date: Mon, 1 Feb 2021 20:11:00 +0800 Subject: [PATCH 40/62] Fix some coding style issues --- data/Duke.txt | 1 + src/main/java/duke/command/DeleteCommand.java | 2 +- src/main/java/duke/command/FindCommand.java | 10 +- src/main/java/duke/command/ListCommand.java | 2 +- src/main/java/duke/task/Task.java | 7 + src/main/java/duke/task/TaskList.java | 32 ++-- src/main/java/duke/utils/TaskStorage.java | 173 +++++++++--------- src/test/java/duke/task/TaskTest.java | 5 +- 8 files changed, 122 insertions(+), 110 deletions(-) diff --git a/data/Duke.txt b/data/Duke.txt index e69de29bb2..fe8cb8f292 100644 --- a/data/Duke.txt +++ b/data/Duke.txt @@ -0,0 +1 @@ +1@@X@@readbook diff --git a/src/main/java/duke/command/DeleteCommand.java b/src/main/java/duke/command/DeleteCommand.java index 3a9ee7547e..3586edc39d 100644 --- a/src/main/java/duke/command/DeleteCommand.java +++ b/src/main/java/duke/command/DeleteCommand.java @@ -28,7 +28,7 @@ private static Boolean handleDelete(String task, String date) { if (task.length() > 0 && date.equals("")) { try { int num = Integer.parseInt(task); - TaskList.delete(num); + TaskList.deleteTask(num); } catch (NumberFormatException e) { DukeException.numberFormatException(); } diff --git a/src/main/java/duke/command/FindCommand.java b/src/main/java/duke/command/FindCommand.java index 011daef35d..fc3eb392c2 100644 --- a/src/main/java/duke/command/FindCommand.java +++ b/src/main/java/duke/command/FindCommand.java @@ -2,11 +2,19 @@ import duke.task.TaskList; +/** + * Sub-class of Command to represents and execute the find instruction. + */ public class FindCommand extends Command { + /** + * Construct a find command object to execute findTasks operation. + * @param task user task. + * @param date date of the user task to be done. + */ public FindCommand(String task, String date) { super("find", task, date, command -> { - System.out.println(TaskList.find(task)); + System.out.println(TaskList.findTasks(task)); return false; }); } diff --git a/src/main/java/duke/command/ListCommand.java b/src/main/java/duke/command/ListCommand.java index 440443db31..052e9c020a 100644 --- a/src/main/java/duke/command/ListCommand.java +++ b/src/main/java/duke/command/ListCommand.java @@ -13,7 +13,7 @@ public class ListCommand extends Command { */ public ListCommand() { super("", "", "", command -> { - TaskList.list(); + TaskList.listTasks(); return false; }); } diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java index 3ad8214078..97edc40b96 100644 --- a/src/main/java/duke/task/Task.java +++ b/src/main/java/duke/task/Task.java @@ -25,6 +25,13 @@ public class Task { } + Task(String taskName, String isDone, boolean check) { + this.taskName = taskName; + this.index = capacity + 1; + this.isDone = isDone; + this.date = ""; + capacity++; + } Task(String taskName, String date) { this.taskName = taskName; diff --git a/src/main/java/duke/task/TaskList.java b/src/main/java/duke/task/TaskList.java index 932854b30f..0078cfa898 100644 --- a/src/main/java/duke/task/TaskList.java +++ b/src/main/java/duke/task/TaskList.java @@ -9,17 +9,13 @@ public class TaskList { - private static List taskList = new ArrayList<>(); + private static List tasks = new ArrayList<>(); - private List list; - public TaskList() { - this.list = new ArrayList<>(); - } public static void addTask(Task t) { - taskList.add(t); + tasks.add(t); } @@ -29,8 +25,8 @@ public static void addTask(Task t) { */ public static void markDone(int i) { try { - Task t = taskList.get(i - 1); - taskList.get(i - 1).markDone(); + Task t = tasks.get(i - 1); + tasks.get(i - 1).markDone(); Ui.doneTask(t); } catch (IndexOutOfBoundsException e) { DukeException.taskErrorException(); @@ -42,10 +38,10 @@ public static void markDone(int i) { * @param keyword keyword that the user want to search. * @return the matched tasks according to the keyword in String. */ - public static String find(String keyword) { + public static String findTasks(String keyword) { int index = 1; StringBuilder sb = new StringBuilder(""); - for (Task task : taskList) { + for (Task task : tasks) { String taskName = task.getTaskName(); if (taskName.contains(keyword)) { String prefix = task.toString().substring(0, 6); @@ -67,9 +63,9 @@ public static String find(String keyword) { /** * Display all the tasks in the list. */ - public static void list() { + public static void listTasks() { System.out.println(Ui.UPPER); - for (Task task : taskList) { + for (Task task : tasks) { if (task == null) { break; } @@ -82,12 +78,12 @@ public static void list() { * Delete a task in the task list with the given index. * @param i the index labelling of the task. */ - public static void delete(int i) { + public static void deleteTask(int i) { try { - Task t = taskList.get(i - 1); - taskList.remove(i - 1); + Task t = tasks.get(i - 1); + tasks.remove(i - 1); Ui.deleteTask(t); - for (Task task : taskList) { + for (Task task : tasks) { if (task.getIndex() > i) { task.changeIndex(task.getIndex() - 1); } @@ -98,11 +94,11 @@ public static void delete(int i) { } public static void clearAllTask() { - taskList.clear(); + tasks.clear(); } public static List getTaskList() { - return taskList; + return tasks; } } diff --git a/src/main/java/duke/utils/TaskStorage.java b/src/main/java/duke/utils/TaskStorage.java index 4695e6bf55..cf00afd779 100644 --- a/src/main/java/duke/utils/TaskStorage.java +++ b/src/main/java/duke/utils/TaskStorage.java @@ -16,91 +16,90 @@ */ public class TaskStorage { - public static final String FILEPATH = "data/Duke.txt"; - public static final String DIRECTORY = "data"; - - - /** - * This method write the content of a taskList to data/Duke.txt. - * - * @return A string display of a successful save. - */ - public static String writeToFiles() { - List taskList = TaskList.getTaskList(); - try { - FileWriter fw = new FileWriter(FILEPATH); - for (Task t : taskList) { - String temp = t.getType() + "@@" + t.getDoneStatus() - + "@@" + t.getTaskName() + (t.getDate().equals("") - ? "" : ("@@" + t.getDate())) + System.lineSeparator(); - fw.write(temp); - } - fw.close(); - } catch (IOException err) { - DukeException.saveToFileError(); - } - return Ui.SUCCESSFUL_SAVE; - } - - - - /** - * This method load the file from data/Duke.txt and display in a list format when the program starts. - * - * @return the String display of a successful load. - */ - public static String loadFiles() { - String output = Ui.LOAD_FILE; - System.out.println(output); - try { - File directory = new File(DIRECTORY); - if (!directory.exists()) { - System.out.println(Ui.NO_DIRECTORY); - directory.mkdir(); - Ui.sleep(); - } - - File file = new File(FILEPATH); - if (!file.exists()) { - System.out.println(Ui.NO_FILE); - file.createNewFile(); - Ui.sleep(); - } - - if (file.length() == 0) { - Ui.sleep(); - System.out.println(Ui.EMPTY_FILE); - return Ui.EMPTY_FILE; - } - - restoreTask(file); - Ui.displayTask(); - } catch (IOException e) { - System.out.println("IO error!: " + e.getMessage()); - } - - return Ui.SUCESSFUL_LOAD; - } - - private static void restoreTask(File file) throws IOException { - Scanner sc = new Scanner(file); - - while (sc.hasNext()) { - String[] line = sc.nextLine().split("@@"); - if (line.length == 3) { - Todo t = new Todo(line[2], line[1]); - TaskList.addTask(t); - - } else { - int type = Integer.parseInt(line[0]); - String done = line[1]; - String taskName = line[2]; - String date = line[3]; - Task t = type == 2 ? new Deadlines(taskName, date, done) : new Event(taskName, date, done); - TaskList.addTask(t); - - } - } - sc.close(); - } + public static final String FILEPATH = "data/Duke.txt"; + public static final String DIRECTORY = "data"; + + + /** + * This method write the content of a taskList to data/Duke.txt. + * + * @return A string display of a successful save. + */ + public static String writeToFiles() { + List taskList = TaskList.getTaskList(); + try { + FileWriter fw = new FileWriter(FILEPATH); + for (Task t : taskList) { + String temp = t.getType() + "@@" + t.getDoneStatus() + + "@@" + t.getTaskName() + (t.getDate().equals("") + ? "" : ("@@" + t.getDate())) + System.lineSeparator(); + fw.write(temp); + } + fw.close(); + } catch (IOException err) { + DukeException.saveToFileError(); + } + return Ui.SUCCESSFUL_SAVE; + } + + + /** + * This method load the file from data/Duke.txt and display in a list format when the program starts. + * + * @return the String display of a successful load. + */ + public static String loadFiles() { + String output = Ui.LOAD_FILE; + System.out.println(output); + try { + File directory = new File(DIRECTORY); + if (!directory.exists()) { + System.out.println(Ui.NO_DIRECTORY); + directory.mkdir(); + Ui.sleep(); + } + + File file = new File(FILEPATH); + if (!file.exists()) { + System.out.println(Ui.NO_FILE); + file.createNewFile(); + Ui.sleep(); + } + + if (file.length() == 0) { + Ui.sleep(); + System.out.println(Ui.EMPTY_FILE); + return Ui.EMPTY_FILE; + } + + restoreTask(file); + Ui.displayTask(); + } catch (IOException e) { + System.out.println("IO error!: " + e.getMessage()); + } + + return Ui.SUCESSFUL_LOAD; + } + + private static void restoreTask(File file) throws IOException { + Scanner sc = new Scanner(file); + + while (sc.hasNext()) { + String[] line = sc.nextLine().split("@@"); + if (line.length == 3) { + Todo t = new Todo(line[2], line[1]); + TaskList.addTask(t); + + } else { + int type = Integer.parseInt(line[0]); + String done = line[1]; + String taskName = line[2]; + String date = line[3]; + Task t = type == 2 ? new Deadlines(taskName, date, done) : new Event(taskName, date, done); + TaskList.addTask(t); + + } + } + sc.close(); + } } diff --git a/src/test/java/duke/task/TaskTest.java b/src/test/java/duke/task/TaskTest.java index b87bf7cb41..f345220fef 100644 --- a/src/test/java/duke/task/TaskTest.java +++ b/src/test/java/duke/task/TaskTest.java @@ -1,8 +1,9 @@ package duke.task; +import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; class TaskTest { @@ -20,7 +21,7 @@ void delete() { TaskList.clearAllTask(); Todo task = new Todo("Scratch back", " "); TaskList.addTask(task); - TaskList.delete(1); + TaskList.deleteTask(1); assertEquals(0, TaskList.getTaskList().size()); } } \ No newline at end of file From abfaa7ee74ed9dc124e50f086c9c957ff5b1aaec Mon Sep 17 00:00:00 2001 From: Hzxin Date: Mon, 1 Feb 2021 20:26:59 +0800 Subject: [PATCH 41/62] Remove capacity variable from Task and add getter for list size in TaskList --- data/Duke.txt | 3 ++- src/main/java/duke/driver/DukeDriver.java | 4 ++-- src/main/java/duke/task/Task.java | 23 +++++------------------ src/main/java/duke/task/TaskList.java | 15 ++++++++++++--- src/main/java/duke/ui/Ui.java | 2 +- 5 files changed, 22 insertions(+), 25 deletions(-) diff --git a/data/Duke.txt b/data/Duke.txt index fe8cb8f292..5283679f57 100644 --- a/data/Duke.txt +++ b/data/Duke.txt @@ -1 +1,2 @@ -1@@X@@readbook +1@@X@@swimming +1@@ @@project diff --git a/src/main/java/duke/driver/DukeDriver.java b/src/main/java/duke/driver/DukeDriver.java index 6bfb49428a..e031af708d 100644 --- a/src/main/java/duke/driver/DukeDriver.java +++ b/src/main/java/duke/driver/DukeDriver.java @@ -27,8 +27,8 @@ public static void executeDuke() { while (sc.hasNext()) { String message = sc.nextLine(); - boolean bye = inputHandler(message); - if (bye) { + boolean willExit = inputHandler(message); + if (willExit) { break; } } diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java index 97edc40b96..520ccd844b 100644 --- a/src/main/java/duke/task/Task.java +++ b/src/main/java/duke/task/Task.java @@ -5,7 +5,6 @@ * A class that store the task that user key in. */ public class Task { - private static int capacity = 0; private final String taskName; private int index; private String isDone; @@ -18,35 +17,30 @@ public class Task { */ Task(String taskName) { this.taskName = taskName; - this.index = capacity + 1; + this.index = TaskList.getTasksSize() + 1; this.isDone = " "; this.date = ""; - capacity++; - } Task(String taskName, String isDone, boolean check) { this.taskName = taskName; - this.index = capacity + 1; + this.index = TaskList.getTasksSize() + 1; this.isDone = isDone; this.date = ""; - capacity++; } Task(String taskName, String date) { this.taskName = taskName; - this.index = capacity + 1; + this.index = TaskList.getTasksSize() + 1; this.isDone = " "; this.date = date; - capacity++; } Task(String taskName, String date, String done) { this.taskName = taskName; - this.index = capacity + 1; + this.index = TaskList.getTasksSize() + 1; this.isDone = done; this.date = date; - capacity++; } @@ -98,14 +92,7 @@ public String getDate() { return date; } - /** - * get the current capacity of the taskList. - * - * @return the int representation of the capacity of the taskList. - */ - public static int getCapacity() { - return Task.capacity; - } + @Override public String toString() { diff --git a/src/main/java/duke/task/TaskList.java b/src/main/java/duke/task/TaskList.java index 0078cfa898..bf27b89440 100644 --- a/src/main/java/duke/task/TaskList.java +++ b/src/main/java/duke/task/TaskList.java @@ -7,13 +7,10 @@ import duke.ui.Ui; - public class TaskList { private static List tasks = new ArrayList<>(); - - public static void addTask(Task t) { tasks.add(t); } @@ -21,6 +18,7 @@ public static void addTask(Task t) { /** * This method marks a task in the list as done. + * * @param i index labelling of the task in list. */ public static void markDone(int i) { @@ -35,6 +33,7 @@ public static void markDone(int i) { /** * This method finds all relevant tasks according to the keyword. + * * @param keyword keyword that the user want to search. * @return the matched tasks according to the keyword in String. */ @@ -76,6 +75,7 @@ public static void listTasks() { /** * Delete a task in the task list with the given index. + * * @param i the index labelling of the task. */ public static void deleteTask(int i) { @@ -101,4 +101,13 @@ public static List getTaskList() { return tasks; } + + /** + * Obtain the total number of tasks in the list. + * @return the number of tasks in the list. + */ + public static int getTasksSize() { + return tasks.size(); + } + } diff --git a/src/main/java/duke/ui/Ui.java b/src/main/java/duke/ui/Ui.java index 3a8c048f42..28ad1818f0 100644 --- a/src/main/java/duke/ui/Ui.java +++ b/src/main/java/duke/ui/Ui.java @@ -67,7 +67,7 @@ public static void deleteTask(Task t) { public static String biggerBox(Task t) { return Ui.UPPER + "Added liao: " + t.toString() + Ui.LINEBREAK - + "You have " + Task.getCapacity() + " tasks in the list!" + + "You have " + TaskList.getTasksSize() + " tasks in the list!" + Ui.LOWER; } From 5ec78ef4913592096de0526fa902da2173bc1ce7 Mon Sep 17 00:00:00 2001 From: Hzxin Date: Wed, 3 Feb 2021 01:39:15 -0800 Subject: [PATCH 42/62] Gradle set up for JavaFx --- build.gradle | 17 ++++++++ src/main/java/duke/Duke.java | 69 +++++++++++++++++++++++++++++++- src/main/java/duke/Launcher.java | 13 ++++++ 3 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 src/main/java/duke/Launcher.java diff --git a/build.gradle b/build.gradle index 1701000c43..ad55baee93 100644 --- a/build.gradle +++ b/build.gradle @@ -11,9 +11,26 @@ repositories { } dependencies { + implementation 'org.junit.jupiter:junit-jupiter:5.4.2' implementation 'org.junit.jupiter:junit-jupiter:5.4.2' testCompile group: 'junit', name: 'junit', version: '4.12' + + + //JavaFx + String javaFxVersion = '11' + implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'linux' + implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'linux' + implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'linux' + implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'linux' } test { diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java index 21e6642b0d..285162c4b7 100644 --- a/src/main/java/duke/Duke.java +++ b/src/main/java/duke/Duke.java @@ -2,11 +2,76 @@ import duke.driver.DukeDriver; - +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TextField; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.Region; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; /** * Encapsulates the main class of the Object. */ -public class Duke { +public class Duke extends Application { + private ScrollPane scrollPane; + private VBox dialogContainer; + private TextField userInput; + private Button sendButton; + private Scene scene; + + @Override + public void start(Stage stage) { + //Step 1. Setting up required components + + //The container for the content of the chat to scroll. + scrollPane = new ScrollPane(); + dialogContainer = new VBox(); + scrollPane.setContent(dialogContainer); + + userInput = new TextField(); + sendButton = new Button("Send"); + + AnchorPane mainLayout = new AnchorPane(); + mainLayout.getChildren().addAll(scrollPane, userInput, sendButton); + + scene = new Scene(mainLayout); + + stage.setScene(scene); + stage.show(); + + stage.setTitle("Duke"); + stage.setResizable(false); + stage.setMinHeight(800); + stage.setMinWidth(500); + + mainLayout.setPrefSize(500, 800); + scrollPane.setPrefSize(450, 750); + scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); + scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS); + scrollPane.setVvalue(1.0); + scrollPane.setFitToWidth(true); + + // You will need to import `javafx.scene.layout.Region` for this. + dialogContainer.setPrefHeight(Region.USE_COMPUTED_SIZE); + + userInput.setPrefWidth(325.0); + + sendButton.setPrefWidth(55.0); + + AnchorPane.setTopAnchor(scrollPane, 1.0); + + AnchorPane.setBottomAnchor(sendButton, 1.0); + AnchorPane.setRightAnchor(sendButton, 1.0); + + AnchorPane.setLeftAnchor(userInput , 1.0); + AnchorPane.setBottomAnchor(userInput, 1.0); + + + // more code to be added here later + } + /** * Executes the programs. diff --git a/src/main/java/duke/Launcher.java b/src/main/java/duke/Launcher.java new file mode 100644 index 0000000000..a24face653 --- /dev/null +++ b/src/main/java/duke/Launcher.java @@ -0,0 +1,13 @@ +package duke; + +import duke.Duke; +import javafx.application.Application; + +/** + * A launcher class to workaround classpath issues. + */ +public class Launcher { + public static void main(String[] args) { + Application.launch(Duke.class, args); + } +} From e0f0ae6d132733d0ff550f68bdfa62b9b7cade95 Mon Sep 17 00:00:00 2001 From: Hzxin Date: Thu, 4 Feb 2021 05:49:03 -0800 Subject: [PATCH 43/62] remove DukeDriver, implement GUI --- data/Duke.txt | 2 - src/main/java/duke/Duke.java | 71 +-------------- src/main/java/duke/Launcher.java | 13 --- src/main/java/duke/Main.java | 32 +++++++ src/main/java/duke/command/AddCommand.java | 44 ++++----- src/main/java/duke/command/Command.java | 12 ++- src/main/java/duke/command/DeleteCommand.java | 12 ++- src/main/java/duke/command/DoneCommand.java | 13 ++- src/main/java/duke/command/ErrorCommand.java | 5 +- src/main/java/duke/command/ExitCommand.java | 9 +- src/main/java/duke/command/FindCommand.java | 7 +- src/main/java/duke/command/ListCommand.java | 6 +- src/main/java/duke/driver/DukeDriver.java | 51 ----------- src/main/java/duke/task/TaskList.java | 22 +++-- src/main/java/duke/ui/DialogBox.java | 64 +++++++++++++ src/main/java/duke/ui/ErrorBox.java | 44 +++++++++ src/main/java/duke/ui/MainMenu.java | 55 ++++++++++++ src/main/java/duke/ui/MainWindow.java | 85 ++++++++++++++++++ src/main/java/duke/ui/Ui.java | 84 +++++------------ src/main/java/duke/utils/DateAndTime.java | 4 + src/main/java/duke/utils/Parser.java | 14 ++- src/main/java/duke/utils/TaskStorage.java | 35 ++++---- src/main/resources/images/cat1.jpg | Bin 0 -> 43297 bytes src/main/resources/images/cat2.jpg | Bin 0 -> 49067 bytes src/main/resources/view/DialogBox.fxml | 16 ++++ src/main/resources/view/MainMenu.fxml | 26 ++++++ src/main/resources/view/MainWindow.fxml | 19 ++++ 27 files changed, 477 insertions(+), 268 deletions(-) delete mode 100644 src/main/java/duke/Launcher.java create mode 100644 src/main/java/duke/Main.java delete mode 100644 src/main/java/duke/driver/DukeDriver.java create mode 100644 src/main/java/duke/ui/DialogBox.java create mode 100644 src/main/java/duke/ui/ErrorBox.java create mode 100644 src/main/java/duke/ui/MainMenu.java create mode 100644 src/main/java/duke/ui/MainWindow.java create mode 100644 src/main/resources/images/cat1.jpg create mode 100644 src/main/resources/images/cat2.jpg create mode 100644 src/main/resources/view/DialogBox.fxml create mode 100644 src/main/resources/view/MainMenu.fxml create mode 100644 src/main/resources/view/MainWindow.fxml diff --git a/data/Duke.txt b/data/Duke.txt index 5283679f57..e69de29bb2 100644 --- a/data/Duke.txt +++ b/data/Duke.txt @@ -1,2 +0,0 @@ -1@@X@@swimming -1@@ @@project diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java index 285162c4b7..47593a23ef 100644 --- a/src/main/java/duke/Duke.java +++ b/src/main/java/duke/Duke.java @@ -1,76 +1,13 @@ package duke; -import duke.driver.DukeDriver; import javafx.application.Application; -import javafx.scene.Scene; -import javafx.scene.control.Button; -import javafx.scene.control.ScrollPane; -import javafx.scene.control.TextField; -import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.Region; -import javafx.scene.layout.VBox; -import javafx.stage.Stage; + + /** * Encapsulates the main class of the Object. */ -public class Duke extends Application { - private ScrollPane scrollPane; - private VBox dialogContainer; - private TextField userInput; - private Button sendButton; - private Scene scene; - - @Override - public void start(Stage stage) { - //Step 1. Setting up required components - - //The container for the content of the chat to scroll. - scrollPane = new ScrollPane(); - dialogContainer = new VBox(); - scrollPane.setContent(dialogContainer); - - userInput = new TextField(); - sendButton = new Button("Send"); - - AnchorPane mainLayout = new AnchorPane(); - mainLayout.getChildren().addAll(scrollPane, userInput, sendButton); - - scene = new Scene(mainLayout); - - stage.setScene(scene); - stage.show(); - - stage.setTitle("Duke"); - stage.setResizable(false); - stage.setMinHeight(800); - stage.setMinWidth(500); - - mainLayout.setPrefSize(500, 800); - scrollPane.setPrefSize(450, 750); - scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); - scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS); - scrollPane.setVvalue(1.0); - scrollPane.setFitToWidth(true); - - // You will need to import `javafx.scene.layout.Region` for this. - dialogContainer.setPrefHeight(Region.USE_COMPUTED_SIZE); - - userInput.setPrefWidth(325.0); - - sendButton.setPrefWidth(55.0); - - AnchorPane.setTopAnchor(scrollPane, 1.0); - - AnchorPane.setBottomAnchor(sendButton, 1.0); - AnchorPane.setRightAnchor(sendButton, 1.0); - - AnchorPane.setLeftAnchor(userInput , 1.0); - AnchorPane.setBottomAnchor(userInput, 1.0); - - - // more code to be added here later - } +public class Duke { /** @@ -80,7 +17,7 @@ public void start(Stage stage) { */ public static void main(String[] args) { - DukeDriver.executeDuke(); + Application.launch(Main.class, args); } diff --git a/src/main/java/duke/Launcher.java b/src/main/java/duke/Launcher.java deleted file mode 100644 index a24face653..0000000000 --- a/src/main/java/duke/Launcher.java +++ /dev/null @@ -1,13 +0,0 @@ -package duke; - -import duke.Duke; -import javafx.application.Application; - -/** - * A launcher class to workaround classpath issues. - */ -public class Launcher { - public static void main(String[] args) { - Application.launch(Duke.class, args); - } -} diff --git a/src/main/java/duke/Main.java b/src/main/java/duke/Main.java new file mode 100644 index 0000000000..a592fe27bc --- /dev/null +++ b/src/main/java/duke/Main.java @@ -0,0 +1,32 @@ +package duke; + +import java.io.IOException; + +import duke.ui.MainWindow; +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.layout.AnchorPane; +import javafx.stage.Stage; +import javafx.stage.Window; + +/** + * A GUI for Duke using FXML. + */ +public class Main extends Application { + + + + @Override + public void start(Stage stage) { + try { + FXMLLoader fxmlLoader = new FXMLLoader(Main.class.getResource("/view/MainMenu.fxml")); + AnchorPane ap = fxmlLoader.load(); + Scene scene = new Scene(ap); + stage.setScene(scene); + stage.show(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/duke/command/AddCommand.java b/src/main/java/duke/command/AddCommand.java index 7b90f6beff..aa9644f0fd 100644 --- a/src/main/java/duke/command/AddCommand.java +++ b/src/main/java/duke/command/AddCommand.java @@ -20,7 +20,7 @@ public class AddCommand extends Command { * @param date date of the user task to be done. */ public AddCommand(String instruction, String task, String date) { - super(instruction, task, date, command -> { + super(instruction, task, date, false, command -> { if (instruction.equals("todo")) { return handleToDo(task); } else if (instruction.equals("deadline")) { @@ -37,35 +37,35 @@ public AddCommand(String instruction, String task, String date) { * * @param task name of the user task. */ - private static Boolean handleToDo(String task) { - if (!task.equals("")) { - Todo todo = new Todo(task); - TaskList.addTask(todo); - System.out.println(Ui.biggerBox(todo)); - } - return false; + private static String handleToDo(String task) { + + Todo todo = new Todo(task); + TaskList.addTask(todo); + System.out.println(Ui.biggerBox(todo)); + + return Ui.biggerBox(todo); } - private static Boolean handleDeadline(String task, String date) { + private static String handleDeadline(String task, String date) { + - if (!date.equals("")) { - Deadlines deadlines = new Deadlines(task, date); - TaskList.addTask(deadlines); - System.out.println(Ui.biggerBox(deadlines)); - } + Deadlines deadlines = new Deadlines(task, date); + TaskList.addTask(deadlines); + System.out.println(Ui.biggerBox(deadlines)); - return false; + + return Ui.biggerBox(deadlines); } - private static Boolean handleEvent(String task, String date) { - if (!task.equals("") && !date.equals("")) { - Event event = new Event(task, date); - TaskList.addTask(event); - System.out.println(Ui.biggerBox(event)); - } - return false; + private static String handleEvent(String task, String date) { + + Event event = new Event(task, date); + TaskList.addTask(event); + System.out.println(Ui.biggerBox(event)); + + return Ui.biggerBox(event); } } diff --git a/src/main/java/duke/command/Command.java b/src/main/java/duke/command/Command.java index 09e2532ce1..a03305f482 100644 --- a/src/main/java/duke/command/Command.java +++ b/src/main/java/duke/command/Command.java @@ -9,7 +9,8 @@ public abstract class Command { private final String instruction; private final String task; private final String date; - private final Function func; + private boolean isExit; + private final Function func; /** @@ -20,10 +21,11 @@ public abstract class Command { * @param date date of the task. * @param func the function takes a command to execute the task and returns a boolean whether to end the program. */ - public Command(String instruction, String task, String date, Function func) { + public Command(String instruction, String task, String date, boolean isExit, Function func) { this.instruction = instruction; this.task = task; this.date = date; + this.isExit = isExit; this.func = func; } @@ -33,11 +35,13 @@ public Command(String instruction, String task, String date, Function handleDelete(task, date)); } @@ -24,16 +26,18 @@ public DeleteCommand(String task, String date) { * @param task user task in String. * @param date date of the task. */ - private static Boolean handleDelete(String task, String date) { + private static String handleDelete(String task, String date) { if (task.length() > 0 && date.equals("")) { try { int num = Integer.parseInt(task); - TaskList.deleteTask(num); + String result = TaskList.deleteTask(num); + return result; } catch (NumberFormatException e) { DukeException.numberFormatException(); + ErrorBox.display(Ui.KEY_IN_NUMBER); } } - return false; + return ""; } } diff --git a/src/main/java/duke/command/DoneCommand.java b/src/main/java/duke/command/DoneCommand.java index 8ecdac2425..7dd3bfe815 100644 --- a/src/main/java/duke/command/DoneCommand.java +++ b/src/main/java/duke/command/DoneCommand.java @@ -2,6 +2,8 @@ import duke.exceptions.DukeException; import duke.task.TaskList; +import duke.ui.ErrorBox; +import duke.ui.Ui; /** @@ -11,7 +13,8 @@ public class DoneCommand extends Command { public DoneCommand(String task, String date) { - super("done", task, date, command -> handleDone(task)); + super("done", task, date, false, + command -> handleDone(task)); } @@ -20,16 +23,18 @@ public DoneCommand(String task, String date) { * * @param task name of the user task. */ - private static Boolean handleDone(String task) { + private static String handleDone(String task) { if (task.length() > 0) { try { int num = Integer.parseInt(task); - TaskList.markDone(num); + String result = TaskList.markDone(num); + return result; } catch (NumberFormatException e) { DukeException.numberFormatException(); + ErrorBox.display(Ui.KEY_IN_NUMBER); } } - return false; + return ""; } diff --git a/src/main/java/duke/command/ErrorCommand.java b/src/main/java/duke/command/ErrorCommand.java index 5f93568394..0951480e73 100644 --- a/src/main/java/duke/command/ErrorCommand.java +++ b/src/main/java/duke/command/ErrorCommand.java @@ -5,7 +5,8 @@ * Sub-class of Command to represents any error in the instruction of user. */ public class ErrorCommand extends Command { - public ErrorCommand() { - super("", "", "", command -> false); + public ErrorCommand(String error) { + super("", "", "", false, + command -> "I don't know what you saying"); } } diff --git a/src/main/java/duke/command/ExitCommand.java b/src/main/java/duke/command/ExitCommand.java index 9932e7c630..befde3c417 100644 --- a/src/main/java/duke/command/ExitCommand.java +++ b/src/main/java/duke/command/ExitCommand.java @@ -1,17 +1,20 @@ package duke.command; +import duke.ui.Ui; + /** * Sub-class of command that represents and execute the "bye" instruction of user. */ public class ExitCommand extends Command { public ExitCommand(String task, String date) { - super("bye", task, date, command -> handleBye(task, date)); + super("bye", task, date, true, + command -> handleBye()); } - private static boolean handleBye(String task, String date) { - return task.equals("") && date.equals(""); + private static String handleBye() { + return Ui.FAREWELL; } } diff --git a/src/main/java/duke/command/FindCommand.java b/src/main/java/duke/command/FindCommand.java index fc3eb392c2..ee949686c5 100644 --- a/src/main/java/duke/command/FindCommand.java +++ b/src/main/java/duke/command/FindCommand.java @@ -13,9 +13,10 @@ public class FindCommand extends Command { * @param date date of the user task to be done. */ public FindCommand(String task, String date) { - super("find", task, date, command -> { - System.out.println(TaskList.findTasks(task)); - return false; + super("find", task, date, false, command -> { + String result = TaskList.findTasks(task); + System.out.println(result); + return result; }); } diff --git a/src/main/java/duke/command/ListCommand.java b/src/main/java/duke/command/ListCommand.java index 052e9c020a..d9a0cdbd4f 100644 --- a/src/main/java/duke/command/ListCommand.java +++ b/src/main/java/duke/command/ListCommand.java @@ -12,9 +12,9 @@ public class ListCommand extends Command { * Create a ListCommand object to carry out listing of tasks. */ public ListCommand() { - super("", "", "", command -> { - TaskList.listTasks(); - return false; + super("", "", "", false, command -> { + String result = TaskList.listTasks(); + return result; }); } } diff --git a/src/main/java/duke/driver/DukeDriver.java b/src/main/java/duke/driver/DukeDriver.java deleted file mode 100644 index e031af708d..0000000000 --- a/src/main/java/duke/driver/DukeDriver.java +++ /dev/null @@ -1,51 +0,0 @@ -package duke.driver; - -import java.util.Scanner; - -import duke.command.Command; -import duke.ui.Ui; -import duke.utils.Parser; -import duke.utils.TaskStorage; - - -/** - * Driver class of Duke that handles the command key in by user and respond. - */ -public class DukeDriver { - - /** - * Take in user input and execute the Duke program. - */ - public static void executeDuke() { - Scanner sc = new Scanner(System.in); - System.out.println(Ui.LOGO); - System.out.println(Ui.GREETING); - - Ui.sleep(); - - TaskStorage.loadFiles(); - - while (sc.hasNext()) { - String message = sc.nextLine(); - boolean willExit = inputHandler(message); - if (willExit) { - break; - } - } - System.out.println(Ui.FAREWELL); - } - - - /** - * The main handler of all the command. - * - * @param message String representation of the message key in by user. - * @return a boolean to whether to exit the program. - */ - private static boolean inputHandler(String message) { - Command command = new Parser(message).parse(); - return command.execute(); - } - - -} diff --git a/src/main/java/duke/task/TaskList.java b/src/main/java/duke/task/TaskList.java index bf27b89440..fbb4d69e74 100644 --- a/src/main/java/duke/task/TaskList.java +++ b/src/main/java/duke/task/TaskList.java @@ -4,6 +4,7 @@ import java.util.List; import duke.exceptions.DukeException; +import duke.ui.ErrorBox; import duke.ui.Ui; @@ -21,14 +22,17 @@ public static void addTask(Task t) { * * @param i index labelling of the task in list. */ - public static void markDone(int i) { + public static String markDone(int i) { try { Task t = tasks.get(i - 1); tasks.get(i - 1).markDone(); - Ui.doneTask(t); + String result = Ui.doneTask(t); + return result; } catch (IndexOutOfBoundsException e) { DukeException.taskErrorException(); + ErrorBox.display(e.getMessage()); } + return ""; } /** @@ -62,15 +66,18 @@ public static String findTasks(String keyword) { /** * Display all the tasks in the list. */ - public static void listTasks() { - System.out.println(Ui.UPPER); + public static String listTasks() { + StringBuilder sb = new StringBuilder(""); + for (Task task : tasks) { if (task == null) { break; } System.out.println(task); + sb.append(task.toString() + "\n"); } - System.out.println(Ui.LOWER); + + return sb.toString(); } /** @@ -78,7 +85,7 @@ public static void listTasks() { * * @param i the index labelling of the task. */ - public static void deleteTask(int i) { + public static String deleteTask(int i) { try { Task t = tasks.get(i - 1); tasks.remove(i - 1); @@ -88,8 +95,11 @@ public static void deleteTask(int i) { task.changeIndex(task.getIndex() - 1); } } + return Ui.deleteTask(t); } catch (IndexOutOfBoundsException e) { DukeException.taskErrorException(); + ErrorBox.display(e.getMessage()); + return ""; } } diff --git a/src/main/java/duke/ui/DialogBox.java b/src/main/java/duke/ui/DialogBox.java new file mode 100644 index 0000000000..49aec9d60c --- /dev/null +++ b/src/main/java/duke/ui/DialogBox.java @@ -0,0 +1,64 @@ +package duke.ui; + +import java.io.IOException; +import java.util.Collections; + +import duke.ui.MainWindow; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.HBox; + +/** + * An example of a custom control using FXML. + * This control represents a dialog box consisting of an ImageView to represent the speaker's face and a label + * containing text from the speaker. + */ +public class DialogBox extends HBox { + @FXML + private Label dialog; + @FXML + private ImageView displayPicture; + + private DialogBox(String text, Image img) { + try { + FXMLLoader fxmlLoader = new FXMLLoader(MainWindow.class.getResource("/view/DialogBox.fxml")); + fxmlLoader.setController(this); + fxmlLoader.setRoot(this); + fxmlLoader.load(); + } catch (IOException e) { + e.printStackTrace(); + } + + dialog.setText(text); + displayPicture.setImage(img); + } + + /** + * Flips the dialog box such that the ImageView is on the left and text on the right. + */ + private void flip() { + ObservableList tmp = FXCollections.observableArrayList(this.getChildren()); + Collections.reverse(tmp); + getChildren().setAll(tmp); + setAlignment(Pos.TOP_LEFT); + } + + + + public static DialogBox getUserDialog(String text, Image img) { + return new DialogBox(text, img); + } + + public static DialogBox getDukeDialog(String text, Image img) { + DialogBox dialogBox = new DialogBox(text, img); + dialogBox.flip(); + return dialogBox; + } +} \ No newline at end of file diff --git a/src/main/java/duke/ui/ErrorBox.java b/src/main/java/duke/ui/ErrorBox.java new file mode 100644 index 0000000000..55087691e9 --- /dev/null +++ b/src/main/java/duke/ui/ErrorBox.java @@ -0,0 +1,44 @@ +package duke.ui; + + +import javafx.geometry.Pos; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.layout.VBox; +import javafx.stage.Modality; +import javafx.stage.Stage; + +/** + * Encapsulates an ErrorBox class that deals with and display exceptions. + */ +public class ErrorBox { + /** + * Displays an alert box with the given title and the alert message. + * + * @param message the main message of the alert. + */ + public static void display(String message) { + Stage window = new Stage(); + + // disable actions in other windows + window.initModality(Modality.APPLICATION_MODAL); + window.setTitle(""); + window.setMinWidth(250); + + Label alertContent = new Label(); + alertContent.setText(message); + alertContent.setWrapText(true); + Button closeButton = new Button("Close"); + closeButton.setOnAction(e -> window.close()); + closeButton.setDefaultButton(true); + + VBox layout = new VBox(20); + layout.getChildren().addAll(alertContent, closeButton); + layout.setAlignment(Pos.CENTER); + + Scene scene = new Scene(layout, 300, 300); + window.setScene(scene); + window.showAndWait(); + } +} \ No newline at end of file diff --git a/src/main/java/duke/ui/MainMenu.java b/src/main/java/duke/ui/MainMenu.java new file mode 100644 index 0000000000..9a55711833 --- /dev/null +++ b/src/main/java/duke/ui/MainMenu.java @@ -0,0 +1,55 @@ +package duke.ui; + + +import duke.Duke; +import duke.Main; +import javafx.application.Application; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.geometry.Pos; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.VBox; +import javafx.stage.Modality; +import javafx.stage.Stage; + +import java.io.IOException; + +/** + * Encapsulates an MainMenu class that deals with displaying an alert UI. + */ +public class MainMenu { + + @FXML + private VBox logoBox; + + @FXML + private Label dukeLogo; + + @FXML + private Button startButton; + + + @FXML + private void initialize() { + dukeLogo.setText(Ui.LOGO); + } + + + + @FXML + private void switchWindow() { + try { + Stage stage = (Stage)startButton.getScene().getWindow(); + Parent root = FXMLLoader.load(duke.Main.class.getResource("/view/MainWindow.fxml")); + Scene scene = new Scene(root); + stage.setScene(scene); + stage.show(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/duke/ui/MainWindow.java b/src/main/java/duke/ui/MainWindow.java new file mode 100644 index 0000000000..71a9157e7f --- /dev/null +++ b/src/main/java/duke/ui/MainWindow.java @@ -0,0 +1,85 @@ +package duke.ui; + +import duke.Duke; +import duke.command.Command; +import duke.utils.Parser; +import duke.utils.TaskStorage; +import javafx.application.Platform; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TextField; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.VBox; +/** + * Controller for MainWindow. Provides the layout for the other controls. + */ +public class MainWindow extends AnchorPane { + @FXML + private ScrollPane scrollPane; + @FXML + private VBox dialogContainer; + @FXML + private TextField userInput; + @FXML + private Button sendButton; + + private Duke duke; + private String response; + + private Image dukeImage = new Image(this.getClass().getResourceAsStream("/images/cat1.jpg")); + private Image userImage = new Image(this.getClass().getResourceAsStream("/images/cat2.jpg")); + + @FXML + public void initialize() { + scrollPane.vvalueProperty().bind(dialogContainer.heightProperty()); + dialogContainer.getChildren().addAll( + DialogBox.getDukeDialog(Ui.GREETING, dukeImage), + DialogBox.getDukeDialog(TaskStorage.loadFiles(), dukeImage) + ); + + } + + + /** + * Creates two dialog boxes, one echoing user input and the other containing Duke's reply and then appends them to + * the dialog container. Clears the user input after processing. + */ + @FXML + private void handleUserInput() { + String userText = userInput.getText(); + Parser parser = new Parser(userText); + Command command = parser.parse(); + response = command.execute(); + String dukeText = response; + + if (response.equals(Ui.FAREWELL)) { + Platform.exit(); + } + + if (!response.equals("")) { + dialogContainer.getChildren().addAll( + DialogBox.getUserDialog(userText, userImage), + DialogBox.getDukeDialog(dukeText, dukeImage) + ); + } else { + dialogContainer.getChildren().addAll( + DialogBox.getDukeDialog(Ui.COMMAND_ERROR, dukeImage) + ); + } + + + + userInput.clear(); + } + + private void saveFiles() { + + } + + + +} \ No newline at end of file diff --git a/src/main/java/duke/ui/Ui.java b/src/main/java/duke/ui/Ui.java index 28ad1818f0..4db93b7fcc 100644 --- a/src/main/java/duke/ui/Ui.java +++ b/src/main/java/duke/ui/Ui.java @@ -9,53 +9,42 @@ public class Ui { public static final String LINEBREAK = "\n"; - public static final String UPPER = LINEBREAK + "^".repeat(90) + LINEBREAK.repeat(2); - public static final String LOWER = LINEBREAK.repeat(1) + "_".repeat(90) + LINEBREAK; - public static final String LOGO = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - + public static final String LOGO = "D U K E"; public static final String WRONG_DATE_FORMAT = "!!!Err, wrong date format.. (yyyy-mm-dd)!!!"; - public static final String KEY_IN_NUMBER = "!!!!!!!PLease Lah! Key in number!!!!!!!!"; - public static final String EMPTY_TASK = "!!!!!!!!!Walao!NO TASK!!!!!!!!!!"; - public static final String MISSING_DATE = "!!!Fill ur date lah (add date with / in yyyy-mm-dd format)!!!"; - public static final String COMMAND_ERROR = "!!!!!!!I DON'T KNOW WHAT U SAYING BRO!!!!!!!"; + public static final String KEY_IN_NUMBER = "!!!!!PLease Lah! Key in number!!!!!!"; + public static final String EMPTY_TASK = "!!!Walao!NO TASK!!!"; + public static final String MISSING_DATE = "Fill ur date lah (add date with / in yyyy-mm-dd format)!"; + public static final String COMMAND_ERROR = "!!I DON'T KNOW WHAT U SAYING BRO!!"; public static final String TASK_ERROR = "!!!!!!!!!!Walao, no such task!!!!!!!!!"; public static final String SAVE_TO_FILE_ERROR = "Huh? Where your file?"; public static final String EMPTY_COMMAND = "!!!Walao, command cannot be empty!!!"; - public static final String SUCCESSFUL_SAVE = "~~~~~~~~~~~File Saved Successfully!~~~~~~~~~~~~"; - public static final String FAREWELL = UPPER - + "~~~~~~~~~~~ I Zao Liao. Don't Miss Meeeeeee ~~~~~~~~~~~." - + LOWER; - public static final String GREETING = UPPER - + "****************** Awww, need help ah? ******************" - + LOWER; + public static final String SUCCESSFUL_SAVE = "~File Saved Successfully!~"; + public static final String FAREWELL = " I Zao Liao. Don't Miss Meeeeeee."; + public static final String GREETING = "** Awww, need help ah? **"; - public static final String NO_DIRECTORY = "********** Cannot find your directory eh, " - + "first time ah? Create one for you **********\n"; - public static final String LOAD_FILE = "********** Wait ah~ Loading file for you **********\n"; - public static final String NO_FILE = "********** File also don't have ah, nvm I make one for you **********\n"; - public static final String EMPTY_FILE = "********** Awwww~ You don't have any history of tasks **********\n"; - public static final String SUCESSFUL_LOAD = "***********Sir, here is your past history************"; + public static final String LOAD_FILE = "*Wait ah~ Loading file for you *"; + public static final String NO_FILE = "* File also don't have ah, nvm I make one for you *"; + public static final String EMPTY_FILE = "*Awwww~ You don't have any history of tasks *"; + public static final String SUCESSFUL_LOAD = "*Sir, here is your past history: *\n"; /** * Display a message to indicate the given task as done. * @param t the task to be displayed as done. */ - public static void doneTask(Task t) { - System.out.println(Ui.UPPER + "Wah~ You done the task: " - + " " + t.toString() + Ui.LOWER); + public static String doneTask(Task t) { + + return "Wah~ You done the task: " + + " " + t.toString(); } /** * Display a message to indicate the given task as deleted. * @param t the task to be displayed as deleted. */ - public static void deleteTask(Task t) { - System.out.println(Ui.UPPER + "Awww~ You've deleted the task: " - + " " + t.toString() + Ui.LOWER); + public static String deleteTask(Task t) { + + return "Awww~ You've deleted the task: " + + " " + t.toString(); } /** @@ -65,38 +54,9 @@ public static void deleteTask(Task t) { * @return the String representation of the task name wrapped in a chatBox. */ public static String biggerBox(Task t) { - return Ui.UPPER + "Added liao: " + return "Added liao: " + t.toString() + Ui.LINEBREAK - + "You have " + TaskList.getTasksSize() + " tasks in the list!" - + Ui.LOWER; - } - - - /** - * Display the tasks loaded from the data file. - */ - public static void displayTask() { - System.out.println(UPPER); - System.out.println("~~~~~Sir, here is your past history: "); - for (Task task : TaskList.getTaskList()) { - if (task == null) { - break; - } - System.out.println(task); - } - - System.out.println(LOWER); - } - - /** - * Set the program to rest for 1 second. - */ - public static void sleep() { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } + + "You have " + TaskList.getTasksSize() + " tasks in the list!"; } } diff --git a/src/main/java/duke/utils/DateAndTime.java b/src/main/java/duke/utils/DateAndTime.java index 9b82bd4754..fe425f9385 100644 --- a/src/main/java/duke/utils/DateAndTime.java +++ b/src/main/java/duke/utils/DateAndTime.java @@ -4,6 +4,7 @@ import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import duke.ui.ErrorBox; import duke.ui.Ui; @@ -25,9 +26,11 @@ public static String converter(String date) { LocalDate d1 = LocalDate.parse(date.trim()); return d1.format(DateTimeFormatter.ofPattern("MMM d yyyy")); } catch (DateTimeParseException e) { + ErrorBox.display(e.getMessage()); return Ui.WRONG_DATE_FORMAT; } } else { + ErrorBox.display(Ui.WRONG_DATE_FORMAT); return Ui.WRONG_DATE_FORMAT; } } @@ -50,6 +53,7 @@ private static boolean isNumeric(String strNum) { try { Double.parseDouble(strNum); } catch (NumberFormatException nfe) { + ErrorBox.display(nfe.getMessage()); return false; } return true; diff --git a/src/main/java/duke/utils/Parser.java b/src/main/java/duke/utils/Parser.java index d545a3e79b..c898998a51 100644 --- a/src/main/java/duke/utils/Parser.java +++ b/src/main/java/duke/utils/Parser.java @@ -10,7 +10,9 @@ import duke.command.ListCommand; import duke.exceptions.DukeException; import duke.type.CommandType; +import duke.ui.ErrorBox; import duke.ui.Ui; +import javafx.application.Platform; /** * This class extract and process the user input and produce the right command to be executed after parsing. @@ -31,26 +33,29 @@ public final Command parse() { String instruction; String taskName; String date; - Command command = new ErrorCommand(); + Command command; try { instruction = extractInstruction(input); } catch (DukeException e) { - System.out.println(e.getMessage()); + ErrorBox.display(e.getMessage()); + command = new ErrorCommand(e.getMessage()); return command; } try { taskName = extractTask(input, instruction); } catch (DukeException e) { - System.out.println(e.getMessage()); + ErrorBox.display(e.getMessage()); + command = new ErrorCommand(e.getMessage()); return command; } try { date = extractDate(input, instruction); } catch (DukeException e) { - System.out.println(e.getMessage()); + ErrorBox.display(e.getMessage()); + command = new ErrorCommand(e.getMessage()); return command; } @@ -77,6 +82,7 @@ public final Command parse() { command = new FindCommand(taskName, date); break; default: + command = new ErrorCommand(""); break; } return command; diff --git a/src/main/java/duke/utils/TaskStorage.java b/src/main/java/duke/utils/TaskStorage.java index cf00afd779..2749b10db1 100644 --- a/src/main/java/duke/utils/TaskStorage.java +++ b/src/main/java/duke/utils/TaskStorage.java @@ -2,6 +2,7 @@ import duke.exceptions.DukeException; import duke.task.*; +import duke.ui.ErrorBox; import duke.ui.Ui; import java.io.File; @@ -37,7 +38,7 @@ public static String writeToFiles() { } fw.close(); } catch (IOException err) { - DukeException.saveToFileError(); + ErrorBox.display(err.getMessage()); } return Ui.SUCCESSFUL_SAVE; } @@ -49,47 +50,44 @@ public static String writeToFiles() { * @return the String display of a successful load. */ public static String loadFiles() { - String output = Ui.LOAD_FILE; - System.out.println(output); + StringBuilder output = new StringBuilder(""); + try { File directory = new File(DIRECTORY); if (!directory.exists()) { - System.out.println(Ui.NO_DIRECTORY); directory.mkdir(); - Ui.sleep(); } File file = new File(FILEPATH); if (!file.exists()) { - System.out.println(Ui.NO_FILE); file.createNewFile(); - Ui.sleep(); } if (file.length() == 0) { - Ui.sleep(); - System.out.println(Ui.EMPTY_FILE); return Ui.EMPTY_FILE; } - restoreTask(file); - Ui.displayTask(); + output.append(restoreTask(file)); } catch (IOException e) { - System.out.println("IO error!: " + e.getMessage()); + ErrorBox.display("IO error!: " + e.getMessage()); } - - return Ui.SUCESSFUL_LOAD; + if (output.length() == 0) { + output.append(Ui.EMPTY_FILE); + } else { + output.insert(0, Ui.SUCESSFUL_LOAD); + } + return output.toString(); } - private static void restoreTask(File file) throws IOException { + private static String restoreTask(File file) throws IOException { Scanner sc = new Scanner(file); - + StringBuilder sb = new StringBuilder(""); while (sc.hasNext()) { String[] line = sc.nextLine().split("@@"); if (line.length == 3) { Todo t = new Todo(line[2], line[1]); TaskList.addTask(t); - + sb.append(t.toString() + "\n"); } else { int type = Integer.parseInt(line[0]); String done = line[1]; @@ -97,9 +95,10 @@ private static void restoreTask(File file) throws IOException { String date = line[3]; Task t = type == 2 ? new Deadlines(taskName, date, done) : new Event(taskName, date, done); TaskList.addTask(t); - + sb.append(t.toString() + "\n"); } } sc.close(); + return sb.toString(); } } diff --git a/src/main/resources/images/cat1.jpg b/src/main/resources/images/cat1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ed415cd4f54baafb117a369e5e1673d86f627ab4 GIT binary patch literal 43297 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ⓈLx{LssFLTAaLX?|^n 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�mWy_X|xkrRL8PINWm{ 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/view/DialogBox.fxml b/src/main/resources/view/DialogBox.fxml new file mode 100644 index 0000000000..90711b0ef0 --- /dev/null +++ b/src/main/resources/view/DialogBox.fxml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/src/main/resources/view/MainMenu.fxml b/src/main/resources/view/MainMenu.fxml new file mode 100644 index 0000000000..f6b2a8dc74 --- /dev/null +++ b/src/main/resources/view/MainMenu.fxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml new file mode 100644 index 0000000000..3466ad0ebb --- /dev/null +++ b/src/main/resources/view/MainWindow.fxml @@ -0,0 +1,19 @@ + + + + + + + + + + + +