From 7b9bd8019bdb20caf75109cb1652c25186427e6c Mon Sep 17 00:00:00 2001 From: thant Date: Thu, 2 Mar 2023 11:15:45 +0800 Subject: [PATCH 001/152] Update README.md --- README.md | 69 +++++-------------------------------------------------- 1 file changed, 6 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index f82e2494b7..80b9d475da 100644 --- a/README.md +++ b/README.md @@ -1,64 +1,7 @@ -# Duke project template +#Names of Group Members -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 (use the exact version), update Intellij to the most recent version. - -1. **Ensure Intellij JDK 11 is defined as an SDK**, as described [here](https://www.jetbrains.com/help/idea/sdk.html#set-up-jdk) -- this step is not needed if you have used JDK 11 in a previous Intellij project. -1. **Import the project _as a Gradle project_**, as described [here](https://se-education.org/guides/tutorials/intellijImportGradleProject.html). -1. **Verify the set up**: After the importing is complete, locate the `src/main/java/seedu/duke/Duke.java` file, right-click it, and choose `Run Duke.main()`. If the setup is correct, you should see something like the below: - ``` - > Task :compileJava - > Task :processResources NO-SOURCE - > Task :classes - - > Task :Duke.main() - Hello from - ____ _ - | _ \ _ _| | _____ - | | | | | | | |/ / _ \ - | |_| | |_| | < __/ - |____/ \__,_|_|\_\___| - - What is your name? - ``` - Type some word and press enter to let the execution proceed to the end. - -## Build automation using Gradle - -* This project uses Gradle for build automation and dependency management. It includes a basic build script as well (i.e. the `build.gradle` file). -* If you are new to Gradle, refer to the [Gradle Tutorial at se-education.org/guides](https://se-education.org/guides/tutorials/gradle.html). - -## Testing - -### I/O redirection tests - -* To run _I/O redirection_ tests (aka _Text UI tests_), navigate to the `text-ui-test` and run the `runtest(.bat/.sh)` script. - -### JUnit tests - -* A skeleton JUnit test (`src/test/java/seedu/duke/DukeTest.java`) is provided with this project template. -* If you are new to JUnit, refer to the [JUnit Tutorial at se-education.org/guides](https://se-education.org/guides/tutorials/junit.html). - -## Checkstyle - -* A sample CheckStyle rule configuration is provided in this project. -* If you are new to Checkstyle, refer to the [Checkstyle Tutorial at se-education.org/guides](https://se-education.org/guides/tutorials/checkstyle.html). - -## CI using GitHub Actions - -The project uses [GitHub actions](https://github.com/features/actions) for CI. When you push a commit to this repo or PR against it, GitHub actions will run automatically to build and verify the code as updated by the commit/PR. - -## Documentation - -`/docs` folder contains a skeleton version of the project documentation. - -Steps for publishing documentation to the public: -1. If you are using this project template for an individual project, go your fork on GitHub.
- If you are using this project template for a team project, go to the team fork on GitHub. -1. Click on the `settings` tab. -1. Scroll down to the `GitHub Pages` section. -1. Set the `source` as `master branch /docs folder`. -1. Optionally, use the `choose a theme` button to choose a theme for your documentation. +1)Thant Aung Htet Nyan +2)Jerald Gau +3)Jeremiah Ong +4)Yan Zaiya +5)Michelle Liang From 210c231079b8d8bac974c52ab30a1c270c04ee47 Mon Sep 17 00:00:00 2001 From: thant Date: Thu, 2 Mar 2023 11:24:03 +0800 Subject: [PATCH 002/152] Create _config.yml --- docs/_config.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 docs/_config.yml diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000000..13866cfa24 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,3 @@ +remote_theme: pages-themes/cayman@v0.2.0 +plugins: +- jekyll-remote-theme # add this line to the plugins list if you already have one From 2d7d6f2d46a92b659abb6088a04044f407379941 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Thu, 9 Mar 2023 22:16:13 +0800 Subject: [PATCH 003/152] Copy over from iP to serve as base code for Duck --- .gitignore | 1 + src/main/java/seedu/duke/Duck.java | 29 +++ src/main/java/seedu/duke/Duke.java | 21 --- src/main/java/seedu/duke/Parser.java | 86 +++++++++ src/main/java/seedu/duke/Storage.java | 168 ++++++++++++++++++ src/main/java/seedu/duke/TaskList.java | 161 +++++++++++++++++ src/main/java/seedu/duke/Ui.java | 161 +++++++++++++++++ .../exception/IllegalDeadlineException.java | 5 + .../duke/exception/IllegalEventException.java | 5 + .../duke/exception/IllegalTodoException.java | 5 + src/main/java/seedu/duke/task/Deadline.java | 28 +++ src/main/java/seedu/duke/task/Event.java | 39 ++++ src/main/java/seedu/duke/task/Task.java | 65 +++++++ src/main/java/seedu/duke/task/Todo.java | 18 ++ 14 files changed, 771 insertions(+), 21 deletions(-) create mode 100644 src/main/java/seedu/duke/Duck.java delete mode 100644 src/main/java/seedu/duke/Duke.java create mode 100644 src/main/java/seedu/duke/Parser.java create mode 100644 src/main/java/seedu/duke/Storage.java create mode 100644 src/main/java/seedu/duke/TaskList.java create mode 100644 src/main/java/seedu/duke/Ui.java create mode 100644 src/main/java/seedu/duke/exception/IllegalDeadlineException.java create mode 100644 src/main/java/seedu/duke/exception/IllegalEventException.java create mode 100644 src/main/java/seedu/duke/exception/IllegalTodoException.java create mode 100644 src/main/java/seedu/duke/task/Deadline.java create mode 100644 src/main/java/seedu/duke/task/Event.java create mode 100644 src/main/java/seedu/duke/task/Task.java create mode 100644 src/main/java/seedu/duke/task/Todo.java diff --git a/.gitignore b/.gitignore index 2873e189e1..58b16a3a79 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ bin/ /text-ui-test/ACTUAL.TXT text-ui-test/EXPECTED-UNIX.TXT +data/savedata.txt diff --git a/src/main/java/seedu/duke/Duck.java b/src/main/java/seedu/duke/Duck.java new file mode 100644 index 0000000000..b9de41a3ce --- /dev/null +++ b/src/main/java/seedu/duke/Duck.java @@ -0,0 +1,29 @@ +package seedu.duke; + +import seedu.duke.task.Task; + +import java.util.ArrayList; +import java.util.Scanner; + +public class Duck { + + /** Runs the Duke bot */ + private static void runDuck() { + Ui.greetingMessage(); + + ArrayList tasks = new ArrayList<>(); + Storage.tryLoad(tasks); + + String line; + Scanner in = new Scanner(System.in); + line = in.nextLine(); + + Parser.processCommand(tasks, line, in); + + Ui.exitMessage(); + } + + public static void main(String[] args) { + runDuck(); + } +} diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java deleted file mode 100644 index 5c74e68d59..0000000000 --- a/src/main/java/seedu/duke/Duke.java +++ /dev/null @@ -1,21 +0,0 @@ -package seedu.duke; - -import java.util.Scanner; - -public class Duke { - /** - * Main entry-point for the java.duke.Duke application. - */ - public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - System.out.println("What is your name?"); - - Scanner in = new Scanner(System.in); - System.out.println("Hello " + in.nextLine()); - } -} diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java new file mode 100644 index 0000000000..a894c46690 --- /dev/null +++ b/src/main/java/seedu/duke/Parser.java @@ -0,0 +1,86 @@ +package seedu.duke; + +import seedu.duke.task.Task; + +import java.util.ArrayList; +import java.util.Scanner; + +/** + * Deals with making sense of the user command + */ +public class Parser { + + /** + * Returns boolean value of true if input String is an integer, + * else returns boolean value of false + * + * @param word String input to check if it is an integer + * @return true if input String is an integer, otherwise false + */ + public static boolean isNumeric(String word) { + int valueToConvert; + try { + valueToConvert = Integer.parseInt(word); + return true; + } catch (NumberFormatException e) { + System.out.println("Incorrect input, please enter an integer."); + } + return false; + } + + /** + * Processes the user input and executes the appropriate command + * + * @param tasks The array list of tasks + * @param line The line of user input + * @param in The input from scanner + */ + static void processCommand(ArrayList tasks, String line, Scanner in) { + while (!line.equals("bye")) { // Exits the program if input is "bye" + String[] words = line.split(" "); + if (line.isBlank()) { + Ui.emptyCommandMessage(); + } else if (line.equals("list")) { + // List out all the tasks added + Ui.list(tasks); + } else if (words[0].equals("unmark") && (words.length == 2) && (isNumeric(words[1]))) { + // Mark a task as not done + TaskList.unmarkTask(tasks, words); + Storage.trySave(tasks); + } else if (words[0].equals("mark") && (words.length == 2) && (isNumeric(words[1]))) { + // Mark a task as done + TaskList.markTask(tasks, words); + Storage.trySave(tasks); + } else if (words[0].equals("delete") && (words.length == 2) && (isNumeric(words[1]))) { + // Delete a task + TaskList.deleteTask(tasks, words); + Storage.trySave(tasks); + } else if (words[0].equals("find") && (words.length > 1)) { + // Find tasks that contain a keyword + Ui.find(tasks, words); + } else { + // Adding a task to the list + TaskList.addTask(line, tasks); + Task.incrementCount(); + Storage.trySave(tasks); + } + line = in.nextLine(); + } + } + + /** + * Process the array of words from the user input and extracts the + * keywords into a single string to use for the find function + * + * @param words The array of words generated from the user input + * @return The keywords string to use for the find function + */ + static String processKeywords(String[] words) { + String rawKeyword = ""; + for (int i = 1; i < words.length; i++) { + rawKeyword += (" " + words[i]); + } + String keyword = rawKeyword.trim(); + return keyword; + } +} \ No newline at end of file diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duke/Storage.java new file mode 100644 index 0000000000..de262d2d66 --- /dev/null +++ b/src/main/java/seedu/duke/Storage.java @@ -0,0 +1,168 @@ +package seedu.duke; + +import seedu.duke.task.Deadline; +import seedu.duke.task.Event; +import seedu.duke.task.Task; +import seedu.duke.task.Todo; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Scanner; + +/** + * Deals with loading tasks from the file and saving tasks in the file + */ +public class Storage { + static final String SAVEPATH = "data/savedata.txt"; + static final String SAVEFOLDER = "data"; + + /** Load tasks from save data into the list + * + * @param line The line of input from the save file + * @param tasks The array list of tasks + */ + static void loadTask(String line, ArrayList tasks) { + if (line.contains("/by")) { + loadDeadline(line, tasks); + } else if (line.contains("/from") || line.contains("/to")) { + loadEvent(line, tasks); + } else { + loadTodo(line, tasks); + } + } + + /** + * Adds a _Todo_ into the list without generating messages, + * to be used when loading from save data. + * + * @param line The line of input from the save file + * @param tasks The array list of tasks + */ + static void loadTodo(String line, ArrayList tasks) { + Todo currTodo = new Todo(line); + tasks.add(currTodo); + } + + /** + * Adds an event into the list without generating messages, + * to be used when loading from save data. + * + * @param line The line of input from the save file + * @param tasks The array list of tasks + */ + static void loadEvent(String line, ArrayList tasks) { + String description = line.substring(0, line.indexOf("/from")).trim(); + String start = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); + String end = line.substring(line.indexOf("/to") + 3).trim(); + Event currEvent = new Event(description, start, end); + tasks.add(currEvent); + } + + /** + * Adds a deadline into the list without generating messages, + * to be used when loading from save data. + * + * @param line The line of input from the save file + * @param tasks The array list of tasks + */ + static void loadDeadline(String line, ArrayList tasks) { + String description = line.substring(0, line.indexOf("/by")).trim(); + String deadline = line.substring(line.indexOf("/by") + 3).trim(); + Deadline currDeadline = new Deadline(description, deadline); + tasks.add(currDeadline); + } + + /** + * Load the task status of a task from the save data + * + * @param tasks The array list of tasks + * @param doneStatus The done status of the current task + */ + static void loadTaskStatus(ArrayList tasks, String doneStatus) { + int taskNumber = Task.getTaskCount(); + if (doneStatus.equals("1")) { + tasks.get(taskNumber).markAsDone(); + } else { + tasks.get(taskNumber).markAsNotDone(); + } + } + + /** + * Saves the tasks in the list to the save file + * + * @param tasks The array list of tasks + */ + static void save(ArrayList tasks) throws IOException { + File f = new File(SAVEPATH); + if (f.exists()) { + f.delete(); + } + f.createNewFile(); + + FileWriter fw = new FileWriter(SAVEPATH); + for (Task currTask : tasks) { + fw.write(currTask.toSaveString()); + } + fw.close(); + } + + /** + * Try to save, shows error message if saving fails + * + * @param tasks The array list of tasks + */ + static void trySave(ArrayList tasks) { + try { + save(tasks); + } catch (IOException e) { + System.out.println("Saving error."); + } + } + + /** + * Load the save data + * + * @param tasks The array list of tasks + */ + static void load(ArrayList tasks) throws IOException { + File folder = new File(SAVEFOLDER); + if (!folder.exists()) { + new File(SAVEFOLDER).mkdir(); + } + + File f = new File(SAVEPATH); + if (!f.exists()) { + f.createNewFile(); + } + + Scanner s = new Scanner(f); + while (s.hasNext()) { + String line = s.nextLine(); + String[] formattedInput = line.split(" "); + String doneStatus = formattedInput[0]; + String command = ""; + for (int i = 1; i < formattedInput.length; i++) { + command += formattedInput[i]; + command += " "; + } + loadTask(command, tasks); + loadTaskStatus(tasks, doneStatus); + Task.incrementCount(); + } + } + + /** + * Try to load the save data, shows error message if loading fails + * + * @param tasks The array list of tasks + */ + static void tryLoad(ArrayList tasks) { + try { + load(tasks); + } catch (IOException e) { + System.out.println("Error loading save file."); + } + } +} \ No newline at end of file diff --git a/src/main/java/seedu/duke/TaskList.java b/src/main/java/seedu/duke/TaskList.java new file mode 100644 index 0000000000..452b41bf04 --- /dev/null +++ b/src/main/java/seedu/duke/TaskList.java @@ -0,0 +1,161 @@ +package seedu.duke; + +import duke.exception.IllegalDeadlineException; +import duke.exception.IllegalEventException; +import duke.exception.IllegalTodoException; +import seedu.duke.task.Deadline; +import seedu.duke.task.Event; +import seedu.duke.task.Task; +import seedu.duke.task.Todo; + +import java.util.ArrayList; + +/** + * Contains operations to manipulate the task list + */ +public class TaskList { + static void addTask(String line, ArrayList tasks) { + if (line.contains("/by")) { + // Adding a Deadline + try { + addDeadline(line, tasks); + } catch (IllegalDeadlineException e) { + Ui.deadlineErrorMessage(); + } + } else if (line.contains("/from") || line.contains("/to")) { + // Adding an Event + try { + addEvent(line, tasks); + } catch (IllegalEventException e) { + Ui.eventErrorMessage(); + } catch (IndexOutOfBoundsException e) { + Ui.eventErrorMessage(); + } + } else { + // Adding a _Todo_ + try { + addTodo(line, tasks); + } catch (IllegalTodoException e) { + Ui.todoErrorMessage(); + } + } + } + + /** + * Adds a _Todo_ to the list + * + * @param line The line of input from the user + * @param tasks The array list of tasks + */ + static void addTodo(String line, ArrayList tasks) throws IllegalTodoException { + if (line.isBlank()) { + throw new IllegalTodoException(); + } else { + Todo currTodo = new Todo(line); + tasks.add(currTodo); + Ui.addedTaskMessage(currTodo); + } + } + + /** + * Adds an event to the list + * + * @param line The line of input from the user + * @param tasks The array list of tasks + */ + static void addEvent(String line, ArrayList tasks) throws IllegalEventException { + String description = line.substring(0, line.indexOf("/from")).trim(); + String start = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); + String end = line.substring(line.indexOf("/to") + 3).trim(); + if (description.isBlank() || start.isBlank() || end.isBlank()) { + throw new IllegalEventException(); + } else { + Event currEvent = new Event(description, start, end); + tasks.add(currEvent); + Ui.addedTaskMessage(currEvent); + } + } + + /** + * Adds a deadline to the list + * + * @param line The line of input from the user + * @param tasks The array list of tasks + */ + static void addDeadline(String line, ArrayList tasks) throws IllegalDeadlineException { + String description = line.substring(0, line.indexOf("/by")).trim(); + String deadline = line.substring(line.indexOf("/by") + 3).trim(); + //System.out.println(description.isBlank()); + if (description.isBlank() || deadline.isBlank()) { + throw new IllegalDeadlineException(); + } else { + Deadline currDeadline = new Deadline(description, deadline); + tasks.add(currDeadline); + Ui.addedTaskMessage(currDeadline); + } + } + + /** + * Marks a task as done + * + * @param tasks The array list of tasks + * @param words The array of words generated from the user input + */ + static void markTask(ArrayList tasks, String[] words) { + int taskNumber = Integer.parseInt(words[1]); + int taskCount = Task.getTaskCount(); + if (taskNumber > taskCount) { + // Input task number exceeds the number of tasks in the list + Ui.exceedTaskNumberMessage(taskNumber); + } else { + tasks.get(taskNumber - 1).markAsDone(); + // Printing out marked as done message + Ui.borderLine(); + System.out.println("\t Understood. I've marked this task as done:"); + System.out.println("\t " + tasks.get(taskNumber - 1)); + Ui.borderLine(); + } + } + + /** + * Marks a task as not done + * + * @param tasks The array list of tasks + * @param words The array of words generated from the user input + */ + static void unmarkTask(ArrayList tasks, String[] words) { + int taskNumber = Integer.parseInt(words[1]); + int taskCount = Task.getTaskCount(); + if (taskNumber > taskCount) { + // Input task number exceeds the number of tasks in the list + Ui.exceedTaskNumberMessage(taskNumber); + } else { + tasks.get(taskNumber - 1).markAsNotDone(); + // Printing out marked as not done message + Ui.borderLine(); + System.out.println("\t Understood. I've marked this task as not done yet:"); + System.out.println("\t " + tasks.get(taskNumber - 1)); + Ui.borderLine(); + } + } + + /** + * Deletes a task from the list + * + * @param tasks The array list of tasks + * @param words The array of words generated from the user input + */ + static void deleteTask(ArrayList tasks, String[] words) { + int taskNumber = Integer.parseInt(words[1]); + int taskCount = Task.getTaskCount(); + if (taskNumber > taskCount) { + // Input task number exceeds the number of tasks in the list + Ui.exceedTaskNumberMessage(taskNumber); + } else { + Task taskToDelete = tasks.get(taskNumber - 1); + tasks.remove(taskNumber - 1); + Task.decrementCount(); + Ui.deleteTaskMessage(taskToDelete); + } + } +} \ No newline at end of file diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java new file mode 100644 index 0000000000..a4026f0b7b --- /dev/null +++ b/src/main/java/seedu/duke/Ui.java @@ -0,0 +1,161 @@ +package seedu.duke; + +import seedu.duke.task.Task; + +import java.util.ArrayList; + +/** + * Deals with interactions with the user + */ +public class Ui { + + /** + * Prints out all currently stored tasks in the list + * + * @param tasks The array list of tasks + */ + static void list(ArrayList tasks) { + int taskCount = Task.getTaskCount(); + borderLine(); + System.out.println("\t Here are the tasks in your list:"); + for (int i = 0; i < taskCount; i++) { + System.out.println("\t " + (i + 1) + "." + tasks.get(i)); + } + borderLine(); + } + + /** + * Finds tasks in the list that contain keywords input by the user + * + * @param tasks The array list of tasks + * @param words The array of words generated from the user input + */ + static void find(ArrayList tasks, String[] words) { + ArrayList matchingResults = new ArrayList<>(); + int matchCount = 0; + String keyword = Parser.processKeywords(words); + + for (Task task : tasks) { + if (task.getDescription().contains(keyword)) { + matchingResults.add(task); + matchCount++; + } + } + printFindResults(matchingResults, matchCount); + } + + /** + * Prints the results of the find command + * + * @param matchingResults The array list of tasks that contain the keywords + * @param matchCount The number of tasks in the list that contain the keywords + */ + private static void printFindResults(ArrayList matchingResults, int matchCount) { + if (matchingResults.isEmpty()) { + noMatchMessage(); + } else { + printMatchingList(matchingResults, matchCount); + } + } + + /** + * Prints the list of tasks that contain the keywords + * + * @param matchingResults The array list of tasks that contain the keywords + * @param matchCount The number of tasks in the list that contain the keywords + */ + static void printMatchingList(ArrayList matchingResults, int matchCount) { + borderLine(); + System.out.println("\t Here are the matching tasks in your list:"); + for (int i = 0; i < matchCount; i++) { + System.out.println("\t " + (i + 1) + "." + matchingResults.get(i)); + } + borderLine(); + } + + /** Prints the border for opening or closing messages */ + static void borderLine() { + System.out.println("\t____________________________________________________________"); + } + + private static void noMatchMessage() { + borderLine(); + System.out.println("\t There are no matching tasks in your list."); + borderLine(); + } + + static void emptyCommandMessage() { + borderLine(); + System.out.println("\t Please enter a non-empty command."); + borderLine(); + } + + static void addedTaskMessage(Task currentTask) { + borderLine(); + System.out.println("\t Alright, I have added this task: \n\t\t" + currentTask); + System.out.println("\t You now have " + (Task.getTaskCount() + 1) + " tasks in your list."); + borderLine(); + } + + static void deleteTaskMessage(Task taskToDelete) { + borderLine(); + System.out.println("\t Understood. I have removed this task:"); + System.out.println("\t\t" + taskToDelete); + System.out.println("\t You now have " + Task.getTaskCount() + " tasks in your list."); + borderLine(); + } + + static void exceedTaskNumberMessage(int taskNumber) { + borderLine(); + System.out.println("\t Task " + taskNumber + " does not exist."); + borderLine(); + } + + static void todoErrorMessage() { + borderLine(); + System.out.println("\t Error. Please enter a valid description."); + borderLine(); + } + + static void eventErrorMessage() { + borderLine(); + System.out.println("\t Error. Please enter a valid description, start time and end time"); + borderLine(); + } + + static void deadlineErrorMessage() { + borderLine(); + System.out.println("\t Error. Please enter a valid description and deadline."); + borderLine(); + } + + /** Prints the startup message, includes instructions on available commands */ + static void greetingMessage() { + borderLine(); + System.out.println("\t Hello! I'm Vivy."); + System.out.println("\t Here are some commands you can give me:"); + System.out.println("\t - list: I'll list out all the tasks you have recorded."); + System.out.println("\t - mark : I'll mark that task as done."); + System.out.println("\t - unmark : I'll mark that task as undone."); + System.out.println("\t - delete : I'll delete that task from your list."); + System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); + System.out.println("\t - bye: I will shut down my program."); + System.out.println("\t - Anything else will be recorded as a task. \n"); + System.out.println("\t Format for tasks:"); + System.out.println("\t Deadlines: /by "); + System.out.println("\t (eg. Eat bread /by Thursday)"); + System.out.println("\t Events: /from /to "); + System.out.println("\t (eg. Meeting /from March 3 8pm /to 9pm)"); + System.out.println("\t Todo: "); + System.out.println("\t (eg. Water the plants) \n"); + System.out.println("\t What can I do for you?"); + borderLine(); + } + + /** Prints the exiting message when closing the program */ + static void exitMessage() { + borderLine(); + System.out.println("\t Bye. Hope to see you again soon!"); + borderLine(); + } +} \ No newline at end of file diff --git a/src/main/java/seedu/duke/exception/IllegalDeadlineException.java b/src/main/java/seedu/duke/exception/IllegalDeadlineException.java new file mode 100644 index 0000000000..685b3681cf --- /dev/null +++ b/src/main/java/seedu/duke/exception/IllegalDeadlineException.java @@ -0,0 +1,5 @@ +package duke.exception; + +public class IllegalDeadlineException extends Exception { + +} diff --git a/src/main/java/seedu/duke/exception/IllegalEventException.java b/src/main/java/seedu/duke/exception/IllegalEventException.java new file mode 100644 index 0000000000..a7f1bb60e6 --- /dev/null +++ b/src/main/java/seedu/duke/exception/IllegalEventException.java @@ -0,0 +1,5 @@ +package duke.exception; + +public class IllegalEventException extends Exception { + +} diff --git a/src/main/java/seedu/duke/exception/IllegalTodoException.java b/src/main/java/seedu/duke/exception/IllegalTodoException.java new file mode 100644 index 0000000000..3a617cfd78 --- /dev/null +++ b/src/main/java/seedu/duke/exception/IllegalTodoException.java @@ -0,0 +1,5 @@ +package duke.exception; + +public class IllegalTodoException extends Exception { + +} diff --git a/src/main/java/seedu/duke/task/Deadline.java b/src/main/java/seedu/duke/task/Deadline.java new file mode 100644 index 0000000000..7cac37d3bf --- /dev/null +++ b/src/main/java/seedu/duke/task/Deadline.java @@ -0,0 +1,28 @@ +package seedu.duke.task; + +public class Deadline extends Task { + private String by; + + public Deadline(String description, String deadline) { + super(description); + by = deadline; + } + + public void setDeadline(String deadline) { + by = deadline; + } + + public String getDeadline() { + return by; + } + + @Override + public String toSaveString() { + return super.toSaveString() + " /by " + getDeadline() + System.lineSeparator(); + } + + @Override + public String toString() { + return "[D]" + super.toString() + " (by: " + by + ")"; + } +} diff --git a/src/main/java/seedu/duke/task/Event.java b/src/main/java/seedu/duke/task/Event.java new file mode 100644 index 0000000000..3f9adc5313 --- /dev/null +++ b/src/main/java/seedu/duke/task/Event.java @@ -0,0 +1,39 @@ +package seedu.duke.task; + +public class Event extends Task { + private String start; // Start date/time + private String end; // End date/time + + public Event(String description, String start, String end) { + super(description); + this.start = start; + this.end = end; + } + + public String getStart() { + return start; + } + + public void setStart(String start) { + this.start = start; + } + + public String getEnd() { + return end; + } + + public void setEnd(String end) { + this.end = end; + } + + @Override + public String toSaveString() { + return super.toSaveString() + " /from " + getStart() + " /to " + getEnd() + System.lineSeparator(); + } + + @Override + public String toString() { + return "[E]" + super.toString() + " (from: " + start + + " to: " + end + ")"; + } +} diff --git a/src/main/java/seedu/duke/task/Task.java b/src/main/java/seedu/duke/task/Task.java new file mode 100644 index 0000000000..f64e9c992b --- /dev/null +++ b/src/main/java/seedu/duke/task/Task.java @@ -0,0 +1,65 @@ +package seedu.duke.task; + +public class Task { + private String description; + private boolean isDone; + private static int taskCount = 0; + + + public Task(String description) { + this.description = description; + this.isDone = false; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDescription() { + return this.description; + } + + public void markAsDone() { + this.isDone = true; + } + + public void markAsNotDone() { + this.isDone = false; + } + + public String getStatusIcon() { + if(isDone) { + // Mark done task with X + return "X"; + } + return " "; + } + + public static void incrementCount() { + taskCount++; + } + + public static void decrementCount() { + taskCount--; + } + + public static int getTaskCount() { + return taskCount; + } + + public String getDoneConditionString() { + if (isDone) { + return "1"; + } + return "0"; + } + + public String toSaveString() { + return getDoneConditionString() + " " + getDescription(); + } + + @Override + public String toString() { + return "[" + getStatusIcon() + "] " + getDescription(); + } +} diff --git a/src/main/java/seedu/duke/task/Todo.java b/src/main/java/seedu/duke/task/Todo.java new file mode 100644 index 0000000000..8ed7828e7f --- /dev/null +++ b/src/main/java/seedu/duke/task/Todo.java @@ -0,0 +1,18 @@ +package seedu.duke.task; + +public class Todo extends Task { + + public Todo(String description) { + super(description); + } + + @Override + public String toSaveString() { + return super.toSaveString() + System.lineSeparator(); + } + + @Override + public String toString() { + return "[T]" + super.toString(); + } +} From 0d5a591414a6268df65f4d955a663f8e8cd6fd89 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Thu, 9 Mar 2023 22:26:05 +0800 Subject: [PATCH 004/152] Changed class and file names to Duck --- src/main/java/seedu/{duke => duck}/Duck.java | 6 +++--- src/main/java/seedu/{duke => duck}/Parser.java | 4 ++-- src/main/java/seedu/{duke => duck}/Storage.java | 10 +++++----- src/main/java/seedu/{duke => duck}/TaskList.java | 16 ++++++++-------- src/main/java/seedu/{duke => duck}/Ui.java | 6 +++--- .../exception/IllegalDeadlineException.java | 2 +- .../exception/IllegalEventException.java | 2 +- .../exception/IllegalTodoException.java | 2 +- .../java/seedu/{duke => duck}/task/Deadline.java | 2 +- .../java/seedu/{duke => duck}/task/Event.java | 2 +- .../java/seedu/{duke => duck}/task/Task.java | 2 +- .../java/seedu/{duke => duck}/task/Todo.java | 2 +- src/test/java/seedu/{duke => duck}/DukeTest.java | 4 ++-- 13 files changed, 30 insertions(+), 30 deletions(-) rename src/main/java/seedu/{duke => duck}/Duck.java (86%) rename src/main/java/seedu/{duke => duck}/Parser.java (98%) rename src/main/java/seedu/{duke => duck}/Storage.java (97%) rename src/main/java/seedu/{duke => duck}/TaskList.java (94%) rename src/main/java/seedu/{duke => duck}/Ui.java (98%) rename src/main/java/seedu/{duke => duck}/exception/IllegalDeadlineException.java (67%) rename src/main/java/seedu/{duke => duck}/exception/IllegalEventException.java (66%) rename src/main/java/seedu/{duke => duck}/exception/IllegalTodoException.java (65%) rename src/main/java/seedu/{duke => duck}/task/Deadline.java (95%) rename src/main/java/seedu/{duke => duck}/task/Event.java (97%) rename src/main/java/seedu/{duke => duck}/task/Task.java (98%) rename src/main/java/seedu/{duke => duck}/task/Todo.java (92%) rename src/test/java/seedu/{duke => duck}/DukeTest.java (82%) diff --git a/src/main/java/seedu/duke/Duck.java b/src/main/java/seedu/duck/Duck.java similarity index 86% rename from src/main/java/seedu/duke/Duck.java rename to src/main/java/seedu/duck/Duck.java index b9de41a3ce..b1a355717e 100644 --- a/src/main/java/seedu/duke/Duck.java +++ b/src/main/java/seedu/duck/Duck.java @@ -1,13 +1,13 @@ -package seedu.duke; +package seedu.duck; -import seedu.duke.task.Task; +import seedu.duck.task.Task; import java.util.ArrayList; import java.util.Scanner; public class Duck { - /** Runs the Duke bot */ + /** Runs the Duck bot */ private static void runDuck() { Ui.greetingMessage(); diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duck/Parser.java similarity index 98% rename from src/main/java/seedu/duke/Parser.java rename to src/main/java/seedu/duck/Parser.java index a894c46690..9427ef43b6 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -1,6 +1,6 @@ -package seedu.duke; +package seedu.duck; -import seedu.duke.task.Task; +import seedu.duck.task.Task; import java.util.ArrayList; import java.util.Scanner; diff --git a/src/main/java/seedu/duke/Storage.java b/src/main/java/seedu/duck/Storage.java similarity index 97% rename from src/main/java/seedu/duke/Storage.java rename to src/main/java/seedu/duck/Storage.java index de262d2d66..3f05999e04 100644 --- a/src/main/java/seedu/duke/Storage.java +++ b/src/main/java/seedu/duck/Storage.java @@ -1,9 +1,9 @@ -package seedu.duke; +package seedu.duck; -import seedu.duke.task.Deadline; -import seedu.duke.task.Event; -import seedu.duke.task.Task; -import seedu.duke.task.Todo; +import seedu.duck.task.Deadline; +import seedu.duck.task.Event; +import seedu.duck.task.Task; +import seedu.duck.task.Todo; import java.io.File; import java.io.FileWriter; diff --git a/src/main/java/seedu/duke/TaskList.java b/src/main/java/seedu/duck/TaskList.java similarity index 94% rename from src/main/java/seedu/duke/TaskList.java rename to src/main/java/seedu/duck/TaskList.java index 452b41bf04..2d3f33adf0 100644 --- a/src/main/java/seedu/duke/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -1,12 +1,12 @@ -package seedu.duke; +package seedu.duck; -import duke.exception.IllegalDeadlineException; -import duke.exception.IllegalEventException; -import duke.exception.IllegalTodoException; -import seedu.duke.task.Deadline; -import seedu.duke.task.Event; -import seedu.duke.task.Task; -import seedu.duke.task.Todo; +import seedu.duck.exception.IllegalDeadlineException; +import seedu.duck.exception.IllegalEventException; +import seedu.duck.exception.IllegalTodoException; +import seedu.duck.task.Deadline; +import seedu.duck.task.Event; +import seedu.duck.task.Task; +import seedu.duck.task.Todo; import java.util.ArrayList; diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duck/Ui.java similarity index 98% rename from src/main/java/seedu/duke/Ui.java rename to src/main/java/seedu/duck/Ui.java index a4026f0b7b..3c2c093c7a 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -1,6 +1,6 @@ -package seedu.duke; +package seedu.duck; -import seedu.duke.task.Task; +import seedu.duck.task.Task; import java.util.ArrayList; @@ -132,7 +132,7 @@ static void deadlineErrorMessage() { /** Prints the startup message, includes instructions on available commands */ static void greetingMessage() { borderLine(); - System.out.println("\t Hello! I'm Vivy."); + System.out.println("\t Hello! I'm Duck."); System.out.println("\t Here are some commands you can give me:"); System.out.println("\t - list: I'll list out all the tasks you have recorded."); System.out.println("\t - mark : I'll mark that task as done."); diff --git a/src/main/java/seedu/duke/exception/IllegalDeadlineException.java b/src/main/java/seedu/duck/exception/IllegalDeadlineException.java similarity index 67% rename from src/main/java/seedu/duke/exception/IllegalDeadlineException.java rename to src/main/java/seedu/duck/exception/IllegalDeadlineException.java index 685b3681cf..394193a618 100644 --- a/src/main/java/seedu/duke/exception/IllegalDeadlineException.java +++ b/src/main/java/seedu/duck/exception/IllegalDeadlineException.java @@ -1,4 +1,4 @@ -package duke.exception; +package seedu.duck.exception; public class IllegalDeadlineException extends Exception { diff --git a/src/main/java/seedu/duke/exception/IllegalEventException.java b/src/main/java/seedu/duck/exception/IllegalEventException.java similarity index 66% rename from src/main/java/seedu/duke/exception/IllegalEventException.java rename to src/main/java/seedu/duck/exception/IllegalEventException.java index a7f1bb60e6..e3fa7261fa 100644 --- a/src/main/java/seedu/duke/exception/IllegalEventException.java +++ b/src/main/java/seedu/duck/exception/IllegalEventException.java @@ -1,4 +1,4 @@ -package duke.exception; +package seedu.duck.exception; public class IllegalEventException extends Exception { diff --git a/src/main/java/seedu/duke/exception/IllegalTodoException.java b/src/main/java/seedu/duck/exception/IllegalTodoException.java similarity index 65% rename from src/main/java/seedu/duke/exception/IllegalTodoException.java rename to src/main/java/seedu/duck/exception/IllegalTodoException.java index 3a617cfd78..8ac39560e7 100644 --- a/src/main/java/seedu/duke/exception/IllegalTodoException.java +++ b/src/main/java/seedu/duck/exception/IllegalTodoException.java @@ -1,4 +1,4 @@ -package duke.exception; +package seedu.duck.exception; public class IllegalTodoException extends Exception { diff --git a/src/main/java/seedu/duke/task/Deadline.java b/src/main/java/seedu/duck/task/Deadline.java similarity index 95% rename from src/main/java/seedu/duke/task/Deadline.java rename to src/main/java/seedu/duck/task/Deadline.java index 7cac37d3bf..6e525afdba 100644 --- a/src/main/java/seedu/duke/task/Deadline.java +++ b/src/main/java/seedu/duck/task/Deadline.java @@ -1,4 +1,4 @@ -package seedu.duke.task; +package seedu.duck.task; public class Deadline extends Task { private String by; diff --git a/src/main/java/seedu/duke/task/Event.java b/src/main/java/seedu/duck/task/Event.java similarity index 97% rename from src/main/java/seedu/duke/task/Event.java rename to src/main/java/seedu/duck/task/Event.java index 3f9adc5313..11efb53b03 100644 --- a/src/main/java/seedu/duke/task/Event.java +++ b/src/main/java/seedu/duck/task/Event.java @@ -1,4 +1,4 @@ -package seedu.duke.task; +package seedu.duck.task; public class Event extends Task { private String start; // Start date/time diff --git a/src/main/java/seedu/duke/task/Task.java b/src/main/java/seedu/duck/task/Task.java similarity index 98% rename from src/main/java/seedu/duke/task/Task.java rename to src/main/java/seedu/duck/task/Task.java index f64e9c992b..cece90fc9e 100644 --- a/src/main/java/seedu/duke/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -1,4 +1,4 @@ -package seedu.duke.task; +package seedu.duck.task; public class Task { private String description; diff --git a/src/main/java/seedu/duke/task/Todo.java b/src/main/java/seedu/duck/task/Todo.java similarity index 92% rename from src/main/java/seedu/duke/task/Todo.java rename to src/main/java/seedu/duck/task/Todo.java index 8ed7828e7f..481f3d6cb3 100644 --- a/src/main/java/seedu/duke/task/Todo.java +++ b/src/main/java/seedu/duck/task/Todo.java @@ -1,4 +1,4 @@ -package seedu.duke.task; +package seedu.duck.task; public class Todo extends Task { diff --git a/src/test/java/seedu/duke/DukeTest.java b/src/test/java/seedu/duck/DukeTest.java similarity index 82% rename from src/test/java/seedu/duke/DukeTest.java rename to src/test/java/seedu/duck/DukeTest.java index 2dda5fd651..921c055f10 100644 --- a/src/test/java/seedu/duke/DukeTest.java +++ b/src/test/java/seedu/duck/DukeTest.java @@ -1,10 +1,10 @@ -package seedu.duke; +package seedu.duck; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; -class DukeTest { +class DuckTest { @Test public void sampleTest() { assertTrue(true); From 948b17596890624ec5fd7a35ca7bf960e899b954 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Thu, 9 Mar 2023 22:33:26 +0800 Subject: [PATCH 005/152] Fixed a bug causing an error message to be shown when string input is given where an integer input is expected in the user command. --- src/main/java/seedu/duck/Parser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 9427ef43b6..e80a9e0ebc 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -23,7 +23,8 @@ public static boolean isNumeric(String word) { valueToConvert = Integer.parseInt(word); return true; } catch (NumberFormatException e) { - System.out.println("Incorrect input, please enter an integer."); + // Empty catch block, since the only purpose is to return false + // if try block fails. } return false; } From 6b986d0ec21c35f0c3e35240d79baf1af7ed5ce9 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Thu, 9 Mar 2023 22:43:01 +0800 Subject: [PATCH 006/152] Fixed checkstyle errors --- src/main/java/seedu/duck/Parser.java | 2 +- src/main/java/seedu/duck/Storage.java | 5 +++-- src/main/java/seedu/duck/TaskList.java | 2 +- src/main/java/seedu/duck/Ui.java | 2 +- src/main/java/seedu/duck/task/Task.java | 3 +-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index e80a9e0ebc..3a3b3f9456 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -84,4 +84,4 @@ static String processKeywords(String[] words) { String keyword = rawKeyword.trim(); return keyword; } -} \ No newline at end of file +} diff --git a/src/main/java/seedu/duck/Storage.java b/src/main/java/seedu/duck/Storage.java index 3f05999e04..9320a33c15 100644 --- a/src/main/java/seedu/duck/Storage.java +++ b/src/main/java/seedu/duck/Storage.java @@ -18,7 +18,8 @@ public class Storage { static final String SAVEPATH = "data/savedata.txt"; static final String SAVEFOLDER = "data"; - /** Load tasks from save data into the list + /** + * Load tasks from save data into the list * * @param line The line of input from the save file * @param tasks The array list of tasks @@ -165,4 +166,4 @@ static void tryLoad(ArrayList tasks) { System.out.println("Error loading save file."); } } -} \ No newline at end of file +} diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 2d3f33adf0..67f5ca60c0 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -158,4 +158,4 @@ static void deleteTask(ArrayList tasks, String[] words) { Ui.deleteTaskMessage(taskToDelete); } } -} \ No newline at end of file +} diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 3c2c093c7a..aa5bbdc68c 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -158,4 +158,4 @@ static void exitMessage() { System.out.println("\t Bye. Hope to see you again soon!"); borderLine(); } -} \ No newline at end of file +} diff --git a/src/main/java/seedu/duck/task/Task.java b/src/main/java/seedu/duck/task/Task.java index cece90fc9e..0b3fa60a6c 100644 --- a/src/main/java/seedu/duck/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -1,10 +1,9 @@ package seedu.duck.task; public class Task { + private static int taskCount = 0; private String description; private boolean isDone; - private static int taskCount = 0; - public Task(String description) { this.description = description; From 61ffd5f78f8fde0eca9563278b3d0a68606e0dc7 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Thu, 9 Mar 2023 23:16:28 +0800 Subject: [PATCH 007/152] Changed README back to the original text Previously changed README to have changed files to compare with main repo, changing the README back for easier reference. --- README.md | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 80b9d475da..f82e2494b7 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,64 @@ -#Names of Group Members +# Duke project template -1)Thant Aung Htet Nyan -2)Jerald Gau -3)Jeremiah Ong -4)Yan Zaiya -5)Michelle Liang +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 (use the exact version), update Intellij to the most recent version. + +1. **Ensure Intellij JDK 11 is defined as an SDK**, as described [here](https://www.jetbrains.com/help/idea/sdk.html#set-up-jdk) -- this step is not needed if you have used JDK 11 in a previous Intellij project. +1. **Import the project _as a Gradle project_**, as described [here](https://se-education.org/guides/tutorials/intellijImportGradleProject.html). +1. **Verify the set up**: After the importing is complete, locate the `src/main/java/seedu/duke/Duke.java` file, right-click it, and choose `Run Duke.main()`. If the setup is correct, you should see something like the below: + ``` + > Task :compileJava + > Task :processResources NO-SOURCE + > Task :classes + + > Task :Duke.main() + Hello from + ____ _ + | _ \ _ _| | _____ + | | | | | | | |/ / _ \ + | |_| | |_| | < __/ + |____/ \__,_|_|\_\___| + + What is your name? + ``` + Type some word and press enter to let the execution proceed to the end. + +## Build automation using Gradle + +* This project uses Gradle for build automation and dependency management. It includes a basic build script as well (i.e. the `build.gradle` file). +* If you are new to Gradle, refer to the [Gradle Tutorial at se-education.org/guides](https://se-education.org/guides/tutorials/gradle.html). + +## Testing + +### I/O redirection tests + +* To run _I/O redirection_ tests (aka _Text UI tests_), navigate to the `text-ui-test` and run the `runtest(.bat/.sh)` script. + +### JUnit tests + +* A skeleton JUnit test (`src/test/java/seedu/duke/DukeTest.java`) is provided with this project template. +* If you are new to JUnit, refer to the [JUnit Tutorial at se-education.org/guides](https://se-education.org/guides/tutorials/junit.html). + +## Checkstyle + +* A sample CheckStyle rule configuration is provided in this project. +* If you are new to Checkstyle, refer to the [Checkstyle Tutorial at se-education.org/guides](https://se-education.org/guides/tutorials/checkstyle.html). + +## CI using GitHub Actions + +The project uses [GitHub actions](https://github.com/features/actions) for CI. When you push a commit to this repo or PR against it, GitHub actions will run automatically to build and verify the code as updated by the commit/PR. + +## Documentation + +`/docs` folder contains a skeleton version of the project documentation. + +Steps for publishing documentation to the public: +1. If you are using this project template for an individual project, go your fork on GitHub.
+ If you are using this project template for a team project, go to the team fork on GitHub. +1. Click on the `settings` tab. +1. Scroll down to the `GitHub Pages` section. +1. Set the `source` as `master branch /docs folder`. +1. Optionally, use the `choose a theme` button to choose a theme for your documentation. From 365cd2a2cbd4566b0bec265a3a351999a1dd1459 Mon Sep 17 00:00:00 2001 From: "DESKTOP-D6UGRNL\\Luluna" Date: Sat, 11 Mar 2023 15:39:48 +0800 Subject: [PATCH 008/152] Added date time tracking for Duck inputs --- src/main/java/seedu/duck/Parser.java | 3 + src/main/java/seedu/duck/TaskList.java | 55 ++++++++++++----- src/main/java/seedu/duck/Ui.java | 59 +++++++++++++------ .../duck/exception/expiredDateException.java | 5 ++ .../exception/startAfterEndException.java | 5 ++ 5 files changed, 95 insertions(+), 32 deletions(-) create mode 100644 src/main/java/seedu/duck/exception/expiredDateException.java create mode 100644 src/main/java/seedu/duck/exception/startAfterEndException.java diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 3a3b3f9456..58a0132ec2 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -44,6 +44,9 @@ static void processCommand(ArrayList tasks, String line, Scanner in) { } else if (line.equals("list")) { // List out all the tasks added Ui.list(tasks); + } else if (line.equals("help")) { + // List out all the tasks added + Ui.help(); } else if (words[0].equals("unmark") && (words.length == 2) && (isNumeric(words[1]))) { // Mark a task as not done TaskList.unmarkTask(tasks, words); diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 67f5ca60c0..f8cfc622b4 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -1,13 +1,14 @@ package seedu.duck; -import seedu.duck.exception.IllegalDeadlineException; -import seedu.duck.exception.IllegalEventException; -import seedu.duck.exception.IllegalTodoException; +import seedu.duck.exception.*; import seedu.duck.task.Deadline; import seedu.duck.task.Event; import seedu.duck.task.Task; import seedu.duck.task.Todo; +import java.time.DateTimeException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; /** @@ -21,15 +22,27 @@ static void addTask(String line, ArrayList tasks) { addDeadline(line, tasks); } catch (IllegalDeadlineException e) { Ui.deadlineErrorMessage(); + } catch (expiredDateException e) { + Ui.expiredErrorMessage(); + } catch (DateTimeException e) { + System.out.println("Please check the inputted format human!\n" + + "There are only 24 hours in a day in Duck World, and 12 months a year...\n"); + System.out.println("\t Please try again!"); } } else if (line.contains("/from") || line.contains("/to")) { // Adding an Event try { addEvent(line, tasks); - } catch (IllegalEventException e) { - Ui.eventErrorMessage(); - } catch (IndexOutOfBoundsException e) { + } catch (IllegalEventException | IndexOutOfBoundsException e) { Ui.eventErrorMessage(); + } catch (expiredDateException e) { + Ui.expiredErrorMessage(); + } catch (startAfterEndException e) { + Ui.startAfterEndErrorMessage(); + } catch (DateTimeException e) { + System.out.println("Please check the inputted format human!\n" + + "There are only 24 hours in a day in Duck World, and 12 months a year...\n"); + System.out.println("\t Please try again!"); } } else { // Adding a _Todo_ @@ -63,14 +76,22 @@ static void addTodo(String line, ArrayList tasks) throws IllegalTodoExcept * @param line The line of input from the user * @param tasks The array list of tasks */ - static void addEvent(String line, ArrayList tasks) throws IllegalEventException { + static void addEvent(String line, ArrayList tasks) throws IllegalEventException, startAfterEndException, + expiredDateException { String description = line.substring(0, line.indexOf("/from")).trim(); - String start = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); - String end = line.substring(line.indexOf("/to") + 3).trim(); - if (description.isBlank() || start.isBlank() || end.isBlank()) { + String startString = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); + String endString = line.substring(line.indexOf("/to") + 3).trim(); + DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); + LocalDateTime start = LocalDateTime.parse(startString, dateFormat); + LocalDateTime end = LocalDateTime.parse(endString, dateFormat); + if (start.isAfter(end)) { + throw new startAfterEndException(); + } else if (start.isBefore(LocalDateTime.now()) || end.isBefore(LocalDateTime.now())) { + throw new expiredDateException(); + } else if (description.isBlank() || startString.isBlank() || endString.isBlank()) { throw new IllegalEventException(); } else { - Event currEvent = new Event(description, start, end); + Event currEvent = new Event(description, startString, endString); tasks.add(currEvent); Ui.addedTaskMessage(currEvent); } @@ -82,14 +103,18 @@ static void addEvent(String line, ArrayList tasks) throws IllegalEventExce * @param line The line of input from the user * @param tasks The array list of tasks */ - static void addDeadline(String line, ArrayList tasks) throws IllegalDeadlineException { + static void addDeadline(String line, ArrayList tasks) throws IllegalDeadlineException, expiredDateException { String description = line.substring(0, line.indexOf("/by")).trim(); - String deadline = line.substring(line.indexOf("/by") + 3).trim(); + String deadlineString = line.substring(line.indexOf("/by") + 3).trim(); + DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); + LocalDateTime deadline = LocalDateTime.parse(deadlineString, dateFormat); //System.out.println(description.isBlank()); - if (description.isBlank() || deadline.isBlank()) { + if (description.isBlank() || deadlineString.isBlank()) { throw new IllegalDeadlineException(); + } else if (deadline.isBefore(LocalDateTime.now())) { + throw new expiredDateException(); } else { - Deadline currDeadline = new Deadline(description, deadline); + Deadline currDeadline = new Deadline(description, deadlineString); tasks.add(currDeadline); Ui.addedTaskMessage(currDeadline); } diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index aa5bbdc68c..df470ca1fb 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -90,6 +90,26 @@ static void emptyCommandMessage() { borderLine(); } + static void help() { + borderLine(); + System.out.println("\t (`・v・´ ): Here are the commands you can give me:"); + System.out.println("\t - list: I'll list out all the tasks you have recorded."); + System.out.println("\t - mark : I'll mark that task as done."); + System.out.println("\t - unmark : I'll mark that task as undone."); + System.out.println("\t - delete : I'll delete that task from your list."); + System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); + System.out.println("\t - bye: I will shut down my program."); + System.out.println("\t Here are the following ways to input tasks:"); + System.out.println("\t Deadlines: /by "); + System.out.println("\t (eg. Eat bread /by 2023-03-15 2015)"); + System.out.println("\t Events: /from /to "); + System.out.println("\t (eg. Meeting /from 2023-03-15 2015 /to 2023-03-15 2215)"); + System.out.println("\t Todo: "); + System.out.println("\t (eg. Water the plants) \n"); + System.out.println("\t (`・v・´ ): How else may I assist you today, human?"); + borderLine(); + } + static void addedTaskMessage(Task currentTask) { borderLine(); System.out.println("\t Alright, I have added this task: \n\t\t" + currentTask); @@ -117,6 +137,22 @@ static void todoErrorMessage() { borderLine(); } + static void expiredErrorMessage() { + borderLine(); + System.out.println("\t Quack! I know humans wish to undo their past mistakes, " + + "but the start date has already passed!"); + System.out.println("\t Please try again!"); + borderLine(); + } + + static void startAfterEndErrorMessage() { + borderLine(); + System.out.println("\t Quack! Somehow this human has time travelled, " + + "and the start date seems to be after the end date! "); + System.out.println("\t Please try again!"); + borderLine(); + } + static void eventErrorMessage() { borderLine(); System.out.println("\t Error. Please enter a valid description, start time and end time"); @@ -132,23 +168,12 @@ static void deadlineErrorMessage() { /** Prints the startup message, includes instructions on available commands */ static void greetingMessage() { borderLine(); - System.out.println("\t Hello! I'm Duck."); - System.out.println("\t Here are some commands you can give me:"); - System.out.println("\t - list: I'll list out all the tasks you have recorded."); - System.out.println("\t - mark : I'll mark that task as done."); - System.out.println("\t - unmark : I'll mark that task as undone."); - System.out.println("\t - delete : I'll delete that task from your list."); - System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); - System.out.println("\t - bye: I will shut down my program."); - System.out.println("\t - Anything else will be recorded as a task. \n"); - System.out.println("\t Format for tasks:"); - System.out.println("\t Deadlines: /by "); - System.out.println("\t (eg. Eat bread /by Thursday)"); - System.out.println("\t Events: /from /to "); - System.out.println("\t (eg. Meeting /from March 3 8pm /to 9pm)"); - System.out.println("\t Todo: "); - System.out.println("\t (eg. Water the plants) \n"); - System.out.println("\t What can I do for you?"); + System.out.println("\t (`・v・´ ): Nice to meet you human. As you can see, I'm a Duck."); + System.out.println("\t (´˘v˘´ ): As a Duck, I can only understand simple commands. " + + "Human speech is so confusing!"); + System.out.println("\t (´˘v˘´ ): That being said, I am a smart Duck. " + + "If you wish to know what I understand, just enter 'help'."); + System.out.println("\t (`・v・´ ): How may I assist you today, human?"); borderLine(); } diff --git a/src/main/java/seedu/duck/exception/expiredDateException.java b/src/main/java/seedu/duck/exception/expiredDateException.java new file mode 100644 index 0000000000..f34db55da8 --- /dev/null +++ b/src/main/java/seedu/duck/exception/expiredDateException.java @@ -0,0 +1,5 @@ +package seedu.duck.exception; + +public class expiredDateException extends Exception { + +} diff --git a/src/main/java/seedu/duck/exception/startAfterEndException.java b/src/main/java/seedu/duck/exception/startAfterEndException.java new file mode 100644 index 0000000000..a81a5f10d7 --- /dev/null +++ b/src/main/java/seedu/duck/exception/startAfterEndException.java @@ -0,0 +1,5 @@ +package seedu.duck.exception; + +public class startAfterEndException extends Exception { + +} From f1c0a87f4ee653bcf734bab230063f6db35c077f Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Wed, 15 Mar 2023 16:20:21 +0800 Subject: [PATCH 009/152] Refactored wrong date/time format message into the Ui class, and added borderlines. --- src/main/java/seedu/duck/TaskList.java | 8 ++------ src/main/java/seedu/duck/Ui.java | 9 +++++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index f8cfc622b4..c9bf2ac24c 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -25,9 +25,7 @@ static void addTask(String line, ArrayList tasks) { } catch (expiredDateException e) { Ui.expiredErrorMessage(); } catch (DateTimeException e) { - System.out.println("Please check the inputted format human!\n" + - "There are only 24 hours in a day in Duck World, and 12 months a year...\n"); - System.out.println("\t Please try again!"); + Ui.invalidDateTimeMessage(); } } else if (line.contains("/from") || line.contains("/to")) { // Adding an Event @@ -40,9 +38,7 @@ static void addTask(String line, ArrayList tasks) { } catch (startAfterEndException e) { Ui.startAfterEndErrorMessage(); } catch (DateTimeException e) { - System.out.println("Please check the inputted format human!\n" + - "There are only 24 hours in a day in Duck World, and 12 months a year...\n"); - System.out.println("\t Please try again!"); + Ui.invalidDateTimeMessage(); } } else { // Adding a _Todo_ diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index df470ca1fb..775214fe54 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -165,6 +165,14 @@ static void deadlineErrorMessage() { borderLine(); } + static void invalidDateTimeMessage() { + borderLine(); + System.out.println("\t Please check the inputted format human!\n" + + "\t There are only 24 hours in a day in Duck World, and 12 months a year...\n"); + System.out.println("\t Please try again!"); + borderLine(); + } + /** Prints the startup message, includes instructions on available commands */ static void greetingMessage() { borderLine(); @@ -183,4 +191,5 @@ static void exitMessage() { System.out.println("\t Bye. Hope to see you again soon!"); borderLine(); } + } From f29775ba0f0520e90181e90e435b5b7fd04bb84d Mon Sep 17 00:00:00 2001 From: "LAPTOP-D5S3B81V\\thant" Date: Wed, 15 Mar 2023 16:45:46 +0800 Subject: [PATCH 010/152] Added -clear function with double check capacity -priority variable that is saved to datafile also -priority function that changes this priorty variable -list function updated to include priority --- src/main/java/seedu/duck/Duck.java | 6 ++-- src/main/java/seedu/duck/Parser.java | 21 +++++++++++++- src/main/java/seedu/duck/Storage.java | 37 +++++++++++++++++++++++-- src/main/java/seedu/duck/TaskList.java | 16 +++++++++++ src/main/java/seedu/duck/Ui.java | 19 +++++++++++++ src/main/java/seedu/duck/task/Task.java | 29 +++++++++++++++++-- 6 files changed, 119 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/duck/Duck.java b/src/main/java/seedu/duck/Duck.java index b1a355717e..9b28405850 100644 --- a/src/main/java/seedu/duck/Duck.java +++ b/src/main/java/seedu/duck/Duck.java @@ -2,13 +2,15 @@ import seedu.duck.task.Task; +import java.io.IOException; import java.util.ArrayList; import java.util.Scanner; public class Duck { + /** Runs the Duck bot */ - private static void runDuck() { + private static void runDuck() throws IOException { Ui.greetingMessage(); ArrayList tasks = new ArrayList<>(); @@ -23,7 +25,7 @@ private static void runDuck() { Ui.exitMessage(); } - public static void main(String[] args) { + public static void main(String[] args) throws IOException { runDuck(); } } diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 58a0132ec2..b98460b734 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -2,6 +2,7 @@ import seedu.duck.task.Task; +import java.io.IOException; import java.util.ArrayList; import java.util.Scanner; @@ -36,7 +37,7 @@ public static boolean isNumeric(String word) { * @param line The line of user input * @param in The input from scanner */ - static void processCommand(ArrayList tasks, String line, Scanner in) { + static void processCommand(ArrayList tasks, String line, Scanner in) throws IOException { while (!line.equals("bye")) { // Exits the program if input is "bye" String[] words = line.split(" "); if (line.isBlank()) { @@ -62,6 +63,24 @@ static void processCommand(ArrayList tasks, String line, Scanner in) { } else if (words[0].equals("find") && (words.length > 1)) { // Find tasks that contain a keyword Ui.find(tasks, words); + } else if (words[0].equals("priority") && (words.length == 3)) { + // Find tasks that contain a keyword + TaskList.setPriority(tasks,words); + Storage.trySave(tasks); + } else if (words[0].equals("clear")) { + if (Ui.doubleCheck()) { + // Find tasks that contain a keyword + tasks.clear(); + Task.clearCount(); + Ui.borderLine(); + System.out.println("\tGot it, all tasks have been cleared."); + Ui.borderLine(); + Storage.clearTask(); + } else { + Ui.borderLine(); + System.out.println("\t Process cancelled."); + Ui.borderLine(); + } } else { // Adding a task to the list TaskList.addTask(line, tasks); diff --git a/src/main/java/seedu/duck/Storage.java b/src/main/java/seedu/duck/Storage.java index 9320a33c15..00b6af8565 100644 --- a/src/main/java/seedu/duck/Storage.java +++ b/src/main/java/seedu/duck/Storage.java @@ -7,6 +7,7 @@ import java.io.File; import java.io.FileWriter; +import java.io.PrintWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Scanner; @@ -33,6 +34,29 @@ static void loadTask(String line, ArrayList tasks) { loadTodo(line, tasks); } } + static void clearTask() throws IOException { + { + + try { + + FileWriter fw = new FileWriter(SAVEPATH, false); + + PrintWriter pw = new PrintWriter(fw, false); + + pw.flush(); + + pw.close(); + + fw.close(); + + } catch (Exception exception) { + + System.out.println("Exception have been caught"); + + } + + } + } /** * Adds a _Todo_ into the list without generating messages, @@ -42,7 +66,10 @@ static void loadTask(String line, ArrayList tasks) { * @param tasks The array list of tasks */ static void loadTodo(String line, ArrayList tasks) { - Todo currTodo = new Todo(line); + String description = line.substring(0, line.indexOf("

")).trim(); + Todo currTodo = new Todo(description); + String priority = line.substring(line.indexOf("

") + 3).trim(); + currTodo.setPriority(priority); tasks.add(currTodo); } @@ -54,10 +81,12 @@ static void loadTodo(String line, ArrayList tasks) { * @param tasks The array list of tasks */ static void loadEvent(String line, ArrayList tasks) { - String description = line.substring(0, line.indexOf("/from")).trim(); + String description = line.substring(0, line.indexOf("/from")-5).trim(); String start = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); String end = line.substring(line.indexOf("/to") + 3).trim(); Event currEvent = new Event(description, start, end); + String priority = line.substring(line.indexOf("

") + 3,line.indexOf("

") + 4).trim(); + currEvent.setPriority(priority); tasks.add(currEvent); } @@ -69,9 +98,11 @@ static void loadEvent(String line, ArrayList tasks) { * @param tasks The array list of tasks */ static void loadDeadline(String line, ArrayList tasks) { - String description = line.substring(0, line.indexOf("/by")).trim(); + String description = line.substring(0, line.indexOf("/by")-5).trim(); String deadline = line.substring(line.indexOf("/by") + 3).trim(); Deadline currDeadline = new Deadline(description, deadline); + String priority = line.substring(line.indexOf("

") + 3,line.indexOf("

") + 4).trim(); + currDeadline.setPriority(priority); tasks.add(currDeadline); } diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index f8cfc622b4..4f5e54501a 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -70,6 +70,22 @@ static void addTodo(String line, ArrayList tasks) throws IllegalTodoExcept } } + static void setPriority(ArrayList tasks, String[] words) { + int taskNumber = Integer.parseInt(words[1]); + int taskCount = Task.getTaskCount(); + if (taskNumber > taskCount) { + // Input task number exceeds the number of tasks in the list + Ui.exceedTaskNumberMessage(taskNumber); + } else { + tasks.get(taskNumber - 1).setPriority(words[2]); + // Printing out marked as done message + Ui.borderLine(); + System.out.println("\t Understood. The task's new priority is:"); + System.out.println("\t " + tasks.get(taskNumber - 1).getPriority()); + Ui.borderLine(); + } + } + /** * Adds an event to the list * diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index df470ca1fb..6c8ece53c7 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -3,6 +3,8 @@ import seedu.duck.task.Task; import java.util.ArrayList; +import java.util.Objects; +import java.util.Scanner; /** * Deals with interactions with the user @@ -24,6 +26,11 @@ static void list(ArrayList tasks) { borderLine(); } + + + + + /** * Finds tasks in the list that contain keywords input by the user * @@ -44,6 +51,7 @@ static void find(ArrayList tasks, String[] words) { printFindResults(matchingResults, matchCount); } + /** * Prints the results of the find command * @@ -90,14 +98,25 @@ static void emptyCommandMessage() { borderLine(); } + static boolean doubleCheck(){ + System.out.println("THIS IS AN IRREVERSIBLE PROCESS. ARE YOU SURE? Y/N"); + Scanner in = new Scanner(System.in); + String line; + line = in.nextLine(); + return Objects.equals(line, "Y"); + } + static void help() { borderLine(); System.out.println("\t (`・v・´ ): Here are the commands you can give me:"); System.out.println("\t - list: I'll list out all the tasks you have recorded."); + System.out.println("\t - clear: The list will be cleared. This in an irreversible process."); System.out.println("\t - mark : I'll mark that task as done."); System.out.println("\t - unmark : I'll mark that task as undone."); System.out.println("\t - delete : I'll delete that task from your list."); System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); + System.out.println("\t - priority <1/2/3>: I'll set the priority of a given task as" + + " 1:Low , 2:Medium and 3:High."); System.out.println("\t - bye: I will shut down my program."); System.out.println("\t Here are the following ways to input tasks:"); System.out.println("\t Deadlines: /by "); diff --git a/src/main/java/seedu/duck/task/Task.java b/src/main/java/seedu/duck/task/Task.java index 0b3fa60a6c..62d6ca2240 100644 --- a/src/main/java/seedu/duck/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -1,23 +1,32 @@ package seedu.duck.task; + public class Task { - private static int taskCount = 0; + private static int taskCount; private String description; + private int priority; private boolean isDone; public Task(String description) { this.description = description; this.isDone = false; + this.priority = 0; } public void setDescription(String description) { this.description = description; } + public void setPriority(String priority) { + this.priority = Integer.parseInt(priority); + } public String getDescription() { return this.description; } + public static void clearCount() { + taskCount = 0;} + public void markAsDone() { this.isDone = true; } @@ -34,6 +43,20 @@ public String getStatusIcon() { return " "; } + public String getPriority() { + if(priority == 1) { + // Mark done task with X + return "Low priority."; + } else if(priority == 2) { + // Mark done task with X + return "Medium priority."; + } else if(priority == 3) { + // Mark done task with X + return "High priority."; + } + return "No priority established."; + } + public static void incrementCount() { taskCount++; } @@ -54,11 +77,11 @@ public String getDoneConditionString() { } public String toSaveString() { - return getDoneConditionString() + " " + getDescription(); + return getDoneConditionString() + " " + getDescription() + "

" + this.priority; } @Override public String toString() { - return "[" + getStatusIcon() + "] " + getDescription(); + return "[" + getStatusIcon() + "] " + getDescription() + " (" + getPriority() + ")"; } } From bbc49565a8e5ca3ca97a3fafff45c924baef0453 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Wed, 15 Mar 2023 20:50:48 +0800 Subject: [PATCH 011/152] Added SchoolClass task --- src/main/java/seedu/duck/Storage.java | 24 ++++++++ src/main/java/seedu/duck/TaskList.java | 42 ++++++++++++++ src/main/java/seedu/duck/Ui.java | 6 ++ .../IllegalSchoolClassException.java | 4 ++ .../java/seedu/duck/task/SchoolClass.java | 55 +++++++++++++++++++ 5 files changed, 131 insertions(+) create mode 100644 src/main/java/seedu/duck/exception/IllegalSchoolClassException.java create mode 100644 src/main/java/seedu/duck/task/SchoolClass.java diff --git a/src/main/java/seedu/duck/Storage.java b/src/main/java/seedu/duck/Storage.java index 9320a33c15..770ef92dea 100644 --- a/src/main/java/seedu/duck/Storage.java +++ b/src/main/java/seedu/duck/Storage.java @@ -1,13 +1,19 @@ package seedu.duck; +import seedu.duck.exception.IllegalSchoolClassException; +import seedu.duck.exception.expiredDateException; +import seedu.duck.exception.startAfterEndException; import seedu.duck.task.Deadline; import seedu.duck.task.Event; +import seedu.duck.task.SchoolClass; import seedu.duck.task.Task; import seedu.duck.task.Todo; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Scanner; @@ -27,6 +33,8 @@ public class Storage { static void loadTask(String line, ArrayList tasks) { if (line.contains("/by")) { loadDeadline(line, tasks); + } else if (line.contains("/class")) { + loadSchoolClass(line, tasks); } else if (line.contains("/from") || line.contains("/to")) { loadEvent(line, tasks); } else { @@ -61,6 +69,22 @@ static void loadEvent(String line, ArrayList tasks) { tasks.add(currEvent); } + /** + * Adds a schoolClass to the list without generating messages, + * to be used when loading from save data. + * + * @param line The line of input from the user + * @param tasks The array list of tasks + */ + static void loadSchoolClass(String line, ArrayList tasks) { + String description = line.substring(0, line.indexOf("/class")).trim(); + String className = line.substring(line.indexOf("/class") + 6, line.indexOf("/from")).trim(); + String startString = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); + String endString = line.substring(line.indexOf("/to") + 3).trim(); + SchoolClass currSchoolClass = new SchoolClass(className, description, startString, endString); + tasks.add(currSchoolClass); + } + /** * Adds a deadline into the list without generating messages, * to be used when loading from save data. diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index c9bf2ac24c..0d26b7c94b 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -3,6 +3,7 @@ import seedu.duck.exception.*; import seedu.duck.task.Deadline; import seedu.duck.task.Event; +import seedu.duck.task.SchoolClass; import seedu.duck.task.Task; import seedu.duck.task.Todo; @@ -27,6 +28,19 @@ static void addTask(String line, ArrayList tasks) { } catch (DateTimeException e) { Ui.invalidDateTimeMessage(); } + } else if (line.contains("/class")){ + // Adding a SchoolClass + try { + addSchoolClass(line, tasks); + } catch (IllegalSchoolClassException | IndexOutOfBoundsException e) { + Ui.eventErrorMessage(); + } catch (expiredDateException e) { + Ui.expiredErrorMessage(); + } catch (startAfterEndException e) { + Ui.startAfterEndErrorMessage(); + } catch (DateTimeException e) { + Ui.invalidDateTimeMessage(); + } } else if (line.contains("/from") || line.contains("/to")) { // Adding an Event try { @@ -93,6 +107,34 @@ static void addEvent(String line, ArrayList tasks) throws IllegalEventExce } } + /** + * Adds a schoolClass to the list + * + * @param line The line of input from the user + * @param tasks The array list of tasks + */ + static void addSchoolClass(String line, ArrayList tasks) throws IllegalSchoolClassException, startAfterEndException, + expiredDateException { + String description = line.substring(0, line.indexOf("/class")).trim(); + String className = line.substring(line.indexOf("/class") + 6, line.indexOf("/from")).trim(); + String startString = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); + String endString = line.substring(line.indexOf("/to") + 3).trim(); + DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); + LocalDateTime start = LocalDateTime.parse(startString, dateFormat); + LocalDateTime end = LocalDateTime.parse(endString, dateFormat); + if (start.isAfter(end)) { + throw new startAfterEndException(); + } else if (start.isBefore(LocalDateTime.now()) || end.isBefore(LocalDateTime.now())) { + throw new expiredDateException(); + } else if (className.isBlank() || startString.isBlank() || endString.isBlank()) { + throw new IllegalSchoolClassException(); + } else { + SchoolClass currSchoolClass = new SchoolClass(className, description, startString, endString); + tasks.add(currSchoolClass); + Ui.addedTaskMessage(currSchoolClass); + } + } + /** * Adds a deadline to the list * diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 775214fe54..b6d99a35d0 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -165,6 +165,12 @@ static void deadlineErrorMessage() { borderLine(); } + static void schoolClassErrorMessage() { + borderLine(); + System.out.println("\t Error. Please enter a valid class name, description, start time and end time"); + borderLine(); + } + static void invalidDateTimeMessage() { borderLine(); System.out.println("\t Please check the inputted format human!\n" + diff --git a/src/main/java/seedu/duck/exception/IllegalSchoolClassException.java b/src/main/java/seedu/duck/exception/IllegalSchoolClassException.java new file mode 100644 index 0000000000..b5268f20ac --- /dev/null +++ b/src/main/java/seedu/duck/exception/IllegalSchoolClassException.java @@ -0,0 +1,4 @@ +package seedu.duck.exception; + +public class IllegalSchoolClassException extends Exception{ +} diff --git a/src/main/java/seedu/duck/task/SchoolClass.java b/src/main/java/seedu/duck/task/SchoolClass.java new file mode 100644 index 0000000000..3508d8d182 --- /dev/null +++ b/src/main/java/seedu/duck/task/SchoolClass.java @@ -0,0 +1,55 @@ +package seedu.duck.task; + +public class SchoolClass extends Task{ + private String className; // Name of class + private String start; // Start date/time + private String end; // End date/time + + public SchoolClass(String className, String description, String start, String end) { + super(description); + this.className = className; + this.start = start; + this.end = end; + } + + public String getClassName() { + return className; + } + + public void setClassName(String className) { + this.className = className; + } + + public String getStart() { + return start; + } + + public void setStart(String start) { + this.start = start; + } + + public String getEnd() { + return end; + } + + public void setEnd(String end) { + this.end = end; + } + + //todo modify save string to accept schoolClass + @Override + public String toSaveString() { + return super.toSaveString() + " /class " + getClassName() + " /from " + getStart() + " /to " + + getEnd() + System.lineSeparator(); + } + + @Override + public String toString() { + if (getDescription().isBlank()) { + return "[C]" + "[" + getStatusIcon() + "] " + className + " (from: " + start + + " to: " + end + ")"; + } + return "[C]" + "[" + getStatusIcon() + "] " + className + ": " + getDescription() + + " (from: " + start + " to: " + end + ")"; + } +} From e7f31a839502f47976a4e271f5626280753511a5 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Wed, 15 Mar 2023 21:37:12 +0800 Subject: [PATCH 012/152] - Fixed how saving and loading works after implementing the SchoolClass task and priority status. - Added how to add SchoolClasses into the help page. --- src/main/java/seedu/duck/Duck.java | 2 -- src/main/java/seedu/duck/Storage.java | 16 +++++++++------- src/main/java/seedu/duck/Ui.java | 17 +++++++---------- src/main/java/seedu/duck/task/Deadline.java | 4 ++-- src/main/java/seedu/duck/task/Event.java | 5 +++-- src/main/java/seedu/duck/task/SchoolClass.java | 7 +++---- src/main/java/seedu/duck/task/Task.java | 10 +++++++--- src/main/java/seedu/duck/task/Todo.java | 4 ++-- 8 files changed, 33 insertions(+), 32 deletions(-) diff --git a/src/main/java/seedu/duck/Duck.java b/src/main/java/seedu/duck/Duck.java index 9b28405850..b8f6f4ac0a 100644 --- a/src/main/java/seedu/duck/Duck.java +++ b/src/main/java/seedu/duck/Duck.java @@ -7,8 +7,6 @@ import java.util.Scanner; public class Duck { - - /** Runs the Duck bot */ private static void runDuck() throws IOException { Ui.greetingMessage(); diff --git a/src/main/java/seedu/duck/Storage.java b/src/main/java/seedu/duck/Storage.java index 2d94077830..7f121e5297 100644 --- a/src/main/java/seedu/duck/Storage.java +++ b/src/main/java/seedu/duck/Storage.java @@ -89,11 +89,11 @@ static void loadTodo(String line, ArrayList tasks) { * @param tasks The array list of tasks */ static void loadEvent(String line, ArrayList tasks) { - String description = line.substring(0, line.indexOf("/from")-5).trim(); + String description = line.substring(0, line.indexOf("/from")).trim(); String start = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); - String end = line.substring(line.indexOf("/to") + 3).trim(); - Event currEvent = new Event(description, start, end); + String end = line.substring(line.indexOf("/to") + 3, line.indexOf("

")).trim(); String priority = line.substring(line.indexOf("

") + 3,line.indexOf("

") + 4).trim(); + Event currEvent = new Event(description, start, end); currEvent.setPriority(priority); tasks.add(currEvent); } @@ -109,8 +109,10 @@ static void loadSchoolClass(String line, ArrayList tasks) { String description = line.substring(0, line.indexOf("/class")).trim(); String className = line.substring(line.indexOf("/class") + 6, line.indexOf("/from")).trim(); String startString = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); - String endString = line.substring(line.indexOf("/to") + 3).trim(); + String endString = line.substring(line.indexOf("/to") + 3, line.indexOf("

")).trim(); + String priority = line.substring(line.indexOf("

") + 3,line.indexOf("

") + 4).trim(); SchoolClass currSchoolClass = new SchoolClass(className, description, startString, endString); + currSchoolClass.setPriority(priority); tasks.add(currSchoolClass); } @@ -122,10 +124,10 @@ static void loadSchoolClass(String line, ArrayList tasks) { * @param tasks The array list of tasks */ static void loadDeadline(String line, ArrayList tasks) { - String description = line.substring(0, line.indexOf("/by")-5).trim(); - String deadline = line.substring(line.indexOf("/by") + 3).trim(); - Deadline currDeadline = new Deadline(description, deadline); + String description = line.substring(0, line.indexOf("/by")).trim(); + String deadline = line.substring(line.indexOf("/by") + 3, line.indexOf("

")).trim(); String priority = line.substring(line.indexOf("

") + 3,line.indexOf("

") + 4).trim(); + Deadline currDeadline = new Deadline(description, deadline); currDeadline.setPriority(priority); tasks.add(currDeadline); } diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index e1e83d4480..00a9b23383 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -26,11 +26,6 @@ static void list(ArrayList tasks) { borderLine(); } - - - - - /** * Finds tasks in the list that contain keywords input by the user * @@ -115,15 +110,17 @@ static void help() { System.out.println("\t - unmark : I'll mark that task as undone."); System.out.println("\t - delete : I'll delete that task from your list."); System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); - System.out.println("\t - priority <1/2/3>: I'll set the priority of a given task as" + - " 1:Low , 2:Medium and 3:High."); - System.out.println("\t - bye: I will shut down my program."); + System.out.println("\t - priority <1/2/3>: I'll set the priority of a given task as"); + System.out.println("\t 1:Low, 2:Medium and 3:High."); + System.out.println("\t - bye: I will shut down my program.\n"); System.out.println("\t Here are the following ways to input tasks:"); System.out.println("\t Deadlines: /by "); System.out.println("\t (eg. Eat bread /by 2023-03-15 2015)"); - System.out.println("\t Events: /from /to "); + System.out.println("\t Events: /from /to "); System.out.println("\t (eg. Meeting /from 2023-03-15 2015 /to 2023-03-15 2215)"); - System.out.println("\t Todo: "); + System.out.println("\t Classes: /class /from /to "); + System.out.println("\t (eg. Bring laptop /class Cs2113 /from 2023-03-15 1100 /to 2023-03-15 1200)"); + System.out.println("\t Todo: "); System.out.println("\t (eg. Water the plants) \n"); System.out.println("\t (`・v・´ ): How else may I assist you today, human?"); borderLine(); diff --git a/src/main/java/seedu/duck/task/Deadline.java b/src/main/java/seedu/duck/task/Deadline.java index 6e525afdba..71076d7f48 100644 --- a/src/main/java/seedu/duck/task/Deadline.java +++ b/src/main/java/seedu/duck/task/Deadline.java @@ -18,11 +18,11 @@ public String getDeadline() { @Override public String toSaveString() { - return super.toSaveString() + " /by " + getDeadline() + System.lineSeparator(); + return super.toSaveString() + " /by " + getDeadline() + "

" + getPriorityIndex() + System.lineSeparator(); } @Override public String toString() { - return "[D]" + super.toString() + " (by: " + by + ")"; + return "[D]" + super.toString() + " (by: " + by + ")" + " (" + getPriority() + ")"; } } diff --git a/src/main/java/seedu/duck/task/Event.java b/src/main/java/seedu/duck/task/Event.java index 11efb53b03..6c8fccb968 100644 --- a/src/main/java/seedu/duck/task/Event.java +++ b/src/main/java/seedu/duck/task/Event.java @@ -28,12 +28,13 @@ public void setEnd(String end) { @Override public String toSaveString() { - return super.toSaveString() + " /from " + getStart() + " /to " + getEnd() + System.lineSeparator(); + return super.toSaveString() + " /from " + getStart() + " /to " + getEnd() + + "

" + getPriorityIndex() + System.lineSeparator(); } @Override public String toString() { return "[E]" + super.toString() + " (from: " + start - + " to: " + end + ")"; + + " to: " + end + ")" + " (" + getPriority() + ")"; } } diff --git a/src/main/java/seedu/duck/task/SchoolClass.java b/src/main/java/seedu/duck/task/SchoolClass.java index 3508d8d182..78b39aaacd 100644 --- a/src/main/java/seedu/duck/task/SchoolClass.java +++ b/src/main/java/seedu/duck/task/SchoolClass.java @@ -36,20 +36,19 @@ public void setEnd(String end) { this.end = end; } - //todo modify save string to accept schoolClass @Override public String toSaveString() { return super.toSaveString() + " /class " + getClassName() + " /from " + getStart() + " /to " - + getEnd() + System.lineSeparator(); + + getEnd() + "

" + getPriorityIndex() + System.lineSeparator(); } @Override public String toString() { if (getDescription().isBlank()) { return "[C]" + "[" + getStatusIcon() + "] " + className + " (from: " + start - + " to: " + end + ")"; + + " to: " + end + ")" + " (" + getPriority() + ")"; } return "[C]" + "[" + getStatusIcon() + "] " + className + ": " + getDescription() + - " (from: " + start + " to: " + end + ")"; + " (from: " + start + " to: " + end + ")" + " (" + getPriority() + ")"; } } diff --git a/src/main/java/seedu/duck/task/Task.java b/src/main/java/seedu/duck/task/Task.java index 62d6ca2240..f0672267bc 100644 --- a/src/main/java/seedu/duck/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -44,7 +44,7 @@ public String getStatusIcon() { } public String getPriority() { - if(priority == 1) { + if (priority == 1) { // Mark done task with X return "Low priority."; } else if(priority == 2) { @@ -57,6 +57,10 @@ public String getPriority() { return "No priority established."; } + public int getPriorityIndex() { + return this.priority; + } + public static void incrementCount() { taskCount++; } @@ -77,11 +81,11 @@ public String getDoneConditionString() { } public String toSaveString() { - return getDoneConditionString() + " " + getDescription() + "

" + this.priority; + return getDoneConditionString() + " " + getDescription(); } @Override public String toString() { - return "[" + getStatusIcon() + "] " + getDescription() + " (" + getPriority() + ")"; + return "[" + getStatusIcon() + "] " + getDescription(); } } diff --git a/src/main/java/seedu/duck/task/Todo.java b/src/main/java/seedu/duck/task/Todo.java index 481f3d6cb3..2bbae233d7 100644 --- a/src/main/java/seedu/duck/task/Todo.java +++ b/src/main/java/seedu/duck/task/Todo.java @@ -8,11 +8,11 @@ public Todo(String description) { @Override public String toSaveString() { - return super.toSaveString() + System.lineSeparator(); + return super.toSaveString() + "

" + getPriorityIndex() + System.lineSeparator(); } @Override public String toString() { - return "[T]" + super.toString(); + return "[T]" + super.toString() + " (" + getPriority() + ")"; } } From ba9ef643bd52a1c21ecfb930474b7367e8de3b5a Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Wed, 15 Mar 2023 21:59:02 +0800 Subject: [PATCH 013/152] minor ui fix in error messages --- src/main/java/seedu/duck/Parser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index b98460b734..8ccdff0662 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -73,7 +73,7 @@ static void processCommand(ArrayList tasks, String line, Scanner in) throw tasks.clear(); Task.clearCount(); Ui.borderLine(); - System.out.println("\tGot it, all tasks have been cleared."); + System.out.println("\t Got it, all tasks have been cleared."); Ui.borderLine(); Storage.clearTask(); } else { From b3126c50836a96725f692b63d5c52a57ecff355e Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Wed, 15 Mar 2023 22:06:01 +0800 Subject: [PATCH 014/152] Fixed the index out of bounds bug --- src/main/java/seedu/duck/Parser.java | 1 - src/main/java/seedu/duck/TaskList.java | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 8ccdff0662..2e85fab016 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -84,7 +84,6 @@ static void processCommand(ArrayList tasks, String line, Scanner in) throw } else { // Adding a task to the list TaskList.addTask(line, tasks); - Task.incrementCount(); Storage.trySave(tasks); } line = in.nextLine(); diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index e56195919e..f113193a48 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -21,6 +21,7 @@ static void addTask(String line, ArrayList tasks) { // Adding a Deadline try { addDeadline(line, tasks); + Task.incrementCount(); } catch (IllegalDeadlineException e) { Ui.deadlineErrorMessage(); } catch (expiredDateException e) { @@ -32,6 +33,7 @@ static void addTask(String line, ArrayList tasks) { // Adding a SchoolClass try { addSchoolClass(line, tasks); + Task.incrementCount(); } catch (IllegalSchoolClassException | IndexOutOfBoundsException e) { Ui.eventErrorMessage(); } catch (expiredDateException e) { @@ -45,6 +47,7 @@ static void addTask(String line, ArrayList tasks) { // Adding an Event try { addEvent(line, tasks); + Task.incrementCount(); } catch (IllegalEventException | IndexOutOfBoundsException e) { Ui.eventErrorMessage(); } catch (expiredDateException e) { @@ -58,6 +61,7 @@ static void addTask(String line, ArrayList tasks) { // Adding a _Todo_ try { addTodo(line, tasks); + Task.incrementCount(); } catch (IllegalTodoException e) { Ui.todoErrorMessage(); } From ea760c4158fc3d3d68ff4e3f53341a46ba81c422 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Wed, 15 Mar 2023 22:15:48 +0800 Subject: [PATCH 015/152] minor ui fix --- META-INF/MANIFEST.MF | 3 +++ src/main/java/seedu/duck/Ui.java | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 META-INF/MANIFEST.MF diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..b2d2c29e06 --- /dev/null +++ b/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: seedu.duck.Duck + diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 00a9b23383..fa47176da2 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -119,7 +119,7 @@ static void help() { System.out.println("\t Events: /from /to "); System.out.println("\t (eg. Meeting /from 2023-03-15 2015 /to 2023-03-15 2215)"); System.out.println("\t Classes: /class /from /to "); - System.out.println("\t (eg. Bring laptop /class Cs2113 /from 2023-03-15 1100 /to 2023-03-15 1200)"); + System.out.println("\t (eg. Bring laptop /class CS2113 /from 2023-03-15 1100 /to 2023-03-15 1200)"); System.out.println("\t Todo: "); System.out.println("\t (eg. Water the plants) \n"); System.out.println("\t (`・v・´ ): How else may I assist you today, human?"); From f3554807573ceed52092c856c8ec0e4b21886026 Mon Sep 17 00:00:00 2001 From: tliangac Date: Tue, 21 Mar 2023 23:16:22 +0800 Subject: [PATCH 016/152] Display upcoming deadline --- src/main/java/seedu/duck/Duck.java | 2 +- src/main/java/seedu/duck/Ui.java | 106 +++++++++++++++++++++++++++-- 2 files changed, 101 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/duck/Duck.java b/src/main/java/seedu/duck/Duck.java index b8f6f4ac0a..c254c8c6f1 100644 --- a/src/main/java/seedu/duck/Duck.java +++ b/src/main/java/seedu/duck/Duck.java @@ -13,7 +13,7 @@ private static void runDuck() throws IOException { ArrayList tasks = new ArrayList<>(); Storage.tryLoad(tasks); - + Ui.displayUpcomingDeadline(tasks); String line; Scanner in = new Scanner(System.in); line = in.nextLine(); diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index fa47176da2..f991dc25ab 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -1,8 +1,12 @@ package seedu.duck; +import seedu.duck.task.Deadline; import seedu.duck.task.Task; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.Objects; import java.util.Scanner; @@ -51,7 +55,7 @@ static void find(ArrayList tasks, String[] words) { * Prints the results of the find command * * @param matchingResults The array list of tasks that contain the keywords - * @param matchCount The number of tasks in the list that contain the keywords + * @param matchCount The number of tasks in the list that contain the keywords */ private static void printFindResults(ArrayList matchingResults, int matchCount) { if (matchingResults.isEmpty()) { @@ -65,7 +69,7 @@ private static void printFindResults(ArrayList matchingResults, int matchC * Prints the list of tasks that contain the keywords * * @param matchingResults The array list of tasks that contain the keywords - * @param matchCount The number of tasks in the list that contain the keywords + * @param matchCount The number of tasks in the list that contain the keywords */ static void printMatchingList(ArrayList matchingResults, int matchCount) { borderLine(); @@ -76,7 +80,93 @@ static void printMatchingList(ArrayList matchingResults, int matchCount) { borderLine(); } - /** Prints the border for opening or closing messages */ + /** + * Display upcoming deadline + * + * @param tasks tasks store in the file + */ + static void displayUpcomingDeadline(ArrayList tasks) { + System.out.println("\t Here are the upcoming deadline: "); + int count = 0; + for (int i = 0; i < tasks.size(); i++) { + if (tasks.get(i) instanceof Deadline) { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); + String deadline = ((Deadline) tasks.get(i)).getDeadline(); + Date d = null; + Date n = new Date(); + try { + d = format.parse(deadline); + } catch (ParseException e) { + e.printStackTrace(); + } + long diff = d.getTime() - n.getTime(); + String di = TimeDiff(diff); + String description = tasks.get(i).getDescription().replace("deadline ", ""); + System.out.println("\t " + (count + 1) + "." + description+" ("+di+"before the deadline)"); + count++; + } + } + borderLine(); + } + + /** + * Function help for calculating time difference + * @param timeDifferenceMilliseconds time difference between now and deadline + * @return time difference in structured format + */ + static String TimeDiff(long timeDifferenceMilliseconds) { + long diffMinutes = timeDifferenceMilliseconds / (60 * 1000) % 60; + long diffHours = timeDifferenceMilliseconds / (60 * 60 * 1000) % 60; + long diffDays = timeDifferenceMilliseconds / (60 * 60 * 1000 * 24) % 24; + long diffMonths = (long) ((timeDifferenceMilliseconds / (60 * 60 * 1000 * 24 * 30.41666666)) % 30.41666666); + long diffYears = timeDifferenceMilliseconds / ((long) 60 * 60 * 1000 * 24 * 365) % 365; + String result = ""; + if (diffYears != 0) { + result += diffYears; + result += " year"; + if (diffYears != 1) { + result += "s"; + } + result += " "; + } + if (diffMonths != 0) { + result += diffMonths; + result += " month"; + if (diffMonths != 1) { + result += "s"; + } + result += " "; + } + if (diffDays != 0) { + result += diffDays; + result += " day"; + if (diffDays != 1) { + result += "s"; + } + result += " "; + } + if (diffHours != 0) { + result += diffHours; + result += " hour"; + if (diffHours != 1) { + result += "s"; + } + result += " "; + } + if (diffMinutes != 0) { + result += diffMinutes; + result += " minute"; + if (diffMinutes != 1) { + result += "s"; + } + result += " "; + } + return result; + } + + /** + * Prints the border for opening or closing messages + */ static void borderLine() { System.out.println("\t____________________________________________________________"); } @@ -93,7 +183,7 @@ static void emptyCommandMessage() { borderLine(); } - static boolean doubleCheck(){ + static boolean doubleCheck() { System.out.println("THIS IS AN IRREVERSIBLE PROCESS. ARE YOU SURE? Y/N"); Scanner in = new Scanner(System.in); String line; @@ -195,7 +285,9 @@ static void invalidDateTimeMessage() { borderLine(); } - /** Prints the startup message, includes instructions on available commands */ + /** + * Prints the startup message, includes instructions on available commands + */ static void greetingMessage() { borderLine(); System.out.println("\t (`・v・´ ): Nice to meet you human. As you can see, I'm a Duck."); @@ -207,7 +299,9 @@ static void greetingMessage() { borderLine(); } - /** Prints the exiting message when closing the program */ + /** + * Prints the exiting message when closing the program + */ static void exitMessage() { borderLine(); System.out.println("\t Bye. Hope to see you again soon!"); From 3a7f5a11e68b09ec2a34e3b23c9d1766524c557b Mon Sep 17 00:00:00 2001 From: thant Date: Wed, 22 Mar 2023 15:29:09 +0800 Subject: [PATCH 017/152] Add files via upload Skeleton files for diagrams used in DG --- docs/tP Diagram Editable.pptx | Bin 0 -> 67073 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/tP Diagram Editable.pptx diff --git a/docs/tP Diagram Editable.pptx b/docs/tP Diagram Editable.pptx new file mode 100644 index 0000000000000000000000000000000000000000..9edf2886beae05f203b853d29d7987046cefa2da GIT binary patch literal 67073 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 literal 0 HcmV?d00001 From 4e71fda0bd85d9d787ddf16a9bb8342691b98fde Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Wed, 22 Mar 2023 17:17:50 +0800 Subject: [PATCH 018/152] Update Developer Guide Added description of the SchoolClass Task and its associated functions. --- docs/DeveloperGuide.md | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 64e1f0ed2b..7147c0a887 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -6,8 +6,37 @@ ## Design & implementation -{Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} +### SchoolClass Feature +**Implementation** + +The ```SchoolClass``` Class is implemented to facilitate the adding of students' classes to the task list. It extends the ```Task``` Class with additional String attributes to store the class name, start date/time, and end date/time. It also overrides the ```toString()``` method to have its own specialised output when being printed, as well as overriding the ```toSaveString()``` method to have correctly save its details to the save file. The ```SchoolClass``` Class will also facilitate the implementation of automatically recurring classes, which is a planned feature for milestone v2.0. ```SchoolClass``` Tasks will be added by default as recurring tasks to the task list, and will be automatically added back at their same set timing each week. + +The following are the new operations implemented. + +- ```TaskList#addSchoolClass()``` - Adds a SchoolClass Task to the task list. + +- ```Ui#addedTaskMessage()``` - Outputs a message to show that the SchoolClass Task was successfully added to the task list + +- ```Storage#loadSchoolClass()``` - Adds a SchoolClass to the task list without generating a successfully added message, to be used when loading from the save data. + +
+ +**Given below is an example usage scenario for TaskList#addSchoolClass().** + +Step 1. The user inputs a command following the proper formatting for adding a ```SchoolClass```. The Duck class will call ```Parser#processCommand()```, instantiating a ```Parser``` class, which will then call ```TaskList#addTask()```, instantiating a ```TaskList``` Class. From there, ```TaskList#addSchoolClass()``` is called and a new ```SchoolClass``` Task is instantiated, which calls ```Ui#addedTaskMessage()``` and instantiating a ```Ui``` Class. This ```SchoolClass``` Task will thus be added to the ArrayList tasks that was instantiated in the ```Duck``` class. + +![](https://lh4.googleusercontent.com/u4zVr8TYxFw3rMvnqdwCYlJmq0JxUgEtC_cFmOY7rPqCM9nvzcQL1t-GcTmgbedeVEHi2L6MG6xG3QaJ7XaOPs8nYvHz1Uf4wGK9bMsHDHwxZVNdS2zR79TtHL_Ub2Za0_jm6bUsnY_RQWX6QmFqCl4) + +![](https://lh3.googleusercontent.com/owAwOcAeTYadanERD7zj2eVD_SsbxhXUvohhaV962-DfYkgh-fV4wWVv8LnLjPpt9jl3yEkBrVUuiPg7jor-uWSpIhwdze4C3yKMWdRQEYrcR7I6tW4RMIGeyazNhEYUZzTd2BTBqUNpKL-6O2KRXug) + +
+ +**Given below is an example usage scenario for Storage#loadSchoolClass.** + +Step 1. The user launches the application. The task list will be initialised with the data from a given pre-existing datafile if it exists, and the ```SchoolClass``` items will be inserted into the task list if they exist using ```Storage#loadSchoolClass()```. + +
## Product scope ### Target user profile From 96f67cd397e96465c5b9a3d1fbe6436a4cd65cd6 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Wed, 22 Mar 2023 17:21:06 +0800 Subject: [PATCH 019/152] Updated Diagrams for DG --- docs/tP Diagram Editable.pptx | Bin 67073 -> 71531 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/tP Diagram Editable.pptx b/docs/tP Diagram Editable.pptx index 9edf2886beae05f203b853d29d7987046cefa2da..6858af68a0b2b5b995a303c3f6b1bdef3754f574 100644 GIT binary patch delta 15431 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 Date: Wed, 22 Mar 2023 17:39:37 +0800 Subject: [PATCH 020/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 7147c0a887..b602175407 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -6,6 +6,8 @@ ## Design & implementation +This section describes how Duck is implemented and how its commands are executed. + ### SchoolClass Feature **Implementation** From 2e19906c42b8ef054f11f40b8450c91466befe2f Mon Sep 17 00:00:00 2001 From: thant Date: Wed, 22 Mar 2023 17:41:15 +0800 Subject: [PATCH 021/152] Update DeveloperGuide.md updated --- docs/DeveloperGuide.md | 140 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index b602175407..29b49210f9 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -4,10 +4,150 @@ {list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well} +##Architecture + +![](https://lh3.googleusercontent.com/FwYOJJpyhNrHNAUjWo1grnsWCDHdKMosDWaJaI_3kqtVbfD8108yk0MeJaybK3ac0MOAL3EVKYYCUjSiAbBrwAT8wRBkPTj2UDfw3AdhPT0fB8twOxfRDfh3BGAawOUOUlt-rxSACvVOhvqRnFamqWM) + +The **Architecture Diagram** given above explains the high-level design of Duck. + +Given below is a quick overview of main components and how they interact with each other. + +
+ +**Main components of the architecture** + +```Duck``` is responsible for: + +- At app launch:  + +- Executes the ```Ui#greetingMessage()``` operation. + +- Initializes a new ArrayList tasks  + +- Populates the ArrayList by executing the ```Storage#tryLoad()``` operation. + +- Begins scanning for user inputs, and passing these inputs to ```Parser``` class. + +- At shut down: Shuts down the components and invokes the ```Ui#exitMessage()``` operation. + +```Commons``` represents a collection of classes used by multiple other components, such as ```java.time.LocalDateTime``` + +The rest of the App consists of four components. + +- ```UI```: The UI of the App. + +- ```Parser```: The command executor. + +- ```TaskList```: Holds the data of Duck in memory. + +- This stores 4 subsequent subclasses that draw upon a shared superclass. + +- ```Task```: The skeleton superclass of all Tasks.  + +- ```ToDo```: Basic form of ```Task``` + +- ```Deadline```: Expands upon ```Task``` by storing a ```by``` variable + +- ```Event```: Expands upon ```Task``` by storing ```start``` and ```end``` variable + +- ```SchoolClass```: Expands upon ```Task``` by storing ```start``` and ```end``` variable, along with a ```className``` variable + +- ```Storage```: Reads data from, and writes data to, the hard disk. + ## Design & implementation This section describes how Duck is implemented and how its commands are executed. +### Purge feature + +**Implementation** + +The ```TaskList#purge()``` command will be implemented to facilitate the removal of expired ```Task``` items from the ```TaskList```. This will be executed once upon Duck's startup, and can be further executed by inputting the term ```purge``` into the CLI when Duck is running. The following is the new operation to be implemented. + +- ```TaskList#purge()``` - Navigates through the ```TaskList``` array, and checks the date/time of each Task item within. If the date/time of a given ```Task``` has passed, it will be removed from the ```TaskList``` array. The user will be then able to view a total of how many ```Tasks``` were purged, along with what ```Task``` they were. + +
+ +**Given below is an example usage scenario for ```purge()```** + +Step 1. The user launches the application for the first time. The ```TaskList``` will be initialized with the data from a given pre-existing datafile if it exists, and the ```Task``` items will be inserted into the ```TaskList```.![](https://lh5.googleusercontent.com/XcnArNZc5ZqHhxXZ1iRuq0aRxNKkcD_snVgDv-dlpMVYFQFQjyGXdtHWvFGzG-k2UW5SXkjQbthIRtkrol_SYsNgmsmKw1kKEkME0vSQ0tfRfUIWj3jZTTVrerHbESuA-AlTpPEkj8JrKl-mMlu-3yM) + +Step 2. The ```TaskList#purge()``` command will be executed. The user will see an output in the following format: + +![](https://lh3.googleusercontent.com/Kbz7j3EmMGJGrIX1aQ8DCkHG8Y3gaIx3Ohf-zmYvr-S-LrxRqt8P1wlTMWUnlnna2tnR0i72yUJWB72Z2mWwGuwXiD_RnlIpYEk-MY6k9zMaLqTk_VkyHaRwIuzxi1trXHX1ySdZWBqZFDaCZ6K-QrY) + +![](https://lh4.googleusercontent.com/kVOcvIKAF1nlLSHXQsRPDuG6RwiyaqRXf9CYTLrv2WUezegCNx05GIC1KPYME6Eojid1hRbqUIzHUjKWRpYjUG7zCYE8586kLzbIrVdjZVnC5j_1ke1WBdFZSHoar_MuXKBA9eMARxCOgcja5qjP2_A) + +The user will see this on his terminal after the ```purge``` command has executed. + +| + +----------------------------------------------------------------------\ +Quack! Tasks have expired! Purge proceeding..\ +2\. [X if , " " if !] \ +4\. [X if , " " if !] + +Purge Completed! Now we are one quack closer to finishing all tasks!\ +---------------------------------------------------------------------- + + | + +Step 3. The ```Duck``` will continue to run as per usual. The user can choose to manually input the keyword purge into the CLI to repeat Step 2 above at any given time. + +
+ +### Clear feature + +**Implementation** + +The ```Storage#clear()``` command was implemented to facilitate the removal of all ```Task``` items from the ```TaskList```. Upon the entry of the keyword ```clear```, the new operation ```Ui#doubleCheck``` will prompt the user for an input of ```Y/N```. + +- If a ```Y``` is inputted, the operation ```Storage#clear()``` executes and removes all ```Task``` items from the ```TaskList```. Additionally, the ```savedata``` file located in ```\data\savedata.txt``` will also be deleted and recreated as a blank slate. + +- If a ```N``` is inputted, the operation ```Storage#clear()``` executes and removes all ```Task``` items from the ```TaskList```. Additionally, the ```savedata``` file located in ```\data\savedata.txt``` will also be deleted and recreated as a blank slate. + +
+ + The following are the new operations implemented. + +- ```Storage#clear()``` - Removes all ```Task``` items from the ```TaskList```. Additionally, the ```savedata``` file located in ```\data\savedata.txt``` will also be deleted and recreated as a blank slate. + +- ```Ui#doubleCheck``` - Prompts the user for further input. If a ```Y``` is inputted, the ```Storage#clear()``` operation is executed. Else if a ```N``` is inputted, the operation is cancelled. + +
+ +Given below is an example usage scenario for ```Storage#clear()``` + +Step 1. The user launches the application for the first time. The ```TaskList``` will be initialised with the data from a given pre-existing datafile if it exists, and the ```Task``` items will be inserted into the ```TaskList```.![](https://lh5.googleusercontent.com/XcnArNZc5ZqHhxXZ1iRuq0aRxNKkcD_snVgDv-dlpMVYFQFQjyGXdtHWvFGzG-k2UW5SXkjQbthIRtkrol_SYsNgmsmKw1kKEkME0vSQ0tfRfUIWj3jZTTVrerHbESuA-AlTpPEkj8JrKl-mMlu-3yM) + +Step 2. The user wants to start afresh. The ```Storage#clear()```  command is then executed. The user will see an output in the following format: + +| + +THIS IS AN IRREVERSIBLE PROCESS. ARE YOU SURE? Y/N + + | + +Step 3.1. The user decides against clearing the ```TaskList```, and inputs a ```N```. The ```TaskList``` has no changes. ```Duck``` resumes after the output in the following format has been displayed: + +| + +Process cancelled. + + | + +Step 3.2. The user decides upon clearing the ```TaskList```, and inputs a ```Y```. The ```TaskList``` has been cleared. + +![](https://lh4.googleusercontent.com/G4PalSoaVQxExSGKCDefJuO4TlyCJwrCfZDT4BsTrrSHMJ8aQSPsaxGoFJYb9YIO1yo3_3nV0Jar3Haqfac90v7G_yfZdx8-OwxSKEART5zLqMZ73k3YW0ssPbIE3kOhkbeusR3jVMdD6kTSkG7rK4s) + +```Duck``` resumes after the output in the following format has been displayed: + +| + +Got it, all tasks have been cleared. + + | + ### SchoolClass Feature **Implementation** From 08ee5022d1b6e39550ff9156862ec065790badea Mon Sep 17 00:00:00 2001 From: thant Date: Wed, 22 Mar 2023 17:42:45 +0800 Subject: [PATCH 022/152] Update DeveloperGuide.md edits to match style --- docs/DeveloperGuide.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 29b49210f9..61ee804e34 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -4,7 +4,7 @@ {list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well} -##Architecture +## Architecture ![](https://lh3.googleusercontent.com/FwYOJJpyhNrHNAUjWo1grnsWCDHdKMosDWaJaI_3kqtVbfD8108yk0MeJaybK3ac0MOAL3EVKYYCUjSiAbBrwAT8wRBkPTj2UDfw3AdhPT0fB8twOxfRDfh3BGAawOUOUlt-rxSACvVOhvqRnFamqWM) @@ -80,8 +80,7 @@ Step 2. The ```TaskList#purge()``` command will be executed. The user will see a The user will see this on his terminal after the ```purge``` command has executed. -| - +``` ----------------------------------------------------------------------\ Quack! Tasks have expired! Purge proceeding..\ 2\. [X if , " " if !] \ @@ -89,8 +88,8 @@ Quack! Tasks have expired! Purge proceeding..\ Purge Completed! Now we are one quack closer to finishing all tasks!\ ---------------------------------------------------------------------- +``` - | Step 3. The ```Duck``` will continue to run as per usual. The user can choose to manually input the keyword purge into the CLI to repeat Step 2 above at any given time. @@ -122,19 +121,17 @@ Step 1. The user launches the application for the first time. The ```TaskList``` Step 2. The user wants to start afresh. The ```Storage#clear()```  command is then executed. The user will see an output in the following format: -| - +``` THIS IS AN IRREVERSIBLE PROCESS. ARE YOU SURE? Y/N - - | +``` Step 3.1. The user decides against clearing the ```TaskList```, and inputs a ```N```. The ```TaskList``` has no changes. ```Duck``` resumes after the output in the following format has been displayed: -| +``` Process cancelled. - | +``` Step 3.2. The user decides upon clearing the ```TaskList```, and inputs a ```Y```. The ```TaskList``` has been cleared. @@ -142,11 +139,11 @@ Step 3.2. The user decides upon clearing the ```TaskList```, and inputs a ```Y`` ```Duck``` resumes after the output in the following format has been displayed: -| +``` Got it, all tasks have been cleared. - | + ``` ### SchoolClass Feature From 236fdd25c0acfcae9203acf92c9a987e5ed33dc6 Mon Sep 17 00:00:00 2001 From: thant Date: Wed, 22 Mar 2023 17:44:59 +0800 Subject: [PATCH 023/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 61ee804e34..93d16f876f 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -72,21 +72,24 @@ The ```TaskList#purge()``` command will be implemented to facilitate the removal Step 1. The user launches the application for the first time. The ```TaskList``` will be initialized with the data from a given pre-existing datafile if it exists, and the ```Task``` items will be inserted into the ```TaskList```.![](https://lh5.googleusercontent.com/XcnArNZc5ZqHhxXZ1iRuq0aRxNKkcD_snVgDv-dlpMVYFQFQjyGXdtHWvFGzG-k2UW5SXkjQbthIRtkrol_SYsNgmsmKw1kKEkME0vSQ0tfRfUIWj3jZTTVrerHbESuA-AlTpPEkj8JrKl-mMlu-3yM) -Step 2. The ```TaskList#purge()``` command will be executed. The user will see an output in the following format: +Step 2. The ```TaskList#purge()``` command will be executed. The process is illustrated through two steps: + +Identifying all expired ```Task``` items in ```TaskList```. ![](https://lh3.googleusercontent.com/Kbz7j3EmMGJGrIX1aQ8DCkHG8Y3gaIx3Ohf-zmYvr-S-LrxRqt8P1wlTMWUnlnna2tnR0i72yUJWB72Z2mWwGuwXiD_RnlIpYEk-MY6k9zMaLqTk_VkyHaRwIuzxi1trXHX1ySdZWBqZFDaCZ6K-QrY) +Removing all expired ```Task``` items in ```TaskList```. ![](https://lh4.googleusercontent.com/kVOcvIKAF1nlLSHXQsRPDuG6RwiyaqRXf9CYTLrv2WUezegCNx05GIC1KPYME6Eojid1hRbqUIzHUjKWRpYjUG7zCYE8586kLzbIrVdjZVnC5j_1ke1WBdFZSHoar_MuXKBA9eMARxCOgcja5qjP2_A) The user will see this on his terminal after the ```purge``` command has executed. ``` -----------------------------------------------------------------------\ -Quack! Tasks have expired! Purge proceeding..\ -2\. [X if , " " if !] \ -4\. [X if , " " if !] +---------------------------------------------------------------------- +Quack! Tasks have expired! Purge proceeding... +2. [X if , " " if !] +4. [X if , " " if !] -Purge Completed! Now we are one quack closer to finishing all tasks!\ +Purge Completed! Now we are one quack closer to finishing all tasks! ---------------------------------------------------------------------- ``` From 309412570d025d0e5c079f8976bed867e3845cf5 Mon Sep 17 00:00:00 2001 From: thant Date: Wed, 22 Mar 2023 17:48:06 +0800 Subject: [PATCH 024/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 93d16f876f..04e6f60e52 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -18,7 +18,7 @@ Given below is a quick overview of main components and how they interact with ea ```Duck``` is responsible for: -- At app launch:  +**At app launch:**  - Executes the ```Ui#greetingMessage()``` operation. @@ -70,15 +70,15 @@ The ```TaskList#purge()``` command will be implemented to facilitate the removal **Given below is an example usage scenario for ```purge()```** -Step 1. The user launches the application for the first time. The ```TaskList``` will be initialized with the data from a given pre-existing datafile if it exists, and the ```Task``` items will be inserted into the ```TaskList```.![](https://lh5.googleusercontent.com/XcnArNZc5ZqHhxXZ1iRuq0aRxNKkcD_snVgDv-dlpMVYFQFQjyGXdtHWvFGzG-k2UW5SXkjQbthIRtkrol_SYsNgmsmKw1kKEkME0vSQ0tfRfUIWj3jZTTVrerHbESuA-AlTpPEkj8JrKl-mMlu-3yM) +**Step 1.** The user launches the application for the first time. The ```TaskList``` will be initialized with the data from a given pre-existing datafile if it exists, and the ```Task``` items will be inserted into the ```TaskList```.![](https://lh5.googleusercontent.com/XcnArNZc5ZqHhxXZ1iRuq0aRxNKkcD_snVgDv-dlpMVYFQFQjyGXdtHWvFGzG-k2UW5SXkjQbthIRtkrol_SYsNgmsmKw1kKEkME0vSQ0tfRfUIWj3jZTTVrerHbESuA-AlTpPEkj8JrKl-mMlu-3yM) -Step 2. The ```TaskList#purge()``` command will be executed. The process is illustrated through two steps: +**Step 2.** The ```TaskList#purge()``` command will be executed. The process is illustrated through two steps: -Identifying all expired ```Task``` items in ```TaskList```. +**Identifying all expired ```Task``` items in ```TaskList```.** ![](https://lh3.googleusercontent.com/Kbz7j3EmMGJGrIX1aQ8DCkHG8Y3gaIx3Ohf-zmYvr-S-LrxRqt8P1wlTMWUnlnna2tnR0i72yUJWB72Z2mWwGuwXiD_RnlIpYEk-MY6k9zMaLqTk_VkyHaRwIuzxi1trXHX1ySdZWBqZFDaCZ6K-QrY) -Removing all expired ```Task``` items in ```TaskList```. +**Removing all expired ```Task``` items in ```TaskList```.** ![](https://lh4.googleusercontent.com/kVOcvIKAF1nlLSHXQsRPDuG6RwiyaqRXf9CYTLrv2WUezegCNx05GIC1KPYME6Eojid1hRbqUIzHUjKWRpYjUG7zCYE8586kLzbIrVdjZVnC5j_1ke1WBdFZSHoar_MuXKBA9eMARxCOgcja5qjP2_A) The user will see this on his terminal after the ```purge``` command has executed. @@ -94,7 +94,7 @@ Purge Completed! Now we are one quack closer to finishing all tasks! ``` -Step 3. The ```Duck``` will continue to run as per usual. The user can choose to manually input the keyword purge into the CLI to repeat Step 2 above at any given time. +**Step 3.** The ```Duck``` will continue to run as per usual. The user can choose to manually input the keyword purge into the CLI to repeat Step 2 above at any given time.
@@ -120,15 +120,15 @@ The ```Storage#clear()``` command was implemented to facilitate the removal of a Given below is an example usage scenario for ```Storage#clear()``` -Step 1. The user launches the application for the first time. The ```TaskList``` will be initialised with the data from a given pre-existing datafile if it exists, and the ```Task``` items will be inserted into the ```TaskList```.![](https://lh5.googleusercontent.com/XcnArNZc5ZqHhxXZ1iRuq0aRxNKkcD_snVgDv-dlpMVYFQFQjyGXdtHWvFGzG-k2UW5SXkjQbthIRtkrol_SYsNgmsmKw1kKEkME0vSQ0tfRfUIWj3jZTTVrerHbESuA-AlTpPEkj8JrKl-mMlu-3yM) +**Step 1.** The user launches the application for the first time. The ```TaskList``` will be initialised with the data from a given pre-existing datafile if it exists, and the ```Task``` items will be inserted into the ```TaskList```.![](https://lh5.googleusercontent.com/XcnArNZc5ZqHhxXZ1iRuq0aRxNKkcD_snVgDv-dlpMVYFQFQjyGXdtHWvFGzG-k2UW5SXkjQbthIRtkrol_SYsNgmsmKw1kKEkME0vSQ0tfRfUIWj3jZTTVrerHbESuA-AlTpPEkj8JrKl-mMlu-3yM) -Step 2. The user wants to start afresh. The ```Storage#clear()```  command is then executed. The user will see an output in the following format: +**Step 2.** The user wants to start afresh. The ```Storage#clear()```  command is then executed. The user will see an output in the following format: ``` THIS IS AN IRREVERSIBLE PROCESS. ARE YOU SURE? Y/N ``` -Step 3.1. The user decides against clearing the ```TaskList```, and inputs a ```N```. The ```TaskList``` has no changes. ```Duck``` resumes after the output in the following format has been displayed: +**Step 3.1.** The user decides against clearing the ```TaskList```, and inputs a ```N```. The ```TaskList``` has no changes. ```Duck``` resumes after the output in the following format has been displayed: ``` @@ -136,7 +136,7 @@ Process cancelled. ``` -Step 3.2. The user decides upon clearing the ```TaskList```, and inputs a ```Y```. The ```TaskList``` has been cleared. +**Step 3.2.** The user decides upon clearing the ```TaskList```, and inputs a ```Y```. The ```TaskList``` has been cleared. ![](https://lh4.googleusercontent.com/G4PalSoaVQxExSGKCDefJuO4TlyCJwrCfZDT4BsTrrSHMJ8aQSPsaxGoFJYb9YIO1yo3_3nV0Jar3Haqfac90v7G_yfZdx8-OwxSKEART5zLqMZ73k3YW0ssPbIE3kOhkbeusR3jVMdD6kTSkG7rK4s) @@ -166,7 +166,7 @@ The following are the new operations implemented. **Given below is an example usage scenario for TaskList#addSchoolClass().** -Step 1. The user inputs a command following the proper formatting for adding a ```SchoolClass```. The Duck class will call ```Parser#processCommand()```, instantiating a ```Parser``` class, which will then call ```TaskList#addTask()```, instantiating a ```TaskList``` Class. From there, ```TaskList#addSchoolClass()``` is called and a new ```SchoolClass``` Task is instantiated, which calls ```Ui#addedTaskMessage()``` and instantiating a ```Ui``` Class. This ```SchoolClass``` Task will thus be added to the ArrayList tasks that was instantiated in the ```Duck``` class. +**Step 1.** The user inputs a command following the proper formatting for adding a ```SchoolClass```. The Duck class will call ```Parser#processCommand()```, instantiating a ```Parser``` class, which will then call ```TaskList#addTask()```, instantiating a ```TaskList``` Class. From there, ```TaskList#addSchoolClass()``` is called and a new ```SchoolClass``` Task is instantiated, which calls ```Ui#addedTaskMessage()``` and instantiating a ```Ui``` Class. This ```SchoolClass``` Task will thus be added to the ArrayList tasks that was instantiated in the ```Duck``` class. ![](https://lh4.googleusercontent.com/u4zVr8TYxFw3rMvnqdwCYlJmq0JxUgEtC_cFmOY7rPqCM9nvzcQL1t-GcTmgbedeVEHi2L6MG6xG3QaJ7XaOPs8nYvHz1Uf4wGK9bMsHDHwxZVNdS2zR79TtHL_Ub2Za0_jm6bUsnY_RQWX6QmFqCl4) @@ -176,7 +176,7 @@ Step 1. The user inputs a command following the proper formatting for adding a ` **Given below is an example usage scenario for Storage#loadSchoolClass.** -Step 1. The user launches the application. The task list will be initialised with the data from a given pre-existing datafile if it exists, and the ```SchoolClass``` items will be inserted into the task list if they exist using ```Storage#loadSchoolClass()```. +**Step 1.** The user launches the application. The task list will be initialised with the data from a given pre-existing datafile if it exists, and the ```SchoolClass``` items will be inserted into the task list if they exist using ```Storage#loadSchoolClass()```.
From c7f117a63546c27dbf4614aa4fa6883973f2089e Mon Sep 17 00:00:00 2001 From: thant Date: Wed, 22 Mar 2023 17:49:16 +0800 Subject: [PATCH 025/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 04e6f60e52..ce6034a784 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -40,9 +40,9 @@ The rest of the App consists of four components. - ```TaskList```: Holds the data of Duck in memory. -- This stores 4 subsequent subclasses that draw upon a shared superclass. +```TaskList``` stores items that belong to 4 subclasses that draw upon a shared superclass. -- ```Task```: The skeleton superclass of all Tasks.  +```Task```: The skeleton superclass of all Tasks.  - ```ToDo```: Basic form of ```Task``` From f1baf616769f4befc47a97a3141b92f1178fbdf3 Mon Sep 17 00:00:00 2001 From: thant Date: Wed, 22 Mar 2023 17:50:05 +0800 Subject: [PATCH 026/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index ce6034a784..91e5f6bdf1 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -38,6 +38,8 @@ The rest of the App consists of four components. - ```Parser```: The command executor. +- ```Storage```: Reads data from, and writes data to, the hard disk. + - ```TaskList```: Holds the data of Duck in memory. ```TaskList``` stores items that belong to 4 subclasses that draw upon a shared superclass. @@ -52,8 +54,6 @@ The rest of the App consists of four components. - ```SchoolClass```: Expands upon ```Task``` by storing ```start``` and ```end``` variable, along with a ```className``` variable -- ```Storage```: Reads data from, and writes data to, the hard disk. - ## Design & implementation This section describes how Duck is implemented and how its commands are executed. From 6a4e7a7f726c29ff63f4642d1ea6e6a2c830f1c4 Mon Sep 17 00:00:00 2001 From: "DESKTOP-FM5QJ06\\User" Date: Wed, 22 Mar 2023 18:17:06 +0800 Subject: [PATCH 027/152] Added printing tasks in low, medium and high priority seperately and printing all tasks arranged via their priority --- src/main/java/seedu/duck/Parser.java | 12 ++++ src/main/java/seedu/duck/Ui.java | 93 +++++++++++++++++++++++++ src/main/java/seedu/duck/task/Task.java | 4 ++ 3 files changed, 109 insertions(+) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 2e85fab016..941e748f3e 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -45,6 +45,18 @@ static void processCommand(ArrayList tasks, String line, Scanner in) throw } else if (line.equals("list")) { // List out all the tasks added Ui.list(tasks); + } else if (line.equals("priority_list")){ + // Lists out all the tasks by priority + Ui.printPriorityList(tasks); + } else if (line.equals("low_priority")){ + // Lists out all the tasks that are low in priority + Ui.printLowPriority(tasks); + } else if (line.equals("medium_priority")){ + // Lists out all the tasks that are medium in priority + Ui.printMediumPriority(tasks); + } else if (line.equals("high_priority")){ + // Lists out all the tasks that are high in priority + Ui.printHighPriority(tasks); } else if (line.equals("help")) { // List out all the tasks added Ui.help(); diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index fa47176da2..a12798d9c5 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -26,6 +26,95 @@ static void list(ArrayList tasks) { borderLine(); } + /** + * Prints out all currently stored tasks in the list arranged by their priority from high, medium to low + * + * @param tasks the list of tasks + */ + static void printPriorityList(ArrayList tasks){ + borderLine(); + System.out.println("\t Here are the tasks in your list arranged by priority:"); + borderLine(); + printHighPriority(tasks); + printMediumPriority(tasks); + printLowPriority(tasks); + } + + /** + * Goes through the task list and prints out the tasks that are high in priority + * + * @param tasks the list of tasks + */ + static void printHighPriority(ArrayList tasks){ + ArrayList indexOfHighPriority = new ArrayList(); + int taskCount = Task.getTaskCount(); + for (int i = 0; i < taskCount; i++){ + if (tasks.get(i).returnPriority() == 3) { + indexOfHighPriority.add(i); + } + } + if (!indexOfHighPriority.isEmpty()) { + System.out.println("\t QUACK QUACK QUACK!!!"); + System.out.println("\t You have " + indexOfHighPriority.size() + " tasks that are high in priority!"); + for (int i = 0; i < indexOfHighPriority.size(); i++) { + System.out.println("\t" + (i + 1) + "." + tasks.get(indexOfHighPriority.get(i))); + } + } else { + System.out.println("\t There are no tasks that are high in priority!"); + } + borderLine(); + } + + /** + * Goes through the task list and prints out the tasks that are medium in priority + * + * @param tasks the list of tasks + */ + static void printMediumPriority(ArrayList tasks){ + ArrayList indexOfMediumPriority = new ArrayList(); + int taskCount = Task.getTaskCount(); + for (int i = 0; i < taskCount; i++) { + if (tasks.get(i).returnPriority() == 3) { + indexOfMediumPriority.add(i); + } + } + if (!indexOfMediumPriority.isEmpty()) { + System.out.println("\t QUACK QUACK!!"); + System.out.println("\t You have " + indexOfMediumPriority.size() + " tasks that are medium in priority!"); + for (int i = 0; i < indexOfMediumPriority.size(); i++) { + System.out.println("\t" + (i + 1) + "." + tasks.get(indexOfMediumPriority.get(i))); + } + } else { + System.out.println("\t There are no tasks that are medium in priority!"); + } + borderLine(); + } + + /** + * Goes through the task list and prints out the tasks that are low in priority + * + * @param tasks the list of tasks + */ + static void printLowPriority(ArrayList tasks){ + ArrayList indexOfLowPriority = new ArrayList(); + int taskCount = Task.getTaskCount(); + for (int i = 0; i < taskCount; i++){ + if (tasks.get(i).returnPriority() == 1) { + indexOfLowPriority.add(i); + } + } + if (!indexOfLowPriority.isEmpty()) { + System.out.println("\t quack!"); + System.out.println("\t You have " + indexOfLowPriority.size() + " tasks that are low in priority!"); + for (int i = 0; i < indexOfLowPriority.size(); i++) { + System.out.println("\t" + (i + 1) + "." + tasks.get(indexOfLowPriority.get(i))); + } + } else { + System.out.println("\t There are no tasks that are low in priority!"); + } + borderLine(); + } + /** * Finds tasks in the list that contain keywords input by the user * @@ -105,6 +194,10 @@ static void help() { borderLine(); System.out.println("\t (`・v・´ ): Here are the commands you can give me:"); System.out.println("\t - list: I'll list out all the tasks you have recorded."); + System.out.println("\t - priority_list: I'll list out all the tasks you have recorded arranged by their priority."); + System.out.println("\t - low_priority: I'll list out all the tasks you have that are low in priority."); + System.out.println("\t - medium_priority: I'll list out all the tasks you have that are medium in priority."); + System.out.println("\t - high_priority: I'll list out all the tasks you have that are high in priority."); System.out.println("\t - clear: The list will be cleared. This in an irreversible process."); System.out.println("\t - mark : I'll mark that task as done."); System.out.println("\t - unmark : I'll mark that task as undone."); diff --git a/src/main/java/seedu/duck/task/Task.java b/src/main/java/seedu/duck/task/Task.java index f0672267bc..73caa6ffbc 100644 --- a/src/main/java/seedu/duck/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -57,6 +57,10 @@ public String getPriority() { return "No priority established."; } + public int returnPriority(){ + return this.priority; + } + public int getPriorityIndex() { return this.priority; } From 1ab51231e5fb2afd772f20701874e7301426ecd6 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Wed, 22 Mar 2023 19:20:17 +0800 Subject: [PATCH 028/152] Added junit tests for the Parser class --- src/test/java/seedu/duck/DukeTest.java | 12 ------------ src/test/java/seedu/duck/ParserTest.java | 25 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 12 deletions(-) delete mode 100644 src/test/java/seedu/duck/DukeTest.java create mode 100644 src/test/java/seedu/duck/ParserTest.java diff --git a/src/test/java/seedu/duck/DukeTest.java b/src/test/java/seedu/duck/DukeTest.java deleted file mode 100644 index 921c055f10..0000000000 --- a/src/test/java/seedu/duck/DukeTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package seedu.duck; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.junit.jupiter.api.Test; - -class DuckTest { - @Test - public void sampleTest() { - assertTrue(true); - } -} diff --git a/src/test/java/seedu/duck/ParserTest.java b/src/test/java/seedu/duck/ParserTest.java new file mode 100644 index 0000000000..03402d9687 --- /dev/null +++ b/src/test/java/seedu/duck/ParserTest.java @@ -0,0 +1,25 @@ +package seedu.duck; + +import seedu.duck.Parser; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; + +import org.junit.jupiter.api.Test; + +public class ParserTest { + + String[] words = {"remove", "keyword"}; + + @Test + public void testIsNumeric() { + assertTrue(Parser.isNumeric("2")); + assertTrue(Parser.isNumeric("5")); + assertFalse(Parser.isNumeric("letter")); + } + + @Test + public void testProcessKeywords() { + assertEquals("keyword", Parser.processKeywords(words)); + } +} From 8ba7ebeb0ca93532dded5881debe33a3ed794f86 Mon Sep 17 00:00:00 2001 From: sunkyan Date: Thu, 23 Mar 2023 01:49:15 +0800 Subject: [PATCH 029/152] Improved coding standard and added list-x-days feature --- src/main/java/seedu/duck/Parser.java | 3 ++ src/main/java/seedu/duck/Storage.java | 6 +-- src/main/java/seedu/duck/TaskList.java | 4 +- src/main/java/seedu/duck/Ui.java | 52 ++++++++++++++++++++++++-- 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 2e85fab016..9bdd6a0bce 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -48,6 +48,9 @@ static void processCommand(ArrayList tasks, String line, Scanner in) throw } else if (line.equals("help")) { // List out all the tasks added Ui.help(); + } else if (words[0].equals("list") && (words.length == 2) && (isNumeric(words[1]))) { + //list out all tasks in x days in the future specified by the user + Ui.printUpcomingTasks(tasks, words[1]); } else if (words[0].equals("unmark") && (words.length == 2) && (isNumeric(words[1]))) { // Mark a task as not done TaskList.unmarkTask(tasks, words); diff --git a/src/main/java/seedu/duck/Storage.java b/src/main/java/seedu/duck/Storage.java index 7f121e5297..27abd26f47 100644 --- a/src/main/java/seedu/duck/Storage.java +++ b/src/main/java/seedu/duck/Storage.java @@ -1,8 +1,6 @@ package seedu.duck; -import seedu.duck.exception.IllegalSchoolClassException; -import seedu.duck.exception.expiredDateException; -import seedu.duck.exception.startAfterEndException; + import seedu.duck.task.Deadline; import seedu.duck.task.Event; import seedu.duck.task.SchoolClass; @@ -13,8 +11,6 @@ import java.io.FileWriter; import java.io.PrintWriter; import java.io.IOException; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Scanner; diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index f113193a48..82bfb566c1 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -133,8 +133,8 @@ static void addEvent(String line, ArrayList tasks) throws IllegalEventExce * @param line The line of input from the user * @param tasks The array list of tasks */ - static void addSchoolClass(String line, ArrayList tasks) throws IllegalSchoolClassException, startAfterEndException, - expiredDateException { + static void addSchoolClass(String line, ArrayList tasks) throws IllegalSchoolClassException, + startAfterEndException, expiredDateException { String description = line.substring(0, line.indexOf("/class")).trim(); String className = line.substring(line.indexOf("/class") + 6, line.indexOf("/from")).trim(); String startString = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index f991dc25ab..a4ebb1f1de 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -1,6 +1,8 @@ package seedu.duck; import seedu.duck.task.Deadline; +import seedu.duck.task.Event; +import seedu.duck.task.SchoolClass; import seedu.duck.task.Task; import java.text.ParseException; @@ -100,7 +102,7 @@ static void displayUpcomingDeadline(ArrayList tasks) { e.printStackTrace(); } long diff = d.getTime() - n.getTime(); - String di = TimeDiff(diff); + String di = getTimeDiff(diff); String description = tasks.get(i).getDescription().replace("deadline ", ""); System.out.println("\t " + (count + 1) + "." + description+" ("+di+"before the deadline)"); count++; @@ -109,12 +111,54 @@ static void displayUpcomingDeadline(ArrayList tasks) { borderLine(); } + /** + * Prints the list of tasks in x days in the future + * + * @param tasks the array list of all the tasks + * @param days the required the number of days x from now onwards + */ + static void printUpcomingTasks(ArrayList tasks, String days) { + borderLine(); + System.out.println("\t Here are your tasks in " + days + " days:"); + int count = 0; + Date d = null; + Date n = new Date(); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); + for (int i = 0; i < tasks.size(); i ++) { + String timeUntilTask = null; + if (tasks.get(i) instanceof Deadline) { + timeUntilTask = ((Deadline) tasks.get(i)).getDeadline(); + } else if (tasks.get(i) instanceof Event) { + timeUntilTask = ((Event) tasks.get(i)).getStart(); + } else if (tasks.get(i) instanceof SchoolClass) { + timeUntilTask = ((SchoolClass) tasks.get(i)).getStart(); + } + if (timeUntilTask != null) { + try { + d = format.parse(timeUntilTask); + } catch (ParseException e) { + e.printStackTrace(); + } + long diff = d.getTime() - n.getTime(); + String di = getTimeDiff(diff); + String[] diffSplit = di.split(" "); + if (diffSplit.length >= 2 && ((diffSplit[1].contains("day") && Integer.parseInt(diffSplit[0]) + <= Integer.parseInt(days)) || diffSplit[1].contains("hour") + || diffSplit[1].contains("minute"))) { + count++; + System.out.println("\t " + count + "." + tasks.get(i).toString()); + } + } + } + borderLine(); + } + /** * Function help for calculating time difference * @param timeDifferenceMilliseconds time difference between now and deadline * @return time difference in structured format */ - static String TimeDiff(long timeDifferenceMilliseconds) { + static String getTimeDiff(long timeDifferenceMilliseconds) { long diffMinutes = timeDifferenceMilliseconds / (60 * 1000) % 60; long diffHours = timeDifferenceMilliseconds / (60 * 60 * 1000) % 60; long diffDays = timeDifferenceMilliseconds / (60 * 60 * 1000 * 24) % 24; @@ -195,6 +239,7 @@ static void help() { borderLine(); System.out.println("\t (`・v・´ ): Here are the commands you can give me:"); System.out.println("\t - list: I'll list out all the tasks you have recorded."); + System.out.println("\t - list : I'll list out all the tasks in that number of days."); System.out.println("\t - clear: The list will be cleared. This in an irreversible process."); System.out.println("\t - mark : I'll mark that task as done."); System.out.println("\t - unmark : I'll mark that task as undone."); @@ -208,7 +253,8 @@ static void help() { System.out.println("\t (eg. Eat bread /by 2023-03-15 2015)"); System.out.println("\t Events: /from /to "); System.out.println("\t (eg. Meeting /from 2023-03-15 2015 /to 2023-03-15 2215)"); - System.out.println("\t Classes: /class /from /to "); + System.out.println("\t Classes: /class /from " + + "/to "); System.out.println("\t (eg. Bring laptop /class CS2113 /from 2023-03-15 1100 /to 2023-03-15 1200)"); System.out.println("\t Todo: "); System.out.println("\t (eg. Water the plants) \n"); From 14fa94a295f98ac9d24356e86060fe60644ddca2 Mon Sep 17 00:00:00 2001 From: sunkyan Date: Thu, 23 Mar 2023 01:55:27 +0800 Subject: [PATCH 030/152] changed the star import for exceptions --- src/main/java/seedu/duck/TaskList.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 82bfb566c1..baf5ca8a4d 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -1,6 +1,11 @@ package seedu.duck; -import seedu.duck.exception.*; +import seedu.duck.exception.expiredDateException; +import seedu.duck.exception.IllegalSchoolClassException; +import seedu.duck.exception.IllegalEventException; +import seedu.duck.exception.IllegalDeadlineException; +import seedu.duck.exception.IllegalTodoException; +import seedu.duck.exception.startAfterEndException; import seedu.duck.task.Deadline; import seedu.duck.task.Event; import seedu.duck.task.SchoolClass; From 9eec8ba5f16b02f256e3a13d5c3dc4df2e4a49b2 Mon Sep 17 00:00:00 2001 From: tliangac Date: Thu, 23 Mar 2023 14:12:44 +0800 Subject: [PATCH 031/152] Display Next Upcoming Class --- src/main/java/seedu/duck/Parser.java | 2 + src/main/java/seedu/duck/Ui.java | 71 +++++++++++++++++++++------- 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 9bdd6a0bce..fc15c3a028 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -51,6 +51,8 @@ static void processCommand(ArrayList tasks, String line, Scanner in) throw } else if (words[0].equals("list") && (words.length == 2) && (isNumeric(words[1]))) { //list out all tasks in x days in the future specified by the user Ui.printUpcomingTasks(tasks, words[1]); + } else if (line.equals("upcoming class")) { + Ui.displayNextUpcomingClass(tasks); } else if (words[0].equals("unmark") && (words.length == 2) && (isNumeric(words[1]))) { // Mark a task as not done TaskList.unmarkTask(tasks, words); diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index a4ebb1f1de..36dbc4cbb6 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -94,18 +94,18 @@ static void displayUpcomingDeadline(ArrayList tasks) { if (tasks.get(i) instanceof Deadline) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); String deadline = ((Deadline) tasks.get(i)).getDeadline(); - Date d = null; + Date d; Date n = new Date(); try { d = format.parse(deadline); + long diff = d.getTime() - n.getTime(); + String di = getTimeDiff(diff); + String description = tasks.get(i).getDescription().replace("deadline ", ""); + System.out.println("\t " + (count + 1) + "." + description + " (" + di + "before the deadline)"); + count++; } catch (ParseException e) { e.printStackTrace(); } - long diff = d.getTime() - n.getTime(); - String di = getTimeDiff(diff); - String description = tasks.get(i).getDescription().replace("deadline ", ""); - System.out.println("\t " + (count + 1) + "." + description+" ("+di+"before the deadline)"); - count++; } } borderLine(); @@ -115,16 +115,16 @@ static void displayUpcomingDeadline(ArrayList tasks) { * Prints the list of tasks in x days in the future * * @param tasks the array list of all the tasks - * @param days the required the number of days x from now onwards + * @param days the required the number of days x from now onwards */ static void printUpcomingTasks(ArrayList tasks, String days) { borderLine(); System.out.println("\t Here are your tasks in " + days + " days:"); int count = 0; - Date d = null; + Date d; Date n = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); - for (int i = 0; i < tasks.size(); i ++) { + for (int i = 0; i < tasks.size(); i++) { String timeUntilTask = null; if (tasks.get(i) instanceof Deadline) { timeUntilTask = ((Deadline) tasks.get(i)).getDeadline(); @@ -136,18 +136,18 @@ static void printUpcomingTasks(ArrayList tasks, String days) { if (timeUntilTask != null) { try { d = format.parse(timeUntilTask); + long diff = d.getTime() - n.getTime(); + String di = getTimeDiff(diff); + String[] diffSplit = di.split(" "); + if (diffSplit.length >= 2 && ((diffSplit[1].contains("day") && Integer.parseInt(diffSplit[0]) + <= Integer.parseInt(days)) || diffSplit[1].contains("hour") + || diffSplit[1].contains("minute"))) { + count++; + System.out.println("\t " + count + "." + tasks.get(i).toString()); + } } catch (ParseException e) { e.printStackTrace(); } - long diff = d.getTime() - n.getTime(); - String di = getTimeDiff(diff); - String[] diffSplit = di.split(" "); - if (diffSplit.length >= 2 && ((diffSplit[1].contains("day") && Integer.parseInt(diffSplit[0]) - <= Integer.parseInt(days)) || diffSplit[1].contains("hour") - || diffSplit[1].contains("minute"))) { - count++; - System.out.println("\t " + count + "." + tasks.get(i).toString()); - } } } borderLine(); @@ -155,6 +155,7 @@ static void printUpcomingTasks(ArrayList tasks, String days) { /** * Function help for calculating time difference + * * @param timeDifferenceMilliseconds time difference between now and deadline * @return time difference in structured format */ @@ -208,6 +209,40 @@ static String getTimeDiff(long timeDifferenceMilliseconds) { return result; } + /** + * Display Next Upcoming Class + * + * @param tasks the array list of all the tasks + */ + static void displayNextUpcomingClass(ArrayList tasks) { + borderLine(); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); + Date compare = null; + int index = -1; + System.out.println("\t Here are your next upcoming class: "); + for (int i = 0; i < tasks.size(); i++) { + if (tasks.get(i) instanceof SchoolClass) { + Date d; + try { + d = format.parse(((SchoolClass) tasks.get(i)).getStart()); + if (compare == null || d.before(compare)) { + compare = d; + index = i; + } + } catch (ParseException e) { + e.printStackTrace(); + } + } + } + if (index != -1) { + String re = tasks.get(index).toString().replace("[C][ ]", ""); + System.out.println("\t " + re); + } else { + System.out.println("\t No upcoming class"); + } + borderLine(); + } + /** * Prints the border for opening or closing messages */ From e748d1183b3cf2bf42b56841f7b9441c4ab5646d Mon Sep 17 00:00:00 2001 From: thant Date: Thu, 23 Mar 2023 14:58:22 +0800 Subject: [PATCH 032/152] Purge functionality for removing expired tasks have been implemented. --- build.gradle | 1 + src/main/java/seedu/duck/Duck.java | 1 + src/main/java/seedu/duck/Parser.java | 5 +- src/main/java/seedu/duck/TaskList.java | 86 +++++++++++++++++++-- src/main/java/seedu/duck/Ui.java | 10 +-- src/main/java/seedu/duck/task/Deadline.java | 2 +- src/main/java/seedu/duck/task/Event.java | 2 +- src/main/java/seedu/duck/task/Todo.java | 2 +- 8 files changed, 95 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index d5e548e85f..f5ef89863f 100644 --- a/build.gradle +++ b/build.gradle @@ -43,4 +43,5 @@ checkstyle { run{ standardInput = System.in + enableAssertions = true } diff --git a/src/main/java/seedu/duck/Duck.java b/src/main/java/seedu/duck/Duck.java index c254c8c6f1..ff71b822dd 100644 --- a/src/main/java/seedu/duck/Duck.java +++ b/src/main/java/seedu/duck/Duck.java @@ -13,6 +13,7 @@ private static void runDuck() throws IOException { ArrayList tasks = new ArrayList<>(); Storage.tryLoad(tasks); + TaskList.purge(tasks); Ui.displayUpcomingDeadline(tasks); String line; Scanner in = new Scanner(System.in); diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 9bdd6a0bce..2b69eef539 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -66,6 +66,9 @@ static void processCommand(ArrayList tasks, String line, Scanner in) throw } else if (words[0].equals("find") && (words.length > 1)) { // Find tasks that contain a keyword Ui.find(tasks, words); + } else if (words[0].equals("purge")){ + // Find tasks that contain a keyword + TaskList.purge(tasks); } else if (words[0].equals("priority") && (words.length == 3)) { // Find tasks that contain a keyword TaskList.setPriority(tasks,words); @@ -81,7 +84,7 @@ static void processCommand(ArrayList tasks, String line, Scanner in) throw Storage.clearTask(); } else { Ui.borderLine(); - System.out.println("\t Process cancelled."); + System.out.println("\t Quack! Process cancelled."); Ui.borderLine(); } } else { diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index baf5ca8a4d..fa67287584 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -12,10 +12,13 @@ import seedu.duck.task.Task; import seedu.duck.task.Todo; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.time.DateTimeException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; +import java.util.Date; /** * Contains operations to manipulate the task list @@ -34,7 +37,7 @@ static void addTask(String line, ArrayList tasks) { } catch (DateTimeException e) { Ui.invalidDateTimeMessage(); } - } else if (line.contains("/class")){ + } else if (line.contains("/class")) { // Adding a SchoolClass try { addSchoolClass(line, tasks); @@ -76,7 +79,7 @@ static void addTask(String line, ArrayList tasks) { /** * Adds a _Todo_ to the list * - * @param line The line of input from the user + * @param line The line of input from the user * @param tasks The array list of tasks */ static void addTodo(String line, ArrayList tasks) throws IllegalTodoException { @@ -108,7 +111,7 @@ static void setPriority(ArrayList tasks, String[] words) { /** * Adds an event to the list * - * @param line The line of input from the user + * @param line The line of input from the user * @param tasks The array list of tasks */ static void addEvent(String line, ArrayList tasks) throws IllegalEventException, startAfterEndException, @@ -135,7 +138,7 @@ static void addEvent(String line, ArrayList tasks) throws IllegalEventExce /** * Adds a schoolClass to the list * - * @param line The line of input from the user + * @param line The line of input from the user * @param tasks The array list of tasks */ static void addSchoolClass(String line, ArrayList tasks) throws IllegalSchoolClassException, @@ -163,7 +166,7 @@ static void addSchoolClass(String line, ArrayList tasks) throws IllegalSch /** * Adds a deadline to the list * - * @param line The line of input from the user + * @param line The line of input from the user * @param tasks The array list of tasks */ static void addDeadline(String line, ArrayList tasks) throws IllegalDeadlineException, expiredDateException { @@ -246,4 +249,77 @@ static void deleteTask(ArrayList tasks, String[] words) { Ui.deleteTaskMessage(taskToDelete); } } + + static void purge(ArrayList tasks) { + Ui.borderLine(); + System.out.println("\t Displaying all expired tasks below..."); + System.out.println(); + if (tasks.size() > 0) { + int expiredCount = 0; + ArrayList expiredTasks = new ArrayList(); + for (Task task : tasks) { + if (task instanceof Deadline) { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); + String deadline = ((Deadline) task).getDeadline(); + Date d = null; + Date n = new Date(); + try { + d = format.parse(deadline); + } catch (ParseException e) { + e.printStackTrace(); + } + assert d != null; + long diff = d.getTime() - n.getTime(); + if (diff < 0) { + expiredCount++; + System.out.println(task); + expiredTasks.add(task); + } + } else if (task instanceof Event) { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); + String end = ((Event) task).getEnd(); + Date d = null; + Date n = new Date(); + try { + d = format.parse(end); + } catch (ParseException e) { + e.printStackTrace(); + } + assert d != null; + long diff = d.getTime() - n.getTime(); + if (diff < 0) { + expiredCount++; + System.out.println(task); + expiredTasks.add(task); + } + } + + } + if (expiredCount > 0) { + Ui.borderLine(); + System.out.println("\t Quack! A total of " + expiredCount + " tasks have expired!"); + System.out.println("\t Should I remove these tasks from the pending list human?"); + Ui.borderLine(); + if (Ui.doubleCheck()) { + for (Task expiredTask : expiredTasks) { + tasks.removeIf(task -> task == expiredTask); + Task.decrementCount(); + } + Storage.trySave(tasks); + Ui.borderLine(); + System.out.println("\t Expired Tasks have been purged from the list!"); + System.out.println("\t I love purging things human..."); + Ui.borderLine(); + } else { + Ui.borderLine(); + System.out.println("\t Quack! Expired tasks have not been purged."); + Ui.borderLine(); + } + } else { + System.out.println("\t Quack! No tasks have expired!"); + Ui.borderLine(); + } + + } + } } diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index a4ebb1f1de..b5d6e679cc 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -228,7 +228,7 @@ static void emptyCommandMessage() { } static boolean doubleCheck() { - System.out.println("THIS IS AN IRREVERSIBLE PROCESS. ARE YOU SURE? Y/N"); + System.out.println("\t THIS IS AN IRREVERSIBLE PROCESS. ARE YOU SURE? Y/N"); Scanner in = new Scanner(System.in); String line; line = in.nextLine(); @@ -244,6 +244,7 @@ static void help() { System.out.println("\t - mark : I'll mark that task as done."); System.out.println("\t - unmark : I'll mark that task as undone."); System.out.println("\t - delete : I'll delete that task from your list."); + System.out.println("\t - purge: I'll delete all expired tasks from your list after a confirmation."); System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); System.out.println("\t - priority <1/2/3>: I'll set the priority of a given task as"); System.out.println("\t 1:Low, 2:Medium and 3:High."); @@ -251,12 +252,12 @@ static void help() { System.out.println("\t Here are the following ways to input tasks:"); System.out.println("\t Deadlines: /by "); System.out.println("\t (eg. Eat bread /by 2023-03-15 2015)"); - System.out.println("\t Events: /from /to "); + System.out.println("\t Events : /from /to "); System.out.println("\t (eg. Meeting /from 2023-03-15 2015 /to 2023-03-15 2215)"); - System.out.println("\t Classes: /class /from " + + System.out.println("\t Classes : /class /from " + "/to "); System.out.println("\t (eg. Bring laptop /class CS2113 /from 2023-03-15 1100 /to 2023-03-15 1200)"); - System.out.println("\t Todo: "); + System.out.println("\t Todo : "); System.out.println("\t (eg. Water the plants) \n"); System.out.println("\t (`・v・´ ): How else may I assist you today, human?"); borderLine(); @@ -342,7 +343,6 @@ static void greetingMessage() { System.out.println("\t (´˘v˘´ ): That being said, I am a smart Duck. " + "If you wish to know what I understand, just enter 'help'."); System.out.println("\t (`・v・´ ): How may I assist you today, human?"); - borderLine(); } /** diff --git a/src/main/java/seedu/duck/task/Deadline.java b/src/main/java/seedu/duck/task/Deadline.java index 71076d7f48..2ab8e14a0d 100644 --- a/src/main/java/seedu/duck/task/Deadline.java +++ b/src/main/java/seedu/duck/task/Deadline.java @@ -23,6 +23,6 @@ public String toSaveString() { @Override public String toString() { - return "[D]" + super.toString() + " (by: " + by + ")" + " (" + getPriority() + ")"; + return "\t [D]" + super.toString() + " (by: " + by + ")" + " (" + getPriority() + ")"; } } diff --git a/src/main/java/seedu/duck/task/Event.java b/src/main/java/seedu/duck/task/Event.java index 6c8fccb968..7e36d028fd 100644 --- a/src/main/java/seedu/duck/task/Event.java +++ b/src/main/java/seedu/duck/task/Event.java @@ -34,7 +34,7 @@ public String toSaveString() { @Override public String toString() { - return "[E]" + super.toString() + " (from: " + start + return "\t [E]" + super.toString() + " (from: " + start + " to: " + end + ")" + " (" + getPriority() + ")"; } } diff --git a/src/main/java/seedu/duck/task/Todo.java b/src/main/java/seedu/duck/task/Todo.java index 2bbae233d7..1f42a910da 100644 --- a/src/main/java/seedu/duck/task/Todo.java +++ b/src/main/java/seedu/duck/task/Todo.java @@ -13,6 +13,6 @@ public String toSaveString() { @Override public String toString() { - return "[T]" + super.toString() + " (" + getPriority() + ")"; + return "\t [T]" + super.toString() + " (" + getPriority() + ")"; } } From 19d9ee4c4a0609e589775042fcda9d1d2a7593be Mon Sep 17 00:00:00 2001 From: thant Date: Thu, 23 Mar 2023 15:09:33 +0800 Subject: [PATCH 033/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 91e5f6bdf1..8b5829c796 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -60,6 +60,13 @@ This section describes how Duck is implemented and how its commands are executed ### Purge feature +**Sequence Diagram** + +![image](https://user-images.githubusercontent.com/1620654/227128864-cfc9cac7-bc68-4962-ac45-77e1ae067db0.png) + +The ```TaskList#purge()``` command will be implemented following the sequence diagram as shown above. + + **Implementation** The ```TaskList#purge()``` command will be implemented to facilitate the removal of expired ```Task``` items from the ```TaskList```. This will be executed once upon Duck's startup, and can be further executed by inputting the term ```purge``` into the CLI when Duck is running. The following is the new operation to be implemented. From 34eedccd955eaa84a26f7ebc9a00be0d67c94627 Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Thu, 23 Mar 2023 15:35:38 +0800 Subject: [PATCH 034/152] Find function now also shows the index of the item in the whole list --- src/main/java/seedu/duck/Ui.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index a12798d9c5..997940ff96 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -123,16 +123,18 @@ static void printLowPriority(ArrayList tasks){ */ static void find(ArrayList tasks, String[] words) { ArrayList matchingResults = new ArrayList<>(); + ArrayList matchingResultsIndex = new ArrayList<>(); int matchCount = 0; String keyword = Parser.processKeywords(words); - for (Task task : tasks) { - if (task.getDescription().contains(keyword)) { - matchingResults.add(task); + for (int i = 0; i < tasks.size(); i++) { + if (tasks.get(i).getDescription().contains(keyword)) { + matchingResults.add(tasks.get(i)); + matchingResultsIndex.add(i+1); matchCount++; } } - printFindResults(matchingResults, matchCount); + printFindResults(matchingResults, matchCount, matchingResultsIndex); } @@ -142,11 +144,11 @@ static void find(ArrayList tasks, String[] words) { * @param matchingResults The array list of tasks that contain the keywords * @param matchCount The number of tasks in the list that contain the keywords */ - private static void printFindResults(ArrayList matchingResults, int matchCount) { + private static void printFindResults(ArrayList matchingResults, int matchCount, ArrayList matchingResultsIndex) { if (matchingResults.isEmpty()) { noMatchMessage(); } else { - printMatchingList(matchingResults, matchCount); + printMatchingList(matchingResults, matchCount, matchingResultsIndex); } } @@ -156,11 +158,11 @@ private static void printFindResults(ArrayList matchingResults, int matchC * @param matchingResults The array list of tasks that contain the keywords * @param matchCount The number of tasks in the list that contain the keywords */ - static void printMatchingList(ArrayList matchingResults, int matchCount) { + static void printMatchingList(ArrayList matchingResults, int matchCount, ArrayList matchingResultsIndex) { borderLine(); System.out.println("\t Here are the matching tasks in your list:"); for (int i = 0; i < matchCount; i++) { - System.out.println("\t " + (i + 1) + "." + matchingResults.get(i)); + System.out.println("\t " + (i + 1) + "." + matchingResults.get(i) + " || The index of this item is " + matchingResultsIndex.get(i)); } borderLine(); } From 17f9dd56483c65c7e88a8ebfeca910c7c4478277 Mon Sep 17 00:00:00 2001 From: thant Date: Thu, 23 Mar 2023 23:56:41 +0800 Subject: [PATCH 035/152] Added purge functionality for SchoolClass objects as well. Cleaned up a bit of indentation for output and fixed a typo in help function --- src/main/java/seedu/duck/TaskList.java | 20 +++++++++++++++++-- src/main/java/seedu/duck/Ui.java | 2 +- .../java/seedu/duck/task/SchoolClass.java | 4 ++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index fa67287584..90e9efa88b 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -256,7 +256,7 @@ static void purge(ArrayList tasks) { System.out.println(); if (tasks.size() > 0) { int expiredCount = 0; - ArrayList expiredTasks = new ArrayList(); + ArrayList expiredTasks = new ArrayList<>(); for (Task task : tasks) { if (task instanceof Deadline) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); @@ -292,8 +292,24 @@ static void purge(ArrayList tasks) { System.out.println(task); expiredTasks.add(task); } + } else if (task instanceof SchoolClass) { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); + String end = ((SchoolClass) task).getEnd(); + Date d = null; + Date n = new Date(); + try { + d = format.parse(end); + } catch (ParseException e) { + e.printStackTrace(); + } + assert d != null; + long diff = d.getTime() - n.getTime(); + if (diff < 0) { + expiredCount++; + System.out.println(task); + expiredTasks.add(task); + } } - } if (expiredCount > 0) { Ui.borderLine(); diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 695d84601e..c4cbfc3841 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -275,7 +275,7 @@ static void help() { System.out.println("\t (`・v・´ ): Here are the commands you can give me:"); System.out.println("\t - list: I'll list out all the tasks you have recorded."); System.out.println("\t - list : I'll list out all the tasks in that number of days."); - System.out.println("\t - clear: The list will be cleared. This in an irreversible process."); + System.out.println("\t - clear: The list will be cleared. This is an IRREVERSIBLE process."); System.out.println("\t - mark : I'll mark that task as done."); System.out.println("\t - unmark : I'll mark that task as undone."); System.out.println("\t - delete : I'll delete that task from your list."); diff --git a/src/main/java/seedu/duck/task/SchoolClass.java b/src/main/java/seedu/duck/task/SchoolClass.java index 78b39aaacd..f5aef5ec6c 100644 --- a/src/main/java/seedu/duck/task/SchoolClass.java +++ b/src/main/java/seedu/duck/task/SchoolClass.java @@ -45,10 +45,10 @@ public String toSaveString() { @Override public String toString() { if (getDescription().isBlank()) { - return "[C]" + "[" + getStatusIcon() + "] " + className + " (from: " + start + return "\t [C]" + "[" + getStatusIcon() + "] " + className + " (from: " + start + " to: " + end + ")" + " (" + getPriority() + ")"; } - return "[C]" + "[" + getStatusIcon() + "] " + className + ": " + getDescription() + + return "\t [C]" + "[" + getStatusIcon() + "] " + className + ": " + getDescription() + " (from: " + start + " to: " + end + ")" + " (" + getPriority() + ")"; } } From 12469808c1a314ac49d34413d5da0cfc66114cee Mon Sep 17 00:00:00 2001 From: skyanzy <88618401+skyanzy@users.noreply.github.com> Date: Fri, 24 Mar 2023 11:42:49 +0800 Subject: [PATCH 036/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 8b5829c796..473b26faf6 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -187,6 +187,16 @@ The following are the new operations implemented.
+### List Upcoming Tasks Feature + +**Implementation** + +The ```Ui#printUpcomingTasks()``` was implemented to allow the user to view their upcoming tasks in ```ndays``` days where ```ndays``` is specified.  + +- ```Ui#printUpcomingTasks()``` - navigates through the task list and compares the due time/starting time of that task and current time. prints all upcoming tasks in the number of days specified. + +
+ ## Product scope ### Target user profile From 5e78e7d96eb2f3650ad0ecf5a9e11dbd1a07f248 Mon Sep 17 00:00:00 2001 From: thant Date: Fri, 24 Mar 2023 13:41:55 +0800 Subject: [PATCH 037/152] Update UserGuide.md User Guide matches 2.0 expectations. --- docs/UserGuide.md | 317 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 294 insertions(+), 23 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index abd9fbe891..b470866e7d 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -1,42 +1,313 @@ -# User Guide +# Duck User Guide(v 2.0) -## Introduction +Duck is a **desktop app for managing tasks and deadlines, optimised for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). Duck will have a number of quality-of-life features for busy students seeking a simple solution to task management. These include automated task removal upon expiration, or limiting the number of tasks displayed to within a date range. Duck also has recurring task functionality to automate routine tasks so users do not have to manually re-add expired tasks. -{Give a product intro} -## Quick Start -{Give steps to get started quickly} +* **Features** + * Viewing help : `help` + * Listing all tasks : `list ` + * Listing all tasks up to X days into the future : `list X ` + * Clearing all tasks (including datafile) : `clear ` + * Mark a specified task as done : `mark ` + * Unmark a specified task as not done : `unmark ` + * Deleting a task : `delete ` + * Purge expired tasks : `purge` + * Designate a given task to be recurring **[TO BE ADDED]** : + * `recurrent ` + * Find tasks matching a given keyword : `find ` + * Designate a priority to a given task : + * `priority ` + * Add tasks that can be broken down into the following 4 types: + + * Add ToDo: + * Add Deadline: /by + * Add Event: /from /to + * Add Class: /class /from /to + * Terminate the program : `bye` -1. Ensure that you have Java 11 or above installed. -1. Down the latest version of `Duke` from [here](http://link.to/duke). -## Features +# Features -{Give detailed description of each feature} -### Adding a todo: `todo` -Adds a new item to the list of todo items. +### **Viewing help : `help`** -Format: `todo n/TODO_NAME d/DEADLINE` +Displays all available commands and their input format on the terminal. -* The `DEADLINE` can be in a natural language format. -* The `TODO_NAME` cannot contain punctuation. +**Input:** `help` -Example of usage: +**Output:** -`todo n/Write the rest of the User Guide d/next week` -`todo n/Refactor the User Guide to remove passive voice d/13/04/2020` +``` +(`・v・´ ): Here are the commands you can give me: +COMMAND_FORMAT : COMMAND_FUNCTIONALITY EXPLANATION +. +. +. +(`・v・´ ): How else may I assist you today, human? +``` -## FAQ -**Q**: How do I transfer my data to another computer? -**A**: {your answer here} +## **Listing all tasks : `list`** -## Command Summary +Displays all tasks currently stored in the application. -{Give a 'cheat sheet' of commands here} +**Input:** `list ` -* Add todo `todo n/TODO_NAME d/DEADLINE` +**Output: Demonstrated with 1 of each type currently in the stored data array** + + +``` +Here are the tasks in your list: + 1. [T][ ] todo (No priority established.) + 2. [D][ ] deadline (by: 2023-03-25 2359) (No priority established.) + 3. [E][ ] event (from: 2023-03-25 1200 to: 2023-03-26 2359) (No priority established.) + 4. [C][ ] CS2113: Class (from: 2023-03-25 1100 to: 2023-03-25 1200) (No priority established.) +``` + + + +## **Listing all tasks up to X days in the future : `list X`** + +Displays all tasks currently stored in the application, up to X days into the future. + +For instance list 0returns all tasks that are starting within 24 hours. + +**Input:** `list X ` + +**Output: Demonstrated by inputting list 0 on 24/3/2023 12:40, using the same array as above** + + +``` + Here are your tasks in 0 days: + 1. [E][ ] event (from: 2023-03-25 1200 to: 2023-03-26 2359) (No priority established.) + 2. [C][ ] CS2113: Class (from: 2023-03-25 1100 to: 2023-03-25 1200) (No priority established.) +``` + + + +## **Marking a task : `mark `** + +Marks a task from the tasklist as complete. + +**Input: `mark `** + +**Output: Demonstrated with input `mark 1`** + + +``` +Understood. I've marked this task as done: + [T][X] todo (No priority established.) +``` + + + +## **Unmarking a task : `unmark `** + +Unmarks a task from the tasklist as not complete. + +**Input:** `unmark ` + +**Output: Demonstrated with input `unmark 1`** + + +``` + Understood. I've marked this task as not done yet: + [T][ ] todo (No priority established.) +``` + + + +## **Deleting a task : `delete`** + +Removes a task from the tasklist. + +**Input:** `delete ` + +**Output: Demonstrated with removing the following task** + + +``` +Understood. I have removed this task: + [T][ ] todo (No priority established.) +You now have 3 tasks in your list. +``` + +## **Designate a task priority : `priority `** + + + +Specifies a priority for a given task, with the following assignments: +* 1 - Low +* 2 - Medium +* 3 - High + +By default there is no priority specified. + +**Input:** `priority ` + +**Output: Demonstrated with input `priority 1 1`** + + +``` +Understood. The task's new priority is: + Low priority. +``` + + +## **Purge Expired Tasks : `purge`** + +Prompts the user for confirmation. Proceeds to remove all expired tasks from storage upon confirmation. This operation is automatically executed once upon Duck’s startup. + +**Input:** `purge` + +**Output: Demonstrated by having an expired deadline task in the array** + + +``` + Displaying all expired tasks below... + + [D][ ] deadline (by: 2023-03-24 1100) (No priority established.) +____________________________________________________________ + Quack! A total of 1 task has expired! + Should I remove these tasks from the pending list human? +____________________________________________________________ + THIS IS AN IRREVERSIBLE PROCESS. ARE YOU SURE? Y/N + +``` + + + +* **If the user inputs ‘Y’:** +``` +Expired Tasks have been purged from the list! +I love purging things,human... +``` + + +* **If the user inputs ‘N’:** +``` +Quack! Expired tasks have not been purged. +``` + +## **Clearing tasks from storage: `clear`** + +Prompts the user for confirmation. Proceeds to clear all tasks from storage upon confirmation. + +**Input:** `clear` + +**Output:** + + +``` +THIS IS AN IRREVERSIBLE PROCESS. ARE YOU SURE? Y/N +``` + + + +* **If the user inputs ‘Y’:** `Got it, all tasks have been cleared.` +* **If the user inputs ‘N’:** `Quack! Process cancelled.` + +## **Finding tasks from storage that match a keyword: `find `** + +Traverses through the stored tasks to return all tasks that contain the keyword + +**Input:** `find ` + +**Output: Demonstrated by using the keyword `todo`** + + +``` +Here are the matching tasks in your list: +1. [T][ ] todo (No priority established.) +``` + + + +## **Adding a ToDo Task : ``** + +Adds a ToDo task to the storage of Duck + +**Input:** `` + +**Output: Demonstrated by inputting `Todo`** + + +``` +Alright, I have added this task: + [T][ ] todo (No priority established.) +You now have 2 tasks in your list. +``` + + + +## **Adding a Deadline Task : ` /by `** + +Adds a Deadline task to the storage of Duck + +**Input:** ` /by ` + +**Output: Demonstrated by inputting `deadline /by 2023-03-25 2359`** + + +``` +Alright, I have added this task: + [D][ ] deadline (by: 2023-03-25 2359) (No priority established.) +You now have 3 tasks in your list. +``` + + + +## **Adding an Event Task : ` /from /to `** + +Adds an Event task to the storage of Duck + +**Input:** ` /from /to ` + +**Output: Demonstrated by inputting `event /from 2023-03-25 2359 /to 2023-03-26 1100`** + + +``` +Alright, I have added this task: + [E][ ] event (from: 2023-03-25 2359 to: 2023-03-26 1100) (No priority established.) +You now have 4 tasks in your list. +``` + + + +## **Adding a Class Task : ` /class /from /to `** + +Adds a Class task to the storage of Duck + +**Input:** ` /class /from /to ` + +**Output: Demonstrated by inputting `homework /class class /from 2023-03-25 1100 /to 2023-03-25 1300`** + + +``` +Alright, I have added this task: + [C][ ] class: homework (from: 2023-03-25 1100 to: 2023-03-25 1300) (No priority established.) +You now have 5 tasks in your list. +``` + + + +## **Exiting the program : `bye`** + +Exits the program. + +**Input:** `bye` + +**Output:** + + +``` +Bye. Hope to see you again soon! +``` + + +## **Saving the data :** + +Duck’s data is saved in the hard disk automatically after any command that changes the data. There is no need to save manually. From 69862c76b7cc46f5cf69c93d0db376207ef0c02d Mon Sep 17 00:00:00 2001 From: thant Date: Fri, 24 Mar 2023 13:47:16 +0800 Subject: [PATCH 038/152] Update TaskList.java --- src/main/java/seedu/duck/TaskList.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 90e9efa88b..81f3d0313b 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -324,7 +324,7 @@ static void purge(ArrayList tasks) { Storage.trySave(tasks); Ui.borderLine(); System.out.println("\t Expired Tasks have been purged from the list!"); - System.out.println("\t I love purging things human..."); + System.out.println("\t I love purging things, human..."); Ui.borderLine(); } else { Ui.borderLine(); @@ -335,7 +335,9 @@ static void purge(ArrayList tasks) { System.out.println("\t Quack! No tasks have expired!"); Ui.borderLine(); } - + } else { + System.out.println("\t Quack! No tasks currently pending!"); + Ui.borderLine(); } } } From 17dfcc803bbf69843fc4f46da84ab6923560fd9c Mon Sep 17 00:00:00 2001 From: thant Date: Fri, 24 Mar 2023 13:55:23 +0800 Subject: [PATCH 039/152] Update UserGuide.md Just cleaning up some formats --- docs/UserGuide.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index b470866e7d..24396711a4 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -50,7 +50,7 @@ COMMAND_FORMAT : COMMAND_FUNCTIONALITY EXPLANATION -## **Listing all tasks : `list`** +### **Listing all tasks : `list`** Displays all tasks currently stored in the application. @@ -69,7 +69,7 @@ Here are the tasks in your list: -## **Listing all tasks up to X days in the future : `list X`** +### **Listing all tasks up to X days in the future : `list X`** Displays all tasks currently stored in the application, up to X days into the future. @@ -88,7 +88,7 @@ For instance list 0returns all tasks that are star -## **Marking a task : `mark `** +### **Marking a task : `mark `** Marks a task from the tasklist as complete. @@ -104,7 +104,7 @@ Understood. I've marked this task as done: -## **Unmarking a task : `unmark `** +### **Unmarking a task : `unmark `** Unmarks a task from the tasklist as not complete. @@ -120,7 +120,7 @@ Unmarks a task from the tasklist as not complete. -## **Deleting a task : `delete`** +### **Deleting a task : `delete`** Removes a task from the tasklist. @@ -135,7 +135,7 @@ Understood. I have removed this task: You now have 3 tasks in your list. ``` -## **Designate a task priority : `priority `** +### **Designate a task priority : `priority `** @@ -157,7 +157,7 @@ Understood. The task's new priority is: ``` -## **Purge Expired Tasks : `purge`** +### **Purge Expired Tasks : `purge`** Prompts the user for confirmation. Proceeds to remove all expired tasks from storage upon confirmation. This operation is automatically executed once upon Duck’s startup. @@ -192,7 +192,7 @@ I love purging things,human... Quack! Expired tasks have not been purged. ``` -## **Clearing tasks from storage: `clear`** +### **Clearing tasks from storage: `clear`** Prompts the user for confirmation. Proceeds to clear all tasks from storage upon confirmation. @@ -210,7 +210,7 @@ THIS IS AN IRREVERSIBLE PROCESS. ARE YOU SURE? Y/N * **If the user inputs ‘Y’:** `Got it, all tasks have been cleared.` * **If the user inputs ‘N’:** `Quack! Process cancelled.` -## **Finding tasks from storage that match a keyword: `find `** +### **Finding tasks from storage that match a keyword: `find `** Traverses through the stored tasks to return all tasks that contain the keyword @@ -226,7 +226,7 @@ Here are the matching tasks in your list: -## **Adding a ToDo Task : ``** +### **Adding a ToDo Task : ``** Adds a ToDo task to the storage of Duck @@ -243,7 +243,7 @@ You now have 2 tasks in your list. -## **Adding a Deadline Task : ` /by `** +### **Adding a Deadline Task : ` /by `** Adds a Deadline task to the storage of Duck @@ -260,7 +260,7 @@ You now have 3 tasks in your list. -## **Adding an Event Task : ` /from /to `** +### **Adding an Event Task : ` /from /to `** Adds an Event task to the storage of Duck @@ -277,7 +277,7 @@ You now have 4 tasks in your list. -## **Adding a Class Task : ` /class /from /to `** +### **Adding a Class Task : ` /class /from /to `** Adds a Class task to the storage of Duck @@ -294,7 +294,7 @@ You now have 5 tasks in your list. -## **Exiting the program : `bye`** +### **Exiting the program : `bye`** Exits the program. @@ -308,6 +308,6 @@ Bye. Hope to see you again soon! ``` -## **Saving the data :** +### **Saving the data :** Duck’s data is saved in the hard disk automatically after any command that changes the data. There is no need to save manually. From 7eb643433f9f1757fa2da5faab7dbda1316f1ff2 Mon Sep 17 00:00:00 2001 From: thant Date: Fri, 24 Mar 2023 14:08:40 +0800 Subject: [PATCH 040/152] Update UserGuide.md Added md section jumping --- docs/UserGuide.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 24396711a4..b28a4af07d 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -4,27 +4,27 @@ Duck is a **desktop app for managing tasks and deadlines, optimised for use via -* **Features** - * Viewing help : `help` - * Listing all tasks : `list ` - * Listing all tasks up to X days into the future : `list X ` - * Clearing all tasks (including datafile) : `clear ` - * Mark a specified task as done : `mark ` - * Unmark a specified task as not done : `unmark ` - * Deleting a task : `delete ` - * Purge expired tasks : `purge` +* [**Features**](#features) + * [Viewing help :](#viewing-help--help) `help` + * [Listing all tasks :](#listing-all-tasks--list) `list ` + * [Listing all tasks up to X days into the future :](#listing-all-tasks-up-to-x-days-in-the-future--list-x) `list X ` + * [Mark a specified task as done :](#marking-a-task--mark-task_number) `mark ` + * [Unmark a specified task as not done :](#unmarking-a-task--unmark-task_number) `unmark ` + * [Deleting a task :](#deleting-a-task--delete) `delete ` + * [Designate a priority to a given task :](#designate-a-task-priority--priority-task_number-priority) + * `priority ` + * [Purge expired tasks :](#purge-expired-tasks--purge) `purge` + * [Clearing all tasks (including datafile) :](#clearing-tasks-from-storage-clear) `clear ` * Designate a given task to be recurring **[TO BE ADDED]** : * `recurrent ` - * Find tasks matching a given keyword : `find ` - * Designate a priority to a given task : - * `priority ` - * Add tasks that can be broken down into the following 4 types: + * [Find tasks matching a given keyword :](#finding-tasks-from-storage-that-match-a-keyword-find-keyword) `find ` + * [Add tasks that can be broken down into the following 4 types:](#adding-a-todo-task--description) * Add ToDo: * Add Deadline: /by * Add Event: /from /to * Add Class: /class /from /to - * Terminate the program : `bye` + * [Terminate the program :](#exiting-the-program--bye) `bye` # Features From 508ae474ef5d3304238ce682d44013ea776ae28d Mon Sep 17 00:00:00 2001 From: thant Date: Fri, 24 Mar 2023 14:10:17 +0800 Subject: [PATCH 041/152] Update UserGuide.md Reverted a few formatting choices for visual clarity --- docs/UserGuide.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index b28a4af07d..975e4821ef 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -30,7 +30,7 @@ Duck is a **desktop app for managing tasks and deadlines, optimised for use via # Features -### **Viewing help : `help`** +## **Viewing help : `help`** Displays all available commands and their input format on the terminal. @@ -50,7 +50,7 @@ COMMAND_FORMAT : COMMAND_FUNCTIONALITY EXPLANATION -### **Listing all tasks : `list`** +## **Listing all tasks : `list`** Displays all tasks currently stored in the application. @@ -69,7 +69,7 @@ Here are the tasks in your list: -### **Listing all tasks up to X days in the future : `list X`** +## **Listing all tasks up to X days in the future : `list X`** Displays all tasks currently stored in the application, up to X days into the future. @@ -88,7 +88,7 @@ For instance list 0returns all tasks that are star -### **Marking a task : `mark `** +## **Marking a task : `mark `** Marks a task from the tasklist as complete. @@ -104,7 +104,7 @@ Understood. I've marked this task as done: -### **Unmarking a task : `unmark `** +## **Unmarking a task : `unmark `** Unmarks a task from the tasklist as not complete. @@ -120,7 +120,7 @@ Unmarks a task from the tasklist as not complete. -### **Deleting a task : `delete`** +## **Deleting a task : `delete`** Removes a task from the tasklist. @@ -135,7 +135,7 @@ Understood. I have removed this task: You now have 3 tasks in your list. ``` -### **Designate a task priority : `priority `** +## **Designate a task priority : `priority `** @@ -157,7 +157,7 @@ Understood. The task's new priority is: ``` -### **Purge Expired Tasks : `purge`** +## **Purge Expired Tasks : `purge`** Prompts the user for confirmation. Proceeds to remove all expired tasks from storage upon confirmation. This operation is automatically executed once upon Duck’s startup. @@ -192,7 +192,7 @@ I love purging things,human... Quack! Expired tasks have not been purged. ``` -### **Clearing tasks from storage: `clear`** +## **Clearing tasks from storage: `clear`** Prompts the user for confirmation. Proceeds to clear all tasks from storage upon confirmation. @@ -210,7 +210,7 @@ THIS IS AN IRREVERSIBLE PROCESS. ARE YOU SURE? Y/N * **If the user inputs ‘Y’:** `Got it, all tasks have been cleared.` * **If the user inputs ‘N’:** `Quack! Process cancelled.` -### **Finding tasks from storage that match a keyword: `find `** +## **Finding tasks from storage that match a keyword: `find `** Traverses through the stored tasks to return all tasks that contain the keyword @@ -226,7 +226,7 @@ Here are the matching tasks in your list: -### **Adding a ToDo Task : ``** +## **Adding a ToDo Task : ``** Adds a ToDo task to the storage of Duck @@ -243,7 +243,7 @@ You now have 2 tasks in your list. -### **Adding a Deadline Task : ` /by `** +## **Adding a Deadline Task : ` /by `** Adds a Deadline task to the storage of Duck @@ -260,7 +260,7 @@ You now have 3 tasks in your list. -### **Adding an Event Task : ` /from /to `** +## **Adding an Event Task : ` /from /to `** Adds an Event task to the storage of Duck @@ -277,7 +277,7 @@ You now have 4 tasks in your list. -### **Adding a Class Task : ` /class /from /to `** +## **Adding a Class Task : ` /class /from /to `** Adds a Class task to the storage of Duck @@ -294,7 +294,7 @@ You now have 5 tasks in your list. -### **Exiting the program : `bye`** +## **Exiting the program : `bye`** Exits the program. @@ -308,6 +308,6 @@ Bye. Hope to see you again soon! ``` -### **Saving the data :** +## **Saving the data :** Duck’s data is saved in the hard disk automatically after any command that changes the data. There is no need to save manually. From 4eec29a318c7b4b672d2438d6468ec5edf4b38c2 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Sun, 26 Mar 2023 15:53:10 +0800 Subject: [PATCH 042/152] Implemented class schedule with automatic day/time sorting, displaying of schedule, deletion of school classes, and revamped saving and loading to save this separate class schedule --- src/main/java/seedu/duck/Duck.java | 9 +- src/main/java/seedu/duck/Parser.java | 25 ++++-- src/main/java/seedu/duck/Storage.java | 63 +++++++------ src/main/java/seedu/duck/TaskList.java | 89 ++++++++++++++----- src/main/java/seedu/duck/Ui.java | 49 ++++++++-- .../java/seedu/duck/task/SchoolClass.java | 46 ++++++++-- 6 files changed, 204 insertions(+), 77 deletions(-) diff --git a/src/main/java/seedu/duck/Duck.java b/src/main/java/seedu/duck/Duck.java index ff71b822dd..9276983437 100644 --- a/src/main/java/seedu/duck/Duck.java +++ b/src/main/java/seedu/duck/Duck.java @@ -1,25 +1,28 @@ package seedu.duck; +import seedu.duck.task.SchoolClass; import seedu.duck.task.Task; import java.io.IOException; import java.util.ArrayList; import java.util.Scanner; +import java.util.PriorityQueue; public class Duck { /** Runs the Duck bot */ private static void runDuck() throws IOException { Ui.greetingMessage(); + PriorityQueue classes = new PriorityQueue<>(); ArrayList tasks = new ArrayList<>(); - Storage.tryLoad(tasks); - TaskList.purge(tasks); + Storage.tryLoad(tasks, classes); + TaskList.purge(tasks, classes); Ui.displayUpcomingDeadline(tasks); String line; Scanner in = new Scanner(System.in); line = in.nextLine(); - Parser.processCommand(tasks, line, in); + Parser.processCommand(tasks, classes, line, in); Ui.exitMessage(); } diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 0d12591192..ea0ba04828 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -1,9 +1,11 @@ package seedu.duck; +import seedu.duck.task.SchoolClass; import seedu.duck.task.Task; import java.io.IOException; import java.util.ArrayList; +import java.util.PriorityQueue; import java.util.Scanner; /** @@ -37,7 +39,8 @@ public static boolean isNumeric(String word) { * @param line The line of user input * @param in The input from scanner */ - static void processCommand(ArrayList tasks, String line, Scanner in) throws IOException { + static void processCommand(ArrayList tasks, PriorityQueue classes, String line, Scanner in) + throws IOException { while (!line.equals("bye")) { // Exits the program if input is "bye" String[] words = line.split(" "); if (line.isBlank()) { @@ -45,6 +48,8 @@ static void processCommand(ArrayList tasks, String line, Scanner in) throw } else if (line.equals("list")) { // List out all the tasks added Ui.list(tasks); + } else if (line.equals("list classes")) { + Ui.listClasses(classes); } else if (line.equals("help")) { // List out all the tasks added Ui.help(); @@ -56,25 +61,29 @@ static void processCommand(ArrayList tasks, String line, Scanner in) throw } else if (words[0].equals("unmark") && (words.length == 2) && (isNumeric(words[1]))) { // Mark a task as not done TaskList.unmarkTask(tasks, words); - Storage.trySave(tasks); + Storage.trySave(tasks, classes); } else if (words[0].equals("mark") && (words.length == 2) && (isNumeric(words[1]))) { // Mark a task as done TaskList.markTask(tasks, words); - Storage.trySave(tasks); + Storage.trySave(tasks, classes); } else if (words[0].equals("delete") && (words.length == 2) && (isNumeric(words[1]))) { // Delete a task TaskList.deleteTask(tasks, words); - Storage.trySave(tasks); + Storage.trySave(tasks, classes); + } else if (words[0].equals("remove") && words[1].equals("class")) { + // Remove a class from class list + TaskList.tryDeleteClass(classes, line); + Storage.trySave(tasks, classes); } else if (words[0].equals("find") && (words.length > 1)) { // Find tasks that contain a keyword Ui.find(tasks, words); } else if (words[0].equals("purge")){ // Find tasks that contain a keyword - TaskList.purge(tasks); + TaskList.purge(tasks, classes); } else if (words[0].equals("priority") && (words.length == 3)) { // Find tasks that contain a keyword TaskList.setPriority(tasks,words); - Storage.trySave(tasks); + Storage.trySave(tasks, classes); } else if (words[0].equals("clear")) { if (Ui.doubleCheck()) { // Find tasks that contain a keyword @@ -91,8 +100,8 @@ static void processCommand(ArrayList tasks, String line, Scanner in) throw } } else { // Adding a task to the list - TaskList.addTask(line, tasks); - Storage.trySave(tasks); + TaskList.addTask(line, tasks, classes); + Storage.trySave(tasks, classes); } line = in.nextLine(); } diff --git a/src/main/java/seedu/duck/Storage.java b/src/main/java/seedu/duck/Storage.java index 27abd26f47..19176e25f0 100644 --- a/src/main/java/seedu/duck/Storage.java +++ b/src/main/java/seedu/duck/Storage.java @@ -11,7 +11,10 @@ import java.io.FileWriter; import java.io.PrintWriter; import java.io.IOException; +import java.time.DayOfWeek; import java.util.ArrayList; +import java.util.Iterator; +import java.util.PriorityQueue; import java.util.Scanner; /** @@ -27,38 +30,34 @@ public class Storage { * @param line The line of input from the save file * @param tasks The array list of tasks */ - static void loadTask(String line, ArrayList tasks) { + static void loadTask(String line, ArrayList tasks, PriorityQueue classes, String doneStatus) { if (line.contains("/by")) { loadDeadline(line, tasks); + loadTaskStatus(tasks, doneStatus); + Task.incrementCount(); } else if (line.contains("/class")) { - loadSchoolClass(line, tasks); + loadSchoolClass(line, classes); } else if (line.contains("/from") || line.contains("/to")) { loadEvent(line, tasks); + loadTaskStatus(tasks, doneStatus); + Task.incrementCount(); } else { loadTodo(line, tasks); + loadTaskStatus(tasks, doneStatus); + Task.incrementCount(); } } static void clearTask() throws IOException { { - try { - FileWriter fw = new FileWriter(SAVEPATH, false); - PrintWriter pw = new PrintWriter(fw, false); - pw.flush(); - pw.close(); - fw.close(); - } catch (Exception exception) { - System.out.println("Exception have been caught"); - } - } } @@ -99,17 +98,16 @@ static void loadEvent(String line, ArrayList tasks) { * to be used when loading from save data. * * @param line The line of input from the user - * @param tasks The array list of tasks + * @param classes The priority queue of school classes */ - static void loadSchoolClass(String line, ArrayList tasks) { + static void loadSchoolClass(String line, PriorityQueue classes) { String description = line.substring(0, line.indexOf("/class")).trim(); - String className = line.substring(line.indexOf("/class") + 6, line.indexOf("/from")).trim(); + String className = line.substring(line.indexOf("/class") + 6, line.indexOf("/day")).trim(); + DayOfWeek day = DayOfWeek.valueOf(line.substring(line.indexOf("/day") + 4, line.indexOf("/from")).trim()); String startString = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); - String endString = line.substring(line.indexOf("/to") + 3, line.indexOf("

")).trim(); - String priority = line.substring(line.indexOf("

") + 3,line.indexOf("

") + 4).trim(); - SchoolClass currSchoolClass = new SchoolClass(className, description, startString, endString); - currSchoolClass.setPriority(priority); - tasks.add(currSchoolClass); + String endString = line.substring(line.indexOf("/to") + 3).trim(); + SchoolClass currSchoolClass = new SchoolClass(className, description, day, startString, endString); + classes.add(currSchoolClass); } /** @@ -148,18 +146,27 @@ static void loadTaskStatus(ArrayList tasks, String doneStatus) { * * @param tasks The array list of tasks */ - static void save(ArrayList tasks) throws IOException { + static void save(ArrayList tasks, PriorityQueue classes) throws IOException { File f = new File(SAVEPATH); if (f.exists()) { f.delete(); } f.createNewFile(); + // Saving the task list to the save file FileWriter fw = new FileWriter(SAVEPATH); for (Task currTask : tasks) { fw.write(currTask.toSaveString()); } fw.close(); + + // Saving the class schedule to the save file + FileWriter fw2 = new FileWriter(SAVEPATH, true); + PriorityQueue temp = new PriorityQueue(classes); + while (!temp.isEmpty()) { + fw2.write(temp.poll().toSaveString()); + } + fw2.close(); } /** @@ -167,9 +174,9 @@ static void save(ArrayList tasks) throws IOException { * * @param tasks The array list of tasks */ - static void trySave(ArrayList tasks) { + static void trySave(ArrayList tasks, PriorityQueue classes) { try { - save(tasks); + save(tasks, classes); } catch (IOException e) { System.out.println("Saving error."); } @@ -180,7 +187,7 @@ static void trySave(ArrayList tasks) { * * @param tasks The array list of tasks */ - static void load(ArrayList tasks) throws IOException { + static void load(ArrayList tasks, PriorityQueue classes) throws IOException { File folder = new File(SAVEFOLDER); if (!folder.exists()) { new File(SAVEFOLDER).mkdir(); @@ -201,9 +208,7 @@ static void load(ArrayList tasks) throws IOException { command += formattedInput[i]; command += " "; } - loadTask(command, tasks); - loadTaskStatus(tasks, doneStatus); - Task.incrementCount(); + loadTask(command, tasks, classes, doneStatus); } } @@ -212,9 +217,9 @@ static void load(ArrayList tasks) throws IOException { * * @param tasks The array list of tasks */ - static void tryLoad(ArrayList tasks) { + static void tryLoad(ArrayList tasks, PriorityQueue classes) { try { - load(tasks); + load(tasks, classes); } catch (IOException e) { System.out.println("Error loading save file."); } diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 81f3d0313b..be9a2066d0 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -16,15 +16,18 @@ import java.text.SimpleDateFormat; import java.time.DateTimeException; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.format.DateTimeFormatter; +import java.time.DayOfWeek; import java.util.ArrayList; import java.util.Date; +import java.util.PriorityQueue; /** * Contains operations to manipulate the task list */ public class TaskList { - static void addTask(String line, ArrayList tasks) { + static void addTask(String line, ArrayList tasks, PriorityQueue classes) { if (line.contains("/by")) { // Adding a Deadline try { @@ -40,8 +43,7 @@ static void addTask(String line, ArrayList tasks) { } else if (line.contains("/class")) { // Adding a SchoolClass try { - addSchoolClass(line, tasks); - Task.incrementCount(); + addSchoolClass(line, classes); } catch (IllegalSchoolClassException | IndexOutOfBoundsException e) { Ui.eventErrorMessage(); } catch (expiredDateException e) { @@ -139,27 +141,32 @@ static void addEvent(String line, ArrayList tasks) throws IllegalEventExce * Adds a schoolClass to the list * * @param line The line of input from the user - * @param tasks The array list of tasks + * @param classes The priority queue of school classes */ - static void addSchoolClass(String line, ArrayList tasks) throws IllegalSchoolClassException, - startAfterEndException, expiredDateException { + static void addSchoolClass(String line, PriorityQueue classes) throws IllegalSchoolClassException, + startAfterEndException, expiredDateException, IllegalArgumentException, NullPointerException { String description = line.substring(0, line.indexOf("/class")).trim(); - String className = line.substring(line.indexOf("/class") + 6, line.indexOf("/from")).trim(); - String startString = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); - String endString = line.substring(line.indexOf("/to") + 3).trim(); - DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); - LocalDateTime start = LocalDateTime.parse(startString, dateFormat); - LocalDateTime end = LocalDateTime.parse(endString, dateFormat); - if (start.isAfter(end)) { - throw new startAfterEndException(); - } else if (start.isBefore(LocalDateTime.now()) || end.isBefore(LocalDateTime.now())) { - throw new expiredDateException(); - } else if (className.isBlank() || startString.isBlank() || endString.isBlank()) { - throw new IllegalSchoolClassException(); - } else { - SchoolClass currSchoolClass = new SchoolClass(className, description, startString, endString); - tasks.add(currSchoolClass); - Ui.addedTaskMessage(currSchoolClass); + String className = line.substring(line.indexOf("/class") + 6, line.indexOf("/day")).trim(); + try { + DayOfWeek day = DayOfWeek.valueOf(line.substring(line.indexOf("/day") + 4, line.indexOf("/from")).trim()); + String startString = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); + String endString = line.substring(line.indexOf("/to") + 3).trim(); + DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("HHmm"); + LocalTime start = LocalTime.parse(startString, timeFormat); + LocalTime end = LocalTime.parse(endString, timeFormat); + if (start.isAfter(end)) { + throw new startAfterEndException(); + } else if (className.isBlank() || startString.isBlank() || endString.isBlank()) { + throw new IllegalSchoolClassException(); + } else { + SchoolClass currSchoolClass = new SchoolClass(className, description, day, startString, endString); + classes.add(currSchoolClass); + Ui.addedSchoolClassMessage(currSchoolClass, classes); + } + } catch (IllegalArgumentException e) { + Ui.invalidDayMessage(); + } catch (NullPointerException e) { + Ui.emptyDayErrorMessage(); } } @@ -250,7 +257,41 @@ static void deleteTask(ArrayList tasks, String[] words) { } } - static void purge(ArrayList tasks) { + static void deleteClass(PriorityQueue classes, String line) throws + IllegalArgumentException, NullPointerException, StringIndexOutOfBoundsException{ + try { + // Buffer holds the string "remove class" and is redundant + String buffer = line.substring(0, line.indexOf("/class")).trim(); + String className = line.substring(line.indexOf("/class") + 6, line.indexOf("/description")).trim(); + String description = line.substring(line.indexOf("/description") + 12, line.indexOf("/day")).trim(); + DayOfWeek day = DayOfWeek.valueOf(line.substring(line.indexOf("/day") + 4, line.indexOf("/from")).trim()); + String startString = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); + String endString = line.substring(line.indexOf("/to") + 3).trim(); + SchoolClass toDelete = new SchoolClass(className, description, day, startString, endString); + if (classes.remove(toDelete) == true) { + System.out.println("class removed"); + } else { + System.out.println("class not removed"); + } + } catch (IllegalArgumentException e) { + Ui.invalidDayMessage(); + } catch (NullPointerException e) { + Ui.emptyDayErrorMessage(); + } catch (StringIndexOutOfBoundsException e) { + Ui.invalidRemoveClassMessage(); + } + } + + static void tryDeleteClass(PriorityQueue classes, String line) { + if (!line.contains("/class") || !line.contains("/description") || !line.contains("/day") || + !line.contains("/from") || !line.contains("/to")) { + Ui.invalidRemoveClassMessage(); + } else { + deleteClass(classes, line); + } + } + + static void purge(ArrayList tasks, PriorityQueue classes) { Ui.borderLine(); System.out.println("\t Displaying all expired tasks below..."); System.out.println(); @@ -321,7 +362,7 @@ static void purge(ArrayList tasks) { tasks.removeIf(task -> task == expiredTask); Task.decrementCount(); } - Storage.trySave(tasks); + Storage.trySave(tasks, classes); Ui.borderLine(); System.out.println("\t Expired Tasks have been purged from the list!"); System.out.println("\t I love purging things, human..."); diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index c4cbfc3841..aa269aedca 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -9,7 +9,9 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; +import java.util.Iterator; import java.util.Objects; +import java.util.PriorityQueue; import java.util.Scanner; /** @@ -32,6 +34,16 @@ static void list(ArrayList tasks) { borderLine(); } + static void listClasses(PriorityQueue classes) { + Iterator iterator = classes.iterator(); + borderLine(); + System.out.println("\t Here is your class schedule:\n"); + while (iterator.hasNext()) { + System.out.println(iterator.next()); + } + borderLine(); + } + /** * Finds tasks in the list that contain keywords input by the user * @@ -279,21 +291,23 @@ static void help() { System.out.println("\t - mark : I'll mark that task as done."); System.out.println("\t - unmark : I'll mark that task as undone."); System.out.println("\t - delete : I'll delete that task from your list."); + System.out.println("\t - remove class /class /description /from /to "); + System.out.println("\t : I'll remove this class from your class schedule."); System.out.println("\t - purge: I'll delete all expired tasks from your list after a confirmation."); System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); System.out.println("\t - priority <1/2/3>: I'll set the priority of a given task as"); System.out.println("\t 1:Low, 2:Medium and 3:High."); System.out.println("\t - bye: I will shut down my program.\n"); - System.out.println("\t Here are the following ways to input tasks:"); + System.out.println("\t Here are the following ways to input tasks/classes:"); System.out.println("\t Deadlines: /by "); System.out.println("\t (eg. Eat bread /by 2023-03-15 2015)"); System.out.println("\t Events : /from /to "); System.out.println("\t (eg. Meeting /from 2023-03-15 2015 /to 2023-03-15 2215)"); - System.out.println("\t Classes : /class /from " + - "/to "); - System.out.println("\t (eg. Bring laptop /class CS2113 /from 2023-03-15 1100 /to 2023-03-15 1200)"); + System.out.println("\t (eg. Bring laptop /class CS2113 /day TUESDAY /from 1100 /to 1200)"); System.out.println("\t Todo : "); - System.out.println("\t (eg. Water the plants) \n"); + System.out.println("\t (eg. Water the plants)"); + System.out.println("\t Classes : /class /day " + + "/from /to \n"); System.out.println("\t (`・v・´ ): How else may I assist you today, human?"); borderLine(); } @@ -305,6 +319,13 @@ static void addedTaskMessage(Task currentTask) { borderLine(); } + static void addedSchoolClassMessage(SchoolClass currentClass, PriorityQueue classes) { + borderLine(); + System.out.println("\t Alright, I have added this class: \n\t\t" + currentClass); + System.out.println("\t You now have " + (classes.size()) + " classes in your schedule."); + borderLine(); + } + static void deleteTaskMessage(Task taskToDelete) { borderLine(); System.out.println("\t Understood. I have removed this task:"); @@ -359,6 +380,24 @@ static void schoolClassErrorMessage() { borderLine(); } + static void invalidDayMessage() { + borderLine(); + System.out.println("\t Error. Please enter a valid day of week in all capital letters (Eg. MONDAY)."); + borderLine(); + } + + static void emptyDayErrorMessage() { + borderLine(); + System.out.println("\t Error. Please enter a day of week."); + borderLine(); + } + + static void invalidRemoveClassMessage() { + borderLine(); + System.out.println("\t Error. Please follow the correct format to remove classes."); + borderLine(); + } + static void invalidDateTimeMessage() { borderLine(); System.out.println("\t Please check the inputted format human!\n" + diff --git a/src/main/java/seedu/duck/task/SchoolClass.java b/src/main/java/seedu/duck/task/SchoolClass.java index f5aef5ec6c..c78d241d1a 100644 --- a/src/main/java/seedu/duck/task/SchoolClass.java +++ b/src/main/java/seedu/duck/task/SchoolClass.java @@ -1,13 +1,17 @@ package seedu.duck.task; -public class SchoolClass extends Task{ +import java.time.DayOfWeek; + +public class SchoolClass extends Task implements Comparable { private String className; // Name of class + private DayOfWeek day; // Day of the week private String start; // Start date/time private String end; // End date/time - public SchoolClass(String className, String description, String start, String end) { + public SchoolClass(String className, String description, DayOfWeek day, String start, String end) { super(description); this.className = className; + this.day = day; this.start = start; this.end = end; } @@ -20,6 +24,10 @@ public void setClassName(String className) { this.className = className; } + public DayOfWeek getDay() { + return this.day; + } + public String getStart() { return start; } @@ -36,19 +44,41 @@ public void setEnd(String end) { this.end = end; } + @Override + public int compareTo(SchoolClass lesson) { + if (lesson.day.compareTo(this.day) == 0) { + return this.start.compareTo(lesson.start); + } else { + return this.day.compareTo(lesson.day); + } + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || obj.getClass() != this.getClass()) { + return false; + } + SchoolClass lesson = (SchoolClass) obj; + return className.equals(lesson.getClassName()) && this.getDescription().equals(lesson.getDescription()) + && day.equals(lesson.getDay()) && start.equals(lesson.getStart()) && end.equals(lesson.getEnd()); + } + @Override public String toSaveString() { - return super.toSaveString() + " /class " + getClassName() + " /from " + getStart() + " /to " - + getEnd() + "

" + getPriorityIndex() + System.lineSeparator(); + return super.toSaveString() + " /class " + getClassName() + " /day " + getDay() + " /from " + + getStart() + " /to "+ getEnd() + System.lineSeparator(); } @Override public String toString() { if (getDescription().isBlank()) { - return "\t [C]" + "[" + getStatusIcon() + "] " + className + " (from: " + start - + " to: " + end + ")" + " (" + getPriority() + ")"; + return "\t [" + day + "]" + "[" + getStatusIcon() + "] " + className + " (from: " + + start + " to: " + end + ")"; } - return "\t [C]" + "[" + getStatusIcon() + "] " + className + ": " + getDescription() + - " (from: " + start + " to: " + end + ")" + " (" + getPriority() + ")"; + return "\t [" + day + "]" + "[" + getStatusIcon() + "] " + className + ": " + + getDescription() + " (from: " + start + " to: " + end + ")"; } } From b303dd6d657543b34b47ef28ab6cf7f62393c890 Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Sun, 26 Mar 2023 23:35:20 +0800 Subject: [PATCH 043/152] Bug fix for medium_priority --- src/main/java/seedu/duck/Ui.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 68b5eba63f..e3d978052c 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -92,7 +92,7 @@ static void printMediumPriority(ArrayList tasks){ ArrayList indexOfMediumPriority = new ArrayList(); int taskCount = Task.getTaskCount(); for (int i = 0; i < taskCount; i++) { - if (tasks.get(i).returnPriority() == 3) { + if (tasks.get(i).returnPriority() == 2) { indexOfMediumPriority.add(i); } } @@ -122,7 +122,7 @@ static void printLowPriority(ArrayList tasks){ } } if (!indexOfLowPriority.isEmpty()) { - System.out.println("\t quack!"); + System.out.println("\t Quack!"); System.out.println("\t You have " + indexOfLowPriority.size() + " tasks that are low in priority!"); for (int i = 0; i < indexOfLowPriority.size(); i++) { System.out.println("\t" + (i + 1) + "." + tasks.get(indexOfLowPriority.get(i))); @@ -175,6 +175,7 @@ private static void printFindResults(ArrayList matchingResults, int matchC * * @param matchingResults The array list of tasks that contain the keywords * @param matchCount The number of tasks in the list that contain the keywords + * @param matchingResultsIndex The index of the task in the main list */ static void printMatchingList(ArrayList matchingResults, int matchCount, ArrayList matchingResultsIndex) { borderLine(); From 7c06d78b2e77fceb86075029e70caa36c0fba1e0 Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Sun, 26 Mar 2023 23:58:47 +0800 Subject: [PATCH 044/152] Updated user guide for listing tasks by priority --- docs/UserGuide.md | 81 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 975e4821ef..a68db20244 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -67,6 +67,87 @@ Here are the tasks in your list: 4. [C][ ] CS2113: Class (from: 2023-03-25 1100 to: 2023-03-25 1200) (No priority established.) ``` +## **Listing all low priority tasks : `low_priority`** +Displays all tasks that have been assigned low priority +If there are no tasks in the low priority list, another message will be shown + +**Input:** `low_priority` +**Output: Demonstrated with 1 of each data type currently in the stored data array** +``` +Quack! + You have 3 tasks that are low in priority! + 1. [T][ ] Water plants (Low priority.) + 2. [D][ ] Submit CS2113 quiz (by: 2023-03-31 2359) (Low priority.) + 3. [E][ ] CS2113 lecture (from: 2023-03-30 1100 to: 2023-03-30 1200) (Low priority.) +``` +**If no tasks in low priority list:** +``` +There are no tasks that are low in priority! + ____________________________________________________________ +``` + +## **Listing all medium priority tasks : `medium_priority`** +Displays all tasks that have been assigned medium priority +If there are no tasks in the medium priority list, another message will be shown + +**Input:** `medium_priority` +**Output: Demonstrated with 1 of each data type currently in the stored data array** +``` +QUACK QUACK!! + You have 3 tasks that are medium in priority! + 1. [T][ ] Water plants (Medium priority.) + 2. [D][ ] Submit CS2113 quiz (by: 2023-03-31 2359) (Medium priority.) + 3. [E][ ] CS2113 lecture (from: 2023-03-30 1100 to: 2023-03-30 1200) (Medium priority.) + ____________________________________________________________ +``` +**If no tasks in medium priority list:** +``` +There are no tasks that are medium in priority! + ____________________________________________________________ +``` + +## **Listing all high priority tasks : `high_priority`** +Displays all tasks that have been assigned high priority +If there are no tasks in the high priority list, another message will be shown + +**Input:** `high_priority` +**Output: Demonstrated with 1 of each data type currently in the stored data array** +``` +QUACK QUACK QUACK!!! + You have 3 tasks that are high in priority! + 1. [T][ ] Water plants (High priority.) + 2. [D][ ] Submit CS2113 quiz (by: 2023-03-31 2359) (High priority.) + 3. [E][ ] CS2113 lecture (from: 2023-03-30 1100 to: 2023-03-30 1200) (High priority.) + ____________________________________________________________ +``` +**If no tasks in high priority list:** +``` +There are no tasks that are high in priority! + ____________________________________________________________ +``` + +## **Listing all tasks arranged by priority : `priority_list`** +Displays all tasks arranged by priority + +**Input:** `priority_list` +**Output: Demonstrated with 1 task in each priority list** +``` +____________________________________________________________ + Here are the tasks in your list arranged by priority: + ____________________________________________________________ + QUACK QUACK QUACK!!! + You have 1 tasks that are high in priority! + 1. [E][ ] CS2113 lecture (from: 2023-03-30 1100 to: 2023-03-30 1200) (High priority.) + ____________________________________________________________ + QUACK QUACK!! + You have 1 tasks that are medium in priority! + 1. [T][ ] Water plants (Medium priority.) + ____________________________________________________________ + Quack! + You have 1 tasks that are low in priority! + 1. [D][ ] Submit CS2113 quiz (by: 2023-03-31 2359) (Low priority.) + ____________________________________________________________ +``` ## **Listing all tasks up to X days in the future : `list X`** From 1d88e832f0b55f5412386ee21a06911bdb6015a2 Mon Sep 17 00:00:00 2001 From: thant Date: Mon, 27 Mar 2023 13:10:24 +0800 Subject: [PATCH 045/152] Update UserGuide.md --- docs/UserGuide.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index a68db20244..338017158e 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -13,6 +13,8 @@ Duck is a **desktop app for managing tasks and deadlines, optimised for use via * [Deleting a task :](#deleting-a-task--delete) `delete ` * [Designate a priority to a given task :](#designate-a-task-priority--priority-task_number-priority) * `priority ` + * [List tasks of low/medium/high priority :](#listing-all-low-priority-tasks--low_priority) `low_priority`/`medium_priority`/`high_priority` + * [List tasks in priority order:](#listing-all-tasks-arranged-by-priority--priority_list) `priority_list` * [Purge expired tasks :](#purge-expired-tasks--purge) `purge` * [Clearing all tasks (including datafile) :](#clearing-tasks-from-storage-clear) `clear ` * Designate a given task to be recurring **[TO BE ADDED]** : From 6e856edd223839b5768692ea94e29b546d800ecf Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Tue, 28 Mar 2023 16:43:54 +0800 Subject: [PATCH 046/152] - Added auto tracking of whether SchoolClasses are over, and resets their done status at the start of each week - Added a refresh command to refresh both the task list and class schedule, mainly used to update the done status of SchoolClasses - Added javadoc headers for newly implemented methods regarding SchoolClasses - Updated help message to show new functions --- src/main/java/seedu/duck/Parser.java | 3 ++ src/main/java/seedu/duck/Storage.java | 3 +- src/main/java/seedu/duck/TaskList.java | 61 +++++++++++++++++++++++++ src/main/java/seedu/duck/Ui.java | 14 ++++-- src/main/java/seedu/duck/task/Task.java | 4 ++ 5 files changed, 81 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 5c0e126b76..ce79012d8e 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -65,6 +65,9 @@ static void processCommand(ArrayList tasks, PriorityQueue cla } else if (line.equals("help")) { // List out all the tasks added Ui.help(); + } else if (line.equals("refresh")) { + // Refresh the task list and class schedule + TaskList.refresh(tasks, classes); } else if (words[0].equals("list") && (words.length == 2) && (isNumeric(words[1]))) { //list out all tasks in x days in the future specified by the user Ui.printUpcomingTasks(tasks, words[1]); diff --git a/src/main/java/seedu/duck/Storage.java b/src/main/java/seedu/duck/Storage.java index 19176e25f0..d162191347 100644 --- a/src/main/java/seedu/duck/Storage.java +++ b/src/main/java/seedu/duck/Storage.java @@ -13,7 +13,6 @@ import java.io.IOException; import java.time.DayOfWeek; import java.util.ArrayList; -import java.util.Iterator; import java.util.PriorityQueue; import java.util.Scanner; @@ -107,6 +106,8 @@ static void loadSchoolClass(String line, PriorityQueue classes) { String startString = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); String endString = line.substring(line.indexOf("/to") + 3).trim(); SchoolClass currSchoolClass = new SchoolClass(className, description, day, startString, endString); + + TaskList.checkClassOver(day, endString, currSchoolClass); classes.add(currSchoolClass); } diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index be9a2066d0..6627432137 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -15,6 +15,7 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.DateTimeException; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; @@ -257,6 +258,15 @@ static void deleteTask(ArrayList tasks, String[] words) { } } + /** + * Deletes a SchoolClass from the priority queue + * + * @param classes The priority queue of SchoolClasses + * @param line The line of user input + * @throws IllegalArgumentException + * @throws NullPointerException + * @throws StringIndexOutOfBoundsException + */ static void deleteClass(PriorityQueue classes, String line) throws IllegalArgumentException, NullPointerException, StringIndexOutOfBoundsException{ try { @@ -282,6 +292,14 @@ static void deleteClass(PriorityQueue classes, String line) throws } } + /** + * Tries to delete a SchoolClass from the priority queue, and throws an error message + * if unsuccessful. This method should be used instead of directly invoking + * the deleteClass() method. + * + * @param classes The priority queue of SchoolClasses + * @param line The line of user input + */ static void tryDeleteClass(PriorityQueue classes, String line) { if (!line.contains("/class") || !line.contains("/description") || !line.contains("/day") || !line.contains("/from") || !line.contains("/to")) { @@ -291,6 +309,48 @@ static void tryDeleteClass(PriorityQueue classes, String line) { } } + /** + * Checks if the current day and time is past the day and end time of the SchoolClass. + * If SchoolClass is over, mark as done, otherwise mark as not done. + * + * @param day The enum for the day of week registered in the current SchoolClass to check + * @param endString The end timing for the current SchoolClass to check + * @param currSchoolClass The current SchoolClass + */ + static void checkClassOver(DayOfWeek day, String endString, SchoolClass currSchoolClass) { + LocalDate today = LocalDate.now(); + DayOfWeek dayToday = today.getDayOfWeek(); + if (dayToday.getValue() > day.getValue()) { // day of week passed + currSchoolClass.markAsDone(); + } else if (dayToday.getValue() < day.getValue()) { // day of week not passed + currSchoolClass.markAsNotDone(); + } else { // same day of week + DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("HHmm"); + LocalTime classEndTime = LocalTime.parse(endString, timeFormat); + LocalTime currTime = LocalTime.now(); + if (currTime.isAfter(classEndTime)) { + currSchoolClass.markAsDone(); + } else { + currSchoolClass.markAsNotDone(); + } + } + } + + /** + * Clears the task list and SchoolClass priority queue, and reloads from save file. + * This function is mainly used to update the done status of SchoolClasses in the schedule. + * + * @param tasks The ArrayList of tasks + * @param classes The priority queue of SchoolClasses + */ + static void refresh(ArrayList tasks, PriorityQueue classes) { + tasks.clear(); + classes.clear(); + Task.resetCount(); + Storage.tryLoad(tasks, classes); + Ui.refreshedMessage(); + } + static void purge(ArrayList tasks, PriorityQueue classes) { Ui.borderLine(); System.out.println("\t Displaying all expired tasks below..."); @@ -381,4 +441,5 @@ static void purge(ArrayList tasks, PriorityQueue classes) { Ui.borderLine(); } } + } diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index e3d978052c..144583e6d0 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -379,6 +379,8 @@ static void help() { System.out.println("\t (`・v・´ ): Here are the commands you can give me:"); System.out.println("\t - list: I'll list out all the tasks you have recorded."); System.out.println("\t - list : I'll list out all the tasks in that number of days."); + System.out.println("\t - list classes: I'll list out the classes you have on your schedule."); + System.out.println("\t - refresh: I'll refresh your task list and class schedule."); System.out.println("\t - priority_list: I'll list out all the tasks you have recorded arranged by their priority."); System.out.println("\t - low_priority: I'll list out all the tasks you have that are low in priority."); System.out.println("\t - medium_priority: I'll list out all the tasks you have that are medium in priority."); @@ -410,14 +412,14 @@ static void help() { static void addedTaskMessage(Task currentTask) { borderLine(); - System.out.println("\t Alright, I have added this task: \n\t\t" + currentTask); + System.out.println("\t Alright, I have added this task: \n\t" + currentTask); System.out.println("\t You now have " + (Task.getTaskCount() + 1) + " tasks in your list."); borderLine(); } static void addedSchoolClassMessage(SchoolClass currentClass, PriorityQueue classes) { borderLine(); - System.out.println("\t Alright, I have added this class: \n\t\t" + currentClass); + System.out.println("\t Alright, I have added this class: \n\t" + currentClass); System.out.println("\t You now have " + (classes.size()) + " classes in your schedule."); borderLine(); } @@ -425,11 +427,17 @@ static void addedSchoolClassMessage(SchoolClass currentClass, PriorityQueue Date: Tue, 28 Mar 2023 16:50:32 +0800 Subject: [PATCH 047/152] Ensured checkstyle compliance, removed test-ui-tests since they are redundant. --- src/main/java/seedu/duck/TaskList.java | 2 +- src/main/java/seedu/duck/Ui.java | 15 ++++++++++----- src/test/java/seedu/duck/ParserTest.java | 1 - text-ui-test/runtest.bat | 19 ------------------- text-ui-test/runtest.sh | 23 ----------------------- 5 files changed, 11 insertions(+), 49 deletions(-) delete mode 100644 text-ui-test/runtest.bat delete mode 100755 text-ui-test/runtest.sh diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 6627432137..d909c84d92 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -270,7 +270,7 @@ static void deleteTask(ArrayList tasks, String[] words) { static void deleteClass(PriorityQueue classes, String line) throws IllegalArgumentException, NullPointerException, StringIndexOutOfBoundsException{ try { - // Buffer holds the string "remove class" and is redundant + // Buffer holds the string "remove class" and is redundant String buffer = line.substring(0, line.indexOf("/class")).trim(); String className = line.substring(line.indexOf("/class") + 6, line.indexOf("/description")).trim(); String description = line.substring(line.indexOf("/description") + 12, line.indexOf("/day")).trim(); diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 144583e6d0..f61b869bea 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -162,7 +162,8 @@ static void find(ArrayList tasks, String[] words) { * @param matchingResults The array list of tasks that contain the keywords * @param matchCount The number of tasks in the list that contain the keywords */ - private static void printFindResults(ArrayList matchingResults, int matchCount, ArrayList matchingResultsIndex) { + private static void printFindResults(ArrayList matchingResults, int matchCount, + ArrayList matchingResultsIndex) { if (matchingResults.isEmpty()) { noMatchMessage(); } else { @@ -177,11 +178,13 @@ private static void printFindResults(ArrayList matchingResults, int matchC * @param matchCount The number of tasks in the list that contain the keywords * @param matchingResultsIndex The index of the task in the main list */ - static void printMatchingList(ArrayList matchingResults, int matchCount, ArrayList matchingResultsIndex) { + static void printMatchingList(ArrayList matchingResults, int matchCount, + ArrayList matchingResultsIndex) { borderLine(); System.out.println("\t Here are the matching tasks in your list:"); for (int i = 0; i < matchCount; i++) { - System.out.println("\t " + (i + 1) + "." + matchingResults.get(i) + " || The index of this item is " + matchingResultsIndex.get(i)); + System.out.println("\t " + (i + 1) + "." + matchingResults.get(i) + + " || The index of this item is " + matchingResultsIndex.get(i)); } borderLine(); } @@ -381,7 +384,8 @@ static void help() { System.out.println("\t - list : I'll list out all the tasks in that number of days."); System.out.println("\t - list classes: I'll list out the classes you have on your schedule."); System.out.println("\t - refresh: I'll refresh your task list and class schedule."); - System.out.println("\t - priority_list: I'll list out all the tasks you have recorded arranged by their priority."); + System.out.println("\t - priority_list: " + + "I'll list out all the tasks you have recorded arranged by their priority."); System.out.println("\t - low_priority: I'll list out all the tasks you have that are low in priority."); System.out.println("\t - medium_priority: I'll list out all the tasks you have that are medium in priority."); System.out.println("\t - high_priority: I'll list out all the tasks you have that are high in priority."); @@ -389,7 +393,8 @@ static void help() { System.out.println("\t - mark : I'll mark that task as done."); System.out.println("\t - unmark : I'll mark that task as undone."); System.out.println("\t - delete : I'll delete that task from your list."); - System.out.println("\t - remove class /class /description /from /to "); + System.out.println("\t - remove class /class /description " + + "/day /from /to "); System.out.println("\t : I'll remove this class from your class schedule."); System.out.println("\t - purge: I'll delete all expired tasks from your list after a confirmation."); System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); diff --git a/src/test/java/seedu/duck/ParserTest.java b/src/test/java/seedu/duck/ParserTest.java index 03402d9687..3522e13a7b 100644 --- a/src/test/java/seedu/duck/ParserTest.java +++ b/src/test/java/seedu/duck/ParserTest.java @@ -1,6 +1,5 @@ package seedu.duck; -import seedu.duck.Parser; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertFalse; diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat deleted file mode 100644 index 25ac7a2989..0000000000 --- a/text-ui-test/runtest.bat +++ /dev/null @@ -1,19 +0,0 @@ -@echo off -setlocal enableextensions -pushd %~dp0 - -cd .. -call gradlew clean shadowJar - -cd build\libs -for /f "tokens=*" %%a in ( - 'dir /b *.jar' -) do ( - set jarloc=%%a -) - -java -jar %jarloc% < ..\..\text-ui-test\input.txt > ..\..\text-ui-test\ACTUAL.TXT - -cd ..\..\text-ui-test - -FC ACTUAL.TXT EXPECTED.TXT >NUL && ECHO Test passed! || Echo Test failed! diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh deleted file mode 100755 index 1dcbd12021..0000000000 --- a/text-ui-test/runtest.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -# change to script directory -cd "${0%/*}" - -cd .. -./gradlew clean shadowJar - -cd text-ui-test - -java -jar $(find ../build/libs/ -mindepth 1 -print -quit) < input.txt > ACTUAL.TXT - -cp EXPECTED.TXT EXPECTED-UNIX.TXT -dos2unix EXPECTED-UNIX.TXT ACTUAL.TXT -diff EXPECTED-UNIX.TXT ACTUAL.TXT -if [ $? -eq 0 ] -then - echo "Test passed!" - exit 0 -else - echo "Test failed!" - exit 1 -fi From 09c401c3d424ad610006f24aab6eab560ab7160d Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Tue, 28 Mar 2023 17:02:09 +0800 Subject: [PATCH 048/152] Update UserGuide.md --- docs/UserGuide.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 338017158e..530cd5b826 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -56,7 +56,7 @@ COMMAND_FORMAT : COMMAND_FUNCTIONALITY EXPLANATION Displays all tasks currently stored in the application. -**Input:** `list ` +**Input:** `list` **Output: Demonstrated with 1 of each type currently in the stored data array** @@ -69,6 +69,24 @@ Here are the tasks in your list: 4. [C][ ] CS2113: Class (from: 2023-03-25 1100 to: 2023-03-25 1200) (No priority established.) ``` +## **Displaying class schedule : `list classes`** + +Displays all School Classes currently stored in the application. + +**Input:** `list classes` + +**Output: Demonstrated with classes with different names and start/end times, with some already past their end time** + + +``` +Here is your class schedule: + +[MONDAY][X] eg2501 (from: 1600 to: 1800) +[TUESDAY][X] ee2026 (from: 0900 to: 1200) +[TUESDAY][ ] cs2113 (from: 1600 to: 1700) + +``` + ## **Listing all low priority tasks : `low_priority`** Displays all tasks that have been assigned low priority If there are no tasks in the low priority list, another message will be shown From 04282c9d7c938fe2ab1bcca16c7ad2f58c6cbd72 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Tue, 28 Mar 2023 17:10:31 +0800 Subject: [PATCH 049/152] removed text ui test folder --- text-ui-test/EXPECTED.TXT | 9 --------- text-ui-test/input.txt | 1 - 2 files changed, 10 deletions(-) delete mode 100644 text-ui-test/EXPECTED.TXT delete mode 100644 text-ui-test/input.txt diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT deleted file mode 100644 index 892cb6cae7..0000000000 --- a/text-ui-test/EXPECTED.TXT +++ /dev/null @@ -1,9 +0,0 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| - -What is your name? -Hello James Gosling diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt deleted file mode 100644 index f6ec2e9f95..0000000000 --- a/text-ui-test/input.txt +++ /dev/null @@ -1 +0,0 @@ -James Gosling \ No newline at end of file From addf3e28b25a6204b7e68fc1b3651882ff6af70b Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Tue, 28 Mar 2023 20:44:19 +0800 Subject: [PATCH 050/152] Bug fixes and added class deleted/not deleted message. --- src/main/java/seedu/duck/Parser.java | 1 + src/main/java/seedu/duck/TaskList.java | 6 +++--- src/main/java/seedu/duck/Ui.java | 12 ++++++++++++ src/main/java/seedu/duck/task/Task.java | 7 ++----- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index ce79012d8e..642dda6277 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -104,6 +104,7 @@ static void processCommand(ArrayList tasks, PriorityQueue cla // Find tasks that contain a keyword tasks.clear(); Task.clearCount(); + classes.clear(); Ui.borderLine(); System.out.println("\t Got it, all tasks have been cleared."); Ui.borderLine(); diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index d909c84d92..3926e6bae7 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -279,9 +279,9 @@ static void deleteClass(PriorityQueue classes, String line) throws String endString = line.substring(line.indexOf("/to") + 3).trim(); SchoolClass toDelete = new SchoolClass(className, description, day, startString, endString); if (classes.remove(toDelete) == true) { - System.out.println("class removed"); + Ui.deleteClassMessage(); } else { - System.out.println("class not removed"); + Ui.unsuccessfulDeleteClassMessage(); } } catch (IllegalArgumentException e) { Ui.invalidDayMessage(); @@ -345,8 +345,8 @@ static void checkClassOver(DayOfWeek day, String endString, SchoolClass currScho */ static void refresh(ArrayList tasks, PriorityQueue classes) { tasks.clear(); + Task.clearCount(); classes.clear(); - Task.resetCount(); Storage.tryLoad(tasks, classes); Ui.refreshedMessage(); } diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index f61b869bea..a31dd0a121 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -437,6 +437,18 @@ static void deleteTaskMessage(Task taskToDelete) { borderLine(); } + static void deleteClassMessage() { + borderLine(); + System.out.println("\t Class has been deleted successfully."); + borderLine(); + } + + static void unsuccessfulDeleteClassMessage() { + borderLine(); + System.out.println("\t Unsuccessful. No class has been deleted."); + borderLine(); + } + static void refreshedMessage() { borderLine(); System.out.println("\t Your task list and class schedule have been refreshed!"); diff --git a/src/main/java/seedu/duck/task/Task.java b/src/main/java/seedu/duck/task/Task.java index 62701b64da..303bac2c44 100644 --- a/src/main/java/seedu/duck/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -25,7 +25,8 @@ public String getDescription() { } public static void clearCount() { - taskCount = 0;} + taskCount = 0; + } public void markAsDone() { this.isDone = true; @@ -73,10 +74,6 @@ public static void decrementCount() { taskCount--; } - public static void resetCount() { - taskCount = 0; - } - public static int getTaskCount() { return taskCount; } From f9e89c631a9a89b929e2cde7f5a45965dfe4e199 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Tue, 28 Mar 2023 20:50:02 +0800 Subject: [PATCH 051/152] Update UserGuide.md --- docs/UserGuide.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 530cd5b826..ae30b65a28 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -6,8 +6,9 @@ Duck is a **desktop app for managing tasks and deadlines, optimised for use via * [**Features**](#features) * [Viewing help :](#viewing-help--help) `help` - * [Listing all tasks :](#listing-all-tasks--list) `list ` - * [Listing all tasks up to X days into the future :](#listing-all-tasks-up-to-x-days-in-the-future--list-x) `list X ` + * [Listing all tasks :](#listing-all-tasks--list) `list` + * [Listing all tasks up to X days into the future :](#listing-all-tasks-up-to-x-days-in-the-future--list-x) `list X` + * [Listing all School Classes :](#listing-all-School-Classes--list-classes) `list classes` * [Mark a specified task as done :](#marking-a-task--mark-task_number) `mark ` * [Unmark a specified task as not done :](#unmarking-a-task--unmark-task_number) `unmark ` * [Deleting a task :](#deleting-a-task--delete) `delete ` @@ -17,8 +18,6 @@ Duck is a **desktop app for managing tasks and deadlines, optimised for use via * [List tasks in priority order:](#listing-all-tasks-arranged-by-priority--priority_list) `priority_list` * [Purge expired tasks :](#purge-expired-tasks--purge) `purge` * [Clearing all tasks (including datafile) :](#clearing-tasks-from-storage-clear) `clear ` - * Designate a given task to be recurring **[TO BE ADDED]** : - * `recurrent ` * [Find tasks matching a given keyword :](#finding-tasks-from-storage-that-match-a-keyword-find-keyword) `find ` * [Add tasks that can be broken down into the following 4 types:](#adding-a-todo-task--description) From ae3a99a0cb50e64b78e43175cf564a32594509b5 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Tue, 28 Mar 2023 20:51:50 +0800 Subject: [PATCH 052/152] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index ae30b65a28..d07442085e 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -8,7 +8,7 @@ Duck is a **desktop app for managing tasks and deadlines, optimised for use via * [Viewing help :](#viewing-help--help) `help` * [Listing all tasks :](#listing-all-tasks--list) `list` * [Listing all tasks up to X days into the future :](#listing-all-tasks-up-to-x-days-in-the-future--list-x) `list X` - * [Listing all School Classes :](#listing-all-School-Classes--list-classes) `list classes` + * [Displaying class schedule :](#displaying-class-schedule--list-classes) `list classes` * [Mark a specified task as done :](#marking-a-task--mark-task_number) `mark ` * [Unmark a specified task as not done :](#unmarking-a-task--unmark-task_number) `unmark ` * [Deleting a task :](#deleting-a-task--delete) `delete ` From d2a2f564b956590781df13c2cf087be03a838e53 Mon Sep 17 00:00:00 2001 From: tliangac Date: Wed, 29 Mar 2023 12:40:33 +0800 Subject: [PATCH 053/152] Change Display Next Class --- src/main/java/seedu/duck/Parser.java | 2 +- src/main/java/seedu/duck/Ui.java | 46 +++++++++------------------- 2 files changed, 15 insertions(+), 33 deletions(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 5c0e126b76..6775e1482c 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -69,7 +69,7 @@ static void processCommand(ArrayList tasks, PriorityQueue cla //list out all tasks in x days in the future specified by the user Ui.printUpcomingTasks(tasks, words[1]); } else if (line.equals("upcoming class")) { - Ui.displayNextUpcomingClass(tasks); + Ui.displayNextUpcomingClass(classes); } else if (words[0].equals("unmark") && (words.length == 2) && (isNumeric(words[1]))) { // Mark a task as not done TaskList.unmarkTask(tasks, words); diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index e3d978052c..c068725b39 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -49,7 +49,7 @@ static void listClasses(PriorityQueue classes) { * * @param tasks the list of tasks */ - static void printPriorityList(ArrayList tasks){ + static void printPriorityList(ArrayList tasks) { borderLine(); System.out.println("\t Here are the tasks in your list arranged by priority:"); borderLine(); @@ -63,10 +63,10 @@ static void printPriorityList(ArrayList tasks){ * * @param tasks the list of tasks */ - static void printHighPriority(ArrayList tasks){ + static void printHighPriority(ArrayList tasks) { ArrayList indexOfHighPriority = new ArrayList(); int taskCount = Task.getTaskCount(); - for (int i = 0; i < taskCount; i++){ + for (int i = 0; i < taskCount; i++) { if (tasks.get(i).returnPriority() == 3) { indexOfHighPriority.add(i); } @@ -88,7 +88,7 @@ static void printHighPriority(ArrayList tasks){ * * @param tasks the list of tasks */ - static void printMediumPriority(ArrayList tasks){ + static void printMediumPriority(ArrayList tasks) { ArrayList indexOfMediumPriority = new ArrayList(); int taskCount = Task.getTaskCount(); for (int i = 0; i < taskCount; i++) { @@ -113,10 +113,10 @@ static void printMediumPriority(ArrayList tasks){ * * @param tasks the list of tasks */ - static void printLowPriority(ArrayList tasks){ + static void printLowPriority(ArrayList tasks) { ArrayList indexOfLowPriority = new ArrayList(); int taskCount = Task.getTaskCount(); - for (int i = 0; i < taskCount; i++){ + for (int i = 0; i < taskCount; i++) { if (tasks.get(i).returnPriority() == 1) { indexOfLowPriority.add(i); } @@ -148,7 +148,7 @@ static void find(ArrayList tasks, String[] words) { for (int i = 0; i < tasks.size(); i++) { if (tasks.get(i).getDescription().contains(keyword)) { matchingResults.add(tasks.get(i)); - matchingResultsIndex.add(i+1); + matchingResultsIndex.add(i + 1); matchCount++; } } @@ -173,8 +173,8 @@ private static void printFindResults(ArrayList matchingResults, int matchC /** * Prints the list of tasks that contain the keywords * - * @param matchingResults The array list of tasks that contain the keywords - * @param matchCount The number of tasks in the list that contain the keywords + * @param matchingResults The array list of tasks that contain the keywords + * @param matchCount The number of tasks in the list that contain the keywords * @param matchingResultsIndex The index of the task in the main list */ static void printMatchingList(ArrayList matchingResults, int matchCount, ArrayList matchingResultsIndex) { @@ -316,33 +316,15 @@ static String getTimeDiff(long timeDifferenceMilliseconds) { /** * Display Next Upcoming Class * - * @param tasks the array list of all the tasks + * @param classes the array list of all the tasks */ - static void displayNextUpcomingClass(ArrayList tasks) { + static void displayNextUpcomingClass(PriorityQueue classes) { borderLine(); - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); - Date compare = null; - int index = -1; System.out.println("\t Here are your next upcoming class: "); - for (int i = 0; i < tasks.size(); i++) { - if (tasks.get(i) instanceof SchoolClass) { - Date d; - try { - d = format.parse(((SchoolClass) tasks.get(i)).getStart()); - if (compare == null || d.before(compare)) { - compare = d; - index = i; - } - } catch (ParseException e) { - e.printStackTrace(); - } - } - } - if (index != -1) { - String re = tasks.get(index).toString().replace("[C][ ]", ""); - System.out.println("\t " + re); + if (classes.isEmpty()) { + System.out.println("\t No upcoming class!"); } else { - System.out.println("\t No upcoming class"); + System.out.println("\t" + classes.peek()); } borderLine(); } From 52b5a593e94a6df5a665974c2fadf066f313e13e Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Wed, 29 Mar 2023 14:14:09 +0800 Subject: [PATCH 054/152] Sets any task to low priority automatically --- src/main/java/seedu/duck/task/Task.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/duck/task/Task.java b/src/main/java/seedu/duck/task/Task.java index 303bac2c44..436fcc2418 100644 --- a/src/main/java/seedu/duck/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -10,7 +10,7 @@ public class Task { public Task(String description) { this.description = description; this.isDone = false; - this.priority = 0; + this.priority = 1; //automatically set to low priority } public void setDescription(String description) { From a4d4765614120ddcfcf99430618d1217ef84b6f2 Mon Sep 17 00:00:00 2001 From: sunkyan Date: Wed, 29 Mar 2023 17:57:44 +0800 Subject: [PATCH 055/152] added classes for recurring deadlines and events --- src/main/java/seedu/duck/Storage.java | 45 +++++-- src/main/java/seedu/duck/TaskList.java | 117 ++++++++++++++---- src/main/java/seedu/duck/Ui.java | 13 +- src/main/java/seedu/duck/task/Deadline.java | 2 +- src/main/java/seedu/duck/task/Event.java | 4 +- .../seedu/duck/task/RecurringDeadline.java | 23 ++++ .../java/seedu/duck/task/RecurringEvent.java | 24 ++++ 7 files changed, 185 insertions(+), 43 deletions(-) create mode 100644 src/main/java/seedu/duck/task/RecurringDeadline.java create mode 100644 src/main/java/seedu/duck/task/RecurringEvent.java diff --git a/src/main/java/seedu/duck/Storage.java b/src/main/java/seedu/duck/Storage.java index d162191347..94d4083bed 100644 --- a/src/main/java/seedu/duck/Storage.java +++ b/src/main/java/seedu/duck/Storage.java @@ -1,11 +1,7 @@ package seedu.duck; -import seedu.duck.task.Deadline; -import seedu.duck.task.Event; -import seedu.duck.task.SchoolClass; -import seedu.duck.task.Task; -import seedu.duck.task.Todo; +import seedu.duck.task.*; import java.io.File; import java.io.FileWriter; @@ -31,13 +27,21 @@ public class Storage { */ static void loadTask(String line, ArrayList tasks, PriorityQueue classes, String doneStatus) { if (line.contains("/by")) { - loadDeadline(line, tasks); + if (line.contains("/day")) { + loadRecurrDeadline(line, tasks); + } else { + loadDeadline(line, tasks); + } loadTaskStatus(tasks, doneStatus); Task.incrementCount(); } else if (line.contains("/class")) { loadSchoolClass(line, classes); } else if (line.contains("/from") || line.contains("/to")) { - loadEvent(line, tasks); + if (line.contains("/day")) { + loadRecurrEvent(line, tasks); + } else { + loadEvent(line, tasks); + } loadTaskStatus(tasks, doneStatus); Task.incrementCount(); } else { @@ -92,6 +96,17 @@ static void loadEvent(String line, ArrayList tasks) { tasks.add(currEvent); } + static void loadRecurrEvent(String line, ArrayList tasks) { + String description = line.substring(0, line.indexOf("/from")).trim(); + String start = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); + String end = line.substring(line.indexOf("/to") + 3, line.indexOf("

")).trim(); + String priority = line.substring(line.indexOf("

") + 3,line.indexOf("/day")).trim(); + DayOfWeek day = DayOfWeek.valueOf(line.substring(line.indexOf("/day") + 4).trim()); + RecurringEvent currEvent = new RecurringEvent(description, start, end, day); + currEvent.setPriority(priority); + tasks.add(currEvent); + } + /** * Adds a schoolClass to the list without generating messages, * to be used when loading from save data. @@ -127,6 +142,22 @@ static void loadDeadline(String line, ArrayList tasks) { tasks.add(currDeadline); } + /** + * Adds a RecurringDeadline to the list when loading from save data + * + * @param line The line of input from save file + * @param tasks the array list of tasks + */ + static void loadRecurrDeadline(String line, ArrayList tasks) { + String description = line.substring(0, line.indexOf("/by")).trim(); + String deadline = line.substring(line.indexOf("/by") + 3, line.indexOf("

")).trim(); + String priority = line.substring(line.indexOf("

") + 3,line.indexOf("/day")).trim(); + DayOfWeek day = DayOfWeek.valueOf(line.substring(line.indexOf("/day") + 4).trim()); + RecurringDeadline currDeadline = new RecurringDeadline(description, deadline, day); + currDeadline.setPriority(priority); + tasks.add(currDeadline); + } + /** * Load the task status of a task from the save data * diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 3926e6bae7..8fba258df0 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -6,11 +6,7 @@ import seedu.duck.exception.IllegalDeadlineException; import seedu.duck.exception.IllegalTodoException; import seedu.duck.exception.startAfterEndException; -import seedu.duck.task.Deadline; -import seedu.duck.task.Event; -import seedu.duck.task.SchoolClass; -import seedu.duck.task.Task; -import seedu.duck.task.Todo; +import seedu.duck.task.*; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -20,6 +16,7 @@ import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.DayOfWeek; +import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Date; import java.util.PriorityQueue; @@ -31,15 +28,28 @@ public class TaskList { static void addTask(String line, ArrayList tasks, PriorityQueue classes) { if (line.contains("/by")) { // Adding a Deadline - try { - addDeadline(line, tasks); - Task.incrementCount(); - } catch (IllegalDeadlineException e) { - Ui.deadlineErrorMessage(); - } catch (expiredDateException e) { - Ui.expiredErrorMessage(); - } catch (DateTimeException e) { - Ui.invalidDateTimeMessage(); + if (line.contains("/re")) { + try { + addRecurrDeadline(line, tasks); + Task.incrementCount(); + } catch(IllegalDeadlineException | StringIndexOutOfBoundsException e) { + Ui.deadlineErrorMessage(); + } catch (IllegalArgumentException e) { + Ui.invalidDayMessage(); + } catch (DateTimeParseException e) { + Ui.invalidDateTimeMessage(); + } + }else { + try { + addDeadline(line, tasks); + Task.incrementCount(); + } catch (IllegalDeadlineException e) { + Ui.deadlineErrorMessage(); + } catch (expiredDateException e) { + Ui.expiredErrorMessage(); + } catch (DateTimeException e) { + Ui.invalidDateTimeMessage(); + } } } else if (line.contains("/class")) { // Adding a SchoolClass @@ -56,17 +66,30 @@ static void addTask(String line, ArrayList tasks, PriorityQueue tasks) throws IllegalEventExce } } + static void addRecurrEvent(String line, ArrayList tasks) throws IllegalEventException{ + String description = line.substring(4, line.indexOf("/from")).trim(); + String start = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); + String end = line.substring(line.indexOf("/to") + 3, line.indexOf("/day")).trim(); + DayOfWeek day = DayOfWeek.valueOf(line.substring(line.indexOf("/day") + 4).trim()); + DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("HHmm"); + //check whether start and end are in the correct format + LocalTime.parse(start, timeFormat); + LocalTime.parse(end, timeFormat); + if (description.isBlank() || start.isBlank() || end.isBlank()) { + throw new IllegalEventException(); + } else { + RecurringEvent currEvent = new RecurringEvent(description, start, end, day); + tasks.add(currEvent); + Ui.addedTaskMessage(currEvent); + } + } + /** * Adds a schoolClass to the list * @@ -194,6 +235,28 @@ static void addDeadline(String line, ArrayList tasks) throws IllegalDeadli } } + /** + * adds a recurringDeadline to the list + * + * @param line the line of input from the user + * @param tasks the array list of tasks + */ + static void addRecurrDeadline(String line, ArrayList tasks) throws IllegalDeadlineException, + IllegalArgumentException { + String description = line.substring(4, line.indexOf("/by")).trim(); + String deadline = line.substring(line.indexOf("/by") + 3, line.indexOf("/day")).trim(); + DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("HHmm"); + LocalTime.parse(deadline, timeFormat); + DayOfWeek day = DayOfWeek.valueOf(line.substring(line.indexOf("/day") + 4).trim()); + if (description.isBlank() || deadline.isBlank()) { + throw new IllegalDeadlineException(); + } else { + RecurringDeadline currDeadline = new RecurringDeadline(description, deadline, day); + tasks.add(currDeadline); + Ui.addedTaskMessage(currDeadline); + } + } + /** * Marks a task as done * @@ -359,7 +422,7 @@ static void purge(ArrayList tasks, PriorityQueue classes) { int expiredCount = 0; ArrayList expiredTasks = new ArrayList<>(); for (Task task : tasks) { - if (task instanceof Deadline) { + if (task instanceof Deadline && !(task instanceof RecurringDeadline)) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); String deadline = ((Deadline) task).getDeadline(); Date d = null; @@ -376,7 +439,7 @@ static void purge(ArrayList tasks, PriorityQueue classes) { System.out.println(task); expiredTasks.add(task); } - } else if (task instanceof Event) { + } else if (task instanceof Event && !(task instanceof RecurringEvent)) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); String end = ((Event) task).getEnd(); Date d = null; diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index a31dd0a121..f4f2339929 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -1,9 +1,6 @@ package seedu.duck; -import seedu.duck.task.Deadline; -import seedu.duck.task.Event; -import seedu.duck.task.SchoolClass; -import seedu.duck.task.Task; +import seedu.duck.task.*; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -198,7 +195,7 @@ static void displayUpcomingDeadline(ArrayList tasks) { System.out.println("\t Here are the upcoming deadline: "); int count = 0; for (int i = 0; i < tasks.size(); i++) { - if (tasks.get(i) instanceof Deadline) { + if (tasks.get(i) instanceof Deadline && !(tasks.get(i) instanceof RecurringDeadline)) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); String deadline = ((Deadline) tasks.get(i)).getDeadline(); Date d; @@ -404,13 +401,17 @@ static void help() { System.out.println("\t Here are the following ways to input tasks/classes:"); System.out.println("\t Deadlines: /by "); System.out.println("\t (eg. Eat bread /by 2023-03-15 2015)"); + System.out.println("\t Recurring deadlines: /re /by /day "); + System.out.println("\t (eg. /re Eat bread /by 2015 /day MONDAY)"); System.out.println("\t Events : /from /to "); System.out.println("\t (eg. Meeting /from 2023-03-15 2015 /to 2023-03-15 2215)"); - System.out.println("\t (eg. Bring laptop /class CS2113 /day TUESDAY /from 1100 /to 1200)"); + System.out.println("\t Recurring events: /re /from /to /day "); + System.out.println("\t (eg. /re Meeting /from 2015 /to 2215 /day MONDAY)"); System.out.println("\t Todo : "); System.out.println("\t (eg. Water the plants)"); System.out.println("\t Classes : /class /day " + "/from /to \n"); + System.out.println("\t (eg. Bring laptop /class CS2113 /day TUESDAY /from 1100 /to 1200)"); System.out.println("\t (`・v・´ ): How else may I assist you today, human?"); borderLine(); } diff --git a/src/main/java/seedu/duck/task/Deadline.java b/src/main/java/seedu/duck/task/Deadline.java index 2ab8e14a0d..f9a59eb076 100644 --- a/src/main/java/seedu/duck/task/Deadline.java +++ b/src/main/java/seedu/duck/task/Deadline.java @@ -1,7 +1,7 @@ package seedu.duck.task; public class Deadline extends Task { - private String by; + protected String by; public Deadline(String description, String deadline) { super(description); diff --git a/src/main/java/seedu/duck/task/Event.java b/src/main/java/seedu/duck/task/Event.java index 7e36d028fd..2022891731 100644 --- a/src/main/java/seedu/duck/task/Event.java +++ b/src/main/java/seedu/duck/task/Event.java @@ -1,8 +1,8 @@ package seedu.duck.task; public class Event extends Task { - private String start; // Start date/time - private String end; // End date/time + protected String start; // Start date/time + protected String end; // End date/time public Event(String description, String start, String end) { super(description); diff --git a/src/main/java/seedu/duck/task/RecurringDeadline.java b/src/main/java/seedu/duck/task/RecurringDeadline.java new file mode 100644 index 0000000000..307613a2a6 --- /dev/null +++ b/src/main/java/seedu/duck/task/RecurringDeadline.java @@ -0,0 +1,23 @@ +package seedu.duck.task; + +import java.time.DayOfWeek; +public class RecurringDeadline extends Deadline{ + private DayOfWeek day; + + public RecurringDeadline(String description, String by, DayOfWeek day) { + super(description, by); + this.day = day; + } + + @Override + public String toSaveString() { + return getDoneConditionString() + " " + getDescription() + " /by " + getDeadline() + "

" + + getPriorityIndex() + " /day " + day + System.lineSeparator(); + } + + @Override + public String toString() { + return "\t [D]" + "[" + getStatusIcon() + "] " + getDescription() + " (by: " + super.by + ")" + + " (every " + day + ") (" + getPriority() + ")"; + } +} diff --git a/src/main/java/seedu/duck/task/RecurringEvent.java b/src/main/java/seedu/duck/task/RecurringEvent.java new file mode 100644 index 0000000000..15392496ee --- /dev/null +++ b/src/main/java/seedu/duck/task/RecurringEvent.java @@ -0,0 +1,24 @@ +package seedu.duck.task; + +import java.time.DayOfWeek; + +public class RecurringEvent extends Event { + private DayOfWeek day; + + public RecurringEvent(String description, String start, String end, DayOfWeek day) { + super(description, start, end); + this.day = day; + } + + @Override + public String toSaveString() { + return getDoneConditionString() + " " + getDescription() + " /from " + getStart() + " /to " + getEnd() + + "

" + getPriorityIndex() + " /day " + day + System.lineSeparator(); + } + + @Override + public String toString() { + return "\t [E]" + "[" + getStatusIcon() + "] " + getDescription() + " (from: " + super.start + + " to: " + super.end + ")" + " (every " + day + ") (" + getPriority() + ")"; + } +} From 7af7c432a711318633edeed72c5b685fa4251b65 Mon Sep 17 00:00:00 2001 From: sunkyan Date: Wed, 29 Mar 2023 20:02:01 +0800 Subject: [PATCH 056/152] added a function to view all tasks and classes today --- src/main/java/seedu/duck/Parser.java | 6 ++- src/main/java/seedu/duck/Ui.java | 49 +++++++++++++++++++ src/main/java/seedu/duck/task/Deadline.java | 2 +- src/main/java/seedu/duck/task/Event.java | 4 +- .../seedu/duck/task/RecurringDeadline.java | 6 ++- .../java/seedu/duck/task/RecurringEvent.java | 8 ++- 6 files changed, 68 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 39b3d9b37a..100bd3f5e7 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -41,13 +41,17 @@ public static boolean isNumeric(String word) { */ static void processCommand(ArrayList tasks, PriorityQueue classes, String line, Scanner in) throws IOException { - while (!line.equals("bye")) { // Exits the program if input is "bye" + while (!line.trim().equals("bye")) { // Exits the program if input is "bye" String[] words = line.split(" "); + line = line.trim(); if (line.isBlank()) { Ui.emptyCommandMessage(); } else if (line.equals("list")) { // List out all the tasks added Ui.list(tasks); + } else if (line.equals("list today")) { + //list out all classes and tasks today + Ui.listToday(tasks, classes); } else if (line.equals("priority_list")){ // Lists out all the tasks by priority Ui.printPriorityList(tasks); diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index ba0bdac16c..4f450abfb0 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -4,6 +4,9 @@ import java.text.ParseException; import java.text.SimpleDateFormat; +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; @@ -41,6 +44,51 @@ static void listClasses(PriorityQueue classes) { borderLine(); } + /** + * prints out all classes, deadlines and events happening today + * @param tasks array list of all tasks + * @param classes pq of all classes + */ + static void listToday(ArrayList tasks, PriorityQueue classes) { + LocalDate today = LocalDate.now(); + DayOfWeek dayToday = today.getDayOfWeek(); + borderLine(); + System.out.println("\t Here is your class schedule for today"); + for (SchoolClass c : classes) { + if (c.getDay() == dayToday) { + System.out.println(c); + } + } + System.out.println(); + DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + String dateToday = dateFormat.format(today); + System.out.println("\t Here are your tasks today"); + for (Task task : tasks) { + if (task instanceof Deadline) { + if (task instanceof RecurringDeadline) { + if (((RecurringDeadline) task).getDay() == dayToday) { + System.out.println(task); + } + } else { + if (((Deadline) task).getDeadline().startsWith(dateToday)) { + System.out.println(task); + } + } + } else if (task instanceof Event) { + if (task instanceof RecurringEvent) { + if (((RecurringEvent) task).getDay() == dayToday) { + System.out.println(task); + } + } else { + if (((Event) task).getStart().startsWith(dateToday)) { + System.out.println(task); + } + } + } + } + borderLine(); + } + /** * Prints out all currently stored tasks in the list arranged by their priority from high, medium to low * @@ -362,6 +410,7 @@ static void help() { System.out.println("\t - list: I'll list out all the tasks you have recorded."); System.out.println("\t - list : I'll list out all the tasks in that number of days."); System.out.println("\t - list classes: I'll list out the classes you have on your schedule."); + System.out.println("\t - list today: I'll list out all the classes, deadlines and events you have today."); System.out.println("\t - refresh: I'll refresh your task list and class schedule."); System.out.println("\t - priority_list: " + "I'll list out all the tasks you have recorded arranged by their priority."); diff --git a/src/main/java/seedu/duck/task/Deadline.java b/src/main/java/seedu/duck/task/Deadline.java index f9a59eb076..2ab8e14a0d 100644 --- a/src/main/java/seedu/duck/task/Deadline.java +++ b/src/main/java/seedu/duck/task/Deadline.java @@ -1,7 +1,7 @@ package seedu.duck.task; public class Deadline extends Task { - protected String by; + private String by; public Deadline(String description, String deadline) { super(description); diff --git a/src/main/java/seedu/duck/task/Event.java b/src/main/java/seedu/duck/task/Event.java index 2022891731..7e36d028fd 100644 --- a/src/main/java/seedu/duck/task/Event.java +++ b/src/main/java/seedu/duck/task/Event.java @@ -1,8 +1,8 @@ package seedu.duck.task; public class Event extends Task { - protected String start; // Start date/time - protected String end; // End date/time + private String start; // Start date/time + private String end; // End date/time public Event(String description, String start, String end) { super(description); diff --git a/src/main/java/seedu/duck/task/RecurringDeadline.java b/src/main/java/seedu/duck/task/RecurringDeadline.java index 307613a2a6..95a95f193e 100644 --- a/src/main/java/seedu/duck/task/RecurringDeadline.java +++ b/src/main/java/seedu/duck/task/RecurringDeadline.java @@ -9,6 +9,10 @@ public RecurringDeadline(String description, String by, DayOfWeek day) { this.day = day; } + public DayOfWeek getDay() { + return this.day; + } + @Override public String toSaveString() { return getDoneConditionString() + " " + getDescription() + " /by " + getDeadline() + "

" + @@ -17,7 +21,7 @@ public String toSaveString() { @Override public String toString() { - return "\t [D]" + "[" + getStatusIcon() + "] " + getDescription() + " (by: " + super.by + ")" + + return "\t [D]" + "[" + getStatusIcon() + "] " + getDescription() + " (by: " + super.getDeadline() + ")" + " (every " + day + ") (" + getPriority() + ")"; } } diff --git a/src/main/java/seedu/duck/task/RecurringEvent.java b/src/main/java/seedu/duck/task/RecurringEvent.java index 15392496ee..4fcc61f284 100644 --- a/src/main/java/seedu/duck/task/RecurringEvent.java +++ b/src/main/java/seedu/duck/task/RecurringEvent.java @@ -10,6 +10,10 @@ public RecurringEvent(String description, String start, String end, DayOfWeek da this.day = day; } + public DayOfWeek getDay() { + return this.day; + } + @Override public String toSaveString() { return getDoneConditionString() + " " + getDescription() + " /from " + getStart() + " /to " + getEnd() + @@ -18,7 +22,7 @@ public String toSaveString() { @Override public String toString() { - return "\t [E]" + "[" + getStatusIcon() + "] " + getDescription() + " (from: " + super.start - + " to: " + super.end + ")" + " (every " + day + ") (" + getPriority() + ")"; + return "\t [E]" + "[" + getStatusIcon() + "] " + getDescription() + " (from: " + super.getStart() + + " to: " + super.getEnd() + ")" + " (every " + day + ") (" + getPriority() + ")"; } } From d85953f0ebab298774dbafacf98b96e8f9f40f86 Mon Sep 17 00:00:00 2001 From: skyanzy <88618401+skyanzy@users.noreply.github.com> Date: Wed, 29 Mar 2023 20:23:34 +0800 Subject: [PATCH 057/152] Update UserGuide.md --- docs/UserGuide.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index d07442085e..4fb76216f4 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -7,6 +7,7 @@ Duck is a **desktop app for managing tasks and deadlines, optimised for use via * [**Features**](#features) * [Viewing help :](#viewing-help--help) `help` * [Listing all tasks :](#listing-all-tasks--list) `list` + * [Listing all tasks and classes happening today :](#listing-all-tasks--list) `list today` * [Listing all tasks up to X days into the future :](#listing-all-tasks-up-to-x-days-in-the-future--list-x) `list X` * [Displaying class schedule :](#displaying-class-schedule--list-classes) `list classes` * [Mark a specified task as done :](#marking-a-task--mark-task_number) `mark ` @@ -68,6 +69,29 @@ Here are the tasks in your list: 4. [C][ ] CS2113: Class (from: 2023-03-25 1100 to: 2023-03-25 1200) (No priority established.) ``` +## **Listing all tasks and classes happening today : `list today`** + +Displays all deadlines, events and classes happening today. + +**Input:** `list today` + +**Output: Demonstrated with 1 of each type currently in the stored data array** + + +``` + ____________________________________________________________ + Here is your class schedule for today + [WEDNESDAY][X] cs2113 (from: 1200 to: 1300) + + Here are your tasks today + [D][ ] sleep (by: 2023-03-29 2000) (No priority established.) + [D][ ] shower (by: 2000) (every WEDNESDAY) (No priority established.) + [E][ ] study (from: 2023-03-29 2100 to: 2023-04-23 2300) (No priority established.) + [E][ ] study (from: 0800 to: 2300) (every WEDNESDAY) (No priority established.) + ____________________________________________________________ +``` + + ## **Displaying class schedule : `list classes`** Displays all School Classes currently stored in the application. From 942adf231dc5f1a609b45aa522c04cf0da000e7c Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Wed, 29 Mar 2023 22:14:28 +0800 Subject: [PATCH 058/152] Added feature to add, delete and view notes of a item. Notes also print with the task that they are under --- src/main/java/seedu/duck/Parser.java | 12 ++++-- src/main/java/seedu/duck/TaskList.java | 23 +++++++++++ src/main/java/seedu/duck/Ui.java | 49 ++++++++++++++++++++++-- src/main/java/seedu/duck/task/Task.java | 16 +++++++- src/test/java/seedu/duck/ParserTest.java | 2 +- 5 files changed, 93 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 39b3d9b37a..ecc92a96fd 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -99,7 +99,13 @@ static void processCommand(ArrayList tasks, PriorityQueue cla // Find tasks that contain a keyword TaskList.setPriority(tasks,words); Storage.trySave(tasks, classes); - } else if (words[0].equals("clear")) { + } else if (words[0].equals("add_note") && (words.length == 2) && (isNumeric(words[1]))){ + TaskList.addNote(tasks,words); + } else if (words[0].equals("delete_note") && (words.length == 3)){ + TaskList.deleteNote(tasks, words); + }else if (words[0].equals("notes") && (words.length == 2) && (isNumeric(words[1]))){ + Ui.printNotes(tasks,words); + }else if (words[0].equals("clear")) { if (Ui.doubleCheck()) { // Find tasks that contain a keyword tasks.clear(); @@ -130,9 +136,9 @@ static void processCommand(ArrayList tasks, PriorityQueue cla * @param words The array of words generated from the user input * @return The keywords string to use for the find function */ - static String processKeywords(String[] words) { + static String processKeywords(String[] words,int index) { String rawKeyword = ""; - for (int i = 1; i < words.length; i++) { + for (int i = index; i < words.length; i++) { rawKeyword += (" " + words[i]); } String keyword = rawKeyword.trim(); diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 3926e6bae7..db356dea4d 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.PriorityQueue; +import java.util.Scanner; /** * Contains operations to manipulate the task list @@ -441,5 +442,27 @@ static void purge(ArrayList tasks, PriorityQueue classes) { Ui.borderLine(); } } + static void addNote(ArrayList tasks, String[] words){ + int index = Integer.parseInt(words[1]); + System.out.println("\t What note would you like to add to the following task?"); + System.out.println(tasks.get(index-1).toString()); + Ui.borderLine(); + Scanner userInput = new Scanner(System.in); + String noteToAdd = userInput.nextLine(); + tasks.get(index-1).addNotes(noteToAdd); + System.out.println("\t The note has been added!"); + Ui.borderLine(); + } + + static void deleteNote(ArrayList tasks, String[] words){ + int index = Integer.parseInt(words[1]); + int indexOfNoteToBeDeleted = Integer.parseInt(words[2]); + Ui.borderLine(); + System.out.println("\t Deleting note: "); + ArrayList noteToBeDeleted = tasks.get(index-1).getAdditionalNotes(); + System.out.println("\t \t" + noteToBeDeleted.get(indexOfNoteToBeDeleted-1)); + tasks.get(index-1).deleteNote(indexOfNoteToBeDeleted); + Ui.borderLine(); + } } diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 8a99ccc3da..63a90d5ad0 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -18,7 +18,6 @@ * Deals with interactions with the user */ public class Ui { - /** * Prints out all currently stored tasks in the list * @@ -30,6 +29,9 @@ static void list(ArrayList tasks) { System.out.println("\t Here are the tasks in your list:"); for (int i = 0; i < taskCount; i++) { System.out.println("\t " + (i + 1) + "." + tasks.get(i)); + if (!tasks.get(i).getAdditionalNotes().isEmpty()){ + printList(tasks, i); + } } borderLine(); } @@ -76,6 +78,12 @@ static void printHighPriority(ArrayList tasks) { System.out.println("\t You have " + indexOfHighPriority.size() + " tasks that are high in priority!"); for (int i = 0; i < indexOfHighPriority.size(); i++) { System.out.println("\t" + (i + 1) + "." + tasks.get(indexOfHighPriority.get(i))); + if (!tasks.get(i).getAdditionalNotes().isEmpty()){ + ArrayList toBePrinted = tasks.get(i).getAdditionalNotes(); + for (int j = 0; j < toBePrinted.size(); j++){ + System.out.println("\t" + "\t - " + (j+1) + ". " + toBePrinted.get(j)); + } + } } } else { System.out.println("\t There are no tasks that are high in priority!"); @@ -101,6 +109,12 @@ static void printMediumPriority(ArrayList tasks) { System.out.println("\t You have " + indexOfMediumPriority.size() + " tasks that are medium in priority!"); for (int i = 0; i < indexOfMediumPriority.size(); i++) { System.out.println("\t" + (i + 1) + "." + tasks.get(indexOfMediumPriority.get(i))); + if (!tasks.get(i).getAdditionalNotes().isEmpty()){ + ArrayList toBePrinted = tasks.get(i).getAdditionalNotes(); + for (int j = 0; j < toBePrinted.size(); j++){ + System.out.println("\t" + "\t - " + (j+1) + ". " + toBePrinted.get(j)); + } + } } } else { System.out.println("\t There are no tasks that are medium in priority!"); @@ -126,6 +140,12 @@ static void printLowPriority(ArrayList tasks) { System.out.println("\t You have " + indexOfLowPriority.size() + " tasks that are low in priority!"); for (int i = 0; i < indexOfLowPriority.size(); i++) { System.out.println("\t" + (i + 1) + "." + tasks.get(indexOfLowPriority.get(i))); + if (!tasks.get(i).getAdditionalNotes().isEmpty()){ + ArrayList toBePrinted = tasks.get(i).getAdditionalNotes(); + for (int j = 0; j < toBePrinted.size(); j++){ + System.out.println("\t" + "\t - " + (j+1) + ". " + toBePrinted.get(j)); + } + } } } else { System.out.println("\t There are no tasks that are low in priority!"); @@ -143,7 +163,7 @@ static void find(ArrayList tasks, String[] words) { ArrayList matchingResults = new ArrayList<>(); ArrayList matchingResultsIndex = new ArrayList<>(); int matchCount = 0; - String keyword = Parser.processKeywords(words); + String keyword = Parser.processKeywords(words, 1); for (int i = 0; i < tasks.size(); i++) { if (tasks.get(i).getDescription().contains(keyword)) { @@ -377,6 +397,9 @@ static void help() { System.out.println("\t - delete : I'll delete that task from your list."); System.out.println("\t - remove class /class /description " + "/day /from /to "); + System.out.println("\t - add_note : I'll add an additional note to that task!" ); + System.out.println("\t - delete_note : I'll delete additional note to that task!" ); + System.out.println("\t - notes : I'll print the additional notes for that task!" ); System.out.println("\t : I'll remove this class from your class schedule."); System.out.println("\t - purge: I'll delete all expired tasks from your list after a confirmation."); System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); @@ -514,13 +537,31 @@ static void invalidDateTimeMessage() { */ static void greetingMessage() { borderLine(); - System.out.println("\t (`・v・´ ): Nice to meet you human. As you can see, I'm a Duck."); - System.out.println("\t (´˘v˘´ ): As a Duck, I can only understand simple commands. " + + borderLine(); + System.out.println("\t (`・v・´ ): Quack. Nice to meet you human. As you can see, I'm a Duck."); + System.out.println("\t (´˘v˘´ ): As a Duck, I can only understand simple commands. Quack. " + "Human speech is so confusing!"); System.out.println("\t (´˘v˘´ ): That being said, I am a smart Duck. " + "If you wish to know what I understand, just enter 'help'."); System.out.println("\t (`・v・´ ): How may I assist you today, human?"); } + static void printNotes(ArrayList tasks, String []words) { + int index = Integer.parseInt(words[1]); + ArrayList toBePrinted = tasks.get(index-1).getAdditionalNotes(); + if (!toBePrinted.isEmpty()) { + for (int i = 0; i < toBePrinted.size(); i++) { + System.out.println("\t" + (i + 1) + ". " + toBePrinted.get(i)); + } + } + borderLine(); + } + + static void printList(ArrayList tasks,int index){ + ArrayList toBePrinted = tasks.get(index).getAdditionalNotes(); + for (int j = 0; j < toBePrinted.size(); j++){ + System.out.println("\t" + "\t - " + (j+1) + ". " + toBePrinted.get(j)); + } + } /** * Prints the exiting message when closing the program diff --git a/src/main/java/seedu/duck/task/Task.java b/src/main/java/seedu/duck/task/Task.java index 436fcc2418..6826e2fe6e 100644 --- a/src/main/java/seedu/duck/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -1,16 +1,18 @@ package seedu.duck.task; - +import java.util.ArrayList; public class Task { private static int taskCount; private String description; private int priority; private boolean isDone; + private final ArrayList additionalNotes; public Task(String description) { this.description = description; this.isDone = false; this.priority = 1; //automatically set to low priority + this.additionalNotes = new ArrayList(); } public void setDescription(String description) { @@ -44,6 +46,18 @@ public String getStatusIcon() { return " "; } + public void addNotes(String noteToAdd){ + this.additionalNotes.add(noteToAdd); + } + + public ArrayList getAdditionalNotes(){ + return this.additionalNotes; + } + + public void deleteNote(int indexToBeDeleted){ + this.additionalNotes.remove(indexToBeDeleted-1); + } + public String getPriority() { if (priority == 1) { // Mark done task with X diff --git a/src/test/java/seedu/duck/ParserTest.java b/src/test/java/seedu/duck/ParserTest.java index 3522e13a7b..5520fce1ab 100644 --- a/src/test/java/seedu/duck/ParserTest.java +++ b/src/test/java/seedu/duck/ParserTest.java @@ -19,6 +19,6 @@ public void testIsNumeric() { @Test public void testProcessKeywords() { - assertEquals("keyword", Parser.processKeywords(words)); + assertEquals("keyword", Parser.processKeywords(words,1)); } } From eb62752cb30a1d3542ed0999e45b9a3b1b590811 Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Wed, 29 Mar 2023 22:16:27 +0800 Subject: [PATCH 059/152] Added a function to print a duck for greeting and exit message --- src/main/java/seedu/duck/Ui.java | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 63a90d5ad0..f03c700011 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -14,10 +14,31 @@ import java.util.PriorityQueue; import java.util.Scanner; + /** * Deals with interactions with the user */ public class Ui { + static void printDuck(){ + System.out.println(" ,-.\n"+ + " ,--' ~.).\n"+ + " ,' `.\n"+ + " ; (((__ __)))\n"+ + " ; ( (#) ( (#)\n"+ + " | \\_/___\\_/\n"+ + " ,\" ,-' `__\".\n"+ + " ( ( ._ ____`.)--._ _\n"+ + " `._ `-.`-' \\(`-' _ `-. _,-' `-/`.\n"+ + " ,') `.`._)) ,' `. `. ,',' ;\n"+ + " .' . `--' / ). `. ;\n"+ + " ; `- / ' ) ;\n"+ + " \\ ') ,'\n"+ + " \\ ,' ;\n"+ + " \\ `~~~' ,'\n"+ + " `. _,'\n"+ + " `-._________,--'"); + } + /** * Prints out all currently stored tasks in the list * @@ -536,6 +557,7 @@ static void invalidDateTimeMessage() { * Prints the startup message, includes instructions on available commands */ static void greetingMessage() { + printDuck(); borderLine(); borderLine(); System.out.println("\t (`・v・´ ): Quack. Nice to meet you human. As you can see, I'm a Duck."); @@ -567,6 +589,7 @@ static void printList(ArrayList tasks,int index){ * Prints the exiting message when closing the program */ static void exitMessage() { + printDuck(); borderLine(); System.out.println("\t Bye. Hope to see you again soon!"); borderLine(); From a74de1a46fa469efe43d22f6be3aa60f2efd29cd Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Wed, 29 Mar 2023 23:59:13 +0800 Subject: [PATCH 060/152] Update UserGuide.md --- docs/UserGuide.md | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 4fb76216f4..1857e67dc9 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -13,10 +13,12 @@ Duck is a **desktop app for managing tasks and deadlines, optimised for use via * [Mark a specified task as done :](#marking-a-task--mark-task_number) `mark ` * [Unmark a specified task as not done :](#unmarking-a-task--unmark-task_number) `unmark ` * [Deleting a task :](#deleting-a-task--delete) `delete ` + * [Deleting a school class :](#deleting-a-school-class--remove-class) `remove class /class /description /day /from /to ` * [Designate a priority to a given task :](#designate-a-task-priority--priority-task_number-priority) * `priority ` * [List tasks of low/medium/high priority :](#listing-all-low-priority-tasks--low_priority) `low_priority`/`medium_priority`/`high_priority` * [List tasks in priority order:](#listing-all-tasks-arranged-by-priority--priority_list) `priority_list` + * [Refresh task list and class schedule:](#refreshing-task-list-and-class-schedule--refresh) `refresh` * [Purge expired tasks :](#purge-expired-tasks--purge) `purge` * [Clearing all tasks (including datafile) :](#clearing-tasks-from-storage-clear) `clear ` * [Find tasks matching a given keyword :](#finding-tasks-from-storage-that-match-a-keyword-find-keyword) `find ` @@ -259,6 +261,23 @@ Understood. I have removed this task: You now have 3 tasks in your list. ``` + + +## **Deleting a school class : `remove class`** + +Removes a school class from the schedule. + +**Input:** `remove class /class /description /day /from /to ` + +**Output: Demonstrated with input `remove class /class CS2113 /description /day THURSDAY /from 1100 /to 1200`** + + +``` +Class has been deleted successfully. +``` + + + ## **Designate a task priority : `priority `** @@ -281,6 +300,19 @@ Understood. The task's new priority is: ``` +## **Refreshing task list and class schedule : `refresh`** + +Clears the task list and class schedule, and reloads them from the savedata. This function is mainly used to update class sorting and tracking. + +**Output:** + + +``` +Your task list and class schedule have been refreshed! +``` + + + ## **Purge Expired Tasks : `purge`** Prompts the user for confirmation. Proceeds to remove all expired tasks from storage upon confirmation. This operation is automatically executed once upon Duck’s startup. @@ -401,19 +433,19 @@ You now have 4 tasks in your list. -## **Adding a Class Task : ` /class /from /to `** +## **Adding a School Class : ` /class /day /from /to `** Adds a Class task to the storage of Duck -**Input:** ` /class /from /to ` +**Input:** ` /class /day /from /to ` -**Output: Demonstrated by inputting `homework /class class /from 2023-03-25 1100 /to 2023-03-25 1300`** +**Output: Demonstrated by inputting `Bring laptop /class CS2113 /day THURSDAY /from 1100 /to 1200`** ``` Alright, I have added this task: - [C][ ] class: homework (from: 2023-03-25 1100 to: 2023-03-25 1300) (No priority established.) -You now have 5 tasks in your list. + [THURSDAY][ ] CS2113: Bring laptop (from: 1100 to: 1200) +You now have 1 class in your schedule. ``` From 6a14272ce22c364dd2962202d4caf229c22c3011 Mon Sep 17 00:00:00 2001 From: skyanzy <88618401+skyanzy@users.noreply.github.com> Date: Thu, 30 Mar 2023 10:27:20 +0800 Subject: [PATCH 061/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 473b26faf6..907fcf7b1a 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -187,13 +187,26 @@ The following are the new operations implemented.
-### List Upcoming Tasks Feature +### Recurring deadlines and events feature **Implementation** -The ```Ui#printUpcomingTasks()``` was implemented to allow the user to view their upcoming tasks in ```ndays``` days where ```ndays``` is specified.  +The `RecurringDeadline` and `RecurringEvent` classes are implemented to facilitate the adding of deadlines and events that happen every week to the `TaskList`. They extend `Deadline` and `Event` respectively with an additional `DayOfWeek` attribute `day` to indicate which day of the week the task recurs on. They both override the `toString()` and `toSaveString()` methods to return the correct `String` representation for output to the user and storage. `RecurringDeadline` and `RecurringEvent` also have a public method `getDay()` to return the private attribute `day`. + +**The following new operations are implemented. ** + +- `TaskList#addRecurrDeadline()` -- adds a `RecurringDeadline` object to the task list + +- `Storage#loadRecurrDeadline()` -- loads a `RecurringDeadline` from the saved data file to the task list + +- `TaskList#addRecurrEvent()` -- adds a `RecurringEvent` object to the task list + +- `Storage#loadRecurrEvent()` -- loads a `RecurringEvent` from the saved data file to the task list + +Below is a class diagram for the implementation + + image -- ```Ui#printUpcomingTasks()``` - navigates through the task list and compares the due time/starting time of that task and current time. prints all upcoming tasks in the number of days specified.
From c5e4adbec729703f69fc3fc424169d9d972563fd Mon Sep 17 00:00:00 2001 From: sunkyan Date: Thu, 30 Mar 2023 11:52:55 +0800 Subject: [PATCH 062/152] added class diagram for recurring tasks --- docs/tP Diagram Editable.pptx | Bin 71531 -> 76131 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/tP Diagram Editable.pptx b/docs/tP Diagram Editable.pptx index 6858af68a0b2b5b995a303c3f6b1bdef3754f574..1a3de56fa1eb462085f2f800ef8759527f7f5a68 100644 GIT binary patch delta 22967 zcmX6^1ymh9)4sSAcXw}bcX#*Vu0@OM#ickGcXxMpibHX?;#}OFzwh_&$;swqHoKEK zJIOOo5^xRl-W)WZiaZoF7629i4*&qj0b5Ql?3)k(fB;%O9xWsgOY%|XO?;oxb_0hl zIHSS%JF9FTT-ts!Cr^t-XYsp_VPX)X92|?*io}i6CBJgL@4?6FH{4mQ=mR;LBFt7< zXf{p!)WQ$}LBr-)S#x3#KBku#{KECSIoHiE_a?QTgheLBN(3Mf!GhXx)GR%%b-<5apvTXb+hoHjJL*L^bo}lRfuyx_9V>4I5@7`s;!lbp=7$OYFOE1e)~? z1V8dS2e&OfVP^%|FH#QLqHNF0xQtb`FJhMY7dgtp#B;=eC3CW|iJt$uWEAE+-S%c} ziXDy3<26_{NZBHA{KmPO_^74uC4+@XnEaSascxI6Uvv*TJO=ZQfR@KLYo`r8NX*4C zsfFBOV$Kt@KWR`8El7D!5gG+VSW)|#{C&-?YBUE%pshVX_|kjKyK>%R>d^Ktj#V8& z$XMw3Ypa5WN#Z~py@LA_Yp5)ya0$!v-w`Yt=eM*0^LSGAG>scGzUOd-><3_o?J144 zS9;ge8t0WuSX{VezJm=1*o$JNE8k$6$}S~(#Q-= z1BG~F5W3$82>>9YfQ;ZsfNLyRBbT)2#1z{~HcmaFAr(~<9OWPt8`3^Sg~-#D1baHy zwa!Z(QnUz~dx)Q*=bzWt*KuYeR{lP8>CL5T*g>@L+Y0fLUNkpBy)?(q^v!1G^opKJ zX*(RE(iMNs|AJG!I4h|%lYSJKRKPg2Wh6k`H`iFk7B(<4Ms}cM0}t}-L%v0Z)%d#o zl-=t08zb^yLVB5J-pusV#IDj7ZQ9(AYww#}1}wCG%BuUbB>caQJ*ZlE7lG@4W6 z!Tjq~!>Kv|MYpd7djg1AT>h3UOy|dGitQDoe0Yf#_oIKz_7V451A^WIiIlv5vLtQh5TRJq(n^ctKkj?dy$X7H|DFr4`>1PxLi4!B z`ap;0;-{gD4qkD!4cE7>&}~#It1el2RMz6%j3=H~zRO#F89g>tnq0A^USHai(~V9u zFWvArT%NsCT*=u*w3DMC#ekMadq9K>CI4cVGdl57sE5u~4Aij~8-p?$=LWH)$jWcI zi>?i*#lKb(&$xnAO6jmX2kNhHrHXl@>aKOQgRs4HS+qP9Xyz{!bbTNzPsBmm+FJJ& zDMDIx??_7Lt%>Ujgz{{K`*L|j=xlD(=BLqnvpY^o0=gU*_%WmsG&>2($i)YH+0U+M zQbMqD6C=X6z<$G!L39=AVi>GDz_5e9v@j%_hOWpiemwZM$vZY41U>^}UKt$SP4{)I zkg5&Du$4&Iw5M!tSyMoXpoj@tOzK^v-1|>rA=XO#ruEiuO;y?7Fz$||y;GSCW*TYp zQ`dSrk@#d-o!+l@S_#Jz@p)~L%s zD>ji>q9IGmpY|zat|{9>{Y)eObJ#!%ZS&W+L^q+F2@jc%XJ(_C(%>1%_N+;(%jqkR zV>^{esoQJwhuzK9?QLllt6&SxteEim=PFN+hvx4&?+35I&$l>XW~P++YqI1VM&_`~ zX(6q}zklC+d0)Qkqo!_8;SPU$cjsiT4cC16?$1M-I=HP~y*%#{6wlL3qGV}h|9nG# zaHOpbQr$f&R9+sgvSpx;I;oRmH1f~-mQuNfqg-yUiZh|1Xz-#0>QNRXG*B9Oc5C-E z!jbgneti=MwzuiO=`RU?p5M+K7_%wuxpAc-*Ur~vWw#19r7n_M<$}472#1BMwosUR z^plsLIq&VS4mNcN-fEveZ{G~AiwUALn5DV5V}(AN_SR-c>h?}=7m=qOH#r_FY&P6I zRx0>=u?p`dg%zS81b?jGEL$|&E|&hhxj4&Z#h4HWnxoD08;`Qp1=>V}REU_nhWr8^ z%zf979xos{Azj7@9$r%K$cY|*{^_sj$DLu+8s|gJc>-awG_K%qBCNWgKp7?KQrs_V z-cOh{lq?k(vmATu`e=!!mZ@Fq#yq_))SA8h+~olK;|Mf|XA)%oj)b=xZR7V?Zc+_n zQsqSeR4^SH&6Z~C`kpj#8gA+@IO@2Sooq7-t|#$Vim_udFi>kPw~_U(?oo>J-F1DC zcTSd~+>BYE1_yrIXd?0@QQFQ%mM)~)t$IG$bJFK9a!LAFYpIf7$UQ~8UDO7hxEgT# zmtB-(JiK&#YHOEMf(MST2f!Hj*+-3;1Ir-bYS)Hlf73uEKld^>)B@7v-+~v@qrKYp zjoK5=F?SusO<&z$Gaf>}tkP#ojpQk)Os2{S{eMGE*{3{p*gR^Z9xis{^~~VUC;1l( zzDag7*5F>FlJx7(`KP*jC#F;PDhDIs#&C#{R)}SR+6#zSX9xON#4bxjmSvjeVEA|- z!)C6kJ@mi`G?7|_O9w2GBkVh@Q+c0S44M!eWO&SD3vZw{Sav9K2N@nnpLlY4g}0Gdw>@Ff@SO7b#PKbvQSV0U%jJM? zg&MW}refq~fi}=!E2UwA)IoODSb)Bg5LEf{k*aUPzNR=^edAGdSMrueH{t%|0yBK9 zu2XV!5w+{dmyS)iD8%sLLEtWoCS_!q%7~-y--!U%9yDm7i9$;%qy@#DJ2eNqO;3fI zRW--6$Wr_S*nk6IQ!+#nz2`X6BASaRgs}0!toU4%_sh@6trnD?t-$W6R6V0@DEv@P z+AdbC`O2i`RhM-o2_)Hu3EOQ*d7Rj8#UWbj#7%}{1l|1whO(EN0K{=rJL=Q8u`X|s zLknq(97=rNSV%k^Xx}`X#AaZjNXU+5$K&w9q+ zsQkX-%)Ez5w#XU_ym_NknXN!D`cDiC4)FH;Pr=Mu(X&RGO& zMvqb!o6+u^PH=nYdi=WR)^1IMM~LhJ$FOmFJz4xwUSt7U!a+Ll+wED~FD3dKFHl1r zsCzJjmBRa>#_BQ$sh9Bu#Ur^ls-IVq7?P$fwCEMhi5?w#+%J0LCL))h-Y*?j8BMXq zi*TwSTD6#~P$%o_60D`q$A#CM!BbY=v)n$he?<47LGh(V-T;0@fM=-)ynP_%P#{(H zJ}>Hu@qLE|>_G_7Ny2tWg^Fb}?^3r6{x=p7nn5tZ+4=!RSYms(=EftIZV=v$EWw!9 z2pxheNF*ae^5(vt>Lr;MY+h}lI1BB=O2K>8X;MAAu$FRn{M-q;_VA4A8#J)EGLIPN zuS{&;V^uj5ptC|q%L_@6eWMnRnQ|FfPZfjju(_oI!Lb5Y**&*a;?wO|J=-d=3^U}R z;AP|U!1P_hG@;T< z?)Qr3AlJn#92&WE&xYJ;Br@~pzH+S{8CMc~b859K#H3|Ji&6983WCu1Qw3M&x89S6$sH7}SOwlfJDc@h$65%XkSR%A)B zD|%o^zt|ohgmkiE>q3d|EZDIL+J}ZKVyM6$Pk$Z5alp1r@rtgE>ZW96mM};yLdLyKQrvlgJ{D8iO5@z zNyN>$aF_zuzAa0v}Wn@suy z<*uv~atpV)nwurL zx+$aup_P{mB5}hD*WMM6WLU0giIFNG^fWRAy5Ef)52}~hk~t4d^%=K*KaWH&`!Ylpt137H<%Rr8BJFH9X?>7Yx7Vdu8$j^m%bx-7W^K?6)SnQ8s-N7^j^7I;9&}06MkcL0%+tRCTwO>%pMFq86 z-mEq33LBiz6=3ZP(%Mf-iH3RNf9|xtO)KNyAmQ~|C8W`_p5`O0zhxlZ4ou6c2I0C7 zebLcw#DjLnqNEj_Ct_A$gIv*rqhPadE|7aEy`b_d@-!)wTeC3mOX~uxT$&*iaT?tG&_>$;P2!fEq46@?tZ^a*3TPZ{LRpdaRLNjn|>NFLbNOA-V# zSTL7I4oGCWTne(#^U#?fv!u)f@2*8S5sZJ#@(QezV>FLIcb%_L5iwY&D&TT|HZ?cz zxU9Rdrk&}>wmm9|4gUmcDBm5j!-sZzF`3!kKn<`^ecw>RV~&0Ch?~cwc1jIbfiO7RxUU1gO%a)LojV+TaMf;E ze`Z*4FP0v}6+V}|c$p2^%%JuX`+M5A^_<6&C{Vk%rdp`_F<8N!9gB9yh~NKYlZU-_ zW3Ak(Kxbjv@`S@AV25!|yKvKxyIshbB;wAEp&iN5ex^B*-8b`IEQ+0X)7R7 zYPbd@s2fK-8jIcS5L*R#*LZnW=wE``#Hi#G*CZ;+M^%A0F~Qm8eHm3P^Jvfe!{Ngn zw$g9pvxd{9Am`ZOGqeyR;VS6eCC%5OHgjhIDenpJ&R!-@>b2@r<22oRu~$ciZc3^T z>@XEPIWn{|en^oWz+_5Ms9jp{8SUY#eQ`2`4Q^2w) zN|~uU7+c=k^!rx}T!Xq&vIZf(QTNB`{c`@Db_?iY*~q|vVj`Y48Ww~m2kklR)X^#P z-D1-DJm{{r;q^?3aags%yAe05vFNrxn(&7OW)HC5HqO#Z6-A{sH>Wyx$h-Rt<(;ad z!&Qra43sVjV~ zIR~J{Gdekp1NX-H;$r0DqWDG9aRvVY-GGz?;sVud>eA1Me%U%m!r#^VyJMvVBq9dn zj5a8hOOUZJn1qm9;7UUyVg(~X*I)I=XH3rHe0J1fdD(DZBO&&yAwt{YCRLaQ)n@|u zI(ibt>7DQQ7wxm zqJUb4ZDE8qoUnV{toHYK#!zZ}90o%DW+9A-u^7C^lmYL3>t#cecU5ey_nV$?r?Ayj zE&j`Yr*#=4)N#I9qJNL|%A`wd|4nZ;P2(6E7TpPBx!xvkB!uh{^?WJWo~CT68Aifk zo3D*ZVe*|O&?*LgSy8XMX4j3Ec=H!A;kOJT#QWL&FkTyoDAwmER!Y*Mx z#mBl8*X=ixiaXIwaD$HDAnFC*`?wHfvmUkyxfnO`!VN+UbGWB6!)cSMxP=V}&qOn& z5T*XIP(VcJWWAjSv5uHNywTgFUL2~v>21UT_?|>YkZaa>b;+|U@#V2`K|AlicFO(&x6SbU(WBAy~Idiujj-czmQBHzAu)OoOpd@bUq8# zd^}8DGplajQUed6h}IvBn9U6Ad78$6`Wk<)C>Nwbn`xK4(QxM#$&JRA*3=pGzCB+4 z%P#q=YEQ*UJ5H*!3v1j9=|XIv6R>%C0x=N%(tz;SRYNYUv4zG&o$5NB&B3HgOz^o{ zoo@I1dv3{oYop_>jazLU%%Ay2Pu5{V6To@ZHC%Rb0X_$Wf^xc z=IE4C3oAmB#gDemXiy7~;{JnCL`_JnEw9hmuN%}nG>@SyACUs^V*1t96=*z)I-jOJ zEDY2OBx#1r=)*X=tI>@_)d`nSo+H8MTNw$IcY<$bPr~>hSBGvgS_Zk5xM|{{9`gwr zETR$pkrXtLG=p>9%&9Rggz9K3mG8+1-@Cp$9w+A1@Xhh$fgfE59gkuCzG)cGXpP;5&k~#pjWoI zn07UiSCmaSCVGiac#b>htrBznLEh~VJbQ80)9yiO&$k}e@aAy$qxnKGz*P2`R|FWn zX34`GI89!bf4St#-qi8@61(gm)4S#R8aMw=yv4CoUtpT$2ai~4h>zqZ(qU-Uy^lzN(Y-yiknk7Kv6=*I)u zfA4_P8#RbF|Dzn=EBQaM3F-|QS?R-hj2M%%15mU>Ftt29`8!JwZ}E>nTBfz3W6Q@Y zC*R5jpQ2j|*_$=fx2M_g7sw;5+-^7+KKRn7vsKN`o{jIhkWG%Lr_gjNTmMQ{BPA)< z>H!azj(3*;C5W{~LV$-dm0y_$O%9OaWK*eeTff3c@cvxSo6c;KymQe%9e-5bk|2fYylhn zFG&kJO-@Y2Od6)z_~0tgxXo)DCHB=Ny{XRax2um~3W-_A<=1AjA|d7*1zpFKgM*Zv zzwJ3&d5IzHo*N-kf}WoicqYdh5uL2T^Oc*))vG80b4tA);`Q0Z$Lk0$!> zf^R?b9q-R=XhR4VGq*e4XLDS=hi4Cq*njDhM}M7K^)y48Hv-3yOgb#KHdzRGqjzb+$l6bUEYximGA$2J*9a>nrq@?Q#X zdCm@!W;?zf9;Q;&L(wYH$r*=~VXI&bEr>@ddfIi$T4TBwYnip=x{0aZNDIk+Y2JBR`$ZY{PuC;Wsg6NXIt7W8+X>VLID zla89Fjczle4suymKLxqd*W6aDqltg><5j=>(R8aTQ%G)%An?;iS|1Cp`_`ZwW`~r3 zJNFd-pynFpf7j;?kbpo*B0}1!X0l=s*M6vz8KasTezEIo-Y!#O{Bp~4g8(|UBu5U> zX_0(_@*bXa*0&S};aQOb|7;bgjWlcaD2Mi3d(w5GXV~S38w%hP+!|Pia*NF~a?mho zDP5VLRr^H;P_{G%PubU~dE&P~64kHbthcmtrKFmC?L%MR?02X4LP_SX$KHvUYF$Bm z($U}Q)B4wTa3cL1X8aa5(0Vcrgii3*jFvb-)OTew6?=zwvSB zHHDp#fSI>@K5o}rYd?E}I*%vrT7=yU;-t=@1K}*3JQs&JL^*Es=|XtvoZ*X2`rhM* zTAOE9Q~2kfhW}XglUd)3 z!I3Qn?urX8GMJ#`ucK+c-aSIi^aKAxpU|%YwY!auHY!j+Uu_G57dTORT%>b*FG-m9 z_j;_)xQ!rLhY*);a$kC$J29B>LYV_Wkv>Th*nCvXc$)f-nvOui5qcC8EaBcAEj6TH zuP)-Da+_2gm=2ev#RSS4%-{<1rFBJ@+kmT`Pz(|?j6<&y2F5u300H>G)DipumMPY2 zRakU?|A9rIaNPJRC@a(KY@aYD)f=y3io*aJz&MBWO$I9f22nQguk|iCY5TQ=&OX^= zxOOrw|0womRn2b=JY@Y^2Qb4pP-be!JZ^Me_dGWV) z_l14uwUbT{{W}AT4}_2lD$;poG6I!TvEP=oDbg`#v$lUz`G9WK!?#_)c1{YLNw6T7 zdNvM-NEk?m|e(T(b1!LSmI*6>)^}ND|GFUV8(% z7m90Ev(vU+bf3m!V1JIH!9f_Qh~Nm!);5yEe8Dhhwc3TuOf(uPA-8vPeZ62N-TJ&; z4}bjh58fQ+y46l-KW*W5rj4b{mck3hOGG;Uj1Zw6pc|#52^rZ9+FNic4d3VTxZCmH zIO+UC{#w(J8qpDt?G@p+94SS|rF=8H zn&3nuRkP5ysCmMWC|o%n>hDgP6aW-)c%pudyZU%2BedKVc-e4aaA|7J6_@e?FvtGj zjgZugB;7g>75@g}QPV_1Ul>p$SJp?Z?=6JMw4~>6ky+5Bv2>nc)Z_nrlv-=_@s6@O ztp8h>e#C&gT9iNMh>km?0!)?=0F9y@%YsNX9P*UozIgOixgQ(QTyavziG6pHWAjs z|5;umDOGL|m;2R71r&X<1c;*-9s8y;_&4Gdjn?& zwpu{Q+E;Y7*=jenJDugkGj8ScR~5~rw>P{;o#!nK5=+>xQcbq56p~Ze`@&}x{%PI! zGuKPM8>brwZqZAEv86Ayx<@9uZD_kPICu51t ztPR#SY~Q8M5j}afC248e!p)1WrvtfY*l$-zCWpM7-n?^ehNrZ+yh9AXbITJ_@t+z= z*G3XrVDFha>oU6IDzD&lz9IauLfP5)Qc+0&^3jjwPGx@(Z5`Qn7AoT{?5;|A;Qrl3 zHHt5aWEs(hAS$b5IwT-G-W^|@qwIKZqktQVC6&BAp3bB|O24KNdKTtTISu?(ll~_S z0g9D1eP}_)|F*y_Y>+dguss}7*orPVAc930N&l>La2#h~P%_A&Q{k4?CUJ|OVabr}DT8ZP9nnn-H~dWF zpn_L*c^~+N{-Pm1kS8)R_EQ(Pq z%enuJhv2=Q=Qk0j8=w@7kq>#XLmDN)E<7Y0^udp9X%hwZI5s&QjGmsID;rorA2pXt zO(udY)6-%)g=Gi|Fc!c{HDHO#Tvm?K8qnQo4a;crWmWLe|M~j8*2v%Y^A*Mcmwl4d z%4K=V&XiWxl#WtPB?v*BDoUI#1U3Rjh};IFT3vYg>@H2fQWOp+cSLF154+)#;r9L4 zCPFS$?JhI6&k%Jzc!n(|I;&xEz|r-cW$6a$k{Jay@%LMIsb%@Hacl`Kroro5f6vSR z96Pq!OfT@CW8WkE=h%&#L8_3zoG;llIj2h->~x~@Tg%!Cb&sftlkdcw3c+KnVz0n< zFDVCCJgSH@>HdUV4X2@)M2?6r`?D0{sxtHil42@o&&8MRE4PU^_b{!=rdk_DJ~Vl5 zQm!-)FcOaq8n0oeit7s--mRB4q-YoKMIlE#vAcRQ@!|7m)cKi(Y<=WF2KW-MLoalu z+htlJCd=c0AO@t(YwZ*(o>)ky47FeC6{to4M|V$|abS|=U2)*i3{fno@wjn&u)YlR ze|@;$#^o`%Grq8%cN5fW0$CvRMX)ECjo?+fglJHnb}vw&~tjTK+0?8Im-~7_*b{E|;hx zxVU$FsIE+1u04DFhx-skm|1%LU;qF_-2V&-|{ukU?xXm!5RPOw#Kpw3xJR*`)=Byev=ED;4QHR-^ySl;=|ot6aJW(u_HDu2UV zs>y>=p3b}3Z;+{GV9MX4P+n-5szL>}>waf*;7E)-$*AO-aIMsR-{MN0lKc_Yqhrvd zm1A25Vai6_gEufaVrxM#uQymbV(HtE(^~955d9rIkAUV;_^Iq>)S{&|=Rvc+Wq$pT zvtrKLN$btmW8878W}un7vH3HrKC4n6JH428eBXJioVCy*GgnDSDuHrCM?w_?no+`D zG$BouR1)Rd5+$xkd(U*CcYd^#QG3-Xd-ztE{1^bP#|!iO%8{%st@=mXgOOh@1|~E z(#>!cuaYtK8M1Rh>bZ{Nhncs|4@LMs6aB+P1^tKo7{lE~12CKqB$@MOQNA`lr>|4H zr({uWaR@5_C&FQ@EQ-37M(}$>k=F>98efu^X+DZVsX@}9=!)VfT@H(Vyj!I$f?ZgG z+*y#SELe4CJsu$)|0qTNRpcUa&1%x-?xDy_S5-H zv0iFO!|);l*gg3n9J53xn(0wPrYKV*OFbmcg)s-$DVPp}dHIAJqWD`T!b3m$xReB< z4I)0u53Tiq2N8!6kCSI3Q|OoJkLZ)=r0YbF5OKz_uL065BYu69X?sFD=#$Q*S0*kC zS7>$ZGrpgJ>a_wcTW9`HeJ8P71ix)Rn`Cn%OZTOXGQMTqk59L`EQ4ps{+^ z>*^T8_L6cc*`u4nPI2C z500%5^&OQ13!H;xClAj~jj)0BxrPq4F^Z_l7|2EZbPPhvHF7;sQN)q$@m0FkvYO^3 z511n%^?qkh$zV^7xd5d_hVTM3<6zVG|>vfehs-8ugH&^R)%pN8tmR3IdT- z(Y%-t>Ec4n4Mpyf9DhQ|eI30}0Y2Y6Z*TYbeq6#|n3C)Z~ucKg;5-2m5NV+JUi@`ncYlx&AEt z_!nQ(e5fs>&J_3&b31BFQ59pXZWW){HnF_^v5%1(mcIgi z*M4Ww1IN`beGv-4uYRwV|G6#R6p!bnGnOH3@72zZ%*fnw1)EtKA7rYNDwWAycZD0F zC22^gyA=?PpXy87yz<8gaeA?8^MmQd0!ZHUka-@;QlX}kS(UbQXNoZ&2RzqOu7bL+ z^vcLR(<)G zr7GC2_|ZKI*CQ_OGnC}XrM@XrZ5M zaO(>uOm63;rFoDq0l>hWtqZMZbOoxwTL8LWuF6f4#2GeR>%HO+9|6|n%8b-O!6AVS zN!sIGgOsl09gVW*lx6AfuKsq{KMf-HkP}G>%{Qe+?`LsN&~Yjkp%J+)%QuF z-|J*~ib`mVJNiP&=v`f`eB2z|3itXwzg;RHGkK>8zaLhCSBJ8BP{^anq*zOkW;yQ2 z(Pktksgr1&(Wt4^H%?f)Cy2j`3B>aIJqAYgRNg(Zwa~uUxwzS1+vl1J-`yYd&Gk&} zAxoz)_~ZS!=DVC}&7g|up`!LK*B&C0bd=OMyCsD#{rrytCrjNyhkyo=rBZ_Q%oZBa zQjsB3z0o1i8vB#=AVAC+G>yvXXV9q`SpTZHiy{yk<5t+IFcJTqfcftt2OzA)*X5xD z0C}L<-_8=8vJ#>io`&a}Uy?U|5}b7?ZH1lf`A|L@WNEll~zXizDspR z1s|3vwa=Pn04E#l7KF{ygHKO|UH-(GJ3(Qgduf;*4TMFHM}imTSv&v{J#e?3biQ}& zYPx;D@pBRt8KO@QBV}>D*7<$$?jd#D<7LeVGoX8aPw1&~q|0UzZ9lxcxX%t@fZ(*; z>m?I>-8+m9!J@@h_xouC<`a1Ey8MiM1RsEp;mNt7-e_*UO0w;J3$RmfxKMxe_8OQ4 z)X5^Wbl7Uw0wJWK`Yfsb0Bzml3_l@=kO7scWR>)BMCAlQxG5cG<(YF3kF@>!5|`K( zddv1z21bAltx%PLn*a3oqEZR@95)C0oooW(oVpM})7V;6ujeyc zp@4At*o932gWXOw0*D>DF;rSVZV^fV(YO9x98|)5bO4ULrSFC$oL+*|j?blGz!CLV z+vAb8Pp)(d#I7puU&J_e^WvAb0YGXZq<1@gf~VZ>PKXap+AsXHD_r8DeZ3fn-k;(N zyg6IveXe8BE+4=nXDmS5<{-7j`qDj?o9lgfi%Uu;o@M3CY$s_NgO2gq5zHNzUrTB> zu-4uXb*}fm5qm?3fJPqvar=tyMQ4Tbr!7N{k8+$+!UJ>onDRW0>#O{h`6P z+D>ortlpDT<1_|*K3AQps`p@|UtGv>?A6dhh7LI51xPDl@V5d;k3PJD=XTSDZ%rPT znMw&VK3w{+%Adl3u}StGSMkbAz|@1C-4t)d&+e$QpMQXeX=L|X8=sUGox}qBpnLHC z#U70DJMbl#Fz6jTQ#~&FiC`SG;L`|1(GX21g`2q<`;p^U^Yi2UM{UDOF+m{DD=*TH z615D{ClT2?xQsj(@p**XQ}hGKiA4HB9i?x*?Ii_JNI+}9XN1=(6n{%2&m9)cc0=Vu z&%FPEcVc(rZwc8CU4H4tmdH(oRq63j&%JKy1)OU9uWvt4I(XN42?M)Q(?wWBPhSUX z)@~CK_uhDpCG3}gE~7_`UhksfitoJ2DUYm}@H8@hpG}ny0?A~)S?jq*arig96B<)5 zNYC|U=%e0?$60S4wvo&gDLRw^#QO^dNNk87&Z5 z-A=V-jMe2;ndC;t*oM++uFjB?>|Lub#cc&0+xOXda^s^B`T1L26FSd*3wjMqK()M6 zJ1kiPF^bTv-c5&h;xcuZuVLfA4fGiD0}w9}uiv~U<7X6Ob57ZhMhXI^ zJ4Q&-iCjeq>ckKt>XAiyeC}URFMub9oSdznCAc$glvkF8$!@XTQ;)K!jSyPKrcf%o z=?5!@pUWuQnG;7(v!v&m?*^#F5dSpbiM9pY_{E*ye|7{P36{?+kX~zs`#)4&x}(*( zl^;_Q1o+MrdcRZGwlDls|2xK#&Uv1m|2HpX;{&x>ZXjiw??|EL(>^CRkbl-EguB;h zNym5H5gA~ofBIZ<3ANA=-pn8vd8vAzHA=q6A-=W{c$AT)Yn5`&e!;f5YvXu&rt4`97@_>pN9h0Qbs?5x6q9>nwL$7VdZ3MS5 zl|ND3(GxAKU*KEl?q4rRpwj!E(+_+?e}*c5oO}~}D?Jr#+_>-ha494ak%;JXbzNd|&S7Ey;Bw$t8|IKPCX| zd{E^+(7OEav^s73=nZL$5p5mb=$kAl#1te580}uj>mc#onerKAp03sVBx-~AXbiO#q8xKszQo@6NM)UZ9ri59X!yTrOtVE*=_FA;L_We z?+D_M&?FUd!{s<|LarA?NE`!`VYz)Tkyo24cm)lvuod(Ih^pegBRI?J#Me z36@}JlfMOaCaS!2MbR>q4}PjUx(B?*JN@j8n85t#1NzB{;G=X9?V@h9LMLMmTA8oF zeNTp75{JX3J+?m%VXk9BsPQf;`WhCuus%&m9C$Am@3$#QAa9YmsJ^nX4)?t`WHp>* zdI!5Xros1O3bqb;td#)c#&;L@u7!0U%1-;)O3+qsforTb%=aIt@!p$3HYe1m z-LB3G1bQ*N@j*+YzX2Fco>=qSp2Me)_&-MfQZe_bkBw$9-r3`(uB!@uAbz~rW|8i2 zB8(Fd=(>r=&lu5qAm0OsD!r$Piz-!eIpsI;HLswu#37q&D9e8DTsSb3-$B&Snds5R z_HGo2mi49=m(=@@Q`|u~(2I6CqV-smlRS?#vi!Os;fysh`4p7DzXE%~DeXg6i9){m z!Fe#|V(fE9YshorH2ZFT>eZ^xuzQYD9H-7gK;Qubcu(^g->*`RNS@SCy~~Sp(6p5A zDoR5Z=eup6(~EN+nvG6-!P`Hwb#32uPn+*aUc*Ng)ca3axbOYeCELyn`F1Hm#Ebv^v8*&|-#3IF z#8)6Hc92d*Ygc=oumte)T{Tz=VkHdv-(EZ9&4m@O`%|FS@jstb(mAyjEd*4F57?4E zaZX+r4n*HRDFwjhdMd06K z=J5c%RPYb^M&htyz<39w)2=`rNft?lw+{&i17E7U=Sx}hWuiVD%>$g5uHtcNZrHF$ z<0-Ys?P9jf!WmUHhn}O6QYNK7f}**eT0?!DZa<}zpG~9`Y}Hs7nhe&+xA6WFaS#OuiJP;4YSHR+gNzxe2pZ&_8-x?Q?qD& zU({Hkg(Pl=6rc*vL7T33Ly_MNzpgu0*ZU9&gws;Suvlo5V5oQ**k1*+o(d?>Pv! zLa#%iuUZ6iS7S~O%>q1_VeaaeKfjv>HdYn});Kr`t8x8%7Ex{HG;2*<8z|V8jV00T z-xj#gIb(pl`=SQ>Pa3B7iG<*6K<}{#u1!biiz#Lz!1&9j_NU_i+PU(0sMh~KXDr!` z?7~#Sr9zhKqM0mlldZZgB_vCWJqej{C?##f9XiqCri)6nSh9{mHzjgQ-H{TLib4&N zZJ6J44x{CFf8SUA?(6>Xd%b>#;W?l4S>Mm+`J6K|&-1WCc4%6^-;p-Xs8uD6RZ{)}FYmvn&4)HRX{bV8f!J#36u)f4Kj;v`1&n)dDV zQPmQvKj6MqU;_g4`gTc%tVNUFMdf*a3RA!BKbXYxL*Ud9mKfmxnwi)AbJ4gj2nfRn`yozisx_5%=dY?fnHD z5KGQZSB1E>yX81#K5>^eh%oj<C$kRFiL4Lc6`o?TQ7SZXYP1X9b!z4L@^z=1=>@k{3abksVbSKexk?=H z?v(@Hy(-WU?*^b=%bKlIj&NEitMG7OEc5E4vk94Rdu2Ekcn+KwL1gDn0E^=$ z4|tE{;xqdvbZf5;42z6r{J_=iU=d=^szY9~2LWBIR)fpfgeO}mN~^PbtA)7*IPQ{m zv#4WNZ9Ao#WZmB0uektBFto%1+E+xK!3=x9nYdhILK8TH@oz1rGajaPf;Gj6jO?kBErW=}D*AFT% z)Z@v+J`nH7yNCA5>RCR~^I)nVV`?mjtj=j3W!RYcMIAozDu3D)-jVl~VXZ zM%Iz!9n-r%E#&USGwBR~vpBT3&l^+O3rtVm{5T!8M!As@rlKG9yU$j5>g2n7n9!Jr z7cH(sKCU{q!VuF*y3Nw)bh4}K7^FJvZQu~p?%7VetJmS`n=2vx;CdrvlGaZgClj-= ze&Bteu9{|S^qS{H6@&*Tc%!gjCp2oTcF#T?Y!2X++4NqF=@p^vkLj~d=W#dyU#k7+ zmi9yp0mF^2;h0g4&VVdR$-7$2v2>jwIC`2?@IK%g=9_;5m#jV|!X4`+dda>TqIkuh zMezgDA2_zm_hOuAMt3#LXLWFj6&$P}=~hd{%DkF1sNBZo+u;r4X>nwo zrip;}7)pLQjpUa?XpX$9Djw!LNc@PWF*C<6a$?)Y_>xZ12W>lhGdn(pv8fa%3I-3{ zm^zkQ#YBUt%zPjH9_xs7L*B2sWc+}3b~N$$z8nn3)G?&0R)aIFOm#>d`7>wx3^?$; zqvjyv8hQho`QB9buK@`HjF=R^;=7X=m4by_-ZsGZrmpf1=sMVLD1)J0$&c7se-KUl ztKBgSEQ>&J(j%6%H~@huBe!CP&Azf$Be`QFh5baOZ$_QbkS>kM>i$rHH}{G;t5avS zXNi$tj%Sa|s1;H9+@<{cGl7Nce?Sd1KX#ms0Jcxhd~py%FP))X&iBI@u+4PbCPsG| zpZqf_?E#&86_det&uK)LwmOzof5bg(x1uznBT*@~R=GiYZI$jAn$us8k3^M9(goq$x{PN)ZCcd`e{WKmYgkgWA#+0?HDMW9ELhny_iXU7qc95@8HNt#R=7^lG|trfqUFW zaabkF;!=bBFu*wrO!t-+)3K0i6MI_Oe>q|%#fe!yiSB0Un3t5pC)9%begCNdY+e6v zoA{3w;F%~wdomhR-cVefrG@v_AlZ z+Z&kqXB$&NnOr`8eUzX!F{9Q9_IqwaRsg_e>ImH2Yq-%rr}1e|{R^u-eKS5Zrbf@3 zbOUHpb0nU%-L+3oHw?KzJPIm%^R&N48(#-~@EKTO`Z3)wG(g+P&%dGacJWAKx8p=qrrgXVLF+ZUP7 zO|x5-Uu9-wR`D^=Q{l%a@k0$g38aq;?N*Cxq}`u8UbZjhl=BM#*00?*R+iG8Z_KNz zPd|yu-O6K&i0vQ_B?MbuTjt{#_**Aq`;r}3@{cc$V&>gDwTD83YuDT#UvIok$Tj2K z=sPl{&~q_#)h1B<&+{^2$wP6kCv7&tzZCM;7fP8oJnB1S+I3xj?eIAnMsDE3yq3gyJNL4mw609k zacD@85~kWoDP3TTK6*uCL!oiW~>?8+kkd9J*;Decc?fv?i!sG;Kni ztps+^bG%syLGvNlWqnAS0U}| zsET;6No(~)5K838t9Kv9DBh7F*;;0yo|}vugsWmLnZCd17M|5Qy(iYl@vwC5Pv`UF zcixzj`D~y$v$f%g*cRtb(Hw)=47mkA%i2+YS*=5nt`pWMi-5C5c9btIjxI2ay7q)N z*Z#M{NpVJ9iwH zxn4jCr35>0e7h_R+e|h3c2~GjUwJKrY7%d0xgNQIbA744CB+PGu-zbUJi6HKm_BmY z=8?=mS*=4-u4=RS76QefPgni)jt{}(W%c;-r(Q?>E%RJ+Nk>v_i8h2O4hv(%jYfuNNT(5ssSvwN0bIr-KjI8HN+a#wftrk_%;$l45V{XNF-ys+OS zyTQ}>2Vu>hxBgi;u%q$BlKpwyOvUk+30I6uOt?wvweeGf`*5doludTh4vp3K4YQ{% z!MlEUV5Q-8Z&-#sa@+6LCj9K-t^>Yrn2AZ6hi(`xC#dDA{#4}n(p{OECtbJzjuiPx z-M!38dbKM>XB8}TGP(z$3f)hfAU?~4TZ%M`K$iG6W%_&-MMPH=(#2=!&^vV$ks!3) zZ-}IeLKYAWc`6E7La~Ut7~pQVLbi!P+D4ytF~s5IKj{RmADnQw(9k{l;ek7S{lcgJ zVVfKx*TjL^FfYVH95Te5!-s4|Pn3`kz&q71H!%2IXOK5S6Ni=|QWB5~zTanB#!><@ z#`pM6pCp4Th`$K9{Mrwr(6@+*AsG@7VOmIjJ4S_8A}JC84HOwXVaK#ASk143t>i}v zBp?O6)J{6fRRehgWU*Dgh?5+kx`)x($?C{KIY=JSp9`dIBk9XB79l@M0xuk*&^F!C zTMRiX31ZwBja}=P1W|oj>WWU@`TW?l52z#}XQd!HRdhL>Bj{ge>94ucV9ao@6eO>T zE*~=ildmlR;$P}on1FGaN&_x*xl|s|6)gKT*U2P|D+%R7R|iQ5<8To1Yp%Ex7*{Lc z5=0loAOq3>fP1MJRht0G3t_YA5ev}7KRtz!_ky+{IyW4l5dib)GZ^&`l#0$|M4qEm z*DOFKBJwhTiq2+4^ke{aDhE&(A-lj7C=^)1H4C>0bPFrRxd?uH0P6 z1phW4YlnaiLFZ7Z;5h~K>NLGs5f!}CHB66F`b;)pedlr=5cQCyvY@ZrZ(u5@vY;Qm z3$Zo}ZEr8a+RNmCYA_c|1s_z5l*mD=@jjKvs2rq)yp#t-A?8U1h^X~9v$Mcw++Pk# z%a;g49>}Sqa&jLLQ*fd>`*HYxW0&XB?-wZ`$_kLKzzQh{u~C2)YRx`lfm=P0`0O}9 zfUr@wcc)(@;-mm_JXZnO(VL6ZDL|U4vyTCw$HCsCpB>_|h@c|0aLsJ_2M-Hhs@|jk n;e11UoOg$WhU@!;?Dj+F{5!7`0;+Jh72wAnXoQr(tpoR83}cU# delta 18802 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 W!Um?m<_GbE8sK%Fj0*31K>rJTXicjC From 3a14d2093725e3633a96944dd3e83f1799d10939 Mon Sep 17 00:00:00 2001 From: thant Date: Thu, 30 Mar 2023 13:31:07 +0800 Subject: [PATCH 063/152] Refactored process Command to use case-switch instead of multiple else-ifs. Also cleaned up other errors and minor tweaks --- src/main/java/seedu/duck/Parser.java | 218 +++++++++++++++---------- src/main/java/seedu/duck/Storage.java | 4 + src/main/java/seedu/duck/TaskList.java | 10 +- src/main/java/seedu/duck/Ui.java | 19 ++- 4 files changed, 159 insertions(+), 92 deletions(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 8e5f9275da..32dd761fa8 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -39,97 +39,145 @@ public static boolean isNumeric(String word) { * @param line The line of user input * @param in The input from scanner */ - static void processCommand(ArrayList tasks, PriorityQueue classes, String line, Scanner in) - throws IOException { - while (!line.trim().equals("bye")) { // Exits the program if input is "bye" + static void processCommand(ArrayList tasks, PriorityQueue classes, String line, Scanner in) throws IOException { + while (!line.trim().equals("bye")) { String[] words = line.split(" "); line = line.trim(); if (line.isBlank()) { Ui.emptyCommandMessage(); - } else if (line.equals("list")) { - // List out all the tasks added - Ui.list(tasks); - } else if (line.equals("list today")) { - //list out all classes and tasks today - Ui.listToday(tasks, classes); - } else if (line.equals("priority_list")){ - // Lists out all the tasks by priority - Ui.printPriorityList(tasks); - } else if (line.equals("low_priority")){ - // Lists out all the tasks that are low in priority - Ui.printLowPriority(tasks); - } else if (line.equals("medium_priority")){ - // Lists out all the tasks that are medium in priority - Ui.printMediumPriority(tasks); - } else if (line.equals("high_priority")){ - // Lists out all the tasks that are high in priority - Ui.printHighPriority(tasks); - } else if (line.equals("list classes")) { - Ui.listClasses(classes); - } else if (line.equals("help")) { - // List out all the tasks added - Ui.help(); - } else if (line.equals("refresh")) { - // Refresh the task list and class schedule - TaskList.refresh(tasks, classes); - } else if (words[0].equals("list") && (words.length == 2) && (isNumeric(words[1]))) { - //list out all tasks in x days in the future specified by the user - Ui.printUpcomingTasks(tasks, words[1]); - } else if (line.equals("upcoming class")) { - Ui.displayNextUpcomingClass(classes); - } else if (words[0].equals("unmark") && (words.length == 2) && (isNumeric(words[1]))) { - // Mark a task as not done - TaskList.unmarkTask(tasks, words); - Storage.trySave(tasks, classes); - } else if (words[0].equals("mark") && (words.length == 2) && (isNumeric(words[1]))) { - // Mark a task as done - TaskList.markTask(tasks, words); - Storage.trySave(tasks, classes); - } else if (words[0].equals("delete") && (words.length == 2) && (isNumeric(words[1]))) { - // Delete a task - TaskList.deleteTask(tasks, words); - Storage.trySave(tasks, classes); - } else if (words[0].equals("remove") && words[1].equals("class")) { - // Remove a class from class list - TaskList.tryDeleteClass(classes, line); - Storage.trySave(tasks, classes); - } else if (words[0].equals("find") && (words.length > 1)) { - // Find tasks that contain a keyword - Ui.find(tasks, words); - } else if (words[0].equals("purge")){ - // Find tasks that contain a keyword - TaskList.purge(tasks, classes); - } else if (words[0].equals("priority") && (words.length == 3)) { - // Find tasks that contain a keyword - TaskList.setPriority(tasks,words); - Storage.trySave(tasks, classes); - } else if (words[0].equals("add_note") && (words.length == 2) && (isNumeric(words[1]))){ - TaskList.addNote(tasks,words); - } else if (words[0].equals("delete_note") && (words.length == 3)){ - TaskList.deleteNote(tasks, words); - }else if (words[0].equals("notes") && (words.length == 2) && (isNumeric(words[1]))){ - Ui.printNotes(tasks,words); - }else if (words[0].equals("clear")) { - if (Ui.doubleCheck()) { - // Find tasks that contain a keyword - tasks.clear(); - Task.clearCount(); - classes.clear(); - Ui.borderLine(); - System.out.println("\t Got it, all tasks have been cleared."); - Ui.borderLine(); - Storage.clearTask(); - } else { - Ui.borderLine(); - System.out.println("\t Quack! Process cancelled."); - Ui.borderLine(); - } } else { - // Adding a task to the list - TaskList.addTask(line, tasks, classes); - Storage.trySave(tasks, classes); + switch (words[0]) { + case "list": + if (words.length == 1) { + Ui.list(tasks); + } else if (words.length == 2 && isNumeric(words[1])) { + Ui.printUpcomingTasks(tasks, words[1]); + } else { + Ui.unknownCommandMessage(); + } + break; + case "list_today": + Ui.listToday(tasks, classes); + break; + case "priority_list": + Ui.printPriorityList(tasks); + break; + case "low_priority": + Ui.printLowPriority(tasks); + break; + case "medium_priority": + Ui.printMediumPriority(tasks); + break; + case "high_priority": + Ui.printHighPriority(tasks); + break; + case "list_classes": + Ui.listClasses(classes); + break; + case "help": + Ui.help(); + break; + case "refresh": + TaskList.refresh(tasks, classes); + break; + case "upcoming_class": + Ui.displayNextUpcomingClass(classes); + break; + case "unmark": + if (words.length == 2 && isNumeric(words[1])) { + TaskList.unmarkTask(tasks, words); + Storage.trySave(tasks, classes); + } else { + Ui.unknownCommandMessage(); + } + break; + case "mark": + if (words.length == 2 && isNumeric(words[1])) { + TaskList.markTask(tasks, words); + Storage.trySave(tasks, classes); + } else { + Ui.unknownCommandMessage(); + } + break; + case "delete": + if (words.length == 2 && isNumeric(words[1])) { + TaskList.deleteTask(tasks, words); + Storage.trySave(tasks, classes); + } else { + Ui.unknownCommandMessage(); + } + break; + case "remove": + if (words.length == 2 && words[1].equals("class")) { + TaskList.tryDeleteClass(classes, line); + Storage.trySave(tasks, classes); + } else { + Ui.unknownCommandMessage(); + } + break; + case "find": + if (words.length > 1) { + Ui.find(tasks, words); + } else { + Ui.unknownCommandMessage(); + } + break; + case "purge": + TaskList.purge(tasks, classes); + break; + case "priority": + if (words.length == 3) { + TaskList.setPriority(tasks, words); + Storage.trySave(tasks, classes); + } else { + Ui.unknownCommandMessage(); + } + break; + case "add_note": + if (words.length == 2 && isNumeric(words[1])) { + TaskList.addNote(tasks, words); + } else { + Ui.unknownCommandMessage(); + } + break; + case "delete_note": + if (words.length == 3) { + TaskList.deleteNote(tasks, words); + } else { + Ui.unknownCommandMessage(); + } + break; + case "notes": + if (words.length == 2 && isNumeric(words[1])) { + Ui.printNotes(tasks, words); + } else { + Ui.unknownCommandMessage(); + } + break; + case "clear": + if (Ui.doubleCheck()) { + // Find tasks that contain a keyword + tasks.clear(); + Task.clearCount(); + classes.clear(); + Ui.borderLine(); + System.out.println("\t Got it, all tasks have been cleared."); + Ui.borderLine(); + Storage.clearTask(); + break; + } else { + Ui.borderLine(); + System.out.println("\t Quack! Process cancelled."); + Ui.borderLine(); + break; + } + default: + TaskList.addTask(line, tasks, classes); + Storage.trySave(tasks, classes); + + } + line = in.nextLine(); } - line = in.nextLine(); } } diff --git a/src/main/java/seedu/duck/Storage.java b/src/main/java/seedu/duck/Storage.java index 94d4083bed..01c00d230f 100644 --- a/src/main/java/seedu/duck/Storage.java +++ b/src/main/java/seedu/duck/Storage.java @@ -50,6 +50,10 @@ static void loadTask(String line, ArrayList tasks, PriorityQueue tasks) throws IllegalTodoExcept Ui.addedTaskMessage(currTodo); } } - + /** + * Sets a priority to the specified task + * + * @param words The input variable from the user, consisting of an index and a priority (from 1 to 3) + * @param tasks The array list of tasks + */ static void setPriority(ArrayList tasks, String[] words) { int taskNumber = Integer.parseInt(words[1]); int taskCount = Task.getTaskCount(); @@ -219,6 +224,8 @@ static void addSchoolClass(String line, PriorityQueue classes) thro * @param line The line of input from the user * @param tasks The array list of tasks */ + + static void addDeadline(String line, ArrayList tasks) throws IllegalDeadlineException, expiredDateException { String description = line.substring(0, line.indexOf("/by")).trim(); String deadlineString = line.substring(line.indexOf("/by") + 3).trim(); @@ -236,6 +243,7 @@ static void addDeadline(String line, ArrayList tasks) throws IllegalDeadli } } + /** * adds a recurringDeadline to the list * diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 5548c85fcf..7f78121fcf 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -447,7 +447,7 @@ static boolean doubleCheck() { static void help() { borderLine(); - System.out.println("\t (`・v・´ ): Here are the commands you can give me:"); + System.out.println("\t Quack! Here are the commands you can give me:"); System.out.println("\t - list: I'll list out all the tasks you have recorded."); System.out.println("\t - list : I'll list out all the tasks in that number of days."); System.out.println("\t - list classes: I'll list out the classes you have on your schedule."); @@ -472,6 +472,7 @@ static void help() { System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); System.out.println("\t - priority <1/2/3>: I'll set the priority of a given task as"); System.out.println("\t 1:Low, 2:Medium and 3:High."); + System.out.println("\t Default: LOW priority."); System.out.println("\t - bye: I will shut down my program.\n"); System.out.println("\t Here are the following ways to input tasks/classes:"); System.out.println("\t Deadlines: /by "); @@ -487,7 +488,7 @@ static void help() { System.out.println("\t Classes : /class /day " + "/from /to \n"); System.out.println("\t (eg. Bring laptop /class CS2113 /day TUESDAY /from 1100 /to 1200)"); - System.out.println("\t (`・v・´ ): How else may I assist you today, human?"); + System.out.println("\t How else may I assist you today, human?"); borderLine(); } @@ -543,6 +544,12 @@ static void todoErrorMessage() { borderLine(); } + static void unknownCommandMessage() { + borderLine(); + System.out.println("\t Error. Please check that the command has been entered correctly."); + borderLine(); + } + static void expiredErrorMessage() { borderLine(); System.out.println("\t Quack! I know humans wish to undo their past mistakes, " + @@ -610,12 +617,12 @@ static void greetingMessage() { printDuck(); borderLine(); borderLine(); - System.out.println("\t (`・v・´ ): Quack. Nice to meet you human. As you can see, I'm a Duck."); - System.out.println("\t (´˘v˘´ ): As a Duck, I can only understand simple commands. Quack. " + + System.out.println("\t Quack! Nice to meet you human. As you can see, I'm a Duck."); + System.out.println("\t As a Duck, I can only understand simple commands. Quack. " + "Human speech is so confusing!"); - System.out.println("\t (´˘v˘´ ): That being said, I am a smart Duck. " + + System.out.println("\t That being said, I am a smart Duck. " + "If you wish to know what I understand, just enter 'help'."); - System.out.println("\t (`・v・´ ): How may I assist you today, human?"); + System.out.println("\t How may I assist you today, human?"); } static void printNotes(ArrayList tasks, String []words) { int index = Integer.parseInt(words[1]); From 4eb3030f7bbd11d64de9541f6cf2460e3c6a1d73 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Thu, 30 Mar 2023 14:43:41 +0800 Subject: [PATCH 064/152] Tied refreshing the schedule to the list_classes function, and removed the ability to explicitly use the refresh command. Fixed some errors in the help list. --- src/main/java/seedu/duck/Parser.java | 7 ++----- src/main/java/seedu/duck/TaskList.java | 1 - src/main/java/seedu/duck/Ui.java | 13 +++++++------ 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 32dd761fa8..cd518ef6c7 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -72,14 +72,11 @@ static void processCommand(ArrayList tasks, PriorityQueue cla Ui.printHighPriority(tasks); break; case "list_classes": - Ui.listClasses(classes); + Ui.listClasses(classes, tasks); break; case "help": Ui.help(); break; - case "refresh": - TaskList.refresh(tasks, classes); - break; case "upcoming_class": Ui.displayNextUpcomingClass(classes); break; @@ -108,7 +105,7 @@ static void processCommand(ArrayList tasks, PriorityQueue cla } break; case "remove": - if (words.length == 2 && words[1].equals("class")) { + if (words[1].equals("class")) { TaskList.tryDeleteClass(classes, line); Storage.trySave(tasks, classes); } else { diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 4f03e46d68..4f406f3253 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -420,7 +420,6 @@ static void refresh(ArrayList tasks, PriorityQueue classes) { Task.clearCount(); classes.clear(); Storage.tryLoad(tasks, classes); - Ui.refreshedMessage(); } static void purge(ArrayList tasks, PriorityQueue classes) { diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 7f78121fcf..f88614e500 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -57,7 +57,8 @@ static void list(ArrayList tasks) { borderLine(); } - static void listClasses(PriorityQueue classes) { + static void listClasses(PriorityQueue classes, ArrayList tasks) { + TaskList.refresh(tasks, classes); Iterator iterator = classes.iterator(); borderLine(); System.out.println("\t Here is your class schedule:\n"); @@ -452,7 +453,6 @@ static void help() { System.out.println("\t - list : I'll list out all the tasks in that number of days."); System.out.println("\t - list classes: I'll list out the classes you have on your schedule."); System.out.println("\t - list today: I'll list out all the classes, deadlines and events you have today."); - System.out.println("\t - refresh: I'll refresh your task list and class schedule."); System.out.println("\t - priority_list: " + "I'll list out all the tasks you have recorded arranged by their priority."); System.out.println("\t - low_priority: I'll list out all the tasks you have that are low in priority."); @@ -464,10 +464,11 @@ static void help() { System.out.println("\t - delete : I'll delete that task from your list."); System.out.println("\t - remove class /class /description " + "/day /from /to "); + System.out.println("\t (/description can be followed by whitespace if the class has no description."); + System.out.println("\t : I'll remove this class from your class schedule."); System.out.println("\t - add_note : I'll add an additional note to that task!" ); System.out.println("\t - delete_note : I'll delete additional note to that task!" ); System.out.println("\t - notes : I'll print the additional notes for that task!" ); - System.out.println("\t : I'll remove this class from your class schedule."); System.out.println("\t - purge: I'll delete all expired tasks from your list after a confirmation."); System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); System.out.println("\t - priority <1/2/3>: I'll set the priority of a given task as"); @@ -485,9 +486,9 @@ static void help() { System.out.println("\t (eg. /re Meeting /from 2015 /to 2215 /day MONDAY)"); System.out.println("\t Todo : "); System.out.println("\t (eg. Water the plants)"); - System.out.println("\t Classes : /class /day " + - "/from /to \n"); - System.out.println("\t (eg. Bring laptop /class CS2113 /day TUESDAY /from 1100 /to 1200)"); + System.out.println("\t Classes : /class /day " + + "/from /to "); + System.out.println("\t (eg. Bring laptop /class CS2113 /day TUESDAY /from 1100 /to 1200) \n"); System.out.println("\t How else may I assist you today, human?"); borderLine(); } From b07b06a63ae74d5a5ff2f2d2785eb2e2d05cc663 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Thu, 30 Mar 2023 16:03:14 +0800 Subject: [PATCH 065/152] changed the format to invoke remove class function --- src/main/java/seedu/duck/Parser.java | 2 +- src/main/java/seedu/duck/Ui.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index cd518ef6c7..e55cd3bd96 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -105,7 +105,7 @@ static void processCommand(ArrayList tasks, PriorityQueue cla } break; case "remove": - if (words[1].equals("class")) { + if (words[1].equals("/class")) { TaskList.tryDeleteClass(classes, line); Storage.trySave(tasks, classes); } else { diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index f88614e500..1a28881358 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -462,7 +462,7 @@ static void help() { System.out.println("\t - mark : I'll mark that task as done."); System.out.println("\t - unmark : I'll mark that task as undone."); System.out.println("\t - delete : I'll delete that task from your list."); - System.out.println("\t - remove class /class /description " + + System.out.println("\t - remove /class /description " + "/day /from /to "); System.out.println("\t (/description can be followed by whitespace if the class has no description."); System.out.println("\t : I'll remove this class from your class schedule."); From 87011a1234e64fddc2f4de501f4cc6d02b0c6719 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Thu, 30 Mar 2023 16:05:11 +0800 Subject: [PATCH 066/152] Update UserGuide.md --- docs/UserGuide.md | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 1857e67dc9..8cec6f5365 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -13,12 +13,11 @@ Duck is a **desktop app for managing tasks and deadlines, optimised for use via * [Mark a specified task as done :](#marking-a-task--mark-task_number) `mark ` * [Unmark a specified task as not done :](#unmarking-a-task--unmark-task_number) `unmark ` * [Deleting a task :](#deleting-a-task--delete) `delete ` - * [Deleting a school class :](#deleting-a-school-class--remove-class) `remove class /class /description /day /from /to ` + * [Deleting a school class :](#deleting-a-school-class--remove-class) `remove /class /description /day /from /to ` * [Designate a priority to a given task :](#designate-a-task-priority--priority-task_number-priority) * `priority ` * [List tasks of low/medium/high priority :](#listing-all-low-priority-tasks--low_priority) `low_priority`/`medium_priority`/`high_priority` * [List tasks in priority order:](#listing-all-tasks-arranged-by-priority--priority_list) `priority_list` - * [Refresh task list and class schedule:](#refreshing-task-list-and-class-schedule--refresh) `refresh` * [Purge expired tasks :](#purge-expired-tasks--purge) `purge` * [Clearing all tasks (including datafile) :](#clearing-tasks-from-storage-clear) `clear ` * [Find tasks matching a given keyword :](#finding-tasks-from-storage-that-match-a-keyword-find-keyword) `find ` @@ -267,7 +266,7 @@ You now have 3 tasks in your list. Removes a school class from the schedule. -**Input:** `remove class /class /description /day /from /to ` +**Input:** `remove /class /description /day /from /to ` **Output: Demonstrated with input `remove class /class CS2113 /description /day THURSDAY /from 1100 /to 1200`** @@ -300,18 +299,6 @@ Understood. The task's new priority is: ``` -## **Refreshing task list and class schedule : `refresh`** - -Clears the task list and class schedule, and reloads them from the savedata. This function is mainly used to update class sorting and tracking. - -**Output:** - - -``` -Your task list and class schedule have been refreshed! -``` - - ## **Purge Expired Tasks : `purge`** From 11164a0c347c2c5e3a6bc1589b656e283896c348 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Thu, 30 Mar 2023 16:06:56 +0800 Subject: [PATCH 067/152] fixed bug for removing classes --- src/main/java/seedu/duck/Parser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index e55cd3bd96..be70f29ec0 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -105,7 +105,7 @@ static void processCommand(ArrayList tasks, PriorityQueue cla } break; case "remove": - if (words[1].equals("/class")) { + if (words.length > 1 && words[1].equals("/class")) { TaskList.tryDeleteClass(classes, line); Storage.trySave(tasks, classes); } else { From 321900ec1d3754ab4668c760ea65b76b91469936 Mon Sep 17 00:00:00 2001 From: sunkyan Date: Thu, 30 Mar 2023 16:13:15 +0800 Subject: [PATCH 068/152] added funtion to edit stored tasks --- src/main/java/seedu/duck/Parser.java | 8 + src/main/java/seedu/duck/TaskList.java | 163 +++++++++++++++++- src/main/java/seedu/duck/Ui.java | 49 +++++- .../exception/EmptyDescriptionException.java | 4 + .../seedu/duck/task/RecurringDeadline.java | 4 + .../java/seedu/duck/task/RecurringEvent.java | 4 + 6 files changed, 224 insertions(+), 8 deletions(-) create mode 100644 src/main/java/seedu/duck/exception/EmptyDescriptionException.java diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 32dd761fa8..dd13b2c3be 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -115,6 +115,14 @@ static void processCommand(ArrayList tasks, PriorityQueue cla Ui.unknownCommandMessage(); } break; + case "edit": + if (words.length == 2 && isNumeric(words[1])) { + TaskList.tryEditTask(tasks, words); + Storage.trySave(tasks, classes); + } else { + Ui.unknownCommandMessage(); + } + break; case "find": if (words.length > 1) { Ui.find(tasks, words); diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 4f03e46d68..f0c7eecfc1 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -1,11 +1,6 @@ package seedu.duck; -import seedu.duck.exception.expiredDateException; -import seedu.duck.exception.IllegalSchoolClassException; -import seedu.duck.exception.IllegalEventException; -import seedu.duck.exception.IllegalDeadlineException; -import seedu.duck.exception.IllegalTodoException; -import seedu.duck.exception.startAfterEndException; +import seedu.duck.exception.*; import seedu.duck.task.*; import java.text.ParseException; @@ -310,6 +305,162 @@ static void unmarkTask(ArrayList tasks, String[] words) { } } + /** + * edits the attributes of a specific task + * @param tasks + * @param words + */ + static void editTask(ArrayList tasks, String[] words) throws expiredDateException, + startAfterEndException, EmptyDescriptionException { + int taskNumber = Integer.parseInt(words[1]); + int taskCount = Task.getTaskCount(); + DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("HHmm"); + DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); + if (taskNumber > taskCount) { + Ui.exceedTaskNumberMessage(taskNumber); + return; + } + Task taskToEdit = tasks.get(taskNumber - 1); + if (taskToEdit instanceof Todo) { + Ui.editTodoMessage(); + String editLine = Ui.askForEditMessage().trim(); + if (editLine.isBlank()) { + throw new EmptyDescriptionException(); + } + taskToEdit.setDescription(editLine); + } else if (taskToEdit instanceof Deadline) { + Ui.editDeadlineMessage(); + String editLine = Ui.askForEditMessage().trim(); + String[] editWords = editLine.split(" "); + if (taskToEdit instanceof RecurringDeadline) { + if (editWords.length > 1 && editWords[0].equals("/description")) { + String newDescription = editLine.substring(12).trim(); + if (newDescription.isBlank()) { + throw new EmptyDescriptionException(); + } + taskToEdit.setDescription(newDescription); + } else if (editWords.length > 1 && editWords[0].equals("/deadline")){ + String deadline = editLine.substring(9).trim(); + LocalTime.parse(deadline, timeFormat); + ((RecurringDeadline) taskToEdit).setDeadline(deadline); + } else if (editWords.length > 1 && editWords[0].equals("/day")) { + DayOfWeek day = DayOfWeek.valueOf(editLine.substring(4).trim()); + ((RecurringDeadline) taskToEdit).setDay(day); + } else { + Ui.unknownCommandMessage(); + } + } else { + if (editWords.length > 1 && editWords[0].equals("/description")) { + String newDescription = editLine.substring(editLine.indexOf(words[1])); + if (newDescription.isBlank()) { + throw new EmptyDescriptionException(); + } + taskToEdit.setDescription(newDescription); + } else if (editWords.length > 1 && editWords[0].equals("/deadline")) { + String deadlineString = editLine.substring(9).trim(); + System.out.println(deadlineString); + LocalDateTime deadline = LocalDateTime.parse(deadlineString, dateFormat); + if (deadline.isBefore(LocalDateTime.now())){ + throw new expiredDateException(); + } else { + ((Deadline) taskToEdit).setDeadline(deadlineString); + } + } else { + Ui.unknownCommandMessage(); + } + } + } else if (taskToEdit instanceof Event) { + Ui.editEventMessage(); + String editLine = Ui.askForEditMessage().trim(); + String[] editWords = editLine.split(" "); + if (taskToEdit instanceof RecurringEvent) { + if (editWords.length > 1 && editWords[0].equals("/description")) { + String newDescription = editLine.substring(12).trim(); + if (newDescription.isBlank()) { + throw new EmptyDescriptionException(); + } + taskToEdit.setDescription(newDescription); + } else if (editWords.length > 1 && editWords[0].equals("/from")){ + String start = editLine.substring(5).trim(); + LocalTime.parse(start, timeFormat); + ((RecurringEvent) taskToEdit).setStart(start); + } else if (editWords.length > 1 && editWords[0].equals("/to")) { + String end = editLine.substring(3).trim(); + LocalTime.parse(end, timeFormat); + ((RecurringEvent) taskToEdit).setEnd(end); + } else if(editWords.length > 1 && editWords[0].equals("/day")) { + DayOfWeek day = DayOfWeek.valueOf(editLine.substring(4).trim()); + ((RecurringEvent) taskToEdit).setDay(day); + } else { + Ui.unknownCommandMessage(); + } + } else { + LocalDateTime start = LocalDateTime.parse(((Event) taskToEdit).getStart(), dateFormat); + LocalDateTime end = LocalDateTime.parse(((Event) taskToEdit).getEnd(), dateFormat); + String newStartString = null; + String newEndString = null; + LocalDateTime newStart = null; + LocalDateTime newEnd = null; + if (editWords.length > 1 && editWords[0].equals("/description")) { + String newDescription = editLine.substring(12).trim(); + if (newDescription.isBlank()) { + throw new EmptyDescriptionException(); + } + taskToEdit.setDescription(newDescription); + } else if (editWords.length > 1 && editWords[0].equals("/from")){ + newStartString = editLine.substring(5).trim(); + newStart = LocalDateTime.parse(newStartString, dateFormat); + //((Event) taskToEdit).setStart(newStart); + } else if (editWords.length > 1 && editWords[0].equals("/to")) { + newEndString = editLine.substring(3).trim(); + newEnd= LocalDateTime.parse(newEndString, dateFormat); + //((Event) taskToEdit).setEnd(newEnd); + } else { + Ui.unknownCommandMessage(); + } + if (newStart != null) { + if (newStart.isAfter(end)) { + throw new startAfterEndException(); + } else if (newStart.isBefore(LocalDateTime.now()) || end.isBefore(LocalDateTime.now())) { + throw new expiredDateException(); + } else { + ((Event) taskToEdit).setStart(newStartString); + } + } else if (newEnd != null) { + if (start.isAfter(newEnd)) { + throw new startAfterEndException(); + } else if (start.isBefore(LocalDateTime.now()) || newEnd.isBefore(LocalDateTime.now())) { + throw new expiredDateException(); + } else { + ((Event) taskToEdit).setEnd(newEndString); + } + } + } + } + Ui.printEditedTask(taskToEdit); + } + + /** + * tries editTask and handles exceptions + * @param tasks + * @param words + */ + static void tryEditTask(ArrayList tasks, String[] words) { + try { + editTask(tasks, words); + } catch (DateTimeParseException e) { + Ui.invalidDateTimeMessage(); + } catch (IllegalArgumentException e) { + Ui.invalidDayMessage(); + } catch (expiredDateException e) { + Ui.expiredErrorMessage(); + } catch (startAfterEndException e) { + Ui.startAfterEndErrorMessage(); + } catch (EmptyDescriptionException e) { + Ui.enmptyDescriptionErrorMessage(); + } + } + /** * Deletes a task from the list * diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 7f78121fcf..9a3d179959 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -319,9 +319,9 @@ static void printUpcomingTasks(ArrayList tasks, String days) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); for (int i = 0; i < tasks.size(); i++) { String timeUntilTask = null; - if (tasks.get(i) instanceof Deadline) { + if (tasks.get(i) instanceof Deadline && !(tasks.get(i) instanceof RecurringDeadline)) { timeUntilTask = ((Deadline) tasks.get(i)).getDeadline(); - } else if (tasks.get(i) instanceof Event) { + } else if (tasks.get(i) instanceof Event && !(tasks.get(i) instanceof RecurringEvent)) { timeUntilTask = ((Event) tasks.get(i)).getStart(); } else if (tasks.get(i) instanceof SchoolClass) { timeUntilTask = ((SchoolClass) tasks.get(i)).getStart(); @@ -445,6 +445,45 @@ static boolean doubleCheck() { return Objects.equals(line, "Y"); } + static void editTodoMessage() { + borderLine(); + System.out.println("\t Please enter a new Todo description:"); + } + + static void editDeadlineMessage() { + borderLine(); + System.out.println("\t Please edit one of the following:"); + System.out.println("\t For non-recurring deadlines: /description or /deadline"); + System.out.println("\t For recurring deadlines: /description or /deadline or /day"); + System.out.println("\t Please follow the format: "); + System.out.println("\t /description or /deadline or /day "); + System.out.println("\t e.g. /deadline 2023-06-30 1200 or /deadline 1200 (for recurring deadlines)"); + } + + static void editEventMessage() { + borderLine(); + System.out.println("\t Please edit one of the following:"); + System.out.println("\t For non-recurring events: /description or /from or /to"); + System.out.println("\t For recurring deadlines: /description or /from or /to or /day"); + System.out.println("\t Please follow the format: "); + System.out.println("\t /description or /from or /day "); + System.out.println("\t e.g. /from 2023-06-30 1200 or /from 1200 (for recurring events)"); + } + + static void printEditedTask(Task task) { + borderLine(); + System.out.println("\t Quack!"); + System.out.println("\t I have changed your task to:"); + System.out.println("\t " + task); + borderLine(); + } + + static String askForEditMessage() { + Scanner in = new Scanner(System.in); + String line = in.nextLine(); + return line; + } + static void help() { borderLine(); System.out.println("\t Quack! Here are the commands you can give me:"); @@ -558,6 +597,12 @@ static void expiredErrorMessage() { borderLine(); } + static void enmptyDescriptionErrorMessage() { + borderLine(); + System.out.println("\t Error. Description cannot be empty"); + borderLine(); + } + static void startAfterEndErrorMessage() { borderLine(); System.out.println("\t Quack! Somehow this human has time travelled, " + diff --git a/src/main/java/seedu/duck/exception/EmptyDescriptionException.java b/src/main/java/seedu/duck/exception/EmptyDescriptionException.java new file mode 100644 index 0000000000..fd61332512 --- /dev/null +++ b/src/main/java/seedu/duck/exception/EmptyDescriptionException.java @@ -0,0 +1,4 @@ +package seedu.duck.exception; + +public class EmptyDescriptionException extends Exception{ +} diff --git a/src/main/java/seedu/duck/task/RecurringDeadline.java b/src/main/java/seedu/duck/task/RecurringDeadline.java index 95a95f193e..c19a1a3d71 100644 --- a/src/main/java/seedu/duck/task/RecurringDeadline.java +++ b/src/main/java/seedu/duck/task/RecurringDeadline.java @@ -13,6 +13,10 @@ public DayOfWeek getDay() { return this.day; } + public void setDay(DayOfWeek day) { + this.day = day; + } + @Override public String toSaveString() { return getDoneConditionString() + " " + getDescription() + " /by " + getDeadline() + "

" + diff --git a/src/main/java/seedu/duck/task/RecurringEvent.java b/src/main/java/seedu/duck/task/RecurringEvent.java index 4fcc61f284..ea6900b735 100644 --- a/src/main/java/seedu/duck/task/RecurringEvent.java +++ b/src/main/java/seedu/duck/task/RecurringEvent.java @@ -14,6 +14,10 @@ public DayOfWeek getDay() { return this.day; } + public void setDay(DayOfWeek day) { + this.day = day; + } + @Override public String toSaveString() { return getDoneConditionString() + " " + getDescription() + " /from " + getStart() + " /to " + getEnd() + From a2d2638d58208089ddb6b430144da9bdbdff55f8 Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Thu, 30 Mar 2023 17:19:04 +0800 Subject: [PATCH 069/152] Added function to edit existing notes --- src/main/java/seedu/duck/Parser.java | 21 ++++++++++++++------- src/main/java/seedu/duck/TaskList.java | 15 ++++++++++++++- src/main/java/seedu/duck/task/Task.java | 9 ++++++++- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 32dd761fa8..1b19ba051b 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -134,23 +134,30 @@ static void processCommand(ArrayList tasks, PriorityQueue cla } break; case "add_note": - if (words.length == 2 && isNumeric(words[1])) { + if(words.length == 2 && isNumeric(words[1])){ TaskList.addNote(tasks, words); - } else { + }else{ Ui.unknownCommandMessage(); } break; case "delete_note": - if (words.length == 3) { - TaskList.deleteNote(tasks, words); - } else { + if(words.length == 3){ + TaskList.deleteNotes(tasks,words); + } else{ Ui.unknownCommandMessage(); } break; case "notes": - if (words.length == 2 && isNumeric(words[1])) { + if(words.length == 2 && isNumeric(words[1])) { Ui.printNotes(tasks, words); - } else { + }else{ + Ui.unknownCommandMessage(); + } + break; + case "edit_note": + if(words.length == 3){ + TaskList.editNote(tasks, words); + }else{ Ui.unknownCommandMessage(); } break; diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 4f03e46d68..d4c8ba8fe4 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -525,7 +525,7 @@ static void addNote(ArrayList tasks, String[] words){ Ui.borderLine(); } - static void deleteNote(ArrayList tasks, String[] words){ + static void deleteNotes(ArrayList tasks, String[] words){ int index = Integer.parseInt(words[1]); int indexOfNoteToBeDeleted = Integer.parseInt(words[2]); Ui.borderLine(); @@ -536,4 +536,17 @@ static void deleteNote(ArrayList tasks, String[] words){ Ui.borderLine(); } + + static void editNote(ArrayList tasks, String[] words){ + int index = Integer.parseInt(words[1]); + int indexOfNoteToBeEdited = Integer.parseInt(words[2]); + Scanner userInput = new Scanner(System.in); + Ui.borderLine(); + System.out.println("\t What would you like to change the note to? "); + System.out.println("\t" + "\t" + tasks.get(index-1).getNote(indexOfNoteToBeEdited-1)); + String editedNote = userInput.nextLine(); + tasks.get(index-1).editNote(indexOfNoteToBeEdited-1,editedNote); + System.out.println("\t" + "The specified note has been edited!"); + Ui.borderLine(); + } } diff --git a/src/main/java/seedu/duck/task/Task.java b/src/main/java/seedu/duck/task/Task.java index 6826e2fe6e..27a5caa815 100644 --- a/src/main/java/seedu/duck/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -6,7 +6,7 @@ public class Task { private String description; private int priority; private boolean isDone; - private final ArrayList additionalNotes; + private ArrayList additionalNotes; public Task(String description) { this.description = description; @@ -53,11 +53,18 @@ public void addNotes(String noteToAdd){ public ArrayList getAdditionalNotes(){ return this.additionalNotes; } + public String getNote(int index){ + return this.additionalNotes.get(index); + }; public void deleteNote(int indexToBeDeleted){ this.additionalNotes.remove(indexToBeDeleted-1); } + public void editNote(int indexToBeEdited, String editedNote){ + this.additionalNotes.set(indexToBeEdited,editedNote); + } + public String getPriority() { if (priority == 1) { // Mark done task with X From 6546fc232849071402df41f0dc3b34beccc7189d Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Thu, 30 Mar 2023 17:42:41 +0800 Subject: [PATCH 070/152] Made code more defensive to handle incorrect inputs when accessing the tasklist --- src/main/java/seedu/duck/TaskList.java | 92 +++++++++++++++++-------- src/main/java/seedu/duck/Ui.java | 6 +- src/main/java/seedu/duck/task/Task.java | 4 ++ 3 files changed, 73 insertions(+), 29 deletions(-) diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index d4c8ba8fe4..48055ddd39 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -127,7 +127,7 @@ static void addTodo(String line, ArrayList tasks) throws IllegalTodoExcept static void setPriority(ArrayList tasks, String[] words) { int taskNumber = Integer.parseInt(words[1]); int taskCount = Task.getTaskCount(); - if (taskNumber > taskCount) { + if (taskNumber > taskCount || taskNumber < 0) { // Input task number exceeds the number of tasks in the list Ui.exceedTaskNumberMessage(taskNumber); } else { @@ -275,7 +275,7 @@ static void addRecurrDeadline(String line, ArrayList tasks) throws Illegal static void markTask(ArrayList tasks, String[] words) { int taskNumber = Integer.parseInt(words[1]); int taskCount = Task.getTaskCount(); - if (taskNumber > taskCount) { + if (taskNumber > taskCount || taskNumber < 0) { // Input task number exceeds the number of tasks in the list Ui.exceedTaskNumberMessage(taskNumber); } else { @@ -297,7 +297,7 @@ static void markTask(ArrayList tasks, String[] words) { static void unmarkTask(ArrayList tasks, String[] words) { int taskNumber = Integer.parseInt(words[1]); int taskCount = Task.getTaskCount(); - if (taskNumber > taskCount) { + if (taskNumber > taskCount || taskNumber < 0) { // Input task number exceeds the number of tasks in the list Ui.exceedTaskNumberMessage(taskNumber); } else { @@ -319,7 +319,7 @@ static void unmarkTask(ArrayList tasks, String[] words) { static void deleteTask(ArrayList tasks, String[] words) { int taskNumber = Integer.parseInt(words[1]); int taskCount = Task.getTaskCount(); - if (taskNumber > taskCount) { + if (taskNumber > taskCount || taskNumber < 0) { // Input task number exceeds the number of tasks in the list Ui.exceedTaskNumberMessage(taskNumber); } else { @@ -513,40 +513,76 @@ static void purge(ArrayList tasks, PriorityQueue classes) { Ui.borderLine(); } } + + /** + * Takes in the task number and adds a note to the list of notes under that task + * + * @param tasks The arraylist of tasks + * @param words The array of strings from user input + */ static void addNote(ArrayList tasks, String[] words){ int index = Integer.parseInt(words[1]); - System.out.println("\t What note would you like to add to the following task?"); - System.out.println(tasks.get(index-1).toString()); - Ui.borderLine(); - Scanner userInput = new Scanner(System.in); - String noteToAdd = userInput.nextLine(); - tasks.get(index-1).addNotes(noteToAdd); - System.out.println("\t The note has been added!"); - Ui.borderLine(); + if (index < tasks.size() && index >= 0) { + System.out.println("\t What note would you like to add to the following task?"); + System.out.println(tasks.get(index - 1).toString()); + Ui.borderLine(); + Scanner userInput = new Scanner(System.in); + String noteToAdd = userInput.nextLine(); + tasks.get(index - 1).addNotes(noteToAdd); + System.out.println("\t The note has been added!"); + Ui.borderLine(); + } else { + Ui.exceedTaskNumberMessage(index); + } } - static void deleteNotes(ArrayList tasks, String[] words){ + /** + * Takes in the task number and index of the note to be deleted and then deletes it + * @param tasks The arraylist of tasks + * @param words The array of strings from user input + */ + static void deleteNotes(ArrayList tasks, String[] words) { int index = Integer.parseInt(words[1]); int indexOfNoteToBeDeleted = Integer.parseInt(words[2]); - Ui.borderLine(); - System.out.println("\t Deleting note: "); - ArrayList noteToBeDeleted = tasks.get(index-1).getAdditionalNotes(); - System.out.println("\t \t" + noteToBeDeleted.get(indexOfNoteToBeDeleted-1)); - tasks.get(index-1).deleteNote(indexOfNoteToBeDeleted); - Ui.borderLine(); + if (index < tasks.size() && index >= 0) { + if (indexOfNoteToBeDeleted < tasks.get(index).numberOfNotes() && indexOfNoteToBeDeleted >= 0) { + Ui.borderLine(); + System.out.println("\t Deleting note: "); + ArrayList noteToBeDeleted = tasks.get(index - 1).getAdditionalNotes(); + System.out.println("\t \t" + noteToBeDeleted.get(indexOfNoteToBeDeleted - 1)); + tasks.get(index - 1).deleteNote(indexOfNoteToBeDeleted); + Ui.borderLine(); + } else { + Ui.exceedNoteNumberMessage(indexOfNoteToBeDeleted); + } + } else { + Ui.exceedTaskNumberMessage(index); + } } - - static void editNote(ArrayList tasks, String[] words){ + /** + * Takes in the task number and index of the note to be edited and then changes it + * @param tasks The arraylist of tasks + * @param words The array of strings from user input + */ + static void editNote(ArrayList tasks, String[] words) { int index = Integer.parseInt(words[1]); int indexOfNoteToBeEdited = Integer.parseInt(words[2]); Scanner userInput = new Scanner(System.in); - Ui.borderLine(); - System.out.println("\t What would you like to change the note to? "); - System.out.println("\t" + "\t" + tasks.get(index-1).getNote(indexOfNoteToBeEdited-1)); - String editedNote = userInput.nextLine(); - tasks.get(index-1).editNote(indexOfNoteToBeEdited-1,editedNote); - System.out.println("\t" + "The specified note has been edited!"); - Ui.borderLine(); + if (index < tasks.size() && index >= 0) { + if (indexOfNoteToBeEdited < tasks.get(index).numberOfNotes() && indexOfNoteToBeEdited >= 0) { + Ui.borderLine(); + System.out.println("\t What would you like to change the note to? "); + System.out.println("\t" + "\t" + tasks.get(index - 1).getNote(indexOfNoteToBeEdited - 1)); + String editedNote = userInput.nextLine(); + tasks.get(index - 1).editNote(indexOfNoteToBeEdited - 1, editedNote); + System.out.println("\t" + "The specified note has been edited!"); + Ui.borderLine(); + } else { + Ui.exceedNoteNumberMessage(indexOfNoteToBeEdited); + } + } else { + Ui.exceedTaskNumberMessage(index); + } } } diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 7f78121fcf..92a9203854 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -537,7 +537,11 @@ static void exceedTaskNumberMessage(int taskNumber) { System.out.println("\t Task " + taskNumber + " does not exist."); borderLine(); } - + static void exceedNoteNumberMessage(int noteNumber){ + borderLine(); + System.out.println("\t Note " + noteNumber + " does not exist for this task"); + borderLine(); + } static void todoErrorMessage() { borderLine(); System.out.println("\t Error. Please enter a valid description."); diff --git a/src/main/java/seedu/duck/task/Task.java b/src/main/java/seedu/duck/task/Task.java index 27a5caa815..e40542f0b8 100644 --- a/src/main/java/seedu/duck/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -65,6 +65,10 @@ public void editNote(int indexToBeEdited, String editedNote){ this.additionalNotes.set(indexToBeEdited,editedNote); } + public int numberOfNotes(){ + return this.additionalNotes.size(); + } + public String getPriority() { if (priority == 1) { // Mark done task with X From 601e9bb9546fead3bdf945a752851298389ceba5 Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Thu, 30 Mar 2023 18:45:44 +0800 Subject: [PATCH 071/152] Corrected bugs caused by previous commit --- src/main/java/seedu/duck/TaskList.java | 12 +++++++----- src/main/java/seedu/duck/task/Task.java | 10 ++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 48055ddd39..105c902b8b 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -522,7 +522,7 @@ static void purge(ArrayList tasks, PriorityQueue classes) { */ static void addNote(ArrayList tasks, String[] words){ int index = Integer.parseInt(words[1]); - if (index < tasks.size() && index >= 0) { + if (index-1 < tasks.size() && index >= 1) { System.out.println("\t What note would you like to add to the following task?"); System.out.println(tasks.get(index - 1).toString()); Ui.borderLine(); @@ -538,14 +538,15 @@ static void addNote(ArrayList tasks, String[] words){ /** * Takes in the task number and index of the note to be deleted and then deletes it + * * @param tasks The arraylist of tasks * @param words The array of strings from user input */ static void deleteNotes(ArrayList tasks, String[] words) { int index = Integer.parseInt(words[1]); int indexOfNoteToBeDeleted = Integer.parseInt(words[2]); - if (index < tasks.size() && index >= 0) { - if (indexOfNoteToBeDeleted < tasks.get(index).numberOfNotes() && indexOfNoteToBeDeleted >= 0) { + if (index-1 < tasks.size() && index >= 1) { + if (indexOfNoteToBeDeleted-1 < tasks.get(index-1).numberOfNotes() && indexOfNoteToBeDeleted >= 1) { Ui.borderLine(); System.out.println("\t Deleting note: "); ArrayList noteToBeDeleted = tasks.get(index - 1).getAdditionalNotes(); @@ -562,6 +563,7 @@ static void deleteNotes(ArrayList tasks, String[] words) { /** * Takes in the task number and index of the note to be edited and then changes it + * * @param tasks The arraylist of tasks * @param words The array of strings from user input */ @@ -569,8 +571,8 @@ static void editNote(ArrayList tasks, String[] words) { int index = Integer.parseInt(words[1]); int indexOfNoteToBeEdited = Integer.parseInt(words[2]); Scanner userInput = new Scanner(System.in); - if (index < tasks.size() && index >= 0) { - if (indexOfNoteToBeEdited < tasks.get(index).numberOfNotes() && indexOfNoteToBeEdited >= 0) { + if (index-1 < tasks.size() && index >= 1) { + if (indexOfNoteToBeEdited-1 < tasks.get(index-1).numberOfNotes() && indexOfNoteToBeEdited >= 1) { Ui.borderLine(); System.out.println("\t What would you like to change the note to? "); System.out.println("\t" + "\t" + tasks.get(index - 1).getNote(indexOfNoteToBeEdited - 1)); diff --git a/src/main/java/seedu/duck/task/Task.java b/src/main/java/seedu/duck/task/Task.java index e40542f0b8..2838938052 100644 --- a/src/main/java/seedu/duck/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -46,6 +46,16 @@ public String getStatusIcon() { return " "; } + public String savedNotes(){ + String save = new String(""); + for (int i = 0; i < additionalNotes.size(); i++){ + save += this.additionalNotes.get(i); + if (!(i==additionalNotes.size()-1)) { + save += "||"; + } + } + return save; + } public void addNotes(String noteToAdd){ this.additionalNotes.add(noteToAdd); } From 6c249494af1463439611d1df3587469506dfa5a9 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Thu, 30 Mar 2023 19:40:04 +0800 Subject: [PATCH 072/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 907fcf7b1a..bccca124d5 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -159,7 +159,7 @@ Got it, all tasks have been cleared. **Implementation** -The ```SchoolClass``` Class is implemented to facilitate the adding of students' classes to the task list. It extends the ```Task``` Class with additional String attributes to store the class name, start date/time, and end date/time. It also overrides the ```toString()``` method to have its own specialised output when being printed, as well as overriding the ```toSaveString()``` method to have correctly save its details to the save file. The ```SchoolClass``` Class will also facilitate the implementation of automatically recurring classes, which is a planned feature for milestone v2.0. ```SchoolClass``` Tasks will be added by default as recurring tasks to the task list, and will be automatically added back at their same set timing each week. +The ```SchoolClass``` Class is implemented to facilitate the adding of students' classes to a separate schedule, which is a priority queue. It extends the ```Task``` Class with additional String attributes to store the class name, day of week, start time, and end time. It also overrides the ```toString()``` method to have its own specialised output when being printed, as well as overriding the ```toSaveString()``` method to correctly save its details to the save file. The ```SchoolClass``` Class will also facilitate the implementation of automatically recurring classes, which is a planned feature for milestone v2.0. ```SchoolClass``` Tasks will be added by default as recurring tasks to the task list, and will be automatically added back at their same set timing each week. The following are the new operations implemented. From ab5d2039a8b6a132f24970bb27bd23d1ce644dcb Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Thu, 30 Mar 2023 22:58:30 +0800 Subject: [PATCH 073/152] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 8cec6f5365..cb56d8f273 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -1,6 +1,6 @@ # Duck User Guide(v 2.0) -Duck is a **desktop app for managing tasks and deadlines, optimised for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). Duck will have a number of quality-of-life features for busy students seeking a simple solution to task management. These include automated task removal upon expiration, or limiting the number of tasks displayed to within a date range. Duck also has recurring task functionality to automate routine tasks so users do not have to manually re-add expired tasks. +Duck is a **desktop app for managing tasks and deadlines, as well as a school class scheduler. It is optimised for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). Duck will have a number of quality-of-life features for busy students seeking a simple solution to task management. These include automated task removal upon expiration, or limiting the number of tasks displayed to within a date range. Duck also has recurring task functionality to automate routine tasks so users do not have to manually re-add expired tasks. From 9cb4a464682f9b4b5bd232423948e1b9c0b8d3f7 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Fri, 31 Mar 2023 01:43:36 +0800 Subject: [PATCH 074/152] Update UserGuide.md --- docs/UserGuide.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index cb56d8f273..7d2f838cfc 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -268,7 +268,11 @@ Removes a school class from the schedule. **Input:** `remove /class /description /day /from /to ` -**Output: Demonstrated with input `remove class /class CS2113 /description /day THURSDAY /from 1100 /to 1200`** +`` can be left empty if the class has no description. + +eg. `remove /class cs2113 /description /day THURSDAY /from 1100 /to 1200` + +**Output: Demonstrated with input `remove class /class CS2113 /description bring laptop /day THURSDAY /from 1100 /to 1200`** ``` From 12ad7a38b3c8ca2fd3838498807e8e08dab832b5 Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Fri, 31 Mar 2023 02:01:07 +0800 Subject: [PATCH 075/152] Updated user guide --- docs/UserGuide.md | 62 ++++++++++++++++++++++++- src/main/java/seedu/duck/Parser.java | 2 +- src/main/java/seedu/duck/Ui.java | 12 +++-- src/main/java/seedu/duck/task/Task.java | 2 +- 4 files changed, 72 insertions(+), 6 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index cb56d8f273..db78f63f43 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -286,7 +286,7 @@ Specifies a priority for a given task, with the following assignments: * 2 - Medium * 3 - High -By default there is no priority specified. +By default, all tasks are low priority. **Input:** `priority ` @@ -298,7 +298,67 @@ Understood. The task's new priority is: Low priority. ``` +## **Print notes for a specific task : `add_note`** +Adds a note to the specified task +**Input:** `add_note ` +**Output: Demonstrated below adding "Bring own recyclable bag"** +``` + What note would you like to add to the following task? + [T][ ] Buy groceries (Low priority.) + ____________________________________________________________ +Bring own recyclable bag + The note has been added! + ____________________________________________________________ +``` + +## **Print notes for a specific task : `delete_note`** +Deletes the + +**Input:** `delete_note ` +**Output: Demonstrated below to delete 1 task** + +``` + ____________________________________________________________ + Deleting note: + Bring own recyclable bag + ____________________________________________________________ +``` +## **Print notes for a specific task : `edit_note`** +Edits the specified note for a specific task. + +**Input:** `edit_note ` +**Output: Demonstrated below to edit "Bring recyclable bag" to "Bring tote bag"** +``` + ____________________________________________________________ + What would you like to change the note to? + Bring recyclable bag +Bring tote bag + The specified note has been edited! + ____________________________________________________________ +``` + +## **Print notes for a specific task : `view_notes`** +Prints the notes for a specific task if they exist. +Otherwise, a message stating that there are no notes for that task will be shown + +**Input:** `view_notes ` +**Output: Demonstrated below for a task with 1 note** +``` + ____________________________________________________________ + Here are the notes for that task quack! + [T][ ] Buy groceries (Low priority.) + 1. Bring own recyclable bag + ____________________________________________________________ +``` +**Output: Demonstrated below for a task with no notes** +``` + ____________________________________________________________ + Here are the notes for that task quack! + [T][ ] Buy groceries (Low priority.) + There are no notes for this task! + ____________________________________________________________ +``` ## **Purge Expired Tasks : `purge`** diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 92759dae91..2c4e42a5fa 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -152,7 +152,7 @@ static void processCommand(ArrayList tasks, PriorityQueue cla Ui.unknownCommandMessage(); } break; - case "notes": + case "view_notes": if(words.length == 2 && isNumeric(words[1])) { Ui.printNotes(tasks, words); }else{ diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 21e15d3511..e989b578db 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -506,13 +506,14 @@ static void help() { System.out.println("\t (/description can be followed by whitespace if the class has no description."); System.out.println("\t : I'll remove this class from your class schedule."); System.out.println("\t - add_note : I'll add an additional note to that task!" ); - System.out.println("\t - delete_note : I'll delete additional note to that task!" ); - System.out.println("\t - notes : I'll print the additional notes for that task!" ); + System.out.println("\t - delete_note : I'll delete the note to that task!" ); + System.out.println("\t - edit_note : I'll edit the note for that task!" ); + System.out.println("\t - view_notes : I'll print the additional notes for that task!" ); System.out.println("\t - purge: I'll delete all expired tasks from your list after a confirmation."); System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); System.out.println("\t - priority <1/2/3>: I'll set the priority of a given task as"); System.out.println("\t 1:Low, 2:Medium and 3:High."); - System.out.println("\t Default: LOW priority."); + System.out.println("\t Default: Low priority."); System.out.println("\t - bye: I will shut down my program.\n"); System.out.println("\t Here are the following ways to input tasks/classes:"); System.out.println("\t Deadlines: /by "); @@ -677,10 +678,15 @@ static void greetingMessage() { static void printNotes(ArrayList tasks, String []words) { int index = Integer.parseInt(words[1]); ArrayList toBePrinted = tasks.get(index-1).getAdditionalNotes(); + borderLine(); + System.out.println("\tHere are the notes for that task quack!"); + System.out.println("\t\t" + tasks.get(index-1).toString()); if (!toBePrinted.isEmpty()) { for (int i = 0; i < toBePrinted.size(); i++) { System.out.println("\t" + (i + 1) + ". " + toBePrinted.get(i)); } + } else { + System.out.println("\tThere are no notes for this task!"); } borderLine(); } diff --git a/src/main/java/seedu/duck/task/Task.java b/src/main/java/seedu/duck/task/Task.java index 2838938052..4a30343f24 100644 --- a/src/main/java/seedu/duck/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -47,7 +47,7 @@ public String getStatusIcon() { } public String savedNotes(){ - String save = new String(""); + String save = ""; for (int i = 0; i < additionalNotes.size(); i++){ save += this.additionalNotes.get(i); if (!(i==additionalNotes.size()-1)) { From 3cd90f401abd33687688d359491f6e71a92debb4 Mon Sep 17 00:00:00 2001 From: skyanzy <88618401+skyanzy@users.noreply.github.com> Date: Fri, 31 Mar 2023 11:29:56 +0800 Subject: [PATCH 076/152] Update UserGuide.md --- docs/UserGuide.md | 61 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index be5d248224..cc2d620ca7 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -12,6 +12,7 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * [Displaying class schedule :](#displaying-class-schedule--list-classes) `list classes` * [Mark a specified task as done :](#marking-a-task--mark-task_number) `mark ` * [Unmark a specified task as not done :](#unmarking-a-task--unmark-task_number) `unmark ` + * [Edit a specific piece information of a task :](#editing-a-task--edit-task_number) `edit ` * [Deleting a task :](#deleting-a-task--delete) `delete ` * [Deleting a school class :](#deleting-a-school-class--remove-class) `remove /class /description /day /from /to ` * [Designate a priority to a given task :](#designate-a-task-priority--priority-task_number-priority) @@ -21,11 +22,13 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * [Purge expired tasks :](#purge-expired-tasks--purge) `purge` * [Clearing all tasks (including datafile) :](#clearing-tasks-from-storage-clear) `clear ` * [Find tasks matching a given keyword :](#finding-tasks-from-storage-that-match-a-keyword-find-keyword) `find ` - * [Add tasks that can be broken down into the following 4 types:](#adding-a-todo-task--description) + * [Add tasks that can be broken down into the following 6 types:](#adding-a-todo-task--description) * Add ToDo: * Add Deadline: /by + * Add RecurringDeadline: /re /by /day * Add Event: /from /to + * Add RecurringEvent: /re /from /to /day * Add Class: /class /from /to * [Terminate the program :](#exiting-the-program--bye) `bye` @@ -243,7 +246,32 @@ Unmarks a task from the tasklist as not complete. [T][ ] todo (No priority established.) ``` +## **Editing a task : `edit `** +Edits a specific piece of information of a task. + +**Input:** `edit ` + +**Output: Demonstrated with input `edit 2`** + +``` + ____________________________________________________________ + Please edit one of the following: + For non-recurring deadlines: /description or /deadline + For recurring deadlines: /description or /deadline or /day + Please follow the format: + /description or /deadline or /day + e.g. /deadline 2023-06-30 1200 or /deadline 1200 (for recurring deadlines) +``` +**Following output: Demonstrated with input `/deadline 2023-04-01 2000`** + +``` + ____________________________________________________________ + Quack! + I have changed your task to: + [D][ ] deadline (by: 2023-04-01 2000) (Low priority.) + ____________________________________________________________ +``` ## **Deleting a task : `delete`** @@ -465,6 +493,20 @@ Alright, I have added this task: You now have 3 tasks in your list. ``` +## **Adding a RecurringDeadline Task : `/re /by /day `** + +Adds a RecurringDeadline task to the storage of Duck + +**Input:** `/re /by /day ` + +**Output: Demonstrated by inputting `/re new_deadline /by 2359 /day MONDAY`** + + +``` +Alright, I have added this task: + [D][ ] new_deadline (by: 2359) (every MONDAY) (Low priority.) +You now have 4 tasks in your list. +``` ## **Adding an Event Task : ` /from /to `** @@ -479,7 +521,22 @@ Adds an Event task to the storage of Duck ``` Alright, I have added this task: [E][ ] event (from: 2023-03-25 2359 to: 2023-03-26 1100) (No priority established.) -You now have 4 tasks in your list. +You now have 5 tasks in your list. +``` + +## **Adding an RecurringEvent Task : `/re /from /to /day `** + +Adds a RecurringEvent task to the storage of Duck + +**Input:** `/re /from /to /day ` + +**Output: Demonstrated by inputting `/re new_event /from 2000 /to 2300 /day MONDAY`** + + +``` +Alright, I have added this task: + [E][ ] new_event (from: 2000 to: 2300) (every MONDAY) (No priority established.) +You now have 6 tasks in your list. ``` From 5a5f95e35c1350020938aaa66b49a4bb0628f10e Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Fri, 31 Mar 2023 11:57:26 +0800 Subject: [PATCH 077/152] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 7d2f838cfc..210a840839 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -95,7 +95,7 @@ Displays all deadlines, events and classes happening today. ## **Displaying class schedule : `list classes`** -Displays all School Classes currently stored in the application. +Displays all School Classes currently stored in the application. Classes will be automatically sorted according to chronological order. Classes will also automatically be marked as done (represented by a cross) if the current time is past the ending time of the class, and their 'done' status will be reset at the start of each week. **Input:** `list classes` From d1ae064b3e7601a249c4cea3d372a07cd1d26c6d Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Fri, 31 Mar 2023 12:33:13 +0800 Subject: [PATCH 078/152] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 66caee3fa0..0deb8d37c3 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -29,7 +29,7 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * Add RecurringDeadline: /re /by /day * Add Event: /from /to * Add RecurringEvent: /re /from /to /day - * Add Class: /class /from /to + * Add Class: /class /day /from /to * [Terminate the program :](#exiting-the-program--bye) `bye` From d7427a53bf6fdd01c3fe5f12ddf827f00d713404 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Fri, 31 Mar 2023 12:50:47 +0800 Subject: [PATCH 079/152] Update UserGuide.md --- docs/UserGuide.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 0deb8d37c3..7e4a6cff7a 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -62,7 +62,7 @@ Displays all tasks currently stored in the application. **Input:** `list` -**Output: Demonstrated with 1 of each type currently in the stored data array** +**Output: Demonstrated with 1 of each type currently in the stored list of tasks** ``` @@ -70,7 +70,6 @@ Here are the tasks in your list: 1. [T][ ] todo (No priority established.) 2. [D][ ] deadline (by: 2023-03-25 2359) (No priority established.) 3. [E][ ] event (from: 2023-03-25 1200 to: 2023-03-26 2359) (No priority established.) - 4. [C][ ] CS2113: Class (from: 2023-03-25 1100 to: 2023-03-25 1200) (No priority established.) ``` ## **Listing all tasks and classes happening today : `list today`** @@ -211,7 +210,7 @@ For instance list 0returns all tasks that are star ``` Here are your tasks in 0 days: 1. [E][ ] event (from: 2023-03-25 1200 to: 2023-03-26 2359) (No priority established.) - 2. [C][ ] CS2113: Class (from: 2023-03-25 1100 to: 2023-03-25 1200) (No priority established.) + 2. [D][ ] Submit CS2113 quiz (by: 2023-03-31 2359) (Low priority.) ``` From 122d183d09a71538e6ab0e8b8dce4c5f7ea10b31 Mon Sep 17 00:00:00 2001 From: skyanzy <88618401+skyanzy@users.noreply.github.com> Date: Fri, 31 Mar 2023 14:51:42 +0800 Subject: [PATCH 080/152] Update UserGuide.md --- docs/UserGuide.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 7e4a6cff7a..1495d3d962 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -471,7 +471,7 @@ Adds a ToDo task to the storage of Duck ``` Alright, I have added this task: - [T][ ] todo (No priority established.) + [T][ ] todo (No priority established.) You now have 2 tasks in your list. ``` @@ -488,7 +488,7 @@ Adds a Deadline task to the storage of Duck ``` Alright, I have added this task: - [D][ ] deadline (by: 2023-03-25 2359) (No priority established.) + [D][ ] deadline (by: 2023-03-25 2359) (No priority established.) You now have 3 tasks in your list. ``` @@ -519,7 +519,7 @@ Adds an Event task to the storage of Duck ``` Alright, I have added this task: - [E][ ] event (from: 2023-03-25 2359 to: 2023-03-26 1100) (No priority established.) + [E][ ] event (from: 2023-03-25 2359 to: 2023-03-26 1100) (No priority established.) You now have 5 tasks in your list. ``` @@ -534,7 +534,7 @@ Adds a RecurringEvent task to the storage of Duck ``` Alright, I have added this task: - [E][ ] new_event (from: 2000 to: 2300) (every MONDAY) (No priority established.) + [E][ ] new_event (from: 2000 to: 2300) (every MONDAY) (No priority established.) You now have 6 tasks in your list. ``` @@ -551,7 +551,7 @@ Adds a Class task to the storage of Duck ``` Alright, I have added this task: - [THURSDAY][ ] CS2113: Bring laptop (from: 1100 to: 1200) + [THURSDAY][ ] CS2113: Bring laptop (from: 1100 to: 1200) You now have 1 class in your schedule. ``` From f2a2f12bc4603b030ab05bb76dbf290c0a57c77a Mon Sep 17 00:00:00 2001 From: skyanzy <88618401+skyanzy@users.noreply.github.com> Date: Fri, 31 Mar 2023 15:03:50 +0800 Subject: [PATCH 081/152] Update UserGuide.md --- docs/UserGuide.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 1495d3d962..a4fbbcddc1 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -15,8 +15,11 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * [Edit a specific piece information of a task :](#editing-a-task--edit-task_number) `edit ` * [Deleting a task :](#deleting-a-task--delete) `delete ` * [Deleting a school class :](#deleting-a-school-class--remove-class) `remove /class /description /day /from /to ` - * [Designate a priority to a given task :](#designate-a-task-priority--priority-task_number-priority) - * `priority ` + * [Designate a priority to a given task :](#designate-a-task-priority--priority-task_number-priority) `priority ` + * [Adding notes for a specific task :](#adding-notes-for-a-specific-task--add_note) `add_note ` + * [Deleting notes for a specific task :](#deleting-notes-for-a-specific-task--delete_note) `delete_note ` + * [Editing notes for a specific task :](#editing-notes-for-a-specific-task--edit_note) `edit_note ` + * [Viewing notes for a specific task :](#printing-notes-for-a-specific-task--view_notes) `view_notes ` * [List tasks of low/medium/high priority :](#listing-all-low-priority-tasks--low_priority) `low_priority`/`medium_priority`/`high_priority` * [List tasks in priority order:](#listing-all-tasks-arranged-by-priority--priority_list) `priority_list` * [Purge expired tasks :](#purge-expired-tasks--purge) `purge` @@ -329,7 +332,7 @@ Understood. The task's new priority is: Low priority. ``` -## **Print notes for a specific task : `add_note`** +## **Adding notes for a specific task : `add_note`** Adds a note to the specified task **Input:** `add_note ` @@ -343,7 +346,7 @@ Bring own recyclable bag ____________________________________________________________ ``` -## **Print notes for a specific task : `delete_note`** +## **Deleting notes for a specific task : `delete_note`** Deletes the **Input:** `delete_note ` @@ -355,7 +358,7 @@ Deletes the Bring own recyclable bag ____________________________________________________________ ``` -## **Print notes for a specific task : `edit_note`** +## **Editing notes for a specific task : `edit_note`** Edits the specified note for a specific task. **Input:** `edit_note ` @@ -369,7 +372,7 @@ Bring tote bag ____________________________________________________________ ``` -## **Print notes for a specific task : `view_notes`** +## **Printing notes for a specific task : `view_notes`** Prints the notes for a specific task if they exist. Otherwise, a message stating that there are no notes for that task will be shown From 746619aaa00451e1a6c719373c4fcd5314a2633c Mon Sep 17 00:00:00 2001 From: tliangac Date: Fri, 31 Mar 2023 17:46:31 +0800 Subject: [PATCH 082/152] Fix typo and bug in upcoming class function --- docs/UserGuide.md | 44 ++++++-- src/main/java/seedu/duck/Storage.java | 30 +++--- src/main/java/seedu/duck/TaskList.java | 26 ++--- src/main/java/seedu/duck/Ui.java | 132 +++++++++++++----------- src/main/java/seedu/duck/task/Task.java | 4 +- 5 files changed, 136 insertions(+), 100 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index a4fbbcddc1..bc190d7e77 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -7,9 +7,11 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * [**Features**](#features) * [Viewing help :](#viewing-help--help) `help` * [Listing all tasks :](#listing-all-tasks--list) `list` - * [Listing all tasks and classes happening today :](#listing-all-tasks--list) `list today` + * [Listing all tasks and classes happening today :](#listing-all-tasks--list) `list_today` * [Listing all tasks up to X days into the future :](#listing-all-tasks-up-to-x-days-in-the-future--list-x) `list X` - * [Displaying class schedule :](#displaying-class-schedule--list-classes) `list classes` + * [Displaying upcoming deadline](#displaying-upcoming-deadline) + * [Displaying class schedule :](#displaying-class-schedule--list-classes) `list_classes` + * [Displaying upcoming class :](#displaying-upcoming-class--upcomingclass) `upcoming_class` * [Mark a specified task as done :](#marking-a-task--mark-task_number) `mark ` * [Unmark a specified task as not done :](#unmarking-a-task--unmark-task_number) `unmark ` * [Edit a specific piece information of a task :](#editing-a-task--edit-task_number) `edit ` @@ -75,11 +77,11 @@ Here are the tasks in your list: 3. [E][ ] event (from: 2023-03-25 1200 to: 2023-03-26 2359) (No priority established.) ``` -## **Listing all tasks and classes happening today : `list today`** +## **Listing all tasks and classes happening today : `list_today`** Displays all deadlines, events and classes happening today. -**Input:** `list today` +**Input:** `list_today` **Output: Demonstrated with 1 of each type currently in the stored data array** @@ -96,13 +98,22 @@ Displays all deadlines, events and classes happening today. [E][ ] study (from: 0800 to: 2300) (every WEDNESDAY) (No priority established.) ____________________________________________________________ ``` +## **Displaying upcoming deadline** +Displays upcoming deadline stored in the application when starting the application. -## **Displaying class schedule : `list classes`** +**Output: The upcoming deadline with remaining time before the deadline** + +``` +Here are the upcoming deadline: +1.Eat bread (1 day 26 hours 50 minutes before the deadline) +``` + +## **Displaying class schedule : `list_classes`** Displays all School Classes currently stored in the application. Classes will be automatically sorted according to chronological order. Classes will also automatically be marked as done (represented by a cross) if the current time is past the ending time of the class, and their 'done' status will be reset at the start of each week. -**Input:** `list classes` +**Input:** `list_classes` **Output: Demonstrated with classes with different names and start/end times, with some already past their end time** @@ -110,11 +121,26 @@ Displays all School Classes currently stored in the application. Classes will be ``` Here is your class schedule: -[MONDAY][X] eg2501 (from: 1600 to: 1800) -[TUESDAY][X] ee2026 (from: 0900 to: 1200) -[TUESDAY][ ] cs2113 (from: 1600 to: 1700) + [MONDAY][X] eg2501 (from: 1600 to: 1800) + [TUESDAY][X] ee2026 (from: 0900 to: 1200) + [TUESDAY][ ] cs2113 (from: 1600 to: 1700) ``` +## **Displaying upcoming class : `upcoming_class`** + +Displays the next upcoming class stored in the application. Classes will be automatically sorted according to chronological order. Classes will also automatically be marked as done (represented by a cross) if the current time is past the ending time of the class, and their 'done' status will be reset at the start of each week. + +**Input:** `upcoming_class` + +**Output: The next upcoming class with names and start/end times** + + +``` +Here is your next upcoming class: + [TUESDAY][ ] cs2113 (from: 1600 to: 1700) + +``` + ## **Listing all low priority tasks : `low_priority`** Displays all tasks that have been assigned low priority diff --git a/src/main/java/seedu/duck/Storage.java b/src/main/java/seedu/duck/Storage.java index 01c00d230f..c8260754e6 100644 --- a/src/main/java/seedu/duck/Storage.java +++ b/src/main/java/seedu/duck/Storage.java @@ -22,13 +22,13 @@ public class Storage { /** * Load tasks from save data into the list * - * @param line The line of input from the save file + * @param line The line of input from the save file * @param tasks The array list of tasks */ static void loadTask(String line, ArrayList tasks, PriorityQueue classes, String doneStatus) { if (line.contains("/by")) { if (line.contains("/day")) { - loadRecurrDeadline(line, tasks); + loadRecurringDeadline(line, tasks); } else { loadDeadline(line, tasks); } @@ -38,7 +38,7 @@ static void loadTask(String line, ArrayList tasks, PriorityQueue tasks) { @@ -87,24 +87,24 @@ static void loadTodo(String line, ArrayList tasks) { * Adds an event into the list without generating messages, * to be used when loading from save data. * - * @param line The line of input from the save file + * @param line The line of input from the save file * @param tasks The array list of tasks */ static void loadEvent(String line, ArrayList tasks) { String description = line.substring(0, line.indexOf("/from")).trim(); String start = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); String end = line.substring(line.indexOf("/to") + 3, line.indexOf("

")).trim(); - String priority = line.substring(line.indexOf("

") + 3,line.indexOf("

") + 4).trim(); + String priority = line.substring(line.indexOf("

") + 3, line.indexOf("

") + 4).trim(); Event currEvent = new Event(description, start, end); currEvent.setPriority(priority); tasks.add(currEvent); } - static void loadRecurrEvent(String line, ArrayList tasks) { + static void loadRecurringEvent(String line, ArrayList tasks) { String description = line.substring(0, line.indexOf("/from")).trim(); String start = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); String end = line.substring(line.indexOf("/to") + 3, line.indexOf("

")).trim(); - String priority = line.substring(line.indexOf("

") + 3,line.indexOf("/day")).trim(); + String priority = line.substring(line.indexOf("

") + 3, line.indexOf("/day")).trim(); DayOfWeek day = DayOfWeek.valueOf(line.substring(line.indexOf("/day") + 4).trim()); RecurringEvent currEvent = new RecurringEvent(description, start, end, day); currEvent.setPriority(priority); @@ -115,7 +115,7 @@ static void loadRecurrEvent(String line, ArrayList tasks) { * Adds a schoolClass to the list without generating messages, * to be used when loading from save data. * - * @param line The line of input from the user + * @param line The line of input from the user * @param classes The priority queue of school classes */ static void loadSchoolClass(String line, PriorityQueue classes) { @@ -134,13 +134,13 @@ static void loadSchoolClass(String line, PriorityQueue classes) { * Adds a deadline into the list without generating messages, * to be used when loading from save data. * - * @param line The line of input from the save file + * @param line The line of input from the save file * @param tasks The array list of tasks */ static void loadDeadline(String line, ArrayList tasks) { String description = line.substring(0, line.indexOf("/by")).trim(); String deadline = line.substring(line.indexOf("/by") + 3, line.indexOf("

")).trim(); - String priority = line.substring(line.indexOf("

") + 3,line.indexOf("

") + 4).trim(); + String priority = line.substring(line.indexOf("

") + 3, line.indexOf("

") + 4).trim(); Deadline currDeadline = new Deadline(description, deadline); currDeadline.setPriority(priority); tasks.add(currDeadline); @@ -149,13 +149,13 @@ static void loadDeadline(String line, ArrayList tasks) { /** * Adds a RecurringDeadline to the list when loading from save data * - * @param line The line of input from save file + * @param line The line of input from save file * @param tasks the array list of tasks */ - static void loadRecurrDeadline(String line, ArrayList tasks) { + static void loadRecurringDeadline(String line, ArrayList tasks) { String description = line.substring(0, line.indexOf("/by")).trim(); String deadline = line.substring(line.indexOf("/by") + 3, line.indexOf("

")).trim(); - String priority = line.substring(line.indexOf("

") + 3,line.indexOf("/day")).trim(); + String priority = line.substring(line.indexOf("

") + 3, line.indexOf("/day")).trim(); DayOfWeek day = DayOfWeek.valueOf(line.substring(line.indexOf("/day") + 4).trim()); RecurringDeadline currDeadline = new RecurringDeadline(description, deadline, day); currDeadline.setPriority(priority); @@ -165,7 +165,7 @@ static void loadRecurrDeadline(String line, ArrayList tasks) { /** * Load the task status of a task from the save data * - * @param tasks The array list of tasks + * @param tasks The array list of tasks * @param doneStatus The done status of the current task */ static void loadTaskStatus(ArrayList tasks, String doneStatus) { diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 156d153fcd..08ca44c3b2 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -26,7 +26,7 @@ static void addTask(String line, ArrayList tasks, PriorityQueue tasks, PriorityQueue tasks) throws IllegalEventExce } } - static void addRecurrEvent(String line, ArrayList tasks) throws IllegalEventException{ + static void addRecurringEvent(String line, ArrayList tasks) throws IllegalEventException{ String description = line.substring(4, line.indexOf("/from")).trim(); String start = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); String end = line.substring(line.indexOf("/to") + 3, line.indexOf("/day")).trim(); @@ -245,7 +245,7 @@ static void addDeadline(String line, ArrayList tasks) throws IllegalDeadli * @param line the line of input from the user * @param tasks the array list of tasks */ - static void addRecurrDeadline(String line, ArrayList tasks) throws IllegalDeadlineException, + static void addRecurringDeadline(String line, ArrayList tasks) throws IllegalDeadlineException, IllegalArgumentException { String description = line.substring(4, line.indexOf("/by")).trim(); String deadline = line.substring(line.indexOf("/by") + 3, line.indexOf("/day")).trim(); @@ -307,8 +307,8 @@ static void unmarkTask(ArrayList tasks, String[] words) { /** * edits the attributes of a specific task - * @param tasks - * @param words + * @param tasks The array list of tasks + * @param words The array of words generated from the user input */ static void editTask(ArrayList tasks, String[] words) throws expiredDateException, startAfterEndException, EmptyDescriptionException { @@ -442,8 +442,8 @@ static void editTask(ArrayList tasks, String[] words) throws expiredDateEx /** * tries editTask and handles exceptions - * @param tasks - * @param words + * @param tasks The array list of tasks + * @param words The array of words generated from the user input */ static void tryEditTask(ArrayList tasks, String[] words) { try { @@ -457,7 +457,7 @@ static void tryEditTask(ArrayList tasks, String[] words) { } catch (startAfterEndException e) { Ui.startAfterEndErrorMessage(); } catch (EmptyDescriptionException e) { - Ui.enmptyDescriptionErrorMessage(); + Ui.emptyDescriptionErrorMessage(); } } @@ -486,9 +486,9 @@ static void deleteTask(ArrayList tasks, String[] words) { * * @param classes The priority queue of SchoolClasses * @param line The line of user input - * @throws IllegalArgumentException - * @throws NullPointerException - * @throws StringIndexOutOfBoundsException + * @throws IllegalArgumentException handle IllegalArgumentException + * @throws NullPointerException handle NullPointerException + * @throws StringIndexOutOfBoundsException handle StringIndexOutOfBoundsException */ static void deleteClass(PriorityQueue classes, String line) throws IllegalArgumentException, NullPointerException, StringIndexOutOfBoundsException{ @@ -501,7 +501,7 @@ static void deleteClass(PriorityQueue classes, String line) throws String startString = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); String endString = line.substring(line.indexOf("/to") + 3).trim(); SchoolClass toDelete = new SchoolClass(className, description, day, startString, endString); - if (classes.remove(toDelete) == true) { + if (classes.remove(toDelete)) { Ui.deleteClassMessage(); } else { Ui.unsuccessfulDeleteClassMessage(); diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index e989b578db..fb13999b66 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -19,23 +19,23 @@ * Deals with interactions with the user */ public class Ui { - static void printDuck(){ - System.out.println(" ,-.\n"+ - " ,--' ~.).\n"+ - " ,' `.\n"+ - " ; (((__ __)))\n"+ - " ; ( (#) ( (#)\n"+ - " | \\_/___\\_/\n"+ - " ,\" ,-' `__\".\n"+ - " ( ( ._ ____`.)--._ _\n"+ - " `._ `-.`-' \\(`-' _ `-. _,-' `-/`.\n"+ - " ,') `.`._)) ,' `. `. ,',' ;\n"+ - " .' . `--' / ). `. ;\n"+ - " ; `- / ' ) ;\n"+ - " \\ ') ,'\n"+ - " \\ ,' ;\n"+ - " \\ `~~~' ,'\n"+ - " `. _,'\n"+ + static void printDuck() { + System.out.println(" ,-.\n" + + " ,--' ~.).\n" + + " ,' `.\n" + + " ; (((__ __)))\n" + + " ; ( (#) ( (#)\n" + + " | \\_/___\\_/\n" + + " ,\" ,-' `__\".\n" + + " ( ( ._ ____`.)--._ _\n" + + " `._ `-.`-' \\(`-' _ `-. _,-' `-/`.\n" + + " ,') `.`._)) ,' `. `. ,',' ;\n" + + " .' . `--' / ). `. ;\n" + + " ; `- / ' ) ;\n" + + " \\ ') ,'\n" + + " \\ ,' ;\n" + + " \\ `~~~' ,'\n" + + " `. _,'\n" + " `-._________,--'"); } @@ -50,7 +50,7 @@ static void list(ArrayList tasks) { System.out.println("\t Here are the tasks in your list:"); for (int i = 0; i < taskCount; i++) { System.out.println("\t " + (i + 1) + "." + tasks.get(i)); - if (!tasks.get(i).getAdditionalNotes().isEmpty()){ + if (!tasks.get(i).getAdditionalNotes().isEmpty()) { printList(tasks, i); } } @@ -63,14 +63,15 @@ static void listClasses(PriorityQueue classes, ArrayList task borderLine(); System.out.println("\t Here is your class schedule:\n"); while (iterator.hasNext()) { - System.out.println(iterator.next()); + System.out.println("\t"+iterator.next()); } borderLine(); } /** * prints out all classes, deadlines and events happening today - * @param tasks array list of all tasks + * + * @param tasks array list of all tasks * @param classes pq of all classes */ static void listToday(ArrayList tasks, PriorityQueue classes) { @@ -133,7 +134,7 @@ static void printPriorityList(ArrayList tasks) { * @param tasks the list of tasks */ static void printHighPriority(ArrayList tasks) { - ArrayList indexOfHighPriority = new ArrayList(); + ArrayList indexOfHighPriority = new ArrayList<>(); int taskCount = Task.getTaskCount(); for (int i = 0; i < taskCount; i++) { if (tasks.get(i).returnPriority() == 3) { @@ -145,10 +146,10 @@ static void printHighPriority(ArrayList tasks) { System.out.println("\t You have " + indexOfHighPriority.size() + " tasks that are high in priority!"); for (int i = 0; i < indexOfHighPriority.size(); i++) { System.out.println("\t" + (i + 1) + "." + tasks.get(indexOfHighPriority.get(i))); - if (!tasks.get(i).getAdditionalNotes().isEmpty()){ + if (!tasks.get(i).getAdditionalNotes().isEmpty()) { ArrayList toBePrinted = tasks.get(i).getAdditionalNotes(); - for (int j = 0; j < toBePrinted.size(); j++){ - System.out.println("\t" + "\t - " + (j+1) + ". " + toBePrinted.get(j)); + for (int j = 0; j < toBePrinted.size(); j++) { + System.out.println("\t" + "\t - " + (j + 1) + ". " + toBePrinted.get(j)); } } } @@ -164,7 +165,7 @@ static void printHighPriority(ArrayList tasks) { * @param tasks the list of tasks */ static void printMediumPriority(ArrayList tasks) { - ArrayList indexOfMediumPriority = new ArrayList(); + ArrayList indexOfMediumPriority = new ArrayList<>(); int taskCount = Task.getTaskCount(); for (int i = 0; i < taskCount; i++) { if (tasks.get(i).returnPriority() == 2) { @@ -176,10 +177,10 @@ static void printMediumPriority(ArrayList tasks) { System.out.println("\t You have " + indexOfMediumPriority.size() + " tasks that are medium in priority!"); for (int i = 0; i < indexOfMediumPriority.size(); i++) { System.out.println("\t" + (i + 1) + "." + tasks.get(indexOfMediumPriority.get(i))); - if (!tasks.get(i).getAdditionalNotes().isEmpty()){ + if (!tasks.get(i).getAdditionalNotes().isEmpty()) { ArrayList toBePrinted = tasks.get(i).getAdditionalNotes(); - for (int j = 0; j < toBePrinted.size(); j++){ - System.out.println("\t" + "\t - " + (j+1) + ". " + toBePrinted.get(j)); + for (int j = 0; j < toBePrinted.size(); j++) { + System.out.println("\t" + "\t - " + (j + 1) + ". " + toBePrinted.get(j)); } } } @@ -195,7 +196,7 @@ static void printMediumPriority(ArrayList tasks) { * @param tasks the list of tasks */ static void printLowPriority(ArrayList tasks) { - ArrayList indexOfLowPriority = new ArrayList(); + ArrayList indexOfLowPriority = new ArrayList<>(); int taskCount = Task.getTaskCount(); for (int i = 0; i < taskCount; i++) { if (tasks.get(i).returnPriority() == 1) { @@ -207,10 +208,10 @@ static void printLowPriority(ArrayList tasks) { System.out.println("\t You have " + indexOfLowPriority.size() + " tasks that are low in priority!"); for (int i = 0; i < indexOfLowPriority.size(); i++) { System.out.println("\t" + (i + 1) + "." + tasks.get(indexOfLowPriority.get(i))); - if (!tasks.get(i).getAdditionalNotes().isEmpty()){ + if (!tasks.get(i).getAdditionalNotes().isEmpty()) { ArrayList toBePrinted = tasks.get(i).getAdditionalNotes(); - for (int j = 0; j < toBePrinted.size(); j++){ - System.out.println("\t" + "\t - " + (j+1) + ". " + toBePrinted.get(j)); + for (int j = 0; j < toBePrinted.size(); j++) { + System.out.println("\t" + "\t - " + (j + 1) + ". " + toBePrinted.get(j)); } } } @@ -284,17 +285,17 @@ static void printMatchingList(ArrayList matchingResults, int matchCount, static void displayUpcomingDeadline(ArrayList tasks) { System.out.println("\t Here are the upcoming deadline: "); int count = 0; - for (int i = 0; i < tasks.size(); i++) { - if (tasks.get(i) instanceof Deadline && !(tasks.get(i) instanceof RecurringDeadline)) { + for (Task t:tasks) { + if (t instanceof Deadline && !(t instanceof RecurringDeadline)) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); - String deadline = ((Deadline) tasks.get(i)).getDeadline(); + String deadline = ((Deadline) t).getDeadline(); Date d; Date n = new Date(); try { d = format.parse(deadline); long diff = d.getTime() - n.getTime(); String di = getTimeDiff(diff); - String description = tasks.get(i).getDescription().replace("deadline ", ""); + String description = t.getDescription().replace("deadline ", ""); System.out.println("\t " + (count + 1) + "." + description + " (" + di + "before the deadline)"); count++; } catch (ParseException e) { @@ -318,14 +319,14 @@ static void printUpcomingTasks(ArrayList tasks, String days) { Date d; Date n = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); - for (int i = 0; i < tasks.size(); i++) { + for (Task t:tasks) { String timeUntilTask = null; - if (tasks.get(i) instanceof Deadline && !(tasks.get(i) instanceof RecurringDeadline)) { - timeUntilTask = ((Deadline) tasks.get(i)).getDeadline(); - } else if (tasks.get(i) instanceof Event && !(tasks.get(i) instanceof RecurringEvent)) { - timeUntilTask = ((Event) tasks.get(i)).getStart(); - } else if (tasks.get(i) instanceof SchoolClass) { - timeUntilTask = ((SchoolClass) tasks.get(i)).getStart(); + if (t instanceof Deadline && !(t instanceof RecurringDeadline)) { + timeUntilTask = ((Deadline) t).getDeadline(); + } else if (t instanceof Event && !(t instanceof RecurringEvent)) { + timeUntilTask = ((Event) t).getStart(); + } else if (t instanceof SchoolClass) { + timeUntilTask = ((SchoolClass) t).getStart(); } if (timeUntilTask != null) { try { @@ -337,7 +338,7 @@ static void printUpcomingTasks(ArrayList tasks, String days) { <= Integer.parseInt(days)) || diffSplit[1].contains("hour") || diffSplit[1].contains("minute"))) { count++; - System.out.println("\t " + count + "." + tasks.get(i).toString()); + System.out.println("\t " + count + "." + t); } } catch (ParseException e) { e.printStackTrace(); @@ -410,11 +411,16 @@ static String getTimeDiff(long timeDifferenceMilliseconds) { */ static void displayNextUpcomingClass(PriorityQueue classes) { borderLine(); + ArrayList result = new ArrayList<>(classes); System.out.println("\t Here are your next upcoming class: "); - if (classes.isEmpty()) { - System.out.println("\t No upcoming class!"); + if (result.isEmpty()) { + System.out.println("\t \t No upcoming class!"); } else { - System.out.println("\t" + classes.peek()); + for (SchoolClass c:result) { + if (c.getStatusIcon() != "X") { + System.out.println("\t"+c); + } + } } borderLine(); } @@ -490,10 +496,11 @@ static void help() { System.out.println("\t Quack! Here are the commands you can give me:"); System.out.println("\t - list: I'll list out all the tasks you have recorded."); System.out.println("\t - list : I'll list out all the tasks in that number of days."); - System.out.println("\t - list classes: I'll list out the classes you have on your schedule."); - System.out.println("\t - list today: I'll list out all the classes, deadlines and events you have today."); + System.out.println("\t - list_classes: I'll list out the classes you have on your schedule."); + System.out.println("\t - list_today: I'll list out all the classes, deadlines and events you have today."); System.out.println("\t - priority_list: " + "I'll list out all the tasks you have recorded arranged by their priority."); + System.out.println("\t - upcoming_class: I'll list out the next upcoming class."); System.out.println("\t - low_priority: I'll list out all the tasks you have that are low in priority."); System.out.println("\t - medium_priority: I'll list out all the tasks you have that are medium in priority."); System.out.println("\t - high_priority: I'll list out all the tasks you have that are high in priority."); @@ -505,10 +512,10 @@ static void help() { "/day /from /to "); System.out.println("\t (/description can be followed by whitespace if the class has no description."); System.out.println("\t : I'll remove this class from your class schedule."); - System.out.println("\t - add_note : I'll add an additional note to that task!" ); - System.out.println("\t - delete_note : I'll delete the note to that task!" ); - System.out.println("\t - edit_note : I'll edit the note for that task!" ); - System.out.println("\t - view_notes : I'll print the additional notes for that task!" ); + System.out.println("\t - add_note : I'll add an additional note to that task!"); + System.out.println("\t - delete_note : I'll delete the note to that task!"); + System.out.println("\t - edit_note : I'll edit the note for that task!"); + System.out.println("\t - view_notes : I'll print the additional notes for that task!"); System.out.println("\t - purge: I'll delete all expired tasks from your list after a confirmation."); System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); System.out.println("\t - priority <1/2/3>: I'll set the priority of a given task as"); @@ -578,11 +585,13 @@ static void exceedTaskNumberMessage(int taskNumber) { System.out.println("\t Task " + taskNumber + " does not exist."); borderLine(); } - static void exceedNoteNumberMessage(int noteNumber){ + + static void exceedNoteNumberMessage(int noteNumber) { borderLine(); System.out.println("\t Note " + noteNumber + " does not exist for this task"); borderLine(); } + static void todoErrorMessage() { borderLine(); System.out.println("\t Error. Please enter a valid description."); @@ -603,7 +612,7 @@ static void expiredErrorMessage() { borderLine(); } - static void enmptyDescriptionErrorMessage() { + static void emptyDescriptionErrorMessage() { borderLine(); System.out.println("\t Error. Description cannot be empty"); borderLine(); @@ -675,12 +684,13 @@ static void greetingMessage() { "If you wish to know what I understand, just enter 'help'."); System.out.println("\t How may I assist you today, human?"); } - static void printNotes(ArrayList tasks, String []words) { + + static void printNotes(ArrayList tasks, String[] words) { int index = Integer.parseInt(words[1]); - ArrayList toBePrinted = tasks.get(index-1).getAdditionalNotes(); + ArrayList toBePrinted = tasks.get(index - 1).getAdditionalNotes(); borderLine(); System.out.println("\tHere are the notes for that task quack!"); - System.out.println("\t\t" + tasks.get(index-1).toString()); + System.out.println("\t\t" + tasks.get(index - 1).toString()); if (!toBePrinted.isEmpty()) { for (int i = 0; i < toBePrinted.size(); i++) { System.out.println("\t" + (i + 1) + ". " + toBePrinted.get(i)); @@ -691,10 +701,10 @@ static void printNotes(ArrayList tasks, String []words) { borderLine(); } - static void printList(ArrayList tasks,int index){ + static void printList(ArrayList tasks, int index) { ArrayList toBePrinted = tasks.get(index).getAdditionalNotes(); - for (int j = 0; j < toBePrinted.size(); j++){ - System.out.println("\t" + "\t - " + (j+1) + ". " + toBePrinted.get(j)); + for (int j = 0; j < toBePrinted.size(); j++) { + System.out.println("\t" + "\t - " + (j + 1) + ". " + toBePrinted.get(j)); } } diff --git a/src/main/java/seedu/duck/task/Task.java b/src/main/java/seedu/duck/task/Task.java index 4a30343f24..7a21656fe5 100644 --- a/src/main/java/seedu/duck/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -12,7 +12,7 @@ public Task(String description) { this.description = description; this.isDone = false; this.priority = 1; //automatically set to low priority - this.additionalNotes = new ArrayList(); + this.additionalNotes = new ArrayList<>(); } public void setDescription(String description) { @@ -65,7 +65,7 @@ public ArrayList getAdditionalNotes(){ } public String getNote(int index){ return this.additionalNotes.get(index); - }; + } public void deleteNote(int indexToBeDeleted){ this.additionalNotes.remove(indexToBeDeleted-1); From 70858d9b16d19000544738efb26b45553f27cd99 Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Sat, 1 Apr 2023 18:33:54 +0800 Subject: [PATCH 083/152] Notes for tasks will now be saved and loaded on to Duck on start up --- src/main/java/seedu/duck/Parser.java | 3 ++ src/main/java/seedu/duck/Storage.java | 32 +++++++++++++++++++-- src/main/java/seedu/duck/Ui.java | 6 ++-- src/main/java/seedu/duck/task/Deadline.java | 2 +- src/main/java/seedu/duck/task/Event.java | 2 +- src/main/java/seedu/duck/task/Task.java | 18 ++++++++---- src/main/java/seedu/duck/task/Todo.java | 2 +- 7 files changed, 51 insertions(+), 14 deletions(-) diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 2c4e42a5fa..0534c2f2e4 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -141,6 +141,7 @@ static void processCommand(ArrayList tasks, PriorityQueue cla case "add_note": if(words.length == 2 && isNumeric(words[1])){ TaskList.addNote(tasks, words); + Storage.trySave(tasks, classes); }else{ Ui.unknownCommandMessage(); } @@ -148,6 +149,7 @@ static void processCommand(ArrayList tasks, PriorityQueue cla case "delete_note": if(words.length == 3){ TaskList.deleteNotes(tasks,words); + Storage.trySave(tasks, classes); } else{ Ui.unknownCommandMessage(); } @@ -162,6 +164,7 @@ static void processCommand(ArrayList tasks, PriorityQueue cla case "edit_note": if(words.length == 3){ TaskList.editNote(tasks, words); + Storage.trySave(tasks, classes); }else{ Ui.unknownCommandMessage(); } diff --git a/src/main/java/seedu/duck/Storage.java b/src/main/java/seedu/duck/Storage.java index 01c00d230f..2f98490ddf 100644 --- a/src/main/java/seedu/duck/Storage.java +++ b/src/main/java/seedu/duck/Storage.java @@ -20,7 +20,7 @@ public class Storage { static final String SAVEFOLDER = "data"; /** - * Load tasks from save data into the list + * Load tasks and the notes under the task from save data into the list * * @param line The line of input from the save file * @param tasks The array list of tasks @@ -78,11 +78,21 @@ static void clearTask() throws IOException { static void loadTodo(String line, ArrayList tasks) { String description = line.substring(0, line.indexOf("

")).trim(); Todo currTodo = new Todo(description); - String priority = line.substring(line.indexOf("

") + 3).trim(); + String priority = line.substring(line.indexOf("

") + 3,line.indexOf("")).trim(); currTodo.setPriority(priority); tasks.add(currTodo); + String savedNotes = line.substring(line.indexOf("") + 3); + if (savedNotes.charAt(0) == '1'){ + savedNotes = savedNotes.substring(1); + String[] notesToBeAdded; + notesToBeAdded = savedNotes.split("@",0); + for (String item : notesToBeAdded) { + tasks.get(tasks.size() - 1).addNotes(item); + } + } } + /** * Adds an event into the list without generating messages, * to be used when loading from save data. @@ -98,6 +108,15 @@ static void loadEvent(String line, ArrayList tasks) { Event currEvent = new Event(description, start, end); currEvent.setPriority(priority); tasks.add(currEvent); + String savedNotes = line.substring(line.indexOf("") + 3); + if (savedNotes.charAt(0) == '1'){ + savedNotes = savedNotes.substring(1); + String[] notesToBeAdded; + notesToBeAdded = savedNotes.split("@",0); + for (String item : notesToBeAdded) { + tasks.get(tasks.size() - 1).addNotes(item); + } + } } static void loadRecurrEvent(String line, ArrayList tasks) { @@ -144,6 +163,15 @@ static void loadDeadline(String line, ArrayList tasks) { Deadline currDeadline = new Deadline(description, deadline); currDeadline.setPriority(priority); tasks.add(currDeadline); + String savedNotes = line.substring(line.indexOf("") + 3); + if (savedNotes.charAt(0) == '1'){ + savedNotes = savedNotes.substring(1); + String[] notesToBeAdded; + notesToBeAdded = savedNotes.split("@",0); + for (String item : notesToBeAdded) { + tasks.get(tasks.size() - 1).addNotes(item); + } + } } /** diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index e989b578db..5db4d4df6a 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -679,11 +679,11 @@ static void printNotes(ArrayList tasks, String []words) { int index = Integer.parseInt(words[1]); ArrayList toBePrinted = tasks.get(index-1).getAdditionalNotes(); borderLine(); - System.out.println("\tHere are the notes for that task quack!"); - System.out.println("\t\t" + tasks.get(index-1).toString()); + System.out.println("\t Here are the notes for that task quack!"); + System.out.println(tasks.get(index-1).toString()); if (!toBePrinted.isEmpty()) { for (int i = 0; i < toBePrinted.size(); i++) { - System.out.println("\t" + (i + 1) + ". " + toBePrinted.get(i)); + System.out.println("\t \t" + (i + 1) + ". " + toBePrinted.get(i)); } } else { System.out.println("\tThere are no notes for this task!"); diff --git a/src/main/java/seedu/duck/task/Deadline.java b/src/main/java/seedu/duck/task/Deadline.java index 2ab8e14a0d..08afc3027b 100644 --- a/src/main/java/seedu/duck/task/Deadline.java +++ b/src/main/java/seedu/duck/task/Deadline.java @@ -18,7 +18,7 @@ public String getDeadline() { @Override public String toSaveString() { - return super.toSaveString() + " /by " + getDeadline() + "

" + getPriorityIndex() + System.lineSeparator(); + return super.toSaveString() + " /by " + getDeadline() + "

" + getPriorityIndex() + " " + getSavedNotes() + System.lineSeparator(); } @Override diff --git a/src/main/java/seedu/duck/task/Event.java b/src/main/java/seedu/duck/task/Event.java index 7e36d028fd..1ece8fd64c 100644 --- a/src/main/java/seedu/duck/task/Event.java +++ b/src/main/java/seedu/duck/task/Event.java @@ -29,7 +29,7 @@ public void setEnd(String end) { @Override public String toSaveString() { return super.toSaveString() + " /from " + getStart() + " /to " + getEnd() + - "

" + getPriorityIndex() + System.lineSeparator(); + "

" + getPriorityIndex() + " " + getSavedNotes() + System.lineSeparator(); } @Override diff --git a/src/main/java/seedu/duck/task/Task.java b/src/main/java/seedu/duck/task/Task.java index 4a30343f24..6c9172c810 100644 --- a/src/main/java/seedu/duck/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -6,13 +6,12 @@ public class Task { private String description; private int priority; private boolean isDone; - private ArrayList additionalNotes; + private final ArrayList additionalNotes = new ArrayList(); public Task(String description) { this.description = description; this.isDone = false; this.priority = 1; //automatically set to low priority - this.additionalNotes = new ArrayList(); } public void setDescription(String description) { @@ -45,13 +44,20 @@ public String getStatusIcon() { } return " "; } - - public String savedNotes(){ + public String hasNotes(){ + if (additionalNotes.isEmpty()){ + return "0"; + } else { + return "1"; + } + } + public String getSavedNotes(){ String save = ""; + save += hasNotes(); for (int i = 0; i < additionalNotes.size(); i++){ - save += this.additionalNotes.get(i); + save += additionalNotes.get(i); if (!(i==additionalNotes.size()-1)) { - save += "||"; + save += "@"; } } return save; diff --git a/src/main/java/seedu/duck/task/Todo.java b/src/main/java/seedu/duck/task/Todo.java index 1f42a910da..cb94286ee2 100644 --- a/src/main/java/seedu/duck/task/Todo.java +++ b/src/main/java/seedu/duck/task/Todo.java @@ -8,7 +8,7 @@ public Todo(String description) { @Override public String toSaveString() { - return super.toSaveString() + "

" + getPriorityIndex() + System.lineSeparator(); + return super.toSaveString() + "

" + getPriorityIndex() + " " + getSavedNotes() + System.lineSeparator(); } @Override From 82b1f92cd8dd8815db36ee2e1a8051ad36ebb3d8 Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Sun, 2 Apr 2023 22:25:22 +0800 Subject: [PATCH 084/152] Added a function that prints a motivational quote whenever Duck is started up --- src/main/java/seedu/duck/Ui.java | 33 +++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 5db4d4df6a..77512b0a14 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -13,6 +13,7 @@ import java.util.Objects; import java.util.PriorityQueue; import java.util.Scanner; +import java.util.Random; /** @@ -38,6 +39,34 @@ static void printDuck(){ " `. _,'\n"+ " `-._________,--'"); } + static void printMotivationalQuote(){ + String[] quotes = { + "Believe you can and you're halfway there. -Theodore Roosevelt", + "Start where you are. Use what you have. Do what you can. -Arthur Ashe", + "You miss 100% of the shots you don't take. -Wayne Gretzky", + "Success is not final, failure is not fatal: it is the courage to continue that counts. -Winston Churchill", + "You are never too old to set another goal or to dream a new dream. -C.S. Lewis", + "Believe in yourself and all that you are. Know that there is something inside you that is greater than any obstacle. -Christian D. Larson", + "Success is not how high you have climbed, but how you make a positive difference to the world. -Roy T. Bennett", + "A journey of a thousand miles begins with a single step. -Lao Tzu", + "The only way to do great work is to love what you do. -Steve Jobs", + "You have brains in your head. You have feet in your shoes. You can steer yourself any direction you choose. -Dr. Seuss", + "Believe you can and you're halfway there. -Theodore Roosevelt", + "You never know how strong you are until being strong is your only choice. -Bob Marley", + "Do not wait for opportunities, create them. -Roy T. Bennett", + "Believe in yourself, take on your challenges, dig deep within yourself to conquer fears. Never let anyone bring you down. You got this. -Chantal Sutherland", + "The greatest glory in living lies not in never falling, but in rising every time we fall. -Nelson Mandela", + "Believe in your infinite potential. Your only limitations are those you set upon yourself. -Roy T. Bennett", + "What you get by achieving your goals is not as important as what you become by achieving your goals. -Zig Ziglar", + "Don't watch the clock; do what it does. Keep going. -Sam Levenson", + "Believe that you will succeed, and you will. -Dale Carnegie", + "Success is not the key to happiness. Happiness is the key to success. If you love what you are doing, you will be successful. -Albert Schweitzer" + }; + Random rand = new Random(); + int index = rand.nextInt(quotes.length); + System.out.println("\t Have some motivation! Quack!" + "\n"); + System.out.println("\t " + quotes[index]); + } /** * Prints out all currently stored tasks in the list @@ -667,6 +696,7 @@ static void invalidDateTimeMessage() { static void greetingMessage() { printDuck(); borderLine(); + printMotivationalQuote(); borderLine(); System.out.println("\t Quack! Nice to meet you human. As you can see, I'm a Duck."); System.out.println("\t As a Duck, I can only understand simple commands. Quack. " + @@ -686,7 +716,7 @@ static void printNotes(ArrayList tasks, String []words) { System.out.println("\t \t" + (i + 1) + ". " + toBePrinted.get(i)); } } else { - System.out.println("\tThere are no notes for this task!"); + System.out.println("\t There are no notes for this task!"); } borderLine(); } @@ -708,4 +738,5 @@ static void exitMessage() { borderLine(); } + } From cf742a99b77669039e9afc17448d41010b274832 Mon Sep 17 00:00:00 2001 From: tliangac Date: Mon, 3 Apr 2023 19:11:27 +0800 Subject: [PATCH 085/152] Add more function --- src/main/java/seedu/duck/Duck.java | 1 + src/main/java/seedu/duck/Parser.java | 23 ++++ src/main/java/seedu/duck/Ui.java | 181 +++++++++++++++++++++++++-- 3 files changed, 197 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/duck/Duck.java b/src/main/java/seedu/duck/Duck.java index 9276983437..0f229430fb 100644 --- a/src/main/java/seedu/duck/Duck.java +++ b/src/main/java/seedu/duck/Duck.java @@ -18,6 +18,7 @@ private static void runDuck() throws IOException { Storage.tryLoad(tasks, classes); TaskList.purge(tasks, classes); Ui.displayUpcomingDeadline(tasks); + Ui.displayUpcomingEvent(tasks); String line; Scanner in = new Scanner(System.in); line = in.nextLine(); diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 2c4e42a5fa..4cbd51bab2 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -56,6 +56,20 @@ static void processCommand(ArrayList tasks, PriorityQueue cla Ui.unknownCommandMessage(); } break; + case "event": + if(words.length==2 && isNumeric(words[1])){ + Ui.printUpcomingEvents(tasks,words[1]); + } else{ + Ui.unknownCommandMessage(); + } + break; + case "deadline": + if(words.length==2 && isNumeric(words[1])){ + Ui.printUpcomingDeadline(tasks,words[1]); + } else{ + Ui.unknownCommandMessage(); + } + break; case "list_today": Ui.listToday(tasks, classes); break; @@ -80,6 +94,15 @@ static void processCommand(ArrayList tasks, PriorityQueue cla case "upcoming_class": Ui.displayNextUpcomingClass(classes); break; + case "upcoming_event": + Ui.displayNextUpcomingEvent(tasks); + break; + case "upcoming_deadline": + Ui.displayNextUpcomingDeadline(tasks); + break; + case "upcoming_task": + Ui.displayNextUpcomingTask(tasks); + break; case "unmark": if (words.length == 2 && isNumeric(words[1])) { TaskList.unmarkTask(tasks, words); diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index fb13999b66..50eab5548a 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -63,7 +63,7 @@ static void listClasses(PriorityQueue classes, ArrayList task borderLine(); System.out.println("\t Here is your class schedule:\n"); while (iterator.hasNext()) { - System.out.println("\t"+iterator.next()); + System.out.println("\t" + iterator.next()); } borderLine(); } @@ -285,7 +285,7 @@ static void printMatchingList(ArrayList matchingResults, int matchCount, static void displayUpcomingDeadline(ArrayList tasks) { System.out.println("\t Here are the upcoming deadline: "); int count = 0; - for (Task t:tasks) { + for (Task t : tasks) { if (t instanceof Deadline && !(t instanceof RecurringDeadline)) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); String deadline = ((Deadline) t).getDeadline(); @@ -295,7 +295,7 @@ static void displayUpcomingDeadline(ArrayList tasks) { d = format.parse(deadline); long diff = d.getTime() - n.getTime(); String di = getTimeDiff(diff); - String description = t.getDescription().replace("deadline ", ""); + String description = t.getDescription().replace("Deadlines", ""); System.out.println("\t " + (count + 1) + "." + description + " (" + di + "before the deadline)"); count++; } catch (ParseException e) { @@ -306,6 +306,35 @@ static void displayUpcomingDeadline(ArrayList tasks) { borderLine(); } + /** + * Display upcoming event + * + * @param tasks tasks store in the file + */ + static void displayUpcomingEvent(ArrayList tasks) { + System.out.println("\t Here are the upcoming event: "); + int count = 0; + for (Task t : tasks) { + if (t instanceof Event && !(t instanceof RecurringEvent)) { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); + String deadline = ((Event) t).getStart(); + Date d; + Date n = new Date(); + try { + d = format.parse(deadline); + long diff = d.getTime() - n.getTime(); + String di = getTimeDiff(diff); + String description = t.getDescription().replace("Events", ""); + System.out.println("\t " + (count + 1) + "." + description + " (" + di + "before the event start)"); + count++; + } catch (ParseException e) { + e.printStackTrace(); + } + } + } + borderLine(); + } + /** * Prints the list of tasks in x days in the future * @@ -319,7 +348,7 @@ static void printUpcomingTasks(ArrayList tasks, String days) { Date d; Date n = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); - for (Task t:tasks) { + for (Task t : tasks) { String timeUntilTask = null; if (t instanceof Deadline && !(t instanceof RecurringDeadline)) { timeUntilTask = ((Deadline) t).getDeadline(); @@ -348,6 +377,88 @@ static void printUpcomingTasks(ArrayList tasks, String days) { borderLine(); } + /** + * Prints the list of events in x days in the future + * + * @param tasks the array list of all the tasks + * @param days the required the number of days x from now onwards + */ + static void printUpcomingEvents(ArrayList tasks, String days) { + borderLine(); + System.out.println("\t Here are your events in " + days + " days:"); + int count = 0; + Date d; + Date n = new Date(); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); + boolean noEvent = true; + for (Task t:tasks) { + String timeUntilTask; + if (t instanceof Event && !(t instanceof RecurringEvent)) { + noEvent = false; + timeUntilTask = ((Event) t).getStart(); + try { + d = format.parse(timeUntilTask); + long diff = d.getTime() - n.getTime(); + String di = getTimeDiff(diff); + String[] diffSplit = di.split(" "); + if (diffSplit.length >= 2 && ((diffSplit[1].contains("day") && Integer.parseInt(diffSplit[0]) + <= Integer.parseInt(days)) || diffSplit[1].contains("hour") + || diffSplit[1].contains("minute"))) { + count++; + System.out.println("\t " + count + "." + t); + } + } catch (ParseException e) { + e.printStackTrace(); + } + } + } + if (noEvent) { + System.out.println("\t No Upcoming Events!"); + } + borderLine(); + } + + /** + * Prints the list of deadlines in x days in the future + * + * @param tasks the array list of all the tasks + * @param days the required the number of days x from now onwards + */ + static void printUpcomingDeadline(ArrayList tasks, String days) { + borderLine(); + System.out.println("\t Here are your deadlines in " + days + " days:"); + int count = 0; + Date d; + Date n = new Date(); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); + boolean noDeadline = true; + for (Task t:tasks) { + String timeUntilTask; + if (t instanceof Deadline && !(t instanceof RecurringDeadline)) { + noDeadline = false; + timeUntilTask = ((Deadline) t).getDeadline(); + try { + d = format.parse(timeUntilTask); + long diff = d.getTime() - n.getTime(); + String di = getTimeDiff(diff); + String[] diffSplit = di.split(" "); + if (diffSplit.length >= 2 && ((diffSplit[1].contains("day") && Integer.parseInt(diffSplit[0]) + <= Integer.parseInt(days)) || diffSplit[1].contains("hour") + || diffSplit[1].contains("minute"))) { + count++; + System.out.println("\t " + count + "." + t); + } + } catch (ParseException e) { + e.printStackTrace(); + } + } + } + if (noDeadline) { + System.out.println("\t No Upcoming Deadline!"); + } + borderLine(); + } + /** * Function help for calculating time difference * @@ -407,24 +518,78 @@ static String getTimeDiff(long timeDifferenceMilliseconds) { /** * Display Next Upcoming Class * - * @param classes the array list of all the tasks + * @param classes the priority queue of all the classes */ static void displayNextUpcomingClass(PriorityQueue classes) { borderLine(); ArrayList result = new ArrayList<>(classes); System.out.println("\t Here are your next upcoming class: "); if (result.isEmpty()) { - System.out.println("\t \t No upcoming class!"); + System.out.println("\t No upcoming class!"); } else { - for (SchoolClass c:result) { + for (SchoolClass c : result) { if (c.getStatusIcon() != "X") { - System.out.println("\t"+c); + System.out.println("\t" + c); } } } borderLine(); } + /** + * Display Next Upcoming Event + * + * @param tasks the array list of all the tasks + */ + static void displayNextUpcomingEvent(ArrayList tasks) { + borderLine(); + System.out.println("\t Here are your next upcoming event: "); + for (int i = 0; i < tasks.size(); i++) { + if (tasks.get(i) instanceof Event && tasks.get(i).getStatusIcon()!="X") { + System.out.println("\t " + tasks.get(i)); + break; + } else if (i == tasks.size() - 1) { + System.out.println("\t No upcoming event!"); + } + } + borderLine(); + } + + /** + * Display Next Upcoming Deadline + * + * @param tasks the array list of all the tasks + */ + static void displayNextUpcomingDeadline(ArrayList tasks) { + borderLine(); + System.out.println("\t Here are your next upcoming event: "); + for (int i = 0; i < tasks.size(); i++) { + if (tasks.get(i) instanceof Deadline && tasks.get(i).getStatusIcon()!="X") { + System.out.println("\t" + tasks.get(i)); + break; + } else if (i == tasks.size() - 1) { + System.out.println("\t No upcoming deadline!"); + } + } + borderLine(); + } + + /** + * Display Next Upcoming Task + * + * @param tasks the array list of all the tasks + */ + static void displayNextUpcomingTask(ArrayList tasks) { + borderLine(); + System.out.println("\t Here are your next upcoming event: "); + if (tasks.isEmpty()) { + System.out.println("\t no upcoming task"); + } else { + System.out.println("\t" + tasks.get(0)); + } + borderLine(); + } + /** * Prints the border for opening or closing messages */ From 6419319ade6f8ff1ee234e5cc8b4e3e26e3e3df5 Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Mon, 3 Apr 2023 21:15:27 +0800 Subject: [PATCH 086/152] Addressed bugs from PED --- docs/UserGuide.md | 3 ++- src/main/java/seedu/duck/Parser.java | 13 ++++----- src/main/java/seedu/duck/TaskList.java | 33 ++++++++++++++--------- src/main/java/seedu/duck/Ui.java | 37 +++++++++++++++----------- 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index db78f63f43..932e9e0281 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -313,7 +313,8 @@ Bring own recyclable bag ``` ## **Print notes for a specific task : `delete_note`** -Deletes the +Deletes the specified note for the task + **Input:** `delete_note ` **Output: Demonstrated below to delete 1 task** diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 0534c2f2e4..9ddb2007fa 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -41,10 +41,11 @@ public static boolean isNumeric(String word) { */ static void processCommand(ArrayList tasks, PriorityQueue classes, String line, Scanner in) throws IOException { while (!line.trim().equals("bye")) { + line = line.trim().replaceAll("\\s{2,}", " "); String[] words = line.split(" "); - line = line.trim(); if (line.isBlank()) { Ui.emptyCommandMessage(); + line = in.nextLine(); } else { switch (words[0]) { case "list": @@ -138,7 +139,7 @@ static void processCommand(ArrayList tasks, PriorityQueue cla Ui.unknownCommandMessage(); } break; - case "add_note": + case "add_notes": if(words.length == 2 && isNumeric(words[1])){ TaskList.addNote(tasks, words); Storage.trySave(tasks, classes); @@ -146,7 +147,7 @@ static void processCommand(ArrayList tasks, PriorityQueue cla Ui.unknownCommandMessage(); } break; - case "delete_note": + case "delete_notes": if(words.length == 3){ TaskList.deleteNotes(tasks,words); Storage.trySave(tasks, classes); @@ -161,7 +162,7 @@ static void processCommand(ArrayList tasks, PriorityQueue cla Ui.unknownCommandMessage(); } break; - case "edit_note": + case "edit_notes": if(words.length == 3){ TaskList.editNote(tasks, words); Storage.trySave(tasks, classes); @@ -189,7 +190,7 @@ static void processCommand(ArrayList tasks, PriorityQueue cla default: TaskList.addTask(line, tasks, classes); Storage.trySave(tasks, classes); - + break; } line = in.nextLine(); } @@ -211,4 +212,4 @@ static String processKeywords(String[] words,int index) { String keyword = rawKeyword.trim(); return keyword; } -} +} \ No newline at end of file diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 156d153fcd..0f7e2f64a5 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -120,17 +120,24 @@ static void addTodo(String line, ArrayList tasks) throws IllegalTodoExcept * @param tasks The array list of tasks */ static void setPriority(ArrayList tasks, String[] words) { - int taskNumber = Integer.parseInt(words[1]); - int taskCount = Task.getTaskCount(); - if (taskNumber > taskCount || taskNumber < 0) { - // Input task number exceeds the number of tasks in the list - Ui.exceedTaskNumberMessage(taskNumber); + words[1] = words[1].trim(); + if (!words[1].equals("1")||!words[1].equals("2")||!words[1].equals("3")) { + int taskNumber = Integer.parseInt(words[1]); + int taskCount = Task.getTaskCount(); + if (taskNumber > taskCount || taskNumber <= 0) { + // Input task number exceeds the number of tasks in the list + Ui.exceedTaskNumberMessage(taskNumber); + } else { + tasks.get(taskNumber - 1).setPriority(words[2]); + // Printing out marked as done message + Ui.borderLine(); + System.out.println("\t Understood. The task's new priority is:"); + System.out.println("\t " + tasks.get(taskNumber - 1).getPriority()); + Ui.borderLine(); + } } else { - tasks.get(taskNumber - 1).setPriority(words[2]); - // Printing out marked as done message Ui.borderLine(); - System.out.println("\t Understood. The task's new priority is:"); - System.out.println("\t " + tasks.get(taskNumber - 1).getPriority()); + System.out.println("\t Please enter a priority from 1 to 3!"); Ui.borderLine(); } } @@ -270,7 +277,7 @@ static void addRecurrDeadline(String line, ArrayList tasks) throws Illegal static void markTask(ArrayList tasks, String[] words) { int taskNumber = Integer.parseInt(words[1]); int taskCount = Task.getTaskCount(); - if (taskNumber > taskCount || taskNumber < 0) { + if (taskNumber > taskCount || taskNumber <= 0) { // Input task number exceeds the number of tasks in the list Ui.exceedTaskNumberMessage(taskNumber); } else { @@ -292,7 +299,7 @@ static void markTask(ArrayList tasks, String[] words) { static void unmarkTask(ArrayList tasks, String[] words) { int taskNumber = Integer.parseInt(words[1]); int taskCount = Task.getTaskCount(); - if (taskNumber > taskCount || taskNumber < 0) { + if (taskNumber > taskCount || taskNumber <= 0) { // Input task number exceeds the number of tasks in the list Ui.exceedTaskNumberMessage(taskNumber); } else { @@ -316,7 +323,7 @@ static void editTask(ArrayList tasks, String[] words) throws expiredDateEx int taskCount = Task.getTaskCount(); DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("HHmm"); DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); - if (taskNumber > taskCount) { + if (taskNumber > taskCount || taskNumber <= 0) { Ui.exceedTaskNumberMessage(taskNumber); return; } @@ -470,7 +477,7 @@ static void tryEditTask(ArrayList tasks, String[] words) { static void deleteTask(ArrayList tasks, String[] words) { int taskNumber = Integer.parseInt(words[1]); int taskCount = Task.getTaskCount(); - if (taskNumber > taskCount || taskNumber < 0) { + if (taskNumber > taskCount || taskNumber <= 0) { // Input task number exceeds the number of tasks in the list Ui.exceedTaskNumberMessage(taskNumber); } else { diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 77512b0a14..d5b25f0bcf 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -2,6 +2,7 @@ import seedu.duck.task.*; +import java.sql.SQLOutput; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.DayOfWeek; @@ -472,6 +473,7 @@ static boolean doubleCheck() { Scanner in = new Scanner(System.in); String line; line = in.nextLine(); + line = line.toUpperCase(); return Objects.equals(line, "Y"); } @@ -519,8 +521,8 @@ static void help() { System.out.println("\t Quack! Here are the commands you can give me:"); System.out.println("\t - list: I'll list out all the tasks you have recorded."); System.out.println("\t - list : I'll list out all the tasks in that number of days."); - System.out.println("\t - list classes: I'll list out the classes you have on your schedule."); - System.out.println("\t - list today: I'll list out all the classes, deadlines and events you have today."); + System.out.println("\t - list_classes: I'll list out the classes you have on your schedule."); + System.out.println("\t - list_today: I'll list out all the classes, deadlines and events you have today."); System.out.println("\t - priority_list: " + "I'll list out all the tasks you have recorded arranged by their priority."); System.out.println("\t - low_priority: I'll list out all the tasks you have that are low in priority."); @@ -534,12 +536,13 @@ static void help() { "/day /from /to "); System.out.println("\t (/description can be followed by whitespace if the class has no description."); System.out.println("\t : I'll remove this class from your class schedule."); - System.out.println("\t - add_note : I'll add an additional note to that task!" ); - System.out.println("\t - delete_note : I'll delete the note to that task!" ); - System.out.println("\t - edit_note : I'll edit the note for that task!" ); + System.out.println("\t - add_notes : I'll add an additional note to that task!" ); + System.out.println("\t - delete_notes : I'll delete the note to that task!" ); + System.out.println("\t - edit_notes : I'll edit the note for that task!" ); System.out.println("\t - view_notes : I'll print the additional notes for that task!" ); System.out.println("\t - purge: I'll delete all expired tasks from your list after a confirmation."); System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); + System.out.println("\t - The index of the item will also be displayed."); System.out.println("\t - priority <1/2/3>: I'll set the priority of a given task as"); System.out.println("\t 1:Low, 2:Medium and 3:High."); System.out.println("\t Default: Low priority."); @@ -707,18 +710,22 @@ static void greetingMessage() { } static void printNotes(ArrayList tasks, String []words) { int index = Integer.parseInt(words[1]); - ArrayList toBePrinted = tasks.get(index-1).getAdditionalNotes(); - borderLine(); - System.out.println("\t Here are the notes for that task quack!"); - System.out.println(tasks.get(index-1).toString()); - if (!toBePrinted.isEmpty()) { - for (int i = 0; i < toBePrinted.size(); i++) { - System.out.println("\t \t" + (i + 1) + ". " + toBePrinted.get(i)); - } + if(index > tasks.size() || index <= 0) { + Ui.exceedTaskNumberMessage(index); } else { - System.out.println("\t There are no notes for this task!"); + ArrayList toBePrinted = tasks.get(index-1).getAdditionalNotes(); + borderLine(); + if (!toBePrinted.isEmpty()) { + for (int i = 0; i < toBePrinted.size(); i++) { + System.out.println("\t Here are the notes for that task quack!"); + System.out.println(tasks.get(index - 1).toString()); + System.out.println("\t \t" + (i + 1) + ". " + toBePrinted.get(i)); + } + } else { + System.out.println("\t There are no notes for this task!"); + } + borderLine(); } - borderLine(); } static void printList(ArrayList tasks,int index){ From 0ac3f65d32abb34b3a7c359c5c22411016f968da Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Tue, 4 Apr 2023 15:42:55 +0800 Subject: [PATCH 087/152] Create jeraldgau.md --- docs/team/jeraldgau.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 docs/team/jeraldgau.md diff --git a/docs/team/jeraldgau.md b/docs/team/jeraldgau.md new file mode 100644 index 0000000000..0c04d855e9 --- /dev/null +++ b/docs/team/jeraldgau.md @@ -0,0 +1,17 @@ +# Jerald Gau - Project Portfolio Page + +## Overview + +Duck is a desktop task and class tracker for users to keep track of their schedule and the things they have to do. The user interacts with it using the CLI. It is written in Java, and has about 3.5kLoc. + +
+ +## Summary of Contributions + +### Base Code: Contributed code from iP Duke bot to serve as a base to work upon. +- Justification: Duck is an improved version of the Duke bot, building upon the pre-existing functionality of Duke with enhanced features like date/time tracking, as well as a new school class scheduler. As such, it made sense to reuse code from the iP and add in features from there. + +
+ +### New Feature: Implementation of the School Class Task +- From c58e3835be3dee8979e2ba48e9bdbfd563892a95 Mon Sep 17 00:00:00 2001 From: thant Date: Tue, 4 Apr 2023 15:49:38 +0800 Subject: [PATCH 088/152] Update UserGuide.md --- docs/UserGuide.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index f14f8dc94a..58a8887b0a 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -72,9 +72,9 @@ Displays all tasks currently stored in the application. ``` Here are the tasks in your list: - 1. [T][ ] todo (No priority established.) - 2. [D][ ] deadline (by: 2023-03-25 2359) (No priority established.) - 3. [E][ ] event (from: 2023-03-25 1200 to: 2023-03-26 2359) (No priority established.) + 1. [T][ ] todo (Low priority.) + 2. [D][ ] deadline (by: 2023-03-25 2359) (Low priority.) + 3. [E][ ] event (from: 2023-03-25 1200 to: 2023-03-26 2359) (Low priority.) ``` ## **Listing all tasks and classes happening today : `list_today`** @@ -92,10 +92,10 @@ Displays all deadlines, events and classes happening today. [WEDNESDAY][X] cs2113 (from: 1200 to: 1300) Here are your tasks today - [D][ ] sleep (by: 2023-03-29 2000) (No priority established.) - [D][ ] shower (by: 2000) (every WEDNESDAY) (No priority established.) - [E][ ] study (from: 2023-03-29 2100 to: 2023-04-23 2300) (No priority established.) - [E][ ] study (from: 0800 to: 2300) (every WEDNESDAY) (No priority established.) + [D][ ] sleep (by: 2023-03-29 2000) (Low priority.) + [D][ ] shower (by: 2000) (every WEDNESDAY) (Low priority.) + [E][ ] study (from: 2023-03-29 2100 to: 2023-04-23 2300) (Low priority.) + [E][ ] study (from: 0800 to: 2300) (every WEDNESDAY) (Low priority.) ____________________________________________________________ ``` ## **Displaying upcoming deadline** @@ -238,7 +238,7 @@ For instance list 0returns all tasks that are star ``` Here are your tasks in 0 days: - 1. [E][ ] event (from: 2023-03-25 1200 to: 2023-03-26 2359) (No priority established.) + 1. [E][ ] event (from: 2023-03-25 1200 to: 2023-03-26 2359) (Low priority.) 2. [D][ ] Submit CS2113 quiz (by: 2023-03-31 2359) (Low priority.) ``` @@ -255,7 +255,7 @@ Marks a task from the tasklist as complete. ``` Understood. I've marked this task as done: - [T][X] todo (No priority established.) + [T][X] todo (Low priority.) ``` @@ -271,7 +271,7 @@ Unmarks a task from the tasklist as not complete. ``` Understood. I've marked this task as not done yet: - [T][ ] todo (No priority established.) + [T][ ] todo (Low priority.) ``` ## **Editing a task : `edit `** @@ -312,7 +312,7 @@ Removes a task from the tasklist. ``` Understood. I have removed this task: - [T][ ] todo (No priority established.) + [T][ ] todo (Low priority.) You now have 3 tasks in your list. ``` @@ -438,7 +438,7 @@ Prompts the user for confirmation. Proceeds to remove all expired tasks from sto ``` Displaying all expired tasks below... - [D][ ] deadline (by: 2023-03-24 1100) (No priority established.) + [D][ ] deadline (by: 2023-03-24 1100) (Low priority.) ____________________________________________________________ Quack! A total of 1 task has expired! Should I remove these tasks from the pending list human? @@ -490,7 +490,7 @@ Traverses through the stored tasks to return all tasks that contain the keyword ``` Here are the matching tasks in your list: -1. [T][ ] todo (No priority established.) +1. [T][ ] todo (Low priority.) ``` @@ -506,7 +506,7 @@ Adds a ToDo task to the storage of Duck ``` Alright, I have added this task: - [T][ ] todo (No priority established.) + [T][ ] todo (Low priority.) You now have 2 tasks in your list. ``` @@ -523,7 +523,7 @@ Adds a Deadline task to the storage of Duck ``` Alright, I have added this task: - [D][ ] deadline (by: 2023-03-25 2359) (No priority established.) + [D][ ] deadline (by: 2023-03-25 2359) (Low priority.) You now have 3 tasks in your list. ``` @@ -554,7 +554,7 @@ Adds an Event task to the storage of Duck ``` Alright, I have added this task: - [E][ ] event (from: 2023-03-25 2359 to: 2023-03-26 1100) (No priority established.) + [E][ ] event (from: 2023-03-25 2359 to: 2023-03-26 1100) (Low priority.) You now have 5 tasks in your list. ``` @@ -569,7 +569,7 @@ Adds a RecurringEvent task to the storage of Duck ``` Alright, I have added this task: - [E][ ] new_event (from: 2000 to: 2300) (every MONDAY) (No priority established.) + [E][ ] new_event (from: 2000 to: 2300) (every MONDAY) (Low priority.) You now have 6 tasks in your list. ``` From f43e41ebfea3b398bff69ffabf024c500e35384a Mon Sep 17 00:00:00 2001 From: thant Date: Tue, 4 Apr 2023 15:52:32 +0800 Subject: [PATCH 089/152] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 58a8887b0a..e82fa9dcfe 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -490,7 +490,7 @@ Traverses through the stored tasks to return all tasks that contain the keyword ``` Here are the matching tasks in your list: -1. [T][ ] todo (Low priority.) +1. [T][ ] todo (Low priority.) || The index of this item is 1 ``` From 73da2e6eae8dd46ed47a4f1d56e586c923bf7eed Mon Sep 17 00:00:00 2001 From: thant Date: Tue, 4 Apr 2023 15:54:01 +0800 Subject: [PATCH 090/152] Update UserGuide.md --- docs/UserGuide.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index e82fa9dcfe..e1f061da0a 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -372,15 +372,9 @@ Bring own recyclable bag ____________________________________________________________ ``` -<<<<<<< HEAD ## **Deleting notes for a specific task : `delete_note`** -Deletes the -======= -## **Print notes for a specific task : `delete_note`** Deletes the specified note for the task ->>>>>>> Print-By-Priority - **Input:** `delete_note ` **Output: Demonstrated below to delete 1 task** From a1d0e01d5a83a323ee11aad6fc2b8512ac6dce19 Mon Sep 17 00:00:00 2001 From: thant Date: Tue, 4 Apr 2023 16:37:50 +0800 Subject: [PATCH 091/152] Update Task.java --- src/main/java/seedu/duck/task/Task.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/seedu/duck/task/Task.java b/src/main/java/seedu/duck/task/Task.java index 050b9f1877..76f344e262 100644 --- a/src/main/java/seedu/duck/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -12,10 +12,6 @@ public Task(String description) { this.description = description; this.isDone = false; this.priority = 1; //automatically set to low priority -<<<<<<< HEAD - this.additionalNotes = new ArrayList<>(); -======= ->>>>>>> Print-By-Priority } public void setDescription(String description) { From c74dc874000ac57d0d22f29e390360359310bd42 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Tue, 4 Apr 2023 16:56:35 +0800 Subject: [PATCH 092/152] Update jeraldgau.md --- docs/team/jeraldgau.md | 51 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/docs/team/jeraldgau.md b/docs/team/jeraldgau.md index 0c04d855e9..7b3101bd44 100644 --- a/docs/team/jeraldgau.md +++ b/docs/team/jeraldgau.md @@ -13,5 +13,52 @@ Duck is a desktop task and class tracker for users to keep track of their schedu
-### New Feature: Implementation of the School Class Task -- +### New Feature: Implementation of the ```SchoolClass``` Task +- Added a new Task class called SchoolClass, which are added to a separate list from the other tasks to facilitate schedule tracking +- Revamped how saving and loading from savefile works from the iP base code, in order to account for the new SchoolClass Task. The saving and loading of task priorities was also tweaked in order for it to work with adding SchoolClasses to the savefile. + +
+ +### New Feature: Class schedule with automatic time tracking +- SchoolClasses will be added to a separate list which automatically sorts them based on their registered day of week, and starting/ending time. +- The SchoolClasses will be automatically marked as done when the current time is past their registered ending time, and their done status will be reset to not done at the start of a new week. + +
+ +### New Feature: ```list_classes``` +- Displays all the currently registered SchoolClasses saved in Duck, and lists them out based on their day of week, starting and ending time. +- Shows whether the class is over for the week, with a "done" marker [X] shown on the left of each class. + +
+ +### New Feature: Adding a SchoolClass +- By following the specified format as indicated in the User Guide, users will be able to add SchoolClasses to their schedule. +- The added SchoolClasses will be saved to the savefile, which will be loaded upon starting up Duck again. + +
+ +### New Feature: Removing a SchoolClass +- By Following the specified format as indicated in the User Guide, users will be able to remove unwanted SchoolClasses from their schedule. + +
+ +### Code Contributed: [RepoSense Link](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=jeraldgau&breakdown=true&sort=groupTitle%20dsc&sortWithin=title&since=2023-02-17&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other) + +
+ +### Project Management: +- Managed the releases ```v1.0``` - ```v2.0``` (2 releases) on GitHub + +
+ +### Documentation: +- User Guide: + - Added documentation for the features ```list_classes```, ```remove class``` and ```Adding a School Class``` + +- Developer Guide: + - Added design and implementation details of the SchoolClass feature + +
+ +### Community: +- Reported bugs and suggestions for other teams (examples: [1](https://github.com/jeraldgau/ped/issues/9), [2](https://github.com/jeraldgau/ped/issues/7), [3](https://github.com/jeraldgau/ped/issues/5)) From 35baf3d0b90bd9a8ac4c6293eb325382ead35cd8 Mon Sep 17 00:00:00 2001 From: sunkyan Date: Tue, 4 Apr 2023 17:22:10 +0800 Subject: [PATCH 093/152] Fixed bugs in TaskList#setPriority and changed invalidDateTimeMessage --- src/main/java/seedu/duck/TaskList.java | 10 ++++------ src/main/java/seedu/duck/Ui.java | 8 +++++++- src/main/java/seedu/duck/task/Task.java | 4 ---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 31a6117e00..39be7b740f 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -113,6 +113,7 @@ static void addTodo(String line, ArrayList tasks) throws IllegalTodoExcept Ui.addedTaskMessage(currTodo); } } + /** * Sets a priority to the specified task * @@ -120,8 +121,9 @@ static void addTodo(String line, ArrayList tasks) throws IllegalTodoExcept * @param tasks The array list of tasks */ static void setPriority(ArrayList tasks, String[] words) { - words[1] = words[1].trim(); - if (!words[1].equals("1")||!words[1].equals("2")||!words[1].equals("3")) { + if (!words[2].equals("1") && !words[2].equals("2") && !words[2].equals("3")) { + Ui.priorityErrorMessage(); + } else { int taskNumber = Integer.parseInt(words[1]); int taskCount = Task.getTaskCount(); if (taskNumber > taskCount || taskNumber <= 0) { @@ -135,10 +137,6 @@ static void setPriority(ArrayList tasks, String[] words) { System.out.println("\t " + tasks.get(taskNumber - 1).getPriority()); Ui.borderLine(); } - } else { - Ui.borderLine(); - System.out.println("\t Please enter a priority from 1 to 3!"); - Ui.borderLine(); } } diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index ed2266419a..0d2114fbb1 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -853,6 +853,12 @@ static void emptyDayErrorMessage() { borderLine(); } + static void priorityErrorMessage() { + Ui.borderLine(); + System.out.println("\t Please enter a priority from 1 to 3!"); + Ui.borderLine(); + } + static void invalidRemoveClassMessage() { borderLine(); System.out.println("\t Error. Please follow the correct format to remove classes."); @@ -862,7 +868,7 @@ static void invalidRemoveClassMessage() { static void invalidDateTimeMessage() { borderLine(); System.out.println("\t Please check the inputted format human!\n" + - "\t There are only 24 hours in a day in Duck World, and 12 months a year...\n"); + "\t Try typing 'help' if you are not sure what the correct format is!\n"); System.out.println("\t Please try again!"); borderLine(); } diff --git a/src/main/java/seedu/duck/task/Task.java b/src/main/java/seedu/duck/task/Task.java index 050b9f1877..76f344e262 100644 --- a/src/main/java/seedu/duck/task/Task.java +++ b/src/main/java/seedu/duck/task/Task.java @@ -12,10 +12,6 @@ public Task(String description) { this.description = description; this.isDone = false; this.priority = 1; //automatically set to low priority -<<<<<<< HEAD - this.additionalNotes = new ArrayList<>(); -======= ->>>>>>> Print-By-Priority } public void setDescription(String description) { From 4acce5c3522b612770caedf8fcd2664611ee0d7f Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Wed, 5 Apr 2023 00:23:43 +0800 Subject: [PATCH 094/152] Update jeraldgau.md --- docs/team/jeraldgau.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/team/jeraldgau.md b/docs/team/jeraldgau.md index 7b3101bd44..0c3bb3e09f 100644 --- a/docs/team/jeraldgau.md +++ b/docs/team/jeraldgau.md @@ -14,7 +14,8 @@ Duck is a desktop task and class tracker for users to keep track of their schedu
### New Feature: Implementation of the ```SchoolClass``` Task -- Added a new Task class called SchoolClass, which are added to a separate list from the other tasks to facilitate schedule tracking +- Added a new Task class called SchoolClass, which are added to a separate list from the other tasks to facilitate schedule tracking. +- Makes use of the jave.time package for registering valid start/end timings, as well as java.time.DayOfWeek to register valid days in a week. This facilitates the time tracking feature. - Revamped how saving and loading from savefile works from the iP base code, in order to account for the new SchoolClass Task. The saving and loading of task priorities was also tweaked in order for it to work with adding SchoolClasses to the savefile.
From 05fc14db126c2509f0b55937260622e6db01bda2 Mon Sep 17 00:00:00 2001 From: tliangac Date: Wed, 5 Apr 2023 18:34:03 +0800 Subject: [PATCH 095/152] Update UG Guide --- docs/UserGuide.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index e1f061da0a..ebb11c6d28 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -12,6 +12,8 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * [Displaying upcoming deadline](#displaying-upcoming-deadline) * [Displaying class schedule :](#displaying-class-schedule--list-classes) `list_classes` * [Displaying upcoming class :](#displaying-upcoming-class--upcomingclass) `upcoming_class` + * [Displaying upcoming deadline :](#displaying-upcoming-class--upcomingdeadline) `upcoming_deadline` + * [Displaying_upcoming_event :](#displaying-upcoming-event--upcomingevent) `upcoming_event` * [Mark a specified task as done :](#marking-a-task--mark-task_number) `mark ` * [Unmark a specified task as not done :](#unmarking-a-task--unmark-task_number) `unmark ` * [Edit a specific piece information of a task :](#editing-a-task--edit-task_number) `edit ` @@ -140,7 +142,35 @@ Here is your next upcoming class: [TUESDAY][ ] cs2113 (from: 1600 to: 1700) ``` +## **Displaying upcoming class : `upcoming_deadline`** +Displays the next upcoming deadline stored in the application. + +**Input:** `upcoming_deadline` + +**Output: The next upcoming deadline with names and due time** + + +``` +Here are your next upcoming event: + [D][ ] Deadlines Eat bread (by: 2023-04-05 2015) (Medium priority.) + +``` + +## **Displaying upcoming event : `upcoming_event`** + +Displays the next upcoming event stored in the application. + +**Input:** `upcoming_event` + +**Output: The next upcoming event with names and start/end time** + + +``` +Here are your next upcoming event: + [E][ ] Meeting (from: 2023-04-15 2015 to: 2023-04-15 2215) (Low priority.) + +``` ## **Listing all low priority tasks : `low_priority`** Displays all tasks that have been assigned low priority From 77b745ca428d2ac3f5fcdb9dd869c76c205eff48 Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Wed, 5 Apr 2023 18:40:30 +0800 Subject: [PATCH 096/152] Added Javadoc --- src/main/java/seedu/duck/TaskList.java | 1 + src/main/java/seedu/duck/Ui.java | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 39be7b740f..7c18ba5354 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -447,6 +447,7 @@ static void editTask(ArrayList tasks, String[] words) throws expiredDateEx /** * tries editTask and handles exceptions + * * @param tasks The array list of tasks * @param words The array of words generated from the user input */ diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 0d2114fbb1..943e2e1b8e 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -889,6 +889,12 @@ static void greetingMessage() { System.out.println("\t How may I assist you today, human?"); } + /** + * Prints out the notes of the task whose index was taken in + * + * @param tasks The arraylist of tasks + * @param words The index of the task + */ static void printNotes(ArrayList tasks, String[] words) { int index = Integer.parseInt(words[1]); if(index > tasks.size() || index <= 0) { From f94e6daac17578c60bb17737591e8a51a285c8e2 Mon Sep 17 00:00:00 2001 From: tliangac Date: Wed, 5 Apr 2023 19:24:10 +0800 Subject: [PATCH 097/152] Fix Magic Number --- src/main/java/seedu/duck/Ui.java | 41 +++++++++++++++++++------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 0d2114fbb1..a09800269c 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -2,7 +2,6 @@ import seedu.duck.task.*; -import java.sql.SQLOutput; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.DayOfWeek; @@ -40,7 +39,8 @@ static void printDuck() { " `. _,'\n" + " `-._________,--'"); } - static void printMotivationalQuote(){ + + static void printMotivationalQuote() { String[] quotes = { "Believe you can and you're halfway there. -Theodore Roosevelt", "Start where you are. Use what you have. Do what you can. -Arthur Ashe", @@ -421,7 +421,7 @@ static void printUpcomingEvents(ArrayList tasks, String days) { Date n = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); boolean noEvent = true; - for (Task t:tasks) { + for (Task t : tasks) { String timeUntilTask; if (t instanceof Event && !(t instanceof RecurringEvent)) { noEvent = false; @@ -462,7 +462,7 @@ static void printUpcomingDeadline(ArrayList tasks, String days) { Date n = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); boolean noDeadline = true; - for (Task t:tasks) { + for (Task t : tasks) { String timeUntilTask; if (t instanceof Deadline && !(t instanceof RecurringDeadline)) { noDeadline = false; @@ -489,6 +489,12 @@ static void printUpcomingDeadline(ArrayList tasks, String days) { borderLine(); } + static final int secondsPerMinute = 60; + static final int minutesPerHour = 60; + static final int hoursPerDay = 24; + static final double daysPerMonth = 30.41666666; + static final int monthsPerYear = 12; + /** * Function help for calculating time difference * @@ -496,11 +502,12 @@ static void printUpcomingDeadline(ArrayList tasks, String days) { * @return time difference in structured format */ static String getTimeDiff(long timeDifferenceMilliseconds) { - long diffMinutes = timeDifferenceMilliseconds / (60 * 1000) % 60; - long diffHours = timeDifferenceMilliseconds / (60 * 60 * 1000) % 60; - long diffDays = timeDifferenceMilliseconds / (60 * 60 * 1000 * 24) % 24; - long diffMonths = (long) ((timeDifferenceMilliseconds / (60 * 60 * 1000 * 24 * 30.41666666)) % 30.41666666); - long diffYears = timeDifferenceMilliseconds / ((long) 60 * 60 * 1000 * 24 * 365) % 365; + + long diffMinutes = timeDifferenceMilliseconds / (secondsPerMinute * 1000) % secondsPerMinute; + long diffHours = timeDifferenceMilliseconds / (secondsPerMinute * minutesPerHour * 1000) % minutesPerHour; + long diffDays = timeDifferenceMilliseconds / (secondsPerMinute * minutesPerHour * 1000 * hoursPerDay) % hoursPerDay; + long diffMonths = (long) ((timeDifferenceMilliseconds / (secondsPerMinute * minutesPerHour * 1000 * hoursPerDay * daysPerMonth)) % daysPerMonth); + long diffYears = (long) ((timeDifferenceMilliseconds / ( secondsPerMinute * minutesPerHour * 1000 * hoursPerDay * daysPerMonth * monthsPerYear)) % monthsPerYear); String result = ""; if (diffYears != 0) { result += diffYears; @@ -575,7 +582,7 @@ static void displayNextUpcomingEvent(ArrayList tasks) { borderLine(); System.out.println("\t Here are your next upcoming event: "); for (int i = 0; i < tasks.size(); i++) { - if (tasks.get(i) instanceof Event && tasks.get(i).getStatusIcon()!="X") { + if (tasks.get(i) instanceof Event && tasks.get(i).getStatusIcon() != "X") { System.out.println("\t " + tasks.get(i)); break; } else if (i == tasks.size() - 1) { @@ -594,7 +601,7 @@ static void displayNextUpcomingDeadline(ArrayList tasks) { borderLine(); System.out.println("\t Here are your next upcoming event: "); for (int i = 0; i < tasks.size(); i++) { - if (tasks.get(i) instanceof Deadline && tasks.get(i).getStatusIcon()!="X") { + if (tasks.get(i) instanceof Deadline && tasks.get(i).getStatusIcon() != "X") { System.out.println("\t" + tasks.get(i)); break; } else if (i == tasks.size() - 1) { @@ -708,10 +715,10 @@ static void help() { "/day /from /to "); System.out.println("\t (/description can be followed by whitespace if the class has no description."); System.out.println("\t : I'll remove this class from your class schedule."); - System.out.println("\t - add_notes : I'll add an additional note to that task!" ); - System.out.println("\t - delete_notes : I'll delete the note to that task!" ); - System.out.println("\t - edit_notes : I'll edit the note for that task!" ); - System.out.println("\t - view_notes : I'll print the additional notes for that task!" ); + System.out.println("\t - add_notes : I'll add an additional note to that task!"); + System.out.println("\t - delete_notes : I'll delete the note to that task!"); + System.out.println("\t - edit_notes : I'll edit the note for that task!"); + System.out.println("\t - view_notes : I'll print the additional notes for that task!"); System.out.println("\t - purge: I'll delete all expired tasks from your list after a confirmation."); System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); System.out.println("\t - The index of the item will also be displayed."); @@ -891,10 +898,10 @@ static void greetingMessage() { static void printNotes(ArrayList tasks, String[] words) { int index = Integer.parseInt(words[1]); - if(index > tasks.size() || index <= 0) { + if (index > tasks.size() || index <= 0) { Ui.exceedTaskNumberMessage(index); } else { - ArrayList toBePrinted = tasks.get(index-1).getAdditionalNotes(); + ArrayList toBePrinted = tasks.get(index - 1).getAdditionalNotes(); borderLine(); if (!toBePrinted.isEmpty()) { for (int i = 0; i < toBePrinted.size(); i++) { From ab15ac3d0f0fd38affe8de38244b7a9b2b0c3d95 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Wed, 5 Apr 2023 23:02:11 +0800 Subject: [PATCH 098/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index bccca124d5..cbbfaf21a6 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -155,17 +155,19 @@ Got it, all tasks have been cleared. ``` -### SchoolClass Feature +### SchoolClass `list_classes` feature **Implementation** -The ```SchoolClass``` Class is implemented to facilitate the adding of students' classes to a separate schedule, which is a priority queue. It extends the ```Task``` Class with additional String attributes to store the class name, day of week, start time, and end time. It also overrides the ```toString()``` method to have its own specialised output when being printed, as well as overriding the ```toSaveString()``` method to correctly save its details to the save file. The ```SchoolClass``` Class will also facilitate the implementation of automatically recurring classes, which is a planned feature for milestone v2.0. ```SchoolClass``` Tasks will be added by default as recurring tasks to the task list, and will be automatically added back at their same set timing each week. +The ```SchoolClass``` Class is implemented to facilitate the adding of students' classes to a separate schedule, which is a priority queue. It extends the ```Task``` Class with additional String attributes to store the class name, day of week, start time, and end time. It also overrides the ```toString()``` method to have its own specialised output when being printed, as well as overriding the ```toSaveString()``` method to correctly save its details to the save file. The ```SchoolClass``` Class will also facilitate the implementation of automatic time tracking of whether the class is over for the week, as well as sorting the SchoolClasses based on their day of week and start/end time. These two features are part of the ```list_classes``` feature, which lists out all the SchoolClasses stored in Duck. The following are the new operations implemented. -- ```TaskList#addSchoolClass()``` - Adds a SchoolClass Task to the task list. +- ```TaskList#addSchoolClass()``` - Adds a SchoolClass to the schedule. -- ```Ui#addedTaskMessage()``` - Outputs a message to show that the SchoolClass Task was successfully added to the task list +- ```TaskList#deleteClass()``` - Removes a SchoolClass from the schedule. + +- ```Ui#listClasses()``` - Lists out all currently stored SchoolClasses according to day of week, start and end time in ascending order. - ```Storage#loadSchoolClass()``` - Adds a SchoolClass to the task list without generating a successfully added message, to be used when loading from the save data. @@ -173,17 +175,17 @@ The following are the new operations implemented. **Given below is an example usage scenario for TaskList#addSchoolClass().** -**Step 1.** The user inputs a command following the proper formatting for adding a ```SchoolClass```. The Duck class will call ```Parser#processCommand()```, instantiating a ```Parser``` class, which will then call ```TaskList#addTask()```, instantiating a ```TaskList``` Class. From there, ```TaskList#addSchoolClass()``` is called and a new ```SchoolClass``` Task is instantiated, which calls ```Ui#addedTaskMessage()``` and instantiating a ```Ui``` Class. This ```SchoolClass``` Task will thus be added to the ArrayList tasks that was instantiated in the ```Duck``` class. - -![](https://lh4.googleusercontent.com/u4zVr8TYxFw3rMvnqdwCYlJmq0JxUgEtC_cFmOY7rPqCM9nvzcQL1t-GcTmgbedeVEHi2L6MG6xG3QaJ7XaOPs8nYvHz1Uf4wGK9bMsHDHwxZVNdS2zR79TtHL_Ub2Za0_jm6bUsnY_RQWX6QmFqCl4) +The user inputs a command following the proper formatting for adding a ```SchoolClass```. The sequence diagram for adding a SchoolClass is shown below -![](https://lh3.googleusercontent.com/owAwOcAeTYadanERD7zj2eVD_SsbxhXUvohhaV962-DfYkgh-fV4wWVv8LnLjPpt9jl3yEkBrVUuiPg7jor-uWSpIhwdze4C3yKMWdRQEYrcR7I6tW4RMIGeyazNhEYUZzTd2BTBqUNpKL-6O2KRXug) +![image](https://user-images.githubusercontent.com/88079008/230120692-d4771d07-b228-400e-9968-aed978a323e6.png)
-**Given below is an example usage scenario for Storage#loadSchoolClass.** +**Given below is an example usage scenario for Ui#listClasses.** -**Step 1.** The user launches the application. The task list will be initialised with the data from a given pre-existing datafile if it exists, and the ```SchoolClass``` items will be inserted into the task list if they exist using ```Storage#loadSchoolClass()```. +The user inputs the command for ```list_classes```. The program then lists out all the SchoolClasses stored in Duck according to chronological order. The sequence diagram for Ui#listClasses is shown below. + +![image](https://user-images.githubusercontent.com/88079008/230112915-fd04ca83-4d30-47c0-a3a4-c7a3c82e0b17.png)
From 3d691e7d54929dc728d5a9b03e73c9434eafefbd Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Wed, 5 Apr 2023 23:03:45 +0800 Subject: [PATCH 099/152] Added sequence diagrams for listClasses and addSchoolClass --- docs/tP Diagram Editable.pptx | Bin 76131 -> 84040 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/tP Diagram Editable.pptx b/docs/tP Diagram Editable.pptx index 1a3de56fa1eb462085f2f800ef8759527f7f5a68..8ed2f4b2c490ecfa66bde1e455f3a6f7fa60f564 100644 GIT binary patch delta 27079 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 delta 19773 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 V!U{Bifx#RIeSqdLN&@Q|1_1105}p76 From 838cc02c7c9f5b589d0243efcdd5524bdb2bd0a7 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Wed, 5 Apr 2023 23:10:37 +0800 Subject: [PATCH 100/152] Update jeraldgau.md --- docs/team/jeraldgau.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/team/jeraldgau.md b/docs/team/jeraldgau.md index 0c3bb3e09f..c9af343914 100644 --- a/docs/team/jeraldgau.md +++ b/docs/team/jeraldgau.md @@ -58,6 +58,8 @@ Duck is a desktop task and class tracker for users to keep track of their schedu - Developer Guide: - Added design and implementation details of the SchoolClass feature + - Added the sequence diagram for the ```Adding a School Class``` function + - Added the sequence diagram for the ```list_classes``` function
From caa1c146db3919772816c5decde3fd7eed2e1716 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Wed, 5 Apr 2023 23:32:52 +0800 Subject: [PATCH 101/152] Update AboutUs.md --- docs/AboutUs.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..71e7bd33d9 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,8 +2,8 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Thant Aung Htet Nyan | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Jeremiah Ong | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Yan Zaiya | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Gau Kiat Lok Jerald | [Github](https://github.com/jeraldgau) | [Portfolio](docs/team/jeraldgau.md) +![](https://via.placeholder.com/100.png?text=Photo) | Liang Ting-Yu | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From b9d7677ac3459730f1aeb275d0c99d53f398f383 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Wed, 5 Apr 2023 23:34:06 +0800 Subject: [PATCH 102/152] Update AboutUs.md --- docs/AboutUs.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 71e7bd33d9..eee312844e 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,8 +2,8 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Thant Aung Htet Nyan | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Jeremiah Ong | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Yan Zaiya | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Gau Kiat Lok Jerald | [Github](https://github.com/jeraldgau) | [Portfolio](docs/team/jeraldgau.md) -![](https://via.placeholder.com/100.png?text=Photo) | Liang Ting-Yu | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Thant Aung Htet Nyan | [Github](https://github.com/) | [Portfolio](team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Jeremiah Ong | [Github](https://github.com/) | [Portfolio](team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Yan Zaiya | [Github](https://github.com/) | [Portfolio](team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Gau Kiat Lok Jerald | [Github](https://github.com/jeraldgau) | [Portfolio](team/jeraldgau.md) +![](https://via.placeholder.com/100.png?text=Photo) | Liang Ting-Yu | [Github](https://github.com/) | [Portfolio](team/johndoe.md) From 197c46c51c92bf97b0051e3b700ad0db8ff5ae3f Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Wed, 5 Apr 2023 23:40:07 +0800 Subject: [PATCH 103/152] Update jeraldgau.md --- docs/team/jeraldgau.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/team/jeraldgau.md b/docs/team/jeraldgau.md index c9af343914..976b4941c6 100644 --- a/docs/team/jeraldgau.md +++ b/docs/team/jeraldgau.md @@ -11,46 +11,46 @@ Duck is a desktop task and class tracker for users to keep track of their schedu ### Base Code: Contributed code from iP Duke bot to serve as a base to work upon. - Justification: Duck is an improved version of the Duke bot, building upon the pre-existing functionality of Duke with enhanced features like date/time tracking, as well as a new school class scheduler. As such, it made sense to reuse code from the iP and add in features from there. -
+ ### New Feature: Implementation of the ```SchoolClass``` Task - Added a new Task class called SchoolClass, which are added to a separate list from the other tasks to facilitate schedule tracking. - Makes use of the jave.time package for registering valid start/end timings, as well as java.time.DayOfWeek to register valid days in a week. This facilitates the time tracking feature. - Revamped how saving and loading from savefile works from the iP base code, in order to account for the new SchoolClass Task. The saving and loading of task priorities was also tweaked in order for it to work with adding SchoolClasses to the savefile. -
+ ### New Feature: Class schedule with automatic time tracking - SchoolClasses will be added to a separate list which automatically sorts them based on their registered day of week, and starting/ending time. - The SchoolClasses will be automatically marked as done when the current time is past their registered ending time, and their done status will be reset to not done at the start of a new week. -
+ ### New Feature: ```list_classes``` - Displays all the currently registered SchoolClasses saved in Duck, and lists them out based on their day of week, starting and ending time. - Shows whether the class is over for the week, with a "done" marker [X] shown on the left of each class. -
+ ### New Feature: Adding a SchoolClass - By following the specified format as indicated in the User Guide, users will be able to add SchoolClasses to their schedule. - The added SchoolClasses will be saved to the savefile, which will be loaded upon starting up Duck again. -
+ ### New Feature: Removing a SchoolClass - By Following the specified format as indicated in the User Guide, users will be able to remove unwanted SchoolClasses from their schedule. -
+ ### Code Contributed: [RepoSense Link](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=jeraldgau&breakdown=true&sort=groupTitle%20dsc&sortWithin=title&since=2023-02-17&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other) -
+ ### Project Management: - Managed the releases ```v1.0``` - ```v2.0``` (2 releases) on GitHub -
+ ### Documentation: - User Guide: @@ -61,7 +61,7 @@ Duck is a desktop task and class tracker for users to keep track of their schedu - Added the sequence diagram for the ```Adding a School Class``` function - Added the sequence diagram for the ```list_classes``` function -
+ ### Community: - Reported bugs and suggestions for other teams (examples: [1](https://github.com/jeraldgau/ped/issues/9), [2](https://github.com/jeraldgau/ped/issues/7), [3](https://github.com/jeraldgau/ped/issues/5)) From 764cc4825c69d24ea76e9785ce5dbf00cdc090c8 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Wed, 5 Apr 2023 23:47:31 +0800 Subject: [PATCH 104/152] Update jeraldgau.md --- docs/team/jeraldgau.md | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/docs/team/jeraldgau.md b/docs/team/jeraldgau.md index 976b4941c6..5dfbdc31a6 100644 --- a/docs/team/jeraldgau.md +++ b/docs/team/jeraldgau.md @@ -4,7 +4,7 @@ Duck is a desktop task and class tracker for users to keep track of their schedule and the things they have to do. The user interacts with it using the CLI. It is written in Java, and has about 3.5kLoc. -
+ ## Summary of Contributions @@ -12,46 +12,36 @@ Duck is a desktop task and class tracker for users to keep track of their schedu - Justification: Duck is an improved version of the Duke bot, building upon the pre-existing functionality of Duke with enhanced features like date/time tracking, as well as a new school class scheduler. As such, it made sense to reuse code from the iP and add in features from there. - ### New Feature: Implementation of the ```SchoolClass``` Task -- Added a new Task class called SchoolClass, which are added to a separate list from the other tasks to facilitate schedule tracking. - Makes use of the jave.time package for registering valid start/end timings, as well as java.time.DayOfWeek to register valid days in a week. This facilitates the time tracking feature. - Revamped how saving and loading from savefile works from the iP base code, in order to account for the new SchoolClass Task. The saving and loading of task priorities was also tweaked in order for it to work with adding SchoolClasses to the savefile. - ### New Feature: Class schedule with automatic time tracking - SchoolClasses will be added to a separate list which automatically sorts them based on their registered day of week, and starting/ending time. - The SchoolClasses will be automatically marked as done when the current time is past their registered ending time, and their done status will be reset to not done at the start of a new week. - ### New Feature: ```list_classes``` - Displays all the currently registered SchoolClasses saved in Duck, and lists them out based on their day of week, starting and ending time. - Shows whether the class is over for the week, with a "done" marker [X] shown on the left of each class. - ### New Feature: Adding a SchoolClass -- By following the specified format as indicated in the User Guide, users will be able to add SchoolClasses to their schedule. -- The added SchoolClasses will be saved to the savefile, which will be loaded upon starting up Duck again. - +- By following the specified format as indicated in the User Guide, users will be able to add SchoolClasses to their schedule which are saved to the savefile. ### New Feature: Removing a SchoolClass - By Following the specified format as indicated in the User Guide, users will be able to remove unwanted SchoolClasses from their schedule. - ### Code Contributed: [RepoSense Link](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=jeraldgau&breakdown=true&sort=groupTitle%20dsc&sortWithin=title&since=2023-02-17&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other) - ### Project Management: - Managed the releases ```v1.0``` - ```v2.0``` (2 releases) on GitHub - ### Documentation: - User Guide: - Added documentation for the features ```list_classes```, ```remove class``` and ```Adding a School Class``` @@ -60,7 +50,6 @@ Duck is a desktop task and class tracker for users to keep track of their schedu - Added design and implementation details of the SchoolClass feature - Added the sequence diagram for the ```Adding a School Class``` function - Added the sequence diagram for the ```list_classes``` function - ### Community: From cadd18d10316105a93f2bbe36ccfa32f77827cdc Mon Sep 17 00:00:00 2001 From: sunkyan Date: Thu, 6 Apr 2023 11:02:52 +0800 Subject: [PATCH 105/152] changed the command for adding a todo task --- src/main/java/seedu/duck/TaskList.java | 16 ++++++++++------ src/main/java/seedu/duck/Ui.java | 4 ++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 39be7b740f..2be9c0a767 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -35,7 +35,7 @@ static void addTask(String line, ArrayList tasks, PriorityQueue tasks, PriorityQueue tasks, PriorityQueue tasks, PriorityQueue tasks, PriorityQueue tasks, PriorityQueue tasks) throws IllegalTodoException { - if (line.isBlank()) { + line = line.trim(); + String description = line.substring(5).trim(); + if (description.isBlank()) { throw new IllegalTodoException(); } else { - Todo currTodo = new Todo(line); + Todo currTodo = new Todo(description); tasks.add(currTodo); Ui.addedTaskMessage(currTodo); } diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index a09800269c..47de0dce68 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -735,8 +735,8 @@ static void help() { System.out.println("\t (eg. Meeting /from 2023-03-15 2015 /to 2023-03-15 2215)"); System.out.println("\t Recurring events: /re /from /to /day "); System.out.println("\t (eg. /re Meeting /from 2015 /to 2215 /day MONDAY)"); - System.out.println("\t Todo : "); - System.out.println("\t (eg. Water the plants)"); + System.out.println("\t Todo : /todo "); + System.out.println("\t (eg. /todo Water the plants)"); System.out.println("\t Classes : /class /day " + "/from /to "); System.out.println("\t (eg. Bring laptop /class CS2113 /day TUESDAY /from 1100 /to 1200) \n"); From 60d9688b442d461c5b28a220d7a7b9b28c63094b Mon Sep 17 00:00:00 2001 From: skyanzy <88618401+skyanzy@users.noreply.github.com> Date: Thu, 6 Apr 2023 11:08:20 +0800 Subject: [PATCH 106/152] Update UserGuide.md --- docs/UserGuide.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index ebb11c6d28..4d3d451f86 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -31,7 +31,7 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * [Find tasks matching a given keyword :](#finding-tasks-from-storage-that-match-a-keyword-find-keyword) `find ` * [Add tasks that can be broken down into the following 6 types:](#adding-a-todo-task--description) - * Add ToDo: + * Add ToDo: /todo * Add Deadline: /by * Add RecurringDeadline: /re /by /day * Add Event: /from /to @@ -519,13 +519,13 @@ Here are the matching tasks in your list: -## **Adding a ToDo Task : ``** +## **Adding a ToDo Task : `/todo `** Adds a ToDo task to the storage of Duck -**Input:** `` +**Input:** `/todo ` -**Output: Demonstrated by inputting `Todo`** +**Output: Demonstrated by inputting `/todo todo`** ``` From 299e8a230ed2552520209f0d9740dc0367ce5dbc Mon Sep 17 00:00:00 2001 From: skyanzy <88618401+skyanzy@users.noreply.github.com> Date: Thu, 6 Apr 2023 11:09:08 +0800 Subject: [PATCH 107/152] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 4d3d451f86..851cc98a79 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -29,7 +29,7 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * [Purge expired tasks :](#purge-expired-tasks--purge) `purge` * [Clearing all tasks (including datafile) :](#clearing-tasks-from-storage-clear) `clear ` * [Find tasks matching a given keyword :](#finding-tasks-from-storage-that-match-a-keyword-find-keyword) `find ` - * [Add tasks that can be broken down into the following 6 types:](#adding-a-todo-task--description) + * [Add tasks that can be broken down into the following 6 types:](#adding-a-todo-task--todo-description) * Add ToDo: /todo * Add Deadline: /by From 4238e3e8116daf3702523d83d3a22b5076116cd9 Mon Sep 17 00:00:00 2001 From: tliangac Date: Thu, 6 Apr 2023 15:54:54 +0800 Subject: [PATCH 108/152] Draft PPP --- docs/team/MichelleLiang0116.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 docs/team/MichelleLiang0116.md diff --git a/docs/team/MichelleLiang0116.md b/docs/team/MichelleLiang0116.md new file mode 100644 index 0000000000..c9ff9b201a --- /dev/null +++ b/docs/team/MichelleLiang0116.md @@ -0,0 +1,10 @@ +# LIANG TING YU - Project Portfolio Page + +## Project: Duck +### Duck is a desktop app for managing tasks and deadlines, as well as a school class scheduler. It is optimised for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). +### Summary of Contributions: +#### • New Feature: Display upcoming deadline/event when starting application +#### • New Feature: Display next upcoming deadline/event/task/class +#### Code contributed: +#### Enhancements implemented: +#### Contributions to the UG: From ac6796a7269943245fb938540dfd0923d68980c3 Mon Sep 17 00:00:00 2001 From: tliangac Date: Thu, 6 Apr 2023 15:56:34 +0800 Subject: [PATCH 109/152] Draft PPP --- docs/team/MichelleLiang0116.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/team/MichelleLiang0116.md b/docs/team/MichelleLiang0116.md index c9ff9b201a..230c2ec40d 100644 --- a/docs/team/MichelleLiang0116.md +++ b/docs/team/MichelleLiang0116.md @@ -8,3 +8,6 @@ #### Code contributed: #### Enhancements implemented: #### Contributions to the UG: +#### Contributions to team-based tasks +#### Review/mentoring contributions: + From 86beb8450dc5172c42354558e6c1779d16a307f8 Mon Sep 17 00:00:00 2001 From: tliangac Date: Fri, 7 Apr 2023 12:58:21 +0800 Subject: [PATCH 110/152] rename Draft PPP --- docs/team/{MichelleLiang0116.md => michelleliang0116.md} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename docs/team/{MichelleLiang0116.md => michelleliang0116.md} (81%) diff --git a/docs/team/MichelleLiang0116.md b/docs/team/michelleliang0116.md similarity index 81% rename from docs/team/MichelleLiang0116.md rename to docs/team/michelleliang0116.md index 230c2ec40d..c19f39ac2e 100644 --- a/docs/team/MichelleLiang0116.md +++ b/docs/team/michelleliang0116.md @@ -2,12 +2,12 @@ ## Project: Duck ### Duck is a desktop app for managing tasks and deadlines, as well as a school class scheduler. It is optimised for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). -### Summary of Contributions: +### Summary of Contributions: #### • New Feature: Display upcoming deadline/event when starting application #### • New Feature: Display next upcoming deadline/event/task/class -#### Code contributed: -#### Enhancements implemented: -#### Contributions to the UG: +#### Code contributed: +#### Enhancements implemented: +#### Contributions to the UG: #### Contributions to team-based tasks #### Review/mentoring contributions: From 9c0c85df63c61f658d205c2938f52187c1dc3cf4 Mon Sep 17 00:00:00 2001 From: thant Date: Fri, 7 Apr 2023 14:17:39 +0800 Subject: [PATCH 111/152] Update UserGuide.md --- docs/UserGuide.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 851cc98a79..444046c697 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -20,9 +20,9 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * [Deleting a task :](#deleting-a-task--delete) `delete ` * [Deleting a school class :](#deleting-a-school-class--remove-class) `remove /class /description /day /from /to ` * [Designate a priority to a given task :](#designate-a-task-priority--priority-task_number-priority) `priority ` - * [Adding notes for a specific task :](#adding-notes-for-a-specific-task--add_note) `add_note ` - * [Deleting notes for a specific task :](#deleting-notes-for-a-specific-task--delete_note) `delete_note ` - * [Editing notes for a specific task :](#editing-notes-for-a-specific-task--edit_note) `edit_note ` + * [Adding notes for a specific task :](#adding-notes-for-a-specific-task--add_note) `add_notes ` + * [Deleting notes for a specific task :](#deleting-notes-for-a-specific-task--delete_note) `delete_notes ` + * [Editing notes for a specific task :](#editing-notes-for-a-specific-task--edit_note) `edit_notes ` * [Viewing notes for a specific task :](#printing-notes-for-a-specific-task--view_notes) `view_notes ` * [List tasks of low/medium/high priority :](#listing-all-low-priority-tasks--low_priority) `low_priority`/`medium_priority`/`high_priority` * [List tasks in priority order:](#listing-all-tasks-arranged-by-priority--priority_list) `priority_list` @@ -388,10 +388,10 @@ Understood. The task's new priority is: Low priority. ``` -## **Adding notes for a specific task : `add_note`** +## **Adding notes for a specific task : `add_notes`** Adds a note to the specified task -**Input:** `add_note ` +**Input:** `add_notes ` **Output: Demonstrated below adding "Bring own recyclable bag"** ``` What note would you like to add to the following task? @@ -402,11 +402,11 @@ Bring own recyclable bag ____________________________________________________________ ``` -## **Deleting notes for a specific task : `delete_note`** +## **Deleting notes for a specific task : `delete_notes`** Deletes the specified note for the task -**Input:** `delete_note ` -**Output: Demonstrated below to delete 1 task** +**Input:** `delete_notes ` +**Output: Demonstrated below to delete 1 task note** ``` ____________________________________________________________ @@ -414,10 +414,10 @@ Deletes the specified note for the task Bring own recyclable bag ____________________________________________________________ ``` -## **Editing notes for a specific task : `edit_note`** +## **Editing notes for a specific task : `edit_notes`** Edits the specified note for a specific task. -**Input:** `edit_note ` +**Input:** `edit_notes ` **Output: Demonstrated below to edit "Bring recyclable bag" to "Bring tote bag"** ``` ____________________________________________________________ From 9c7636bf7c502a527c9310fcd1e6beca36d357ec Mon Sep 17 00:00:00 2001 From: thant Date: Fri, 7 Apr 2023 14:18:13 +0800 Subject: [PATCH 112/152] Update UserGuide.md --- docs/UserGuide.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 444046c697..9edff044e8 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -20,9 +20,9 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * [Deleting a task :](#deleting-a-task--delete) `delete ` * [Deleting a school class :](#deleting-a-school-class--remove-class) `remove /class /description /day /from /to ` * [Designate a priority to a given task :](#designate-a-task-priority--priority-task_number-priority) `priority ` - * [Adding notes for a specific task :](#adding-notes-for-a-specific-task--add_note) `add_notes ` - * [Deleting notes for a specific task :](#deleting-notes-for-a-specific-task--delete_note) `delete_notes ` - * [Editing notes for a specific task :](#editing-notes-for-a-specific-task--edit_note) `edit_notes ` + * [Adding notes for a specific task :](#adding-notes-for-a-specific-task--add_notes) `add_notes ` + * [Deleting notes for a specific task :](#deleting-notes-for-a-specific-task--delete_notes) `delete_notes ` + * [Editing notes for a specific task :](#editing-notes-for-a-specific-task--edit_notes) `edit_notes ` * [Viewing notes for a specific task :](#printing-notes-for-a-specific-task--view_notes) `view_notes ` * [List tasks of low/medium/high priority :](#listing-all-low-priority-tasks--low_priority) `low_priority`/`medium_priority`/`high_priority` * [List tasks in priority order:](#listing-all-tasks-arranged-by-priority--priority_list) `priority_list` From efe3dd5f446ebdac9875a77050820843ba31f5e6 Mon Sep 17 00:00:00 2001 From: thant Date: Fri, 7 Apr 2023 15:55:20 +0800 Subject: [PATCH 113/152] Draft for PPP --- docs/team/thant.md | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 docs/team/thant.md diff --git a/docs/team/thant.md b/docs/team/thant.md new file mode 100644 index 0000000000..fccbfc9113 --- /dev/null +++ b/docs/team/thant.md @@ -0,0 +1,56 @@ +# Thant Aung Htet Nyan - Project Portfolio Page + +## Overview + +Duck is a desktop task and class tracker for users to keep track of their schedule and the things they have to do. The user interacts with it using the CLI. It is written in Java, and has about 3.5kLoc. + + + +## Summary of Contributions + +### New Feature: Implementation of Date-Time tracking across Duck +- Elaboration: Duck is an improved version of the Duke bot, building upon the pre-existing functionality of Duke with enhanced features like date/time tracking, which was added by me. This date/time tracking is crucial in a number of new Duck features. + + +### New Feature: Implementation of the ```priority``` variables +- Adds a new priority variable to the Task class that ranges from 1-3, being LOW MEDIUM HIGH respectively. +- This is utilized in the ```priority_list``` new feature as well as the ```high_priority```,```medium_priority```,```low_priority```commands. + + +### New Feature: Implementation of the ```purge``` feature +- Checks across the ```TaskList``` array to identify all ```Deadline``` and ```Event``` objects. +- Checks for if the ```by``` variable for ```Deadline```objects or the ```end```variable for ```Event``` objects have passed the localtime of the local machine where Duck is running on. +- Displays all expired tasks, as well as the total count of expired tasks. +- Prompts user for a ```Y/N``` to confirm the removal of expired tasks. +- This feature helps keep the list of tasks clean, and is automatically run once on Duck's startup. + + +### New Feature: Implementation of the ```clear``` feature +- Wipes the ```TaskList``` array clean and wipes the local ```savedata``` file clean as well. +- User is prompted for a ```Y/N``` confirmation as this process is irreversible. +- Justification: During debugging / demonstrations, I continually manually deleted and recreated the ```savedata``` file to reset Duck to a blank slate. Hence, I decided to just make it an easily accessible feature for Duck users and it became highly useful. + + +### Code Contributed: [RepoSense Link](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=thant&breakdown=true&sort=groupTitle%20dsc&sortWithin=title&since=2023-02-17&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other) + + +### Project Management: +- Initiated meetings / kept group on track to meet specific deadlines. +- Specified and broke down which issues should be done by v1.0, v2.0 and so forth to breakdown work timelines. + + +### Documentation: +- User Guide: + - Did up most of the initial User Guide. + - Updated respective features as new features were added / input methods were updated. + - Added hyperlinks to the feature lists. + +- Developer Guide: + - Did the ```architecture``` section. + - Did the design and implementation for ```purge``` and ```clear``` features + - Added the sequence diagram for the ```purge``` function + - Added an editable class diagram powerpoint skeleton located at ```docs/tP Diagram Editable.pptx``` + + +### Community: +- Reported bugs and suggestions for other teams (examples: [1](https://github.com/thant/ped/issues/5), [2](https://github.com/thant/ped/issues/6), [3](https://github.com/thant/ped/issues/8)) From e170ff5e678aeb0f4884390aefb81bc736fc5ee7 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Fri, 7 Apr 2023 21:56:45 +0800 Subject: [PATCH 114/152] Handled the case where the save file is tampered with --- src/main/java/seedu/duck/Storage.java | 15 ++++++++++++--- src/main/java/seedu/duck/Ui.java | 6 ++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/duck/Storage.java b/src/main/java/seedu/duck/Storage.java index 963a0f261b..f5e7238945 100644 --- a/src/main/java/seedu/duck/Storage.java +++ b/src/main/java/seedu/duck/Storage.java @@ -25,7 +25,8 @@ public class Storage { * @param line The line of input from the save file * @param tasks The array list of tasks */ - static void loadTask(String line, ArrayList tasks, PriorityQueue classes, String doneStatus) { + static void loadTask(String line, ArrayList tasks, PriorityQueue classes, String doneStatus) + throws IndexOutOfBoundsException { if (line.contains("/by")) { if (line.contains("/day")) { loadRecurringDeadline(line, tasks); @@ -251,7 +252,8 @@ static void trySave(ArrayList tasks, PriorityQueue classes) { * * @param tasks The array list of tasks */ - static void load(ArrayList tasks, PriorityQueue classes) throws IOException { + static void load(ArrayList tasks, PriorityQueue classes) throws IOException, + IndexOutOfBoundsException { File folder = new File(SAVEFOLDER); if (!folder.exists()) { new File(SAVEFOLDER).mkdir(); @@ -272,7 +274,12 @@ static void load(ArrayList tasks, PriorityQueue classes) thro command += formattedInput[i]; command += " "; } + try { loadTask(command, tasks, classes, doneStatus); + } catch (IndexOutOfBoundsException e) { + FileWriter fw = new FileWriter(SAVEPATH); + throw new IndexOutOfBoundsException(); + } } } @@ -285,7 +292,9 @@ static void tryLoad(ArrayList tasks, PriorityQueue classes) { try { load(tasks, classes); } catch (IOException e) { - System.out.println("Error loading save file."); + Ui.loadingErrorMessage(); + } catch (IndexOutOfBoundsException e) { + Ui.loadingErrorMessage(); } } } diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 47de0dce68..4a5b6a7138 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -880,6 +880,12 @@ static void invalidDateTimeMessage() { borderLine(); } + static void loadingErrorMessage() { + borderLine(); + System.out.println("\t Error loading save file."); + borderLine(); + } + /** * Prints the startup message, includes instructions on available commands */ From d963c23db6f2bc5d484506e5deff5eb83b4014c1 Mon Sep 17 00:00:00 2001 From: thant Date: Sat, 8 Apr 2023 16:01:05 +0800 Subject: [PATCH 115/152] Update AboutUs.md --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index eee312844e..87cbba3467 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,7 +2,7 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Thant Aung Htet Nyan | [Github](https://github.com/) | [Portfolio](team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Thant Aung Htet Nyan | [Github](https://github.com/) | [Portfolio](team/thant.md) ![](https://via.placeholder.com/100.png?text=Photo) | Jeremiah Ong | [Github](https://github.com/) | [Portfolio](team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Yan Zaiya | [Github](https://github.com/) | [Portfolio](team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Gau Kiat Lok Jerald | [Github](https://github.com/jeraldgau) | [Portfolio](team/jeraldgau.md) From 06b8280d61b8db294892f212bca6723daa97bb2a Mon Sep 17 00:00:00 2001 From: thant Date: Sat, 8 Apr 2023 16:04:16 +0800 Subject: [PATCH 116/152] Update AboutUs.md --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 87cbba3467..93e19c4537 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,7 +2,7 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Thant Aung Htet Nyan | [Github](https://github.com/) | [Portfolio](team/thant.md) +![](https://via.placeholder.com/100.png?text=Photo) | Thant Aung Htet Nyan | [Github](https://github.com/thant) | [Portfolio](team/thant.md) ![](https://via.placeholder.com/100.png?text=Photo) | Jeremiah Ong | [Github](https://github.com/) | [Portfolio](team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Yan Zaiya | [Github](https://github.com/) | [Portfolio](team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Gau Kiat Lok Jerald | [Github](https://github.com/jeraldgau) | [Portfolio](team/jeraldgau.md) From e27d3a2df5d89bead3dc05c9e36d0cff9376a700 Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Sat, 8 Apr 2023 21:01:24 +0800 Subject: [PATCH 117/152] Added function to print motivational quotes on command, added JavaDoc and cleaned up motivational quote printing --- docs/UserGuide.md | 12 ++++++++++++ src/main/java/seedu/duck/Parser.java | 4 ++++ src/main/java/seedu/duck/Ui.java | 19 ++++++++++++++++--- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 9edff044e8..748035f043 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -614,7 +614,19 @@ Alright, I have added this task: You now have 1 class in your schedule. ``` +## **Printing a motivaional quote : `motivation`** +Prints a random motivational quote. + +**Input:** `motivation` + +**Output:** + + +``` +Success is not how high you have climbed, but how you make a positive difference to the world. -Roy T. Bennett +____________________________________________________________ +``` ## **Exiting the program : `bye`** diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 0f3dd1b165..83eedc9022 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -193,6 +193,10 @@ static void processCommand(ArrayList tasks, PriorityQueue cla Ui.unknownCommandMessage(); } break; + case "motivation": + Ui.printMotivationalQuote(); + Ui.borderLine(); + break; case "clear": if (Ui.doubleCheck()) { // Find tasks that contain a keyword diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 62f8860c29..390563bc02 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -40,6 +40,9 @@ static void printDuck() { " `-._________,--'"); } + /** + * Prints a random motivational quote + */ static void printMotivationalQuote() { String[] quotes = { "Believe you can and you're halfway there. -Theodore Roosevelt", @@ -47,7 +50,8 @@ static void printMotivationalQuote() { "You miss 100% of the shots you don't take. -Wayne Gretzky", "Success is not final, failure is not fatal: it is the courage to continue that counts. -Winston Churchill", "You are never too old to set another goal or to dream a new dream. -C.S. Lewis", - "Believe in yourself and all that you are. Know that there is something inside you that is greater than any obstacle. -Christian D. Larson", + "Believe in yourself and all that you are. Know that there is something \n\t " + + "inside you that is greater than any obstacle. -Christian D. Larson", "Success is not how high you have climbed, but how you make a positive difference to the world. -Roy T. Bennett", "A journey of a thousand miles begins with a single step. -Lao Tzu", "The only way to do great work is to love what you do. -Steve Jobs", @@ -55,13 +59,15 @@ static void printMotivationalQuote() { "Believe you can and you're halfway there. -Theodore Roosevelt", "You never know how strong you are until being strong is your only choice. -Bob Marley", "Do not wait for opportunities, create them. -Roy T. Bennett", - "Believe in yourself, take on your challenges, dig deep within yourself to conquer fears. Never let anyone bring you down. You got this. -Chantal Sutherland", + "Believe in yourself, take on your challenges, dig deep within yourself to conquer fears. \n\t " + + "Never let anyone bring you down. You got this. -Chantal Sutherland", "The greatest glory in living lies not in never falling, but in rising every time we fall. -Nelson Mandela", "Believe in your infinite potential. Your only limitations are those you set upon yourself. -Roy T. Bennett", "What you get by achieving your goals is not as important as what you become by achieving your goals. -Zig Ziglar", "Don't watch the clock; do what it does. Keep going. -Sam Levenson", "Believe that you will succeed, and you will. -Dale Carnegie", - "Success is not the key to happiness. Happiness is the key to success. If you love what you are doing, you will be successful. -Albert Schweitzer" + "Success is not the key to happiness. Happiness is the key to success.\n\t" + + " If you love what you are doing, you will be successful. -Albert Schweitzer" }; Random rand = new Random(); int index = rand.nextInt(quotes.length); @@ -725,6 +731,7 @@ static void help() { System.out.println("\t - priority <1/2/3>: I'll set the priority of a given task as"); System.out.println("\t 1:Low, 2:Medium and 3:High."); System.out.println("\t Default: Low priority."); + System.out.println("\t - motivation: I'll print a random motivational quack for you!"); System.out.println("\t - bye: I will shut down my program.\n"); System.out.println("\t Here are the following ways to input tasks/classes:"); System.out.println("\t Deadlines: /by "); @@ -928,6 +935,12 @@ static void printNotes(ArrayList tasks, String[] words) { } } + /** + * Prints the lists of notes under the specified tasks + * + * @param tasks The arraylist of tasks + * @param index The index of the task whose notes are to be printed + */ static void printList(ArrayList tasks, int index) { ArrayList toBePrinted = tasks.get(index).getAdditionalNotes(); for (int j = 0; j < toBePrinted.size(); j++) { From bb87c7b1b7b1d75e89907b5a347d831d39bd5ebc Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Sat, 8 Apr 2023 21:39:06 +0800 Subject: [PATCH 118/152] Added PPP --- docs/team/miahjerry.md | 66 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 docs/team/miahjerry.md diff --git a/docs/team/miahjerry.md b/docs/team/miahjerry.md new file mode 100644 index 0000000000..41585542dd --- /dev/null +++ b/docs/team/miahjerry.md @@ -0,0 +1,66 @@ +# Jeremiah Ong - Project Portfolio Page + +## Overview +Duck is a desktop task and class tracker for users to keep track of their schedule and the things they have to do. The user interacts with it using the CLI. It is written in Java, and has about 3.5kLoc. + + +## Summary of Contributions + +### New Feature: Implementation of ```print_priority``` feature + +- Added functions to print all tasks arranged by priority, rather than by the order in which they were added +- Also has other smaller functions as specified by the user guide to only print tasks of a certain priority + +### New Feature: Implementation of ```notes``` feature + +- This feature allows users to add additional notes to each task that they will want to take note of +- Notes will also be saved to be viewed again on next start up of Duck + +### New Feature: New tasks automatically assigned low priority + +- Automatically assigns new tasks low priority until they are assigned a higher priority by the user + + +### New Feature: Adding notes to tasks + +- Allows the user to add a note to the specified task +- By following the steps outlined by the user guide, a note can be added to a task. +The note will be saved when Duck is closed + +### New Feature: Deleting notes under tasks + +- his feature allows the user to delete notes that have been created for whatever reason +- By following the steps outlined by the user guide, existing notes can be deleted under their respective tasks. + +### New Feature: Editing notes under tasks + +- This feature allows the user to change an existing note under a specified task +- By following the steps outlined by the user guide, existing notes can be edited. + +### New Feature: Printing Duck + +- Prints ASCII art of a duck to suit the theme of the product +- Acts as the avatar for the application + +### New Feature: Implementation of ```motivation``` feature + +- Prints a motivational quote for the user if they want some motivation +- Also prints on startup when greeting the user + +### Cleaning up of code + +- Helped to make the code more defensive to prevent bad inputs from crashing Duck, specifically indexes that accessed out of bounds + +### Code Contributed: [RepoSense Link](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=miahjerry&breakdown=true&sort=groupTitle%20dsc&sortWithin=title&since=2023-02-17&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other) + +### Project Management: + +- Helped to host group meetings and organize them to ensure group was on task and on the same page +- Liased with other groups to promote mutual stress-testing of each other's product + +### Documentation: +- User Guide: + - Added documentation for the features ```print_priority```, ```low_priority```,```medium_priority```, ```high_priority```, ```add_notes```, ```edit_notes```, ```delete_notes```,and ```motivation``` + +### Community: +- Reported bugs and suggestions for other teams (examples: [1](https://github.com/miahjerry/ped/issues/4), [2](https://github.com/miahjerry/ped/issues/7), [3](https://github.com/miahjerry/ped/issues/8)) From 113f603a35ed556c671238ac6b751fa303b80630 Mon Sep 17 00:00:00 2001 From: skyanzy <88618401+skyanzy@users.noreply.github.com> Date: Sun, 9 Apr 2023 14:37:48 +0800 Subject: [PATCH 119/152] Create skyanzy.md --- docs/team/skyanzy.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/team/skyanzy.md diff --git a/docs/team/skyanzy.md b/docs/team/skyanzy.md new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/docs/team/skyanzy.md @@ -0,0 +1 @@ + From c16a7c897f43d0b508073d749eb10f86f3ed6d54 Mon Sep 17 00:00:00 2001 From: skyanzy <88618401+skyanzy@users.noreply.github.com> Date: Sun, 9 Apr 2023 15:22:51 +0800 Subject: [PATCH 120/152] Update skyanzy.md --- docs/team/skyanzy.md | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/docs/team/skyanzy.md b/docs/team/skyanzy.md index 8b13789179..9294671657 100644 --- a/docs/team/skyanzy.md +++ b/docs/team/skyanzy.md @@ -1 +1,52 @@ +# Yan Zaiya - Project Portfolio Page +## Overview + +Duck is a desktop task and class tracker for users to keep track of their schedule and the things they have to do. The user interacts with it using the CLI. It is written in Java, and has about 3.5kLoc. + + +## Summary of Contributions + +### New Feature: Implementation of the `RecurringDeadline` Task +- Allows users to keep track of deadlines that happen every week by only adding the deadline once instead of every week. +- `Storage` class was modified to recognise a `RecurringDeadline`. + +### New Feature: Implementation of the `RecurringEvent` Task +- Allows users to keep track of events that happen every week by only adding the event once instead of every week. +- `Storage` class was modified to recognise a `RecurringEvent`. + +### New Feature: `list_today` +- Displays all deadlines and events(recurring tasks included) saved in Duck that take place on the same day as the local time. + +### New Feature: Adding a `RecurringDeadline` +- By following the specified format as indicated in the User Guide, users will be able to add RecurringDeadline to their schedule which are saved to the savefile. + +### New Feature: Adding a `RecurringEvent` +- By following the specified format as indicated in the User Guide, users will be able to add RecurringEvent to their schedule which are saved to the savefile. + +### New Feature: `list X` +- Lists all the non-recurring deadlines and events that would happen within X+1 days. +- Justification: this allows users to plan their schedule better by easily referring to the upcoming tasks in the future. + +### New Feature: `edit ` +- Allows uers to edit a specific piece of information regarding a stored task and then updates the savefile. +- Justification: this is done so that the if the users want to modify/ save wrong information about a certain task, they do not have to delete the task and add a new one back in. + +### Code Contributed: [RepoSense Link](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=T11&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2023-02-17&tabOpen=true&tabType=authorship&tabAuthor=skyanzy&tabRepo=AY2223S2-CS2113-T11-1%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false) + +### Project Management: +- Updating the team when a new PR is merged to ensure everyone is on the same page. +- Integration of different parts when a new feature is implemented. + +### Documentation: +- User Guide: + - Added documentation for the features `edit ` , `list_today`, adding a `RecurringDeadline and RecurringEvnet`. + - cleared some issues regarding inconsistent format. + - Added some missing links to the table of contents. + +- Developer Guide: + - Added design and the implementation of RecurringDeadline and RecurringEvent + - Added a class diagram to illustrate the implementation + +### Community: +- Reported bugs and suggestions for other teams(e.g. [1](https://github.com/skyanzy/ped/issues/5), [2](https://github.com/skyanzy/ped/issues/2), [3](https://github.com/skyanzy/ped/issues/1)) From c3d2dce7227e961faae3ff1a79d6b15a3efaff27 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Sun, 9 Apr 2023 15:45:27 +0800 Subject: [PATCH 121/152] Bug fixes --- docs/UserGuide.md | 7 ++++--- src/main/java/seedu/duck/Parser.java | 6 ++++-- src/main/java/seedu/duck/TaskList.java | 2 ++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 748035f043..02ef5fcaa3 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -37,6 +37,7 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * Add Event: /from /to * Add RecurringEvent: /re /from /to /day * Add Class: /class /day /from /to + * [Motivational quotes :](#printing-a-motivational-quote--motivation) `motivation` * [Terminate the program :](#exiting-the-program--bye) `bye` @@ -53,12 +54,12 @@ Displays all available commands and their input format on the terminal. ``` -(`・v・´ ): Here are the commands you can give me: +Here are the commands you can give me: COMMAND_FORMAT : COMMAND_FUNCTIONALITY EXPLANATION . . . -(`・v・´ ): How else may I assist you today, human? +How else may I assist you today, human? ``` @@ -614,7 +615,7 @@ Alright, I have added this task: You now have 1 class in your schedule. ``` -## **Printing a motivaional quote : `motivation`** +## **Printing a motivational quote : `motivation`** Prints a random motivational quote. diff --git a/src/main/java/seedu/duck/Parser.java b/src/main/java/seedu/duck/Parser.java index 83eedc9022..af5e2a3d63 100644 --- a/src/main/java/seedu/duck/Parser.java +++ b/src/main/java/seedu/duck/Parser.java @@ -61,14 +61,16 @@ static void processCommand(ArrayList tasks, PriorityQueue cla if(words.length==2 && isNumeric(words[1])){ Ui.printUpcomingEvents(tasks,words[1]); } else{ - Ui.unknownCommandMessage(); + TaskList.addTask(line, tasks, classes); + Storage.trySave(tasks, classes); } break; case "deadline": if(words.length==2 && isNumeric(words[1])){ Ui.printUpcomingDeadline(tasks,words[1]); } else{ - Ui.unknownCommandMessage(); + TaskList.addTask(line, tasks, classes); + Storage.trySave(tasks, classes); } break; case "list_today": diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 37e54aaa02..0d01777219 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -127,6 +127,8 @@ static void addTodo(String line, ArrayList tasks) throws IllegalTodoExcept static void setPriority(ArrayList tasks, String[] words) { if (!words[2].equals("1") && !words[2].equals("2") && !words[2].equals("3")) { Ui.priorityErrorMessage(); + } else if (!Parser.isNumeric(words[1])) { + Ui.unknownCommandMessage(); } else { int taskNumber = Integer.parseInt(words[1]); int taskCount = Task.getTaskCount(); From 2241c306882056321a889e9856991960bc574b08 Mon Sep 17 00:00:00 2001 From: sunkyan Date: Sun, 9 Apr 2023 15:59:16 +0800 Subject: [PATCH 122/152] improved coding standard --- src/main/java/seedu/duck/TaskList.java | 271 +++++++++++++++---------- 1 file changed, 159 insertions(+), 112 deletions(-) diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index 37e54aaa02..b6fbf7c2e6 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -21,6 +21,13 @@ * Contains operations to manipulate the task list */ public class TaskList { + private static final int DESCRIPTION_OFFSET = 12; + private static final int DEADLINE_OFFSET = 12; + private static final int FROM_OFFSET = 5; + private static final int TO_OFFSET = 3; + private static final int DAY_OFFSET = 4; + private static final int BY_OFFSET = 3; + static void addTask(String line, ArrayList tasks, PriorityQueue classes) { if (line.contains("/by")) { // Adding a Deadline @@ -153,7 +160,7 @@ static void setPriority(ArrayList tasks, String[] words) { static void addEvent(String line, ArrayList tasks) throws IllegalEventException, startAfterEndException, expiredDateException { String description = line.substring(0, line.indexOf("/from")).trim(); - String startString = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); + String startString = line.substring(line.indexOf("/from") + FROM_OFFSET, line.indexOf("/to")).trim(); String endString = line.substring(line.indexOf("/to") + 3).trim(); DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); LocalDateTime start = LocalDateTime.parse(startString, dateFormat); @@ -171,11 +178,17 @@ static void addEvent(String line, ArrayList tasks) throws IllegalEventExce } } + /** + * Adds a RecurringEvent to the list + * @param line input from user + * @param tasks the array list of tasks + * @throws IllegalEventException handles incorrect event format + */ static void addRecurringEvent(String line, ArrayList tasks) throws IllegalEventException{ String description = line.substring(4, line.indexOf("/from")).trim(); - String start = line.substring(line.indexOf("/from") + 5, line.indexOf("/to")).trim(); - String end = line.substring(line.indexOf("/to") + 3, line.indexOf("/day")).trim(); - DayOfWeek day = DayOfWeek.valueOf(line.substring(line.indexOf("/day") + 4).trim()); + String start = line.substring(line.indexOf("/from") + FROM_OFFSET, line.indexOf("/to")).trim(); + String end = line.substring(line.indexOf("/to") + TO_OFFSET, line.indexOf("/day")).trim(); + DayOfWeek day = DayOfWeek.valueOf(line.substring(line.indexOf("/day") + DAY_OFFSET).trim()); DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("HHmm"); //check whether start and end are in the correct format LocalTime.parse(start, timeFormat); @@ -228,8 +241,6 @@ static void addSchoolClass(String line, PriorityQueue classes) thro * @param line The line of input from the user * @param tasks The array list of tasks */ - - static void addDeadline(String line, ArrayList tasks) throws IllegalDeadlineException, expiredDateException { String description = line.substring(0, line.indexOf("/by")).trim(); String deadlineString = line.substring(line.indexOf("/by") + 3).trim(); @@ -257,10 +268,10 @@ static void addDeadline(String line, ArrayList tasks) throws IllegalDeadli static void addRecurringDeadline(String line, ArrayList tasks) throws IllegalDeadlineException, IllegalArgumentException { String description = line.substring(4, line.indexOf("/by")).trim(); - String deadline = line.substring(line.indexOf("/by") + 3, line.indexOf("/day")).trim(); + String deadline = line.substring(line.indexOf("/by") + BY_OFFSET, line.indexOf("/day")).trim(); DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("HHmm"); LocalTime.parse(deadline, timeFormat); - DayOfWeek day = DayOfWeek.valueOf(line.substring(line.indexOf("/day") + 4).trim()); + DayOfWeek day = DayOfWeek.valueOf(line.substring(line.indexOf("/day") + DAY_OFFSET).trim()); if (description.isBlank() || deadline.isBlank()) { throw new IllegalDeadlineException(); } else { @@ -331,122 +342,158 @@ static void editTask(ArrayList tasks, String[] words) throws expiredDateEx } Task taskToEdit = tasks.get(taskNumber - 1); if (taskToEdit instanceof Todo) { - Ui.editTodoMessage(); - String editLine = Ui.askForEditMessage().trim(); - if (editLine.isBlank()) { - throw new EmptyDescriptionException(); - } - taskToEdit.setDescription(editLine); + editTodo(taskToEdit); } else if (taskToEdit instanceof Deadline) { - Ui.editDeadlineMessage(); - String editLine = Ui.askForEditMessage().trim(); - String[] editWords = editLine.split(" "); - if (taskToEdit instanceof RecurringDeadline) { - if (editWords.length > 1 && editWords[0].equals("/description")) { - String newDescription = editLine.substring(12).trim(); - if (newDescription.isBlank()) { - throw new EmptyDescriptionException(); - } - taskToEdit.setDescription(newDescription); - } else if (editWords.length > 1 && editWords[0].equals("/deadline")){ - String deadline = editLine.substring(9).trim(); - LocalTime.parse(deadline, timeFormat); - ((RecurringDeadline) taskToEdit).setDeadline(deadline); - } else if (editWords.length > 1 && editWords[0].equals("/day")) { - DayOfWeek day = DayOfWeek.valueOf(editLine.substring(4).trim()); - ((RecurringDeadline) taskToEdit).setDay(day); - } else { - Ui.unknownCommandMessage(); + editDeadline(words, timeFormat, dateFormat, taskToEdit); + } else if (taskToEdit instanceof Event) { + editEvent(timeFormat, dateFormat, taskToEdit); + } + Ui.printEditedTask(taskToEdit); + } + + /** + * edits an attribute of an event + * @param timeFormat time format for event + * @param dateFormat date format for event + * @param taskToEdit the event to edit + * @throws EmptyDescriptionException if the new description is empty + * @throws startAfterEndException if the start-end time is incorrect + * @throws expiredDateException if the task is expired + */ + private static void editEvent(DateTimeFormatter timeFormat, DateTimeFormatter dateFormat, Task taskToEdit) throws + EmptyDescriptionException, startAfterEndException, expiredDateException { + Ui.editEventMessage(); + String editLine = Ui.askForEditMessage().trim(); + String[] editWords = editLine.split(" "); + if (taskToEdit instanceof RecurringEvent) { + if (editWords.length > 1 && editWords[0].equals("/description")) { + String newDescription = editLine.substring(DESCRIPTION_OFFSET).trim(); + if (newDescription.isBlank()) { + throw new EmptyDescriptionException(); } + taskToEdit.setDescription(newDescription); + } else if (editWords.length > 1 && editWords[0].equals("/from")){ + String start = editLine.substring(FROM_OFFSET).trim(); + LocalTime.parse(start, timeFormat); + ((RecurringEvent) taskToEdit).setStart(start); + } else if (editWords.length > 1 && editWords[0].equals("/to")) { + String end = editLine.substring(TO_OFFSET).trim(); + LocalTime.parse(end, timeFormat); + ((RecurringEvent) taskToEdit).setEnd(end); + } else if(editWords.length > 1 && editWords[0].equals("/day")) { + DayOfWeek day = DayOfWeek.valueOf(editLine.substring(DAY_OFFSET).trim()); + ((RecurringEvent) taskToEdit).setDay(day); } else { - if (editWords.length > 1 && editWords[0].equals("/description")) { - String newDescription = editLine.substring(editLine.indexOf(words[1])); - if (newDescription.isBlank()) { - throw new EmptyDescriptionException(); - } - taskToEdit.setDescription(newDescription); - } else if (editWords.length > 1 && editWords[0].equals("/deadline")) { - String deadlineString = editLine.substring(9).trim(); - System.out.println(deadlineString); - LocalDateTime deadline = LocalDateTime.parse(deadlineString, dateFormat); - if (deadline.isBefore(LocalDateTime.now())){ - throw new expiredDateException(); - } else { - ((Deadline) taskToEdit).setDeadline(deadlineString); - } - } else { - Ui.unknownCommandMessage(); + Ui.unknownCommandMessage(); + } + } else { + LocalDateTime start = LocalDateTime.parse(((Event) taskToEdit).getStart(), dateFormat); + LocalDateTime end = LocalDateTime.parse(((Event) taskToEdit).getEnd(), dateFormat); + String newStartString = null; + String newEndString = null; + LocalDateTime newStart = null; + LocalDateTime newEnd = null; + if (editWords.length > 1 && editWords[0].equals("/description")) { + String newDescription = editLine.substring(DESCRIPTION_OFFSET).trim(); + if (newDescription.isBlank()) { + throw new EmptyDescriptionException(); } + taskToEdit.setDescription(newDescription); + } else if (editWords.length > 1 && editWords[0].equals("/from")){ + newStartString = editLine.substring(FROM_OFFSET).trim(); + newStart = LocalDateTime.parse(newStartString, dateFormat); + } else if (editWords.length > 1 && editWords[0].equals("/to")) { + newEndString = editLine.substring(TO_OFFSET).trim(); + newEnd= LocalDateTime.parse(newEndString, dateFormat); + } else { + Ui.unknownCommandMessage(); } - } else if (taskToEdit instanceof Event) { - Ui.editEventMessage(); - String editLine = Ui.askForEditMessage().trim(); - String[] editWords = editLine.split(" "); - if (taskToEdit instanceof RecurringEvent) { - if (editWords.length > 1 && editWords[0].equals("/description")) { - String newDescription = editLine.substring(12).trim(); - if (newDescription.isBlank()) { - throw new EmptyDescriptionException(); - } - taskToEdit.setDescription(newDescription); - } else if (editWords.length > 1 && editWords[0].equals("/from")){ - String start = editLine.substring(5).trim(); - LocalTime.parse(start, timeFormat); - ((RecurringEvent) taskToEdit).setStart(start); - } else if (editWords.length > 1 && editWords[0].equals("/to")) { - String end = editLine.substring(3).trim(); - LocalTime.parse(end, timeFormat); - ((RecurringEvent) taskToEdit).setEnd(end); - } else if(editWords.length > 1 && editWords[0].equals("/day")) { - DayOfWeek day = DayOfWeek.valueOf(editLine.substring(4).trim()); - ((RecurringEvent) taskToEdit).setDay(day); + if (newStart != null) { + if (newStart.isAfter(end)) { + throw new startAfterEndException(); + } else if (newStart.isBefore(LocalDateTime.now()) || end.isBefore(LocalDateTime.now())) { + throw new expiredDateException(); } else { - Ui.unknownCommandMessage(); + ((Event) taskToEdit).setStart(newStartString); } - } else { - LocalDateTime start = LocalDateTime.parse(((Event) taskToEdit).getStart(), dateFormat); - LocalDateTime end = LocalDateTime.parse(((Event) taskToEdit).getEnd(), dateFormat); - String newStartString = null; - String newEndString = null; - LocalDateTime newStart = null; - LocalDateTime newEnd = null; - if (editWords.length > 1 && editWords[0].equals("/description")) { - String newDescription = editLine.substring(12).trim(); - if (newDescription.isBlank()) { - throw new EmptyDescriptionException(); - } - taskToEdit.setDescription(newDescription); - } else if (editWords.length > 1 && editWords[0].equals("/from")){ - newStartString = editLine.substring(5).trim(); - newStart = LocalDateTime.parse(newStartString, dateFormat); - //((Event) taskToEdit).setStart(newStart); - } else if (editWords.length > 1 && editWords[0].equals("/to")) { - newEndString = editLine.substring(3).trim(); - newEnd= LocalDateTime.parse(newEndString, dateFormat); - //((Event) taskToEdit).setEnd(newEnd); + } else if (newEnd != null) { + if (start.isAfter(newEnd)) { + throw new startAfterEndException(); + } else if (start.isBefore(LocalDateTime.now()) || newEnd.isBefore(LocalDateTime.now())) { + throw new expiredDateException(); } else { - Ui.unknownCommandMessage(); + ((Event) taskToEdit).setEnd(newEndString); } - if (newStart != null) { - if (newStart.isAfter(end)) { - throw new startAfterEndException(); - } else if (newStart.isBefore(LocalDateTime.now()) || end.isBefore(LocalDateTime.now())) { - throw new expiredDateException(); - } else { - ((Event) taskToEdit).setStart(newStartString); - } - } else if (newEnd != null) { - if (start.isAfter(newEnd)) { - throw new startAfterEndException(); - } else if (start.isBefore(LocalDateTime.now()) || newEnd.isBefore(LocalDateTime.now())) { - throw new expiredDateException(); - } else { - ((Event) taskToEdit).setEnd(newEndString); - } + } + } + } + + /** + * edits an attribute of a stored deadline + * + * @param words input split into an array of string + * @param timeFormat time format for deadline + * @param dateFormat date format for deadline + * @param taskToEdit the task to edit + * @throws EmptyDescriptionException if the new description is empty + * @throws expiredDateException if the deadline has expired + */ + private static void editDeadline(String[] words, DateTimeFormatter timeFormat, DateTimeFormatter dateFormat, + Task taskToEdit) throws EmptyDescriptionException, expiredDateException { + Ui.editDeadlineMessage(); + String editLine = Ui.askForEditMessage().trim(); + String[] editWords = editLine.split(" "); + if (taskToEdit instanceof RecurringDeadline) { + if (editWords.length > 1 && editWords[0].equals("/description")) { + String newDescription = editLine.substring(12).trim(); + if (newDescription.isBlank()) { + throw new EmptyDescriptionException(); + } + taskToEdit.setDescription(newDescription); + } else if (editWords.length > 1 && editWords[0].equals("/deadline")){ + String deadline = editLine.substring(DEADLINE_OFFSET).trim(); + LocalTime.parse(deadline, timeFormat); + ((RecurringDeadline) taskToEdit).setDeadline(deadline); + } else if (editWords.length > 1 && editWords[0].equals("/day")) { + DayOfWeek day = DayOfWeek.valueOf(editLine.substring(DAY_OFFSET).trim()); + ((RecurringDeadline) taskToEdit).setDay(day); + } else { + Ui.unknownCommandMessage(); + } + } else { + if (editWords.length > 1 && editWords[0].equals("/description")) { + String newDescription = editLine.substring(editLine.indexOf(words[1])); + if (newDescription.isBlank()) { + throw new EmptyDescriptionException(); } + taskToEdit.setDescription(newDescription); + } else if (editWords.length > 1 && editWords[0].equals("/deadline")) { + String deadlineString = editLine.substring(DEADLINE_OFFSET).trim(); + System.out.println(deadlineString); + LocalDateTime deadline = LocalDateTime.parse(deadlineString, dateFormat); + if (deadline.isBefore(LocalDateTime.now())){ + throw new expiredDateException(); + } else { + ((Deadline) taskToEdit).setDeadline(deadlineString); + } + } else { + Ui.unknownCommandMessage(); } } - Ui.printEditedTask(taskToEdit); + } + + /** + * edits the todd + * @param taskToEdit the todo to edit + * @throws EmptyDescriptionException empty description + */ + private static void editTodo(Task taskToEdit) throws EmptyDescriptionException { + Ui.editTodoMessage(); + String editLine = Ui.askForEditMessage().trim(); + if (editLine.isBlank()) { + throw new EmptyDescriptionException(); + } + taskToEdit.setDescription(editLine); } /** From 3353cb0276f46683a0b944d90e040d5194bd5c68 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Sun, 9 Apr 2023 16:44:04 +0800 Subject: [PATCH 123/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index cbbfaf21a6..a370eafece 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -225,8 +225,19 @@ Below is a class diagram for the implementation |Version| As a ... | I want to ... | So that I can ...| |--------|----------|---------------|------------------| -|v1.0|new user|see usage instructions|refer to them when I forget how to use the application| -|v2.0|user|find a to-do item by name|locate a to-do without having to go through the entire list| +|v1.0|user|have a help command that will display all possible commands and their appropriate input format|understand how to use Duck easily and conveniently| +|v1.0|student|be able to add tasks and events|remind myself constantly| +|v1.0|user|have a command to close the program|exit the program when I want to| +|v1.0|user|have a find filter|find the tasks in the list that contain a specified input keyword| +|v1.0|user|add a priority tag to each task such that they will be easily identified|be aware of urgent tasks to completed| +|v1.0|user|clear function with double check confirmation|delete all tasks from the list, with a confirmation message before clearing| +|v1.0|user|have priority variables for tasks|add priority levels to individual tasks| +|v1.0|student|be able to add school classes|keep track of my classes| +|v2.0|student|receive notifications about deadlines|not miss out on any tasks| +|v2.0|student with different classes|view my next class with its specified time|| +|v2.0|student with multiple classes|record recurring classes at fixed times throughout the week|view my weekly class schedule without needing to record them down again each week| +|v2.0|student|create recurring tasks that will reset their 'Done' status when appropriate|not have to manually unmark these tasks| +|v2.0|student|easily access my schedule|plan my daily life| ## Non-Functional Requirements From bd84f4bbdf49a8e5665531413d516f60f328c6f3 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Sun, 9 Apr 2023 17:25:36 +0800 Subject: [PATCH 124/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index a370eafece..3d3e07e790 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -215,11 +215,11 @@ Below is a class diagram for the implementation ## Product scope ### Target user profile -{Describe the target user profile} +Duck is a program developed for students with multiple tasks such as deadlines and events, as well as many different classes who prefer CLI applications. ### Value proposition -{Describe the value proposition: what problem does it solve?} +Duck will be able to allow students who can type fast to quickly record down the tasks that they need to do, as well as helping them keep track of their different classes in an organised manner. By inputting short commands, students will be able to retrieve information on their upcoming tasks and classes and any related notes easily. ## User Stories @@ -241,12 +241,37 @@ Below is a class diagram for the implementation ## Non-Functional Requirements -{Give non-functional requirements} +1. Duck should be able to run on Macos, Windows and Linux with at least Java 11 installed. +2. Recorded tasks and classes should not be lost when the program or the system is shut down. +3. Users who are proficient in typing should be able to accomplish the different tasks faster than a typical user trying to accomplish the same tasks with a GUI instead. ## Glossary -* *glossary item* - Definition +* *Duck* - The name of the program +* *Task* - A task that can be recorded in Duck (Todo, Deadline, Event) +* *Command* - Lines of input that when typed into the terminal, will execute appropriate functions as indicated in the User Guide ## Instructions for manual testing {Give instructions on how to do a manual product testing e.g., how to load sample data to be used for testing} + +### Launching the program +1. Ensure that Java 11 or above is installed +2. Download the latest version of Duck +3. Launch the terminal and navigate to the folder where Duck is located in +4. Type in the command ```java -jar Duck.jar``` to lauch Duck + - Expected Outcome: Duck launches in the terminal with its start message displayed. + +### Closing the program +1. Type ```bye``` in the terminal to exit the program + - Expected Outcome: The exit message is displayed in the terminal, and the program closes. + +### Storage and Save Data +- If Duck is run for the first time, the save file will be generated automatically along with the ```data``` folder + - Expected Outcome: The ```data``` folder will be created, and the ```savedata.txt``` file will be created inside this folder + +- After any changes are made to the list of tasks or schedule, the changes will be stored in to the save file located in ```data/savedata.txt``` + - Expected Outcome: Any newly added tasks or school classes or other changes made will be reflected in the ```savedata.txt``` file + +- If any edits or changes are made directly to the ```savedata.txt``` file (which users are strongly recommended not to do so) which leads to the save file being invalid, the ```savedata.txt``` file will have all its data wiped upon starting up Duck. + - Expected Outcome: An error message will be displayed in the terminal when Duck is lauched, with none of the previously saved tasks or classes being loaded. The ```savedata.txt``` file will have all of its contents erased. From 47a3d6d17bce66a7dedf5b86fb06bcd66a35a253 Mon Sep 17 00:00:00 2001 From: sunkyan Date: Sun, 9 Apr 2023 17:28:16 +0800 Subject: [PATCH 125/152] fixed list x --- src/main/java/seedu/duck/TaskList.java | 2 +- src/main/java/seedu/duck/Ui.java | 38 ++++++++++++-------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index b6fbf7c2e6..6ed3354bfd 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -22,7 +22,7 @@ */ public class TaskList { private static final int DESCRIPTION_OFFSET = 12; - private static final int DEADLINE_OFFSET = 12; + private static final int DEADLINE_OFFSET = 9; private static final int FROM_OFFSET = 5; private static final int TO_OFFSET = 3; private static final int DAY_OFFSET = 4; diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 390563bc02..823fc875a2 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -7,13 +7,7 @@ import java.time.DayOfWeek; import java.time.LocalDate; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Date; -import java.util.Iterator; -import java.util.Objects; -import java.util.PriorityQueue; -import java.util.Scanner; -import java.util.Random; +import java.util.*; /** @@ -384,24 +378,20 @@ static void printUpcomingTasks(ArrayList tasks, String days) { Date d; Date n = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HHmm"); + int requiredDays = Integer.parseInt(days); for (Task t : tasks) { String timeUntilTask = null; if (t instanceof Deadline && !(t instanceof RecurringDeadline)) { timeUntilTask = ((Deadline) t).getDeadline(); } else if (t instanceof Event && !(t instanceof RecurringEvent)) { timeUntilTask = ((Event) t).getStart(); - } else if (t instanceof SchoolClass) { - timeUntilTask = ((SchoolClass) t).getStart(); } if (timeUntilTask != null) { try { d = format.parse(timeUntilTask); long diff = d.getTime() - n.getTime(); - String di = getTimeDiff(diff); - String[] diffSplit = di.split(" "); - if (diffSplit.length >= 2 && ((diffSplit[1].contains("day") && Integer.parseInt(diffSplit[0]) - <= Integer.parseInt(days)) || diffSplit[1].contains("hour") - || diffSplit[1].contains("minute"))) { + int di = getDayDiff(diff); + if (di <= requiredDays) { count++; System.out.println("\t " + count + "." + t); } @@ -495,6 +485,15 @@ static void printUpcomingDeadline(ArrayList tasks, String days) { borderLine(); } + /** + * gets the day difference + * @param timeDifferenceMilliseconds time difference between now and the input time + * @return day difference + */ + static int getDayDiff(long timeDifferenceMilliseconds) { + return (int) (timeDifferenceMilliseconds / (secondsPerMinute * minutesPerHour * 1000 * hoursPerDay)); + } + static final int secondsPerMinute = 60; static final int minutesPerHour = 60; static final int hoursPerDay = 24; @@ -508,12 +507,11 @@ static void printUpcomingDeadline(ArrayList tasks, String days) { * @return time difference in structured format */ static String getTimeDiff(long timeDifferenceMilliseconds) { - - long diffMinutes = timeDifferenceMilliseconds / (secondsPerMinute * 1000) % secondsPerMinute; - long diffHours = timeDifferenceMilliseconds / (secondsPerMinute * minutesPerHour * 1000) % minutesPerHour; - long diffDays = timeDifferenceMilliseconds / (secondsPerMinute * minutesPerHour * 1000 * hoursPerDay) % hoursPerDay; - long diffMonths = (long) ((timeDifferenceMilliseconds / (secondsPerMinute * minutesPerHour * 1000 * hoursPerDay * daysPerMonth)) % daysPerMonth); - long diffYears = (long) ((timeDifferenceMilliseconds / ( secondsPerMinute * minutesPerHour * 1000 * hoursPerDay * daysPerMonth * monthsPerYear)) % monthsPerYear); + long diffMinutes = timeDifferenceMilliseconds / (secondsPerMinute * 1000) % minutesPerHour; + long diffHours = timeDifferenceMilliseconds / (secondsPerMinute * minutesPerHour * 1000) % hoursPerDay; + long diffDays = (long) (timeDifferenceMilliseconds / (secondsPerMinute * minutesPerHour * 1000 * hoursPerDay) % daysPerMonth); + long diffMonths = (long) (timeDifferenceMilliseconds / (secondsPerMinute * minutesPerHour * 1000 * hoursPerDay * daysPerMonth)) % monthsPerYear; + long diffYears = (long) (timeDifferenceMilliseconds / ( secondsPerMinute * minutesPerHour * 1000 * hoursPerDay * daysPerMonth * monthsPerYear)); String result = ""; if (diffYears != 0) { result += diffYears; From 6b98495f9ba16dd6fc32c2c2dde3f2fff06186ba Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Sun, 9 Apr 2023 17:34:11 +0800 Subject: [PATCH 126/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 3d3e07e790..03d1699caa 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -2,7 +2,7 @@ ## Acknowledgements -{list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well} +Reused iP to serve as base code from [jeraldgau/ip](https://github.com/jeraldgau/ip) ## Architecture @@ -238,6 +238,10 @@ Duck will be able to allow students who can type fast to quickly record down the |v2.0|student with multiple classes|record recurring classes at fixed times throughout the week|view my weekly class schedule without needing to record them down again each week| |v2.0|student|create recurring tasks that will reset their 'Done' status when appropriate|not have to manually unmark these tasks| |v2.0|student|easily access my schedule|plan my daily life| +|v2.0|user|automatically remove my expired tasks|not deal with the hassle of having to manually remove expired tasks| +|v2.0|user|add notes to my tasks|record down additional details| +|v2.0|user|edit my tasks|change previously recorded information| +|v2.0|student|delete my classes|remove classes that are no longer necessary| ## Non-Functional Requirements From 364f2961772bdb1d28b9e708942ddc5eb5b90bb2 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Sun, 9 Apr 2023 17:46:02 +0800 Subject: [PATCH 127/152] Update jeraldgau.md --- docs/team/jeraldgau.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/team/jeraldgau.md b/docs/team/jeraldgau.md index 5dfbdc31a6..c60b51dbb7 100644 --- a/docs/team/jeraldgau.md +++ b/docs/team/jeraldgau.md @@ -50,6 +50,7 @@ Duck is a desktop task and class tracker for users to keep track of their schedu - Added design and implementation details of the SchoolClass feature - Added the sequence diagram for the ```Adding a School Class``` function - Added the sequence diagram for the ```list_classes``` function + - Added Product Scope, User Stories, Non-Functional Requirements, Glossary, and Instructions for Manual Testing ### Community: From 650ee7ac1e369122ff3cb8b5203d9bd070467cc4 Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Mon, 10 Apr 2023 00:42:00 +0800 Subject: [PATCH 128/152] Fixed hyperlinks in UG, fixed more bugs that were surfaced, updated list function to print seperate function if there are no tasks in the arraylist --- docs/UserGuide.md | 26 +++++++++++++------------- docs/team/miahjerry.md | 7 +++++-- src/main/java/seedu/duck/Ui.java | 28 ++++++++++++++++------------ 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 02ef5fcaa3..191b5ac31c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -10,27 +10,27 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * [Listing all tasks and classes happening today :](#listing-all-tasks--list) `list_today` * [Listing all tasks up to X days into the future :](#listing-all-tasks-up-to-x-days-in-the-future--list-x) `list X` * [Displaying upcoming deadline](#displaying-upcoming-deadline) - * [Displaying class schedule :](#displaying-class-schedule--list-classes) `list_classes` + * [Displaying class schedule :](#displaying-class-schedule--listclasses) `list_classes` * [Displaying upcoming class :](#displaying-upcoming-class--upcomingclass) `upcoming_class` * [Displaying upcoming deadline :](#displaying-upcoming-class--upcomingdeadline) `upcoming_deadline` - * [Displaying_upcoming_event :](#displaying-upcoming-event--upcomingevent) `upcoming_event` - * [Mark a specified task as done :](#marking-a-task--mark-task_number) `mark ` - * [Unmark a specified task as not done :](#unmarking-a-task--unmark-task_number) `unmark ` - * [Edit a specific piece information of a task :](#editing-a-task--edit-task_number) `edit ` + * [Displaying upcoming event :](#displaying-upcoming-event--upcomingevent) `upcoming_event` + * [Mark a specified task as done :](#marking-a-task--mark-tasknumber) `mark ` + * [Unmark a specified task as not done :](#unmarking-a-task--unmark-tasknumber) `unmark ` + * [Edit a specific piece information of a task :](#editing-a-task--editnotes) `edit ` * [Deleting a task :](#deleting-a-task--delete) `delete ` * [Deleting a school class :](#deleting-a-school-class--remove-class) `remove /class /description /day /from /to ` - * [Designate a priority to a given task :](#designate-a-task-priority--priority-task_number-priority) `priority ` - * [Adding notes for a specific task :](#adding-notes-for-a-specific-task--add_notes) `add_notes ` - * [Deleting notes for a specific task :](#deleting-notes-for-a-specific-task--delete_notes) `delete_notes ` - * [Editing notes for a specific task :](#editing-notes-for-a-specific-task--edit_notes) `edit_notes ` - * [Viewing notes for a specific task :](#printing-notes-for-a-specific-task--view_notes) `view_notes ` - * [List tasks of low/medium/high priority :](#listing-all-low-priority-tasks--low_priority) `low_priority`/`medium_priority`/`high_priority` - * [List tasks in priority order:](#listing-all-tasks-arranged-by-priority--priority_list) `priority_list` + * [Designate a priority to a given task :](#designate-a-task-priority--priority-tasknumber-priority) `priority ` + * [Adding notes for a specific task :](#adding-notes-for-a-specific-task--addnotes) `add_notes ` + * [Deleting notes for a specific task :](#deleting-notes-for-a-specific-task--deletenotes) `delete_notes ` + * [Editing notes for a specific task :](#editing-notes-for-a-specific-task--editnotes) `edit_notes ` + * [Viewing notes for a specific task :](#printing-notes-for-a-specific-task--viewnotes) `view_notes ` + * [List tasks of low/medium/high priority :](#listing-all-low-priority-tasks--lowpriority) `low_priority`/`medium_priority`/`high_priority` + * [List tasks in priority order:](#listing-all-tasks-arranged-by-priority--prioritylist) `priority_list` * [Purge expired tasks :](#purge-expired-tasks--purge) `purge` * [Clearing all tasks (including datafile) :](#clearing-tasks-from-storage-clear) `clear ` * [Find tasks matching a given keyword :](#finding-tasks-from-storage-that-match-a-keyword-find-keyword) `find ` * [Add tasks that can be broken down into the following 6 types:](#adding-a-todo-task--todo-description) - + * Add ToDo: /todo * Add Deadline: /by * Add RecurringDeadline: /re /by /day diff --git a/docs/team/miahjerry.md b/docs/team/miahjerry.md index 41585542dd..6c80d7ca97 100644 --- a/docs/team/miahjerry.md +++ b/docs/team/miahjerry.md @@ -29,7 +29,7 @@ The note will be saved when Duck is closed ### New Feature: Deleting notes under tasks -- his feature allows the user to delete notes that have been created for whatever reason +- This feature allows the user to delete notes that have been created for whatever reason - By following the steps outlined by the user guide, existing notes can be deleted under their respective tasks. ### New Feature: Editing notes under tasks @@ -56,11 +56,14 @@ The note will be saved when Duck is closed ### Project Management: - Helped to host group meetings and organize them to ensure group was on task and on the same page -- Liased with other groups to promote mutual stress-testing of each other's product +- Liased with other groups to carry out mutual stress-testing of each other's product +- Updated team of new merges and PRs whenever necessary ### Documentation: - User Guide: - Added documentation for the features ```print_priority```, ```low_priority```,```medium_priority```, ```high_priority```, ```add_notes```, ```edit_notes```, ```delete_notes```,and ```motivation``` + - Helped to fix bugs with the hyperlink to enable easier navigation of the UG ### Community: - Reported bugs and suggestions for other teams (examples: [1](https://github.com/miahjerry/ped/issues/4), [2](https://github.com/miahjerry/ped/issues/7), [3](https://github.com/miahjerry/ped/issues/8)) +- Helped to connect to other teams for mutual stress testing of products (examples: [1](https://ginger-vicuna-3c7.notion.site/Duck-jar-62da4045517945f880b94392f6c0478e),[2](https://docs.google.com/document/d/1Um9IQ-UzBePFyVlHz3TH4wGpermMRMWOpBLmJe6c0IM/edit?usp=sharing)) \ No newline at end of file diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 823fc875a2..c527c7edbd 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -77,12 +77,16 @@ static void printMotivationalQuote() { static void list(ArrayList tasks) { int taskCount = Task.getTaskCount(); borderLine(); - System.out.println("\t Here are the tasks in your list:"); - for (int i = 0; i < taskCount; i++) { - System.out.println("\t " + (i + 1) + "." + tasks.get(i)); - if (!tasks.get(i).getAdditionalNotes().isEmpty()) { - printList(tasks, i); + if(!tasks.isEmpty()) { + System.out.println("\t Here are the tasks in your list:"); + for (int i = 0; i < taskCount; i++) { + System.out.println("\t " + (i + 1) + "." + tasks.get(i)); + if (!tasks.get(i).getAdditionalNotes().isEmpty()) { + printList(tasks, i); + } } + } else { + System.out.println("\t There are no tasks in the list currently!"); } borderLine(); } @@ -313,7 +317,7 @@ static void printMatchingList(ArrayList matchingResults, int matchCount, * @param tasks tasks store in the file */ static void displayUpcomingDeadline(ArrayList tasks) { - System.out.println("\t Here are the upcoming deadline: "); + System.out.println("\t Here are the upcoming deadlines: "); int count = 0; for (Task t : tasks) { if (t instanceof Deadline && !(t instanceof RecurringDeadline)) { @@ -342,7 +346,7 @@ static void displayUpcomingDeadline(ArrayList tasks) { * @param tasks tasks store in the file */ static void displayUpcomingEvent(ArrayList tasks) { - System.out.println("\t Here are the upcoming event: "); + System.out.println("\t Here are the upcoming events: "); int count = 0; for (Task t : tasks) { if (t instanceof Event && !(t instanceof RecurringEvent)) { @@ -708,6 +712,9 @@ static void help() { System.out.println("\t - priority_list: " + "I'll list out all the tasks you have recorded arranged by their priority."); System.out.println("\t - upcoming_class: I'll list out the next upcoming class."); + System.out.println("\t - priority <1/2/3>: I'll set the priority of a given task as"); + System.out.println("\t 1:Low, 2:Medium and 3:High."); + System.out.println("\t Default: Low priority."); System.out.println("\t - low_priority: I'll list out all the tasks you have that are low in priority."); System.out.println("\t - medium_priority: I'll list out all the tasks you have that are medium in priority."); System.out.println("\t - high_priority: I'll list out all the tasks you have that are high in priority."); @@ -726,9 +733,6 @@ static void help() { System.out.println("\t - purge: I'll delete all expired tasks from your list after a confirmation."); System.out.println("\t - find : I'll find the tasks in your list that contain the keyword."); System.out.println("\t - The index of the item will also be displayed."); - System.out.println("\t - priority <1/2/3>: I'll set the priority of a given task as"); - System.out.println("\t 1:Low, 2:Medium and 3:High."); - System.out.println("\t Default: Low priority."); System.out.println("\t - motivation: I'll print a random motivational quack for you!"); System.out.println("\t - bye: I will shut down my program.\n"); System.out.println("\t Here are the following ways to input tasks/classes:"); @@ -921,9 +925,9 @@ static void printNotes(ArrayList tasks, String[] words) { ArrayList toBePrinted = tasks.get(index - 1).getAdditionalNotes(); borderLine(); if (!toBePrinted.isEmpty()) { + System.out.println("\t Here are the notes for that task quack!"); + System.out.println(tasks.get(index - 1).toString()); for (int i = 0; i < toBePrinted.size(); i++) { - System.out.println("\t Here are the notes for that task quack!"); - System.out.println(tasks.get(index - 1).toString()); System.out.println("\t \t" + (i + 1) + ". " + toBePrinted.get(i)); } } else { From 16064f862e3ffe0277b79f7fb775e7862502d72c Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Mon, 10 Apr 2023 11:16:14 +0800 Subject: [PATCH 129/152] Updated docs --- docs/team/miahjerry.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/team/miahjerry.md b/docs/team/miahjerry.md index 6c80d7ca97..40e8c03089 100644 --- a/docs/team/miahjerry.md +++ b/docs/team/miahjerry.md @@ -24,8 +24,7 @@ Duck is a desktop task and class tracker for users to keep track of their schedu ### New Feature: Adding notes to tasks - Allows the user to add a note to the specified task -- By following the steps outlined by the user guide, a note can be added to a task. -The note will be saved when Duck is closed +- By following the steps outlined by the user guide, a note can be added to a task. ### New Feature: Deleting notes under tasks @@ -66,4 +65,5 @@ The note will be saved when Duck is closed ### Community: - Reported bugs and suggestions for other teams (examples: [1](https://github.com/miahjerry/ped/issues/4), [2](https://github.com/miahjerry/ped/issues/7), [3](https://github.com/miahjerry/ped/issues/8)) -- Helped to connect to other teams for mutual stress testing of products (examples: [1](https://ginger-vicuna-3c7.notion.site/Duck-jar-62da4045517945f880b94392f6c0478e),[2](https://docs.google.com/document/d/1Um9IQ-UzBePFyVlHz3TH4wGpermMRMWOpBLmJe6c0IM/edit?usp=sharing)) \ No newline at end of file +- Helped to connect to other teams for more feedback on Duck (examples: [1](https://ginger-vicuna-3c7.notion.site/Duck-jar-62da4045517945f880b94392f6c0478e),[2](https://docs.google.com/document/d/1Um9IQ-UzBePFyVlHz3TH4wGpermMRMWOpBLmJe6c0IM/edit?usp=sharing)) +- Helped to give other teams feedback on their product (examples: [1](https://docs.google.com/document/d/1UVnMxMm19w6zJRVTrtQq-U1MtQGjcguNfLYa4f1Uh28/edit?usp=sharing),[2](https://docs.google.com/document/d/1JXlZDlqaf9X08aNsDAeK3y8I08eVEqsbz_Pqo6yOFTo/edit?usp=sharing)) \ No newline at end of file From 9d17a298571b2d53474dbf1b093a4109a17a2001 Mon Sep 17 00:00:00 2001 From: sunkyan Date: Mon, 10 Apr 2023 13:28:25 +0800 Subject: [PATCH 130/152] imroved coding standard. refactored arrowhead method --- src/main/java/seedu/duck/Ui.java | 58 ++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index c527c7edbd..5209c1f7a6 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -124,30 +124,52 @@ static void listToday(ArrayList tasks, PriorityQueue classes) System.out.println("\t Here are your tasks today"); for (Task task : tasks) { if (task instanceof Deadline) { - if (task instanceof RecurringDeadline) { - if (((RecurringDeadline) task).getDay() == dayToday) { - System.out.println(task); - } - } else { - if (((Deadline) task).getDeadline().startsWith(dateToday)) { - System.out.println(task); - } - } + listTodayDeadline(dayToday, dateToday, task); } else if (task instanceof Event) { - if (task instanceof RecurringEvent) { - if (((RecurringEvent) task).getDay() == dayToday) { - System.out.println(task); - } - } else { - if (((Event) task).getStart().startsWith(dateToday)) { - System.out.println(task); - } - } + listTodayEvent(dayToday, dateToday, task); } } borderLine(); } + /** + * checks if an event happens today and prints the task if yes + * + * @param dayToday the DayOfWeek today + * @param dateToday the date today + * @param task the task (event specifically) to be checked + */ + private static void listTodayEvent(DayOfWeek dayToday, String dateToday, Task task) { + if (task instanceof RecurringEvent) { + if (((RecurringEvent) task).getDay() == dayToday) { + System.out.println(task); + } + } else { + if (((Event) task).getStart().startsWith(dateToday)) { + System.out.println(task); + } + } + } + + /** + * checks if a deadline happens today and prints the task if yes + * + * @param dayToday the DayOfWeek today + * @param dateToday the date today + * @param task the task (deadline specifically) to be checked + */ + private static void listTodayDeadline(DayOfWeek dayToday, String dateToday, Task task) { + if (task instanceof RecurringDeadline) { + if (((RecurringDeadline) task).getDay() == dayToday) { + System.out.println(task); + } + } else { + if (((Deadline) task).getDeadline().startsWith(dateToday)) { + System.out.println(task); + } + } + } + /** * Prints out all currently stored tasks in the list arranged by their priority from high, medium to low * From d44615f38626322512adfc0952e950f0f27f513e Mon Sep 17 00:00:00 2001 From: skyanzy <88618401+skyanzy@users.noreply.github.com> Date: Mon, 10 Apr 2023 13:42:36 +0800 Subject: [PATCH 131/152] Update skyanzy.md --- docs/team/skyanzy.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/team/skyanzy.md b/docs/team/skyanzy.md index 9294671657..4016d1c387 100644 --- a/docs/team/skyanzy.md +++ b/docs/team/skyanzy.md @@ -37,6 +37,7 @@ Duck is a desktop task and class tracker for users to keep track of their schedu ### Project Management: - Updating the team when a new PR is merged to ensure everyone is on the same page. - Integration of different parts when a new feature is implemented. +- Seting up milestone v2.1 and dividing issues among the team members. ### Documentation: - User Guide: From acef6db2f3efa19b6169f18f9746f74e7b064c3a Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Mon, 10 Apr 2023 13:43:49 +0800 Subject: [PATCH 132/152] Updated PPP --- docs/team/miahjerry.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/team/miahjerry.md b/docs/team/miahjerry.md index 40e8c03089..9a7dad6e4f 100644 --- a/docs/team/miahjerry.md +++ b/docs/team/miahjerry.md @@ -49,6 +49,7 @@ Duck is a desktop task and class tracker for users to keep track of their schedu ### Cleaning up of code - Helped to make the code more defensive to prevent bad inputs from crashing Duck, specifically indexes that accessed out of bounds +- Helped to refactor code to better fulfil coding standard ### Code Contributed: [RepoSense Link](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=miahjerry&breakdown=true&sort=groupTitle%20dsc&sortWithin=title&since=2023-02-17&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other) @@ -64,6 +65,5 @@ Duck is a desktop task and class tracker for users to keep track of their schedu - Helped to fix bugs with the hyperlink to enable easier navigation of the UG ### Community: -- Reported bugs and suggestions for other teams (examples: [1](https://github.com/miahjerry/ped/issues/4), [2](https://github.com/miahjerry/ped/issues/7), [3](https://github.com/miahjerry/ped/issues/8)) - Helped to connect to other teams for more feedback on Duck (examples: [1](https://ginger-vicuna-3c7.notion.site/Duck-jar-62da4045517945f880b94392f6c0478e),[2](https://docs.google.com/document/d/1Um9IQ-UzBePFyVlHz3TH4wGpermMRMWOpBLmJe6c0IM/edit?usp=sharing)) -- Helped to give other teams feedback on their product (examples: [1](https://docs.google.com/document/d/1UVnMxMm19w6zJRVTrtQq-U1MtQGjcguNfLYa4f1Uh28/edit?usp=sharing),[2](https://docs.google.com/document/d/1JXlZDlqaf9X08aNsDAeK3y8I08eVEqsbz_Pqo6yOFTo/edit?usp=sharing)) \ No newline at end of file +- Helped to give other teams feedback on their product (examples: [1](https://docs.google.com/document/d/1UVnMxMm19w6zJRVTrtQq-U1MtQGjcguNfLYa4f1Uh28/edit?usp=sharing),[2](https://docs.google.com/document/d/1JXlZDlqaf9X08aNsDAeK3y8I08eVEqsbz_Pqo6yOFTo/edit?usp=sharing),[3](https://github.com/miahjerry/ped/issues/4)) \ No newline at end of file From da8d0fab88c60c4b647a2862279363d572a5ea18 Mon Sep 17 00:00:00 2001 From: jeraldgau Date: Mon, 10 Apr 2023 14:39:38 +0800 Subject: [PATCH 133/152] Minor tweaks according to code review --- src/main/java/seedu/duck/TaskList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/duck/TaskList.java b/src/main/java/seedu/duck/TaskList.java index c8521ed496..0f04b15f83 100644 --- a/src/main/java/seedu/duck/TaskList.java +++ b/src/main/java/seedu/duck/TaskList.java @@ -18,7 +18,7 @@ import java.util.Scanner; /** - * Contains operations to manipulate the task list + * Contains operations to make changes to the list of tasks or the class schedule */ public class TaskList { private static final int DESCRIPTION_OFFSET = 12; From 3bc28504e1b161631cf5a51476e5928268b4c442 Mon Sep 17 00:00:00 2001 From: sunkyan Date: Mon, 10 Apr 2023 15:54:23 +0800 Subject: [PATCH 134/152] added some junit tests for TaskList --- src/main/java/seedu/duck/Ui.java | 15 +++- src/test/java/seedu/duck/TaskListTest.java | 92 ++++++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 src/test/java/seedu/duck/TaskListTest.java diff --git a/src/main/java/seedu/duck/Ui.java b/src/main/java/seedu/duck/Ui.java index 5209c1f7a6..2fa76b88eb 100644 --- a/src/main/java/seedu/duck/Ui.java +++ b/src/main/java/seedu/duck/Ui.java @@ -1,13 +1,24 @@ package seedu.duck; -import seedu.duck.task.*; +import seedu.duck.task.Deadline; +import seedu.duck.task.Event; +import seedu.duck.task.RecurringDeadline; +import seedu.duck.task.RecurringEvent; +import seedu.duck.task.SchoolClass; +import seedu.duck.task.Task; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.format.DateTimeFormatter; -import java.util.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.Objects; +import java.util.PriorityQueue; +import java.util.Random; +import java.util.Scanner; /** diff --git a/src/test/java/seedu/duck/TaskListTest.java b/src/test/java/seedu/duck/TaskListTest.java new file mode 100644 index 0000000000..736a3bb4ea --- /dev/null +++ b/src/test/java/seedu/duck/TaskListTest.java @@ -0,0 +1,92 @@ +package seedu.duck; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +import seedu.duck.exception.IllegalDeadlineException; +import seedu.duck.exception.IllegalEventException; +import seedu.duck.exception.IllegalTodoException; +import seedu.duck.exception.expiredDateException; +import seedu.duck.exception.startAfterEndException; +import seedu.duck.task.Deadline; +import seedu.duck.task.Event; +import seedu.duck.task.RecurringDeadline; +import seedu.duck.task.RecurringEvent; +import seedu.duck.task.Task; +import seedu.duck.task.Todo; + +import java.util.ArrayList; + +public class TaskListTest { + @Test + public void addTodo_correctCommand_correctTypeAdded() throws IllegalTodoException { + ArrayList testTasks = new ArrayList<>(); + String line = "/todo todo"; + TaskList.addTodo(line, testTasks); + assertTrue(testTasks.get(0) instanceof Todo); + } + + @Test + public void addTodo_correctCommand_correctDescriptionAdded() throws IllegalTodoException { + ArrayList testTasks = new ArrayList<>(); + String line = "/todo todo"; + TaskList.addTodo(line, testTasks); + assertEquals("todo", testTasks.get(0).getDescription()); + } + @Test + public void addDeadline_correctCommand() throws expiredDateException, IllegalDeadlineException { + ArrayList testTasks = new ArrayList<>(); + String line = "deadline /by 2023-04-30 1200"; + TaskList.addDeadline(line, testTasks); + assertTrue(testTasks.get(0) instanceof Deadline && !(testTasks.get(0) instanceof RecurringDeadline)); + assertEquals("deadline", testTasks.get(0).getDescription()); + } + + @Test + public void addRecurringDeadline_correctCommand() throws IllegalDeadlineException { + ArrayList testTasks = new ArrayList<>(); + String line = "/re deadline /by 1200 /day MONDAY"; + TaskList.addRecurringDeadline(line, testTasks); + assertTrue(testTasks.get(0) instanceof RecurringDeadline); + assertEquals("deadline", testTasks.get(0).getDescription()); + } + + @Test + public void addEvent_correctCommand() throws expiredDateException, startAfterEndException, + IllegalEventException { + ArrayList testTasks = new ArrayList<>(); + String line = "event /from 2023-04-30 1200 /to 2023-04-30 1900"; + TaskList.addEvent(line, testTasks); + assertTrue(testTasks.get(0) instanceof Event && !(testTasks.get(0) instanceof RecurringEvent)); + assertEquals("event", testTasks.get(0).getDescription()); + } + + @Test + public void addRecurringEvent_correctCommand() throws IllegalEventException { + ArrayList testTasks = new ArrayList<>(); + String line = "/re event /from 1200 /to 1900 /day MONDAY"; + TaskList.addRecurringEvent(line, testTasks); + assertTrue(testTasks.get(0) instanceof RecurringEvent); + assertEquals("event", testTasks.get(0).getDescription()); + } + + @Test + public void setPriority_correctCommand() { + ArrayList testTasks = new ArrayList<>(); + Todo todo = new Todo("todo"); + testTasks.add(todo); + Task.incrementCount(); + int firstPri = 2; + int secondPri = 3; + String firstTest = "priority 1 2"; + String secondTest = "priority 1 3"; + String[] wordsOne = firstTest.split(" "); + String[] wordsTwo = secondTest.split(" "); + TaskList.setPriority(testTasks, wordsOne); + assertEquals(firstPri, testTasks.get(0).getPriorityIndex()); + TaskList.setPriority(testTasks, wordsTwo); + assertEquals(secondPri, testTasks.get(0).getPriorityIndex()); + } +} From 05d3cf2e74b040e86bbea401ce06c031bda4d326 Mon Sep 17 00:00:00 2001 From: thant Date: Mon, 10 Apr 2023 18:12:14 +0800 Subject: [PATCH 135/152] Update UserGuide.md Fixed hyperlinking, typo cleanup --- docs/UserGuide.md | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 191b5ac31c..cb9e00e8b6 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -9,23 +9,22 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * [Listing all tasks :](#listing-all-tasks--list) `list` * [Listing all tasks and classes happening today :](#listing-all-tasks--list) `list_today` * [Listing all tasks up to X days into the future :](#listing-all-tasks-up-to-x-days-in-the-future--list-x) `list X` - * [Displaying upcoming deadline](#displaying-upcoming-deadline) - * [Displaying class schedule :](#displaying-class-schedule--listclasses) `list_classes` - * [Displaying upcoming class :](#displaying-upcoming-class--upcomingclass) `upcoming_class` - * [Displaying upcoming deadline :](#displaying-upcoming-class--upcomingdeadline) `upcoming_deadline` - * [Displaying upcoming event :](#displaying-upcoming-event--upcomingevent) `upcoming_event` - * [Mark a specified task as done :](#marking-a-task--mark-tasknumber) `mark ` - * [Unmark a specified task as not done :](#unmarking-a-task--unmark-tasknumber) `unmark ` - * [Edit a specific piece information of a task :](#editing-a-task--editnotes) `edit ` + * [Displaying class schedule :](#displaying-class-schedule--list_classes) `list_classes` + * [Displaying upcoming class :](#displaying-upcoming-class--upcoming_class) `upcoming_class` + * [Displaying upcoming deadline :](#displaying-upcoming-class--upcoming_deadline) `upcoming_deadline` + * [Displaying upcoming event :](#displaying-upcoming-event--upcoming_event) `upcoming_event` + * [Mark a specified task as done :](#marking-a-task--mark-task_number) `mark ` + * [Unmark a specified task as not done :](#unmarking-a-task--unmark-task_number) `unmark ` + * [Edit a specific piece of information for a given task :](#editing-a-task--edit-task_number) `edit ` * [Deleting a task :](#deleting-a-task--delete) `delete ` * [Deleting a school class :](#deleting-a-school-class--remove-class) `remove /class /description /day /from /to ` - * [Designate a priority to a given task :](#designate-a-task-priority--priority-tasknumber-priority) `priority ` - * [Adding notes for a specific task :](#adding-notes-for-a-specific-task--addnotes) `add_notes ` - * [Deleting notes for a specific task :](#deleting-notes-for-a-specific-task--deletenotes) `delete_notes ` - * [Editing notes for a specific task :](#editing-notes-for-a-specific-task--editnotes) `edit_notes ` - * [Viewing notes for a specific task :](#printing-notes-for-a-specific-task--viewnotes) `view_notes ` - * [List tasks of low/medium/high priority :](#listing-all-low-priority-tasks--lowpriority) `low_priority`/`medium_priority`/`high_priority` - * [List tasks in priority order:](#listing-all-tasks-arranged-by-priority--prioritylist) `priority_list` + * [Designate a priority to a given task :](#designate-a-task-priority--priority-task_number-priority) `priority ` + * [Adding notes for a specific task :](#adding-notes-for-a-specific-task--add_notes) `add_notes ` + * [Deleting notes for a specific task :](#deleting-notes-for-a-specific-task--delete_notes) `delete_notes ` + * [Editing notes for a specific task :](#editing-notes-for-a-specific-task--edit_notes) `edit_notes ` + * [Viewing notes for a specific task :](#printing-notes-for-a-specific-task--view_notes) `view_notes ` + * [List tasks of low/medium/high priority :](#listing-all-low-priority-tasks--low_priority) `low_priority`/`medium_priority`/`high_priority` + * [List tasks in priority order:](#listing-all-tasks-arranged-by-priority--priority_list) `priority_list` * [Purge expired tasks :](#purge-expired-tasks--purge) `purge` * [Clearing all tasks (including datafile) :](#clearing-tasks-from-storage-clear) `clear ` * [Find tasks matching a given keyword :](#finding-tasks-from-storage-that-match-a-keyword-find-keyword) `find ` @@ -101,16 +100,6 @@ Displays all deadlines, events and classes happening today. [E][ ] study (from: 0800 to: 2300) (every WEDNESDAY) (Low priority.) ____________________________________________________________ ``` -## **Displaying upcoming deadline** - -Displays upcoming deadline stored in the application when starting the application. - -**Output: The upcoming deadline with remaining time before the deadline** - -``` -Here are the upcoming deadline: -1.Eat bread (1 day 26 hours 50 minutes before the deadline) -``` ## **Displaying class schedule : `list_classes`** From 32fa37413d6e301be172d0ef5ee2c28ba0ddafe0 Mon Sep 17 00:00:00 2001 From: Jerald Gau <88079008+jeraldgau@users.noreply.github.com> Date: Mon, 10 Apr 2023 18:15:44 +0800 Subject: [PATCH 136/152] Update AboutUs.md --- docs/AboutUs.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 93e19c4537..7b551d5bb3 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -3,7 +3,7 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | Thant Aung Htet Nyan | [Github](https://github.com/thant) | [Portfolio](team/thant.md) -![](https://via.placeholder.com/100.png?text=Photo) | Jeremiah Ong | [Github](https://github.com/) | [Portfolio](team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Yan Zaiya | [Github](https://github.com/) | [Portfolio](team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Jeremiah Ong | [Github](https://github.com/miahjerry) | [Portfolio](team/miahjerry.md) +![](https://via.placeholder.com/100.png?text=Photo) | Yan Zaiya | [Github](https://github.com/skyanzy) | [Portfolio](team/skyanzy.md) ![](https://via.placeholder.com/100.png?text=Photo) | Gau Kiat Lok Jerald | [Github](https://github.com/jeraldgau) | [Portfolio](team/jeraldgau.md) -![](https://via.placeholder.com/100.png?text=Photo) | Liang Ting-Yu | [Github](https://github.com/) | [Portfolio](team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Liang Ting-Yu | [Github](https://github.com/michelleliang0116) | [Portfolio](team/michelleliang0116.md) From 28ef1df741ebd8096a5045f44d768948dfa2c7ff Mon Sep 17 00:00:00 2001 From: thant Date: Mon, 10 Apr 2023 18:16:50 +0800 Subject: [PATCH 137/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 03d1699caa..30f965ff9b 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -6,7 +6,7 @@ Reused iP to serve as base code from [jeraldgau/ip](https://github.com/jeraldgau ## Architecture -![](https://lh3.googleusercontent.com/FwYOJJpyhNrHNAUjWo1grnsWCDHdKMosDWaJaI_3kqtVbfD8108yk0MeJaybK3ac0MOAL3EVKYYCUjSiAbBrwAT8wRBkPTj2UDfw3AdhPT0fB8twOxfRDfh3BGAawOUOUlt-rxSACvVOhvqRnFamqWM) +![]![image](https://user-images.githubusercontent.com/1620654/230882687-7c5f75d1-9bba-4e3b-8aed-4dd432f165ea.png) The **Architecture Diagram** given above explains the high-level design of Duck. From 88d3c12824d5cda82a7a60af2ce11eb4be02e7ed Mon Sep 17 00:00:00 2001 From: thant Date: Mon, 10 Apr 2023 18:22:14 +0800 Subject: [PATCH 138/152] Update DeveloperGuide.md Fixed labels in diagrams, cleaned up architecture diagram --- docs/DeveloperGuide.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 30f965ff9b..a043170332 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -6,7 +6,7 @@ Reused iP to serve as base code from [jeraldgau/ip](https://github.com/jeraldgau ## Architecture -![]![image](https://user-images.githubusercontent.com/1620654/230882687-7c5f75d1-9bba-4e3b-8aed-4dd432f165ea.png) +![image](https://user-images.githubusercontent.com/1620654/230882687-7c5f75d1-9bba-4e3b-8aed-4dd432f165ea.png) The **Architecture Diagram** given above explains the high-level design of Duck. @@ -77,16 +77,17 @@ The ```TaskList#purge()``` command will be implemented to facilitate the removal **Given below is an example usage scenario for ```purge()```** -**Step 1.** The user launches the application for the first time. The ```TaskList``` will be initialized with the data from a given pre-existing datafile if it exists, and the ```Task``` items will be inserted into the ```TaskList```.![](https://lh5.googleusercontent.com/XcnArNZc5ZqHhxXZ1iRuq0aRxNKkcD_snVgDv-dlpMVYFQFQjyGXdtHWvFGzG-k2UW5SXkjQbthIRtkrol_SYsNgmsmKw1kKEkME0vSQ0tfRfUIWj3jZTTVrerHbESuA-AlTpPEkj8JrKl-mMlu-3yM) +**Step 1.** The user launches the application for the first time. The ```TaskList``` will be initialized with the data from a given pre-existing datafile if it exists, and the ```Task``` items will be inserted into the ```TaskList```.![image](https://user-images.githubusercontent.com/1620654/230883139-f664bde2-6c65-45f5-b060-06ec9708c620.png) + **Step 2.** The ```TaskList#purge()``` command will be executed. The process is illustrated through two steps: **Identifying all expired ```Task``` items in ```TaskList```.** -![](https://lh3.googleusercontent.com/Kbz7j3EmMGJGrIX1aQ8DCkHG8Y3gaIx3Ohf-zmYvr-S-LrxRqt8P1wlTMWUnlnna2tnR0i72yUJWB72Z2mWwGuwXiD_RnlIpYEk-MY6k9zMaLqTk_VkyHaRwIuzxi1trXHX1ySdZWBqZFDaCZ6K-QrY) +![image](https://user-images.githubusercontent.com/1620654/230883393-ef0d4e33-96c9-4e32-a6f6-f30121b953dd.png) **Removing all expired ```Task``` items in ```TaskList```.** -![](https://lh4.googleusercontent.com/kVOcvIKAF1nlLSHXQsRPDuG6RwiyaqRXf9CYTLrv2WUezegCNx05GIC1KPYME6Eojid1hRbqUIzHUjKWRpYjUG7zCYE8586kLzbIrVdjZVnC5j_1ke1WBdFZSHoar_MuXKBA9eMARxCOgcja5qjP2_A) +![image](https://user-images.githubusercontent.com/1620654/230883437-d1c3d47b-ef8b-451a-804e-cc2ce5a74e1b.png) The user will see this on his terminal after the ```purge``` command has executed. @@ -127,7 +128,7 @@ The ```Storage#clear()``` command was implemented to facilitate the removal of a Given below is an example usage scenario for ```Storage#clear()``` -**Step 1.** The user launches the application for the first time. The ```TaskList``` will be initialised with the data from a given pre-existing datafile if it exists, and the ```Task``` items will be inserted into the ```TaskList```.![](https://lh5.googleusercontent.com/XcnArNZc5ZqHhxXZ1iRuq0aRxNKkcD_snVgDv-dlpMVYFQFQjyGXdtHWvFGzG-k2UW5SXkjQbthIRtkrol_SYsNgmsmKw1kKEkME0vSQ0tfRfUIWj3jZTTVrerHbESuA-AlTpPEkj8JrKl-mMlu-3yM) +**Step 1.** The user launches the application for the first time. The ```TaskList``` will be initialised with the data from a given pre-existing datafile if it exists, and the ```Task``` items will be inserted into the ```TaskList```.![image](https://user-images.githubusercontent.com/1620654/230883139-f664bde2-6c65-45f5-b060-06ec9708c620.png) **Step 2.** The user wants to start afresh. The ```Storage#clear()```  command is then executed. The user will see an output in the following format: @@ -145,7 +146,7 @@ Process cancelled. **Step 3.2.** The user decides upon clearing the ```TaskList```, and inputs a ```Y```. The ```TaskList``` has been cleared. -![](https://lh4.googleusercontent.com/G4PalSoaVQxExSGKCDefJuO4TlyCJwrCfZDT4BsTrrSHMJ8aQSPsaxGoFJYb9YIO1yo3_3nV0Jar3Haqfac90v7G_yfZdx8-OwxSKEART5zLqMZ73k3YW0ssPbIE3kOhkbeusR3jVMdD6kTSkG7rK4s) +![image](https://user-images.githubusercontent.com/1620654/230883611-5f7c49bd-9e8a-405e-8c96-e55241fa9cca.png) ```Duck``` resumes after the output in the following format has been displayed: From 73a8e0bfa4f22800ecc443aeb1f8b94fe58c2835 Mon Sep 17 00:00:00 2001 From: thant Date: Mon, 10 Apr 2023 18:24:57 +0800 Subject: [PATCH 139/152] Update UserGuide.md Removed extra spaces, typos fixed --- docs/UserGuide.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index cb9e00e8b6..1400224fb8 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -13,11 +13,11 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * [Displaying upcoming class :](#displaying-upcoming-class--upcoming_class) `upcoming_class` * [Displaying upcoming deadline :](#displaying-upcoming-class--upcoming_deadline) `upcoming_deadline` * [Displaying upcoming event :](#displaying-upcoming-event--upcoming_event) `upcoming_event` - * [Mark a specified task as done :](#marking-a-task--mark-task_number) `mark ` + * [Mark a specified task as done :](#marking-a-task--mark-task_number) `mark ` * [Unmark a specified task as not done :](#unmarking-a-task--unmark-task_number) `unmark ` * [Edit a specific piece of information for a given task :](#editing-a-task--edit-task_number) `edit ` - * [Deleting a task :](#deleting-a-task--delete) `delete ` - * [Deleting a school class :](#deleting-a-school-class--remove-class) `remove /class /description /day /from /to ` + * [Deleting a task :](#deleting-a-task--delete) `delete ` + * [Deleting a school class :](#deleting-a-school-class--remove-class) `remove /class /description /day /from /to ` * [Designate a priority to a given task :](#designate-a-task-priority--priority-task_number-priority) `priority ` * [Adding notes for a specific task :](#adding-notes-for-a-specific-task--add_notes) `add_notes ` * [Deleting notes for a specific task :](#deleting-notes-for-a-specific-task--delete_notes) `delete_notes ` @@ -26,7 +26,7 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * [List tasks of low/medium/high priority :](#listing-all-low-priority-tasks--low_priority) `low_priority`/`medium_priority`/`high_priority` * [List tasks in priority order:](#listing-all-tasks-arranged-by-priority--priority_list) `priority_list` * [Purge expired tasks :](#purge-expired-tasks--purge) `purge` - * [Clearing all tasks (including datafile) :](#clearing-tasks-from-storage-clear) `clear ` + * [Clearing all tasks (including datafile) :](#clearing-tasks-from-storage-clear) `clear` * [Find tasks matching a given keyword :](#finding-tasks-from-storage-that-match-a-keyword-find-keyword) `find ` * [Add tasks that can be broken down into the following 6 types:](#adding-a-todo-task--todo-description) @@ -132,7 +132,7 @@ Here is your next upcoming class: [TUESDAY][ ] cs2113 (from: 1600 to: 1700) ``` -## **Displaying upcoming class : `upcoming_deadline`** +## **Displaying upcoming deadline : `upcoming_deadline`** Displays the next upcoming deadline stored in the application. From a445b5e79bb15d8d18db23d26ae38c515c6350a4 Mon Sep 17 00:00:00 2001 From: thant Date: Mon, 10 Apr 2023 18:27:46 +0800 Subject: [PATCH 140/152] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 1400224fb8..85a416b26c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -11,7 +11,7 @@ Duck is a **desktop app for managing tasks and deadlines, as well as a school cl * [Listing all tasks up to X days into the future :](#listing-all-tasks-up-to-x-days-in-the-future--list-x) `list X` * [Displaying class schedule :](#displaying-class-schedule--list_classes) `list_classes` * [Displaying upcoming class :](#displaying-upcoming-class--upcoming_class) `upcoming_class` - * [Displaying upcoming deadline :](#displaying-upcoming-class--upcoming_deadline) `upcoming_deadline` + * [Displaying upcoming deadline :](#displaying-upcoming-deadline--upcoming_deadline) `upcoming_deadline` * [Displaying upcoming event :](#displaying-upcoming-event--upcoming_event) `upcoming_event` * [Mark a specified task as done :](#marking-a-task--mark-task_number) `mark ` * [Unmark a specified task as not done :](#unmarking-a-task--unmark-task_number) `unmark ` From 5185b07cf2e071905464decfa56d7e8d3e2099e1 Mon Sep 17 00:00:00 2001 From: thant Date: Mon, 10 Apr 2023 18:29:06 +0800 Subject: [PATCH 141/152] Update README.md --- docs/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index bbcc99c1e7..544e12fd12 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ -# Duke +# Duck -{Give product intro here} +Duck is a desktop task and class tracker for users to keep track of their schedule and the things they have to do. The user interacts with it using the CLI. It is written in Java, and has about 3.5kLoc. Useful links: * [User Guide](UserGuide.md) From 8eabe3e46c6baf77e84ae7d64e078b05dc7bbb8a Mon Sep 17 00:00:00 2001 From: thant Date: Mon, 10 Apr 2023 18:33:22 +0800 Subject: [PATCH 142/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index a043170332..49e6229e2b 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -264,7 +264,7 @@ Duck will be able to allow students who can type fast to quickly record down the 1. Ensure that Java 11 or above is installed 2. Download the latest version of Duck 3. Launch the terminal and navigate to the folder where Duck is located in -4. Type in the command ```java -jar Duck.jar``` to lauch Duck +4. Type in the command ```java -jar [CS2113-T11-1][DUCK].jar``` to lauch Duck - Expected Outcome: Duck launches in the terminal with its start message displayed. ### Closing the program From c0527e9212feaf70186f75fc07a0b188cc7a3699 Mon Sep 17 00:00:00 2001 From: thant Date: Mon, 10 Apr 2023 18:38:13 +0800 Subject: [PATCH 143/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 49e6229e2b..f4f7d49ce8 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -62,7 +62,7 @@ This section describes how Duck is implemented and how its commands are executed **Sequence Diagram** -![image](https://user-images.githubusercontent.com/1620654/227128864-cfc9cac7-bc68-4962-ac45-77e1ae067db0.png) +![image](https://user-images.githubusercontent.com/1620654/227128864-cfc9cac7-bc68-4962-ac45-77e1ae067db0.png)
The ```TaskList#purge()``` command will be implemented following the sequence diagram as shown above. From d1d231668d9d6660cdb398d7052f63bef4c06aea Mon Sep 17 00:00:00 2001 From: thant Date: Mon, 10 Apr 2023 18:40:15 +0800 Subject: [PATCH 144/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index f4f7d49ce8..edc1db0b29 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -62,7 +62,9 @@ This section describes how Duck is implemented and how its commands are executed **Sequence Diagram** -![image](https://user-images.githubusercontent.com/1620654/227128864-cfc9cac7-bc68-4962-ac45-77e1ae067db0.png)
+![image](https://user-images.githubusercontent.com/1620654/227128864-cfc9cac7-bc68-4962-ac45-77e1ae067db0.png) + +
The ```TaskList#purge()``` command will be implemented following the sequence diagram as shown above. From 710c5f49b56b6834c875bf24bfeb8659395797bf Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Mon, 10 Apr 2023 18:51:27 +0800 Subject: [PATCH 145/152] Updated PPP to fit page limit --- docs/team/miahjerry.md | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/docs/team/miahjerry.md b/docs/team/miahjerry.md index 9a7dad6e4f..7bded60636 100644 --- a/docs/team/miahjerry.md +++ b/docs/team/miahjerry.md @@ -3,24 +3,17 @@ ## Overview Duck is a desktop task and class tracker for users to keep track of their schedule and the things they have to do. The user interacts with it using the CLI. It is written in Java, and has about 3.5kLoc. - ## Summary of Contributions ### New Feature: Implementation of ```print_priority``` feature - Added functions to print all tasks arranged by priority, rather than by the order in which they were added -- Also has other smaller functions as specified by the user guide to only print tasks of a certain priority ### New Feature: Implementation of ```notes``` feature - This feature allows users to add additional notes to each task that they will want to take note of - Notes will also be saved to be viewed again on next start up of Duck -### New Feature: New tasks automatically assigned low priority - -- Automatically assigns new tasks low priority until they are assigned a higher priority by the user - - ### New Feature: Adding notes to tasks - Allows the user to add a note to the specified task @@ -36,20 +29,10 @@ Duck is a desktop task and class tracker for users to keep track of their schedu - This feature allows the user to change an existing note under a specified task - By following the steps outlined by the user guide, existing notes can be edited. -### New Feature: Printing Duck - -- Prints ASCII art of a duck to suit the theme of the product -- Acts as the avatar for the application - -### New Feature: Implementation of ```motivation``` feature - -- Prints a motivational quote for the user if they want some motivation -- Also prints on startup when greeting the user - ### Cleaning up of code - Helped to make the code more defensive to prevent bad inputs from crashing Duck, specifically indexes that accessed out of bounds -- Helped to refactor code to better fulfil coding standard +- Helped to refactor code to better fulfill coding standard ### Code Contributed: [RepoSense Link](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=miahjerry&breakdown=true&sort=groupTitle%20dsc&sortWithin=title&since=2023-02-17&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other) From 2ba565546942cfd128468a528edb902914be9408 Mon Sep 17 00:00:00 2001 From: thant Date: Mon, 10 Apr 2023 18:51:51 +0800 Subject: [PATCH 146/152] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index edc1db0b29..670dc494bb 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -60,15 +60,6 @@ This section describes how Duck is implemented and how its commands are executed ### Purge feature -**Sequence Diagram** - -![image](https://user-images.githubusercontent.com/1620654/227128864-cfc9cac7-bc68-4962-ac45-77e1ae067db0.png) - -
- -The ```TaskList#purge()``` command will be implemented following the sequence diagram as shown above. - - **Implementation** The ```TaskList#purge()``` command will be implemented to facilitate the removal of expired ```Task``` items from the ```TaskList```. This will be executed once upon Duck's startup, and can be further executed by inputting the term ```purge``` into the CLI when Duck is running. The following is the new operation to be implemented. @@ -268,6 +259,7 @@ Duck will be able to allow students who can type fast to quickly record down the 3. Launch the terminal and navigate to the folder where Duck is located in 4. Type in the command ```java -jar [CS2113-T11-1][DUCK].jar``` to lauch Duck - Expected Outcome: Duck launches in the terminal with its start message displayed. + - If the file was sourced from our Github Releases, type in the command ```java -jar CS2113-T11-1.DUCK.jar``` to lauch Duck instead! ### Closing the program 1. Type ```bye``` in the terminal to exit the program From 77cdd2b2e34693a9f5a57a316c436d231834341b Mon Sep 17 00:00:00 2001 From: thant Date: Mon, 10 Apr 2023 18:52:29 +0800 Subject: [PATCH 147/152] Update thant.md --- docs/team/thant.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/team/thant.md b/docs/team/thant.md index fccbfc9113..fe9b183700 100644 --- a/docs/team/thant.md +++ b/docs/team/thant.md @@ -48,7 +48,6 @@ Duck is a desktop task and class tracker for users to keep track of their schedu - Developer Guide: - Did the ```architecture``` section. - Did the design and implementation for ```purge``` and ```clear``` features - - Added the sequence diagram for the ```purge``` function - Added an editable class diagram powerpoint skeleton located at ```docs/tP Diagram Editable.pptx``` From 87d00b11f751eecfdf621db8bcab11f63ac9ed65 Mon Sep 17 00:00:00 2001 From: skyanzy <88618401+skyanzy@users.noreply.github.com> Date: Mon, 10 Apr 2023 18:53:22 +0800 Subject: [PATCH 148/152] Update skyanzy.md --- docs/team/skyanzy.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/team/skyanzy.md b/docs/team/skyanzy.md index 4016d1c387..7dcb5f3b89 100644 --- a/docs/team/skyanzy.md +++ b/docs/team/skyanzy.md @@ -4,7 +4,6 @@ Duck is a desktop task and class tracker for users to keep track of their schedule and the things they have to do. The user interacts with it using the CLI. It is written in Java, and has about 3.5kLoc. - ## Summary of Contributions ### New Feature: Implementation of the `RecurringDeadline` Task From c10aebc066d564e03c488cc43630119c0ba9c0dd Mon Sep 17 00:00:00 2001 From: skyanzy <88618401+skyanzy@users.noreply.github.com> Date: Mon, 10 Apr 2023 18:55:59 +0800 Subject: [PATCH 149/152] Update skyanzy.md --- docs/team/skyanzy.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/team/skyanzy.md b/docs/team/skyanzy.md index 7dcb5f3b89..b8e3082b17 100644 --- a/docs/team/skyanzy.md +++ b/docs/team/skyanzy.md @@ -34,15 +34,13 @@ Duck is a desktop task and class tracker for users to keep track of their schedu ### Code Contributed: [RepoSense Link](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=T11&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2023-02-17&tabOpen=true&tabType=authorship&tabAuthor=skyanzy&tabRepo=AY2223S2-CS2113-T11-1%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false) ### Project Management: -- Updating the team when a new PR is merged to ensure everyone is on the same page. - Integration of different parts when a new feature is implemented. - Seting up milestone v2.1 and dividing issues among the team members. ### Documentation: - User Guide: - Added documentation for the features `edit ` , `list_today`, adding a `RecurringDeadline and RecurringEvnet`. - - cleared some issues regarding inconsistent format. - - Added some missing links to the table of contents. + - Added some missing links to the table of contents and cleared some issues regarding inconsistent format.. - Developer Guide: - Added design and the implementation of RecurringDeadline and RecurringEvent From eece6d8c5959024c4af0c2ae7d7bd05e5d7ba88e Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Mon, 10 Apr 2023 18:58:23 +0800 Subject: [PATCH 150/152] Updated PPP --- docs/team/miahjerry.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/team/miahjerry.md b/docs/team/miahjerry.md index 7bded60636..404d5dd6f3 100644 --- a/docs/team/miahjerry.md +++ b/docs/team/miahjerry.md @@ -29,6 +29,11 @@ Duck is a desktop task and class tracker for users to keep track of their schedu - This feature allows the user to change an existing note under a specified task - By following the steps outlined by the user guide, existing notes can be edited. +### New Feature: Implementation of ```motivation``` feature +- Prints a motivational quote for the user +- Also prints on start up when greeting the user + +### New Feature: Printing Duck ### Cleaning up of code - Helped to make the code more defensive to prevent bad inputs from crashing Duck, specifically indexes that accessed out of bounds From a882564a7e55111246394ecd440698fa558f0da3 Mon Sep 17 00:00:00 2001 From: Jeremiah Ong Date: Mon, 10 Apr 2023 19:03:15 +0800 Subject: [PATCH 151/152] Removed unnecesary line from PPP --- docs/team/miahjerry.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/team/miahjerry.md b/docs/team/miahjerry.md index 404d5dd6f3..718e113ed7 100644 --- a/docs/team/miahjerry.md +++ b/docs/team/miahjerry.md @@ -31,9 +31,8 @@ Duck is a desktop task and class tracker for users to keep track of their schedu ### New Feature: Implementation of ```motivation``` feature - Prints a motivational quote for the user -- Also prints on start up when greeting the user +- Also prints on start up to greet the user -### New Feature: Printing Duck ### Cleaning up of code - Helped to make the code more defensive to prevent bad inputs from crashing Duck, specifically indexes that accessed out of bounds From 83b2f601fdd50d8bd38a41fdf9e98d198a0fafc0 Mon Sep 17 00:00:00 2001 From: MichelleLiang0116 <122435100+MichelleLiang0116@users.noreply.github.com> Date: Tue, 11 Apr 2023 02:01:18 +0800 Subject: [PATCH 152/152] Update michelleliang0116.md --- docs/team/michelleliang0116.md | 45 ++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/docs/team/michelleliang0116.md b/docs/team/michelleliang0116.md index c19f39ac2e..6fb7f2e525 100644 --- a/docs/team/michelleliang0116.md +++ b/docs/team/michelleliang0116.md @@ -1,13 +1,38 @@ # LIANG TING YU - Project Portfolio Page -## Project: Duck -### Duck is a desktop app for managing tasks and deadlines, as well as a school class scheduler. It is optimised for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). -### Summary of Contributions: -#### • New Feature: Display upcoming deadline/event when starting application -#### • New Feature: Display next upcoming deadline/event/task/class -#### Code contributed: -#### Enhancements implemented: -#### Contributions to the UG: -#### Contributions to team-based tasks -#### Review/mentoring contributions: +## Overview + +Duck is a desktop task and class tracker for users to keep track of their schedule and the things they have to do. The user interacts with it using the CLI. It is written in Java, and has about 3.5kLoc. + + + +## Summary of Contributions + +### New Feature: Implementation of displaying upcoming deadline/event when starting duck. +- Displays upcoming deadline stored in the application when starting the application. +- Calculate the remaining time before the deadline + + +### New Feature: Implementation of displaying next upcoming deadline/event/class. +- Displays the next upcoming class stored in the application. Classes will be automatically sorted according to chronological order. Classes will also automatically be marked as done (represented by a cross) if the current time is past the ending time of the class, and their 'done' status will be reset at the start of each week. +- This is utilized in the ```upcoming_deadline```,```upcoming_class```,```upcoming_event```commands. + + +### Code Contributed: [RepoSense Link](https://nus-cs2113-ay2223s2.github.io/tp-dashboard/?search=liang&breakdown=true&sort=groupTitle%20dsc&sortWithin=title&since=2023-02-17&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other) + + +### Project Management: +- Group meetings/notes. +- Complete assigned task and double check typo/bugs of others. + + +### Documentation: +- User Guide: + - Added documentation for the features `upcoming_deadline` , `upcoming_event`, `upcoming_class` , and feature displaying upcoming deadline/event. + - fix inconsistent format. + - Added missing links to the table of contents. + + +### Community: +- Reported bugs and suggestions for other teams (examples: [1](https://github.com/MichelleLiang0116/ped/issues/3), [2](https://github.com/MichelleLiang0116/ped/issues/2), [3](https://github.com/MichelleLiang0116/ped/issues/1))