From 845e31aa3befed8bf7076bf2b1e75cc13e4ef29f Mon Sep 17 00:00:00 2001 From: mxksowie <34589654+mxksowie@users.noreply.github.com> Date: Sun, 30 Aug 2020 17:51:48 +0800 Subject: [PATCH 01/15] Add greet and exit --- src/main/java/Duke.java | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 5d313334cc..091e5fbbc7 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,4 +1,8 @@ public class Duke { + /** + * Main method which (strictly) handles IO + * @param args + */ public static void main(String[] args) { String logo = " ____ _ \n" + "| _ \\ _ _| | _____ \n" @@ -6,5 +10,31 @@ public static void main(String[] args) { + "| |_| | |_| | < __/\n" + "|____/ \\__,_|_|\\_\\___|\n"; System.out.println("Hello from\n" + logo); + + printBreak(); + greetUser(); + + printBreak(); + byeUser(); + + printBreak(); + + + } + + /** + * Prints a standard breakline meant to break up sections of text + */ + private static void printBreak() { + System.out.println("____________________________________________________________"); + } + + private static void greetUser() { + System.out.println(" Hello! I'm Duke"); + System.out.println(" What can I do for you?"); + } + + private static void byeUser() { + System.out.println(" Bye. Hope to see you again soon!"); } } From dceb48edd0b3a5e9827ec4258749f8284f37a012 Mon Sep 17 00:00:00 2001 From: mxksowie <34589654+mxksowie@users.noreply.github.com> Date: Mon, 31 Aug 2020 13:15:17 +0800 Subject: [PATCH 02/15] Add Echo User input is parsed and printed --- src/main/java/Duke.java | 54 ++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 091e5fbbc7..749efea8a2 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,24 +1,25 @@ +import java.util.Scanner; + + public class Duke { /** * Main method which (strictly) handles IO * @param args */ public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - printBreak(); + Scanner scan = new Scanner(System.in); + // TaskList tasks = new TaskList(); + + introduceDuke(); greetUser(); - printBreak(); + while(echo(scan.nextLine())) { + } + + scan.close(); byeUser(); - printBreak(); - } @@ -26,15 +27,46 @@ public static void main(String[] args) { * Prints a standard breakline meant to break up sections of text */ private static void printBreak() { - System.out.println("____________________________________________________________"); + System.out.println(" ________________________________________________________"); + } + + /** + * Prints out the logo to introduce the program + */ + private static void introduceDuke() { + String logo = " ____ _ \n" + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; + System.out.println("Hello from\n" + logo); + printBreak(); } private static void greetUser() { System.out.println(" Hello! I'm Duke"); System.out.println(" What can I do for you?"); + printBreak(); } private static void byeUser() { System.out.println(" Bye. Hope to see you again soon!"); + printBreak(); + + } + + /** + * Echos the String input while checking for "bye"s + * @param userInput + * @return + */ + private static boolean echo(String userInput) { + if (userInput.equals("bye")) { + return false; + } + printBreak(); + System.out.println(" " + userInput); + printBreak(); + return true; } } From e91af959f79eda71ec8a78fa9f326c323140d767 Mon Sep 17 00:00:00 2001 From: mxksowie <34589654+mxksowie@users.noreply.github.com> Date: Tue, 1 Sep 2020 20:43:07 +0800 Subject: [PATCH 03/15] Add add, list User input was only echoed back. Update parses user input, maintains a list of tasks that can be retrieved on command. --- src/main/java/Duke.java | 29 +++++++++++++++++++++++++---- src/main/java/Task.java | 19 +++++++++++++++++++ src/main/java/TaskList.java | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 src/main/java/Task.java create mode 100644 src/main/java/TaskList.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 749efea8a2..0eb8548190 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -9,18 +9,20 @@ public class Duke { public static void main(String[] args) { Scanner scan = new Scanner(System.in); - // TaskList tasks = new TaskList(); introduceDuke(); greetUser(); - - while(echo(scan.nextLine())) { + + TaskList tasks = new TaskList(); + + while(parseInput(scan.nextLine(), tasks)) { + printBreak(); + System.out.println("\n"); } scan.close(); byeUser(); - } /** @@ -50,6 +52,7 @@ private static void greetUser() { } private static void byeUser() { + printBreak(); System.out.println(" Bye. Hope to see you again soon!"); printBreak(); @@ -69,4 +72,22 @@ private static boolean echo(String userInput) { printBreak(); return true; } + + + private static boolean parseInput(String userInput, TaskList tasks) { + if (userInput.equals("bye")) { + return false; + } + + if (userInput.equals("list")) { + printBreak(); + System.out.println(tasks); + return true; + } + + printBreak(); + System.out.println(" " + tasks.addTask(userInput)); + + return true; + } } diff --git a/src/main/java/Task.java b/src/main/java/Task.java new file mode 100644 index 0000000000..4b1307e311 --- /dev/null +++ b/src/main/java/Task.java @@ -0,0 +1,19 @@ +public class Task { + protected String description; + private boolean isComplete; + + public Task(String description) { + this.description = description; + this.isComplete = false; + } + + @Override + public String toString() { + return this.description; //Subject to change; return string rep for printing purposes + } + + protected boolean markAsComplete() { + this.isComplete = true; + return this.isComplete; + } +} \ No newline at end of file diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java new file mode 100644 index 0000000000..98698fbd91 --- /dev/null +++ b/src/main/java/TaskList.java @@ -0,0 +1,32 @@ +import java.util.ArrayList; + +public class TaskList { + private ArrayList tasks; + + public TaskList() { + this.tasks = new ArrayList(); + } + + public TaskList(String description) { + this.tasks = new ArrayList(); + this.tasks.add(new Task(description)); + } + + public String addTask(String description) { + + this.tasks.add(new Task(description)); + + return String.format("added: %s", description); + } + + @Override + public String toString() { + String result = ""; + //for (Task task : tasks) { + for (int i = 0; i < tasks.size(); i++){ + Task task = tasks.get(i); + result += i + ". " + task.toString() + "\n"; + } + return result; + } +} \ No newline at end of file From 4b337f9e8aaee1774bb5719a2f18782a355ba524 Mon Sep 17 00:00:00 2001 From: mxksowie <34589654+mxksowie@users.noreply.github.com> Date: Wed, 2 Sep 2020 01:00:38 +0800 Subject: [PATCH 04/15] add done User can use the done keyword to change the status of a task to done. List also keeps tracks of done and undone tasks. --- src/main/java/Duke.java | 24 +++++++++++++++++++++++- src/main/java/Task.java | 8 ++++++++ src/main/java/TaskList.java | 14 +++++++++++--- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 0eb8548190..b12d42b7f5 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -75,6 +75,27 @@ private static boolean echo(String userInput) { private static boolean parseInput(String userInput, TaskList tasks) { + String[] inputs = userInput.split(" "); + + String keyword = inputs[0]; + + switch (keyword) { + case "bye": + return false; + case "list": + printBreak(); + System.out.println(tasks); + return true; + case "done": + // change it + String msg = tasks.markComplete(Integer.parseInt(inputs[1])); + printBreak(); + System.out.println("Nice! I've marked this task as done:"); + System.out.println(" " + msg); + return true; + } + + /** if (userInput.equals("bye")) { return false; } @@ -84,7 +105,8 @@ private static boolean parseInput(String userInput, TaskList tasks) { System.out.println(tasks); return true; } - + */ + printBreak(); System.out.println(" " + tasks.addTask(userInput)); diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 4b1307e311..d439df55b3 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -16,4 +16,12 @@ protected boolean markAsComplete() { this.isComplete = true; return this.isComplete; } + + protected boolean checkIsComplete() { + return this.isComplete; + } + + protected String getCompletionStatusIcon() { + return (isComplete ? "[\u2713]" : "[\u2718]"); + } } \ No newline at end of file diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index 98698fbd91..e16daa63ef 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -12,20 +12,28 @@ public TaskList(String description) { this.tasks.add(new Task(description)); } - public String addTask(String description) { + protected String addTask(String description) { this.tasks.add(new Task(description)); return String.format("added: %s", description); } + protected String markComplete(int index) { + index = index - 1; // start from 0 instead of 1 + Task task = tasks.get(index); + task.markAsComplete(); + return (task.getCompletionStatusIcon() + " " + task.toString()); + } + @Override public String toString() { String result = ""; //for (Task task : tasks) { - for (int i = 0; i < tasks.size(); i++){ + for (int i = 0; i < tasks.size(); i++) { Task task = tasks.get(i); - result += i + ". " + task.toString() + "\n"; + result += i + ". " + task.getCompletionStatusIcon() + " " + + task.toString() + "\n"; } return result; } From c7bccc449047b8c7841327ebc2449cdbef54dbee Mon Sep 17 00:00:00 2001 From: mxksowie <34589654+mxksowie@users.noreply.github.com> Date: Wed, 2 Sep 2020 23:40:58 +0800 Subject: [PATCH 05/15] add Todo, Events, Deadlines Main interfaced directly with TaskList and only Tasks could be created. Introduced todos, events, and deadlines as new types of tasks that can be added with more details. Task manager now parses user input and puts a barrier between Duke and TaskList/other task implementations. --- src/main/java/Deadline.java | 21 ++++++ src/main/java/Duke.java | 47 ++---------- src/main/java/Event.java | 21 ++++++ src/main/java/Task.java | 5 +- src/main/java/TaskList.java | 38 ++++++++-- src/main/java/TaskManager.java | 127 +++++++++++++++++++++++++++++++++ src/main/java/Todo.java | 12 ++++ 7 files changed, 222 insertions(+), 49 deletions(-) create mode 100644 src/main/java/Deadline.java create mode 100644 src/main/java/Event.java create mode 100644 src/main/java/TaskManager.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 0000000000..ff40d6d4fb --- /dev/null +++ b/src/main/java/Deadline.java @@ -0,0 +1,21 @@ +public class Deadline extends Task { + private String deadline; + + public Deadline(String description, String deadline) { + super(description); + this.deadline = deadline; + } + + public String getBy() { + return this.deadline; + } + + public void setBy(String newDeadline) { + this.deadline = newDeadline; + } + + @Override + public String toString() { + return String.format("[D]%s (by: %s)", super.toString(), this.deadline); + } +} \ No newline at end of file diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index b12d42b7f5..fc46c083a2 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -13,9 +13,9 @@ public static void main(String[] args) { introduceDuke(); greetUser(); - TaskList tasks = new TaskList(); + TaskManager manager = new TaskManager(); - while(parseInput(scan.nextLine(), tasks)) { + while(manager.parseInput(scan.nextLine())) { printBreak(); System.out.println("\n"); } @@ -27,8 +27,9 @@ public static void main(String[] args) { /** * Prints a standard breakline meant to break up sections of text + * Dev note: Might have cyclic dependencies because of printBreak usage */ - private static void printBreak() { + public static void printBreak() { System.out.println(" ________________________________________________________"); } @@ -72,44 +73,4 @@ private static boolean echo(String userInput) { printBreak(); return true; } - - - private static boolean parseInput(String userInput, TaskList tasks) { - String[] inputs = userInput.split(" "); - - String keyword = inputs[0]; - - switch (keyword) { - case "bye": - return false; - case "list": - printBreak(); - System.out.println(tasks); - return true; - case "done": - // change it - String msg = tasks.markComplete(Integer.parseInt(inputs[1])); - printBreak(); - System.out.println("Nice! I've marked this task as done:"); - System.out.println(" " + msg); - return true; - } - - /** - if (userInput.equals("bye")) { - return false; - } - - if (userInput.equals("list")) { - printBreak(); - System.out.println(tasks); - return true; - } - */ - - printBreak(); - System.out.println(" " + tasks.addTask(userInput)); - - return true; - } } diff --git a/src/main/java/Event.java b/src/main/java/Event.java new file mode 100644 index 0000000000..2fb9564987 --- /dev/null +++ b/src/main/java/Event.java @@ -0,0 +1,21 @@ +public class Event extends Task { + private String event; + + public Event(String description, String event) { + super(description); + this.event = event; + } + + public String getBy() { + return this.event; + } + + public void setBy(String newEvent) { + this.event = newEvent; + } + + @Override + public String toString() { + return String.format("[E]%s (at: %s)", super.toString(), this.event); + } +} \ No newline at end of file diff --git a/src/main/java/Task.java b/src/main/java/Task.java index d439df55b3..1a65ca8d38 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -9,7 +9,8 @@ public Task(String description) { @Override public String toString() { - return this.description; //Subject to change; return string rep for printing purposes + //Subject to change; return string rep for printing purposes + return this.getCompletionStatusIcon() + " " + this.description; } protected boolean markAsComplete() { @@ -21,7 +22,7 @@ protected boolean checkIsComplete() { return this.isComplete; } - protected String getCompletionStatusIcon() { + private String getCompletionStatusIcon() { return (isComplete ? "[\u2713]" : "[\u2718]"); } } \ No newline at end of file diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index e16daa63ef..4631a5c7b7 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -19,22 +19,52 @@ protected String addTask(String description) { return String.format("added: %s", description); } + protected String addTodo(String description) { + Task task = new Todo(description); + this.tasks.add(task); + + return task.toString(); + } + + protected String addDeadline(String description, String deadline) { + Task task = new Deadline(description, deadline); + this.tasks.add(task); + + return task.toString(); + } + + + protected String addEvent(String description, String detail) { + Task task = new Event(description, detail); + this.tasks.add(task); + + return task.toString(); + } + protected String markComplete(int index) { index = index - 1; // start from 0 instead of 1 Task task = tasks.get(index); task.markAsComplete(); - return (task.getCompletionStatusIcon() + " " + task.toString()); + return (task.toString()); + } + + protected int size() { + return this.tasks.size(); } @Override public String toString() { String result = ""; //for (Task task : tasks) { - for (int i = 0; i < tasks.size(); i++) { - Task task = tasks.get(i); - result += i + ". " + task.getCompletionStatusIcon() + " " + for (int i = 1; i <= tasks.size(); i++) { + Task task = tasks.get(i - 1); + result += i + ". " // + task.getCompletionStatusIcon() + " " + task.toString() + "\n"; } + result += String.format("Now you have %s tasks in the list.", tasks.size()); + return result; } + + } \ No newline at end of file diff --git a/src/main/java/TaskManager.java b/src/main/java/TaskManager.java new file mode 100644 index 0000000000..359d97d210 --- /dev/null +++ b/src/main/java/TaskManager.java @@ -0,0 +1,127 @@ +import java.util.Arrays; +import java.util.ArrayList; + +public class TaskManager { + private TaskList tasks; + + public TaskManager() { + this.tasks = new TaskList(); + } + + public boolean parseInput(String userInput) { + String[] inputs = userInput.split(" "); + + String keyword = inputs[0]; + + switch (keyword) { + case "bye": + return false; + case "list": + listTaskList(); + return true; + case "done": + String msg = tasks.markComplete(Integer.parseInt(inputs[1])); + Duke.printBreak(); + System.out.println("Nice! I've marked this task as done:"); + System.out.println(" " + msg); + return true; + case "todo": + addTodo(String.join(" ", Arrays.copyOfRange(inputs, 1, inputs.length))); + break; + case "deadline": + addDeadline(Arrays.copyOfRange(inputs, 1, inputs.length)); + break; + case "event": + addEvent(Arrays.copyOfRange(inputs, 1, inputs.length)); + break; + default: + Duke.printBreak(); + System.out.println(" " + tasks.addTask(userInput)); + } + + System.out.println(String.format(" Now you have %s tasks in the list.", tasks.size())); + + + + return true; + } + + private void listTaskList() { + Duke.printBreak(); + System.out.println("Here are the tasks in your list:"); + System.out.println(tasks); + } + + private void addTodo(String userInput) { + Duke.printBreak(); + System.out.println("Got it. I've added this task :"); + System.out.println(" " + tasks.addTodo(userInput)); + } + + private void addEvent(String[] userInput) { + boolean flag = false; + ArrayList detailWords = new ArrayList<>(); + ArrayList descriptionWords = new ArrayList<>(); + + for (String input : userInput) { + if (flag) { + detailWords.add(input); + continue; + } + + /** + * Dev note: the following commented out code assumes that / is the keyword + * and not /at + if (input.charAt(0) == '/' || flag) { + detailWords.add(input.substring(1)); + flag = true; + continue; + } + */ + + if (input.equals("/at")){ + flag = true; + continue; + } + descriptionWords.add(input); + } + + Duke.printBreak(); + System.out.println("Got it. I've added this task :"); + System.out.println(" " + tasks.addEvent(String.join(" ", descriptionWords), + String.join(" ", detailWords))); + } + + private void addDeadline(String[] userInput) { + boolean flag = false; + ArrayList deadlineWords = new ArrayList<>(); + ArrayList descriptionWords = new ArrayList<>(); + + for (String input : userInput) { + if (flag) { + deadlineWords.add(input); + continue; + } + if (input.equals("/by")) { + flag = true; + continue; + } + /** + * Dev note: the following commented out code assumes that / and not /by is the keyword. + * + if (input.charAt(0) == '/' || flag) { + deadlineWords.add(input.substring(1)); + flag = true; + continue; + } + */ + descriptionWords.add(input); + } + + Duke.printBreak(); + System.out.println("Got it. I've added this task :"); + System.out.println(" " + tasks.addDeadline(String.join(" ", descriptionWords), + String.join(" ", deadlineWords))); + } +} + diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java new file mode 100644 index 0000000000..2a7b09e6f3 --- /dev/null +++ b/src/main/java/Todo.java @@ -0,0 +1,12 @@ +public class Todo extends Task { + + + public Todo(String description) { + super(description); + } + + @Override + public String toString() { + return "[T]" + super.toString(); + } +} \ No newline at end of file From 5fc77ec8907b198865edcd501623bee59bb1bea4 Mon Sep 17 00:00:00 2001 From: mxksowie <34589654+mxksowie@users.noreply.github.com> Date: Sun, 13 Sep 2020 17:29:30 +0800 Subject: [PATCH 06/15] Error Handling on TaskManager TaskManager now informs user of errors due to erroneous user input: Missing command words, not enough arguments, and invalid int/index. --- src/main/java/TaskManager.java | 60 ++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/src/main/java/TaskManager.java b/src/main/java/TaskManager.java index 359d97d210..bf83ed705f 100644 --- a/src/main/java/TaskManager.java +++ b/src/main/java/TaskManager.java @@ -8,6 +8,12 @@ public TaskManager() { this.tasks = new TaskList(); } + /** + * Parses the user input for keywords and commands. + * Calls the relevant methods to manage the list and print outputs to the user. + * @param userInput + * @return + */ public boolean parseInput(String userInput) { String[] inputs = userInput.split(" "); @@ -19,11 +25,21 @@ public boolean parseInput(String userInput) { case "list": listTaskList(); return true; + + } + + if (inputs.length == 1) { + printError("You need to tell me more about what you want to do."); + return true; + } + + switch (keyword) { case "done": - String msg = tasks.markComplete(Integer.parseInt(inputs[1])); - Duke.printBreak(); - System.out.println("Nice! I've marked this task as done:"); - System.out.println(" " + msg); + try { + markComplete(Integer.parseInt(inputs[1])); + } catch (NumberFormatException e) { + printError("You need to provide me with an integer."); + } return true; case "todo": addTodo(String.join(" ", Arrays.copyOfRange(inputs, 1, inputs.length))); @@ -35,8 +51,8 @@ public boolean parseInput(String userInput) { addEvent(Arrays.copyOfRange(inputs, 1, inputs.length)); break; default: - Duke.printBreak(); - System.out.println(" " + tasks.addTask(userInput)); + printError("Sorry. I don't know what that means"); + return true; } System.out.println(String.format(" Now you have %s tasks in the list.", tasks.size())); @@ -46,6 +62,19 @@ public boolean parseInput(String userInput) { return true; } + private void markComplete(int i){ + try { + String msg = tasks.markComplete(i); + Duke.printBreak(); + System.out.println("Nice! I've marked this task as done:"); + System.out.println(" " + msg); + } catch (IndexOutOfBoundsException e) { + printError("I couldn't delete the task at position " + i + + "\n You don't have that many tasks in your list."); + } + + } + private void listTaskList() { Duke.printBreak(); System.out.println("Here are the tasks in your list:"); @@ -69,16 +98,6 @@ private void addEvent(String[] userInput) { continue; } - /** - * Dev note: the following commented out code assumes that / is the keyword - * and not /at - if (input.charAt(0) == '/' || flag) { - detailWords.add(input.substring(1)); - flag = true; - continue; - } - */ - if (input.equals("/at")){ flag = true; continue; @@ -89,7 +108,7 @@ private void addEvent(String[] userInput) { Duke.printBreak(); System.out.println("Got it. I've added this task :"); System.out.println(" " + tasks.addEvent(String.join(" ", descriptionWords), - String.join(" ", detailWords))); + String.join(" ", detailWords))); } private void addDeadline(String[] userInput) { @@ -121,7 +140,12 @@ private void addDeadline(String[] userInput) { Duke.printBreak(); System.out.println("Got it. I've added this task :"); System.out.println(" " + tasks.addDeadline(String.join(" ", descriptionWords), - String.join(" ", deadlineWords))); + String.join(" ", deadlineWords))); + } + + private void printError(String s) { + Duke.printBreak(); + System.out.println(" " + s); } } From f0de2258ceca9559c7e35b8dbbef33a429661132 Mon Sep 17 00:00:00 2001 From: mxksowie <34589654+mxksowie@users.noreply.github.com> Date: Sun, 20 Sep 2020 19:03:50 +0800 Subject: [PATCH 07/15] Keywords increased "at" and "by" keywords added to compliment existing keywords which had "/" prefixes. --- src/main/java/TaskManager.java | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/java/TaskManager.java b/src/main/java/TaskManager.java index bf83ed705f..216cc2c20e 100644 --- a/src/main/java/TaskManager.java +++ b/src/main/java/TaskManager.java @@ -38,9 +38,15 @@ public boolean parseInput(String userInput) { try { markComplete(Integer.parseInt(inputs[1])); } catch (NumberFormatException e) { - printError("You need to provide me with an integer."); + printError("You need to provide me with an integer index."); } return true; + case "delete": + try { + deleteTask(Integer.parseInt(inputs[1])); + } catch (NumberFormatException e) { + printError("You need to provide me with an integer index."); + } case "todo": addTodo(String.join(" ", Arrays.copyOfRange(inputs, 1, inputs.length))); break; @@ -57,12 +63,14 @@ public boolean parseInput(String userInput) { System.out.println(String.format(" Now you have %s tasks in the list.", tasks.size())); - - return true; } + + private void deleteTask(int i) { - private void markComplete(int i){ + } + + private void markComplete(int i) { try { String msg = tasks.markComplete(i); Duke.printBreak(); @@ -70,7 +78,7 @@ private void markComplete(int i){ System.out.println(" " + msg); } catch (IndexOutOfBoundsException e) { printError("I couldn't delete the task at position " + i + - "\n You don't have that many tasks in your list."); + "\n I think you don't have that many tasks in your list."); } } @@ -98,7 +106,7 @@ private void addEvent(String[] userInput) { continue; } - if (input.equals("/at")){ + if (input.equals("/at") || input.equals("at")){ flag = true; continue; } @@ -121,19 +129,11 @@ private void addDeadline(String[] userInput) { deadlineWords.add(input); continue; } - if (input.equals("/by")) { + if (input.equals("/by") || input.equals("by")) { flag = true; continue; } - /** - * Dev note: the following commented out code assumes that / and not /by is the keyword. - * - if (input.charAt(0) == '/' || flag) { - deadlineWords.add(input.substring(1)); - flag = true; - continue; - } - */ + descriptionWords.add(input); } From 7648f2536bfb6ac8adbbab7d4a5c3b6579bf552a Mon Sep 17 00:00:00 2001 From: mxksowie <34589654+mxksowie@users.noreply.github.com> Date: Sun, 20 Sep 2020 19:25:38 +0800 Subject: [PATCH 08/15] Add delete Delete task from task list by providing its index. --- src/main/java/TaskList.java | 20 ++++++++++++-------- src/main/java/TaskManager.java | 13 +++++++++++-- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index 4631a5c7b7..1ea0d76a1c 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -4,31 +4,31 @@ public class TaskList { private ArrayList tasks; public TaskList() { - this.tasks = new ArrayList(); + tasks = new ArrayList(); } public TaskList(String description) { - this.tasks = new ArrayList(); - this.tasks.add(new Task(description)); + tasks = new ArrayList(); + tasks.add(new Task(description)); } protected String addTask(String description) { - this.tasks.add(new Task(description)); + tasks.add(new Task(description)); return String.format("added: %s", description); } protected String addTodo(String description) { Task task = new Todo(description); - this.tasks.add(task); + tasks.add(task); return task.toString(); } protected String addDeadline(String description, String deadline) { Task task = new Deadline(description, deadline); - this.tasks.add(task); + tasks.add(task); return task.toString(); } @@ -36,7 +36,7 @@ protected String addDeadline(String description, String deadline) { protected String addEvent(String description, String detail) { Task task = new Event(description, detail); - this.tasks.add(task); + tasks.add(task); return task.toString(); } @@ -49,7 +49,11 @@ protected String markComplete(int index) { } protected int size() { - return this.tasks.size(); + return tasks.size(); + } + + protected String delete(int i) { + return tasks.remove(i - 1).toString(); } @Override diff --git a/src/main/java/TaskManager.java b/src/main/java/TaskManager.java index 216cc2c20e..5d0ef9aba0 100644 --- a/src/main/java/TaskManager.java +++ b/src/main/java/TaskManager.java @@ -47,6 +47,7 @@ public boolean parseInput(String userInput) { } catch (NumberFormatException e) { printError("You need to provide me with an integer index."); } + break; case "todo": addTodo(String.join(" ", Arrays.copyOfRange(inputs, 1, inputs.length))); break; @@ -67,7 +68,15 @@ public boolean parseInput(String userInput) { } private void deleteTask(int i) { - + try{ + String task = tasks.delete(i); + Duke.printBreak(); + System.out.println(String.format(" Noted. I've removed this task: \n %s", task)); + } catch (IndexOutOfBoundsException e) { + printError("I couldn't delete the task at position " + i + + "\n I think you don't have that many tasks in your list."); + } + } private void markComplete(int i) { @@ -77,7 +86,7 @@ private void markComplete(int i) { System.out.println("Nice! I've marked this task as done:"); System.out.println(" " + msg); } catch (IndexOutOfBoundsException e) { - printError("I couldn't delete the task at position " + i + + printError("I couldn't mark the task at position " + i + "\n I think you don't have that many tasks in your list."); } From 36bdea41baf51c6e3f9616370e80c63b421418e1 Mon Sep 17 00:00:00 2001 From: mxksowie <34589654+mxksowie@users.noreply.github.com> Date: Wed, 23 Sep 2020 20:30:58 +0800 Subject: [PATCH 09/15] Add Output class Output class removes cyclic dependency of TaskManager and Duke. Output class will be used to further streamline the TaskManager class so that it does not need to handle parsing, commands, and outputs all together. --- src/main/java/Duke.java | 60 +++------------------------------- src/main/java/Output.java | 40 +++++++++++++++++++++++ src/main/java/TaskManager.java | 34 ++++++++----------- 3 files changed, 57 insertions(+), 77 deletions(-) create mode 100644 src/main/java/Output.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index fc46c083a2..cb875efcaa 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -9,68 +9,16 @@ public class Duke { public static void main(String[] args) { Scanner scan = new Scanner(System.in); - - introduceDuke(); - greetUser(); + Output.introduceDuke(); + Output.greetUser(); TaskManager manager = new TaskManager(); while(manager.parseInput(scan.nextLine())) { - printBreak(); + Output.printBreak(); System.out.println("\n"); } - scan.close(); - byeUser(); - - } - - /** - * Prints a standard breakline meant to break up sections of text - * Dev note: Might have cyclic dependencies because of printBreak usage - */ - public static void printBreak() { - System.out.println(" ________________________________________________________"); - } - - /** - * Prints out the logo to introduce the program - */ - private static void introduceDuke() { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - printBreak(); - } - - private static void greetUser() { - System.out.println(" Hello! I'm Duke"); - System.out.println(" What can I do for you?"); - printBreak(); - } - - private static void byeUser() { - printBreak(); - System.out.println(" Bye. Hope to see you again soon!"); - printBreak(); - - } - - /** - * Echos the String input while checking for "bye"s - * @param userInput - * @return - */ - private static boolean echo(String userInput) { - if (userInput.equals("bye")) { - return false; - } - printBreak(); - System.out.println(" " + userInput); - printBreak(); - return true; + Output.byeUser(); } } diff --git a/src/main/java/Output.java b/src/main/java/Output.java new file mode 100644 index 0000000000..942aae9a5f --- /dev/null +++ b/src/main/java/Output.java @@ -0,0 +1,40 @@ +public class Output { + + /** + * Prints a standard breakline meant to break up sections of text + */ + public static void printBreak() { + System.out.println(" ________________________________________________________"); + } + + /** + * Prints out the logo to introduce the program + */ + public static void introduceDuke() { + String logo = " ____ _ \n" + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; + System.out.println("Hello from\n" + logo); + printBreak(); + } + + public static void greetUser() { + System.out.println(" Hello! I'm Duke"); + System.out.println(" What can I do for you?"); + printBreak(); + } + + public static void byeUser() { + printBreak(); + System.out.println(" Bye. Hope to see you again soon!"); + printBreak(); + + } + + public static void printError(String s) { + Output.printBreak(); + System.out.println(" " + s); + } +} diff --git a/src/main/java/TaskManager.java b/src/main/java/TaskManager.java index 5d0ef9aba0..07d50b03b7 100644 --- a/src/main/java/TaskManager.java +++ b/src/main/java/TaskManager.java @@ -25,11 +25,10 @@ public boolean parseInput(String userInput) { case "list": listTaskList(); return true; - } if (inputs.length == 1) { - printError("You need to tell me more about what you want to do."); + Output.printError("You need to tell me more about what you want to do."); return true; } @@ -38,14 +37,14 @@ public boolean parseInput(String userInput) { try { markComplete(Integer.parseInt(inputs[1])); } catch (NumberFormatException e) { - printError("You need to provide me with an integer index."); + Output.printError("You need to provide me with an integer index."); } return true; case "delete": try { deleteTask(Integer.parseInt(inputs[1])); } catch (NumberFormatException e) { - printError("You need to provide me with an integer index."); + Output.printError("You need to provide me with an integer index."); } break; case "todo": @@ -58,7 +57,7 @@ public boolean parseInput(String userInput) { addEvent(Arrays.copyOfRange(inputs, 1, inputs.length)); break; default: - printError("Sorry. I don't know what that means"); + Output.printError("Sorry. I don't know what that means"); return true; } @@ -70,10 +69,10 @@ public boolean parseInput(String userInput) { private void deleteTask(int i) { try{ String task = tasks.delete(i); - Duke.printBreak(); + Output.printBreak(); System.out.println(String.format(" Noted. I've removed this task: \n %s", task)); } catch (IndexOutOfBoundsException e) { - printError("I couldn't delete the task at position " + i + + Output.printError("I couldn't delete the task at position " + i + "\n I think you don't have that many tasks in your list."); } @@ -82,24 +81,23 @@ private void deleteTask(int i) { private void markComplete(int i) { try { String msg = tasks.markComplete(i); - Duke.printBreak(); + Output.printBreak(); System.out.println("Nice! I've marked this task as done:"); System.out.println(" " + msg); } catch (IndexOutOfBoundsException e) { - printError("I couldn't mark the task at position " + i + + Output.printError("I couldn't mark the task at position " + i + "\n I think you don't have that many tasks in your list."); } - } private void listTaskList() { - Duke.printBreak(); + Output.printBreak(); System.out.println("Here are the tasks in your list:"); System.out.println(tasks); } private void addTodo(String userInput) { - Duke.printBreak(); + Output.printBreak(); System.out.println("Got it. I've added this task :"); System.out.println(" " + tasks.addTodo(userInput)); } @@ -114,7 +112,6 @@ private void addEvent(String[] userInput) { detailWords.add(input); continue; } - if (input.equals("/at") || input.equals("at")){ flag = true; continue; @@ -122,7 +119,7 @@ private void addEvent(String[] userInput) { descriptionWords.add(input); } - Duke.printBreak(); + Output.printBreak(); System.out.println("Got it. I've added this task :"); System.out.println(" " + tasks.addEvent(String.join(" ", descriptionWords), String.join(" ", detailWords))); @@ -142,19 +139,14 @@ private void addDeadline(String[] userInput) { flag = true; continue; } - descriptionWords.add(input); } - - Duke.printBreak(); + Output.printBreak(); System.out.println("Got it. I've added this task :"); System.out.println(" " + tasks.addDeadline(String.join(" ", descriptionWords), String.join(" ", deadlineWords))); } - private void printError(String s) { - Duke.printBreak(); - System.out.println(" " + s); - } + } From 5d9366594b1cbeb2ca71ce86a2f9e3cc72a79f90 Mon Sep 17 00:00:00 2001 From: mxksowie <34589654+mxksowie@users.noreply.github.com> Date: Tue, 29 Sep 2020 18:31:24 +0800 Subject: [PATCH 10/15] add Save List of tasks now saved automatically to user's home directory after the list is updated. This list is retrieved and loaded upon (re)starting the application. --- src/main/java/Duke.java | 12 ++++-- src/main/java/Event.java | 1 + src/main/java/RetrieveList.java | 73 +++++++++++++++++++++++++++++++++ src/main/java/SaveList.java | 25 +++++++++++ src/main/java/Task.java | 5 +++ src/main/java/TaskList.java | 37 +++++++++++++++++ src/main/java/TaskManager.java | 23 +++++++++++ 7 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 src/main/java/RetrieveList.java create mode 100644 src/main/java/SaveList.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index cb875efcaa..aed8f9704c 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -3,7 +3,7 @@ public class Duke { /** - * Main method which (strictly) handles IO + * Main method which handles initialisation and closing interactions. * @param args */ public static void main(String[] args) { @@ -12,13 +12,17 @@ public static void main(String[] args) { Output.introduceDuke(); Output.greetUser(); - TaskManager manager = new TaskManager(); + + scan.close(); + Output.byeUser(); + } + + private static void run() { + TaskManager manager = RetrieveList.retrieveList(); // new TaskManager(); while(manager.parseInput(scan.nextLine())) { Output.printBreak(); System.out.println("\n"); } - scan.close(); - Output.byeUser(); } } diff --git a/src/main/java/Event.java b/src/main/java/Event.java index 2fb9564987..7731987096 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -18,4 +18,5 @@ public void setBy(String newEvent) { public String toString() { return String.format("[E]%s (at: %s)", super.toString(), this.event); } + } \ No newline at end of file diff --git a/src/main/java/RetrieveList.java b/src/main/java/RetrieveList.java new file mode 100644 index 0000000000..5dcc289c16 --- /dev/null +++ b/src/main/java/RetrieveList.java @@ -0,0 +1,73 @@ +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.InvalidPathException; +import java.nio.file.Files; +import java.io.IOException; + + +public class RetrieveList { + private static int TASK_TYPE_INDEX = 1; + private static int TASK_STATUS_INDEX = 4; + private static int TASK_DESCRIPTION_INDEX = 7; + + public static TaskManager retrieveList() { + try { + String home = System.getProperty("user.home"); + Path path = Paths.get(home, "duke-data.txt"); + return parseTxt(path); + } catch (InvalidPathException e) { + Output.printError("Seems like this is your first time using Duke."); + return new TaskManager(); + } + } + + private static TaskManager parseTxt(Path path) { + TaskList tasks = new TaskList(); + try { + Files.lines(path).forEachOrdered(line -> { + char key = line.charAt(TASK_TYPE_INDEX); + Character statusChar = line.charAt(TASK_STATUS_INDEX); + String description = line.substring(TASK_DESCRIPTION_INDEX); + + boolean status = false; + if (statusChar.equals('\u2713')) { + status = true; + } + + switch (key) { + case 'T': + addTodo(tasks, description, status); + break; + case 'D': + addDeadline(tasks, description, status); + break; + case 'E': + addEvent(tasks, description, status); + } + + }); + return new TaskManager(tasks); + } catch (IOException e) { + return new TaskManager(); + } + + } + + private static void addTodo(TaskList tasks, String description, boolean status) { + tasks.addTodo(description.strip(), status); + } + + private static void addDeadline(TaskList tasks, String description, boolean status) { + String cleanString = description.replace(')', ' ').replace('(', ' ').replaceFirst("by", " "); + String[] inputs = cleanString.split(":", 2); + tasks.addDeadline(inputs[0].strip(), inputs[1].strip(), status); + } + + private static void addEvent(TaskList tasks, String description, boolean status) { + // dev note: "repeated code" + String cleanString = description.replace(')', ' ').replace('(', ' ').replaceFirst("at", " "); + String[] inputs = cleanString.split(":", 2); + tasks.addEvent(inputs[0].strip(), inputs[1].strip(), status); + } + +} diff --git a/src/main/java/SaveList.java b/src/main/java/SaveList.java new file mode 100644 index 0000000000..8ba923a606 --- /dev/null +++ b/src/main/java/SaveList.java @@ -0,0 +1,25 @@ +import java.nio.file.Path; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; + + +public class SaveList { + + protected static void saveListToFile(Path path, ArrayList list) { + try { + FileWriter writer = new FileWriter(path.toString()); + list.forEach(x -> { + try { + writer.write(x.toString() + "\n"); + } catch (IOException e) { + Output.printError("A task could not be saved: " + x.toString()); + } + }); + writer.close(); + } catch (IOException e) { + Output.printError("Not able to open or close the filewriter"); + } + } + +} diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 1a65ca8d38..99e4ec4cc9 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -25,4 +25,9 @@ protected boolean checkIsComplete() { private String getCompletionStatusIcon() { return (isComplete ? "[\u2713]" : "[\u2718]"); } + + public String toTextRep() { + return this.description; + } + } \ No newline at end of file diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index 1ea0d76a1c..fc4fab44f9 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -1,4 +1,5 @@ import java.util.ArrayList; +import java.nio.file.Path; public class TaskList { private ArrayList tasks; @@ -41,6 +42,37 @@ protected String addEvent(String description, String detail) { return task.toString(); } + protected String addTodo(String description, boolean status) { + Task task = new Todo(description); + if (status) { + task.markAsComplete(); + } + tasks.add(task); + + return task.toString(); + } + + protected String addDeadline(String description, String deadline, boolean status) { + Task task = new Deadline(description, deadline); + if (status) { + task.markAsComplete(); + } + tasks.add(task); + + return task.toString(); + } + + + protected String addEvent(String description, String detail, boolean status) { + Task task = new Event(description, detail); + if (status) { + task.markAsComplete(); + } + tasks.add(task); + + return task.toString(); + } + protected String markComplete(int index) { index = index - 1; // start from 0 instead of 1 Task task = tasks.get(index); @@ -56,6 +88,11 @@ protected String delete(int i) { return tasks.remove(i - 1).toString(); } + protected void saveToFile(Path path) { + SaveList.saveListToFile(path, tasks); + } + + @Override public String toString() { String result = ""; diff --git a/src/main/java/TaskManager.java b/src/main/java/TaskManager.java index 07d50b03b7..dc829dd983 100644 --- a/src/main/java/TaskManager.java +++ b/src/main/java/TaskManager.java @@ -1,5 +1,8 @@ import java.util.Arrays; import java.util.ArrayList; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.InvalidPathException; public class TaskManager { private TaskList tasks; @@ -8,6 +11,10 @@ public TaskManager() { this.tasks = new TaskList(); } + public TaskManager(TaskList tasks) { + this.tasks = tasks; + } + /** * Parses the user input for keywords and commands. * Calls the relevant methods to manage the list and print outputs to the user. @@ -25,6 +32,9 @@ public boolean parseInput(String userInput) { case "list": listTaskList(); return true; + case "save": + saveTaskList(); + return true; } if (inputs.length == 1) { @@ -62,10 +72,13 @@ public boolean parseInput(String userInput) { } System.out.println(String.format(" Now you have %s tasks in the list.", tasks.size())); + + saveTaskList(); // task list is automatically saved without user input of save. return true; } + private void deleteTask(int i) { try{ String task = tasks.delete(i); @@ -78,6 +91,16 @@ private void deleteTask(int i) { } + private void saveTaskList() { + try { + String home = System.getProperty("user.home"); + Path path = Paths.get(home, "duke-data.txt"); + tasks.saveToFile(path); + } catch (InvalidPathException e) { + Output.printError("Not able to path the file."); + } + } + private void markComplete(int i) { try { String msg = tasks.markComplete(i); From cde1ed4e73374b861896dca483a66cca7071a1c0 Mon Sep 17 00:00:00 2001 From: mxksowie <34589654+mxksowie@users.noreply.github.com> Date: Tue, 29 Sep 2020 19:30:36 +0800 Subject: [PATCH 11/15] cleanup Main Refactored code in main to improve readability --- src/main/java/Duke.java | 24 ++++++++++++++++++------ src/main/java/Output.java | 13 +++++++++++++ src/main/java/RetrieveList.java | 5 +++++ 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index aed8f9704c..fbfd576ca7 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -3,26 +3,38 @@ public class Duke { /** - * Main method which handles initialisation and closing interactions. + * Main method which handles initial and closing interactions. * @param args */ public static void main(String[] args) { - Scanner scan = new Scanner(System.in); Output.introduceDuke(); Output.greetUser(); + run(); - scan.close(); Output.byeUser(); } + + /** + * Method containing the continuous while loop that parses user inputs and handles interactions accordingly + * Also initialises the task list. Attempts to retrieve a stored task list, if any. + */ private static void run() { - TaskManager manager = RetrieveList.retrieveList(); // new TaskManager(); + + Scanner scan = new Scanner(System.in); + + TaskManager manager = RetrieveList.retrieveList(); while(manager.parseInput(scan.nextLine())) { Output.printBreak(); - System.out.println("\n"); - } + Output.printEmptyLine(); + } + + scan.close(); } + + + } diff --git a/src/main/java/Output.java b/src/main/java/Output.java index 942aae9a5f..01e1d5c3c6 100644 --- a/src/main/java/Output.java +++ b/src/main/java/Output.java @@ -20,12 +20,18 @@ public static void introduceDuke() { printBreak(); } + /** + * Standard greeting that indicates program start / ready to recieve user input + */ public static void greetUser() { System.out.println(" Hello! I'm Duke"); System.out.println(" What can I do for you?"); printBreak(); } + /** + * Standard farewell that marks end of program + */ public static void byeUser() { printBreak(); System.out.println(" Bye. Hope to see you again soon!"); @@ -33,8 +39,15 @@ public static void byeUser() { } + /** + * Informs user of a caught error by providing a message with proper indentation/formating. + */ public static void printError(String s) { Output.printBreak(); System.out.println(" " + s); } + + public static void printEmptyLine() { + System.out.println("\n"); + } } diff --git a/src/main/java/RetrieveList.java b/src/main/java/RetrieveList.java index 5dcc289c16..c4778d2c47 100644 --- a/src/main/java/RetrieveList.java +++ b/src/main/java/RetrieveList.java @@ -10,6 +10,11 @@ public class RetrieveList { private static int TASK_STATUS_INDEX = 4; private static int TASK_DESCRIPTION_INDEX = 7; + + /** + * RetrieveList attempts to load the previously stored list in [user.home]/duke-data.txt + * @return TaskManager object with pre-loaded list or an empty one if stored list could not be retrieved. + */ public static TaskManager retrieveList() { try { String home = System.getProperty("user.home"); From 14c77932b99b0c639cf4d220bfb8ceab0f6fe543 Mon Sep 17 00:00:00 2001 From: mxksowie <34589654+mxksowie@users.noreply.github.com> Date: Fri, 2 Oct 2020 12:26:31 +0800 Subject: [PATCH 12/15] Update TaskManager to have no prints Streamlined methods in TaskManager by having Output class handle all printing. Extracted repeated/similar functionality in addEvent and addDeadline --- src/main/java/Output.java | 23 +++++++ src/main/java/StringPair.java | 9 +++ src/main/java/Task.java | 5 +- src/main/java/TaskManager.java | 121 +++++++++++++++------------------ 4 files changed, 86 insertions(+), 72 deletions(-) create mode 100644 src/main/java/StringPair.java diff --git a/src/main/java/Output.java b/src/main/java/Output.java index 01e1d5c3c6..da809a44f4 100644 --- a/src/main/java/Output.java +++ b/src/main/java/Output.java @@ -50,4 +50,27 @@ public static void printError(String s) { public static void printEmptyLine() { System.out.println("\n"); } + + protected static void printDeletedTask(String taskString) { + System.out.println(String.format(" Noted. I've removed this task: \n %s", taskString)); + } + + protected static void printAddedTask(String taskString) { + System.out.println("Got it. I've added this task :"); + System.out.println(" " + taskString); + } + + protected static void printCompletedTask(String taskString) { + System.out.println("Nice! I've marked this task as done:"); + System.out.println(" " + taskString); + } + + protected static void printTaskList (String listString) { + System.out.println("Here are the tasks in your list:"); + System.out.println(listString); + } + + protected static void printTaskCount(int count) { + System.out.println(String.format(" Now you have %s tasks in the list.", count)); + } } diff --git a/src/main/java/StringPair.java b/src/main/java/StringPair.java new file mode 100644 index 0000000000..d023f93641 --- /dev/null +++ b/src/main/java/StringPair.java @@ -0,0 +1,9 @@ +public final class StringPair { + public String first; + public String second; + + public StringPair(String first, String second) { + this.first = first; + this.second = second; + } +} diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 99e4ec4cc9..9552142fdc 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -25,9 +25,6 @@ protected boolean checkIsComplete() { private String getCompletionStatusIcon() { return (isComplete ? "[\u2713]" : "[\u2718]"); } - - public String toTextRep() { - return this.description; - } + } \ No newline at end of file diff --git a/src/main/java/TaskManager.java b/src/main/java/TaskManager.java index dc829dd983..4911b6bd8b 100644 --- a/src/main/java/TaskManager.java +++ b/src/main/java/TaskManager.java @@ -4,8 +4,10 @@ import java.nio.file.Paths; import java.nio.file.InvalidPathException; + public class TaskManager { private TaskList tasks; + private int COMMAND_START_INDEX= 1; public TaskManager() { this.tasks = new TaskList(); @@ -37,55 +39,54 @@ public boolean parseInput(String userInput) { return true; } - if (inputs.length == 1) { + if (inputs.length == COMMAND_START_INDEX) { Output.printError("You need to tell me more about what you want to do."); return true; } switch (keyword) { - case "done": - try { - markComplete(Integer.parseInt(inputs[1])); - } catch (NumberFormatException e) { - Output.printError("You need to provide me with an integer index."); - } - return true; - case "delete": - try { - deleteTask(Integer.parseInt(inputs[1])); - } catch (NumberFormatException e) { - Output.printError("You need to provide me with an integer index."); - } - break; - case "todo": - addTodo(String.join(" ", Arrays.copyOfRange(inputs, 1, inputs.length))); - break; - case "deadline": - addDeadline(Arrays.copyOfRange(inputs, 1, inputs.length)); - break; - case "event": - addEvent(Arrays.copyOfRange(inputs, 1, inputs.length)); - break; - default: - Output.printError("Sorry. I don't know what that means"); - return true; + case "done": + try { + markComplete(Integer.parseInt(inputs[COMMAND_START_INDEX])); + } catch (NumberFormatException e) { + Output.printError("You need to provide me with an integer index."); + } + return true; + case "delete": + try { + deleteTask(Integer.parseInt(inputs[COMMAND_START_INDEX])); + } catch (NumberFormatException e) { + Output.printError("You need to provide me with an integer index."); + } + break; + case "todo": + addTodo(String.join(" ", Arrays.copyOfRange(inputs, COMMAND_START_INDEX, inputs.length))); + break; + case "deadline": + addDeadline(Arrays.copyOfRange(inputs, COMMAND_START_INDEX, inputs.length)); + break; + case "event": + addEvent(Arrays.copyOfRange(inputs, COMMAND_START_INDEX, inputs.length)); + break; + default: + Output.printError("Sorry. I don't know what that means"); + return true; } - System.out.println(String.format(" Now you have %s tasks in the list.", tasks.size())); + Output.printTaskCount(tasks.size()); saveTaskList(); // task list is automatically saved without user input of save. return true; } - - private void deleteTask(int i) { + + private void deleteTask(int index) { try{ - String task = tasks.delete(i); Output.printBreak(); - System.out.println(String.format(" Noted. I've removed this task: \n %s", task)); + Output.printDeletedTask(tasks.delete(index)); } catch (IndexOutOfBoundsException e) { - Output.printError("I couldn't delete the task at position " + i + + Output.printError("I couldn't delete the task at position " + index + "\n I think you don't have that many tasks in your list."); } @@ -101,75 +102,59 @@ private void saveTaskList() { } } - private void markComplete(int i) { + private void markComplete(int index) { try { - String msg = tasks.markComplete(i); Output.printBreak(); - System.out.println("Nice! I've marked this task as done:"); - System.out.println(" " + msg); + Output.printCompletedTask(tasks.markComplete(index)); } catch (IndexOutOfBoundsException e) { - Output.printError("I couldn't mark the task at position " + i + + Output.printError("I couldn't mark the task at position " + index + "\n I think you don't have that many tasks in your list."); } } private void listTaskList() { Output.printBreak(); - System.out.println("Here are the tasks in your list:"); - System.out.println(tasks); + Output.printTaskList(tasks.toString()); } private void addTodo(String userInput) { Output.printBreak(); - System.out.println("Got it. I've added this task :"); - System.out.println(" " + tasks.addTodo(userInput)); + Output.printAddedTask(tasks.addTodo(userInput)); } private void addEvent(String[] userInput) { - boolean flag = false; - ArrayList detailWords = new ArrayList<>(); - ArrayList descriptionWords = new ArrayList<>(); - - for (String input : userInput) { - if (flag) { - detailWords.add(input); - continue; - } - if (input.equals("/at") || input.equals("at")){ - flag = true; - continue; - } - descriptionWords.add(input); - } - + StringPair taskInfo = splitAtCommand(userInput, "at"); Output.printBreak(); - System.out.println("Got it. I've added this task :"); - System.out.println(" " + tasks.addEvent(String.join(" ", descriptionWords), - String.join(" ", detailWords))); + Output.printAddedTask(tasks.addEvent(taskInfo.first, taskInfo.second)); } private void addDeadline(String[] userInput) { + StringPair taskInfo = splitAtCommand(userInput, "by"); + Output.printBreak(); + Output.printAddedTask(tasks.addDeadline(taskInfo.first, taskInfo.second)); + } + + private StringPair splitAtCommand(String[] userInput, String command) { boolean flag = false; - ArrayList deadlineWords = new ArrayList<>(); + ArrayList detailWords = new ArrayList<>(); ArrayList descriptionWords = new ArrayList<>(); for (String input : userInput) { if (flag) { - deadlineWords.add(input); + detailWords.add(input); continue; } - if (input.equals("/by") || input.equals("by")) { + if (input.equals("/" + command) || input.equals(command)) { flag = true; continue; } descriptionWords.add(input); } - Output.printBreak(); - System.out.println("Got it. I've added this task :"); - System.out.println(" " + tasks.addDeadline(String.join(" ", descriptionWords), - String.join(" ", deadlineWords))); + return new StringPair(String.join(" ", descriptionWords), String.join(" ", detailWords)); + } + } From 553d4a6fc3b1a9a781c3c3afa3426acfa673f085 Mon Sep 17 00:00:00 2001 From: mxksowie <34589654+mxksowie@users.noreply.github.com> Date: Fri, 2 Oct 2020 13:20:11 +0800 Subject: [PATCH 13/15] add Find based on keyword match User can input find to get a list of tasks that contain the keywords (case insensitive) --- src/main/java/Output.java | 11 +++++++++++ src/main/java/Task.java | 4 ++++ src/main/java/TaskList.java | 36 +++++++++++++++++++++++++++------- src/main/java/TaskManager.java | 8 ++++++++ 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/main/java/Output.java b/src/main/java/Output.java index da809a44f4..c70bb3ea71 100644 --- a/src/main/java/Output.java +++ b/src/main/java/Output.java @@ -70,6 +70,17 @@ protected static void printTaskList (String listString) { System.out.println(listString); } + protected static void printMatches (String matchList) { + printBreak(); + if (matchList.length() == 0) { + System.out.println(" Sorry! I couldn't find any matches."); + return; + } + + System.out.println("Here are the matching tasks in your list:"); + System.out.println(matchList); + } + protected static void printTaskCount(int count) { System.out.println(String.format(" Now you have %s tasks in the list.", count)); } diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 9552142fdc..0cafac036e 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -26,5 +26,9 @@ private String getCompletionStatusIcon() { return (isComplete ? "[\u2713]" : "[\u2718]"); } + protected String getDescription() { + return this.description; + } + } \ No newline at end of file diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index fc4fab44f9..00944e614a 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -92,16 +92,38 @@ protected void saveToFile(Path path) { SaveList.saveListToFile(path, tasks); } + protected String findTasksWithKeyword(String keyword) { + ArrayList matchingTasks = new ArrayList<>(); + CharSequence keywordCharSeq = new StringBuffer(keyword.toLowerCase()); + + for (Task task : tasks) { + // Use the task's description for a case insensitve comparison (all lower case) + String taskDescription = task.getDescription().toLowerCase(); + if (! taskDescription.contains(keywordCharSeq)){ + continue; + } + matchingTasks.add(task); + } - @Override - public String toString() { - String result = ""; - //for (Task task : tasks) { - for (int i = 1; i <= tasks.size(); i++) { - Task task = tasks.get(i - 1); - result += i + ". " // + task.getCompletionStatusIcon() + " " + return listToString(matchingTasks); + } + + private String listToString(ArrayList list) { + String listString = ""; + + for (int i = 1; i <= list.size(); i++) { + Task task = list.get(i - 1); + listString += i + ". " + task.toString() + "\n"; } + return listString; + } + + @Override + public String toString() { + + String result = listToString(tasks); + result += String.format("Now you have %s tasks in the list.", tasks.size()); return result; diff --git a/src/main/java/TaskManager.java b/src/main/java/TaskManager.java index 4911b6bd8b..516f9b9b7b 100644 --- a/src/main/java/TaskManager.java +++ b/src/main/java/TaskManager.java @@ -68,6 +68,10 @@ public boolean parseInput(String userInput) { case "event": addEvent(Arrays.copyOfRange(inputs, COMMAND_START_INDEX, inputs.length)); break; + + case "find": + findTasks(String.join(" ", Arrays.copyOfRange(inputs, COMMAND_START_INDEX, inputs.length))); + return true; default: Output.printError("Sorry. I don't know what that means"); return true; @@ -80,6 +84,10 @@ public boolean parseInput(String userInput) { return true; } + private void findTasks(String keyword) { + Output.printMatches(tasks.findTasksWithKeyword(keyword)); + } + private void deleteTask(int index) { try{ From f06ca94b65b27ac2e105c0cbf5a23656b53b3432 Mon Sep 17 00:00:00 2001 From: mxksowie <34589654+mxksowie@users.noreply.github.com> Date: Fri, 2 Oct 2020 21:44:25 +0800 Subject: [PATCH 14/15] add DateTime support Event and deadline now support ISO dates as details. New class DateType is new parent class to deadline and event to support this --- src/main/java/DatedTask.java | 33 +++++++++++++++++++++++++++++++++ src/main/java/Deadline.java | 17 +++++------------ src/main/java/Event.java | 18 +++++------------- src/main/java/Task.java | 1 - 4 files changed, 43 insertions(+), 26 deletions(-) create mode 100644 src/main/java/DatedTask.java diff --git a/src/main/java/DatedTask.java b/src/main/java/DatedTask.java new file mode 100644 index 0000000000..c4efe0d7a7 --- /dev/null +++ b/src/main/java/DatedTask.java @@ -0,0 +1,33 @@ +import java.util.Optional; +import java.time.LocalDate; +import java.time.format.DateTimeParseException; +import java.time.format.DateTimeFormatter; + +public class DatedTask extends Task{ + private Optional date; + private String detail; + + public DatedTask(String description, String date) { + super(description); + this.detail = date; + try { + CharSequence dateChars = new StringBuffer(date.strip()); + LocalDate localDate = LocalDate.parse(dateChars); + this.date = Optional.of(localDate); + } catch (DateTimeParseException e) { + this.date = Optional.empty(); + } + } + + protected Optional getBy() { + return date; + } + + protected String getDateOrDetail() { + if (date.isEmpty()) { + return detail; + } + return date.get().format(DateTimeFormatter.ofPattern("dd/MM/yyyy")); + } + +} diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index ff40d6d4fb..47462658a5 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -1,21 +1,14 @@ -public class Deadline extends Task { - private String deadline; +public class Deadline extends DatedTask { + public Deadline(String description, String deadline) { - super(description); - this.deadline = deadline; - } - - public String getBy() { - return this.deadline; - } + super(description, deadline); - public void setBy(String newDeadline) { - this.deadline = newDeadline; } @Override public String toString() { - return String.format("[D]%s (by: %s)", super.toString(), this.deadline); + return String.format("[D]%s (at: %s)", super.toString(), + super.getDateOrDetail()); } } \ No newline at end of file diff --git a/src/main/java/Event.java b/src/main/java/Event.java index 7731987096..2d5eeed4ed 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -1,22 +1,14 @@ -public class Event extends Task { - private String event; +public class Event extends DatedTask { + public Event(String description, String event) { - super(description); - this.event = event; - } - - public String getBy() { - return this.event; - } - - public void setBy(String newEvent) { - this.event = newEvent; + super(description, event); } @Override public String toString() { - return String.format("[E]%s (at: %s)", super.toString(), this.event); + return String.format("[E]%s (at: %s)", super.toString(), + super.getDateOrDetail()); } } \ No newline at end of file diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 0cafac036e..6d40b13f7a 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -9,7 +9,6 @@ public Task(String description) { @Override public String toString() { - //Subject to change; return string rep for printing purposes return this.getCompletionStatusIcon() + " " + this.description; } From 60777b517ebbad146d914e35b25bd27a98caab51 Mon Sep 17 00:00:00 2001 From: mxksowie <34589654+mxksowie@users.noreply.github.com> Date: Fri, 2 Oct 2020 22:18:48 +0800 Subject: [PATCH 15/15] add date matching Find (dated) tasks with matching dates when user queries for a date in ISO format. --- src/main/java/DatedTask.java | 4 ++-- src/main/java/TaskList.java | 34 ++++++++++++++++++++++++++++++++++ src/main/java/TaskManager.java | 13 +++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/main/java/DatedTask.java b/src/main/java/DatedTask.java index c4efe0d7a7..32bf07012e 100644 --- a/src/main/java/DatedTask.java +++ b/src/main/java/DatedTask.java @@ -11,8 +11,8 @@ public DatedTask(String description, String date) { super(description); this.detail = date; try { - CharSequence dateChars = new StringBuffer(date.strip()); - LocalDate localDate = LocalDate.parse(dateChars); + CharSequence dateCharSeq = new StringBuffer(date.strip()); + LocalDate localDate = LocalDate.parse(dateCharSeq); this.date = Optional.of(localDate); } catch (DateTimeParseException e) { this.date = Optional.empty(); diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index 00944e614a..0bfceb9a02 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -1,5 +1,7 @@ import java.util.ArrayList; import java.nio.file.Path; +import java.time.LocalDate; +import java.time.format.DateTimeParseException; public class TaskList { private ArrayList tasks; @@ -108,6 +110,38 @@ protected String findTasksWithKeyword(String keyword) { return listToString(matchingTasks); } + /** + * Searches the task list for (dated) tasks that match the date queried by the user + * @param dateString ISO formated date as a string + * @return list of matched tasks as a string + * @throws DateTimeParseException exception thrown as is. + */ + protected String findTasksWithDate(String dateString) throws DateTimeParseException { + ArrayList matchingTasks = new ArrayList<>(); + CharSequence dateCharSeq = new StringBuffer(dateString.strip()); + + try { + LocalDate localDate = LocalDate.parse(dateCharSeq); + for (Task task : tasks) { + if (!(task instanceof DatedTask)) { + continue; + } + DatedTask datedTask = (DatedTask) task; + if (datedTask.getBy().isEmpty()) { + continue; + } + if (!(localDate.equals(datedTask.getBy().get()))) { + continue; + } + matchingTasks.add(task); + } + } catch (DateTimeParseException e) { + throw e; + } + + return listToString(matchingTasks); + } + private String listToString(ArrayList list) { String listString = ""; diff --git a/src/main/java/TaskManager.java b/src/main/java/TaskManager.java index 516f9b9b7b..afd2364846 100644 --- a/src/main/java/TaskManager.java +++ b/src/main/java/TaskManager.java @@ -3,6 +3,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.InvalidPathException; +import java.time.format.DateTimeParseException; public class TaskManager { @@ -72,6 +73,9 @@ public boolean parseInput(String userInput) { case "find": findTasks(String.join(" ", Arrays.copyOfRange(inputs, COMMAND_START_INDEX, inputs.length))); return true; + case "dated": + findDated(String.join(" ", Arrays.copyOfRange(inputs, COMMAND_START_INDEX, inputs.length))); + return true; default: Output.printError("Sorry. I don't know what that means"); return true; @@ -84,6 +88,15 @@ public boolean parseInput(String userInput) { return true; } + private void findDated(String date) { + try{ + Output.printMatches(tasks.findTasksWithDate(date)); + } catch (DateTimeParseException e) { + Output.printError("Sorry, I could not figure out that date. It needs to be in ISO format."); + } + + } + private void findTasks(String keyword) { Output.printMatches(tasks.findTasksWithKeyword(keyword)); }