From 94a4a1978b4761c7b5149b7d0facf0e4d97d23dc Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 19 Aug 2023 15:38:28 +0800 Subject: [PATCH 01/52] Complete Level-0 --- src/main/java/Duke.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 5d313334c..7dc4b17ee 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,10 +1,15 @@ public class Duke { public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; + String logo = " ___ _ _ \n" + + "| \\ | |_ _| | _____ \n" + + "| |\\ \\ | | | | | |/ / _ \\\n" + + "| | \\ \\| | |_| | < __/\n" + + "|_| \\___|\\__,_|_|\\_\\___|\n"; System.out.println("Hello from\n" + logo); + System.out.println(); + System.out.println("Hello! I'm Nuke."); + System.out.println("What can I do for you?"); + System.out.println(); + System.out.println("Bye. Hope to see you again soon!"); } } From bb8421b5921c1a6a182f378c257fa970f6fee9a7 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 26 Aug 2023 13:10:02 +0800 Subject: [PATCH 02/52] Rename class file & Customize answers --- src/main/java/Duke.java | 15 --------------- src/main/java/Nuke.java | 25 +++++++++++++++++++++++++ text-ui-test/runtest.bat | 2 +- 3 files changed, 26 insertions(+), 16 deletions(-) delete mode 100644 src/main/java/Duke.java create mode 100644 src/main/java/Nuke.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java deleted file mode 100644 index 7dc4b17ee..000000000 --- a/src/main/java/Duke.java +++ /dev/null @@ -1,15 +0,0 @@ -public class Duke { - public static void main(String[] args) { - String logo = " ___ _ _ \n" - + "| \\ | |_ _| | _____ \n" - + "| |\\ \\ | | | | | |/ / _ \\\n" - + "| | \\ \\| | |_| | < __/\n" - + "|_| \\___|\\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - System.out.println(); - System.out.println("Hello! I'm Nuke."); - System.out.println("What can I do for you?"); - System.out.println(); - System.out.println("Bye. Hope to see you again soon!"); - } -} diff --git a/src/main/java/Nuke.java b/src/main/java/Nuke.java new file mode 100644 index 000000000..5f9be4bf3 --- /dev/null +++ b/src/main/java/Nuke.java @@ -0,0 +1,25 @@ +public class Nuke { + public static void main(String[] args) { + String logo = "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣠⣤⣤⣤⣤⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n" + + "⠀⠀⠀⠀⠀⠀⠀⣠⡶⠟⠛⠉⠉⠉⠀⠈⠉⠉⠙⠛⠷⢦⡀⠀⠀⠀⠀⠀⠀⠀\n" + + "⠀⠀⠀⠀⢀⣴⠟⢁⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣄⡀⠻⣦⡀⠀⠀⠀⠀\n" + + "⠀⠀⠀⣠⠟⢁⣴⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣦⠈⢻⡆⠀⠀⠀\n" + + "⠀⠀⣰⠏⢠⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣷⠘⢷⡀⠀⠀\n" + + "⠀⢰⡟⠀⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⡆⣿⡆⠀⠀\n" + + "⠀⣾⡇⢸⣿⣿⣿⣿⣿⣿⣿⣿⠟⣀⣤⣄⠈⢿⣿⣿⣿⣿⣿⣿⣿⠀⢻⡆⠀⠀\n" + + "⠀⣿⠀⠘⠛⠛⠛⠛⠛⠛⠛⠃⢸⣿⣿⣿⣷⠀⠛⠛⠛⠛⠛⠛⠛⠃⠀⣿⠀⠀\n" + + "⠀⢻⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⣿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿\n" + + "⠀⠸⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣶⣶⣶⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇\n" + + "⠀⠀⠹⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⣰⠇⠀\n" + + "⠀⠀⠀⠘⢧⡀⠀⠀⠀⠀⠀⣠⣿⣿⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀⢀⣴⠏⠀⠀⠀\n" + + "⠀⠀⠀⠀⠈⠻⢦⣀⠀⠀⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇⠀⣠⡾⠋⠀⠀⠀⠀⠀\n" + + "⠀⠀⠀⠀⠀⠀⠀⠉⠛⠶⣦⣤⣀⣉⣉⣉⣉⣩⣤⣴⠶⠛⠁⠀⠀⠀⠀⠀⠀⠀\n" + + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀"; + System.out.println(logo); + System.out.println(); + System.out.println("[☢] Hello! I'm Nuke."); + System.out.println("[☢] What can I do for you?"); + System.out.println(); + System.out.println("[☢] Bye. Hope to see you again soon!"); + } +} diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index 087374464..d22f2fb7c 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 Nuke < input.txt > ACTUAL.TXT REM compare the output to the expected output FC ACTUAL.TXT EXPECTED.TXT From df853c8a38b86c207aed8f2184592c6f652b2cbc Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 26 Aug 2023 13:22:39 +0800 Subject: [PATCH 03/52] Complete Level-1 --- src/main/java/Nuke.java | 54 +++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/src/main/java/Nuke.java b/src/main/java/Nuke.java index 5f9be4bf3..7ae6b960d 100644 --- a/src/main/java/Nuke.java +++ b/src/main/java/Nuke.java @@ -1,25 +1,43 @@ +import java.util.Scanner; + public class Nuke { + public static String LOGO = + "⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⢀⣀⣠⣤⣤⣤⣤⣀⣀\n" + + "⠀⠀⠀⠀⠀⠀⠀⣠⡶⠟⠛⠉⠉⠉⠀⠈⠉⠉⠙⠛⠷⢦⡀\n" + + "⠀⠀⠀⠀⢀⣴⠟⢁⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣄⡀⠻⣦⡀\n" + + "⠀⠀⠀⣠⠟⢁⣴⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣦⠈⢻⡆\n" + + "⠀⠀⣰⠏⢠⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣷⠘⢷⡀\n" + + "⠀⢰⡟⠀⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⡆⣿⡆\n" + + "⠀⣾⡇⢸⣿⣿⣿⣿⣿⣿⣿⣿⠟⣀⣤⣄⠈⢿⣿⣿⣿⣿⣿⣿⣿⠀⢻⡆\n" + + "⠀⣿⠀⠘⠛⠛⠛⠛⠛⠛⠛⠃⢸⣿⣿⣿⣷⠀⠛⠛⠛⠛⠛⠛⠛⠃⠀⣿\n" + + "⠀⢻⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⣿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿\n" + + "⠀⠸⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣶⣶⣶⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇\n" + + "⠀⠀⠹⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⣰⠇\n" + + "⠀⠀⠀⠘⢧⡀⠀⠀⠀⠀⠀⣠⣿⣿⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀⢀⣴⠏\n" + + "⠀⠀⠀⠀⠈⠻⢦⣀⠀⠀⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇⠀⣠⡾⠋\n" + + "⠀⠀⠀⠀⠀⠀⠀⠉⠛⠶⣦⣤⣀⣉⣉⣉⣉⣩⣤⣴⠶⠛⠁\n" + + "⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠉⠉⠁"; + private static boolean running = true; + public static void main(String[] args) { - String logo = "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣠⣤⣤⣤⣤⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n" + - "⠀⠀⠀⠀⠀⠀⠀⣠⡶⠟⠛⠉⠉⠉⠀⠈⠉⠉⠙⠛⠷⢦⡀⠀⠀⠀⠀⠀⠀⠀\n" + - "⠀⠀⠀⠀⢀⣴⠟⢁⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣄⡀⠻⣦⡀⠀⠀⠀⠀\n" + - "⠀⠀⠀⣠⠟⢁⣴⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣦⠈⢻⡆⠀⠀⠀\n" + - "⠀⠀⣰⠏⢠⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣷⠘⢷⡀⠀⠀\n" + - "⠀⢰⡟⠀⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⡆⣿⡆⠀⠀\n" + - "⠀⣾⡇⢸⣿⣿⣿⣿⣿⣿⣿⣿⠟⣀⣤⣄⠈⢿⣿⣿⣿⣿⣿⣿⣿⠀⢻⡆⠀⠀\n" + - "⠀⣿⠀⠘⠛⠛⠛⠛⠛⠛⠛⠃⢸⣿⣿⣿⣷⠀⠛⠛⠛⠛⠛⠛⠛⠃⠀⣿⠀⠀\n" + - "⠀⢻⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⣿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿\n" + - "⠀⠸⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣶⣶⣶⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇\n" + - "⠀⠀⠹⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⣰⠇⠀\n" + - "⠀⠀⠀⠘⢧⡀⠀⠀⠀⠀⠀⣠⣿⣿⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀⢀⣴⠏⠀⠀⠀\n" + - "⠀⠀⠀⠀⠈⠻⢦⣀⠀⠀⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇⠀⣠⡾⠋⠀⠀⠀⠀⠀\n" + - "⠀⠀⠀⠀⠀⠀⠀⠉⠛⠶⣦⣤⣀⣉⣉⣉⣉⣩⣤⣴⠶⠛⠁⠀⠀⠀⠀⠀⠀⠀\n" + - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀"; - System.out.println(logo); + Scanner in = new Scanner(System.in); + + // Welcome message + System.out.println(LOGO); System.out.println(); System.out.println("[☢] Hello! I'm Nuke."); System.out.println("[☢] What can I do for you?"); - System.out.println(); - System.out.println("[☢] Bye. Hope to see you again soon!"); + + // Loop for user input + while(running) { + System.out.print("> "); + String input = in.nextLine(); + if(input.equals("bye")) { + System.out.println("[☢] Bye. Hope to see you again soon!"); + running = false; + } else { + System.out.println(input); + } + } } } From 26a3cd94760732092d32e7dbac7d43ca5eb0172f Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 26 Aug 2023 13:33:59 +0800 Subject: [PATCH 04/52] Complete Level-2 --- src/main/java/Nuke.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/Nuke.java b/src/main/java/Nuke.java index 7ae6b960d..3f7610c80 100644 --- a/src/main/java/Nuke.java +++ b/src/main/java/Nuke.java @@ -1,3 +1,4 @@ +import java.util.ArrayList; import java.util.Scanner; public class Nuke { @@ -19,6 +20,8 @@ public class Nuke { "⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠉⠉⠁"; private static boolean running = true; + private static ArrayList tasks = new ArrayList<>(); + public static void main(String[] args) { Scanner in = new Scanner(System.in); @@ -35,8 +38,13 @@ public static void main(String[] args) { if(input.equals("bye")) { System.out.println("[☢] Bye. Hope to see you again soon!"); running = false; + } else if(input.equals("list")) { + for(int i = 0; i < tasks.size(); i++) { + System.out.printf("%d. %s\n", i + 1, tasks.get(i)); + } } else { - System.out.println(input); + tasks.add(input); + System.out.println("added: " + input); } } } From b40af3aeae6e1979e47e3052cbe6aa57cc930e17 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 26 Aug 2023 13:52:20 +0800 Subject: [PATCH 05/52] Complete Level-3 --- src/main/java/Nuke.java | 21 ++++++++++++++++++--- src/main/java/Task.java | 25 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 src/main/java/Task.java diff --git a/src/main/java/Nuke.java b/src/main/java/Nuke.java index 3f7610c80..5e67a4740 100644 --- a/src/main/java/Nuke.java +++ b/src/main/java/Nuke.java @@ -20,7 +20,7 @@ public class Nuke { "⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠉⠉⠁"; private static boolean running = true; - private static ArrayList tasks = new ArrayList<>(); + private static ArrayList tasks = new ArrayList<>(); public static void main(String[] args) { Scanner in = new Scanner(System.in); @@ -40,10 +40,25 @@ public static void main(String[] args) { running = false; } else if(input.equals("list")) { for(int i = 0; i < tasks.size(); i++) { - System.out.printf("%d. %s\n", i + 1, tasks.get(i)); + Task task = tasks.get(i); + if(task.isDone()) { + System.out.printf("%d.[X] %s\n", i + 1, task.getName()); + } else { + System.out.printf("%d.[ ] %s\n", i + 1, task.getName()); + } } + } else if(input.startsWith("mark ")) { + int idx = Integer.parseInt(input.substring(5)) - 1; + tasks.get(idx).setDone(true); + System.out.println("[☢] Nice! I've marked this task as done:"); + System.out.println(" [X] " + tasks.get(idx).getName()); + } else if(input.startsWith("unmark ")) { + int idx = Integer.parseInt(input.substring(7)) - 1; + tasks.get(idx).setDone(false); + System.out.println("[☢] OK, I've marked this task as not done yet:"); + System.out.println(" [ ] " + tasks.get(idx).getName()); } else { - tasks.add(input); + tasks.add(new Task(input)); System.out.println("added: " + input); } } diff --git a/src/main/java/Task.java b/src/main/java/Task.java new file mode 100644 index 000000000..dd7246ae6 --- /dev/null +++ b/src/main/java/Task.java @@ -0,0 +1,25 @@ +public class Task { + private String name; + private boolean done; + + public Task(String name) { + setName(name); + setDone(false); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isDone() { + return done; + } + + public void setDone(boolean done) { + this.done = done; + } +} From 8f23d37e9d7c7bf879c76eb3454c9c2e14fca315 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 26 Aug 2023 15:39:48 +0800 Subject: [PATCH 06/52] Refactor for clean code --- src/main/java/Nuke.java | 81 +++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/src/main/java/Nuke.java b/src/main/java/Nuke.java index 5e67a4740..f03efb63c 100644 --- a/src/main/java/Nuke.java +++ b/src/main/java/Nuke.java @@ -20,7 +20,7 @@ public class Nuke { "⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠉⠉⠁"; private static boolean running = true; - private static ArrayList tasks = new ArrayList<>(); + private static final ArrayList tasks = new ArrayList<>(); public static void main(String[] args) { Scanner in = new Scanner(System.in); @@ -35,32 +35,59 @@ public static void main(String[] args) { while(running) { System.out.print("> "); String input = in.nextLine(); - if(input.equals("bye")) { - System.out.println("[☢] Bye. Hope to see you again soon!"); - running = false; - } else if(input.equals("list")) { - for(int i = 0; i < tasks.size(); i++) { - Task task = tasks.get(i); - if(task.isDone()) { - System.out.printf("%d.[X] %s\n", i + 1, task.getName()); - } else { - System.out.printf("%d.[ ] %s\n", i + 1, task.getName()); - } - } - } else if(input.startsWith("mark ")) { - int idx = Integer.parseInt(input.substring(5)) - 1; - tasks.get(idx).setDone(true); - System.out.println("[☢] Nice! I've marked this task as done:"); - System.out.println(" [X] " + tasks.get(idx).getName()); - } else if(input.startsWith("unmark ")) { - int idx = Integer.parseInt(input.substring(7)) - 1; - tasks.get(idx).setDone(false); - System.out.println("[☢] OK, I've marked this task as not done yet:"); - System.out.println(" [ ] " + tasks.get(idx).getName()); - } else { - tasks.add(new Task(input)); - System.out.println("added: " + input); - } + runCommand(input); } } + + private static void runCommand(String line) { + String[] words = line.split(" "); + String type = words[0]; + // String[] args = Arrays.copyOfRange(words, 1, words.length); + + int idx; + switch(type) { + case "bye": + System.out.println("[☢] Bye. Hope to see you again soon!"); + running = false; + break; + case "list": + listTask(); + break; + case "mark": + idx = Integer.parseInt(words[1]) - 1; + markTask(idx); + break; + case "unmark": + idx = Integer.parseInt(words[1]) - 1; + unmarkTask(idx); + break; + default: + addTask(line); + } + } + + private static void addTask(String taskName) { + tasks.add(new Task(taskName)); + System.out.println("added: " + taskName); + } + + private static void listTask() { + for(int i = 0; i < tasks.size(); i++) { + Task task = tasks.get(i); + String mark = task.isDone()? "X" : " "; + System.out.printf("%d.[%s] %s\n", i + 1, mark, task.getName()); + } + } + + private static void markTask(int idx) { + tasks.get(idx).setDone(true); + System.out.println("[☢] Nice! I've marked this task as done:"); + System.out.println(" [X] " + tasks.get(idx).getName()); + } + + private static void unmarkTask(int idx) { + tasks.get(idx).setDone(false); + System.out.println("[☢] OK, I've marked this task as not done yet:"); + System.out.println(" [ ] " + tasks.get(idx).getName()); + } } From 68e19ab62692e51db8735b6f949614e64d086050 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Tue, 5 Sep 2023 15:25:22 +0800 Subject: [PATCH 07/52] Add toString() in Task --- src/main/java/Nuke.java | 3 +-- src/main/java/Task.java | 6 ++++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/Nuke.java b/src/main/java/Nuke.java index f03efb63c..d254b8fb4 100644 --- a/src/main/java/Nuke.java +++ b/src/main/java/Nuke.java @@ -74,8 +74,7 @@ private static void addTask(String taskName) { private static void listTask() { for(int i = 0; i < tasks.size(); i++) { Task task = tasks.get(i); - String mark = task.isDone()? "X" : " "; - System.out.printf("%d.[%s] %s\n", i + 1, mark, task.getName()); + System.out.printf("%d.%s\n", i + 1, task.toString()); } } diff --git a/src/main/java/Task.java b/src/main/java/Task.java index dd7246ae6..6f7b6cb50 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -22,4 +22,10 @@ public boolean isDone() { public void setDone(boolean done) { this.done = done; } + + @Override + public String toString() { + String mark = isDone()? "X" : " "; + return String.format("[%s] %s", mark, getName()); + } } From 7934bea9efcee65d74bdc5a1142cf054cba34fea Mon Sep 17 00:00:00 2001 From: ICubE- Date: Tue, 5 Sep 2023 16:05:45 +0800 Subject: [PATCH 08/52] Update markTask() and unmarkTask() --- src/main/java/Nuke.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/Nuke.java b/src/main/java/Nuke.java index d254b8fb4..323e694aa 100644 --- a/src/main/java/Nuke.java +++ b/src/main/java/Nuke.java @@ -79,14 +79,16 @@ private static void listTask() { } private static void markTask(int idx) { - tasks.get(idx).setDone(true); + Task task = tasks.get(idx); + task.setDone(true); System.out.println("[☢] Nice! I've marked this task as done:"); - System.out.println(" [X] " + tasks.get(idx).getName()); + System.out.println(" " + task); } private static void unmarkTask(int idx) { - tasks.get(idx).setDone(false); + Task task = tasks.get(idx); + task.setDone(false); System.out.println("[☢] OK, I've marked this task as not done yet:"); - System.out.println(" [ ] " + tasks.get(idx).getName()); + System.out.println(" " + task); } } From dda2a87389cbe4558974d586fbf4bb2cf6dd1202 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Tue, 5 Sep 2023 16:06:14 +0800 Subject: [PATCH 09/52] Complete Level-4 --- src/main/java/Deadline.java | 22 ++++++++++++++++++++++ src/main/java/Event.java | 32 ++++++++++++++++++++++++++++++++ src/main/java/Nuke.java | 37 ++++++++++++++++++++++++++++++++----- src/main/java/Todo.java | 10 ++++++++++ 4 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 src/main/java/Deadline.java create mode 100644 src/main/java/Event.java create mode 100644 src/main/java/Todo.java diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java new file mode 100644 index 000000000..82d0d226a --- /dev/null +++ b/src/main/java/Deadline.java @@ -0,0 +1,22 @@ +public class Deadline extends Task { + private String by; + + public Deadline(String name, String by) { + super(name); + this.by = by; + } + + public String getBy() { + return by; + } + + public void setBy(String by) { + this.by = by; + } + + @Override + public String toString() { + return String.format("[D]%s (by: %s)", + super.toString(), getBy()); + } +} diff --git a/src/main/java/Event.java b/src/main/java/Event.java new file mode 100644 index 000000000..b7de8f3f2 --- /dev/null +++ b/src/main/java/Event.java @@ -0,0 +1,32 @@ +public class Event extends Task { + private String from; + private String to; + + public Event(String name, String from, String to) { + super(name); + this.from = from; + this.to = to; + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public String getTo() { + return to; + } + + public void setTo(String to) { + this.to = to; + } + + @Override + public String toString() { + return String.format("[E]%s (from: %s to: %s)", + super.toString(), getFrom(), getTo()); + } +} diff --git a/src/main/java/Nuke.java b/src/main/java/Nuke.java index 323e694aa..0c4ce283e 100644 --- a/src/main/java/Nuke.java +++ b/src/main/java/Nuke.java @@ -1,4 +1,5 @@ import java.util.ArrayList; +import java.util.Arrays; import java.util.Scanner; public class Nuke { @@ -42,7 +43,7 @@ public static void main(String[] args) { private static void runCommand(String line) { String[] words = line.split(" "); String type = words[0]; - // String[] args = Arrays.copyOfRange(words, 1, words.length); + String[] args = Arrays.copyOfRange(words, 1, words.length); int idx; switch(type) { @@ -61,17 +62,43 @@ private static void runCommand(String line) { idx = Integer.parseInt(words[1]) - 1; unmarkTask(idx); break; + case "todo": + String todoName = String.join(" ", args); + addTask(new Todo(todoName)); + break; + case "deadline": + int byIdx = Arrays.asList(args).indexOf("/by"); + String[] deadlineNameArr = Arrays.copyOfRange(args, 0, byIdx); + String deadlineName = String.join(" ", deadlineNameArr); + String[] byArr = Arrays.copyOfRange(args, byIdx + 1, args.length); + String by = String.join(" ", byArr); + addTask(new Deadline(deadlineName, by)); + break; + case "event": + int fromIdx = Arrays.asList(args).indexOf("/from"); + int toIdx = Arrays.asList(args).indexOf("/to"); + String[] eventNameArr = Arrays.copyOfRange(args, 0, fromIdx); + String eventName = String.join(" ", eventNameArr); + String[] fromArr = Arrays.copyOfRange(args, fromIdx + 1, toIdx); + String from = String.join(" ", fromArr); + String[] toArr = Arrays.copyOfRange(args, toIdx + 1, args.length); + String to = String.join(" ", toArr); + addTask(new Event(eventName, from, to)); + break; default: - addTask(line); + addTask(new Task(line)); } } - private static void addTask(String taskName) { - tasks.add(new Task(taskName)); - System.out.println("added: " + taskName); + private static void addTask(Task task) { + tasks.add(task); + System.out.println("[☢] Got it. I've added this task:"); + System.out.println(" " + task); + System.out.printf("[☢] Now you have %d tasks in the list.\n", tasks.size()); } private static void listTask() { + System.out.println("[☢] Here are the tasks in you list:"); for(int i = 0; i < tasks.size(); i++) { Task task = tasks.get(i); System.out.printf("%d.%s\n", i + 1, task.toString()); diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java new file mode 100644 index 000000000..e86d063ef --- /dev/null +++ b/src/main/java/Todo.java @@ -0,0 +1,10 @@ +public class Todo extends Task { + public Todo(String name) { + super(name); + } + + @Override + public String toString() { + return "[T]" + super.toString(); + } +} From 3cd71572dfd7c17bd1bd83dfef96412a6c4520d8 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Tue, 5 Sep 2023 16:49:02 +0800 Subject: [PATCH 10/52] Customize logo and minor stuffs --- src/main/java/Nuke.java | 43 ++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/src/main/java/Nuke.java b/src/main/java/Nuke.java index 0c4ce283e..e9e98fe0e 100644 --- a/src/main/java/Nuke.java +++ b/src/main/java/Nuke.java @@ -4,21 +4,17 @@ public class Nuke { public static String LOGO = - "⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⢀⣀⣠⣤⣤⣤⣤⣀⣀\n" + - "⠀⠀⠀⠀⠀⠀⠀⣠⡶⠟⠛⠉⠉⠉⠀⠈⠉⠉⠙⠛⠷⢦⡀\n" + - "⠀⠀⠀⠀⢀⣴⠟⢁⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣄⡀⠻⣦⡀\n" + - "⠀⠀⠀⣠⠟⢁⣴⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣦⠈⢻⡆\n" + - "⠀⠀⣰⠏⢠⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣷⠘⢷⡀\n" + - "⠀⢰⡟⠀⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⡆⣿⡆\n" + - "⠀⣾⡇⢸⣿⣿⣿⣿⣿⣿⣿⣿⠟⣀⣤⣄⠈⢿⣿⣿⣿⣿⣿⣿⣿⠀⢻⡆\n" + - "⠀⣿⠀⠘⠛⠛⠛⠛⠛⠛⠛⠃⢸⣿⣿⣿⣷⠀⠛⠛⠛⠛⠛⠛⠛⠃⠀⣿\n" + - "⠀⢻⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⣿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿\n" + - "⠀⠸⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣶⣶⣶⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇\n" + - "⠀⠀⠹⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⣰⠇\n" + - "⠀⠀⠀⠘⢧⡀⠀⠀⠀⠀⠀⣠⣿⣿⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀⢀⣴⠏\n" + - "⠀⠀⠀⠀⠈⠻⢦⣀⠀⠀⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇⠀⣠⡾⠋\n" + - "⠀⠀⠀⠀⠀⠀⠀⠉⠛⠶⣦⣤⣀⣉⣉⣉⣉⣩⣤⣴⠶⠛⠁\n" + - "⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠉⠉⠁"; + " _.-^^---....,,-- \n" + + " _-- --_ \n" + + "< >)\n" + + "| |\n" + + " \\._ _./ \n" + + " ```--. . , ; .--''' \n" + + " | | | \n" + + " .-=|| | |=-. \n" + + " `-=#$%&%$#=-' \n" + + " | ; :| \n" + + " _____.,-#%&$@%#&#~,._____ \n"; private static boolean running = true; private static final ArrayList tasks = new ArrayList<>(); @@ -29,12 +25,11 @@ public static void main(String[] args) { // Welcome message System.out.println(LOGO); System.out.println(); - System.out.println("[☢] Hello! I'm Nuke."); - System.out.println("[☢] What can I do for you?"); + System.out.println("[@] Hello! I'm Nuke."); + System.out.println("[@] What can I do for you?"); // Loop for user input while(running) { - System.out.print("> "); String input = in.nextLine(); runCommand(input); } @@ -48,7 +43,7 @@ private static void runCommand(String line) { int idx; switch(type) { case "bye": - System.out.println("[☢] Bye. Hope to see you again soon!"); + System.out.println("[@] Bye. Hope to see you again soon!"); running = false; break; case "list": @@ -92,13 +87,13 @@ private static void runCommand(String line) { private static void addTask(Task task) { tasks.add(task); - System.out.println("[☢] Got it. I've added this task:"); + System.out.println("[@] Got it. I've added this task:"); System.out.println(" " + task); - System.out.printf("[☢] Now you have %d tasks in the list.\n", tasks.size()); + System.out.printf("[@] Now you have %d tasks in the list.\n", tasks.size()); } private static void listTask() { - System.out.println("[☢] Here are the tasks in you list:"); + System.out.println("[@] Here are the tasks in you list:"); for(int i = 0; i < tasks.size(); i++) { Task task = tasks.get(i); System.out.printf("%d.%s\n", i + 1, task.toString()); @@ -108,14 +103,14 @@ private static void listTask() { private static void markTask(int idx) { Task task = tasks.get(idx); task.setDone(true); - System.out.println("[☢] Nice! I've marked this task as done:"); + System.out.println("[@] Nice! I've marked this task as done:"); System.out.println(" " + task); } private static void unmarkTask(int idx) { Task task = tasks.get(idx); task.setDone(false); - System.out.println("[☢] OK, I've marked this task as not done yet:"); + System.out.println("[@] OK, I've marked this task as not done yet:"); System.out.println(" " + task); } } From ab7c348219a0f3d6ebd13f24d8bf0a3ba062cb95 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Tue, 5 Sep 2023 16:50:02 +0800 Subject: [PATCH 11/52] Automate text ui testing (semi) --- text-ui-test/EXPECTED.TXT | 55 ++++++++++++++++++++++++++++++++++----- text-ui-test/input.txt | 12 +++++++++ 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 657e74f6e..f89fed2b3 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,7 +1,50 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| + _.-^^---....,,-- + _-- --_ +< >) +| | + \._ _./ + ```--. . , ; .--''' + | | | + .-=|| | |=-. + `-=#$%&%$#=-' + | ; :| + _____.,-#%&$@%#&#~,._____ + +[@] Hello! I'm Nuke. +[@] What can I do for you? +[@] Got it. I've added this task: + [T][ ] read book +[@] Now you have 1 tasks in the list. +[@] Got it. I've added this task: + [D][ ] return book (by: June 6th) +[@] Now you have 2 tasks in the list. +[@] Got it. I've added this task: + [E][ ] project meeting (from: Aug 6th 2pm to: 4pm) +[@] Now you have 3 tasks in the list. +[@] Got it. I've added this task: + [T][ ] join sports club +[@] Now you have 4 tasks in the list. +[@] Nice! I've marked this task as done: + [T][X] read book +[@] Nice! I've marked this task as done: + [T][X] join sports club +[@] Got it. I've added this task: + [T][ ] borrow book +[@] Now you have 5 tasks in the list. +[@] Here are the tasks in you list: +1.[T][X] read book +2.[D][ ] return book (by: June 6th) +3.[E][ ] project meeting (from: Aug 6th 2pm to: 4pm) +4.[T][X] join sports club +5.[T][ ] borrow book +[@] Got it. I've added this task: + [D][ ] return book (by: Sunday) +[@] Now you have 6 tasks in the list. +[@] Got it. I've added this task: + [E][ ] project meeting (from: Mon 2pm to: 4pm) +[@] Now you have 7 tasks in the list. +[@] Got it. I've added this task: + [D][ ] do homework (by: no idea :-p) +[@] Now you have 8 tasks in the list. +[@] Bye. Hope to see you again soon! diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e69de29bb..d04360f0f 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -0,0 +1,12 @@ +todo read book +deadline return book /by June 6th +event project meeting /from Aug 6th 2pm /to 4pm +todo join sports club +mark 1 +mark 4 +todo borrow book +list +deadline return book /by Sunday +event project meeting /from Mon 2pm /to 4pm +deadline do homework /by no idea :-p +bye From 7a931ef6a415cd521187071e9bfe7c59d4d5bb29 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Tue, 5 Sep 2023 17:45:51 +0800 Subject: [PATCH 12/52] Refactor to improve code quality --- src/main/java/Deadline.java | 10 ++++++++++ src/main/java/Event.java | 9 +++++++++ src/main/java/Nuke.java | 23 ++++------------------- src/main/java/Todo.java | 4 ++++ 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index 82d0d226a..6961e6b76 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -1,6 +1,16 @@ +import java.util.Arrays; + public class Deadline extends Task { private String by; + public static Deadline parseDeadline(String arg) { + String[] args = arg.split(" /by "); + String name = args[0]; + String by = args[1]; + + return new Deadline(name, by); + } + public Deadline(String name, String by) { super(name); this.by = by; diff --git a/src/main/java/Event.java b/src/main/java/Event.java index b7de8f3f2..15ed76fbb 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -2,6 +2,15 @@ public class Event extends Task { private String from; private String to; + public static Event parseEvent(String arg) { + String[] args = arg.split(" /from | /to "); + String name = args[0]; + String from = args[1]; + String to = args[2]; + + return new Event(name, from, to); + } + public Event(String name, String from, String to) { super(name); this.from = from; diff --git a/src/main/java/Nuke.java b/src/main/java/Nuke.java index e9e98fe0e..2a66c84ba 100644 --- a/src/main/java/Nuke.java +++ b/src/main/java/Nuke.java @@ -1,5 +1,4 @@ import java.util.ArrayList; -import java.util.Arrays; import java.util.Scanner; public class Nuke { @@ -38,7 +37,7 @@ public static void main(String[] args) { private static void runCommand(String line) { String[] words = line.split(" "); String type = words[0]; - String[] args = Arrays.copyOfRange(words, 1, words.length); + String arg = line.substring(type.length()).strip(); int idx; switch(type) { @@ -58,27 +57,13 @@ private static void runCommand(String line) { unmarkTask(idx); break; case "todo": - String todoName = String.join(" ", args); - addTask(new Todo(todoName)); + addTask(Todo.parseTodo(arg)); break; case "deadline": - int byIdx = Arrays.asList(args).indexOf("/by"); - String[] deadlineNameArr = Arrays.copyOfRange(args, 0, byIdx); - String deadlineName = String.join(" ", deadlineNameArr); - String[] byArr = Arrays.copyOfRange(args, byIdx + 1, args.length); - String by = String.join(" ", byArr); - addTask(new Deadline(deadlineName, by)); + addTask(Deadline.parseDeadline(arg)); break; case "event": - int fromIdx = Arrays.asList(args).indexOf("/from"); - int toIdx = Arrays.asList(args).indexOf("/to"); - String[] eventNameArr = Arrays.copyOfRange(args, 0, fromIdx); - String eventName = String.join(" ", eventNameArr); - String[] fromArr = Arrays.copyOfRange(args, fromIdx + 1, toIdx); - String from = String.join(" ", fromArr); - String[] toArr = Arrays.copyOfRange(args, toIdx + 1, args.length); - String to = String.join(" ", toArr); - addTask(new Event(eventName, from, to)); + addTask(Event.parseEvent(arg)); break; default: addTask(new Task(line)); diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java index e86d063ef..ce3102e05 100644 --- a/src/main/java/Todo.java +++ b/src/main/java/Todo.java @@ -1,4 +1,8 @@ public class Todo extends Task { + public static Todo parseTodo(String arg) { + return new Todo(arg); + } + public Todo(String name) { super(name); } From 75f40471c94d09f665885701b78b26bed6dda14e Mon Sep 17 00:00:00 2001 From: ICubE- Date: Wed, 6 Sep 2023 13:50:15 +0800 Subject: [PATCH 13/52] Apply peers' PR comments --- src/main/java/Deadline.java | 4 ++-- src/main/java/Event.java | 4 ++-- src/main/java/Nuke.java | 23 +++++++++++++---------- src/main/java/Task.java | 6 +++--- src/main/java/Todo.java | 4 ++-- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index 6961e6b76..e4dc09745 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -3,8 +3,8 @@ public class Deadline extends Task { private String by; - public static Deadline parseDeadline(String arg) { - String[] args = arg.split(" /by "); + public static Deadline parseDeadline(String cmdBody) { + String[] args = cmdBody.split(" /by "); String name = args[0]; String by = args[1]; diff --git a/src/main/java/Event.java b/src/main/java/Event.java index 15ed76fbb..117ef6e9a 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -2,8 +2,8 @@ public class Event extends Task { private String from; private String to; - public static Event parseEvent(String arg) { - String[] args = arg.split(" /from | /to "); + public static Event parseEvent(String cmdBody) { + String[] args = cmdBody.split(" /from | /to "); String name = args[0]; String from = args[1]; String to = args[2]; diff --git a/src/main/java/Nuke.java b/src/main/java/Nuke.java index 2a66c84ba..576af5422 100644 --- a/src/main/java/Nuke.java +++ b/src/main/java/Nuke.java @@ -2,7 +2,7 @@ import java.util.Scanner; public class Nuke { - public static String LOGO = + public static final String LOGO = " _.-^^---....,,-- \n" + " _-- --_ \n" + "< >)\n" + @@ -14,7 +14,8 @@ public class Nuke { " `-=#$%&%$#=-' \n" + " | ; :| \n" + " _____.,-#%&$@%#&#~,._____ \n"; - private static boolean running = true; + + private static boolean isRunning = true; private static final ArrayList tasks = new ArrayList<>(); @@ -26,24 +27,26 @@ public static void main(String[] args) { System.out.println(); System.out.println("[@] Hello! I'm Nuke."); System.out.println("[@] What can I do for you?"); + System.out.println(); // Loop for user input - while(running) { + while (isRunning) { String input = in.nextLine(); runCommand(input); + System.out.println(); } } private static void runCommand(String line) { String[] words = line.split(" "); String type = words[0]; - String arg = line.substring(type.length()).strip(); + String cmdBody = line.substring(type.length()).strip(); int idx; - switch(type) { + switch (type) { case "bye": System.out.println("[@] Bye. Hope to see you again soon!"); - running = false; + isRunning = false; break; case "list": listTask(); @@ -57,13 +60,13 @@ private static void runCommand(String line) { unmarkTask(idx); break; case "todo": - addTask(Todo.parseTodo(arg)); + addTask(Todo.parseTodo(cmdBody)); break; case "deadline": - addTask(Deadline.parseDeadline(arg)); + addTask(Deadline.parseDeadline(cmdBody)); break; case "event": - addTask(Event.parseEvent(arg)); + addTask(Event.parseEvent(cmdBody)); break; default: addTask(new Task(line)); @@ -79,7 +82,7 @@ private static void addTask(Task task) { private static void listTask() { System.out.println("[@] Here are the tasks in you list:"); - for(int i = 0; i < tasks.size(); i++) { + for (int i = 0; i < tasks.size(); i++) { Task task = tasks.get(i); System.out.printf("%d.%s\n", i + 1, task.toString()); } diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 6f7b6cb50..39823d0e3 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -1,6 +1,6 @@ public class Task { private String name; - private boolean done; + private boolean isDone; public Task(String name) { setName(name); @@ -16,11 +16,11 @@ public void setName(String name) { } public boolean isDone() { - return done; + return isDone; } public void setDone(boolean done) { - this.done = done; + this.isDone = done; } @Override diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java index ce3102e05..477e3c8b4 100644 --- a/src/main/java/Todo.java +++ b/src/main/java/Todo.java @@ -1,6 +1,6 @@ public class Todo extends Task { - public static Todo parseTodo(String arg) { - return new Todo(arg); + public static Todo parseTodo(String cmdBody) { + return new Todo(cmdBody); } public Todo(String name) { From 5f887e289ef56c3e302ca1769440f1ac189741ea Mon Sep 17 00:00:00 2001 From: ICubE- Date: Wed, 6 Sep 2023 14:04:36 +0800 Subject: [PATCH 14/52] Fix parsing regex --- src/main/java/Deadline.java | 2 +- src/main/java/Event.java | 2 +- text-ui-test/EXPECTED.TXT | 13 +++++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index e4dc09745..682fda8e8 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -4,7 +4,7 @@ public class Deadline extends Task { private String by; public static Deadline parseDeadline(String cmdBody) { - String[] args = cmdBody.split(" /by "); + String[] args = cmdBody.split(" +/by +"); String name = args[0]; String by = args[1]; diff --git a/src/main/java/Event.java b/src/main/java/Event.java index 117ef6e9a..9afc565cd 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -3,7 +3,7 @@ public class Event extends Task { private String to; public static Event parseEvent(String cmdBody) { - String[] args = cmdBody.split(" /from | /to "); + String[] args = cmdBody.split(" +(/from|/to) +"); String name = args[0]; String from = args[1]; String to = args[2]; diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index f89fed2b3..dc27a0464 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -13,38 +13,51 @@ [@] Hello! I'm Nuke. [@] What can I do for you? + [@] Got it. I've added this task: [T][ ] read book [@] Now you have 1 tasks in the list. + [@] Got it. I've added this task: [D][ ] return book (by: June 6th) [@] Now you have 2 tasks in the list. + [@] Got it. I've added this task: [E][ ] project meeting (from: Aug 6th 2pm to: 4pm) [@] Now you have 3 tasks in the list. + [@] Got it. I've added this task: [T][ ] join sports club [@] Now you have 4 tasks in the list. + [@] Nice! I've marked this task as done: [T][X] read book + [@] Nice! I've marked this task as done: [T][X] join sports club + [@] Got it. I've added this task: [T][ ] borrow book [@] Now you have 5 tasks in the list. + [@] Here are the tasks in you list: 1.[T][X] read book 2.[D][ ] return book (by: June 6th) 3.[E][ ] project meeting (from: Aug 6th 2pm to: 4pm) 4.[T][X] join sports club 5.[T][ ] borrow book + [@] Got it. I've added this task: [D][ ] return book (by: Sunday) [@] Now you have 6 tasks in the list. + [@] Got it. I've added this task: [E][ ] project meeting (from: Mon 2pm to: 4pm) [@] Now you have 7 tasks in the list. + [@] Got it. I've added this task: [D][ ] do homework (by: no idea :-p) [@] Now you have 8 tasks in the list. + [@] Bye. Hope to see you again soon! + From a613e5abe13aa128ba1ab306ff399986effb0719 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 9 Sep 2023 23:17:31 +0800 Subject: [PATCH 15/52] Complete Level-5 Add command classes Add exceptions Handle user input exceptions --- src/main/java/Command.java | 15 +++ src/main/java/CommandBye.java | 16 +++ src/main/java/CommandDeadline.java | 35 ++++++ src/main/java/CommandEvent.java | 51 ++++++++ src/main/java/CommandList.java | 16 +++ src/main/java/CommandMark.java | 30 +++++ src/main/java/CommandTodo.java | 19 +++ src/main/java/CommandUnmark.java | 25 ++++ .../java/InvalidCommandArgumentException.java | 7 ++ .../java/InvalidCommandTypeException.java | 7 ++ src/main/java/Nuke.java | 113 +++++++----------- src/main/java/NukeException.java | 2 + src/main/java/Parser.java | 85 +++++++++++++ src/main/java/Task.java | 2 +- src/main/java/Ui.java | 53 ++++++++ 15 files changed, 404 insertions(+), 72 deletions(-) create mode 100644 src/main/java/Command.java create mode 100644 src/main/java/CommandBye.java create mode 100644 src/main/java/CommandDeadline.java create mode 100644 src/main/java/CommandEvent.java create mode 100644 src/main/java/CommandList.java create mode 100644 src/main/java/CommandMark.java create mode 100644 src/main/java/CommandTodo.java create mode 100644 src/main/java/CommandUnmark.java create mode 100644 src/main/java/InvalidCommandArgumentException.java create mode 100644 src/main/java/InvalidCommandTypeException.java create mode 100644 src/main/java/NukeException.java create mode 100644 src/main/java/Parser.java create mode 100644 src/main/java/Ui.java diff --git a/src/main/java/Command.java b/src/main/java/Command.java new file mode 100644 index 000000000..ae65f708e --- /dev/null +++ b/src/main/java/Command.java @@ -0,0 +1,15 @@ +public abstract class Command { + + public abstract void applyArguments(String args) throws InvalidCommandArgumentException; + + public void handleArgumentError(InvalidCommandArgumentException e) { + Ui.printCommandError(e.reason); + } + + public abstract void run(); + + public static void handleTypeError(InvalidCommandTypeException e) { + String desc = String.format("I'm sorry, but I don't know what '%s' means.", e.type); + Ui.printCommandError(desc); + } +} diff --git a/src/main/java/CommandBye.java b/src/main/java/CommandBye.java new file mode 100644 index 000000000..f1e412f65 --- /dev/null +++ b/src/main/java/CommandBye.java @@ -0,0 +1,16 @@ +public class CommandBye extends Command { + private static final String TOO_MANY_ARGUMENTS_ERROR = + "Command 'bye' should have no argument."; + + @Override + public void applyArguments(String args) throws InvalidCommandArgumentException { + if (!args.isEmpty()) { + throw new InvalidCommandArgumentException(TOO_MANY_ARGUMENTS_ERROR); + } + } + + @Override + public void run() { + Nuke.quit(); + } +} diff --git a/src/main/java/CommandDeadline.java b/src/main/java/CommandDeadline.java new file mode 100644 index 000000000..926c794d2 --- /dev/null +++ b/src/main/java/CommandDeadline.java @@ -0,0 +1,35 @@ +public class CommandDeadline extends Command { + private static final String NO_ARGUMENTS_ERROR = + "Command 'deadline' should have arguments."; + private static final String BY_NUMBER_ERROR = + "Command 'deadline' should have one '/by' label for the deadline."; + private static final String NAME_EMPTY_ERROR = + "Command 'deadline' should have a string as a name of the task."; + private static final String BY_EMPTY_ERROR = + "Command 'deadline' should have a string as a deadline of the task."; + + public String name; + public String by; + + @Override + public void applyArguments(String args) throws InvalidCommandArgumentException { + if (args.isEmpty()) { + throw new InvalidCommandArgumentException(NO_ARGUMENTS_ERROR); + } else if (!Parser.containsExactOneLabel(args, "/by")) { + throw new InvalidCommandArgumentException(BY_NUMBER_ERROR); + } else if (Parser.matches(args, "/by(.*)")) { + throw new InvalidCommandArgumentException(NAME_EMPTY_ERROR); + } else if (Parser.matches(args, "(.+)\\s/by")) { + throw new InvalidCommandArgumentException(BY_EMPTY_ERROR); + } + + String[] parsedArgs = Parser.parseArguments(args, "(.+)\\s/by\\s(.+)"); + name = parsedArgs[0]; + by = parsedArgs[1]; + } + + @Override + public void run() { + Nuke.addDeadline(name, by); + } +} diff --git a/src/main/java/CommandEvent.java b/src/main/java/CommandEvent.java new file mode 100644 index 000000000..aaf25d5a0 --- /dev/null +++ b/src/main/java/CommandEvent.java @@ -0,0 +1,51 @@ +public class CommandEvent extends Command { + private static final String NO_ARGUMENTS_ERROR = + "Command 'event' should have arguments."; + private static final String FROM_TO_NUMBER_ERROR = + "Command 'event' should have one '/from' label and one '/to' label for the period of event."; + private static final String NAME_EMPTY_ERROR = + "Command 'event' should have a string as a name of the task."; + private static final String FROM_EMPTY_ERROR = + "Command 'event' should have a string, after '/from' label, as a start period of the task."; + private static final String TO_EMPTY_ERROR = + "Command 'event' should have a string, after '/to' label, as an end period of the task."; + + public String name; + public String from; + public String to; + + @Override + public void applyArguments(String args) throws InvalidCommandArgumentException { + if (args.isEmpty()) { + throw new InvalidCommandArgumentException(NO_ARGUMENTS_ERROR); + } else if (!Parser.containsExactOneLabel(args, "/from")) { + throw new InvalidCommandArgumentException(FROM_TO_NUMBER_ERROR); + } else if (!Parser.containsExactOneLabel(args, "/to")) { + throw new InvalidCommandArgumentException(FROM_TO_NUMBER_ERROR); + } else if (Parser.matches(args, "/from(.*)")) { + throw new InvalidCommandArgumentException(NAME_EMPTY_ERROR); + } else if (Parser.matches(args, "(.+)\\s/from\\s/to(.*)")) { + throw new InvalidCommandArgumentException(FROM_EMPTY_ERROR); + } else if (Parser.matches(args, "(.+)\\s/from\\s(.+)\\s/to")) { + throw new InvalidCommandArgumentException(TO_EMPTY_ERROR); + } + + String[] parsedArgs = Parser.parseArguments(args, "(.+)\\s/from\\s(.+)\\s/to\\s(.+)"); + name = parsedArgs[0]; + from = parsedArgs[1]; + to = parsedArgs[2]; + + if (name.isEmpty()) { + throw new InvalidCommandArgumentException(NAME_EMPTY_ERROR); + } else if (from.isEmpty()) { + throw new InvalidCommandArgumentException(FROM_EMPTY_ERROR); + } else if (to.isEmpty()) { + throw new InvalidCommandArgumentException(TO_EMPTY_ERROR); + } + } + + @Override + public void run() { + Nuke.addEvent(name, from, to); + } +} diff --git a/src/main/java/CommandList.java b/src/main/java/CommandList.java new file mode 100644 index 000000000..2b7b216dd --- /dev/null +++ b/src/main/java/CommandList.java @@ -0,0 +1,16 @@ +public class CommandList extends Command { + private static final String TOO_MANY_ARGUMENTS_ERROR = + "Command 'list' should have no argument."; + + @Override + public void applyArguments(String args) throws InvalidCommandArgumentException { + if (!args.isEmpty()) { + throw new InvalidCommandArgumentException(TOO_MANY_ARGUMENTS_ERROR); + } + } + + @Override + public void run() { + Nuke.listTask(); + } +} diff --git a/src/main/java/CommandMark.java b/src/main/java/CommandMark.java new file mode 100644 index 000000000..9e86f9030 --- /dev/null +++ b/src/main/java/CommandMark.java @@ -0,0 +1,30 @@ +public class CommandMark extends Command { + private static final String TOO_MANY_ARGUMENTS_ERROR = + "Command 'mark' should have one argument as an index."; + private static final String INDEX_NOT_INTEGER_ERROR = + "Command 'mark' should have a number as an index."; + private static final String INDEX_INVALID_VALUE_ERROR = + "A value of index is invalid. Please check the number of tasks."; + + public int index; + + @Override + public void applyArguments(String args) throws InvalidCommandArgumentException { + if (args.split("\\s").length != 1) { + throw new InvalidCommandArgumentException(TOO_MANY_ARGUMENTS_ERROR); + } + try { + index = Integer.parseInt(args) - 1; + } catch (NumberFormatException e) { + throw new InvalidCommandArgumentException(INDEX_NOT_INTEGER_ERROR); + } + if(index < 0 || index >= Nuke.getNumberOfTasks()) { + throw new InvalidCommandArgumentException(INDEX_INVALID_VALUE_ERROR); + } + } + + @Override + public void run() { + Nuke.markTask(index); + } +} diff --git a/src/main/java/CommandTodo.java b/src/main/java/CommandTodo.java new file mode 100644 index 000000000..90ec64f9c --- /dev/null +++ b/src/main/java/CommandTodo.java @@ -0,0 +1,19 @@ +public class CommandTodo extends Command { + private static final String NAME_EMPTY_ERROR = + "Command 'todo' should have a string as a name of the task."; + + public String name; + + @Override + public void applyArguments(String args) throws InvalidCommandArgumentException { + name = args; + if (name.isEmpty()) { + throw new InvalidCommandArgumentException(NAME_EMPTY_ERROR); + } + } + + @Override + public void run() { + Nuke.addTodo(name); + } +} diff --git a/src/main/java/CommandUnmark.java b/src/main/java/CommandUnmark.java new file mode 100644 index 000000000..a51faf3a7 --- /dev/null +++ b/src/main/java/CommandUnmark.java @@ -0,0 +1,25 @@ +public class CommandUnmark extends Command { + private static final String INDEX_NOT_INTEGER_ERROR = + "Command 'unmark' should have a number as an index."; + private static final String INDEX_INVALID_VALUE_ERROR = + "A value of index is invalid. Please check the number of tasks."; + + public int index; + + @Override + public void applyArguments(String args) throws InvalidCommandArgumentException { + try { + index = Integer.parseInt(args) - 1; + } catch (NumberFormatException e) { + throw new InvalidCommandArgumentException(INDEX_NOT_INTEGER_ERROR); + } + if(index < 0 || index >= Nuke.getNumberOfTasks()) { + throw new InvalidCommandArgumentException(INDEX_INVALID_VALUE_ERROR); + } + } + + @Override + public void run() { + Nuke.unmarkTask(index); + } +} diff --git a/src/main/java/InvalidCommandArgumentException.java b/src/main/java/InvalidCommandArgumentException.java new file mode 100644 index 000000000..ace638e4b --- /dev/null +++ b/src/main/java/InvalidCommandArgumentException.java @@ -0,0 +1,7 @@ +public class InvalidCommandArgumentException extends NukeException { + public String reason; + + public InvalidCommandArgumentException(String reason) { + this.reason = reason; + } +} diff --git a/src/main/java/InvalidCommandTypeException.java b/src/main/java/InvalidCommandTypeException.java new file mode 100644 index 000000000..da158fe6a --- /dev/null +++ b/src/main/java/InvalidCommandTypeException.java @@ -0,0 +1,7 @@ +public class InvalidCommandTypeException extends NukeException { + public String type; + + public InvalidCommandTypeException(String type) { + this.type = type; + } +} diff --git a/src/main/java/Nuke.java b/src/main/java/Nuke.java index 576af5422..3034601aa 100644 --- a/src/main/java/Nuke.java +++ b/src/main/java/Nuke.java @@ -2,103 +2,74 @@ import java.util.Scanner; public class Nuke { - public static final String LOGO = - " _.-^^---....,,-- \n" + - " _-- --_ \n" + - "< >)\n" + - "| |\n" + - " \\._ _./ \n" + - " ```--. . , ; .--''' \n" + - " | | | \n" + - " .-=|| | |=-. \n" + - " `-=#$%&%$#=-' \n" + - " | ; :| \n" + - " _____.,-#%&$@%#&#~,._____ \n"; - private static boolean isRunning = true; - private static final ArrayList tasks = new ArrayList<>(); public static void main(String[] args) { - Scanner in = new Scanner(System.in); + final Scanner USER_IN = new Scanner(System.in); - // Welcome message - System.out.println(LOGO); - System.out.println(); - System.out.println("[@] Hello! I'm Nuke."); - System.out.println("[@] What can I do for you?"); - System.out.println(); + Ui.printWelcome(); // Loop for user input while (isRunning) { - String input = in.nextLine(); + String input = USER_IN.nextLine(); runCommand(input); System.out.println(); } } - private static void runCommand(String line) { - String[] words = line.split(" "); - String type = words[0]; - String cmdBody = line.substring(type.length()).strip(); - - int idx; - switch (type) { - case "bye": - System.out.println("[@] Bye. Hope to see you again soon!"); - isRunning = false; - break; - case "list": - listTask(); - break; - case "mark": - idx = Integer.parseInt(words[1]) - 1; - markTask(idx); - break; - case "unmark": - idx = Integer.parseInt(words[1]) - 1; - unmarkTask(idx); - break; - case "todo": - addTask(Todo.parseTodo(cmdBody)); - break; - case "deadline": - addTask(Deadline.parseDeadline(cmdBody)); - break; - case "event": - addTask(Event.parseEvent(cmdBody)); - break; - default: - addTask(new Task(line)); + private static void runCommand(String commandLine) { + Command command; + try { + command = Parser.parseCommand(commandLine); + command.run(); + } catch (InvalidCommandTypeException e) { + Command.handleTypeError(e); + } catch (InvalidCommandArgumentException ignored) { + // already processed in Parse.parseCommand(). } } - private static void addTask(Task task) { + public static void quit() { + isRunning = false; + Ui.printBye(); + } + + public static void addTask(Task task) { tasks.add(task); - System.out.println("[@] Got it. I've added this task:"); - System.out.println(" " + task); - System.out.printf("[@] Now you have %d tasks in the list.\n", tasks.size()); + Ui.printAddedTask(task.toString(), getNumberOfTasks()); } - private static void listTask() { - System.out.println("[@] Here are the tasks in you list:"); - for (int i = 0; i < tasks.size(); i++) { - Task task = tasks.get(i); - System.out.printf("%d.%s\n", i + 1, task.toString()); - } + public static void listTask() { + String[] taskList = tasks.stream().map(Task::toString).toArray(String[]::new); + Ui.printListOfTasks(taskList); } - private static void markTask(int idx) { + public static void markTask(int idx) { Task task = tasks.get(idx); task.setDone(true); - System.out.println("[@] Nice! I've marked this task as done:"); - System.out.println(" " + task); + Ui.printMarkedTask(task.toString()); } - private static void unmarkTask(int idx) { + public static void unmarkTask(int idx) { Task task = tasks.get(idx); task.setDone(false); - System.out.println("[@] OK, I've marked this task as not done yet:"); - System.out.println(" " + task); + Ui.printUnmarkedTask(task.toString()); + } + + public static void addTodo(String name) { + addTask(new Todo(name)); + } + + public static void addDeadline(String name, String by) { + addTask(new Deadline(name, by)); + } + + public static void addEvent(String name, String from, String to) { + addTask(new Event(name, from, to)); + } + + public static int getNumberOfTasks() { + return tasks.size(); } } diff --git a/src/main/java/NukeException.java b/src/main/java/NukeException.java new file mode 100644 index 000000000..7eb620490 --- /dev/null +++ b/src/main/java/NukeException.java @@ -0,0 +1,2 @@ +public class NukeException extends Exception { +} diff --git a/src/main/java/Parser.java b/src/main/java/Parser.java new file mode 100644 index 000000000..8a76a3284 --- /dev/null +++ b/src/main/java/Parser.java @@ -0,0 +1,85 @@ +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Parser { + public static Command parseCommand(String commandLine) + throws InvalidCommandTypeException, InvalidCommandArgumentException { + String type = getCommandType(commandLine); + String args = getCommandArguments(commandLine, type); + + Command command = getBlankCommand(type); + + try { + command.applyArguments(args); + } catch (InvalidCommandArgumentException e) { + command.handleArgumentError(e); + throw e; + } + + return command; + } + + private static Command getBlankCommand(String type) + throws InvalidCommandTypeException { + Command command; + switch (type) { + case "bye": + command = new CommandBye(); + break; + case "list": + command = new CommandList(); + break; + case "mark": + command = new CommandMark(); + break; + case "unmark": + command = new CommandUnmark(); + break; + case "todo": + command = new CommandTodo(); + break; + case "deadline": + command = new CommandDeadline(); + break; + case "event": + command = new CommandEvent(); + break; + default: + throw new InvalidCommandTypeException(type); + } + return command; + } + + private static String getCommandType(String commandLine) { + return commandLine.split("\\s")[0]; + } + + private static String getCommandArguments(String commandLine, String type) { + return commandLine.substring(type.length()).strip(); + } + + public static boolean containsExactOneLabel(String str, String label) { + String[] argSplit = str.split("\\s"); + long labelCnt = Arrays.stream(argSplit).filter(a -> a.equals(label)).count(); + return labelCnt == 1; + } + + public static boolean matches(String str, String regex) { + Matcher matcher = Pattern.compile(regex).matcher(str); + return matcher.matches(); + } + + public static String[] parseArguments(String args, String regex) { + String[] parsedArgs; + + Matcher matcher = Pattern.compile(regex).matcher(args); + boolean b = matcher.find(); + parsedArgs = new String[matcher.groupCount()]; + for (int i = 1; i <= matcher.groupCount(); i++) { + parsedArgs[i - 1] = matcher.group(i); + } + + return parsedArgs; + } +} diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 39823d0e3..7094da302 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -1,4 +1,4 @@ -public class Task { +public abstract class Task { private String name; private boolean isDone; diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java new file mode 100644 index 000000000..2d3cb84be --- /dev/null +++ b/src/main/java/Ui.java @@ -0,0 +1,53 @@ +public class Ui { + public static final String LOGO = + " _.-^^---....,,-- \n" + + " _-- --_ \n" + + "< >)\n" + + "| |\n" + + " \\._ _./ \n" + + " ```--. . , ; .--''' \n" + + " | | | \n" + + " .-=|| | |=-. \n" + + " `-=#$%&%$#=-' \n" + + " | ; :| \n" + + " _____.,-#%&$@%#&#~,._____ \n"; + + public static void printWelcome() { + System.out.println(LOGO); + System.out.println(); + System.out.println("[@] Hello! I'm Nuke."); + System.out.println("[@] What can I do for you?"); + System.out.println(); + } + + public static void printBye() { + System.out.println("[@] Bye. Hope to see you again soon!"); + } + + public static void printAddedTask(String addedTask, int taskCnt) { + System.out.println("[@] Got it. I've added this task:"); + System.out.println(" " + addedTask); + System.out.printf("[@] Now you have %d tasks in the list.\n", taskCnt); + } + + public static void printListOfTasks(String[] tasks) { + System.out.println("[@] Here are the tasks in you list:"); + for (int i = 0; i < tasks.length; i++) { + System.out.printf("%d.%s\n", i + 1, tasks[i]); + } + } + + public static void printMarkedTask(String markedTask) { + System.out.println("[@] Nice! I've marked this task as done:"); + System.out.println(" " + markedTask); + } + + public static void printUnmarkedTask(String unmarkedTask) { + System.out.println("[@] OK, I've marked this task as not done yet:"); + System.out.println(" " + unmarkedTask); + } + + public static void printCommandError(String description) { + System.out.println("[@] OOPS!!! " + description); + } +} From 1b7e33d4881004435d8ebf65367dd77d14c42221 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 9 Sep 2023 23:43:16 +0800 Subject: [PATCH 16/52] Provide input error details Fix error in unmark command --- src/main/java/Command.java | 9 ++++++--- src/main/java/CommandBye.java | 5 +++++ src/main/java/CommandDeadline.java | 5 +++++ src/main/java/CommandEvent.java | 5 +++++ src/main/java/CommandList.java | 5 +++++ src/main/java/CommandMark.java | 5 +++++ src/main/java/CommandTodo.java | 5 +++++ src/main/java/CommandUnmark.java | 10 ++++++++++ src/main/java/Parser.java | 2 +- src/main/java/Ui.java | 11 ++++++++--- 10 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/main/java/Command.java b/src/main/java/Command.java index ae65f708e..f26f0c74d 100644 --- a/src/main/java/Command.java +++ b/src/main/java/Command.java @@ -3,13 +3,16 @@ public abstract class Command { public abstract void applyArguments(String args) throws InvalidCommandArgumentException; public void handleArgumentError(InvalidCommandArgumentException e) { - Ui.printCommandError(e.reason); + Ui.printCommandError(e.reason, getArgumentErrorDetail()); } + protected abstract String getArgumentErrorDetail(); + public abstract void run(); public static void handleTypeError(InvalidCommandTypeException e) { - String desc = String.format("I'm sorry, but I don't know what '%s' means.", e.type); - Ui.printCommandError(desc); + String desc = String.format("There is no command called '%s'.", e.type); + String detail = "Existing command: bye, list, mark, unmark, todo, deadline, event"; + Ui.printCommandError(desc, detail); } } diff --git a/src/main/java/CommandBye.java b/src/main/java/CommandBye.java index f1e412f65..88ff65ef3 100644 --- a/src/main/java/CommandBye.java +++ b/src/main/java/CommandBye.java @@ -9,6 +9,11 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { } } + @Override + protected String getArgumentErrorDetail() { + return "Usage: bye"; + } + @Override public void run() { Nuke.quit(); diff --git a/src/main/java/CommandDeadline.java b/src/main/java/CommandDeadline.java index 926c794d2..1481f6859 100644 --- a/src/main/java/CommandDeadline.java +++ b/src/main/java/CommandDeadline.java @@ -28,6 +28,11 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { by = parsedArgs[1]; } + @Override + protected String getArgumentErrorDetail() { + return "Usage: deadline ((name)) /by ((deadline))"; + } + @Override public void run() { Nuke.addDeadline(name, by); diff --git a/src/main/java/CommandEvent.java b/src/main/java/CommandEvent.java index aaf25d5a0..3d681e951 100644 --- a/src/main/java/CommandEvent.java +++ b/src/main/java/CommandEvent.java @@ -44,6 +44,11 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { } } + @Override + protected String getArgumentErrorDetail() { + return "Usage: event ((name)) /from ((start)) /to ((end))"; + } + @Override public void run() { Nuke.addEvent(name, from, to); diff --git a/src/main/java/CommandList.java b/src/main/java/CommandList.java index 2b7b216dd..00057f6d0 100644 --- a/src/main/java/CommandList.java +++ b/src/main/java/CommandList.java @@ -9,6 +9,11 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { } } + @Override + protected String getArgumentErrorDetail() { + return "Usage: list"; + } + @Override public void run() { Nuke.listTask(); diff --git a/src/main/java/CommandMark.java b/src/main/java/CommandMark.java index 9e86f9030..c6b293428 100644 --- a/src/main/java/CommandMark.java +++ b/src/main/java/CommandMark.java @@ -23,6 +23,11 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { } } + @Override + protected String getArgumentErrorDetail() { + return "Usage: mark ((number))"; + } + @Override public void run() { Nuke.markTask(index); diff --git a/src/main/java/CommandTodo.java b/src/main/java/CommandTodo.java index 90ec64f9c..dd1bd9ff7 100644 --- a/src/main/java/CommandTodo.java +++ b/src/main/java/CommandTodo.java @@ -12,6 +12,11 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { } } + @Override + protected String getArgumentErrorDetail() { + return "Usage: todo ((name))"; + } + @Override public void run() { Nuke.addTodo(name); diff --git a/src/main/java/CommandUnmark.java b/src/main/java/CommandUnmark.java index a51faf3a7..310f1ffc0 100644 --- a/src/main/java/CommandUnmark.java +++ b/src/main/java/CommandUnmark.java @@ -1,4 +1,6 @@ public class CommandUnmark extends Command { + private static final String TOO_MANY_ARGUMENTS_ERROR = + "Command 'mark' should have one argument as an index."; private static final String INDEX_NOT_INTEGER_ERROR = "Command 'unmark' should have a number as an index."; private static final String INDEX_INVALID_VALUE_ERROR = @@ -8,6 +10,9 @@ public class CommandUnmark extends Command { @Override public void applyArguments(String args) throws InvalidCommandArgumentException { + if (args.split("\\s").length != 1) { + throw new InvalidCommandArgumentException(TOO_MANY_ARGUMENTS_ERROR); + } try { index = Integer.parseInt(args) - 1; } catch (NumberFormatException e) { @@ -18,6 +23,11 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { } } + @Override + protected String getArgumentErrorDetail() { + return "Usage: unmark ((number))"; + } + @Override public void run() { Nuke.unmarkTask(index); diff --git a/src/main/java/Parser.java b/src/main/java/Parser.java index 8a76a3284..ee57258a4 100644 --- a/src/main/java/Parser.java +++ b/src/main/java/Parser.java @@ -74,7 +74,7 @@ public static String[] parseArguments(String args, String regex) { String[] parsedArgs; Matcher matcher = Pattern.compile(regex).matcher(args); - boolean b = matcher.find(); + matcher.find(); parsedArgs = new String[matcher.groupCount()]; for (int i = 1; i <= matcher.groupCount(); i++) { parsedArgs[i - 1] = matcher.group(i); diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java index 2d3cb84be..07b59d5c6 100644 --- a/src/main/java/Ui.java +++ b/src/main/java/Ui.java @@ -31,7 +31,11 @@ public static void printAddedTask(String addedTask, int taskCnt) { } public static void printListOfTasks(String[] tasks) { - System.out.println("[@] Here are the tasks in you list:"); + if(tasks.length == 0) { + System.out.println("[@] There are no tasks in your list."); + return; + } + System.out.println("[@] Here are the tasks in your list:"); for (int i = 0; i < tasks.length; i++) { System.out.printf("%d.%s\n", i + 1, tasks[i]); } @@ -47,7 +51,8 @@ public static void printUnmarkedTask(String unmarkedTask) { System.out.println(" " + unmarkedTask); } - public static void printCommandError(String description) { - System.out.println("[@] OOPS!!! " + description); + public static void printCommandError(String description, String detail) { + System.out.println("[@] Wrong input; " + description); + System.out.println("[@] " + detail); } } From e5586836b5c696e663292ca9ba2d5e43333ad0cc Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sun, 10 Sep 2023 01:01:14 +0800 Subject: [PATCH 17/52] Refactor for clean code --- src/main/java/Command.java | 6 +++- src/main/java/CommandBye.java | 11 ++++--- src/main/java/CommandDeadline.java | 32 +++++++++---------- src/main/java/CommandEvent.java | 50 +++++++++++++----------------- src/main/java/CommandList.java | 11 ++++--- src/main/java/CommandMark.java | 29 ++++++++--------- src/main/java/CommandTodo.java | 16 +++++----- src/main/java/CommandUnmark.java | 29 ++++++++--------- src/main/java/Deadline.java | 10 +----- src/main/java/Event.java | 13 ++------ src/main/java/Nuke.java | 11 +++---- src/main/java/Parser.java | 22 ++++++++++--- src/main/java/Todo.java | 3 -- src/main/java/Ui.java | 4 +++ 14 files changed, 121 insertions(+), 126 deletions(-) diff --git a/src/main/java/Command.java b/src/main/java/Command.java index f26f0c74d..37d4447ae 100644 --- a/src/main/java/Command.java +++ b/src/main/java/Command.java @@ -6,7 +6,11 @@ public void handleArgumentError(InvalidCommandArgumentException e) { Ui.printCommandError(e.reason, getArgumentErrorDetail()); } - protected abstract String getArgumentErrorDetail(); + private String getArgumentErrorDetail() { + return "Usage: " + getUsage(); + } + + protected abstract String getUsage(); public abstract void run(); diff --git a/src/main/java/CommandBye.java b/src/main/java/CommandBye.java index 88ff65ef3..bf318d80d 100644 --- a/src/main/java/CommandBye.java +++ b/src/main/java/CommandBye.java @@ -1,21 +1,22 @@ public class CommandBye extends Command { - private static final String TOO_MANY_ARGUMENTS_ERROR = - "Command 'bye' should have no argument."; @Override public void applyArguments(String args) throws InvalidCommandArgumentException { if (!args.isEmpty()) { - throw new InvalidCommandArgumentException(TOO_MANY_ARGUMENTS_ERROR); + throw new InvalidCommandArgumentException(ERROR_MSG_TOO_MANY_ARGS); } } @Override - protected String getArgumentErrorDetail() { - return "Usage: bye"; + protected String getUsage() { + return "bye"; } @Override public void run() { Nuke.quit(); } + + private static final String ERROR_MSG_TOO_MANY_ARGS = + "Command 'bye' should have no arguments."; } diff --git a/src/main/java/CommandDeadline.java b/src/main/java/CommandDeadline.java index 1481f6859..b671d0af2 100644 --- a/src/main/java/CommandDeadline.java +++ b/src/main/java/CommandDeadline.java @@ -1,26 +1,17 @@ public class CommandDeadline extends Command { - private static final String NO_ARGUMENTS_ERROR = - "Command 'deadline' should have arguments."; - private static final String BY_NUMBER_ERROR = - "Command 'deadline' should have one '/by' label for the deadline."; - private static final String NAME_EMPTY_ERROR = - "Command 'deadline' should have a string as a name of the task."; - private static final String BY_EMPTY_ERROR = - "Command 'deadline' should have a string as a deadline of the task."; - public String name; public String by; @Override public void applyArguments(String args) throws InvalidCommandArgumentException { if (args.isEmpty()) { - throw new InvalidCommandArgumentException(NO_ARGUMENTS_ERROR); - } else if (!Parser.containsExactOneLabel(args, "/by")) { - throw new InvalidCommandArgumentException(BY_NUMBER_ERROR); + throw new InvalidCommandArgumentException(ERROR_MSG_NO_ARGS); + } else if (Parser.isNotContainingExactOneLabel(args, "/by")) { + throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_BY); } else if (Parser.matches(args, "/by(.*)")) { - throw new InvalidCommandArgumentException(NAME_EMPTY_ERROR); + throw new InvalidCommandArgumentException(ERROR_MSG_NAME_EMPTY); } else if (Parser.matches(args, "(.+)\\s/by")) { - throw new InvalidCommandArgumentException(BY_EMPTY_ERROR); + throw new InvalidCommandArgumentException(ERROR_MSG_BY_EMPTY); } String[] parsedArgs = Parser.parseArguments(args, "(.+)\\s/by\\s(.+)"); @@ -29,12 +20,21 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { } @Override - protected String getArgumentErrorDetail() { - return "Usage: deadline ((name)) /by ((deadline))"; + protected String getUsage() { + return "deadline ((name)) /by ((deadline))"; } @Override public void run() { Nuke.addDeadline(name, by); } + + private static final String ERROR_MSG_NO_ARGS = + "Command 'deadline' should have two arguments, name and deadline of the task."; + private static final String ERROR_MSG_INVALID_NUMBER_OF_BY = + "Command 'deadline' should have one '/by' label for the deadline."; + private static final String ERROR_MSG_NAME_EMPTY = + "Command 'deadline' should have a string for name of the task."; + private static final String ERROR_MSG_BY_EMPTY = + "Command 'deadline' should have a string for deadline of the task."; } diff --git a/src/main/java/CommandEvent.java b/src/main/java/CommandEvent.java index 3d681e951..d0ac295cf 100644 --- a/src/main/java/CommandEvent.java +++ b/src/main/java/CommandEvent.java @@ -1,15 +1,4 @@ public class CommandEvent extends Command { - private static final String NO_ARGUMENTS_ERROR = - "Command 'event' should have arguments."; - private static final String FROM_TO_NUMBER_ERROR = - "Command 'event' should have one '/from' label and one '/to' label for the period of event."; - private static final String NAME_EMPTY_ERROR = - "Command 'event' should have a string as a name of the task."; - private static final String FROM_EMPTY_ERROR = - "Command 'event' should have a string, after '/from' label, as a start period of the task."; - private static final String TO_EMPTY_ERROR = - "Command 'event' should have a string, after '/to' label, as an end period of the task."; - public String name; public String from; public String to; @@ -17,40 +6,43 @@ public class CommandEvent extends Command { @Override public void applyArguments(String args) throws InvalidCommandArgumentException { if (args.isEmpty()) { - throw new InvalidCommandArgumentException(NO_ARGUMENTS_ERROR); - } else if (!Parser.containsExactOneLabel(args, "/from")) { - throw new InvalidCommandArgumentException(FROM_TO_NUMBER_ERROR); - } else if (!Parser.containsExactOneLabel(args, "/to")) { - throw new InvalidCommandArgumentException(FROM_TO_NUMBER_ERROR); + throw new InvalidCommandArgumentException(ERROR_MSG_NO_ARGS); + } else if (Parser.isNotContainingExactOneLabel(args, "/from")) { + throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_FROM_TO); + } else if (Parser.isNotContainingExactOneLabel(args, "/to")) { + throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_FROM_TO); } else if (Parser.matches(args, "/from(.*)")) { - throw new InvalidCommandArgumentException(NAME_EMPTY_ERROR); + throw new InvalidCommandArgumentException(ERROR_MSG_NAME_EMPTY); } else if (Parser.matches(args, "(.+)\\s/from\\s/to(.*)")) { - throw new InvalidCommandArgumentException(FROM_EMPTY_ERROR); + throw new InvalidCommandArgumentException(ERROR_MSG_FROM_EMPTY); } else if (Parser.matches(args, "(.+)\\s/from\\s(.+)\\s/to")) { - throw new InvalidCommandArgumentException(TO_EMPTY_ERROR); + throw new InvalidCommandArgumentException(ERROR_MSG_TO_EMPTY); } String[] parsedArgs = Parser.parseArguments(args, "(.+)\\s/from\\s(.+)\\s/to\\s(.+)"); name = parsedArgs[0]; from = parsedArgs[1]; to = parsedArgs[2]; - - if (name.isEmpty()) { - throw new InvalidCommandArgumentException(NAME_EMPTY_ERROR); - } else if (from.isEmpty()) { - throw new InvalidCommandArgumentException(FROM_EMPTY_ERROR); - } else if (to.isEmpty()) { - throw new InvalidCommandArgumentException(TO_EMPTY_ERROR); - } } @Override - protected String getArgumentErrorDetail() { - return "Usage: event ((name)) /from ((start)) /to ((end))"; + protected String getUsage() { + return "event ((name)) /from ((start)) /to ((end))"; } @Override public void run() { Nuke.addEvent(name, from, to); } + + private static final String ERROR_MSG_NO_ARGS = + "Command 'event' should have arguments."; + private static final String ERROR_MSG_INVALID_NUMBER_OF_FROM_TO = + "Command 'event' should have one '/from' label and one '/to' label for the period of event."; + private static final String ERROR_MSG_NAME_EMPTY = + "Command 'event' should have a string for name of the task."; + private static final String ERROR_MSG_FROM_EMPTY = + "Command 'event' should have a string, after '/from' label, for start period of the task."; + private static final String ERROR_MSG_TO_EMPTY = + "Command 'event' should have a string, after '/to' label, for end period of the task."; } diff --git a/src/main/java/CommandList.java b/src/main/java/CommandList.java index 00057f6d0..3e055af6c 100644 --- a/src/main/java/CommandList.java +++ b/src/main/java/CommandList.java @@ -1,21 +1,22 @@ public class CommandList extends Command { - private static final String TOO_MANY_ARGUMENTS_ERROR = - "Command 'list' should have no argument."; @Override public void applyArguments(String args) throws InvalidCommandArgumentException { if (!args.isEmpty()) { - throw new InvalidCommandArgumentException(TOO_MANY_ARGUMENTS_ERROR); + throw new InvalidCommandArgumentException(ERROR_MSG_TOO_MANY_ARGS); } } @Override - protected String getArgumentErrorDetail() { - return "Usage: list"; + protected String getUsage() { + return "list"; } @Override public void run() { Nuke.listTask(); } + + private static final String ERROR_MSG_TOO_MANY_ARGS = + "Command 'list' should have no arguments."; } diff --git a/src/main/java/CommandMark.java b/src/main/java/CommandMark.java index c6b293428..a433fae05 100644 --- a/src/main/java/CommandMark.java +++ b/src/main/java/CommandMark.java @@ -1,35 +1,36 @@ public class CommandMark extends Command { - private static final String TOO_MANY_ARGUMENTS_ERROR = - "Command 'mark' should have one argument as an index."; - private static final String INDEX_NOT_INTEGER_ERROR = - "Command 'mark' should have a number as an index."; - private static final String INDEX_INVALID_VALUE_ERROR = - "A value of index is invalid. Please check the number of tasks."; - - public int index; + private int index; @Override public void applyArguments(String args) throws InvalidCommandArgumentException { - if (args.split("\\s").length != 1) { - throw new InvalidCommandArgumentException(TOO_MANY_ARGUMENTS_ERROR); + if (Parser.isNotOneWord(args)) { + throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_ARGS); } + // Input index starts with 1, logical index starts with 0. try { index = Integer.parseInt(args) - 1; } catch (NumberFormatException e) { - throw new InvalidCommandArgumentException(INDEX_NOT_INTEGER_ERROR); + throw new InvalidCommandArgumentException(ERROR_MSG_INDEX_NOT_INTEGER); } if(index < 0 || index >= Nuke.getNumberOfTasks()) { - throw new InvalidCommandArgumentException(INDEX_INVALID_VALUE_ERROR); + throw new InvalidCommandArgumentException(ERROR_MSG_INDEX_INVALID_VALUE); } } @Override - protected String getArgumentErrorDetail() { - return "Usage: mark ((number))"; + protected String getUsage() { + return "mark ((index))"; } @Override public void run() { Nuke.markTask(index); } + + private static final String ERROR_MSG_INVALID_NUMBER_OF_ARGS = + "Command 'mark' should have one argument, index of the task."; + private static final String ERROR_MSG_INDEX_NOT_INTEGER = + "Command 'mark' should have a number for index of the task."; + private static final String ERROR_MSG_INDEX_INVALID_VALUE = + "The value of index is invalid. Please check the number of tasks."; } diff --git a/src/main/java/CommandTodo.java b/src/main/java/CommandTodo.java index dd1bd9ff7..81612be54 100644 --- a/src/main/java/CommandTodo.java +++ b/src/main/java/CommandTodo.java @@ -1,24 +1,24 @@ public class CommandTodo extends Command { - private static final String NAME_EMPTY_ERROR = - "Command 'todo' should have a string as a name of the task."; - public String name; @Override public void applyArguments(String args) throws InvalidCommandArgumentException { - name = args; - if (name.isEmpty()) { - throw new InvalidCommandArgumentException(NAME_EMPTY_ERROR); + if (args.isEmpty()) { + throw new InvalidCommandArgumentException(ERROR_MSG_NO_ARGS); } + name = args; } @Override - protected String getArgumentErrorDetail() { - return "Usage: todo ((name))"; + protected String getUsage() { + return "todo ((name))"; } @Override public void run() { Nuke.addTodo(name); } + + private static final String ERROR_MSG_NO_ARGS = + "Command 'todo' should have one argument, name of the task."; } diff --git a/src/main/java/CommandUnmark.java b/src/main/java/CommandUnmark.java index 310f1ffc0..2a9216203 100644 --- a/src/main/java/CommandUnmark.java +++ b/src/main/java/CommandUnmark.java @@ -1,35 +1,36 @@ public class CommandUnmark extends Command { - private static final String TOO_MANY_ARGUMENTS_ERROR = - "Command 'mark' should have one argument as an index."; - private static final String INDEX_NOT_INTEGER_ERROR = - "Command 'unmark' should have a number as an index."; - private static final String INDEX_INVALID_VALUE_ERROR = - "A value of index is invalid. Please check the number of tasks."; - - public int index; + private int index; @Override public void applyArguments(String args) throws InvalidCommandArgumentException { - if (args.split("\\s").length != 1) { - throw new InvalidCommandArgumentException(TOO_MANY_ARGUMENTS_ERROR); + if (Parser.isNotOneWord(args)) { + throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_ARGS); } + // Input index starts with 1, logical index starts with 0. try { index = Integer.parseInt(args) - 1; } catch (NumberFormatException e) { - throw new InvalidCommandArgumentException(INDEX_NOT_INTEGER_ERROR); + throw new InvalidCommandArgumentException(ERROR_MSG_INDEX_NOT_INTEGER); } if(index < 0 || index >= Nuke.getNumberOfTasks()) { - throw new InvalidCommandArgumentException(INDEX_INVALID_VALUE_ERROR); + throw new InvalidCommandArgumentException(ERROR_MSG_INDEX_INVALID_VALUE); } } @Override - protected String getArgumentErrorDetail() { - return "Usage: unmark ((number))"; + protected String getUsage() { + return "unmark ((index))"; } @Override public void run() { Nuke.unmarkTask(index); } + + private static final String ERROR_MSG_INVALID_NUMBER_OF_ARGS = + "Command 'mark' should have one argument, index of the task."; + private static final String ERROR_MSG_INDEX_NOT_INTEGER = + "Command 'mark' should have a number for index of the task."; + private static final String ERROR_MSG_INDEX_INVALID_VALUE = + "The value of index is invalid. Please check the number of tasks."; } diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index 682fda8e8..1ea54ad17 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -3,17 +3,9 @@ public class Deadline extends Task { private String by; - public static Deadline parseDeadline(String cmdBody) { - String[] args = cmdBody.split(" +/by +"); - String name = args[0]; - String by = args[1]; - - return new Deadline(name, by); - } - public Deadline(String name, String by) { super(name); - this.by = by; + setBy(by); } public String getBy() { diff --git a/src/main/java/Event.java b/src/main/java/Event.java index 9afc565cd..9d0eb64da 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -2,19 +2,10 @@ public class Event extends Task { private String from; private String to; - public static Event parseEvent(String cmdBody) { - String[] args = cmdBody.split(" +(/from|/to) +"); - String name = args[0]; - String from = args[1]; - String to = args[2]; - - return new Event(name, from, to); - } - public Event(String name, String from, String to) { super(name); - this.from = from; - this.to = to; + setFrom(from); + setTo(to); } public String getFrom() { diff --git a/src/main/java/Nuke.java b/src/main/java/Nuke.java index 3034601aa..6cb3fc83d 100644 --- a/src/main/java/Nuke.java +++ b/src/main/java/Nuke.java @@ -14,19 +14,16 @@ public static void main(String[] args) { while (isRunning) { String input = USER_IN.nextLine(); runCommand(input); - System.out.println(); + Ui.printBlankLine(); } } private static void runCommand(String commandLine) { - Command command; try { - command = Parser.parseCommand(commandLine); + Command command = Parser.parseCommand(commandLine); command.run(); - } catch (InvalidCommandTypeException e) { - Command.handleTypeError(e); - } catch (InvalidCommandArgumentException ignored) { - // already processed in Parse.parseCommand(). + } catch (InvalidCommandTypeException | InvalidCommandArgumentException ignored) { + // Thrown by Parse.parseCommand() to prevent command.run(). } } diff --git a/src/main/java/Parser.java b/src/main/java/Parser.java index ee57258a4..33fd251d9 100644 --- a/src/main/java/Parser.java +++ b/src/main/java/Parser.java @@ -5,11 +5,19 @@ public class Parser { public static Command parseCommand(String commandLine) throws InvalidCommandTypeException, InvalidCommandArgumentException { + // Get command type and arguments. String type = getCommandType(commandLine); String args = getCommandArguments(commandLine, type); + Command command; - Command command = getBlankCommand(type); - + // Construct command using command type. + try { + command = getBlankCommand(type); + } catch (InvalidCommandTypeException e) { + Command.handleTypeError(e); + throw e; + } + // Apply arguments on command. try { command.applyArguments(args); } catch (InvalidCommandArgumentException e) { @@ -59,10 +67,16 @@ private static String getCommandArguments(String commandLine, String type) { return commandLine.substring(type.length()).strip(); } - public static boolean containsExactOneLabel(String str, String label) { + public static boolean isNotOneWord(String str) { + if (str.isEmpty()) { + return true; + } else return str.split("\\s").length != 1; + } + + public static boolean isNotContainingExactOneLabel(String str, String label) { String[] argSplit = str.split("\\s"); long labelCnt = Arrays.stream(argSplit).filter(a -> a.equals(label)).count(); - return labelCnt == 1; + return labelCnt != 1; } public static boolean matches(String str, String regex) { diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java index 477e3c8b4..16cb3595e 100644 --- a/src/main/java/Todo.java +++ b/src/main/java/Todo.java @@ -1,7 +1,4 @@ public class Todo extends Task { - public static Todo parseTodo(String cmdBody) { - return new Todo(cmdBody); - } public Todo(String name) { super(name); diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java index 07b59d5c6..67eb72c56 100644 --- a/src/main/java/Ui.java +++ b/src/main/java/Ui.java @@ -20,6 +20,10 @@ public static void printWelcome() { System.out.println(); } + public static void printBlankLine() { + System.out.println(); + } + public static void printBye() { System.out.println("[@] Bye. Hope to see you again soon!"); } From 54e09f3d33a571c52a75db733e6d9f93a0185c70 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sun, 10 Sep 2023 01:20:45 +0800 Subject: [PATCH 18/52] Fix minor error --- src/main/java/CommandEvent.java | 2 +- src/main/java/CommandUnmark.java | 4 ++-- src/main/java/Ui.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/CommandEvent.java b/src/main/java/CommandEvent.java index d0ac295cf..466d5a3ce 100644 --- a/src/main/java/CommandEvent.java +++ b/src/main/java/CommandEvent.java @@ -36,7 +36,7 @@ public void run() { } private static final String ERROR_MSG_NO_ARGS = - "Command 'event' should have arguments."; + "Command 'event' should have three arguments, name, start and end of the event."; private static final String ERROR_MSG_INVALID_NUMBER_OF_FROM_TO = "Command 'event' should have one '/from' label and one '/to' label for the period of event."; private static final String ERROR_MSG_NAME_EMPTY = diff --git a/src/main/java/CommandUnmark.java b/src/main/java/CommandUnmark.java index 2a9216203..923a36b56 100644 --- a/src/main/java/CommandUnmark.java +++ b/src/main/java/CommandUnmark.java @@ -28,9 +28,9 @@ public void run() { } private static final String ERROR_MSG_INVALID_NUMBER_OF_ARGS = - "Command 'mark' should have one argument, index of the task."; + "Command 'unmark' should have one argument, index of the task."; private static final String ERROR_MSG_INDEX_NOT_INTEGER = - "Command 'mark' should have a number for index of the task."; + "Command 'unmark' should have a number for index of the task."; private static final String ERROR_MSG_INDEX_INVALID_VALUE = "The value of index is invalid. Please check the number of tasks."; } diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java index 67eb72c56..dc103feb6 100644 --- a/src/main/java/Ui.java +++ b/src/main/java/Ui.java @@ -31,7 +31,7 @@ public static void printBye() { public static void printAddedTask(String addedTask, int taskCnt) { System.out.println("[@] Got it. I've added this task:"); System.out.println(" " + addedTask); - System.out.printf("[@] Now you have %d tasks in the list.\n", taskCnt); + System.out.printf("[@] Now you have %d task%s in the list.\n", taskCnt, taskCnt == 1? "": "s"); } public static void printListOfTasks(String[] tasks) { From aa2850f6afef74d83925e81e6b23441ad85af9be Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sun, 10 Sep 2023 01:21:40 +0800 Subject: [PATCH 19/52] Update input.txt and EXPECTED.TXT --- text-ui-test/EXPECTED.TXT | 119 +++++++++++++++++++++++++++++++------- text-ui-test/input.txt | 39 +++++++++++-- 2 files changed, 130 insertions(+), 28 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index dc27a0464..07f34fc5f 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -14,50 +14,125 @@ [@] Hello! I'm Nuke. [@] What can I do for you? +[@] Wrong input; Command 'bye' should have no arguments. +[@] Usage: bye + +[@] Wrong input; Command 'list' should have no arguments. +[@] Usage: list + +[@] There are no tasks in your list. + +[@] Wrong input; Command 'todo' should have one argument, name of the task. +[@] Usage: todo ((name)) + [@] Got it. I've added this task: [T][ ] read book -[@] Now you have 1 tasks in the list. +[@] Now you have 1 task in the list. + +[@] Wrong input; Command 'deadline' should have two arguments, name and deadline of the task. +[@] Usage: deadline ((name)) /by ((deadline)) + +[@] Wrong input; Command 'deadline' should have a string for name of the task. +[@] Usage: deadline ((name)) /by ((deadline)) + +[@] Wrong input; Command 'deadline' should have a string for name of the task. +[@] Usage: deadline ((name)) /by ((deadline)) + +[@] Wrong input; Command 'deadline' should have one '/by' label for the deadline. +[@] Usage: deadline ((name)) /by ((deadline)) + +[@] Wrong input; Command 'deadline' should have a string for deadline of the task. +[@] Usage: deadline ((name)) /by ((deadline)) [@] Got it. I've added this task: [D][ ] return book (by: June 6th) [@] Now you have 2 tasks in the list. +[@] Wrong input; Command 'event' should have three arguments, name, start and end of the event. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should have one '/from' label and one '/to' label for the period of event. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should have one '/from' label and one '/to' label for the period of event. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should have one '/from' label and one '/to' label for the period of event. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should have one '/from' label and one '/to' label for the period of event. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should have a string for name of the task. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should have a string for name of the task. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should have a string for name of the task. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should have one '/from' label and one '/to' label for the period of event. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should have one '/from' label and one '/to' label for the period of event. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should have one '/from' label and one '/to' label for the period of event. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should have one '/from' label and one '/to' label for the period of event. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should have one '/from' label and one '/to' label for the period of event. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should have a string, after '/from' label, for start period of the task. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should have a string, after '/to' label, for end period of the task. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + [@] Got it. I've added this task: [E][ ] project meeting (from: Aug 6th 2pm to: 4pm) [@] Now you have 3 tasks in the list. -[@] Got it. I've added this task: - [T][ ] join sports club -[@] Now you have 4 tasks in the list. +[@] Wrong input; Command 'mark' should have one argument, index of the task. +[@] Usage: mark ((index)) + +[@] Wrong input; The value of index is invalid. Please check the number of tasks. +[@] Usage: mark ((index)) + +[@] Wrong input; The value of index is invalid. Please check the number of tasks. +[@] Usage: mark ((index)) [@] Nice! I've marked this task as done: [T][X] read book [@] Nice! I've marked this task as done: - [T][X] join sports club + [E][X] project meeting (from: Aug 6th 2pm to: 4pm) -[@] Got it. I've added this task: - [T][ ] borrow book -[@] Now you have 5 tasks in the list. - -[@] Here are the tasks in you list: +[@] Here are the tasks in your list: 1.[T][X] read book 2.[D][ ] return book (by: June 6th) -3.[E][ ] project meeting (from: Aug 6th 2pm to: 4pm) -4.[T][X] join sports club -5.[T][ ] borrow book +3.[E][X] project meeting (from: Aug 6th 2pm to: 4pm) -[@] Got it. I've added this task: - [D][ ] return book (by: Sunday) -[@] Now you have 6 tasks in the list. +[@] Wrong input; Command 'unmark' should have one argument, index of the task. +[@] Usage: unmark ((index)) -[@] Got it. I've added this task: - [E][ ] project meeting (from: Mon 2pm to: 4pm) -[@] Now you have 7 tasks in the list. +[@] Wrong input; The value of index is invalid. Please check the number of tasks. +[@] Usage: unmark ((index)) -[@] Got it. I've added this task: - [D][ ] do homework (by: no idea :-p) -[@] Now you have 8 tasks in the list. +[@] Wrong input; The value of index is invalid. Please check the number of tasks. +[@] Usage: unmark ((index)) + +[@] OK, I've marked this task as not done yet: + [E][ ] project meeting (from: Aug 6th 2pm to: 4pm) + +[@] Here are the tasks in your list: +1.[T][X] read book +2.[D][ ] return book (by: June 6th) +3.[E][ ] project meeting (from: Aug 6th 2pm to: 4pm) [@] Bye. Hope to see you again soon! diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index d04360f0f..49db48603 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,12 +1,39 @@ +bye no +list no +list +todo todo read book +deadline +deadline /by +deadline /by June 6th +deadline return book +deadline return book /by deadline return book /by June 6th +event +event /to +event /to 4pm +event /from +event /from Aug 6th 2pm +event /from /to +event /from Aug 6th 2pm /to +event /from Aug 6th 2pm /to 4pm +event project meeting +event project meeting /to +event project meeting /to 4pm +event project meeting /from +event project meeting /from Aug 6th 2pm +event project meeting /from /to +event project meeting /from Aug 6th 2pm /to event project meeting /from Aug 6th 2pm /to 4pm -todo join sports club -mark 1 +mark +mark 0 mark 4 -todo borrow book +mark 1 +mark 3 +list +unmark +unmark 0 +unmark 4 +unmark 3 list -deadline return book /by Sunday -event project meeting /from Mon 2pm /to 4pm -deadline do homework /by no idea :-p bye From 31bd2ea1dc045b903c3f2acf5875ccc550bbad9b Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sun, 10 Sep 2023 01:39:25 +0800 Subject: [PATCH 20/52] Organize classes into packages --- src/main/java/{ => nuke}/Nuke.java | 10 ++++++++++ src/main/java/{ => nuke}/NukeException.java | 2 ++ src/main/java/{ => nuke}/Parser.java | 6 ++++++ src/main/java/{ => nuke}/Ui.java | 2 ++ src/main/java/{ => nuke/command}/Command.java | 6 ++++++ src/main/java/{ => nuke/command}/CommandBye.java | 5 +++++ src/main/java/{ => nuke/command}/CommandDeadline.java | 6 ++++++ src/main/java/{ => nuke/command}/CommandEvent.java | 6 ++++++ src/main/java/{ => nuke/command}/CommandList.java | 5 +++++ src/main/java/{ => nuke/command}/CommandMark.java | 6 ++++++ src/main/java/{ => nuke/command}/CommandTodo.java | 5 +++++ src/main/java/{ => nuke/command}/CommandUnmark.java | 6 ++++++ .../exception}/InvalidCommandArgumentException.java | 4 ++++ .../exception}/InvalidCommandTypeException.java | 4 ++++ src/main/java/{ => nuke/task}/Deadline.java | 2 +- src/main/java/{ => nuke/task}/Event.java | 2 ++ src/main/java/{ => nuke/task}/Task.java | 2 ++ src/main/java/{ => nuke/task}/Todo.java | 2 ++ 18 files changed, 80 insertions(+), 1 deletion(-) rename src/main/java/{ => nuke}/Nuke.java (88%) rename src/main/java/{ => nuke}/NukeException.java (76%) rename src/main/java/{ => nuke}/Parser.java (94%) rename src/main/java/{ => nuke}/Ui.java (99%) rename src/main/java/{ => nuke/command}/Command.java (82%) rename src/main/java/{ => nuke/command}/CommandBye.java (83%) rename src/main/java/{ => nuke/command}/CommandDeadline.java (92%) rename src/main/java/{ => nuke/command}/CommandEvent.java (94%) rename src/main/java/{ => nuke/command}/CommandList.java (83%) rename src/main/java/{ => nuke/command}/CommandMark.java (91%) rename src/main/java/{ => nuke/command}/CommandTodo.java (85%) rename src/main/java/{ => nuke/command}/CommandUnmark.java (91%) rename src/main/java/{ => nuke/command/exception}/InvalidCommandArgumentException.java (76%) rename src/main/java/{ => nuke/command/exception}/InvalidCommandTypeException.java (74%) rename src/main/java/{ => nuke/task}/Deadline.java (94%) rename src/main/java/{ => nuke/task}/Event.java (96%) rename src/main/java/{ => nuke/task}/Task.java (96%) rename src/main/java/{ => nuke/task}/Todo.java (90%) diff --git a/src/main/java/Nuke.java b/src/main/java/nuke/Nuke.java similarity index 88% rename from src/main/java/Nuke.java rename to src/main/java/nuke/Nuke.java index 6cb3fc83d..18e723d35 100644 --- a/src/main/java/Nuke.java +++ b/src/main/java/nuke/Nuke.java @@ -1,3 +1,13 @@ +package nuke; + +import nuke.command.Command; +import nuke.command.exception.InvalidCommandArgumentException; +import nuke.command.exception.InvalidCommandTypeException; +import nuke.task.Deadline; +import nuke.task.Event; +import nuke.task.Task; +import nuke.task.Todo; + import java.util.ArrayList; import java.util.Scanner; diff --git a/src/main/java/NukeException.java b/src/main/java/nuke/NukeException.java similarity index 76% rename from src/main/java/NukeException.java rename to src/main/java/nuke/NukeException.java index 7eb620490..9a089e3a3 100644 --- a/src/main/java/NukeException.java +++ b/src/main/java/nuke/NukeException.java @@ -1,2 +1,4 @@ +package nuke; + public class NukeException extends Exception { } diff --git a/src/main/java/Parser.java b/src/main/java/nuke/Parser.java similarity index 94% rename from src/main/java/Parser.java rename to src/main/java/nuke/Parser.java index 33fd251d9..e99c10361 100644 --- a/src/main/java/Parser.java +++ b/src/main/java/nuke/Parser.java @@ -1,3 +1,9 @@ +package nuke; + +import nuke.command.*; +import nuke.command.exception.InvalidCommandArgumentException; +import nuke.command.exception.InvalidCommandTypeException; + import java.util.Arrays; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/src/main/java/Ui.java b/src/main/java/nuke/Ui.java similarity index 99% rename from src/main/java/Ui.java rename to src/main/java/nuke/Ui.java index dc103feb6..c9bddc4b4 100644 --- a/src/main/java/Ui.java +++ b/src/main/java/nuke/Ui.java @@ -1,3 +1,5 @@ +package nuke; + public class Ui { public static final String LOGO = " _.-^^---....,,-- \n" + diff --git a/src/main/java/Command.java b/src/main/java/nuke/command/Command.java similarity index 82% rename from src/main/java/Command.java rename to src/main/java/nuke/command/Command.java index 37d4447ae..571a2b449 100644 --- a/src/main/java/Command.java +++ b/src/main/java/nuke/command/Command.java @@ -1,3 +1,9 @@ +package nuke.command; + +import nuke.command.exception.InvalidCommandArgumentException; +import nuke.command.exception.InvalidCommandTypeException; +import nuke.Ui; + public abstract class Command { public abstract void applyArguments(String args) throws InvalidCommandArgumentException; diff --git a/src/main/java/CommandBye.java b/src/main/java/nuke/command/CommandBye.java similarity index 83% rename from src/main/java/CommandBye.java rename to src/main/java/nuke/command/CommandBye.java index bf318d80d..7ae1c1616 100644 --- a/src/main/java/CommandBye.java +++ b/src/main/java/nuke/command/CommandBye.java @@ -1,3 +1,8 @@ +package nuke.command; + +import nuke.command.exception.InvalidCommandArgumentException; +import nuke.Nuke; + public class CommandBye extends Command { @Override diff --git a/src/main/java/CommandDeadline.java b/src/main/java/nuke/command/CommandDeadline.java similarity index 92% rename from src/main/java/CommandDeadline.java rename to src/main/java/nuke/command/CommandDeadline.java index b671d0af2..5a7562999 100644 --- a/src/main/java/CommandDeadline.java +++ b/src/main/java/nuke/command/CommandDeadline.java @@ -1,3 +1,9 @@ +package nuke.command; + +import nuke.command.exception.InvalidCommandArgumentException; +import nuke.Nuke; +import nuke.Parser; + public class CommandDeadline extends Command { public String name; public String by; diff --git a/src/main/java/CommandEvent.java b/src/main/java/nuke/command/CommandEvent.java similarity index 94% rename from src/main/java/CommandEvent.java rename to src/main/java/nuke/command/CommandEvent.java index 466d5a3ce..67e5e1f1c 100644 --- a/src/main/java/CommandEvent.java +++ b/src/main/java/nuke/command/CommandEvent.java @@ -1,3 +1,9 @@ +package nuke.command; + +import nuke.command.exception.InvalidCommandArgumentException; +import nuke.Nuke; +import nuke.Parser; + public class CommandEvent extends Command { public String name; public String from; diff --git a/src/main/java/CommandList.java b/src/main/java/nuke/command/CommandList.java similarity index 83% rename from src/main/java/CommandList.java rename to src/main/java/nuke/command/CommandList.java index 3e055af6c..1d8b931a8 100644 --- a/src/main/java/CommandList.java +++ b/src/main/java/nuke/command/CommandList.java @@ -1,3 +1,8 @@ +package nuke.command; + +import nuke.command.exception.InvalidCommandArgumentException; +import nuke.Nuke; + public class CommandList extends Command { @Override diff --git a/src/main/java/CommandMark.java b/src/main/java/nuke/command/CommandMark.java similarity index 91% rename from src/main/java/CommandMark.java rename to src/main/java/nuke/command/CommandMark.java index a433fae05..d4fc8ba7f 100644 --- a/src/main/java/CommandMark.java +++ b/src/main/java/nuke/command/CommandMark.java @@ -1,3 +1,9 @@ +package nuke.command; + +import nuke.command.exception.InvalidCommandArgumentException; +import nuke.Nuke; +import nuke.Parser; + public class CommandMark extends Command { private int index; diff --git a/src/main/java/CommandTodo.java b/src/main/java/nuke/command/CommandTodo.java similarity index 85% rename from src/main/java/CommandTodo.java rename to src/main/java/nuke/command/CommandTodo.java index 81612be54..e34fba2d5 100644 --- a/src/main/java/CommandTodo.java +++ b/src/main/java/nuke/command/CommandTodo.java @@ -1,3 +1,8 @@ +package nuke.command; + +import nuke.command.exception.InvalidCommandArgumentException; +import nuke.Nuke; + public class CommandTodo extends Command { public String name; diff --git a/src/main/java/CommandUnmark.java b/src/main/java/nuke/command/CommandUnmark.java similarity index 91% rename from src/main/java/CommandUnmark.java rename to src/main/java/nuke/command/CommandUnmark.java index 923a36b56..e2e554f09 100644 --- a/src/main/java/CommandUnmark.java +++ b/src/main/java/nuke/command/CommandUnmark.java @@ -1,3 +1,9 @@ +package nuke.command; + +import nuke.command.exception.InvalidCommandArgumentException; +import nuke.Nuke; +import nuke.Parser; + public class CommandUnmark extends Command { private int index; diff --git a/src/main/java/InvalidCommandArgumentException.java b/src/main/java/nuke/command/exception/InvalidCommandArgumentException.java similarity index 76% rename from src/main/java/InvalidCommandArgumentException.java rename to src/main/java/nuke/command/exception/InvalidCommandArgumentException.java index ace638e4b..81d318b59 100644 --- a/src/main/java/InvalidCommandArgumentException.java +++ b/src/main/java/nuke/command/exception/InvalidCommandArgumentException.java @@ -1,3 +1,7 @@ +package nuke.command.exception; + +import nuke.NukeException; + public class InvalidCommandArgumentException extends NukeException { public String reason; diff --git a/src/main/java/InvalidCommandTypeException.java b/src/main/java/nuke/command/exception/InvalidCommandTypeException.java similarity index 74% rename from src/main/java/InvalidCommandTypeException.java rename to src/main/java/nuke/command/exception/InvalidCommandTypeException.java index da158fe6a..a93eecccf 100644 --- a/src/main/java/InvalidCommandTypeException.java +++ b/src/main/java/nuke/command/exception/InvalidCommandTypeException.java @@ -1,3 +1,7 @@ +package nuke.command.exception; + +import nuke.NukeException; + public class InvalidCommandTypeException extends NukeException { public String type; diff --git a/src/main/java/Deadline.java b/src/main/java/nuke/task/Deadline.java similarity index 94% rename from src/main/java/Deadline.java rename to src/main/java/nuke/task/Deadline.java index 1ea54ad17..ac6d63b46 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/nuke/task/Deadline.java @@ -1,4 +1,4 @@ -import java.util.Arrays; +package nuke.task; public class Deadline extends Task { private String by; diff --git a/src/main/java/Event.java b/src/main/java/nuke/task/Event.java similarity index 96% rename from src/main/java/Event.java rename to src/main/java/nuke/task/Event.java index 9d0eb64da..9a712343e 100644 --- a/src/main/java/Event.java +++ b/src/main/java/nuke/task/Event.java @@ -1,3 +1,5 @@ +package nuke.task; + public class Event extends Task { private String from; private String to; diff --git a/src/main/java/Task.java b/src/main/java/nuke/task/Task.java similarity index 96% rename from src/main/java/Task.java rename to src/main/java/nuke/task/Task.java index 7094da302..876199868 100644 --- a/src/main/java/Task.java +++ b/src/main/java/nuke/task/Task.java @@ -1,3 +1,5 @@ +package nuke.task; + public abstract class Task { private String name; private boolean isDone; diff --git a/src/main/java/Todo.java b/src/main/java/nuke/task/Todo.java similarity index 90% rename from src/main/java/Todo.java rename to src/main/java/nuke/task/Todo.java index 16cb3595e..a73694a89 100644 --- a/src/main/java/Todo.java +++ b/src/main/java/nuke/task/Todo.java @@ -1,3 +1,5 @@ +package nuke.task; + public class Todo extends Task { public Todo(String name) { From 080dfa1ee31f088c945117a3c2eb9c074a6c2cf7 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Fri, 15 Sep 2023 17:42:43 +0800 Subject: [PATCH 21/52] Update runtest.bat to compile without errors --- text-ui-test/EXPECTED.TXT | 6 ++++++ text-ui-test/input.txt | 2 ++ text-ui-test/runtest.bat | 7 +++++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 07f34fc5f..fbd22ac4a 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -103,6 +103,9 @@ [@] Wrong input; The value of index is invalid. Please check the number of tasks. [@] Usage: mark ((index)) +[@] Wrong input; Command 'mark' should have a number for index of the task. +[@] Usage: mark ((index)) + [@] Wrong input; The value of index is invalid. Please check the number of tasks. [@] Usage: mark ((index)) @@ -120,6 +123,9 @@ [@] Wrong input; Command 'unmark' should have one argument, index of the task. [@] Usage: unmark ((index)) +[@] Wrong input; Command 'unmark' should have a number for index of the task. +[@] Usage: unmark ((index)) + [@] Wrong input; The value of index is invalid. Please check the number of tasks. [@] Usage: unmark ((index)) diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 49db48603..0bca5430b 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -27,11 +27,13 @@ event project meeting /from Aug 6th 2pm /to event project meeting /from Aug 6th 2pm /to 4pm mark mark 0 +mark hi mark 4 mark 1 mark 3 list unmark +unmark hi unmark 0 unmark 4 unmark 3 diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index d22f2fb7c..50e2c63fe 100644 --- a/text-ui-test/runtest.bat +++ b/text-ui-test/runtest.bat @@ -7,7 +7,10 @@ REM delete output from previous run if exist ACTUAL.TXT del ACTUAL.TXT REM compile the code into the bin folder -javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\*.java +javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\nuke\*.java +javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\nuke\command\*.java +javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\nuke\command\exception\*.java +javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\nuke\task\*.java IF ERRORLEVEL 1 ( echo ********** BUILD FAILURE ********** exit /b 1 @@ -15,7 +18,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 Nuke < input.txt > ACTUAL.TXT +java -classpath ..\bin nuke.Nuke < input.txt > ACTUAL.TXT REM compare the output to the expected output FC ACTUAL.TXT EXPECTED.TXT From 53c43d460dc7b381c38f9036ca23bf8734547931 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Fri, 15 Sep 2023 18:25:11 +0800 Subject: [PATCH 22/52] Complete Level-6 --- src/main/java/nuke/Nuke.java | 5 +++ src/main/java/nuke/Parser.java | 3 ++ src/main/java/nuke/Ui.java | 9 +++- src/main/java/nuke/command/CommandDelete.java | 42 +++++++++++++++++++ text-ui-test/EXPECTED.TXT | 31 ++++++++++++++ text-ui-test/input.txt | 8 ++++ 6 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/main/java/nuke/command/CommandDelete.java diff --git a/src/main/java/nuke/Nuke.java b/src/main/java/nuke/Nuke.java index 18e723d35..269192ba6 100644 --- a/src/main/java/nuke/Nuke.java +++ b/src/main/java/nuke/Nuke.java @@ -64,6 +64,11 @@ public static void unmarkTask(int idx) { Ui.printUnmarkedTask(task.toString()); } + public static void deleteTask(int idx) { + Task task = tasks.remove(idx); + Ui.printDeletedTask(task.toString(), getNumberOfTasks()); + } + public static void addTodo(String name) { addTask(new Todo(name)); } diff --git a/src/main/java/nuke/Parser.java b/src/main/java/nuke/Parser.java index e99c10361..55a87be54 100644 --- a/src/main/java/nuke/Parser.java +++ b/src/main/java/nuke/Parser.java @@ -59,6 +59,9 @@ private static Command getBlankCommand(String type) case "event": command = new CommandEvent(); break; + case "delete": + command = new CommandDelete(); + break; default: throw new InvalidCommandTypeException(type); } diff --git a/src/main/java/nuke/Ui.java b/src/main/java/nuke/Ui.java index c9bddc4b4..21e4c2bf2 100644 --- a/src/main/java/nuke/Ui.java +++ b/src/main/java/nuke/Ui.java @@ -33,9 +33,8 @@ public static void printBye() { public static void printAddedTask(String addedTask, int taskCnt) { System.out.println("[@] Got it. I've added this task:"); System.out.println(" " + addedTask); - System.out.printf("[@] Now you have %d task%s in the list.\n", taskCnt, taskCnt == 1? "": "s"); + System.out.printf("[@] Now you have %d task%s in the list.\n", taskCnt, taskCnt == 1 ? "": "s"); } - public static void printListOfTasks(String[] tasks) { if(tasks.length == 0) { System.out.println("[@] There are no tasks in your list."); @@ -57,6 +56,12 @@ public static void printUnmarkedTask(String unmarkedTask) { System.out.println(" " + unmarkedTask); } + public static void printDeletedTask(String deletedTask, int taskCnt) { + System.out.println("[@] Noted. I've removed this task:"); + System.out.println(" " + deletedTask); + System.out.printf("[@] Now you have %d task%s in the list.\n", taskCnt, taskCnt == 1 ? "": "s"); + } + public static void printCommandError(String description, String detail) { System.out.println("[@] Wrong input; " + description); System.out.println("[@] " + detail); diff --git a/src/main/java/nuke/command/CommandDelete.java b/src/main/java/nuke/command/CommandDelete.java new file mode 100644 index 000000000..3fa05bbf6 --- /dev/null +++ b/src/main/java/nuke/command/CommandDelete.java @@ -0,0 +1,42 @@ +package nuke.command; + +import nuke.Nuke; +import nuke.Parser; +import nuke.command.exception.InvalidCommandArgumentException; + +public class CommandDelete extends Command { + private int index; + + @Override + public void applyArguments(String args) throws InvalidCommandArgumentException { + if (Parser.isNotOneWord(args)) { + throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_ARGS); + } + // Input index starts with 1, logical index starts with 0. + try { + index = Integer.parseInt(args) - 1; + } catch (NumberFormatException e) { + throw new InvalidCommandArgumentException(ERROR_MSG_INDEX_NOT_INTEGER); + } + if(index < 0 || index >= Nuke.getNumberOfTasks()) { + throw new InvalidCommandArgumentException(ERROR_MSG_INDEX_INVALID_VALUE); + } + } + + @Override + protected String getUsage() { + return "delete ((index))"; + } + + @Override + public void run() { + Nuke.deleteTask(index); + } + + private static final String ERROR_MSG_INVALID_NUMBER_OF_ARGS = + "Command 'delete' should have one argument, index of the task."; + private static final String ERROR_MSG_INDEX_NOT_INTEGER = + "Command 'delete' should have a number for index of the task."; + private static final String ERROR_MSG_INDEX_INVALID_VALUE = + "The value of index is invalid. Please check the number of tasks."; +} diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index fbd22ac4a..02952bfd7 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -140,5 +140,36 @@ 2.[D][ ] return book (by: June 6th) 3.[E][ ] project meeting (from: Aug 6th 2pm to: 4pm) +[@] Got it. I've added this task: + [T][ ] delete this +[@] Now you have 4 tasks in the list. + +[@] Here are the tasks in your list: +1.[T][X] read book +2.[D][ ] return book (by: June 6th) +3.[E][ ] project meeting (from: Aug 6th 2pm to: 4pm) +4.[T][ ] delete this + +[@] Wrong input; Command 'delete' should have one argument, index of the task. +[@] Usage: delete ((index)) + +[@] Wrong input; Command 'delete' should have a number for index of the task. +[@] Usage: delete ((index)) + +[@] Wrong input; The value of index is invalid. Please check the number of tasks. +[@] Usage: delete ((index)) + +[@] Wrong input; The value of index is invalid. Please check the number of tasks. +[@] Usage: delete ((index)) + +[@] Noted. I've removed this task: + [T][ ] delete this +[@] Now you have 3 tasks in the list. + +[@] Here are the tasks in your list: +1.[T][X] read book +2.[D][ ] return book (by: June 6th) +3.[E][ ] project meeting (from: Aug 6th 2pm to: 4pm) + [@] Bye. Hope to see you again soon! diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 0bca5430b..e6ce754c5 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -38,4 +38,12 @@ unmark 0 unmark 4 unmark 3 list +todo delete this +list +delete +delete hi +delete 0 +delete 5 +delete 4 +list bye From 015b9525a8a44ee8cb8867aaac36cf0a8675e7ae Mon Sep 17 00:00:00 2001 From: ICubE- Date: Fri, 15 Sep 2023 18:48:05 +0800 Subject: [PATCH 23/52] Update command type error detail --- src/main/java/nuke/command/Command.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/nuke/command/Command.java b/src/main/java/nuke/command/Command.java index 571a2b449..4ddc156b5 100644 --- a/src/main/java/nuke/command/Command.java +++ b/src/main/java/nuke/command/Command.java @@ -22,7 +22,7 @@ private String getArgumentErrorDetail() { public static void handleTypeError(InvalidCommandTypeException e) { String desc = String.format("There is no command called '%s'.", e.type); - String detail = "Existing command: bye, list, mark, unmark, todo, deadline, event"; + String detail = "Existing command: bye, list, mark, unmark, todo, deadline, event, delete"; Ui.printCommandError(desc, detail); } } From c9c11b7d5d238ebef3455d3445d9e33934f5a337 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Fri, 15 Sep 2023 19:24:11 +0800 Subject: [PATCH 24/52] Add forbidden characters --- src/main/java/nuke/Ui.java | 2 +- src/main/java/nuke/command/Command.java | 18 ++++++++++++++++++ .../java/nuke/command/CommandDeadline.java | 1 + src/main/java/nuke/command/CommandEvent.java | 1 + src/main/java/nuke/command/CommandTodo.java | 1 + text-ui-test/EXPECTED.TXT | 19 ++++++++++++++++++- text-ui-test/input.txt | 6 ++++++ 7 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/main/java/nuke/Ui.java b/src/main/java/nuke/Ui.java index c9bddc4b4..49c7ef21f 100644 --- a/src/main/java/nuke/Ui.java +++ b/src/main/java/nuke/Ui.java @@ -12,7 +12,7 @@ public class Ui { " .-=|| | |=-. \n" + " `-=#$%&%$#=-' \n" + " | ; :| \n" + - " _____.,-#%&$@%#&#~,._____ \n"; + " _____.,-#%&$@%#&#~,._____ "; public static void printWelcome() { System.out.println(LOGO); diff --git a/src/main/java/nuke/command/Command.java b/src/main/java/nuke/command/Command.java index 571a2b449..f1b8bd7b2 100644 --- a/src/main/java/nuke/command/Command.java +++ b/src/main/java/nuke/command/Command.java @@ -4,10 +4,24 @@ import nuke.command.exception.InvalidCommandTypeException; import nuke.Ui; +import java.util.Arrays; + public abstract class Command { + private static final String FORBIDDEN_CHARACTERS = "/"; + private static final String ERROR_MSG_FORBIDDEN_CHARACTERS = + "Command '%s' should not contain '" + FORBIDDEN_CHARACTERS + "' in arguments."; + public abstract void applyArguments(String args) throws InvalidCommandArgumentException; + protected void checkForbiddenCharacters(String[] parsedArgs) + throws InvalidCommandArgumentException { + if (Arrays.stream(parsedArgs).anyMatch(s -> s.contains(FORBIDDEN_CHARACTERS))) { + String errorMessage = String.format(ERROR_MSG_FORBIDDEN_CHARACTERS, getType()); + throw new InvalidCommandArgumentException(errorMessage); + } + } + public void handleArgumentError(InvalidCommandArgumentException e) { Ui.printCommandError(e.reason, getArgumentErrorDetail()); } @@ -16,6 +30,10 @@ private String getArgumentErrorDetail() { return "Usage: " + getUsage(); } + protected String getType() { + return getUsage().split(" ")[0]; + } + protected abstract String getUsage(); public abstract void run(); diff --git a/src/main/java/nuke/command/CommandDeadline.java b/src/main/java/nuke/command/CommandDeadline.java index 5a7562999..9b51d1df9 100644 --- a/src/main/java/nuke/command/CommandDeadline.java +++ b/src/main/java/nuke/command/CommandDeadline.java @@ -21,6 +21,7 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { } String[] parsedArgs = Parser.parseArguments(args, "(.+)\\s/by\\s(.+)"); + checkForbiddenCharacters(parsedArgs); name = parsedArgs[0]; by = parsedArgs[1]; } diff --git a/src/main/java/nuke/command/CommandEvent.java b/src/main/java/nuke/command/CommandEvent.java index 67e5e1f1c..06999ddb0 100644 --- a/src/main/java/nuke/command/CommandEvent.java +++ b/src/main/java/nuke/command/CommandEvent.java @@ -26,6 +26,7 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { } String[] parsedArgs = Parser.parseArguments(args, "(.+)\\s/from\\s(.+)\\s/to\\s(.+)"); + checkForbiddenCharacters(parsedArgs); name = parsedArgs[0]; from = parsedArgs[1]; to = parsedArgs[2]; diff --git a/src/main/java/nuke/command/CommandTodo.java b/src/main/java/nuke/command/CommandTodo.java index e34fba2d5..29fdc882b 100644 --- a/src/main/java/nuke/command/CommandTodo.java +++ b/src/main/java/nuke/command/CommandTodo.java @@ -11,6 +11,7 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { if (args.isEmpty()) { throw new InvalidCommandArgumentException(ERROR_MSG_NO_ARGS); } + checkForbiddenCharacters(new String[]{args}); name = args; } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index fbd22ac4a..962f22311 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -10,7 +10,6 @@ | ; :| _____.,-#%&$@%#&#~,._____ - [@] Hello! I'm Nuke. [@] What can I do for you? @@ -25,6 +24,9 @@ [@] Wrong input; Command 'todo' should have one argument, name of the task. [@] Usage: todo ((name)) +[@] Wrong input; Command 'todo' should not contain '/' in arguments. +[@] Usage: todo ((name)) + [@] Got it. I've added this task: [T][ ] read book [@] Now you have 1 task in the list. @@ -44,6 +46,12 @@ [@] Wrong input; Command 'deadline' should have a string for deadline of the task. [@] Usage: deadline ((name)) /by ((deadline)) +[@] Wrong input; Command 'deadline' should not contain '/' in arguments. +[@] Usage: deadline ((name)) /by ((deadline)) + +[@] Wrong input; Command 'deadline' should not contain '/' in arguments. +[@] Usage: deadline ((name)) /by ((deadline)) + [@] Got it. I've added this task: [D][ ] return book (by: June 6th) [@] Now you have 2 tasks in the list. @@ -93,6 +101,15 @@ [@] Wrong input; Command 'event' should have a string, after '/to' label, for end period of the task. [@] Usage: event ((name)) /from ((start)) /to ((end)) +[@] Wrong input; Command 'event' should not contain '/' in arguments. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should not contain '/' in arguments. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + +[@] Wrong input; Command 'event' should not contain '/' in arguments. +[@] Usage: event ((name)) /from ((start)) /to ((end)) + [@] Got it. I've added this task: [E][ ] project meeting (from: Aug 6th 2pm to: 4pm) [@] Now you have 3 tasks in the list. diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 0bca5430b..a530766ce 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -2,12 +2,15 @@ bye no list no list todo +todo read/book todo read book deadline deadline /by deadline /by June 6th deadline return book deadline return book /by +deadline return/book /by June 6th +deadline return book /by June/6th deadline return book /by June 6th event event /to @@ -24,6 +27,9 @@ event project meeting /from event project meeting /from Aug 6th 2pm event project meeting /from /to event project meeting /from Aug 6th 2pm /to +event project/meeting /from Aug 6th 2pm /to 4pm +event project meeting /from Aug/6th/2pm /to 4pm +event project meeting /from Aug 6th 2pm /to 4pm/ event project meeting /from Aug 6th 2pm /to 4pm mark mark 0 From 02afe6ee3144ff477717b1d5d9dac7daa8b054c5 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 16 Sep 2023 13:02:57 +0800 Subject: [PATCH 25/52] Rename Parser to CommandParser --- src/main/java/nuke/command/Command.java | 7 ------- src/main/java/nuke/command/CommandDeadline.java | 9 ++++----- src/main/java/nuke/command/CommandEvent.java | 13 ++++++------- src/main/java/nuke/command/CommandMark.java | 3 +-- .../{Parser.java => command/CommandParser.java} | 13 ++++++++++--- src/main/java/nuke/command/CommandUnmark.java | 3 +-- 6 files changed, 22 insertions(+), 26 deletions(-) rename src/main/java/nuke/{Parser.java => command/CommandParser.java} (88%) diff --git a/src/main/java/nuke/command/Command.java b/src/main/java/nuke/command/Command.java index f1b8bd7b2..942d7f678 100644 --- a/src/main/java/nuke/command/Command.java +++ b/src/main/java/nuke/command/Command.java @@ -1,7 +1,6 @@ package nuke.command; import nuke.command.exception.InvalidCommandArgumentException; -import nuke.command.exception.InvalidCommandTypeException; import nuke.Ui; import java.util.Arrays; @@ -37,10 +36,4 @@ protected String getType() { protected abstract String getUsage(); public abstract void run(); - - public static void handleTypeError(InvalidCommandTypeException e) { - String desc = String.format("There is no command called '%s'.", e.type); - String detail = "Existing command: bye, list, mark, unmark, todo, deadline, event"; - Ui.printCommandError(desc, detail); - } } diff --git a/src/main/java/nuke/command/CommandDeadline.java b/src/main/java/nuke/command/CommandDeadline.java index 9b51d1df9..043670197 100644 --- a/src/main/java/nuke/command/CommandDeadline.java +++ b/src/main/java/nuke/command/CommandDeadline.java @@ -2,7 +2,6 @@ import nuke.command.exception.InvalidCommandArgumentException; import nuke.Nuke; -import nuke.Parser; public class CommandDeadline extends Command { public String name; @@ -12,15 +11,15 @@ public class CommandDeadline extends Command { public void applyArguments(String args) throws InvalidCommandArgumentException { if (args.isEmpty()) { throw new InvalidCommandArgumentException(ERROR_MSG_NO_ARGS); - } else if (Parser.isNotContainingExactOneLabel(args, "/by")) { + } else if (CommandParser.isNotContainingExactOneLabel(args, "/by")) { throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_BY); - } else if (Parser.matches(args, "/by(.*)")) { + } else if (CommandParser.matches(args, "/by(.*)")) { throw new InvalidCommandArgumentException(ERROR_MSG_NAME_EMPTY); - } else if (Parser.matches(args, "(.+)\\s/by")) { + } else if (CommandParser.matches(args, "(.+)\\s/by")) { throw new InvalidCommandArgumentException(ERROR_MSG_BY_EMPTY); } - String[] parsedArgs = Parser.parseArguments(args, "(.+)\\s/by\\s(.+)"); + String[] parsedArgs = CommandParser.parseArguments(args, "(.+)\\s/by\\s(.+)"); checkForbiddenCharacters(parsedArgs); name = parsedArgs[0]; by = parsedArgs[1]; diff --git a/src/main/java/nuke/command/CommandEvent.java b/src/main/java/nuke/command/CommandEvent.java index 06999ddb0..5bce02254 100644 --- a/src/main/java/nuke/command/CommandEvent.java +++ b/src/main/java/nuke/command/CommandEvent.java @@ -2,7 +2,6 @@ import nuke.command.exception.InvalidCommandArgumentException; import nuke.Nuke; -import nuke.Parser; public class CommandEvent extends Command { public String name; @@ -13,19 +12,19 @@ public class CommandEvent extends Command { public void applyArguments(String args) throws InvalidCommandArgumentException { if (args.isEmpty()) { throw new InvalidCommandArgumentException(ERROR_MSG_NO_ARGS); - } else if (Parser.isNotContainingExactOneLabel(args, "/from")) { + } else if (CommandParser.isNotContainingExactOneLabel(args, "/from")) { throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_FROM_TO); - } else if (Parser.isNotContainingExactOneLabel(args, "/to")) { + } else if (CommandParser.isNotContainingExactOneLabel(args, "/to")) { throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_FROM_TO); - } else if (Parser.matches(args, "/from(.*)")) { + } else if (CommandParser.matches(args, "/from(.*)")) { throw new InvalidCommandArgumentException(ERROR_MSG_NAME_EMPTY); - } else if (Parser.matches(args, "(.+)\\s/from\\s/to(.*)")) { + } else if (CommandParser.matches(args, "(.+)\\s/from\\s/to(.*)")) { throw new InvalidCommandArgumentException(ERROR_MSG_FROM_EMPTY); - } else if (Parser.matches(args, "(.+)\\s/from\\s(.+)\\s/to")) { + } else if (CommandParser.matches(args, "(.+)\\s/from\\s(.+)\\s/to")) { throw new InvalidCommandArgumentException(ERROR_MSG_TO_EMPTY); } - String[] parsedArgs = Parser.parseArguments(args, "(.+)\\s/from\\s(.+)\\s/to\\s(.+)"); + String[] parsedArgs = CommandParser.parseArguments(args, "(.+)\\s/from\\s(.+)\\s/to\\s(.+)"); checkForbiddenCharacters(parsedArgs); name = parsedArgs[0]; from = parsedArgs[1]; diff --git a/src/main/java/nuke/command/CommandMark.java b/src/main/java/nuke/command/CommandMark.java index d4fc8ba7f..c58756f7b 100644 --- a/src/main/java/nuke/command/CommandMark.java +++ b/src/main/java/nuke/command/CommandMark.java @@ -2,14 +2,13 @@ import nuke.command.exception.InvalidCommandArgumentException; import nuke.Nuke; -import nuke.Parser; public class CommandMark extends Command { private int index; @Override public void applyArguments(String args) throws InvalidCommandArgumentException { - if (Parser.isNotOneWord(args)) { + if (CommandParser.isNotOneWord(args)) { throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_ARGS); } // Input index starts with 1, logical index starts with 0. diff --git a/src/main/java/nuke/Parser.java b/src/main/java/nuke/command/CommandParser.java similarity index 88% rename from src/main/java/nuke/Parser.java rename to src/main/java/nuke/command/CommandParser.java index e99c10361..8caf4e3f1 100644 --- a/src/main/java/nuke/Parser.java +++ b/src/main/java/nuke/command/CommandParser.java @@ -1,5 +1,6 @@ -package nuke; +package nuke.command; +import nuke.Ui; import nuke.command.*; import nuke.command.exception.InvalidCommandArgumentException; import nuke.command.exception.InvalidCommandTypeException; @@ -8,7 +9,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public class Parser { +public class CommandParser { public static Command parseCommand(String commandLine) throws InvalidCommandTypeException, InvalidCommandArgumentException { // Get command type and arguments. @@ -20,7 +21,7 @@ public static Command parseCommand(String commandLine) try { command = getBlankCommand(type); } catch (InvalidCommandTypeException e) { - Command.handleTypeError(e); + handleTypeError(e); throw e; } // Apply arguments on command. @@ -73,6 +74,12 @@ private static String getCommandArguments(String commandLine, String type) { return commandLine.substring(type.length()).strip(); } + public static void handleTypeError(InvalidCommandTypeException e) { + String desc = String.format("There is no command called '%s'.", e.type); + String detail = "Existing command: bye, list, mark, unmark, todo, deadline, event"; + Ui.printCommandError(desc, detail); + } + public static boolean isNotOneWord(String str) { if (str.isEmpty()) { return true; diff --git a/src/main/java/nuke/command/CommandUnmark.java b/src/main/java/nuke/command/CommandUnmark.java index e2e554f09..fa7c6858d 100644 --- a/src/main/java/nuke/command/CommandUnmark.java +++ b/src/main/java/nuke/command/CommandUnmark.java @@ -2,14 +2,13 @@ import nuke.command.exception.InvalidCommandArgumentException; import nuke.Nuke; -import nuke.Parser; public class CommandUnmark extends Command { private int index; @Override public void applyArguments(String args) throws InvalidCommandArgumentException { - if (Parser.isNotOneWord(args)) { + if (CommandParser.isNotOneWord(args)) { throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_ARGS); } // Input index starts with 1, logical index starts with 0. From a9b7f1df26948d7e46db9e378f00890e39e93e99 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 16 Sep 2023 13:03:46 +0800 Subject: [PATCH 26/52] Complete Level-7 --- .gitignore | 2 + src/main/java/nuke/Nuke.java | 59 ++++++++++++++- src/main/java/nuke/Ui.java | 23 ++++++ src/main/java/nuke/command/CommandParser.java | 1 - src/main/java/nuke/savefile/SaveManager.java | 73 +++++++++++++++++++ .../savefile/exception/SaveFileException.java | 6 ++ .../exception/TaskFileMoveException.java | 9 +++ .../savefile/exception/TaskLoadException.java | 9 +++ .../exception/TaskParseException.java | 4 + .../savefile/exception/TaskSaveException.java | 4 + src/main/java/nuke/task/Deadline.java | 15 +++- src/main/java/nuke/task/Event.java | 14 +++- src/main/java/nuke/task/Task.java | 9 ++- src/main/java/nuke/task/TaskParser.java | 39 ++++++++++ src/main/java/nuke/task/Todo.java | 6 +- text-ui-test/runtest.bat | 2 + 16 files changed, 265 insertions(+), 10 deletions(-) create mode 100644 src/main/java/nuke/savefile/SaveManager.java create mode 100644 src/main/java/nuke/savefile/exception/SaveFileException.java create mode 100644 src/main/java/nuke/savefile/exception/TaskFileMoveException.java create mode 100644 src/main/java/nuke/savefile/exception/TaskLoadException.java create mode 100644 src/main/java/nuke/savefile/exception/TaskParseException.java create mode 100644 src/main/java/nuke/savefile/exception/TaskSaveException.java create mode 100644 src/main/java/nuke/task/TaskParser.java diff --git a/.gitignore b/.gitignore index 2873e189e..6690f772d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ bin/ /text-ui-test/ACTUAL.TXT text-ui-test/EXPECTED-UNIX.TXT +/data/ +/text-ui-test/data/ diff --git a/src/main/java/nuke/Nuke.java b/src/main/java/nuke/Nuke.java index 18e723d35..2158ef925 100644 --- a/src/main/java/nuke/Nuke.java +++ b/src/main/java/nuke/Nuke.java @@ -1,8 +1,13 @@ package nuke; import nuke.command.Command; +import nuke.command.CommandParser; import nuke.command.exception.InvalidCommandArgumentException; import nuke.command.exception.InvalidCommandTypeException; +import nuke.savefile.SaveManager; +import nuke.savefile.exception.TaskFileMoveException; +import nuke.savefile.exception.TaskLoadException; +import nuke.savefile.exception.TaskSaveException; import nuke.task.Deadline; import nuke.task.Event; import nuke.task.Task; @@ -20,23 +25,64 @@ public static void main(String[] args) { Ui.printWelcome(); + // Fail to run if + // 1. loading tasks from the file fails and + // 2. backing up the file fails and + // 3. user does not ignore the error + if (!loadTasksFromStorage(USER_IN)) { + return; + } + // Loop for user input while (isRunning) { String input = USER_IN.nextLine(); runCommand(input); Ui.printBlankLine(); } + + saveTasksToStorage(USER_IN); } private static void runCommand(String commandLine) { try { - Command command = Parser.parseCommand(commandLine); + Command command = CommandParser.parseCommand(commandLine); command.run(); } catch (InvalidCommandTypeException | InvalidCommandArgumentException ignored) { // Thrown by Parse.parseCommand() to prevent command.run(). } } + private static boolean loadTasksFromStorage(final Scanner USER_IN) { + ArrayList loadedTasks; + try { + loadedTasks = SaveManager.loadTasksFromStorage(); + tasks.addAll(loadedTasks); + } catch (TaskLoadException e) { + Ui.printTaskLoadError(e.backupFilePath); + } catch (TaskFileMoveException e) { + Ui.printTaskFileMoveError(e.filePath); + + String input = USER_IN.nextLine(); + if (!input.equalsIgnoreCase("ignore")) { + return false; + } + } + return true; + } + + private static void saveTasksToStorage(final Scanner USER_IN) { + try { + SaveManager.saveTasksToStorage(); + } catch (TaskSaveException e) { + Ui.printTaskSaveError(getTasks()); + boolean isQuitting = false; + while (!isQuitting) { + String input = USER_IN.nextLine(); + isQuitting = !input.isEmpty(); + } + } + } + public static void quit() { isRunning = false; Ui.printBye(); @@ -48,8 +94,7 @@ public static void addTask(Task task) { } public static void listTask() { - String[] taskList = tasks.stream().map(Task::toString).toArray(String[]::new); - Ui.printListOfTasks(taskList); + Ui.printListOfTasks(getTasks()); } public static void markTask(int idx) { @@ -79,4 +124,12 @@ public static void addEvent(String name, String from, String to) { public static int getNumberOfTasks() { return tasks.size(); } + + public static String[] getTasks() { + return tasks.stream().map(Task::toString).toArray(String[]::new); + } + + public static String[] getFormattedTasks() { + return tasks.stream().map(Task::formatData).toArray(String[]::new); + } } diff --git a/src/main/java/nuke/Ui.java b/src/main/java/nuke/Ui.java index 49c7ef21f..c0060b187 100644 --- a/src/main/java/nuke/Ui.java +++ b/src/main/java/nuke/Ui.java @@ -61,4 +61,27 @@ public static void printCommandError(String description, String detail) { System.out.println("[@] Wrong input; " + description); System.out.println("[@] " + detail); } + + public static void printTaskLoadError(String backupFilePath) { + System.out.println("[@] Error occurred while loading the tasks!"); + System.out.println("[@] I backed up your save file."); + System.out.println("[@] Path: " + backupFilePath); + System.out.println(); + } + public static void printTaskFileMoveError(String filePath) { + System.out.println("[@] Error occurred while loading the tasks!"); + System.out.println("[@] I tried to back up your save file, but it failed as well."); + System.out.println("[@] You can back up your save file manually."); + System.out.println("[@] Path: " + filePath); + System.out.println(); + System.out.println("[@] Ignore and continue to run by entering 'ignore'."); + } + public static void printTaskSaveError(String[] tasks) { + System.out.println("[@] Error occurred while saving the tasks!"); + System.out.println("[@] I will show all the tasks you have added."); + printListOfTasks(tasks); + System.out.println(); + System.out.println("[@] Please back up your save file manually."); + System.out.println("[@] Continue to quit by entering non-empty input."); + } } diff --git a/src/main/java/nuke/command/CommandParser.java b/src/main/java/nuke/command/CommandParser.java index 8caf4e3f1..bdae2b1e8 100644 --- a/src/main/java/nuke/command/CommandParser.java +++ b/src/main/java/nuke/command/CommandParser.java @@ -1,7 +1,6 @@ package nuke.command; import nuke.Ui; -import nuke.command.*; import nuke.command.exception.InvalidCommandArgumentException; import nuke.command.exception.InvalidCommandTypeException; diff --git a/src/main/java/nuke/savefile/SaveManager.java b/src/main/java/nuke/savefile/SaveManager.java new file mode 100644 index 000000000..c9bbed7ac --- /dev/null +++ b/src/main/java/nuke/savefile/SaveManager.java @@ -0,0 +1,73 @@ +package nuke.savefile; + +import nuke.Nuke; +import nuke.savefile.exception.TaskFileMoveException; +import nuke.savefile.exception.TaskLoadException; +import nuke.savefile.exception.TaskParseException; +import nuke.savefile.exception.TaskSaveException; +import nuke.task.Task; +import nuke.task.TaskParser; + +import java.io.*; +import java.nio.file.*; +import java.util.ArrayList; +import java.util.Scanner; + +public class SaveManager { + private static final String DIR_DATA = "data"; + private static final String FILENAME_TASKS = "nuke.txt"; + private static final String FILENAME_TASKS_BACKUP = "nuke_old.txt"; + + public static ArrayList loadTasksFromStorage() + throws TaskLoadException, TaskFileMoveException { + ArrayList loadedTasks = new ArrayList<>(); + + Path currentRelativePath = Paths.get(""); + Path currentDir = currentRelativePath.toAbsolutePath(); + Path filePath = currentDir.resolve(DIR_DATA).resolve(FILENAME_TASKS); + + File file = new File(filePath.toString()); + if (!file.exists()) { + return loadedTasks; + } + try { + Scanner scanner = new Scanner(file); + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + Task task = TaskParser.parseTask(line); + loadedTasks.add(task); + } + } catch (IOException | TaskParseException e) { + Path oldFilePath = currentDir.resolve(DIR_DATA).resolve(FILENAME_TASKS_BACKUP); + try { + Files.move(filePath, oldFilePath, StandardCopyOption.REPLACE_EXISTING); + throw new TaskLoadException(FILENAME_TASKS_BACKUP); + } catch (IOException ex) { + throw new TaskFileMoveException(FILENAME_TASKS); + } + } + return loadedTasks; + } + + public static void saveTasksToStorage() throws TaskSaveException { + Path currentRelativePath = Paths.get(""); + Path currentDir = currentRelativePath.toAbsolutePath(); + Path dirPath = currentDir.resolve(DIR_DATA); + Path filePath = currentDir.resolve(DIR_DATA).resolve(FILENAME_TASKS); + + File dir = new File(dirPath.toString()); + File file = new File(filePath.toString()); + try { + dir.mkdir(); + file.createNewFile(); + try (FileWriter writer = new FileWriter(file)) { + for (String formattedTask: Nuke.getFormattedTasks()) { + writer.write(formattedTask); + writer.write('\n'); + } + } + } catch (IOException e) { + throw new TaskSaveException(); + } + } +} diff --git a/src/main/java/nuke/savefile/exception/SaveFileException.java b/src/main/java/nuke/savefile/exception/SaveFileException.java new file mode 100644 index 000000000..b4221a80f --- /dev/null +++ b/src/main/java/nuke/savefile/exception/SaveFileException.java @@ -0,0 +1,6 @@ +package nuke.savefile.exception; + +import nuke.NukeException; + +public class SaveFileException extends NukeException { +} diff --git a/src/main/java/nuke/savefile/exception/TaskFileMoveException.java b/src/main/java/nuke/savefile/exception/TaskFileMoveException.java new file mode 100644 index 000000000..c28ac3959 --- /dev/null +++ b/src/main/java/nuke/savefile/exception/TaskFileMoveException.java @@ -0,0 +1,9 @@ +package nuke.savefile.exception; + +public class TaskFileMoveException extends SaveFileException { + public String filePath; + + public TaskFileMoveException(String filePath) { + this.filePath = filePath; + } +} diff --git a/src/main/java/nuke/savefile/exception/TaskLoadException.java b/src/main/java/nuke/savefile/exception/TaskLoadException.java new file mode 100644 index 000000000..6d61de01f --- /dev/null +++ b/src/main/java/nuke/savefile/exception/TaskLoadException.java @@ -0,0 +1,9 @@ +package nuke.savefile.exception; + +public class TaskLoadException extends SaveFileException { + public String backupFilePath; + + public TaskLoadException(String backupFilePath) { + this.backupFilePath = backupFilePath; + } +} diff --git a/src/main/java/nuke/savefile/exception/TaskParseException.java b/src/main/java/nuke/savefile/exception/TaskParseException.java new file mode 100644 index 000000000..4edc69d8e --- /dev/null +++ b/src/main/java/nuke/savefile/exception/TaskParseException.java @@ -0,0 +1,4 @@ +package nuke.savefile.exception; + +public class TaskParseException extends SaveFileException { +} diff --git a/src/main/java/nuke/savefile/exception/TaskSaveException.java b/src/main/java/nuke/savefile/exception/TaskSaveException.java new file mode 100644 index 000000000..780d64df7 --- /dev/null +++ b/src/main/java/nuke/savefile/exception/TaskSaveException.java @@ -0,0 +1,4 @@ +package nuke.savefile.exception; + +public class TaskSaveException extends SaveFileException { +} diff --git a/src/main/java/nuke/task/Deadline.java b/src/main/java/nuke/task/Deadline.java index ac6d63b46..4f72b12f2 100644 --- a/src/main/java/nuke/task/Deadline.java +++ b/src/main/java/nuke/task/Deadline.java @@ -16,9 +16,20 @@ public void setBy(String by) { this.by = by; } + @Override + public String getType() { + return TYPE; + } + @Override public String toString() { - return String.format("[D]%s (by: %s)", - super.toString(), getBy()); + return String.format("%s (by: %s)", super.toString(), getBy()); } + + @Override + public String formatData() { + return String.format("%s / %s", super.formatData(), getBy()); + } + + public static final String TYPE = "D"; } diff --git a/src/main/java/nuke/task/Event.java b/src/main/java/nuke/task/Event.java index 9a712343e..ef2eb2524 100644 --- a/src/main/java/nuke/task/Event.java +++ b/src/main/java/nuke/task/Event.java @@ -26,9 +26,21 @@ public void setTo(String to) { this.to = to; } + @Override + public String getType() { + return TYPE; + } + @Override public String toString() { - return String.format("[E]%s (from: %s to: %s)", + return String.format("%s (from: %s to: %s)", super.toString(), getFrom(), getTo()); } + + @Override + public String formatData() { + return String.format("%s / %s / %s", super.formatData(), getFrom(), getTo()); + } + + public static final String TYPE = "E"; } diff --git a/src/main/java/nuke/task/Task.java b/src/main/java/nuke/task/Task.java index 876199868..d5f7df8cb 100644 --- a/src/main/java/nuke/task/Task.java +++ b/src/main/java/nuke/task/Task.java @@ -25,9 +25,16 @@ public void setDone(boolean done) { this.isDone = done; } + public abstract String getType(); + @Override public String toString() { String mark = isDone()? "X" : " "; - return String.format("[%s] %s", mark, getName()); + return String.format("[%s][%s] %s", getType(), mark, getName()); + } + + public String formatData() { + String mark = isDone()? "1" : "0"; + return String.format("%s / %s / %s", getType(), mark, getName()); } } diff --git a/src/main/java/nuke/task/TaskParser.java b/src/main/java/nuke/task/TaskParser.java new file mode 100644 index 000000000..004f9c4c8 --- /dev/null +++ b/src/main/java/nuke/task/TaskParser.java @@ -0,0 +1,39 @@ +package nuke.task; + +import nuke.savefile.exception.TaskParseException; + +public class TaskParser { + + public static Task parseTask(String line) throws TaskParseException { + Task task; + String[] words = line.split(" / "); + String type = words[0]; + boolean mark; + switch (words[1]) { + case "1": + mark = true; + break; + case "0": + mark = false; + break; + default: + throw new TaskParseException(); + } + switch (type) { + case Todo.TYPE: + task = new Todo(words[2]); + break; + case Deadline.TYPE: + task = new Deadline(words[2], words[3]); + break; + case Event.TYPE: + task = new Event(words[2], words[3], words[4]); + break; + default: + throw new TaskParseException(); + } + task.setDone(mark); + + return task; + } +} diff --git a/src/main/java/nuke/task/Todo.java b/src/main/java/nuke/task/Todo.java index a73694a89..f641ae5ab 100644 --- a/src/main/java/nuke/task/Todo.java +++ b/src/main/java/nuke/task/Todo.java @@ -7,7 +7,9 @@ public Todo(String name) { } @Override - public String toString() { - return "[T]" + super.toString(); + public String getType() { + return TYPE; } + + public static final String TYPE = "T"; } diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index 50e2c63fe..6fa1e2d5a 100644 --- a/text-ui-test/runtest.bat +++ b/text-ui-test/runtest.bat @@ -6,6 +6,8 @@ if not exist ..\bin mkdir ..\bin REM delete output from previous run if exist ACTUAL.TXT del ACTUAL.TXT +if exist data\nuke.txt del data\nuke.txt + REM compile the code into the bin folder javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\nuke\*.java javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\nuke\command\*.java From 8ac69e1056ffe09cd84908c2f0f6fdb8e5d198e1 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 16 Sep 2023 13:35:37 +0800 Subject: [PATCH 27/52] Fix exception handlers --- src/main/java/nuke/Nuke.java | 8 +++++--- src/main/java/nuke/Ui.java | 8 +++++++- src/main/java/nuke/savefile/SaveManager.java | 9 +++++---- .../nuke/savefile/exception/TaskFileCopyException.java | 9 +++++++++ .../nuke/savefile/exception/TaskFileMoveException.java | 9 --------- src/main/java/nuke/task/TaskParser.java | 3 +++ 6 files changed, 29 insertions(+), 17 deletions(-) create mode 100644 src/main/java/nuke/savefile/exception/TaskFileCopyException.java delete mode 100644 src/main/java/nuke/savefile/exception/TaskFileMoveException.java diff --git a/src/main/java/nuke/Nuke.java b/src/main/java/nuke/Nuke.java index 2158ef925..8949bf9c3 100644 --- a/src/main/java/nuke/Nuke.java +++ b/src/main/java/nuke/Nuke.java @@ -5,7 +5,7 @@ import nuke.command.exception.InvalidCommandArgumentException; import nuke.command.exception.InvalidCommandTypeException; import nuke.savefile.SaveManager; -import nuke.savefile.exception.TaskFileMoveException; +import nuke.savefile.exception.TaskFileCopyException; import nuke.savefile.exception.TaskLoadException; import nuke.savefile.exception.TaskSaveException; import nuke.task.Deadline; @@ -33,6 +33,8 @@ public static void main(String[] args) { return; } + Ui.printWelcomeAfter(); + // Loop for user input while (isRunning) { String input = USER_IN.nextLine(); @@ -59,8 +61,8 @@ private static boolean loadTasksFromStorage(final Scanner USER_IN) { tasks.addAll(loadedTasks); } catch (TaskLoadException e) { Ui.printTaskLoadError(e.backupFilePath); - } catch (TaskFileMoveException e) { - Ui.printTaskFileMoveError(e.filePath); + } catch (TaskFileCopyException e) { + Ui.printTaskFileCopyError(e.filePath); String input = USER_IN.nextLine(); if (!input.equalsIgnoreCase("ignore")) { diff --git a/src/main/java/nuke/Ui.java b/src/main/java/nuke/Ui.java index c0060b187..60e22d799 100644 --- a/src/main/java/nuke/Ui.java +++ b/src/main/java/nuke/Ui.java @@ -18,6 +18,9 @@ public static void printWelcome() { System.out.println(LOGO); System.out.println(); System.out.println("[@] Hello! I'm Nuke."); + } + + public static void printWelcomeAfter() { System.out.println("[@] What can I do for you?"); System.out.println(); } @@ -63,18 +66,21 @@ public static void printCommandError(String description, String detail) { } public static void printTaskLoadError(String backupFilePath) { + System.out.println(); System.out.println("[@] Error occurred while loading the tasks!"); System.out.println("[@] I backed up your save file."); System.out.println("[@] Path: " + backupFilePath); System.out.println(); } - public static void printTaskFileMoveError(String filePath) { + public static void printTaskFileCopyError(String filePath) { + System.out.println(); System.out.println("[@] Error occurred while loading the tasks!"); System.out.println("[@] I tried to back up your save file, but it failed as well."); System.out.println("[@] You can back up your save file manually."); System.out.println("[@] Path: " + filePath); System.out.println(); System.out.println("[@] Ignore and continue to run by entering 'ignore'."); + System.out.println(); } public static void printTaskSaveError(String[] tasks) { System.out.println("[@] Error occurred while saving the tasks!"); diff --git a/src/main/java/nuke/savefile/SaveManager.java b/src/main/java/nuke/savefile/SaveManager.java index c9bbed7ac..12dbaa638 100644 --- a/src/main/java/nuke/savefile/SaveManager.java +++ b/src/main/java/nuke/savefile/SaveManager.java @@ -1,7 +1,7 @@ package nuke.savefile; import nuke.Nuke; -import nuke.savefile.exception.TaskFileMoveException; +import nuke.savefile.exception.TaskFileCopyException; import nuke.savefile.exception.TaskLoadException; import nuke.savefile.exception.TaskParseException; import nuke.savefile.exception.TaskSaveException; @@ -19,7 +19,7 @@ public class SaveManager { private static final String FILENAME_TASKS_BACKUP = "nuke_old.txt"; public static ArrayList loadTasksFromStorage() - throws TaskLoadException, TaskFileMoveException { + throws TaskLoadException, TaskFileCopyException { ArrayList loadedTasks = new ArrayList<>(); Path currentRelativePath = Paths.get(""); @@ -40,10 +40,10 @@ public static ArrayList loadTasksFromStorage() } catch (IOException | TaskParseException e) { Path oldFilePath = currentDir.resolve(DIR_DATA).resolve(FILENAME_TASKS_BACKUP); try { - Files.move(filePath, oldFilePath, StandardCopyOption.REPLACE_EXISTING); + Files.copy(filePath, oldFilePath, StandardCopyOption.REPLACE_EXISTING); throw new TaskLoadException(FILENAME_TASKS_BACKUP); } catch (IOException ex) { - throw new TaskFileMoveException(FILENAME_TASKS); + throw new TaskFileCopyException(FILENAME_TASKS); } } return loadedTasks; @@ -66,6 +66,7 @@ public static void saveTasksToStorage() throws TaskSaveException { writer.write('\n'); } } + throw new IOException(); } catch (IOException e) { throw new TaskSaveException(); } diff --git a/src/main/java/nuke/savefile/exception/TaskFileCopyException.java b/src/main/java/nuke/savefile/exception/TaskFileCopyException.java new file mode 100644 index 000000000..7fd90259d --- /dev/null +++ b/src/main/java/nuke/savefile/exception/TaskFileCopyException.java @@ -0,0 +1,9 @@ +package nuke.savefile.exception; + +public class TaskFileCopyException extends SaveFileException { + public String filePath; + + public TaskFileCopyException(String filePath) { + this.filePath = filePath; + } +} diff --git a/src/main/java/nuke/savefile/exception/TaskFileMoveException.java b/src/main/java/nuke/savefile/exception/TaskFileMoveException.java deleted file mode 100644 index c28ac3959..000000000 --- a/src/main/java/nuke/savefile/exception/TaskFileMoveException.java +++ /dev/null @@ -1,9 +0,0 @@ -package nuke.savefile.exception; - -public class TaskFileMoveException extends SaveFileException { - public String filePath; - - public TaskFileMoveException(String filePath) { - this.filePath = filePath; - } -} diff --git a/src/main/java/nuke/task/TaskParser.java b/src/main/java/nuke/task/TaskParser.java index 004f9c4c8..213670d96 100644 --- a/src/main/java/nuke/task/TaskParser.java +++ b/src/main/java/nuke/task/TaskParser.java @@ -7,6 +7,9 @@ public class TaskParser { public static Task parseTask(String line) throws TaskParseException { Task task; String[] words = line.split(" / "); + if (words.length < 3) { + throw new TaskParseException(); + } String type = words[0]; boolean mark; switch (words[1]) { From 2c1d0db4fc7e69624a00821e53987791cce04bd5 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 16 Sep 2023 13:51:36 +0800 Subject: [PATCH 28/52] Fix error by merge --- src/main/java/nuke/command/CommandDelete.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/nuke/command/CommandDelete.java b/src/main/java/nuke/command/CommandDelete.java index 3fa05bbf6..e9e7cac6b 100644 --- a/src/main/java/nuke/command/CommandDelete.java +++ b/src/main/java/nuke/command/CommandDelete.java @@ -1,7 +1,6 @@ package nuke.command; import nuke.Nuke; -import nuke.Parser; import nuke.command.exception.InvalidCommandArgumentException; public class CommandDelete extends Command { @@ -9,7 +8,7 @@ public class CommandDelete extends Command { @Override public void applyArguments(String args) throws InvalidCommandArgumentException { - if (Parser.isNotOneWord(args)) { + if (CommandParser.isNotOneWord(args)) { throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_ARGS); } // Input index starts with 1, logical index starts with 0. From 1e93e13e4e1a9810b2a37a4e84007b0ca01a4d1a Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 16 Sep 2023 13:56:15 +0800 Subject: [PATCH 29/52] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6690f772d..7ac3b119e 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ bin/ text-ui-test/EXPECTED-UNIX.TXT /data/ /text-ui-test/data/ +src/main/java/META-INF/MANIFEST.MF From d36601c1e3f36548d50f4bc38dd325cf83a9f542 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 16 Sep 2023 14:03:29 +0800 Subject: [PATCH 30/52] Update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7ac3b119e..d686beb48 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,4 @@ bin/ text-ui-test/EXPECTED-UNIX.TXT /data/ /text-ui-test/data/ -src/main/java/META-INF/MANIFEST.MF +/src/main/java/META-INF/ From c8e2d6d836799cb4630bdf33fa284237481ea353 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Tue, 19 Sep 2023 15:12:45 +0800 Subject: [PATCH 31/52] Rename classes and packages SaveFile -> Storage CommandXXX -> XXXCommand --- src/main/java/nuke/Nuke.java | 12 ++++++------ .../command/{CommandBye.java => ByeCommand.java} | 2 +- src/main/java/nuke/command/CommandParser.java | 16 ++++++++-------- ...CommandDeadline.java => DeadlineCommand.java} | 2 +- .../{CommandDelete.java => DeleteCommand.java} | 2 +- .../{CommandEvent.java => EventCommand.java} | 2 +- .../{CommandList.java => ListCommand.java} | 2 +- .../{CommandMark.java => MarkCommand.java} | 2 +- .../{CommandTodo.java => TodoCommand.java} | 2 +- .../{CommandUnmark.java => UnmarkCommand.java} | 2 +- .../savefile/exception/SaveFileException.java | 6 ------ .../savefile/exception/TaskParseException.java | 4 ---- .../savefile/exception/TaskSaveException.java | 4 ---- .../SaveManager.java => storage/Storage.java} | 16 ++++++++-------- .../nuke/storage/exception/StorageException.java | 6 ++++++ .../exception/TaskFileCopyException.java | 4 ++-- .../exception/TaskLoadException.java | 4 ++-- .../storage/exception/TaskParseException.java | 4 ++++ .../storage/exception/TaskSaveException.java | 4 ++++ src/main/java/nuke/task/TaskParser.java | 2 +- 20 files changed, 49 insertions(+), 49 deletions(-) rename src/main/java/nuke/command/{CommandBye.java => ByeCommand.java} (93%) rename src/main/java/nuke/command/{CommandDeadline.java => DeadlineCommand.java} (97%) rename src/main/java/nuke/command/{CommandDelete.java => DeleteCommand.java} (96%) rename src/main/java/nuke/command/{CommandEvent.java => EventCommand.java} (98%) rename src/main/java/nuke/command/{CommandList.java => ListCommand.java} (93%) rename src/main/java/nuke/command/{CommandMark.java => MarkCommand.java} (97%) rename src/main/java/nuke/command/{CommandTodo.java => TodoCommand.java} (94%) rename src/main/java/nuke/command/{CommandUnmark.java => UnmarkCommand.java} (96%) delete mode 100644 src/main/java/nuke/savefile/exception/SaveFileException.java delete mode 100644 src/main/java/nuke/savefile/exception/TaskParseException.java delete mode 100644 src/main/java/nuke/savefile/exception/TaskSaveException.java rename src/main/java/nuke/{savefile/SaveManager.java => storage/Storage.java} (85%) create mode 100644 src/main/java/nuke/storage/exception/StorageException.java rename src/main/java/nuke/{savefile => storage}/exception/TaskFileCopyException.java (56%) rename src/main/java/nuke/{savefile => storage}/exception/TaskLoadException.java (61%) create mode 100644 src/main/java/nuke/storage/exception/TaskParseException.java create mode 100644 src/main/java/nuke/storage/exception/TaskSaveException.java diff --git a/src/main/java/nuke/Nuke.java b/src/main/java/nuke/Nuke.java index 32d5942e1..1ad8aa7e9 100644 --- a/src/main/java/nuke/Nuke.java +++ b/src/main/java/nuke/Nuke.java @@ -4,10 +4,10 @@ import nuke.command.CommandParser; import nuke.command.exception.InvalidCommandArgumentException; import nuke.command.exception.InvalidCommandTypeException; -import nuke.savefile.SaveManager; -import nuke.savefile.exception.TaskFileCopyException; -import nuke.savefile.exception.TaskLoadException; -import nuke.savefile.exception.TaskSaveException; +import nuke.storage.Storage; +import nuke.storage.exception.TaskFileCopyException; +import nuke.storage.exception.TaskLoadException; +import nuke.storage.exception.TaskSaveException; import nuke.task.Deadline; import nuke.task.Event; import nuke.task.Task; @@ -57,7 +57,7 @@ private static void runCommand(String commandLine) { private static boolean loadTasksFromStorage(final Scanner USER_IN) { ArrayList loadedTasks; try { - loadedTasks = SaveManager.loadTasksFromStorage(); + loadedTasks = Storage.loadTasks(); tasks.addAll(loadedTasks); } catch (TaskLoadException e) { Ui.printTaskLoadError(e.backupFilePath); @@ -74,7 +74,7 @@ private static boolean loadTasksFromStorage(final Scanner USER_IN) { private static void saveTasksToStorage(final Scanner USER_IN) { try { - SaveManager.saveTasksToStorage(); + Storage.saveTasks(); } catch (TaskSaveException e) { Ui.printTaskSaveError(getTasks()); boolean isQuitting = false; diff --git a/src/main/java/nuke/command/CommandBye.java b/src/main/java/nuke/command/ByeCommand.java similarity index 93% rename from src/main/java/nuke/command/CommandBye.java rename to src/main/java/nuke/command/ByeCommand.java index 7ae1c1616..be6a2b3ab 100644 --- a/src/main/java/nuke/command/CommandBye.java +++ b/src/main/java/nuke/command/ByeCommand.java @@ -3,7 +3,7 @@ import nuke.command.exception.InvalidCommandArgumentException; import nuke.Nuke; -public class CommandBye extends Command { +public class ByeCommand extends Command { @Override public void applyArguments(String args) throws InvalidCommandArgumentException { diff --git a/src/main/java/nuke/command/CommandParser.java b/src/main/java/nuke/command/CommandParser.java index aa6f0a070..439045c1d 100644 --- a/src/main/java/nuke/command/CommandParser.java +++ b/src/main/java/nuke/command/CommandParser.java @@ -39,28 +39,28 @@ private static Command getBlankCommand(String type) Command command; switch (type) { case "bye": - command = new CommandBye(); + command = new ByeCommand(); break; case "list": - command = new CommandList(); + command = new ListCommand(); break; case "mark": - command = new CommandMark(); + command = new MarkCommand(); break; case "unmark": - command = new CommandUnmark(); + command = new UnmarkCommand(); break; case "todo": - command = new CommandTodo(); + command = new TodoCommand(); break; case "deadline": - command = new CommandDeadline(); + command = new DeadlineCommand(); break; case "event": - command = new CommandEvent(); + command = new EventCommand(); break; case "delete": - command = new CommandDelete(); + command = new DeleteCommand(); break; default: throw new InvalidCommandTypeException(type); diff --git a/src/main/java/nuke/command/CommandDeadline.java b/src/main/java/nuke/command/DeadlineCommand.java similarity index 97% rename from src/main/java/nuke/command/CommandDeadline.java rename to src/main/java/nuke/command/DeadlineCommand.java index 043670197..d76ae8004 100644 --- a/src/main/java/nuke/command/CommandDeadline.java +++ b/src/main/java/nuke/command/DeadlineCommand.java @@ -3,7 +3,7 @@ import nuke.command.exception.InvalidCommandArgumentException; import nuke.Nuke; -public class CommandDeadline extends Command { +public class DeadlineCommand extends Command { public String name; public String by; diff --git a/src/main/java/nuke/command/CommandDelete.java b/src/main/java/nuke/command/DeleteCommand.java similarity index 96% rename from src/main/java/nuke/command/CommandDelete.java rename to src/main/java/nuke/command/DeleteCommand.java index e9e7cac6b..0c61dd3fa 100644 --- a/src/main/java/nuke/command/CommandDelete.java +++ b/src/main/java/nuke/command/DeleteCommand.java @@ -3,7 +3,7 @@ import nuke.Nuke; import nuke.command.exception.InvalidCommandArgumentException; -public class CommandDelete extends Command { +public class DeleteCommand extends Command { private int index; @Override diff --git a/src/main/java/nuke/command/CommandEvent.java b/src/main/java/nuke/command/EventCommand.java similarity index 98% rename from src/main/java/nuke/command/CommandEvent.java rename to src/main/java/nuke/command/EventCommand.java index 5bce02254..c8cc8f7bb 100644 --- a/src/main/java/nuke/command/CommandEvent.java +++ b/src/main/java/nuke/command/EventCommand.java @@ -3,7 +3,7 @@ import nuke.command.exception.InvalidCommandArgumentException; import nuke.Nuke; -public class CommandEvent extends Command { +public class EventCommand extends Command { public String name; public String from; public String to; diff --git a/src/main/java/nuke/command/CommandList.java b/src/main/java/nuke/command/ListCommand.java similarity index 93% rename from src/main/java/nuke/command/CommandList.java rename to src/main/java/nuke/command/ListCommand.java index 1d8b931a8..ed5104650 100644 --- a/src/main/java/nuke/command/CommandList.java +++ b/src/main/java/nuke/command/ListCommand.java @@ -3,7 +3,7 @@ import nuke.command.exception.InvalidCommandArgumentException; import nuke.Nuke; -public class CommandList extends Command { +public class ListCommand extends Command { @Override public void applyArguments(String args) throws InvalidCommandArgumentException { diff --git a/src/main/java/nuke/command/CommandMark.java b/src/main/java/nuke/command/MarkCommand.java similarity index 97% rename from src/main/java/nuke/command/CommandMark.java rename to src/main/java/nuke/command/MarkCommand.java index c58756f7b..d174b2a48 100644 --- a/src/main/java/nuke/command/CommandMark.java +++ b/src/main/java/nuke/command/MarkCommand.java @@ -3,7 +3,7 @@ import nuke.command.exception.InvalidCommandArgumentException; import nuke.Nuke; -public class CommandMark extends Command { +public class MarkCommand extends Command { private int index; @Override diff --git a/src/main/java/nuke/command/CommandTodo.java b/src/main/java/nuke/command/TodoCommand.java similarity index 94% rename from src/main/java/nuke/command/CommandTodo.java rename to src/main/java/nuke/command/TodoCommand.java index 29fdc882b..9e9974609 100644 --- a/src/main/java/nuke/command/CommandTodo.java +++ b/src/main/java/nuke/command/TodoCommand.java @@ -3,7 +3,7 @@ import nuke.command.exception.InvalidCommandArgumentException; import nuke.Nuke; -public class CommandTodo extends Command { +public class TodoCommand extends Command { public String name; @Override diff --git a/src/main/java/nuke/command/CommandUnmark.java b/src/main/java/nuke/command/UnmarkCommand.java similarity index 96% rename from src/main/java/nuke/command/CommandUnmark.java rename to src/main/java/nuke/command/UnmarkCommand.java index fa7c6858d..e2f86f757 100644 --- a/src/main/java/nuke/command/CommandUnmark.java +++ b/src/main/java/nuke/command/UnmarkCommand.java @@ -3,7 +3,7 @@ import nuke.command.exception.InvalidCommandArgumentException; import nuke.Nuke; -public class CommandUnmark extends Command { +public class UnmarkCommand extends Command { private int index; @Override diff --git a/src/main/java/nuke/savefile/exception/SaveFileException.java b/src/main/java/nuke/savefile/exception/SaveFileException.java deleted file mode 100644 index b4221a80f..000000000 --- a/src/main/java/nuke/savefile/exception/SaveFileException.java +++ /dev/null @@ -1,6 +0,0 @@ -package nuke.savefile.exception; - -import nuke.NukeException; - -public class SaveFileException extends NukeException { -} diff --git a/src/main/java/nuke/savefile/exception/TaskParseException.java b/src/main/java/nuke/savefile/exception/TaskParseException.java deleted file mode 100644 index 4edc69d8e..000000000 --- a/src/main/java/nuke/savefile/exception/TaskParseException.java +++ /dev/null @@ -1,4 +0,0 @@ -package nuke.savefile.exception; - -public class TaskParseException extends SaveFileException { -} diff --git a/src/main/java/nuke/savefile/exception/TaskSaveException.java b/src/main/java/nuke/savefile/exception/TaskSaveException.java deleted file mode 100644 index 780d64df7..000000000 --- a/src/main/java/nuke/savefile/exception/TaskSaveException.java +++ /dev/null @@ -1,4 +0,0 @@ -package nuke.savefile.exception; - -public class TaskSaveException extends SaveFileException { -} diff --git a/src/main/java/nuke/savefile/SaveManager.java b/src/main/java/nuke/storage/Storage.java similarity index 85% rename from src/main/java/nuke/savefile/SaveManager.java rename to src/main/java/nuke/storage/Storage.java index 12dbaa638..b5ee4911f 100644 --- a/src/main/java/nuke/savefile/SaveManager.java +++ b/src/main/java/nuke/storage/Storage.java @@ -1,10 +1,10 @@ -package nuke.savefile; +package nuke.storage; import nuke.Nuke; -import nuke.savefile.exception.TaskFileCopyException; -import nuke.savefile.exception.TaskLoadException; -import nuke.savefile.exception.TaskParseException; -import nuke.savefile.exception.TaskSaveException; +import nuke.storage.exception.TaskFileCopyException; +import nuke.storage.exception.TaskLoadException; +import nuke.storage.exception.TaskParseException; +import nuke.storage.exception.TaskSaveException; import nuke.task.Task; import nuke.task.TaskParser; @@ -13,12 +13,12 @@ import java.util.ArrayList; import java.util.Scanner; -public class SaveManager { +public class Storage { private static final String DIR_DATA = "data"; private static final String FILENAME_TASKS = "nuke.txt"; private static final String FILENAME_TASKS_BACKUP = "nuke_old.txt"; - public static ArrayList loadTasksFromStorage() + public static ArrayList loadTasks() throws TaskLoadException, TaskFileCopyException { ArrayList loadedTasks = new ArrayList<>(); @@ -49,7 +49,7 @@ public static ArrayList loadTasksFromStorage() return loadedTasks; } - public static void saveTasksToStorage() throws TaskSaveException { + public static void saveTasks() throws TaskSaveException { Path currentRelativePath = Paths.get(""); Path currentDir = currentRelativePath.toAbsolutePath(); Path dirPath = currentDir.resolve(DIR_DATA); diff --git a/src/main/java/nuke/storage/exception/StorageException.java b/src/main/java/nuke/storage/exception/StorageException.java new file mode 100644 index 000000000..35c37696e --- /dev/null +++ b/src/main/java/nuke/storage/exception/StorageException.java @@ -0,0 +1,6 @@ +package nuke.storage.exception; + +import nuke.NukeException; + +public class StorageException extends NukeException { +} diff --git a/src/main/java/nuke/savefile/exception/TaskFileCopyException.java b/src/main/java/nuke/storage/exception/TaskFileCopyException.java similarity index 56% rename from src/main/java/nuke/savefile/exception/TaskFileCopyException.java rename to src/main/java/nuke/storage/exception/TaskFileCopyException.java index 7fd90259d..fee4fc556 100644 --- a/src/main/java/nuke/savefile/exception/TaskFileCopyException.java +++ b/src/main/java/nuke/storage/exception/TaskFileCopyException.java @@ -1,6 +1,6 @@ -package nuke.savefile.exception; +package nuke.storage.exception; -public class TaskFileCopyException extends SaveFileException { +public class TaskFileCopyException extends StorageException { public String filePath; public TaskFileCopyException(String filePath) { diff --git a/src/main/java/nuke/savefile/exception/TaskLoadException.java b/src/main/java/nuke/storage/exception/TaskLoadException.java similarity index 61% rename from src/main/java/nuke/savefile/exception/TaskLoadException.java rename to src/main/java/nuke/storage/exception/TaskLoadException.java index 6d61de01f..e3d8d7814 100644 --- a/src/main/java/nuke/savefile/exception/TaskLoadException.java +++ b/src/main/java/nuke/storage/exception/TaskLoadException.java @@ -1,6 +1,6 @@ -package nuke.savefile.exception; +package nuke.storage.exception; -public class TaskLoadException extends SaveFileException { +public class TaskLoadException extends StorageException { public String backupFilePath; public TaskLoadException(String backupFilePath) { diff --git a/src/main/java/nuke/storage/exception/TaskParseException.java b/src/main/java/nuke/storage/exception/TaskParseException.java new file mode 100644 index 000000000..a555b999a --- /dev/null +++ b/src/main/java/nuke/storage/exception/TaskParseException.java @@ -0,0 +1,4 @@ +package nuke.storage.exception; + +public class TaskParseException extends StorageException { +} diff --git a/src/main/java/nuke/storage/exception/TaskSaveException.java b/src/main/java/nuke/storage/exception/TaskSaveException.java new file mode 100644 index 000000000..311d5eb11 --- /dev/null +++ b/src/main/java/nuke/storage/exception/TaskSaveException.java @@ -0,0 +1,4 @@ +package nuke.storage.exception; + +public class TaskSaveException extends StorageException { +} diff --git a/src/main/java/nuke/task/TaskParser.java b/src/main/java/nuke/task/TaskParser.java index 213670d96..a48d8e981 100644 --- a/src/main/java/nuke/task/TaskParser.java +++ b/src/main/java/nuke/task/TaskParser.java @@ -1,6 +1,6 @@ package nuke.task; -import nuke.savefile.exception.TaskParseException; +import nuke.storage.exception.TaskParseException; public class TaskParser { From 6045b24fef30582e1746aa860f3a2a519c171c42 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Tue, 19 Sep 2023 15:13:18 +0800 Subject: [PATCH 32/52] Change minor structure --- src/main/java/nuke/command/exception/CommandException.java | 6 ++++++ .../command/exception/InvalidCommandArgumentException.java | 4 +--- .../nuke/command/exception/InvalidCommandTypeException.java | 4 +--- 3 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 src/main/java/nuke/command/exception/CommandException.java diff --git a/src/main/java/nuke/command/exception/CommandException.java b/src/main/java/nuke/command/exception/CommandException.java new file mode 100644 index 000000000..762e6185e --- /dev/null +++ b/src/main/java/nuke/command/exception/CommandException.java @@ -0,0 +1,6 @@ +package nuke.command.exception; + +import nuke.NukeException; + +public class CommandException extends NukeException { +} diff --git a/src/main/java/nuke/command/exception/InvalidCommandArgumentException.java b/src/main/java/nuke/command/exception/InvalidCommandArgumentException.java index 81d318b59..50faf47ce 100644 --- a/src/main/java/nuke/command/exception/InvalidCommandArgumentException.java +++ b/src/main/java/nuke/command/exception/InvalidCommandArgumentException.java @@ -1,8 +1,6 @@ package nuke.command.exception; -import nuke.NukeException; - -public class InvalidCommandArgumentException extends NukeException { +public class InvalidCommandArgumentException extends CommandException { public String reason; public InvalidCommandArgumentException(String reason) { diff --git a/src/main/java/nuke/command/exception/InvalidCommandTypeException.java b/src/main/java/nuke/command/exception/InvalidCommandTypeException.java index a93eecccf..a3177afb4 100644 --- a/src/main/java/nuke/command/exception/InvalidCommandTypeException.java +++ b/src/main/java/nuke/command/exception/InvalidCommandTypeException.java @@ -1,8 +1,6 @@ package nuke.command.exception; -import nuke.NukeException; - -public class InvalidCommandTypeException extends NukeException { +public class InvalidCommandTypeException extends CommandException { public String type; public InvalidCommandTypeException(String type) { From 341c18f728e82e16a529543abf80afbb031569ae Mon Sep 17 00:00:00 2001 From: ICubE- Date: Tue, 19 Sep 2023 15:24:15 +0800 Subject: [PATCH 33/52] Fix crucial storage error --- src/main/java/nuke/storage/Storage.java | 1 - text-ui-test/runtest.bat | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/nuke/storage/Storage.java b/src/main/java/nuke/storage/Storage.java index b5ee4911f..dc7216a67 100644 --- a/src/main/java/nuke/storage/Storage.java +++ b/src/main/java/nuke/storage/Storage.java @@ -66,7 +66,6 @@ public static void saveTasks() throws TaskSaveException { writer.write('\n'); } } - throw new IOException(); } catch (IOException e) { throw new TaskSaveException(); } diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index 6fa1e2d5a..6c7944ae8 100644 --- a/text-ui-test/runtest.bat +++ b/text-ui-test/runtest.bat @@ -12,6 +12,8 @@ REM compile the code into the bin folder javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\nuke\*.java javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\nuke\command\*.java javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\nuke\command\exception\*.java +javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\nuke\storage\*.java +javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\nuke\storage\exception\*.java javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\nuke\task\*.java IF ERRORLEVEL 1 ( echo ********** BUILD FAILURE ********** From ba173fa28802d0e3634e35aadf6696a6659500fe Mon Sep 17 00:00:00 2001 From: ICubE- Date: Wed, 20 Sep 2023 01:29:30 +0800 Subject: [PATCH 34/52] Make the code more OOP Reduce static parts from Nuke, Storage, Ui --- src/main/java/nuke/Nuke.java | 141 +++++++++--------- src/main/java/nuke/Ui.java | 112 ++++++++++---- src/main/java/nuke/command/ByeCommand.java | 6 +- src/main/java/nuke/command/Command.java | 29 ++-- src/main/java/nuke/command/CommandParser.java | 22 +-- .../java/nuke/command/DeadlineCommand.java | 12 +- src/main/java/nuke/command/DeleteCommand.java | 14 +- src/main/java/nuke/command/EventCommand.java | 16 +- src/main/java/nuke/command/ListCommand.java | 6 +- src/main/java/nuke/command/MarkCommand.java | 14 +- src/main/java/nuke/command/TodoCommand.java | 6 +- src/main/java/nuke/command/UnmarkCommand.java | 14 +- .../InvalidCommandArgumentException.java | 4 +- src/main/java/nuke/storage/Storage.java | 6 +- .../storage/exception/TaskSaveException.java | 1 + src/main/java/nuke/task/TaskList.java | 62 ++++++++ 16 files changed, 279 insertions(+), 186 deletions(-) create mode 100644 src/main/java/nuke/task/TaskList.java diff --git a/src/main/java/nuke/Nuke.java b/src/main/java/nuke/Nuke.java index 1ad8aa7e9..14da3ecf9 100644 --- a/src/main/java/nuke/Nuke.java +++ b/src/main/java/nuke/Nuke.java @@ -8,135 +8,128 @@ import nuke.storage.exception.TaskFileCopyException; import nuke.storage.exception.TaskLoadException; import nuke.storage.exception.TaskSaveException; -import nuke.task.Deadline; -import nuke.task.Event; -import nuke.task.Task; -import nuke.task.Todo; - -import java.util.ArrayList; -import java.util.Scanner; +import nuke.task.*; public class Nuke { - private static boolean isRunning = true; - private static final ArrayList tasks = new ArrayList<>(); + private final Storage storage; + private final TaskList tasks; + private final Ui ui; + private boolean isRunning; public static void main(String[] args) { - final Scanner USER_IN = new Scanner(System.in); + new Nuke().run(); + } - Ui.printWelcome(); + public Nuke() { + ui = new Ui(); + ui.printWelcome(); - // Fail to run if - // 1. loading tasks from the file fails and - // 2. backing up the file fails and - // 3. user does not ignore the error - if (!loadTasksFromStorage(USER_IN)) { - return; - } + storage = new Storage(); + tasks = loadTasksFromStorage(storage, ui); - Ui.printWelcomeAfter(); + isRunning = true; + } + + public void run() { + ui.printGreetingQuestion(); // Loop for user input while (isRunning) { - String input = USER_IN.nextLine(); + String input = ui.scanNextLine(); runCommand(input); - Ui.printBlankLine(); + ui.printBlankLine(); } - saveTasksToStorage(USER_IN); + saveTasksToStorage(storage, ui); } - private static void runCommand(String commandLine) { + private TaskList loadTasksFromStorage(Storage storage, Ui ui) { try { - Command command = CommandParser.parseCommand(commandLine); - command.run(); - } catch (InvalidCommandTypeException | InvalidCommandArgumentException ignored) { - // Thrown by Parse.parseCommand() to prevent command.run(). + return new TaskList(storage.loadTasks()); + } catch (TaskLoadException e) { + // Invoked when loading tasks from the file fails + ui.printTaskLoadError(e); + return new TaskList(); + } catch (TaskFileCopyException e) { + // Invoked when + // 1. loading tasks from the file fails and + // 2. backing up the file fails + // If user does not ignore the error, throw RuntimeException. + ui.handleTaskFileCopyError(e); + return new TaskList(); } } - private static boolean loadTasksFromStorage(final Scanner USER_IN) { - ArrayList loadedTasks; + private void runCommand(String commandLine) { try { - loadedTasks = Storage.loadTasks(); - tasks.addAll(loadedTasks); - } catch (TaskLoadException e) { - Ui.printTaskLoadError(e.backupFilePath); - } catch (TaskFileCopyException e) { - Ui.printTaskFileCopyError(e.filePath); - - String input = USER_IN.nextLine(); - if (!input.equalsIgnoreCase("ignore")) { - return false; - } + Command command = CommandParser.parseCommand(commandLine); + command.run(this); + } catch (InvalidCommandTypeException e) { + ui.printCommandTypeError(e); + } catch (InvalidCommandArgumentException e) { + ui.printCommandArgumentError(e); } - return true; } - private static void saveTasksToStorage(final Scanner USER_IN) { + private void saveTasksToStorage(Storage storage, Ui ui) { try { - Storage.saveTasks(); + storage.saveTasks(getFormattedTasks()); } catch (TaskSaveException e) { - Ui.printTaskSaveError(getTasks()); - boolean isQuitting = false; - while (!isQuitting) { - String input = USER_IN.nextLine(); - isQuitting = !input.isEmpty(); - } + e.tasks = getTasks(); + ui.handleTaskSaveError(e); } } - public static void quit() { + public void quit() { isRunning = false; - Ui.printBye(); + ui.printBye(); } - public static void addTask(Task task) { + public void addTask(Task task) { tasks.add(task); - Ui.printAddedTask(task.toString(), getNumberOfTasks()); + ui.printAddedTask(task.toString(), getNumberOfTasks()); } - public static void listTask() { - Ui.printListOfTasks(getTasks()); + public void listTask() { + ui.printListOfTasks(getTasks()); } - public static void markTask(int idx) { - Task task = tasks.get(idx); - task.setDone(true); - Ui.printMarkedTask(task.toString()); + public void markTask(int idx) { + String task = tasks.mark(idx); + ui.printMarkedTask(task); } - public static void unmarkTask(int idx) { - Task task = tasks.get(idx); - task.setDone(false); - Ui.printUnmarkedTask(task.toString()); + public void unmarkTask(int idx) { + String task = tasks.unmark(idx); + ui.printUnmarkedTask(task); } - public static void deleteTask(int idx) { - Task task = tasks.remove(idx); - Ui.printDeletedTask(task.toString(), getNumberOfTasks()); + public void deleteTask(int idx) { + String task = tasks.delete(idx); + ui.printDeletedTask(task, getNumberOfTasks()); } - public static void addTodo(String name) { + public void addTodo(String name) { addTask(new Todo(name)); } - public static void addDeadline(String name, String by) { + public void addDeadline(String name, String by) { addTask(new Deadline(name, by)); } - public static void addEvent(String name, String from, String to) { + public void addEvent(String name, String from, String to) { addTask(new Event(name, from, to)); } - public static int getNumberOfTasks() { + public int getNumberOfTasks() { return tasks.size(); } - public static String[] getTasks() { - return tasks.stream().map(Task::toString).toArray(String[]::new); + public String[] getTasks() { + return tasks.getTasks(); } - public static String[] getFormattedTasks() { - return tasks.stream().map(Task::formatData).toArray(String[]::new); + public String[] getFormattedTasks() { + return tasks.getFormattedTasks(); } } diff --git a/src/main/java/nuke/Ui.java b/src/main/java/nuke/Ui.java index 19000d2fb..efde5a64b 100644 --- a/src/main/java/nuke/Ui.java +++ b/src/main/java/nuke/Ui.java @@ -1,44 +1,60 @@ package nuke; +import nuke.command.exception.InvalidCommandArgumentException; +import nuke.command.exception.InvalidCommandTypeException; +import nuke.storage.exception.TaskFileCopyException; +import nuke.storage.exception.TaskLoadException; +import nuke.storage.exception.TaskSaveException; + +import java.util.Scanner; + public class Ui { - public static final String LOGO = - " _.-^^---....,,-- \n" + - " _-- --_ \n" + - "< >)\n" + - "| |\n" + - " \\._ _./ \n" + - " ```--. . , ; .--''' \n" + - " | | | \n" + - " .-=|| | |=-. \n" + - " `-=#$%&%$#=-' \n" + - " | ; :| \n" + - " _____.,-#%&$@%#&#~,._____ "; + private final String IGNORE_ERROR_COMMAND = "ignore"; + + private final Scanner USER_IN; + + public Ui() { + USER_IN = new Scanner(System.in); + } + + public String scanNextLine() { + return USER_IN.nextLine(); + } - public static void printWelcome() { + public boolean scanIgnore() { + return scanNextLine().equals(IGNORE_ERROR_COMMAND); + } + + public void scanWhileEmpty() { + while (scanNextLine().isEmpty()); + } + + public void printWelcome() { System.out.println(LOGO); System.out.println(); System.out.println("[@] Hello! I'm Nuke."); } - public static void printWelcomeAfter() { + public void printGreetingQuestion() { System.out.println("[@] What can I do for you?"); System.out.println(); } - public static void printBlankLine() { + public void printBlankLine() { System.out.println(); } - public static void printBye() { + public void printBye() { System.out.println("[@] Bye. Hope to see you again soon!"); } - public static void printAddedTask(String addedTask, int taskCnt) { + public void printAddedTask(String addedTask, int taskCnt) { System.out.println("[@] Got it. I've added this task:"); System.out.println(" " + addedTask); System.out.printf("[@] Now you have %d task%s in the list.\n", taskCnt, taskCnt == 1 ? "": "s"); } - public static void printListOfTasks(String[] tasks) { + + public void printListOfTasks(String[] tasks) { if(tasks.length == 0) { System.out.println("[@] There are no tasks in your list."); return; @@ -49,50 +65,90 @@ public static void printListOfTasks(String[] tasks) { } } - public static void printMarkedTask(String markedTask) { + public void printMarkedTask(String markedTask) { System.out.println("[@] Nice! I've marked this task as done:"); System.out.println(" " + markedTask); } - public static void printUnmarkedTask(String unmarkedTask) { + public void printUnmarkedTask(String unmarkedTask) { System.out.println("[@] OK, I've marked this task as not done yet:"); System.out.println(" " + unmarkedTask); } - public static void printDeletedTask(String deletedTask, int taskCnt) { + public void printDeletedTask(String deletedTask, int taskCnt) { System.out.println("[@] Noted. I've removed this task:"); System.out.println(" " + deletedTask); System.out.printf("[@] Now you have %d task%s in the list.\n", taskCnt, taskCnt == 1 ? "": "s"); } - public static void printCommandError(String description, String detail) { + public void printCommandError(String description, String detail) { System.out.println("[@] Wrong input; " + description); System.out.println("[@] " + detail); } - public static void printTaskLoadError(String backupFilePath) { + public void printCommandTypeError(InvalidCommandTypeException e) { + String desc = String.format("There is no command called '%s'.", e.type); + String detail = "Existing command: bye, list, mark, unmark, todo, deadline, event"; + printCommandError(desc, detail); + } + + public void printCommandArgumentError(InvalidCommandArgumentException e) { + String desc = e.reason; + printCommandError(desc, e.correctUsage); + } + + public void printTaskLoadError(TaskLoadException e) { System.out.println(); System.out.println("[@] Error occurred while loading the tasks!"); System.out.println("[@] I backed up your save file."); - System.out.println("[@] Path: " + backupFilePath); + System.out.println("[@] Path: " + e.backupFilePath); System.out.println(); } - public static void printTaskFileCopyError(String filePath) { + + public void handleTaskFileCopyError(TaskFileCopyException e) { + printTaskFileCopyError(e, IGNORE_ERROR_COMMAND); + if (!scanIgnore()) { + throw new RuntimeException(e); + } + } + + public void printTaskFileCopyError(TaskFileCopyException e, String ignoreCommand) { System.out.println(); System.out.println("[@] Error occurred while loading the tasks!"); System.out.println("[@] I tried to back up your save file, but it failed as well."); System.out.println("[@] You can back up your save file manually."); - System.out.println("[@] Path: " + filePath); + System.out.println("[@] Path: " + e.filePath); System.out.println(); - System.out.println("[@] Ignore and continue to run by entering 'ignore'."); + System.out.printf("[@] Ignore and continue to run by entering '%s'.", ignoreCommand); + System.out.println("[@] Otherwise I will quit."); System.out.println(); } - public static void printTaskSaveError(String[] tasks) { + + public void handleTaskSaveError(TaskSaveException e) { + printTaskSaveError(e.tasks); + scanWhileEmpty(); + } + + public void printTaskSaveError(String[] tasks) { System.out.println("[@] Error occurred while saving the tasks!"); System.out.println("[@] I will show all the tasks you have added."); printListOfTasks(tasks); System.out.println(); System.out.println("[@] Please back up your save file manually."); System.out.println("[@] Continue to quit by entering non-empty input."); + System.out.println(); } + + public static final String LOGO = + " _.-^^---....,,-- \n" + + " _-- --_ \n" + + "< >)\n" + + "| |\n" + + " \\._ _./ \n" + + " ```--. . , ; .--''' \n" + + " | | | \n" + + " .-=|| | |=-. \n" + + " `-=#$%&%$#=-' \n" + + " | ; :| \n" + + " _____.,-#%&$@%#&#~,._____ "; } diff --git a/src/main/java/nuke/command/ByeCommand.java b/src/main/java/nuke/command/ByeCommand.java index be6a2b3ab..6ce2eb016 100644 --- a/src/main/java/nuke/command/ByeCommand.java +++ b/src/main/java/nuke/command/ByeCommand.java @@ -8,7 +8,7 @@ public class ByeCommand extends Command { @Override public void applyArguments(String args) throws InvalidCommandArgumentException { if (!args.isEmpty()) { - throw new InvalidCommandArgumentException(ERROR_MSG_TOO_MANY_ARGS); + throwArgumentException(ERROR_MSG_TOO_MANY_ARGS); } } @@ -18,8 +18,8 @@ protected String getUsage() { } @Override - public void run() { - Nuke.quit(); + public void run(Nuke nuke) { + nuke.quit(); } private static final String ERROR_MSG_TOO_MANY_ARGS = diff --git a/src/main/java/nuke/command/Command.java b/src/main/java/nuke/command/Command.java index 942d7f678..125b921fa 100644 --- a/src/main/java/nuke/command/Command.java +++ b/src/main/java/nuke/command/Command.java @@ -1,39 +1,36 @@ package nuke.command; +import nuke.Nuke; import nuke.command.exception.InvalidCommandArgumentException; -import nuke.Ui; import java.util.Arrays; public abstract class Command { - private static final String FORBIDDEN_CHARACTERS = "/"; - private static final String ERROR_MSG_FORBIDDEN_CHARACTERS = - "Command '%s' should not contain '" + FORBIDDEN_CHARACTERS + "' in arguments."; - public abstract void applyArguments(String args) throws InvalidCommandArgumentException; + abstract String getUsage(); + + public abstract void run(Nuke nuke) throws InvalidCommandArgumentException; + protected void checkForbiddenCharacters(String[] parsedArgs) throws InvalidCommandArgumentException { if (Arrays.stream(parsedArgs).anyMatch(s -> s.contains(FORBIDDEN_CHARACTERS))) { String errorMessage = String.format(ERROR_MSG_FORBIDDEN_CHARACTERS, getType()); - throw new InvalidCommandArgumentException(errorMessage); + throwArgumentException(errorMessage); } } - public void handleArgumentError(InvalidCommandArgumentException e) { - Ui.printCommandError(e.reason, getArgumentErrorDetail()); - } - - private String getArgumentErrorDetail() { - return "Usage: " + getUsage(); - } - protected String getType() { return getUsage().split(" ")[0]; } - protected abstract String getUsage(); + protected void throwArgumentException(String reason) + throws InvalidCommandArgumentException { + throw new InvalidCommandArgumentException(reason, "Usage: " + getUsage()); + } - public abstract void run(); + private static final String FORBIDDEN_CHARACTERS = "/"; + private static final String ERROR_MSG_FORBIDDEN_CHARACTERS = + "Command '%s' should not contain '" + FORBIDDEN_CHARACTERS + "' in arguments."; } diff --git a/src/main/java/nuke/command/CommandParser.java b/src/main/java/nuke/command/CommandParser.java index 439045c1d..1c2ad7264 100644 --- a/src/main/java/nuke/command/CommandParser.java +++ b/src/main/java/nuke/command/CommandParser.java @@ -1,6 +1,5 @@ package nuke.command; -import nuke.Ui; import nuke.command.exception.InvalidCommandArgumentException; import nuke.command.exception.InvalidCommandTypeException; @@ -14,22 +13,11 @@ public static Command parseCommand(String commandLine) // Get command type and arguments. String type = getCommandType(commandLine); String args = getCommandArguments(commandLine, type); - Command command; // Construct command using command type. - try { - command = getBlankCommand(type); - } catch (InvalidCommandTypeException e) { - handleTypeError(e); - throw e; - } + Command command = getBlankCommand(type); // Apply arguments on command. - try { - command.applyArguments(args); - } catch (InvalidCommandArgumentException e) { - command.handleArgumentError(e); - throw e; - } + command.applyArguments(args); return command; } @@ -76,12 +64,6 @@ private static String getCommandArguments(String commandLine, String type) { return commandLine.substring(type.length()).strip(); } - public static void handleTypeError(InvalidCommandTypeException e) { - String desc = String.format("There is no command called '%s'.", e.type); - String detail = "Existing command: bye, list, mark, unmark, todo, deadline, event"; - Ui.printCommandError(desc, detail); - } - public static boolean isNotOneWord(String str) { if (str.isEmpty()) { return true; diff --git a/src/main/java/nuke/command/DeadlineCommand.java b/src/main/java/nuke/command/DeadlineCommand.java index d76ae8004..5ce177b70 100644 --- a/src/main/java/nuke/command/DeadlineCommand.java +++ b/src/main/java/nuke/command/DeadlineCommand.java @@ -10,13 +10,13 @@ public class DeadlineCommand extends Command { @Override public void applyArguments(String args) throws InvalidCommandArgumentException { if (args.isEmpty()) { - throw new InvalidCommandArgumentException(ERROR_MSG_NO_ARGS); + throwArgumentException(ERROR_MSG_NO_ARGS); } else if (CommandParser.isNotContainingExactOneLabel(args, "/by")) { - throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_BY); + throwArgumentException(ERROR_MSG_INVALID_NUMBER_OF_BY); } else if (CommandParser.matches(args, "/by(.*)")) { - throw new InvalidCommandArgumentException(ERROR_MSG_NAME_EMPTY); + throwArgumentException(ERROR_MSG_NAME_EMPTY); } else if (CommandParser.matches(args, "(.+)\\s/by")) { - throw new InvalidCommandArgumentException(ERROR_MSG_BY_EMPTY); + throwArgumentException(ERROR_MSG_BY_EMPTY); } String[] parsedArgs = CommandParser.parseArguments(args, "(.+)\\s/by\\s(.+)"); @@ -31,8 +31,8 @@ protected String getUsage() { } @Override - public void run() { - Nuke.addDeadline(name, by); + public void run(Nuke nuke) { + nuke.addDeadline(name, by); } private static final String ERROR_MSG_NO_ARGS = diff --git a/src/main/java/nuke/command/DeleteCommand.java b/src/main/java/nuke/command/DeleteCommand.java index 0c61dd3fa..c3eb0833f 100644 --- a/src/main/java/nuke/command/DeleteCommand.java +++ b/src/main/java/nuke/command/DeleteCommand.java @@ -9,16 +9,13 @@ public class DeleteCommand extends Command { @Override public void applyArguments(String args) throws InvalidCommandArgumentException { if (CommandParser.isNotOneWord(args)) { - throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_ARGS); + throwArgumentException(ERROR_MSG_INVALID_NUMBER_OF_ARGS); } // Input index starts with 1, logical index starts with 0. try { index = Integer.parseInt(args) - 1; } catch (NumberFormatException e) { - throw new InvalidCommandArgumentException(ERROR_MSG_INDEX_NOT_INTEGER); - } - if(index < 0 || index >= Nuke.getNumberOfTasks()) { - throw new InvalidCommandArgumentException(ERROR_MSG_INDEX_INVALID_VALUE); + throwArgumentException(ERROR_MSG_INDEX_NOT_INTEGER); } } @@ -28,8 +25,11 @@ protected String getUsage() { } @Override - public void run() { - Nuke.deleteTask(index); + public void run(Nuke nuke) throws InvalidCommandArgumentException { + if(index < 0 || index >= nuke.getNumberOfTasks()) { + throwArgumentException(ERROR_MSG_INDEX_INVALID_VALUE); + } + nuke.deleteTask(index); } private static final String ERROR_MSG_INVALID_NUMBER_OF_ARGS = diff --git a/src/main/java/nuke/command/EventCommand.java b/src/main/java/nuke/command/EventCommand.java index c8cc8f7bb..a04fa92e9 100644 --- a/src/main/java/nuke/command/EventCommand.java +++ b/src/main/java/nuke/command/EventCommand.java @@ -11,17 +11,17 @@ public class EventCommand extends Command { @Override public void applyArguments(String args) throws InvalidCommandArgumentException { if (args.isEmpty()) { - throw new InvalidCommandArgumentException(ERROR_MSG_NO_ARGS); + throwArgumentException(ERROR_MSG_NO_ARGS); } else if (CommandParser.isNotContainingExactOneLabel(args, "/from")) { - throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_FROM_TO); + throwArgumentException(ERROR_MSG_INVALID_NUMBER_OF_FROM_TO); } else if (CommandParser.isNotContainingExactOneLabel(args, "/to")) { - throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_FROM_TO); + throwArgumentException(ERROR_MSG_INVALID_NUMBER_OF_FROM_TO); } else if (CommandParser.matches(args, "/from(.*)")) { - throw new InvalidCommandArgumentException(ERROR_MSG_NAME_EMPTY); + throwArgumentException(ERROR_MSG_NAME_EMPTY); } else if (CommandParser.matches(args, "(.+)\\s/from\\s/to(.*)")) { - throw new InvalidCommandArgumentException(ERROR_MSG_FROM_EMPTY); + throwArgumentException(ERROR_MSG_FROM_EMPTY); } else if (CommandParser.matches(args, "(.+)\\s/from\\s(.+)\\s/to")) { - throw new InvalidCommandArgumentException(ERROR_MSG_TO_EMPTY); + throwArgumentException(ERROR_MSG_TO_EMPTY); } String[] parsedArgs = CommandParser.parseArguments(args, "(.+)\\s/from\\s(.+)\\s/to\\s(.+)"); @@ -37,8 +37,8 @@ protected String getUsage() { } @Override - public void run() { - Nuke.addEvent(name, from, to); + public void run(Nuke nuke) { + nuke.addEvent(name, from, to); } private static final String ERROR_MSG_NO_ARGS = diff --git a/src/main/java/nuke/command/ListCommand.java b/src/main/java/nuke/command/ListCommand.java index ed5104650..a4e6ff210 100644 --- a/src/main/java/nuke/command/ListCommand.java +++ b/src/main/java/nuke/command/ListCommand.java @@ -8,7 +8,7 @@ public class ListCommand extends Command { @Override public void applyArguments(String args) throws InvalidCommandArgumentException { if (!args.isEmpty()) { - throw new InvalidCommandArgumentException(ERROR_MSG_TOO_MANY_ARGS); + throwArgumentException(ERROR_MSG_TOO_MANY_ARGS); } } @@ -18,8 +18,8 @@ protected String getUsage() { } @Override - public void run() { - Nuke.listTask(); + public void run(Nuke nuke) { + nuke.listTask(); } private static final String ERROR_MSG_TOO_MANY_ARGS = diff --git a/src/main/java/nuke/command/MarkCommand.java b/src/main/java/nuke/command/MarkCommand.java index d174b2a48..8ec1bcdf5 100644 --- a/src/main/java/nuke/command/MarkCommand.java +++ b/src/main/java/nuke/command/MarkCommand.java @@ -9,16 +9,13 @@ public class MarkCommand extends Command { @Override public void applyArguments(String args) throws InvalidCommandArgumentException { if (CommandParser.isNotOneWord(args)) { - throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_ARGS); + throwArgumentException(ERROR_MSG_INVALID_NUMBER_OF_ARGS); } // Input index starts with 1, logical index starts with 0. try { index = Integer.parseInt(args) - 1; } catch (NumberFormatException e) { - throw new InvalidCommandArgumentException(ERROR_MSG_INDEX_NOT_INTEGER); - } - if(index < 0 || index >= Nuke.getNumberOfTasks()) { - throw new InvalidCommandArgumentException(ERROR_MSG_INDEX_INVALID_VALUE); + throwArgumentException(ERROR_MSG_INDEX_NOT_INTEGER); } } @@ -28,8 +25,11 @@ protected String getUsage() { } @Override - public void run() { - Nuke.markTask(index); + public void run(Nuke nuke) throws InvalidCommandArgumentException { + if(index < 0 || index >= nuke.getNumberOfTasks()) { + throwArgumentException(ERROR_MSG_INDEX_INVALID_VALUE); + } + nuke.markTask(index); } private static final String ERROR_MSG_INVALID_NUMBER_OF_ARGS = diff --git a/src/main/java/nuke/command/TodoCommand.java b/src/main/java/nuke/command/TodoCommand.java index 9e9974609..fa5a51388 100644 --- a/src/main/java/nuke/command/TodoCommand.java +++ b/src/main/java/nuke/command/TodoCommand.java @@ -9,7 +9,7 @@ public class TodoCommand extends Command { @Override public void applyArguments(String args) throws InvalidCommandArgumentException { if (args.isEmpty()) { - throw new InvalidCommandArgumentException(ERROR_MSG_NO_ARGS); + throwArgumentException(ERROR_MSG_NO_ARGS); } checkForbiddenCharacters(new String[]{args}); name = args; @@ -21,8 +21,8 @@ protected String getUsage() { } @Override - public void run() { - Nuke.addTodo(name); + public void run(Nuke nuke) { + nuke.addTodo(name); } private static final String ERROR_MSG_NO_ARGS = diff --git a/src/main/java/nuke/command/UnmarkCommand.java b/src/main/java/nuke/command/UnmarkCommand.java index e2f86f757..cd09108f3 100644 --- a/src/main/java/nuke/command/UnmarkCommand.java +++ b/src/main/java/nuke/command/UnmarkCommand.java @@ -9,16 +9,13 @@ public class UnmarkCommand extends Command { @Override public void applyArguments(String args) throws InvalidCommandArgumentException { if (CommandParser.isNotOneWord(args)) { - throw new InvalidCommandArgumentException(ERROR_MSG_INVALID_NUMBER_OF_ARGS); + throwArgumentException(ERROR_MSG_INVALID_NUMBER_OF_ARGS); } // Input index starts with 1, logical index starts with 0. try { index = Integer.parseInt(args) - 1; } catch (NumberFormatException e) { - throw new InvalidCommandArgumentException(ERROR_MSG_INDEX_NOT_INTEGER); - } - if(index < 0 || index >= Nuke.getNumberOfTasks()) { - throw new InvalidCommandArgumentException(ERROR_MSG_INDEX_INVALID_VALUE); + throwArgumentException(ERROR_MSG_INDEX_NOT_INTEGER); } } @@ -28,8 +25,11 @@ protected String getUsage() { } @Override - public void run() { - Nuke.unmarkTask(index); + public void run(Nuke nuke) throws InvalidCommandArgumentException { + if(index < 0 || index >= nuke.getNumberOfTasks()) { + throwArgumentException(ERROR_MSG_INDEX_INVALID_VALUE); + } + nuke.unmarkTask(index); } private static final String ERROR_MSG_INVALID_NUMBER_OF_ARGS = diff --git a/src/main/java/nuke/command/exception/InvalidCommandArgumentException.java b/src/main/java/nuke/command/exception/InvalidCommandArgumentException.java index 50faf47ce..7b35a166f 100644 --- a/src/main/java/nuke/command/exception/InvalidCommandArgumentException.java +++ b/src/main/java/nuke/command/exception/InvalidCommandArgumentException.java @@ -2,8 +2,10 @@ public class InvalidCommandArgumentException extends CommandException { public String reason; + public String correctUsage; - public InvalidCommandArgumentException(String reason) { + public InvalidCommandArgumentException(String reason, String correctUsage) { this.reason = reason; + this.correctUsage = correctUsage; } } diff --git a/src/main/java/nuke/storage/Storage.java b/src/main/java/nuke/storage/Storage.java index dc7216a67..697069eb9 100644 --- a/src/main/java/nuke/storage/Storage.java +++ b/src/main/java/nuke/storage/Storage.java @@ -18,7 +18,7 @@ public class Storage { private static final String FILENAME_TASKS = "nuke.txt"; private static final String FILENAME_TASKS_BACKUP = "nuke_old.txt"; - public static ArrayList loadTasks() + public ArrayList loadTasks() throws TaskLoadException, TaskFileCopyException { ArrayList loadedTasks = new ArrayList<>(); @@ -49,7 +49,7 @@ public static ArrayList loadTasks() return loadedTasks; } - public static void saveTasks() throws TaskSaveException { + public void saveTasks(String[] formattedTasks) throws TaskSaveException { Path currentRelativePath = Paths.get(""); Path currentDir = currentRelativePath.toAbsolutePath(); Path dirPath = currentDir.resolve(DIR_DATA); @@ -61,7 +61,7 @@ public static void saveTasks() throws TaskSaveException { dir.mkdir(); file.createNewFile(); try (FileWriter writer = new FileWriter(file)) { - for (String formattedTask: Nuke.getFormattedTasks()) { + for (String formattedTask: formattedTasks) { writer.write(formattedTask); writer.write('\n'); } diff --git a/src/main/java/nuke/storage/exception/TaskSaveException.java b/src/main/java/nuke/storage/exception/TaskSaveException.java index 311d5eb11..88436f783 100644 --- a/src/main/java/nuke/storage/exception/TaskSaveException.java +++ b/src/main/java/nuke/storage/exception/TaskSaveException.java @@ -1,4 +1,5 @@ package nuke.storage.exception; public class TaskSaveException extends StorageException { + public String[] tasks; } diff --git a/src/main/java/nuke/task/TaskList.java b/src/main/java/nuke/task/TaskList.java new file mode 100644 index 000000000..7266c270c --- /dev/null +++ b/src/main/java/nuke/task/TaskList.java @@ -0,0 +1,62 @@ +package nuke.task; + +import nuke.Ui; + +import java.util.ArrayList; + +public class TaskList { + private final ArrayList tasks; + + public TaskList() { + this(new ArrayList<>()); + } + + public TaskList(ArrayList tasks) { + this.tasks = tasks; + } + + public void add(Task task) { + tasks.add(task); + } + + public String mark(int idx) { + Task task = tasks.get(idx); + task.setDone(true); + return task.toString(); + } + + public String unmark(int idx) { + Task task = tasks.get(idx); + task.setDone(false); + return task.toString(); + } + + public String delete(int idx) { + Task task = tasks.remove(idx); + return task.toString(); + } + + public void addTodo(String name) { + add(new Todo(name)); + } + + public void addDeadline(String name, String by) { + add(new Deadline(name, by)); + } + + public void addEvent(String name, String from, String to) { + add(new Event(name, from, to)); + } + + public int size() { + return tasks.size(); + } + + public String[] getTasks() { + return tasks.stream().map(Task::toString).toArray(String[]::new); + } + + public String[] getFormattedTasks() { + return tasks.stream().map(Task::formatData).toArray(String[]::new); + } +} From 3e74a3b42f47d7658e893d68c6c88ad2ee19b332 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Wed, 20 Sep 2023 02:26:51 +0800 Subject: [PATCH 35/52] Apply TA's PR comments Reduce magic literals --- src/main/java/nuke/Nuke.java | 6 +++- src/main/java/nuke/Ui.java | 1 + src/main/java/nuke/command/ByeCommand.java | 9 ++++- src/main/java/nuke/command/Command.java | 8 ++--- src/main/java/nuke/command/CommandParser.java | 24 +++++++------ .../java/nuke/command/DeadlineCommand.java | 22 +++++++++--- src/main/java/nuke/command/DeleteCommand.java | 10 +++++- src/main/java/nuke/command/EventCommand.java | 32 +++++++++++++---- src/main/java/nuke/command/ListCommand.java | 9 ++++- src/main/java/nuke/command/MarkCommand.java | 10 +++++- src/main/java/nuke/command/TodoCommand.java | 10 +++++- src/main/java/nuke/command/UnmarkCommand.java | 10 +++++- src/main/java/nuke/storage/Storage.java | 10 ++++-- src/main/java/nuke/task/TaskList.java | 36 +++++++------------ 14 files changed, 136 insertions(+), 61 deletions(-) diff --git a/src/main/java/nuke/Nuke.java b/src/main/java/nuke/Nuke.java index 14da3ecf9..c4665886f 100644 --- a/src/main/java/nuke/Nuke.java +++ b/src/main/java/nuke/Nuke.java @@ -8,7 +8,11 @@ import nuke.storage.exception.TaskFileCopyException; import nuke.storage.exception.TaskLoadException; import nuke.storage.exception.TaskSaveException; -import nuke.task.*; +import nuke.task.Deadline; +import nuke.task.Event; +import nuke.task.Task; +import nuke.task.TaskList; +import nuke.task.Todo; public class Nuke { private final Storage storage; diff --git a/src/main/java/nuke/Ui.java b/src/main/java/nuke/Ui.java index efde5a64b..5d33efcd7 100644 --- a/src/main/java/nuke/Ui.java +++ b/src/main/java/nuke/Ui.java @@ -26,6 +26,7 @@ public boolean scanIgnore() { } public void scanWhileEmpty() { + //noinspection StatementWithEmptyBody while (scanNextLine().isEmpty()); } diff --git a/src/main/java/nuke/command/ByeCommand.java b/src/main/java/nuke/command/ByeCommand.java index 6ce2eb016..b2f2d1ac0 100644 --- a/src/main/java/nuke/command/ByeCommand.java +++ b/src/main/java/nuke/command/ByeCommand.java @@ -4,6 +4,8 @@ import nuke.Nuke; public class ByeCommand extends Command { + public static final String TYPE = "bye"; + private static final String USAGE = TYPE; @Override public void applyArguments(String args) throws InvalidCommandArgumentException { @@ -12,9 +14,14 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { } } + @Override + protected String getType() { + return TYPE; + } + @Override protected String getUsage() { - return "bye"; + return USAGE; } @Override diff --git a/src/main/java/nuke/command/Command.java b/src/main/java/nuke/command/Command.java index 125b921fa..9e6812ac0 100644 --- a/src/main/java/nuke/command/Command.java +++ b/src/main/java/nuke/command/Command.java @@ -9,7 +9,9 @@ public abstract class Command { public abstract void applyArguments(String args) throws InvalidCommandArgumentException; - abstract String getUsage(); + protected abstract String getType(); + + protected abstract String getUsage(); public abstract void run(Nuke nuke) throws InvalidCommandArgumentException; @@ -21,10 +23,6 @@ protected void checkForbiddenCharacters(String[] parsedArgs) } } - protected String getType() { - return getUsage().split(" ")[0]; - } - protected void throwArgumentException(String reason) throws InvalidCommandArgumentException { throw new InvalidCommandArgumentException(reason, "Usage: " + getUsage()); diff --git a/src/main/java/nuke/command/CommandParser.java b/src/main/java/nuke/command/CommandParser.java index 1c2ad7264..e3552209d 100644 --- a/src/main/java/nuke/command/CommandParser.java +++ b/src/main/java/nuke/command/CommandParser.java @@ -26,28 +26,28 @@ private static Command getBlankCommand(String type) throws InvalidCommandTypeException { Command command; switch (type) { - case "bye": + case ByeCommand.TYPE: command = new ByeCommand(); break; - case "list": + case ListCommand.TYPE: command = new ListCommand(); break; - case "mark": + case MarkCommand.TYPE: command = new MarkCommand(); break; - case "unmark": + case UnmarkCommand.TYPE: command = new UnmarkCommand(); break; - case "todo": + case TodoCommand.TYPE: command = new TodoCommand(); break; - case "deadline": + case DeadlineCommand.TYPE: command = new DeadlineCommand(); break; - case "event": + case EventCommand.TYPE: command = new EventCommand(); break; - case "delete": + case DeleteCommand.TYPE: command = new DeleteCommand(); break; default: @@ -57,7 +57,7 @@ private static Command getBlankCommand(String type) } private static String getCommandType(String commandLine) { - return commandLine.split("\\s")[0]; + return commandLine.split(REGEX_WHITESPACE)[0]; } private static String getCommandArguments(String commandLine, String type) { @@ -67,11 +67,11 @@ private static String getCommandArguments(String commandLine, String type) { public static boolean isNotOneWord(String str) { if (str.isEmpty()) { return true; - } else return str.split("\\s").length != 1; + } else return str.split(REGEX_WHITESPACE).length != 1; } public static boolean isNotContainingExactOneLabel(String str, String label) { - String[] argSplit = str.split("\\s"); + String[] argSplit = str.split(REGEX_WHITESPACE); long labelCnt = Arrays.stream(argSplit).filter(a -> a.equals(label)).count(); return labelCnt != 1; } @@ -93,4 +93,6 @@ public static String[] parseArguments(String args, String regex) { return parsedArgs; } + + private static final String REGEX_WHITESPACE = "\\s"; } diff --git a/src/main/java/nuke/command/DeadlineCommand.java b/src/main/java/nuke/command/DeadlineCommand.java index 5ce177b70..5363c5628 100644 --- a/src/main/java/nuke/command/DeadlineCommand.java +++ b/src/main/java/nuke/command/DeadlineCommand.java @@ -4,6 +4,13 @@ import nuke.Nuke; public class DeadlineCommand extends Command { + public static final String TYPE = "deadline"; + private static final String BY_LABEL = "/by"; + private static final String USAGE = TYPE + " ((name)) " + BY_LABEL + " ((deadline))"; + private static final String REGEX_NAME_EMPTY = BY_LABEL + "(.*)"; + private static final String REGEX_BY_EMPTY = "(.+)\\s" + BY_LABEL; + private static final String REGEX_PARSE = "(.+)\\s" + BY_LABEL + "\\s(.+)"; + public String name; public String by; @@ -11,23 +18,28 @@ public class DeadlineCommand extends Command { public void applyArguments(String args) throws InvalidCommandArgumentException { if (args.isEmpty()) { throwArgumentException(ERROR_MSG_NO_ARGS); - } else if (CommandParser.isNotContainingExactOneLabel(args, "/by")) { + } else if (CommandParser.isNotContainingExactOneLabel(args, BY_LABEL)) { throwArgumentException(ERROR_MSG_INVALID_NUMBER_OF_BY); - } else if (CommandParser.matches(args, "/by(.*)")) { + } else if (CommandParser.matches(args, REGEX_NAME_EMPTY)) { throwArgumentException(ERROR_MSG_NAME_EMPTY); - } else if (CommandParser.matches(args, "(.+)\\s/by")) { + } else if (CommandParser.matches(args, REGEX_BY_EMPTY)) { throwArgumentException(ERROR_MSG_BY_EMPTY); } - String[] parsedArgs = CommandParser.parseArguments(args, "(.+)\\s/by\\s(.+)"); + String[] parsedArgs = CommandParser.parseArguments(args, REGEX_PARSE); checkForbiddenCharacters(parsedArgs); name = parsedArgs[0]; by = parsedArgs[1]; } + @Override + protected String getType() { + return TYPE; + } + @Override protected String getUsage() { - return "deadline ((name)) /by ((deadline))"; + return USAGE; } @Override diff --git a/src/main/java/nuke/command/DeleteCommand.java b/src/main/java/nuke/command/DeleteCommand.java index c3eb0833f..68c92843a 100644 --- a/src/main/java/nuke/command/DeleteCommand.java +++ b/src/main/java/nuke/command/DeleteCommand.java @@ -4,6 +4,9 @@ import nuke.command.exception.InvalidCommandArgumentException; public class DeleteCommand extends Command { + public static final String TYPE = "delete"; + private static final String USAGE = TYPE + " ((index))"; + private int index; @Override @@ -19,9 +22,14 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { } } + @Override + protected String getType() { + return TYPE; + } + @Override protected String getUsage() { - return "delete ((index))"; + return USAGE; } @Override diff --git a/src/main/java/nuke/command/EventCommand.java b/src/main/java/nuke/command/EventCommand.java index a04fa92e9..9ae6bd987 100644 --- a/src/main/java/nuke/command/EventCommand.java +++ b/src/main/java/nuke/command/EventCommand.java @@ -4,6 +4,19 @@ import nuke.Nuke; public class EventCommand extends Command { + public static final String TYPE = "event"; + private static final String FROM_LABEL = "/from"; + private static final String TO_LABEL = "/to"; + private static final String USAGE = + TYPE + " ((name)) " + FROM_LABEL + " ((start)) " + TO_LABEL + " ((end))"; + private static final String REGEX_NAME_EMPTY = FROM_LABEL + "(.*)"; + private static final String REGEX_FROM_EMPTY = + "(.+)\\s" + FROM_LABEL + "\\s" + TO_LABEL + "(.*)"; + private static final String REGEX_TO_EMPTY = + "(.+)\\s" + FROM_LABEL + "\\s(.+)\\s" + TO_LABEL; + private static final String REGEX_PARSE = + "(.+)\\s" + FROM_LABEL + "\\s(.+)\\s" + TO_LABEL + "\\s(.+)"; + public String name; public String from; public String to; @@ -12,28 +25,33 @@ public class EventCommand extends Command { public void applyArguments(String args) throws InvalidCommandArgumentException { if (args.isEmpty()) { throwArgumentException(ERROR_MSG_NO_ARGS); - } else if (CommandParser.isNotContainingExactOneLabel(args, "/from")) { + } else if (CommandParser.isNotContainingExactOneLabel(args, FROM_LABEL)) { throwArgumentException(ERROR_MSG_INVALID_NUMBER_OF_FROM_TO); - } else if (CommandParser.isNotContainingExactOneLabel(args, "/to")) { + } else if (CommandParser.isNotContainingExactOneLabel(args, TO_LABEL)) { throwArgumentException(ERROR_MSG_INVALID_NUMBER_OF_FROM_TO); - } else if (CommandParser.matches(args, "/from(.*)")) { + } else if (CommandParser.matches(args, REGEX_NAME_EMPTY)) { throwArgumentException(ERROR_MSG_NAME_EMPTY); - } else if (CommandParser.matches(args, "(.+)\\s/from\\s/to(.*)")) { + } else if (CommandParser.matches(args, REGEX_FROM_EMPTY)) { throwArgumentException(ERROR_MSG_FROM_EMPTY); - } else if (CommandParser.matches(args, "(.+)\\s/from\\s(.+)\\s/to")) { + } else if (CommandParser.matches(args, REGEX_TO_EMPTY)) { throwArgumentException(ERROR_MSG_TO_EMPTY); } - String[] parsedArgs = CommandParser.parseArguments(args, "(.+)\\s/from\\s(.+)\\s/to\\s(.+)"); + String[] parsedArgs = CommandParser.parseArguments(args, REGEX_PARSE); checkForbiddenCharacters(parsedArgs); name = parsedArgs[0]; from = parsedArgs[1]; to = parsedArgs[2]; } + @Override + protected String getType() { + return TYPE; + } + @Override protected String getUsage() { - return "event ((name)) /from ((start)) /to ((end))"; + return USAGE; } @Override diff --git a/src/main/java/nuke/command/ListCommand.java b/src/main/java/nuke/command/ListCommand.java index a4e6ff210..8327b153f 100644 --- a/src/main/java/nuke/command/ListCommand.java +++ b/src/main/java/nuke/command/ListCommand.java @@ -4,6 +4,8 @@ import nuke.Nuke; public class ListCommand extends Command { + public static final String TYPE = "list"; + private static final String USAGE = TYPE; @Override public void applyArguments(String args) throws InvalidCommandArgumentException { @@ -12,9 +14,14 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { } } + @Override + protected String getType() { + return TYPE; + } + @Override protected String getUsage() { - return "list"; + return USAGE; } @Override diff --git a/src/main/java/nuke/command/MarkCommand.java b/src/main/java/nuke/command/MarkCommand.java index 8ec1bcdf5..0bfe41ae6 100644 --- a/src/main/java/nuke/command/MarkCommand.java +++ b/src/main/java/nuke/command/MarkCommand.java @@ -4,6 +4,9 @@ import nuke.Nuke; public class MarkCommand extends Command { + public static final String TYPE = "mark"; + private static final String USAGE = TYPE + " ((index))"; + private int index; @Override @@ -19,9 +22,14 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { } } + @Override + protected String getType() { + return TYPE; + } + @Override protected String getUsage() { - return "mark ((index))"; + return USAGE; } @Override diff --git a/src/main/java/nuke/command/TodoCommand.java b/src/main/java/nuke/command/TodoCommand.java index fa5a51388..2317d272f 100644 --- a/src/main/java/nuke/command/TodoCommand.java +++ b/src/main/java/nuke/command/TodoCommand.java @@ -4,6 +4,9 @@ import nuke.Nuke; public class TodoCommand extends Command { + public static final String TYPE = "todo"; + private static final String USAGE = TYPE + " ((name))"; + public String name; @Override @@ -15,9 +18,14 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { name = args; } + @Override + protected String getType() { + return TYPE; + } + @Override protected String getUsage() { - return "todo ((name))"; + return USAGE; } @Override diff --git a/src/main/java/nuke/command/UnmarkCommand.java b/src/main/java/nuke/command/UnmarkCommand.java index cd09108f3..09a52e013 100644 --- a/src/main/java/nuke/command/UnmarkCommand.java +++ b/src/main/java/nuke/command/UnmarkCommand.java @@ -4,6 +4,9 @@ import nuke.Nuke; public class UnmarkCommand extends Command { + public static final String TYPE = "unmark"; + private static final String USAGE = TYPE + " ((index))"; + private int index; @Override @@ -19,9 +22,14 @@ public void applyArguments(String args) throws InvalidCommandArgumentException { } } + @Override + protected String getType() { + return TYPE; + } + @Override protected String getUsage() { - return "unmark ((index))"; + return USAGE; } @Override diff --git a/src/main/java/nuke/storage/Storage.java b/src/main/java/nuke/storage/Storage.java index 697069eb9..17893e899 100644 --- a/src/main/java/nuke/storage/Storage.java +++ b/src/main/java/nuke/storage/Storage.java @@ -1,6 +1,5 @@ package nuke.storage; -import nuke.Nuke; import nuke.storage.exception.TaskFileCopyException; import nuke.storage.exception.TaskLoadException; import nuke.storage.exception.TaskParseException; @@ -8,8 +7,13 @@ import nuke.task.Task; import nuke.task.TaskParser; -import java.io.*; -import java.nio.file.*; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Scanner; diff --git a/src/main/java/nuke/task/TaskList.java b/src/main/java/nuke/task/TaskList.java index 7266c270c..c88b7d4aa 100644 --- a/src/main/java/nuke/task/TaskList.java +++ b/src/main/java/nuke/task/TaskList.java @@ -1,62 +1,52 @@ package nuke.task; -import nuke.Ui; - import java.util.ArrayList; public class TaskList { - private final ArrayList tasks; + private final ArrayList TASKS; public TaskList() { this(new ArrayList<>()); } public TaskList(ArrayList tasks) { - this.tasks = tasks; + this.TASKS = tasks; } public void add(Task task) { - tasks.add(task); + TASKS.add(task); } public String mark(int idx) { - Task task = tasks.get(idx); + Task task = TASKS.get(idx); task.setDone(true); return task.toString(); } public String unmark(int idx) { - Task task = tasks.get(idx); + Task task = TASKS.get(idx); task.setDone(false); return task.toString(); } public String delete(int idx) { - Task task = tasks.remove(idx); + Task task = TASKS.remove(idx); return task.toString(); } - public void addTodo(String name) { - add(new Todo(name)); - } - - public void addDeadline(String name, String by) { - add(new Deadline(name, by)); - } - - public void addEvent(String name, String from, String to) { - add(new Event(name, from, to)); - } - public int size() { - return tasks.size(); + return TASKS.size(); } public String[] getTasks() { - return tasks.stream().map(Task::toString).toArray(String[]::new); + return TASKS.stream() + .map(Task::toString) + .toArray(String[]::new); } public String[] getFormattedTasks() { - return tasks.stream().map(Task::formatData).toArray(String[]::new); + return TASKS.stream() + .map(Task::formatData) + .toArray(String[]::new); } } From 7d860b159bb79891987a59a32f45da43cda80063 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Wed, 20 Sep 2023 14:12:51 +0800 Subject: [PATCH 36/52] Fix command type error detail --- src/main/java/nuke/Ui.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/nuke/Ui.java b/src/main/java/nuke/Ui.java index 5d33efcd7..09c554f31 100644 --- a/src/main/java/nuke/Ui.java +++ b/src/main/java/nuke/Ui.java @@ -89,7 +89,7 @@ public void printCommandError(String description, String detail) { public void printCommandTypeError(InvalidCommandTypeException e) { String desc = String.format("There is no command called '%s'.", e.type); - String detail = "Existing command: bye, list, mark, unmark, todo, deadline, event"; + String detail = "Existing command: bye, list, mark, unmark, todo, deadline, event, delete"; printCommandError(desc, detail); } From 056fcabe1be4c759da5d5fed05b072067dcf6b9a Mon Sep 17 00:00:00 2001 From: ICubE- Date: Wed, 20 Sep 2023 14:22:15 +0800 Subject: [PATCH 37/52] Update .gitignore --- .gitignore | 1 - src/main/java/META-INF/MANIFEST.MF | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 src/main/java/META-INF/MANIFEST.MF diff --git a/.gitignore b/.gitignore index d686beb48..6690f772d 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,3 @@ bin/ text-ui-test/EXPECTED-UNIX.TXT /data/ /text-ui-test/data/ -/src/main/java/META-INF/ diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 000000000..940e1c023 --- /dev/null +++ b/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 0.1 +Main-Class: nuke.Nuke + From 1651817cccf974cd441ea54708683d52d3c191e5 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Wed, 20 Sep 2023 14:39:06 +0800 Subject: [PATCH 38/52] Rename and remove some methods --- src/main/java/nuke/Nuke.java | 20 ++++++------------- src/main/java/nuke/command/DeleteCommand.java | 2 +- src/main/java/nuke/command/MarkCommand.java | 2 +- src/main/java/nuke/command/UnmarkCommand.java | 2 +- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/main/java/nuke/Nuke.java b/src/main/java/nuke/Nuke.java index c4665886f..7cac96c2c 100644 --- a/src/main/java/nuke/Nuke.java +++ b/src/main/java/nuke/Nuke.java @@ -77,9 +77,9 @@ private void runCommand(String commandLine) { private void saveTasksToStorage(Storage storage, Ui ui) { try { - storage.saveTasks(getFormattedTasks()); + storage.saveTasks(tasks.getFormattedTasks()); } catch (TaskSaveException e) { - e.tasks = getTasks(); + e.tasks = tasks.getTasks(); ui.handleTaskSaveError(e); } } @@ -91,11 +91,11 @@ public void quit() { public void addTask(Task task) { tasks.add(task); - ui.printAddedTask(task.toString(), getNumberOfTasks()); + ui.printAddedTask(task.toString(), countTasks()); } public void listTask() { - ui.printListOfTasks(getTasks()); + ui.printListOfTasks(tasks.getTasks()); } public void markTask(int idx) { @@ -110,7 +110,7 @@ public void unmarkTask(int idx) { public void deleteTask(int idx) { String task = tasks.delete(idx); - ui.printDeletedTask(task, getNumberOfTasks()); + ui.printDeletedTask(task, countTasks()); } public void addTodo(String name) { @@ -125,15 +125,7 @@ public void addEvent(String name, String from, String to) { addTask(new Event(name, from, to)); } - public int getNumberOfTasks() { + public int countTasks() { return tasks.size(); } - - public String[] getTasks() { - return tasks.getTasks(); - } - - public String[] getFormattedTasks() { - return tasks.getFormattedTasks(); - } } diff --git a/src/main/java/nuke/command/DeleteCommand.java b/src/main/java/nuke/command/DeleteCommand.java index 68c92843a..115c3e773 100644 --- a/src/main/java/nuke/command/DeleteCommand.java +++ b/src/main/java/nuke/command/DeleteCommand.java @@ -34,7 +34,7 @@ protected String getUsage() { @Override public void run(Nuke nuke) throws InvalidCommandArgumentException { - if(index < 0 || index >= nuke.getNumberOfTasks()) { + if(index < 0 || index >= nuke.countTasks()) { throwArgumentException(ERROR_MSG_INDEX_INVALID_VALUE); } nuke.deleteTask(index); diff --git a/src/main/java/nuke/command/MarkCommand.java b/src/main/java/nuke/command/MarkCommand.java index 0bfe41ae6..70368e147 100644 --- a/src/main/java/nuke/command/MarkCommand.java +++ b/src/main/java/nuke/command/MarkCommand.java @@ -34,7 +34,7 @@ protected String getUsage() { @Override public void run(Nuke nuke) throws InvalidCommandArgumentException { - if(index < 0 || index >= nuke.getNumberOfTasks()) { + if(index < 0 || index >= nuke.countTasks()) { throwArgumentException(ERROR_MSG_INDEX_INVALID_VALUE); } nuke.markTask(index); diff --git a/src/main/java/nuke/command/UnmarkCommand.java b/src/main/java/nuke/command/UnmarkCommand.java index 09a52e013..708357439 100644 --- a/src/main/java/nuke/command/UnmarkCommand.java +++ b/src/main/java/nuke/command/UnmarkCommand.java @@ -34,7 +34,7 @@ protected String getUsage() { @Override public void run(Nuke nuke) throws InvalidCommandArgumentException { - if(index < 0 || index >= nuke.getNumberOfTasks()) { + if(index < 0 || index >= nuke.countTasks()) { throwArgumentException(ERROR_MSG_INDEX_INVALID_VALUE); } nuke.unmarkTask(index); From 2cdf203a5a351c10de5e4b7abeadf3209f4786b0 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Wed, 20 Sep 2023 14:53:48 +0800 Subject: [PATCH 39/52] Rename some variables --- src/main/java/nuke/Nuke.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/nuke/Nuke.java b/src/main/java/nuke/Nuke.java index 7cac96c2c..fec7d1d30 100644 --- a/src/main/java/nuke/Nuke.java +++ b/src/main/java/nuke/Nuke.java @@ -99,18 +99,18 @@ public void listTask() { } public void markTask(int idx) { - String task = tasks.mark(idx); - ui.printMarkedTask(task); + String markedTask = tasks.mark(idx); + ui.printMarkedTask(markedTask); } public void unmarkTask(int idx) { - String task = tasks.unmark(idx); - ui.printUnmarkedTask(task); + String unmarkedTask = tasks.unmark(idx); + ui.printUnmarkedTask(unmarkedTask); } public void deleteTask(int idx) { - String task = tasks.delete(idx); - ui.printDeletedTask(task, countTasks()); + String deletedTask = tasks.delete(idx); + ui.printDeletedTask(deletedTask, countTasks()); } public void addTodo(String name) { From ff41ef86675a1eafb0568d3bcb96c02927bc187a Mon Sep 17 00:00:00 2001 From: ICubE- Date: Wed, 20 Sep 2023 14:54:55 +0800 Subject: [PATCH 40/52] Complete Level-9 Add find command --- src/main/java/nuke/Nuke.java | 5 +++ src/main/java/nuke/Ui.java | 13 ++++++- src/main/java/nuke/command/CommandParser.java | 3 ++ src/main/java/nuke/command/FindCommand.java | 38 +++++++++++++++++++ src/main/java/nuke/task/TaskList.java | 7 ++++ 5 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/main/java/nuke/command/FindCommand.java diff --git a/src/main/java/nuke/Nuke.java b/src/main/java/nuke/Nuke.java index fec7d1d30..2fd2b056d 100644 --- a/src/main/java/nuke/Nuke.java +++ b/src/main/java/nuke/Nuke.java @@ -113,6 +113,11 @@ public void deleteTask(int idx) { ui.printDeletedTask(deletedTask, countTasks()); } + public void findTasks(String keyword) { + String[] foundTasks = tasks.find(keyword); + ui.printFoundTask(foundTasks); + } + public void addTodo(String name) { addTask(new Todo(name)); } diff --git a/src/main/java/nuke/Ui.java b/src/main/java/nuke/Ui.java index 09c554f31..749b894ff 100644 --- a/src/main/java/nuke/Ui.java +++ b/src/main/java/nuke/Ui.java @@ -82,6 +82,17 @@ public void printDeletedTask(String deletedTask, int taskCnt) { System.out.printf("[@] Now you have %d task%s in the list.\n", taskCnt, taskCnt == 1 ? "": "s"); } + public void printFoundTask(String[] foundTasks) { + if(foundTasks.length == 0) { + System.out.println("[@] There are no matching tasks in your list."); + return; + } + System.out.println("[@] Here are the matching tasks in your list:"); + for (int i = 0; i < foundTasks.length; i++) { + System.out.printf("%d.%s\n", i + 1, foundTasks[i]); + } + } + public void printCommandError(String description, String detail) { System.out.println("[@] Wrong input; " + description); System.out.println("[@] " + detail); @@ -89,7 +100,7 @@ public void printCommandError(String description, String detail) { public void printCommandTypeError(InvalidCommandTypeException e) { String desc = String.format("There is no command called '%s'.", e.type); - String detail = "Existing command: bye, list, mark, unmark, todo, deadline, event, delete"; + String detail = "Existing command: bye, list, mark, unmark, todo, deadline, event, delete, find"; printCommandError(desc, detail); } diff --git a/src/main/java/nuke/command/CommandParser.java b/src/main/java/nuke/command/CommandParser.java index e3552209d..45b1cc856 100644 --- a/src/main/java/nuke/command/CommandParser.java +++ b/src/main/java/nuke/command/CommandParser.java @@ -50,6 +50,9 @@ private static Command getBlankCommand(String type) case DeleteCommand.TYPE: command = new DeleteCommand(); break; + case FindCommand.TYPE: + command = new FindCommand(); + break; default: throw new InvalidCommandTypeException(type); } diff --git a/src/main/java/nuke/command/FindCommand.java b/src/main/java/nuke/command/FindCommand.java new file mode 100644 index 000000000..92bc6ac56 --- /dev/null +++ b/src/main/java/nuke/command/FindCommand.java @@ -0,0 +1,38 @@ +package nuke.command; + +import nuke.Nuke; +import nuke.command.exception.InvalidCommandArgumentException; + +public class FindCommand extends Command { + public static final String TYPE = "find"; + private static final String USAGE = TYPE + " ((keyword))"; + + public String keyword; + + @Override + public void applyArguments(String args) throws InvalidCommandArgumentException { + if (args.isEmpty()) { + throwArgumentException(ERROR_MSG_NO_ARGS); + } + checkForbiddenCharacters(new String[]{args}); + keyword = args; + } + + @Override + protected String getType() { + return TYPE; + } + + @Override + protected String getUsage() { + return USAGE; + } + + @Override + public void run(Nuke nuke) { + nuke.findTasks(keyword); + } + + private static final String ERROR_MSG_NO_ARGS = + "Command 'find' should have one argument, keyword for matching."; +} diff --git a/src/main/java/nuke/task/TaskList.java b/src/main/java/nuke/task/TaskList.java index c88b7d4aa..901111f8c 100644 --- a/src/main/java/nuke/task/TaskList.java +++ b/src/main/java/nuke/task/TaskList.java @@ -34,6 +34,13 @@ public String delete(int idx) { return task.toString(); } + public String[] find(String keyword) { + return TASKS.stream() + .filter(task -> task.getName().contains(keyword)) + .map(Task::toString) + .toArray(String[]::new); + } + public int size() { return TASKS.size(); } From 997db5976c96a4348eda9084dfbe0ccc749f3c27 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Wed, 20 Sep 2023 14:55:08 +0800 Subject: [PATCH 41/52] Update test case --- text-ui-test/EXPECTED.TXT | 10 ++++++++++ text-ui-test/input.txt | 3 +++ 2 files changed, 13 insertions(+) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 43e534c61..3bd3d6a12 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -188,5 +188,15 @@ 2.[D][ ] return book (by: June 6th) 3.[E][ ] project meeting (from: Aug 6th 2pm to: 4pm) +[@] Wrong input; Command 'find' should have one argument, keyword for matching. +[@] Usage: find ((keyword)) + +[@] Wrong input; Command 'find' should not contain '/' in arguments. +[@] Usage: find ((keyword)) + +[@] Here are the matching tasks in your list: +1.[T][X] read book +2.[D][ ] return book (by: June 6th) + [@] Bye. Hope to see you again soon! diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index c91df3135..24adb560f 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -52,4 +52,7 @@ delete 0 delete 5 delete 4 list +find +find bo/ok +find book bye From 250bf612510ba7d0ecd533e564062a06a53241a9 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Thu, 21 Sep 2023 16:28:31 +0800 Subject: [PATCH 42/52] Add NukeDateTime NukeDataTime supports both String and LocalDateTime for time variants --- src/main/java/nuke/NukeDateTime.java | 91 +++++++++++++++++++++++++++ src/main/java/nuke/task/Deadline.java | 10 ++- src/main/java/nuke/task/Event.java | 14 +++-- text-ui-test/EXPECTED.TXT | 15 +++++ text-ui-test/input.txt | 3 + 5 files changed, 124 insertions(+), 9 deletions(-) create mode 100644 src/main/java/nuke/NukeDateTime.java diff --git a/src/main/java/nuke/NukeDateTime.java b/src/main/java/nuke/NukeDateTime.java new file mode 100644 index 000000000..19d7f9d10 --- /dev/null +++ b/src/main/java/nuke/NukeDateTime.java @@ -0,0 +1,91 @@ +package nuke; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoField; +import java.util.Locale; + +public class NukeDateTime { + private boolean isUsingLocalDateTime; + private LocalDateTime localDateTime; + private String string; + + public NukeDateTime(String dateTime) { + try { + localDateTime = parseDateTime(dateTime); + isUsingLocalDateTime = true; + string = toString(); + } catch (NukeException e) { + localDateTime = null; + isUsingLocalDateTime = false; + string = dateTime; + } + } + + @Override + public String toString() { + if (isUsingLocalDateTime) { + return localDateTime.format( + DateTimeFormatter.ofPattern("MMM dd yyyy, HH:mm", Locale.US) + ); + } else { + return string; + } + } + + private LocalDateTime parseDateTime(String dateTime) throws NukeException { + // Tries to parse using 10 different formats. + // ISO_DATE; yyyy-MM-dd with optional offset + // MM-dd + // ISO_TIME; HH:mm:ss or HH:mm with optional offset + // ISO_DATE_TIME; yyyy-MM-dd'T'HH:mm:ss or yyyy-MM-dd'T'HH:mm with optional offset + // yyyy-MM-dd HH:mm:ss + // yyyy-MM-dd HH:mm + // MM-dd HH:mm:ss + // MM-dd HH:mm + // d/M/y HHmm + // d/M/y + try { + return LocalDate.parse(dateTime, DateTimeFormatter.ISO_DATE).atStartOfDay(); + } catch (DateTimeParseException ignored) { } + try { + return LocalDate.parse(dateTime, createFormatterWithoutYear("MM-dd")).atStartOfDay(); + } catch (DateTimeParseException ignored) { } + try { + return LocalTime.parse(dateTime, DateTimeFormatter.ISO_TIME).atDate(LocalDate.now()); + } catch (DateTimeParseException ignored) { } + try { + return LocalDateTime.parse(dateTime, DateTimeFormatter.ISO_DATE_TIME); + } catch (DateTimeParseException ignored) { } + try { + return LocalDateTime.parse(dateTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + } catch (DateTimeParseException ignored) { } + try { + return LocalDateTime.parse(dateTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")); + } catch (DateTimeParseException ignored) { } + try { + return LocalDateTime.parse(dateTime, createFormatterWithoutYear("MM-dd HH:mm:ss")); + } catch (DateTimeParseException ignored) { } + try { + return LocalDateTime.parse(dateTime, createFormatterWithoutYear("MM-dd HH:mm")); + } catch (DateTimeParseException ignored) { } + try { + return LocalDateTime.parse(dateTime, DateTimeFormatter.ofPattern("d/M/y HHmm")); + } catch (DateTimeParseException ignored) { } + try { + return LocalDate.parse(dateTime, DateTimeFormatter.ofPattern("d/M/y")).atStartOfDay(); + } catch (DateTimeParseException ignored) { } + throw new NukeException(); + } + + private static DateTimeFormatter createFormatterWithoutYear(String pattern) { + return new DateTimeFormatterBuilder() + .appendPattern(pattern) + .parseDefaulting(ChronoField.YEAR, LocalDate.now().getYear()) + .toFormatter(); + } +} diff --git a/src/main/java/nuke/task/Deadline.java b/src/main/java/nuke/task/Deadline.java index 4f72b12f2..38b5527bb 100644 --- a/src/main/java/nuke/task/Deadline.java +++ b/src/main/java/nuke/task/Deadline.java @@ -1,7 +1,11 @@ package nuke.task; +import nuke.NukeDateTime; + +import java.time.LocalDateTime; + public class Deadline extends Task { - private String by; + private NukeDateTime by; public Deadline(String name, String by) { super(name); @@ -9,11 +13,11 @@ public Deadline(String name, String by) { } public String getBy() { - return by; + return by.toString(); } public void setBy(String by) { - this.by = by; + this.by = new NukeDateTime(by); } @Override diff --git a/src/main/java/nuke/task/Event.java b/src/main/java/nuke/task/Event.java index ef2eb2524..2afa6a4d1 100644 --- a/src/main/java/nuke/task/Event.java +++ b/src/main/java/nuke/task/Event.java @@ -1,8 +1,10 @@ package nuke.task; +import nuke.NukeDateTime; + public class Event extends Task { - private String from; - private String to; + private NukeDateTime from; + private NukeDateTime to; public Event(String name, String from, String to) { super(name); @@ -11,19 +13,19 @@ public Event(String name, String from, String to) { } public String getFrom() { - return from; + return from.toString(); } public void setFrom(String from) { - this.from = from; + this.from = new NukeDateTime(from); } public String getTo() { - return to; + return to.toString(); } public void setTo(String to) { - this.to = to; + this.to = new NukeDateTime(to); } @Override diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 43e534c61..f2c502a6b 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -188,5 +188,20 @@ 2.[D][ ] return book (by: June 6th) 3.[E][ ] project meeting (from: Aug 6th 2pm to: 4pm) +[@] Got it. I've added this task: + [D][ ] dtTest (by: Sep 21 2023, 16:24) +[@] Now you have 4 tasks in the list. + +[@] Got it. I've added this task: + [E][ ] dtTest (from: Sep 22 2023, 00:00 to: Sep 23 2023, 00:00) +[@] Now you have 5 tasks in the list. + +[@] Here are the tasks in your list: +1.[T][X] read book +2.[D][ ] return book (by: June 6th) +3.[E][ ] project meeting (from: Aug 6th 2pm to: 4pm) +4.[D][ ] dtTest (by: Sep 21 2023, 16:24) +5.[E][ ] dtTest (from: Sep 22 2023, 00:00 to: Sep 23 2023, 00:00) + [@] Bye. Hope to see you again soon! diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index c91df3135..12761ef57 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -52,4 +52,7 @@ delete 0 delete 5 delete 4 list +deadline dtTest /by 2023-09-21 16:24 +event dtTest /from 09-22 /to 09-23 +list bye From 0d21b620183861aa774bbd133427b9c4330e5ee1 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Thu, 21 Sep 2023 16:44:23 +0800 Subject: [PATCH 43/52] Add exception and minor format --- src/main/java/nuke/NukeDateTime.java | 56 +++++++++++++++---- .../java/nuke/NukeDateTimeParseException.java | 4 ++ 2 files changed, 48 insertions(+), 12 deletions(-) create mode 100644 src/main/java/nuke/NukeDateTimeParseException.java diff --git a/src/main/java/nuke/NukeDateTime.java b/src/main/java/nuke/NukeDateTime.java index 19d7f9d10..a1b92cb07 100644 --- a/src/main/java/nuke/NukeDateTime.java +++ b/src/main/java/nuke/NukeDateTime.java @@ -37,7 +37,8 @@ public String toString() { } } - private LocalDateTime parseDateTime(String dateTime) throws NukeException { + public static LocalDateTime parseDateTime(String dateTime) + throws NukeDateTimeParseException { // Tries to parse using 10 different formats. // ISO_DATE; yyyy-MM-dd with optional offset // MM-dd @@ -50,36 +51,67 @@ private LocalDateTime parseDateTime(String dateTime) throws NukeException { // d/M/y HHmm // d/M/y try { - return LocalDate.parse(dateTime, DateTimeFormatter.ISO_DATE).atStartOfDay(); + return LocalDate.parse( + dateTime, + DateTimeFormatter.ISO_DATE + ).atStartOfDay(); } catch (DateTimeParseException ignored) { } try { - return LocalDate.parse(dateTime, createFormatterWithoutYear("MM-dd")).atStartOfDay(); + return LocalDate.parse( + dateTime, + createFormatterWithoutYear("MM-dd") + ).atStartOfDay(); } catch (DateTimeParseException ignored) { } try { - return LocalTime.parse(dateTime, DateTimeFormatter.ISO_TIME).atDate(LocalDate.now()); + return LocalTime.parse( + dateTime, + DateTimeFormatter.ISO_TIME + ).atDate(LocalDate.now()); } catch (DateTimeParseException ignored) { } try { - return LocalDateTime.parse(dateTime, DateTimeFormatter.ISO_DATE_TIME); + return LocalDateTime.parse( + dateTime, + DateTimeFormatter.ISO_DATE_TIME + ); } catch (DateTimeParseException ignored) { } try { - return LocalDateTime.parse(dateTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + return LocalDateTime.parse( + dateTime, + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") + ); } catch (DateTimeParseException ignored) { } try { - return LocalDateTime.parse(dateTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")); + return LocalDateTime.parse( + dateTime, + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm") + ); } catch (DateTimeParseException ignored) { } try { - return LocalDateTime.parse(dateTime, createFormatterWithoutYear("MM-dd HH:mm:ss")); + return LocalDateTime.parse( + dateTime, + createFormatterWithoutYear("MM-dd HH:mm:ss") + ); } catch (DateTimeParseException ignored) { } try { - return LocalDateTime.parse(dateTime, createFormatterWithoutYear("MM-dd HH:mm")); + return LocalDateTime.parse( + dateTime, + createFormatterWithoutYear("MM-dd HH:mm") + ); } catch (DateTimeParseException ignored) { } try { - return LocalDateTime.parse(dateTime, DateTimeFormatter.ofPattern("d/M/y HHmm")); + return LocalDateTime.parse( + dateTime, + DateTimeFormatter.ofPattern("d/M/y HHmm") + ); } catch (DateTimeParseException ignored) { } try { - return LocalDate.parse(dateTime, DateTimeFormatter.ofPattern("d/M/y")).atStartOfDay(); + return LocalDate.parse( + dateTime, + DateTimeFormatter.ofPattern("d/M/y") + ).atStartOfDay(); } catch (DateTimeParseException ignored) { } - throw new NukeException(); + + throw new NukeDateTimeParseException(); } private static DateTimeFormatter createFormatterWithoutYear(String pattern) { diff --git a/src/main/java/nuke/NukeDateTimeParseException.java b/src/main/java/nuke/NukeDateTimeParseException.java new file mode 100644 index 000000000..4596169e7 --- /dev/null +++ b/src/main/java/nuke/NukeDateTimeParseException.java @@ -0,0 +1,4 @@ +package nuke; + +public class NukeDateTimeParseException extends NukeException { +} From 39e4000bf094207d3fd513f104d87234e6de723f Mon Sep 17 00:00:00 2001 From: ICubE- Date: Thu, 21 Sep 2023 16:44:59 +0800 Subject: [PATCH 44/52] Update NukeDateTime.java --- src/main/java/nuke/NukeDateTime.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/nuke/NukeDateTime.java b/src/main/java/nuke/NukeDateTime.java index a1b92cb07..e71c5256f 100644 --- a/src/main/java/nuke/NukeDateTime.java +++ b/src/main/java/nuke/NukeDateTime.java @@ -37,7 +37,7 @@ public String toString() { } } - public static LocalDateTime parseDateTime(String dateTime) + private LocalDateTime parseDateTime(String dateTime) throws NukeDateTimeParseException { // Tries to parse using 10 different formats. // ISO_DATE; yyyy-MM-dd with optional offset From 307adb300a061a0dd964f317cfd4cfeb96e95a9c Mon Sep 17 00:00:00 2001 From: ICubE- Date: Thu, 21 Sep 2023 20:30:11 +0800 Subject: [PATCH 45/52] Add JavaDoc comments --- src/main/java/nuke/Nuke.java | 67 ++++++++++++++++++- src/main/java/nuke/Ui.java | 19 ++++++ src/main/java/nuke/command/Command.java | 35 ++++++++++ src/main/java/nuke/command/CommandParser.java | 36 ++++++++++ src/main/java/nuke/storage/Storage.java | 16 +++++ src/main/java/nuke/task/Deadline.java | 20 ++++++ src/main/java/nuke/task/Event.java | 30 +++++++++ src/main/java/nuke/task/Task.java | 44 ++++++++++++ src/main/java/nuke/task/TaskList.java | 47 +++++++++++++ src/main/java/nuke/task/TaskParser.java | 10 +++ src/main/java/nuke/task/Todo.java | 8 +++ 11 files changed, 330 insertions(+), 2 deletions(-) diff --git a/src/main/java/nuke/Nuke.java b/src/main/java/nuke/Nuke.java index c4665886f..641dd9f13 100644 --- a/src/main/java/nuke/Nuke.java +++ b/src/main/java/nuke/Nuke.java @@ -14,6 +14,9 @@ import nuke.task.TaskList; import nuke.task.Todo; +/** + * Represents main part of Nuke. + */ public class Nuke { private final Storage storage; private final TaskList tasks; @@ -24,7 +27,7 @@ public static void main(String[] args) { new Nuke().run(); } - public Nuke() { + private Nuke() { ui = new Ui(); ui.printWelcome(); @@ -34,7 +37,7 @@ public Nuke() { isRunning = true; } - public void run() { + private void run() { ui.printGreetingQuestion(); // Loop for user input @@ -84,55 +87,115 @@ private void saveTasksToStorage(Storage storage, Ui ui) { } } + /** + * Makes Nuke to quit. + */ public void quit() { isRunning = false; ui.printBye(); } + /** + * Adds the task. + * + * @param task task to add + */ public void addTask(Task task) { tasks.add(task); ui.printAddedTask(task.toString(), getNumberOfTasks()); } + /** + * Lists all tasks. + */ public void listTask() { ui.printListOfTasks(getTasks()); } + /** + * Marks the task of the index as done. + * + * @param idx index of the task to be marked done + */ public void markTask(int idx) { String task = tasks.mark(idx); ui.printMarkedTask(task); } + /** + * Marks the task of the index as not done. + * + * @param idx index of the task to be marked not done + */ public void unmarkTask(int idx) { String task = tasks.unmark(idx); ui.printUnmarkedTask(task); } + /** + * Deletes the task of the index. + * + * @param idx index of the task to be deleted + */ public void deleteTask(int idx) { String task = tasks.delete(idx); ui.printDeletedTask(task, getNumberOfTasks()); } + /** + * Adds {@link Todo}. + * + * @param name name of {@link Todo} to be added + */ public void addTodo(String name) { addTask(new Todo(name)); } + /** + * Adds {@link Deadline}. + * + * @param name name of {@link Deadline} to be added + * @param by deadline of {@link Deadline} to be added + */ public void addDeadline(String name, String by) { addTask(new Deadline(name, by)); } + /** + * Adds {@link Event}. + * + * @param name name of {@link Event} to be added + * @param from start period of {@link Event} to be added + * @param to end period of {@link Event} to be added + */ public void addEvent(String name, String from, String to) { addTask(new Event(name, from, to)); } + /** + * Returns the number of the tasks. + * + * @return the number of the tasks + */ public int getNumberOfTasks() { return tasks.size(); } + /** + * Returns string representations of all tasks. + * + * @return all tasks in form of {@link String}[]. + */ public String[] getTasks() { return tasks.getTasks(); } + /** + * Returns all tasks in form of formatted manner, + * which is used to save in file. + * + * @return all tasks in form of formatted manner. + */ public String[] getFormattedTasks() { return tasks.getFormattedTasks(); } diff --git a/src/main/java/nuke/Ui.java b/src/main/java/nuke/Ui.java index 09c554f31..4f84724a4 100644 --- a/src/main/java/nuke/Ui.java +++ b/src/main/java/nuke/Ui.java @@ -8,23 +8,42 @@ import java.util.Scanner; +/** + * Represents UI of Nuke. + */ public class Ui { private final String IGNORE_ERROR_COMMAND = "ignore"; private final Scanner USER_IN; + /** + * Constructs UI of Nuke. + */ public Ui() { USER_IN = new Scanner(System.in); } + /** + * Scans a line from user input. + * + * @return user input as a line of string + */ public String scanNextLine() { return USER_IN.nextLine(); } + /** + * Returns if user inputs to ignore error. + * + * @return if the user input equals to the {@code IGNORE_ERROR_COMMAND}. + */ public boolean scanIgnore() { return scanNextLine().equals(IGNORE_ERROR_COMMAND); } + /** + * Scans until user input is not empty. + */ public void scanWhileEmpty() { //noinspection StatementWithEmptyBody while (scanNextLine().isEmpty()); diff --git a/src/main/java/nuke/command/Command.java b/src/main/java/nuke/command/Command.java index 9e6812ac0..9d8025a37 100644 --- a/src/main/java/nuke/command/Command.java +++ b/src/main/java/nuke/command/Command.java @@ -5,16 +5,46 @@ import java.util.Arrays; +/** + * Represents command which can be input by users. + */ public abstract class Command { + /** + * Parses arguments and then applies the result to set the values. + * @param args command argument + * @throws InvalidCommandArgumentException if parsing argument fails + */ public abstract void applyArguments(String args) throws InvalidCommandArgumentException; + /** + * Returns the type of the command. + * + * @return the type of the command. + */ protected abstract String getType(); + /** + * Returns the usage of the command. + * + * @return the usage of the command. + */ protected abstract String getUsage(); + /** + * Runs the command. + * + * @param nuke the Nuke which is running this command. + * @throws InvalidCommandArgumentException if running fails due to one or more arguments + */ public abstract void run(Nuke nuke) throws InvalidCommandArgumentException; + /** + * Checks if one of forbidden characters exists, + * and throws exception if it does. + * @param parsedArgs array of parsed arguments + * @throws InvalidCommandArgumentException if one of forbidden characters exists in the arguments + */ protected void checkForbiddenCharacters(String[] parsedArgs) throws InvalidCommandArgumentException { if (Arrays.stream(parsedArgs).anyMatch(s -> s.contains(FORBIDDEN_CHARACTERS))) { @@ -23,6 +53,11 @@ protected void checkForbiddenCharacters(String[] parsedArgs) } } + /** + * Throws an argument exception. + * @param reason reason of the exception + * @throws InvalidCommandArgumentException with a reason and the usage of the command + */ protected void throwArgumentException(String reason) throws InvalidCommandArgumentException { throw new InvalidCommandArgumentException(reason, "Usage: " + getUsage()); diff --git a/src/main/java/nuke/command/CommandParser.java b/src/main/java/nuke/command/CommandParser.java index e3552209d..cef20560e 100644 --- a/src/main/java/nuke/command/CommandParser.java +++ b/src/main/java/nuke/command/CommandParser.java @@ -7,7 +7,18 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +/** + * Represents parser of commands. + */ public class CommandParser { + + /** + * Parses a line of command into {@link Command} and returns it. + * @param commandLine string of command + * @return command; result of parsing + * @throws InvalidCommandTypeException if type of command is invalid + * @throws InvalidCommandArgumentException if one or more arguments of command are invalid + */ public static Command parseCommand(String commandLine) throws InvalidCommandTypeException, InvalidCommandArgumentException { // Get command type and arguments. @@ -64,23 +75,48 @@ private static String getCommandArguments(String commandLine, String type) { return commandLine.substring(type.length()).strip(); } + /** + * Returns if the string is one word. + * @param str string + * @return if the string is not one word. + */ public static boolean isNotOneWord(String str) { if (str.isEmpty()) { return true; } else return str.split(REGEX_WHITESPACE).length != 1; } + /** + * Returns if the string is not containing exact one label + * @param str string + * @param label label + * @return if the string is not containing exact one label + */ public static boolean isNotContainingExactOneLabel(String str, String label) { String[] argSplit = str.split(REGEX_WHITESPACE); long labelCnt = Arrays.stream(argSplit).filter(a -> a.equals(label)).count(); return labelCnt != 1; } + /** + * Returns if the string matches the regular expression. + * @param str string + * @param regex regular expression + * @return if the string matches the regular expression + */ public static boolean matches(String str, String regex) { Matcher matcher = Pattern.compile(regex).matcher(str); return matcher.matches(); } + /** + * Parses the arguments using the regular expression and returns them. + * Arguments in the regular expression has to in the group. + * + * @param args arguments + * @param regex regular expression + * @return parsed arguments + */ public static String[] parseArguments(String args, String regex) { String[] parsedArgs; diff --git a/src/main/java/nuke/storage/Storage.java b/src/main/java/nuke/storage/Storage.java index 17893e899..484e549a8 100644 --- a/src/main/java/nuke/storage/Storage.java +++ b/src/main/java/nuke/storage/Storage.java @@ -17,11 +17,21 @@ import java.util.ArrayList; import java.util.Scanner; +/** + * Represents storage of Nuke. + */ public class Storage { private static final String DIR_DATA = "data"; private static final String FILENAME_TASKS = "nuke.txt"; private static final String FILENAME_TASKS_BACKUP = "nuke_old.txt"; + /** + * Loads saved tasks from the designated file. + * + * @return list of saved tasks + * @throws TaskLoadException if loading the tasks fails + * @throws TaskFileCopyException if both loading the tasks and backing up the file fails + */ public ArrayList loadTasks() throws TaskLoadException, TaskFileCopyException { ArrayList loadedTasks = new ArrayList<>(); @@ -53,6 +63,12 @@ public ArrayList loadTasks() return loadedTasks; } + /** + * Saves the tasks to the designated file. + * + * @param formattedTasks tasks formatted to save. + * @throws TaskSaveException if saving the tasks fails + */ public void saveTasks(String[] formattedTasks) throws TaskSaveException { Path currentRelativePath = Paths.get(""); Path currentDir = currentRelativePath.toAbsolutePath(); diff --git a/src/main/java/nuke/task/Deadline.java b/src/main/java/nuke/task/Deadline.java index 4f72b12f2..e592b6a71 100644 --- a/src/main/java/nuke/task/Deadline.java +++ b/src/main/java/nuke/task/Deadline.java @@ -1,17 +1,37 @@ package nuke.task; +/** + * Represents a task that has a deadline. + */ public class Deadline extends Task { private String by; + /** + * Constructs a task that has a deadline, + * with the name and the deadline. + * + * @param name name of the task. + * @param by deadline of the task. + */ public Deadline(String name, String by) { super(name); setBy(by); } + /** + * Returns deadline of the task. + * + * @return deadline of the task + */ public String getBy() { return by; } + /** + * Sets deadline of the task. + * + * @param by deadline of the task + */ public void setBy(String by) { this.by = by; } diff --git a/src/main/java/nuke/task/Event.java b/src/main/java/nuke/task/Event.java index ef2eb2524..17e401428 100644 --- a/src/main/java/nuke/task/Event.java +++ b/src/main/java/nuke/task/Event.java @@ -1,27 +1,57 @@ package nuke.task; +/** + * Represents an event that has the start and the end. + */ public class Event extends Task { private String from; private String to; + /** + * Constructs an event with the name, the start period, and the end period. + * + * @param name name of the task. + * @param from start period of the task. + * @param to end period of the task. + */ public Event(String name, String from, String to) { super(name); setFrom(from); setTo(to); } + /** + * Returns start period of the event. + * + * @return start period of the event + */ public String getFrom() { return from; } + /** + * Sets start period of the event. + * + * @param from start period of the event + */ public void setFrom(String from) { this.from = from; } + /** + * Returns end period of the event. + * + * @return end period of the event + */ public String getTo() { return to; } + /** + * Sets end period of the event. + * + * @param to end period of the event + */ public void setTo(String to) { this.to = to; } diff --git a/src/main/java/nuke/task/Task.java b/src/main/java/nuke/task/Task.java index d5f7df8cb..70ea9a780 100644 --- a/src/main/java/nuke/task/Task.java +++ b/src/main/java/nuke/task/Task.java @@ -1,38 +1,82 @@ package nuke.task; +/** + * Represents a task. + */ public abstract class Task { private String name; private boolean isDone; + /** + * Constructs a task with the name. + * + * @param name name of the task + */ public Task(String name) { setName(name); setDone(false); } + /** + * Returns name of the task. + * + * @return name of the task + */ public String getName() { return name; } + /** + * Sets name of the task. + * + * @param name name of the task + */ public void setName(String name) { this.name = name; } + /** + * Returns condition of the task if it is done or not. + * + * @return condition of the task + */ public boolean isDone() { return isDone; } + /** + * Sets condition of the task as done or not. + * + * @param done condition of the task + */ public void setDone(boolean done) { this.isDone = done; } + /** + * Returns type of the task. + * + * @return type of the task + */ public abstract String getType(); + /** + * Returns string representations of the task. + * + * @return string representations of the task + */ @Override public String toString() { String mark = isDone()? "X" : " "; return String.format("[%s][%s] %s", getType(), mark, getName()); } + /** + * Returns the task in form of formatted manner, + * which is used to save in file. + * + * @return the task in form of formatted manner. + */ public String formatData() { String mark = isDone()? "1" : "0"; return String.format("%s / %s / %s", getType(), mark, getName()); diff --git a/src/main/java/nuke/task/TaskList.java b/src/main/java/nuke/task/TaskList.java index c88b7d4aa..01f5e42f5 100644 --- a/src/main/java/nuke/task/TaskList.java +++ b/src/main/java/nuke/task/TaskList.java @@ -2,48 +2,95 @@ import java.util.ArrayList; +/** + * Represents a list of tasks. + */ public class TaskList { private final ArrayList TASKS; + /** + * Constructs an empty list of tasks. + */ public TaskList() { this(new ArrayList<>()); } + /** + * Constructs a list of tasks with all elements in {@code tasks}. + * + * @param tasks a list of tasks + */ public TaskList(ArrayList tasks) { this.TASKS = tasks; } + /** + * Adds the task in the list. + * + * @param task task to add + */ public void add(Task task) { TASKS.add(task); } + /** + * Marks the task of the index as done. + * + * @param idx index of the task to be marked done + */ public String mark(int idx) { Task task = TASKS.get(idx); task.setDone(true); return task.toString(); } + /** + * Marks the task of the index as not done. + * + * @param idx index of the task to be marked not done + */ public String unmark(int idx) { Task task = TASKS.get(idx); task.setDone(false); return task.toString(); } + /** + * Deletes the task of the index. + * + * @param idx index of the task to be deleted + */ public String delete(int idx) { Task task = TASKS.remove(idx); return task.toString(); } + /** + * Returns the size of the list. + * + * @return the size of the list + */ public int size() { return TASKS.size(); } + /** + * Returns string representations of all tasks. + * + * @return all tasks in form of {@link String}[]. + */ public String[] getTasks() { return TASKS.stream() .map(Task::toString) .toArray(String[]::new); } + /** + * Returns all tasks in form of formatted manner, + * which is used to save in file. + * + * @return all tasks in form of formatted manner. + */ public String[] getFormattedTasks() { return TASKS.stream() .map(Task::formatData) diff --git a/src/main/java/nuke/task/TaskParser.java b/src/main/java/nuke/task/TaskParser.java index a48d8e981..dd99165b5 100644 --- a/src/main/java/nuke/task/TaskParser.java +++ b/src/main/java/nuke/task/TaskParser.java @@ -2,8 +2,18 @@ import nuke.storage.exception.TaskParseException; +/** + * Parser that parses formatted tasks in the save file. + */ public class TaskParser { + /** + * Parses a line of string into {@link Task} and returns it. + * + * @param line string of formatted tasks + * @return task; result of parsing + * @throws TaskParseException if parse fails + */ public static Task parseTask(String line) throws TaskParseException { Task task; String[] words = line.split(" / "); diff --git a/src/main/java/nuke/task/Todo.java b/src/main/java/nuke/task/Todo.java index f641ae5ab..db6d813a0 100644 --- a/src/main/java/nuke/task/Todo.java +++ b/src/main/java/nuke/task/Todo.java @@ -1,7 +1,15 @@ package nuke.task; +/** + * Represents a task to do. + */ public class Todo extends Task { + /** + * Constructs a task to do with the name. + * + * @param name name of the task to do. + */ public Todo(String name) { super(name); } From 02b71e1a2d62f61739e8b62fa199a397f73599a2 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Thu, 21 Sep 2023 20:58:10 +0800 Subject: [PATCH 46/52] Change access modifiers of some variables --- src/main/java/nuke/command/DeadlineCommand.java | 4 ++-- src/main/java/nuke/command/EventCommand.java | 6 +++--- src/main/java/nuke/command/FindCommand.java | 2 +- src/main/java/nuke/command/TodoCommand.java | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/nuke/command/DeadlineCommand.java b/src/main/java/nuke/command/DeadlineCommand.java index 5363c5628..76a4bdf9e 100644 --- a/src/main/java/nuke/command/DeadlineCommand.java +++ b/src/main/java/nuke/command/DeadlineCommand.java @@ -11,8 +11,8 @@ public class DeadlineCommand extends Command { private static final String REGEX_BY_EMPTY = "(.+)\\s" + BY_LABEL; private static final String REGEX_PARSE = "(.+)\\s" + BY_LABEL + "\\s(.+)"; - public String name; - public String by; + private String name; + private String by; @Override public void applyArguments(String args) throws InvalidCommandArgumentException { diff --git a/src/main/java/nuke/command/EventCommand.java b/src/main/java/nuke/command/EventCommand.java index 9ae6bd987..755e245b9 100644 --- a/src/main/java/nuke/command/EventCommand.java +++ b/src/main/java/nuke/command/EventCommand.java @@ -17,9 +17,9 @@ public class EventCommand extends Command { private static final String REGEX_PARSE = "(.+)\\s" + FROM_LABEL + "\\s(.+)\\s" + TO_LABEL + "\\s(.+)"; - public String name; - public String from; - public String to; + private String name; + private String from; + private String to; @Override public void applyArguments(String args) throws InvalidCommandArgumentException { diff --git a/src/main/java/nuke/command/FindCommand.java b/src/main/java/nuke/command/FindCommand.java index 92bc6ac56..66f33d2ac 100644 --- a/src/main/java/nuke/command/FindCommand.java +++ b/src/main/java/nuke/command/FindCommand.java @@ -7,7 +7,7 @@ public class FindCommand extends Command { public static final String TYPE = "find"; private static final String USAGE = TYPE + " ((keyword))"; - public String keyword; + private String keyword; @Override public void applyArguments(String args) throws InvalidCommandArgumentException { diff --git a/src/main/java/nuke/command/TodoCommand.java b/src/main/java/nuke/command/TodoCommand.java index 2317d272f..2defa8faa 100644 --- a/src/main/java/nuke/command/TodoCommand.java +++ b/src/main/java/nuke/command/TodoCommand.java @@ -7,7 +7,7 @@ public class TodoCommand extends Command { public static final String TYPE = "todo"; private static final String USAGE = TYPE + " ((name))"; - public String name; + private String name; @Override public void applyArguments(String args) throws InvalidCommandArgumentException { From 5c4296fcc51ba5996cd246aa6f03e201f72f135a Mon Sep 17 00:00:00 2001 From: ICubE- Date: Thu, 21 Sep 2023 20:58:25 +0800 Subject: [PATCH 47/52] Update JavaDoc --- src/main/java/nuke/Nuke.java | 5 +++ src/main/java/nuke/NukeDateTime.java | 47 +++++++++++++++++++++------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/main/java/nuke/Nuke.java b/src/main/java/nuke/Nuke.java index e38c3b266..dc2f1f0fc 100644 --- a/src/main/java/nuke/Nuke.java +++ b/src/main/java/nuke/Nuke.java @@ -142,6 +142,11 @@ public void deleteTask(int idx) { ui.printDeletedTask(deletedTask, countTasks()); } + /** + * Finds tasks with the keyword. + * + * @param keyword keyword + */ public void findTasks(String keyword) { String[] foundTasks = tasks.find(keyword); ui.printFoundTask(foundTasks); diff --git a/src/main/java/nuke/NukeDateTime.java b/src/main/java/nuke/NukeDateTime.java index e71c5256f..de016664a 100644 --- a/src/main/java/nuke/NukeDateTime.java +++ b/src/main/java/nuke/NukeDateTime.java @@ -9,11 +9,20 @@ import java.time.temporal.ChronoField; import java.util.Locale; +/** + * Represents a chronological period. + * It supports both {@link String} and {@link LocalDateTime}. + */ public class NukeDateTime { private boolean isUsingLocalDateTime; private LocalDateTime localDateTime; private String string; + /** + * Constructs a period with a string. + * + * @param dateTime string indicating the period + */ public NukeDateTime(String dateTime) { try { localDateTime = parseDateTime(dateTime); @@ -26,6 +35,14 @@ public NukeDateTime(String dateTime) { } } + /** + * Returns a string representation of the period. + * The format is as following. + *

+ * 'MMM dd yyyy, HH:mm' + * + * @return a string representation of the period + */ @Override public String toString() { if (isUsingLocalDateTime) { @@ -37,19 +54,27 @@ public String toString() { } } + /** + * Parses the period from {@link String} to {@link LocalDateTime}. + * Tries to parse using 10 different formats. + *

+ * ISO_DATE; yyyy-MM-dd with optional offset
+ * MM-dd
+ * ISO_TIME; HH:mm:ss or HH:mm with optional offset
+ * ISO_DATE_TIME; yyyy-MM-dd'T'HH:mm:ss or yyyy-MM-dd'T'HH:mm with optional offset
+ * yyyy-MM-dd HH:mm:ss
+ * yyyy-MM-dd HH:mm
+ * MM-dd HH:mm:ss
+ * MM-dd HH:mm
+ * d/M/y HHmm
+ * d/M/y + * + * @param dateTime period + * @return parsed period + * @throws NukeDateTimeParseException if parsing fails + */ private LocalDateTime parseDateTime(String dateTime) throws NukeDateTimeParseException { - // Tries to parse using 10 different formats. - // ISO_DATE; yyyy-MM-dd with optional offset - // MM-dd - // ISO_TIME; HH:mm:ss or HH:mm with optional offset - // ISO_DATE_TIME; yyyy-MM-dd'T'HH:mm:ss or yyyy-MM-dd'T'HH:mm with optional offset - // yyyy-MM-dd HH:mm:ss - // yyyy-MM-dd HH:mm - // MM-dd HH:mm:ss - // MM-dd HH:mm - // d/M/y HHmm - // d/M/y try { return LocalDate.parse( dateTime, From fa8f273d31d0b3e03325e65fe79929f72ebc79ed Mon Sep 17 00:00:00 2001 From: ICubE- Date: Thu, 21 Sep 2023 21:17:11 +0800 Subject: [PATCH 48/52] Refactor TaskParser --- src/main/java/nuke/task/Deadline.java | 4 +-- src/main/java/nuke/task/Event.java | 6 +++- src/main/java/nuke/task/Task.java | 10 ++++-- src/main/java/nuke/task/TaskParser.java | 45 ++++++++++++++++--------- 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/main/java/nuke/task/Deadline.java b/src/main/java/nuke/task/Deadline.java index 85177ecb4..dcab78ced 100644 --- a/src/main/java/nuke/task/Deadline.java +++ b/src/main/java/nuke/task/Deadline.java @@ -2,7 +2,7 @@ import nuke.NukeDateTime; -import java.time.LocalDateTime; +import static nuke.task.TaskParser.TASK_FORMAT_SEPARATOR; /** * Represents a task that has a deadline. @@ -52,7 +52,7 @@ public String toString() { @Override public String formatData() { - return String.format("%s / %s", super.formatData(), getBy()); + return super.formatData() + TASK_FORMAT_SEPARATOR + getBy(); } public static final String TYPE = "D"; diff --git a/src/main/java/nuke/task/Event.java b/src/main/java/nuke/task/Event.java index 092241f8c..4f8449e82 100644 --- a/src/main/java/nuke/task/Event.java +++ b/src/main/java/nuke/task/Event.java @@ -2,6 +2,8 @@ import nuke.NukeDateTime; +import static nuke.task.TaskParser.TASK_FORMAT_SEPARATOR; + /** * Represents an event that has the start and the end. */ @@ -71,7 +73,9 @@ public String toString() { @Override public String formatData() { - return String.format("%s / %s / %s", super.formatData(), getFrom(), getTo()); + return super.formatData() + TASK_FORMAT_SEPARATOR + + getFrom() + TASK_FORMAT_SEPARATOR + + getTo(); } public static final String TYPE = "E"; diff --git a/src/main/java/nuke/task/Task.java b/src/main/java/nuke/task/Task.java index 70ea9a780..9312df0bb 100644 --- a/src/main/java/nuke/task/Task.java +++ b/src/main/java/nuke/task/Task.java @@ -1,5 +1,9 @@ package nuke.task; +import static nuke.task.TaskParser.TASK_FORMAT_MARKED; +import static nuke.task.TaskParser.TASK_FORMAT_SEPARATOR; +import static nuke.task.TaskParser.TASK_FORMAT_UNMARKED; + /** * Represents a task. */ @@ -78,7 +82,9 @@ public String toString() { * @return the task in form of formatted manner. */ public String formatData() { - String mark = isDone()? "1" : "0"; - return String.format("%s / %s / %s", getType(), mark, getName()); + String mark = isDone()? TASK_FORMAT_MARKED : TASK_FORMAT_UNMARKED; + return getType() + TASK_FORMAT_SEPARATOR + + mark + TASK_FORMAT_SEPARATOR + + getName(); } } diff --git a/src/main/java/nuke/task/TaskParser.java b/src/main/java/nuke/task/TaskParser.java index dd99165b5..f2d1d4037 100644 --- a/src/main/java/nuke/task/TaskParser.java +++ b/src/main/java/nuke/task/TaskParser.java @@ -2,51 +2,64 @@ import nuke.storage.exception.TaskParseException; +import java.util.Arrays; + /** * Parser that parses formatted tasks in the save file. */ public class TaskParser { + public static final String TASK_FORMAT_SEPARATOR = " / "; + public static final String TASK_FORMAT_MARKED = "1"; + public static final String TASK_FORMAT_UNMARKED = "0"; /** * Parses a line of string into {@link Task} and returns it. * - * @param line string of formatted tasks + * @param line string of a formatted task * @return task; result of parsing * @throws TaskParseException if parse fails */ public static Task parseTask(String line) throws TaskParseException { - Task task; - String[] words = line.split(" / "); + String[] words = line.split(TASK_FORMAT_SEPARATOR); if (words.length < 3) { throw new TaskParseException(); } + String type = words[0]; - boolean mark; - switch (words[1]) { - case "1": - mark = true; - break; - case "0": - mark = false; - break; + boolean mark = parseMark(words[1]); + String[] args = Arrays.copyOfRange(words, 2, words.length); + + Task task = parseArgs(type, args); + task.setDone(mark); + return task; + } + + private static boolean parseMark(String mark) throws TaskParseException { + switch (mark) { + case TASK_FORMAT_MARKED: + return true; + case TASK_FORMAT_UNMARKED: + return false; default: throw new TaskParseException(); } + } + + private static Task parseArgs(String type, String[] args) throws TaskParseException { + Task task; switch (type) { case Todo.TYPE: - task = new Todo(words[2]); + task = new Todo(args[0]); break; case Deadline.TYPE: - task = new Deadline(words[2], words[3]); + task = new Deadline(args[0], args[1]); break; case Event.TYPE: - task = new Event(words[2], words[3], words[4]); + task = new Event(args[0], args[1], args[2]); break; default: throw new TaskParseException(); } - task.setDone(mark); - return task; } } From 6e79886c4239c5ffc34f693de01139d2340226bb Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 30 Sep 2023 16:51:10 +0800 Subject: [PATCH 49/52] Update JavaDoc --- src/main/java/nuke/Ui.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/nuke/Ui.java b/src/main/java/nuke/Ui.java index 744f1bba3..3674b4518 100644 --- a/src/main/java/nuke/Ui.java +++ b/src/main/java/nuke/Ui.java @@ -136,6 +136,14 @@ public void printTaskLoadError(TaskLoadException e) { System.out.println(); } + /** + * Handles an error which occurs when + * loading tasks from the file fails and + * backing up the file fails. + * If user does not ignore the error, this throws RuntimeException. + * + * @param e exception + */ public void handleTaskFileCopyError(TaskFileCopyException e) { printTaskFileCopyError(e, IGNORE_ERROR_COMMAND); if (!scanIgnore()) { @@ -155,6 +163,13 @@ public void printTaskFileCopyError(TaskFileCopyException e, String ignoreCommand System.out.println(); } + /** + * Handles an error which occurs when + * saving tasks to the file fails. + * If user enters non-empty input, this continues to quit. + * + * @param e exception + */ public void handleTaskSaveError(TaskSaveException e) { printTaskSaveError(e.tasks); scanWhileEmpty(); From 5b2f3917d6294466015e5b85d7149b4558098d59 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 30 Sep 2023 17:36:49 +0800 Subject: [PATCH 50/52] Update README.md --- README.md | 85 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 8715d4d91..0a09509ef 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,61 @@ -# 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. - -## Setting up in Intellij - -Prerequisites: JDK 11, update Intellij to the most recent version. - -1. Open Intellij (if you are not in the welcome screen, click `File` > `Close Project` to close the existing project first) -1. Open the project into Intellij as follows: - 1. Click `Open`. - 1. Select the project directory, and click `OK`. - 1. If there are any further prompts, accept the defaults. -1. Configure the project to use **JDK 11** (not other versions) as explained in [here](https://www.jetbrains.com/help/idea/sdk.html#set-up-jdk).
- In the same dialog, set the **Project language level** field to the `SDK default` option. -3. After that, locate the `src/main/java/Duke.java` file, right-click it, and choose `Run Duke.main()` (if the code editor is showing compile errors, try restarting the IDE). If the setup is correct, you should see something like the below as the output: - ``` - Hello from - ____ _ - | _ \ _ _| | _____ - | | | | | | | |/ / _ \ - | |_| | |_| | < __/ - |____/ \__,_|_|\_\___| - ``` +# Nuke User Guide +Nuke is a desktop app for managing tasks using CLI (Command Line Interface). + + +## Features + + +### Exiting: `bye` + +Exits program while saving the tasks on the file system. + +Format: `bye` + +### Adding a task: `todo` + +Adds a task to the list. + +Format: `todo ` + +### Adding a task with a deadline: `deadline` + +Adds a task with a deadline to the list. + +Format: `deadline /by ` + +### Adding an event: `event` + +Adds an event to the list. + +Format: `event /from /to ` + +### Viewing all tasks: `list` + +Shows a list of tasks in the list. + +Format: `list` + +### Marking a task as done: `mark` + +Marks a task as done. + +Format: `mark ` + +### Marking a task as not done: `unmark` + +Marks a task as not done. + +Format: `unmark ` + +### Deleting a task: `delete` + +Deletes a task in the list. + +Format: `delete ` + +### Finding a task by keyword: `find` + +Finds a task in the list by a keyword. + +Format: `find ` + From 6fef454d30736f0416e35b263460a585b2d4f4fe Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 30 Sep 2023 17:44:15 +0800 Subject: [PATCH 51/52] Update README.md --- docs/README.md | 58 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/docs/README.md b/docs/README.md index 8077118eb..3c6a87224 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,29 +1,59 @@ # User Guide +Nuke is a desktop app for managing tasks using CLI (Command Line Interface). ## Features -### Feature-ABC +### Exiting: `bye` -Description of the feature. +Exits program while saving the tasks on the file system. -### Feature-XYZ +Format: `bye` -Description of the feature. +### Adding a task: `todo` -## Usage +Adds a task to the list. -### `Keyword` - Describe action +Format: `todo ` -Describe the action and its outcome. +### Adding a task with a deadline: `deadline` -Example of usage: +Adds a task with a deadline to the list. -`keyword (optional arguments)` +Format: `deadline /by ` -Expected outcome: +### Adding an event: `event` -Description of the outcome. +Adds an event to the list. + +Format: `event /from /to ` + +### Viewing all tasks: `list` + +Shows a list of tasks in the list. + +Format: `list` + +### Marking a task as done: `mark` + +Marks a task as done. + +Format: `mark ` + +### Marking a task as not done: `unmark` + +Marks a task as not done. + +Format: `unmark ` + +### Deleting a task: `delete` + +Deletes a task in the list. + +Format: `delete ` + +### Finding a task by keyword: `find` + +Finds a task in the list by a keyword. + +Format: `find ` -``` -expected output -``` From dd4fb3d99a5088c17239e45b423b5b4e3b52a307 Mon Sep 17 00:00:00 2001 From: ICubE- Date: Sat, 7 Oct 2023 01:21:58 +0800 Subject: [PATCH 52/52] Update README.md --- docs/README.md | 173 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 156 insertions(+), 17 deletions(-) diff --git a/docs/README.md b/docs/README.md index 3c6a87224..38f9c23c5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,53 +7,192 @@ Nuke is a desktop app for managing tasks using CLI (Command Line Interface). Exits program while saving the tasks on the file system. -Format: `bye` - ### Adding a task: `todo` Adds a task to the list. -Format: `todo ` - ### Adding a task with a deadline: `deadline` Adds a task with a deadline to the list. -Format: `deadline /by ` - ### Adding an event: `event` Adds an event to the list. -Format: `event /from /to ` - ### Viewing all tasks: `list` Shows a list of tasks in the list. -Format: `list` - ### Marking a task as done: `mark` Marks a task as done. -Format: `mark ` - ### Marking a task as not done: `unmark` Marks a task as not done. -Format: `unmark ` - ### Deleting a task: `delete` Deletes a task in the list. -Format: `delete ` - ### Finding a task by keyword: `find` Finds a task in the list by a keyword. -Format: `find ` +## Usage + +### `bye` - Exits program + +Exits program while saving the tasks on the file system. + +Example of usage: + +`bye` + +Expected outcome: + +``` +[@] Bye. Hope to see you again soon! +``` + +### `todo` - Adds a task + +Adds a task to the list. + +Example of usage: + +`todo ` + +Expected outcome: + +If input is `todo read book`, + +``` +[@] Got it. I've added this task: + [T][ ] read book +[@] Now you have 1 task in the list. +``` + +### `deadline` - Adds a task with a deadline + +Adds a task with a deadline to the list. + +Example of usage: + +`deadline /by ` + +Expected outcome: + +If input is `deadline return book /by June 6th`, + +``` +[@] Got it. I've added this task: + [D][ ] return book (by: June 6th) +[@] Now you have 2 tasks in the list. +``` + +### `event` - Adds an event + +Adds an event to the list. + +Example of usage: + +`event /from /to ` + +Expected outcome: + +If input is `event project meeting /from Aug 6th 2pm /to 4pm`, + +``` +[@] Got it. I've added this task: + [E][ ] project meeting (from: Aug 6th 2pm to: 4pm) +[@] Now you have 3 tasks in the list. +``` + +### `list` - Views all tasks + +Shows a list of tasks in the list. + +Example of usage: + +`list` + +Expected outcome: + +``` +[@] Here are the tasks in your list: +1.[T][ ] read book +2.[D][ ] return book (by: June 6th) +3.[E][ ] project meeting (from: Aug 6th 2pm to: 4pm) +``` + +### `mark` - Marks a task as done + +Marks a task as done. + +Example of usage: + +`mark ` + +Expected outcome: + +If input is `mark 1`, + +``` +[@] Nice! I've marked this task as done: + [T][X] read book +``` + +### `unmark` - Marks a task as not done + +Marks a task as not done. + +Example of usage: + +`unmark ` + +Expected outcome: + +If input is `unmark 3`, + +``` +[@] OK, I've marked this task as not done yet: + [E][ ] project meeting (from: Aug 6th 2pm to: 4pm) +``` + +### `delete` - Deletes a task + +Deletes a task in the list. + +Example of usage: + +`delete ` + +Expected outcome: + +If input is `delete 3`, + +``` +[@] Noted. I've removed this task: + [E][ ] project meeting (from: Aug 6th 2pm to: 4pm) +[@] Now you have 2 tasks in the list. +``` + +### `find` - Finds a task by keyword + +Finds a task in the list by a keyword. + +Example of usage: + +`find ` + +Expected outcome: + +If input is `find book`, + +``` +[@] Here are the matching tasks in your list: +1.[T][X] read book +2.[D][ ] return book (by: June 6th) +```