From c6b907ca39edc8e82ccd56b0d307b9474c1a7238 Mon Sep 17 00:00:00 2001 From: Chang Ji-xuan Date: Thu, 21 Sep 2023 13:28:12 +0800 Subject: [PATCH] added comments to the purpose of each method and class --- src/main/java/duke/Command.java | 1 + src/main/java/duke/DateConverter.java | 2 + src/main/java/duke/Deadline.java | 8 +- src/main/java/duke/Duke.java | 256 +++++++++++------- .../java/duke/EmptyDeadlineException.java | 1 + src/main/java/duke/EmptyEventException.java | 1 + src/main/java/duke/EmptyTodoException.java | 1 + src/main/java/duke/Event.java | 7 + src/main/java/duke/Exit.java | 2 + src/main/java/duke/Parser.java | 3 + src/main/java/duke/Storage.java | 4 +- src/main/java/duke/Task.java | 6 + src/main/java/duke/TaskList.java | 32 ++- src/main/java/duke/TaskReader.java | 9 +- src/main/java/duke/TaskWriter.java | 2 + src/main/java/duke/Todo.java | 2 +- src/main/java/duke/Ui.java | 17 +- src/main/java/duke/UnknownInputException.java | 1 + 18 files changed, 235 insertions(+), 120 deletions(-) diff --git a/src/main/java/duke/Command.java b/src/main/java/duke/Command.java index 58309e43f5..9cdd39e2e7 100644 --- a/src/main/java/duke/Command.java +++ b/src/main/java/duke/Command.java @@ -1,4 +1,5 @@ package duke; +//list of possible commands by the user public enum Command { TODO, DEADLINE, diff --git a/src/main/java/duke/DateConverter.java b/src/main/java/duke/DateConverter.java index 19b5c8de9a..8605aa0b94 100644 --- a/src/main/java/duke/DateConverter.java +++ b/src/main/java/duke/DateConverter.java @@ -3,7 +3,9 @@ import java.text.SimpleDateFormat; import java.util.Date; + public class DateConverter { + // converts the input string from MMM dd yyyy to a Date object with "YYYY/MM/DD" public static String convertDate(String inputDateStr) { try { // Define a SimpleDateFormat for parsing the input date diff --git a/src/main/java/duke/Deadline.java b/src/main/java/duke/Deadline.java index f9a9590438..19f805f009 100644 --- a/src/main/java/duke/Deadline.java +++ b/src/main/java/duke/Deadline.java @@ -5,22 +5,24 @@ public class Deadline extends Task { private LocalDate deadline; - + // constructor of deadline takes in a string, whether it is marked and a deadline public Deadline(String name, boolean isMarked, LocalDate deadline) { super(name, isMarked); this.deadline = deadline; } - + // gets the deadline of the Deadline object public LocalDate getDeadline() { + return deadline; } - + // sets the deadline of the Deadline Object public void setDeadline(LocalDate deadline) { this.deadline = deadline; } + // returns a String depending on if it is marked as [D] by: @Override public String toString() { String status = isMarked ? "[X]" : "[ ]"; diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java index 83797d20a7..d68e1c8e47 100644 --- a/src/main/java/duke/Duke.java +++ b/src/main/java/duke/Duke.java @@ -30,130 +30,182 @@ public void run() { Command command = Parser.parseCommand(userInput); String description = Parser.parseDescription(userInput); switch (command) { + //if user wants to exit, tasks are saved and exit message is shown case EXIT: - storage.save(tasks, "tasks.txt"); - ui.closeScanner(); - ui.showExitMessage(); + handleExit(); return; + // lists all the tasks out case LIST: - ui.showTaskList(tasks); + handleList(); break; + case FIND: + handleFind(description); + break; + // unmarks task case UNMARK: - try { - int taskNumber = Integer.parseInt(description) - 1; - if (taskNumber >= 0 && taskNumber < tasks.size()) { - tasks.unmarkTask(taskNumber); - } else { - ui.showError("Task number out of range."); - } - } catch (NumberFormatException e) { - ui.showError("Invalid task number. Please provide a valid integer."); - } + handleUnmark(description); break; + //marks the task case MARK: - try { - int taskNumber = Integer.parseInt(description) - 1; - if (taskNumber >= 0 && taskNumber < tasks.size()) { - tasks.markTaskAsDone(taskNumber); - } else { - ui.showError("Task number out of range."); - } - } catch (NumberFormatException e) { - ui.showError("Invalid task number. Please provide a valid integer."); - } + handleMark(description); break; + // if user wants to add a todo object case TODO: - try { - if (description.isEmpty()) { - throw new EmptyTodoException(); - } - Todo todo = new Todo(description, false); - tasks.addTask(todo); - - } catch (EmptyTodoException e) { - System.out.println(e.getMessage()); - } + handleTodo(description); break; + // if user wants to input deadline case DEADLINE: - - if (description.isEmpty()) { - try { - throw new EmptyDeadlineException(); - } catch (EmptyDeadlineException e) { - System.out.println(e.getMessage()); - } - } else { - // Find the index of the deadline separator "/" - int separatorIndex = description.indexOf('/'); - - if (separatorIndex != -1) { // Ensure the separator exists in the input - // Extract the task description and deadline - - String descriptionString = description.substring(0, separatorIndex).trim(); - String deadline = description.substring(separatorIndex + 4).trim(); - String pattern = "\\d{4}/\\d{2}/\\d{2}"; - Pattern datePattern = Pattern.compile(pattern); - Matcher matcher = datePattern.matcher(deadline); - if (matcher.find()) { - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); - LocalDate localDateDeadline = LocalDate.parse(deadline, formatter); - Deadline deadlineTask = new Deadline(descriptionString, false, localDateDeadline); - tasks.addTask(deadlineTask); - - } else { - System.out.println("Please input your deadline in YYYY/MM/DD format"); - } - } else { - System.out.println("Invalid input format for deadline. Please input in the following format: /by "); - } - } + handleDeadline(description); break; + // if user wants to input an event case EVENT: - if (description.isEmpty()) { - try { - throw new EmptyEventException(); - } catch (EmptyEventException e) { - System.out.println(e.getMessage()); - } - } else { - // Find the indices of the time separators - int fromIndex = description.indexOf("/from"); - int toIndex = description.indexOf("/to"); - - if (fromIndex != -1 && toIndex != -1) { - // Extract the task description, startTime, and endTime - String descriptionString = description.substring(0, fromIndex).trim(); - String startTime = description.substring(fromIndex + 5, toIndex).trim(); - String endTime = description.substring(toIndex + 3).trim(); - - // Create a new Event object - Event eventTask = new Event(descriptionString, false, startTime, endTime); - tasks.addTask(eventTask); - - } else { - System.out.println("Invalid input format for event command."); - } - } + handleEvent(description); break; + // if user wants to delete existing task case DELETE: - try { - int taskNumber = Integer.parseInt(description) - 1; - if (taskNumber >= 0 && taskNumber < tasks.size()) { - tasks.deleteTask(taskNumber); - } else { - ui.showError("Task number out of range."); - } - } catch (NumberFormatException e) { - ui.showError("Invalid task number. Please provide a valid integer."); - } + handleDelete(description); break; + // if user just enters a completely invalid command case INVALID: - ui.showError("Invalid command. Please try again."); + handleInvalid(); break; } } } + private void handleExit() { + storage.save(tasks, "tasks.txt"); + ui.closeScanner(); + ui.showExitMessage(); + } + + private void handleList() { + ui.showTaskList(tasks); + } + + private void handleFind(String description) { + tasks.findTasksContainingKeyword(description); + } + + private void handleUnmark(String description) { + // if user inputs task number, check if it is even an integer, and whether it is within range + try { + int taskNumber = Integer.parseInt(description) - 1; + if (taskNumber >= 0 && taskNumber < tasks.size()) { + tasks.unmarkTask(taskNumber); + } else { + ui.showError("Task number out of range."); + } + + } catch (NumberFormatException e) { + ui.showError("Invalid task number. Please provide a valid integer."); + } + } + + private void handleMark(String description) { + // if user inputs task number, check if it is even an integer, and whether it is within range + try { + int taskNumber = Integer.parseInt(description) - 1; + if (taskNumber >= 0 && taskNumber < tasks.size()) { + tasks.markTaskAsDone(taskNumber); + } else { + ui.showError("Task number out of range."); + } + } catch (NumberFormatException e) { + ui.showError("Invalid task number. Please provide a valid integer."); + } + } + private void handleTodo(String description) { + try { + if (description.isEmpty()) { + throw new EmptyTodoException(); + } + Todo todo = new Todo(description, false); + tasks.addTask(todo); + + } catch (EmptyTodoException e) { + System.out.println(e.getMessage()); + } + } + private void handleDeadline(String description) { + if (description.isEmpty()) { + try { + throw new EmptyDeadlineException(); + } catch (EmptyDeadlineException e) { + System.out.println(e.getMessage()); + } + } else { + // Find the index of the deadline separator "/" + int separatorIndex = description.indexOf('/'); + + if (separatorIndex != -1) { // Ensure the separator exists in the input + // Extract the task description and deadline + + String descriptionString = description.substring(0, separatorIndex).trim(); + String deadline = description.substring(separatorIndex + 4).trim(); + String pattern = "\\d{4}/\\d{2}/\\d{2}"; + Pattern datePattern = Pattern.compile(pattern); + Matcher matcher = datePattern.matcher(deadline); + if (matcher.find()) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); + LocalDate localDateDeadline = LocalDate.parse(deadline, formatter); + Deadline deadlineTask = new Deadline(descriptionString, false, localDateDeadline); + tasks.addTask(deadlineTask); + + } else { + System.out.println("Please input your deadline in YYYY/MM/DD format"); + } + } else { + System.out.println("Invalid input format for deadline. Please input in the following format: /by "); + } + } + } + + private void handleEvent(String description) { + if (description.isEmpty()) { + try { + throw new EmptyEventException(); + } catch (EmptyEventException e) { + System.out.println(e.getMessage()); + } + } else { + // Find the indices of the time separators + int fromIndex = description.indexOf("/from"); + int toIndex = description.indexOf("/to"); + + if (fromIndex != -1 && toIndex != -1) { + // Extract the task description, startTime, and endTime + String descriptionString = description.substring(0, fromIndex).trim(); + String startTime = description.substring(fromIndex + 5, toIndex).trim(); + String endTime = description.substring(toIndex + 3).trim(); + + // Create a new Event object + Event eventTask = new Event(descriptionString, false, startTime, endTime); + tasks.addTask(eventTask); + + } else { + System.out.println("Invalid input format for event command."); + } + } + } + + private void handleDelete(String description) { + try { + int taskNumber = Integer.parseInt(description) - 1; + if (taskNumber >= 0 && taskNumber < tasks.size()) { + tasks.deleteTask(taskNumber); + } else { + ui.showError("Task number out of range."); + } + } catch (NumberFormatException e) { + ui.showError("Invalid task number. Please provide a valid integer."); + } + } + + private void handleInvalid() { + ui.showError("Invalid command. Please try again."); + } + public static void main(String[] args) { new Duke("tasks.txt").run(); } diff --git a/src/main/java/duke/EmptyDeadlineException.java b/src/main/java/duke/EmptyDeadlineException.java index 5ddf2626b8..0257155d46 100644 --- a/src/main/java/duke/EmptyDeadlineException.java +++ b/src/main/java/duke/EmptyDeadlineException.java @@ -1,4 +1,5 @@ package duke; +// if the description of a deadline is empty, return error message public class EmptyDeadlineException extends Exception { public EmptyDeadlineException() { super("OOPS!!! The description of a deadline cannot be empty."); diff --git a/src/main/java/duke/EmptyEventException.java b/src/main/java/duke/EmptyEventException.java index 9e5bec390b..022fcaffd0 100644 --- a/src/main/java/duke/EmptyEventException.java +++ b/src/main/java/duke/EmptyEventException.java @@ -1,4 +1,5 @@ package duke; +// if the description of an event is empty, return error message public class EmptyEventException extends Exception { public EmptyEventException() { super("OOPS!!! The description of an event cannot be empty."); diff --git a/src/main/java/duke/EmptyTodoException.java b/src/main/java/duke/EmptyTodoException.java index a0b60eacfc..adf4810cf9 100644 --- a/src/main/java/duke/EmptyTodoException.java +++ b/src/main/java/duke/EmptyTodoException.java @@ -1,4 +1,5 @@ package duke; +// if the description of a todo is empty, return error message public class EmptyTodoException extends Exception { public EmptyTodoException() { super("OOPS!!! The description of a todo cannot be empty."); diff --git a/src/main/java/duke/Event.java b/src/main/java/duke/Event.java index 6bfce68d19..2c4a207227 100644 --- a/src/main/java/duke/Event.java +++ b/src/main/java/duke/Event.java @@ -1,26 +1,33 @@ package duke; + public class Event extends Task { private String startTime; private String endTime; + //Event objects inherit from tasks and has additional attributes start and end time + public Event(String name, boolean isMarked, String startTime, String endTime) { super(name, isMarked); this.startTime = startTime; this.endTime = endTime; } + //getter of start time of event public String getStartTime() { return startTime; } + // setter of start time for event public void setStartTime(String startTime) { this.startTime = startTime; } + // getter of end time for event public String getEndTime() { return endTime; } + // setter of end time for event public void setEndTime(String endTime) { this.endTime = endTime; } diff --git a/src/main/java/duke/Exit.java b/src/main/java/duke/Exit.java index cd9f079479..69ce476f66 100644 --- a/src/main/java/duke/Exit.java +++ b/src/main/java/duke/Exit.java @@ -1,4 +1,6 @@ package duke; + +// when user enters bye and wants to exit the bot , this message is shown public class Exit { public String exitMessage() { return "Bye. Hope to see you again soon!"; diff --git a/src/main/java/duke/Parser.java b/src/main/java/duke/Parser.java index 784cacb015..25928672ed 100644 --- a/src/main/java/duke/Parser.java +++ b/src/main/java/duke/Parser.java @@ -1,5 +1,7 @@ package duke; public class Parser { + + // allows bot to process the command and acts accordingly public static Command parseCommand(String userInput) { String[] inputParts = userInput.split(" ", 2); // Split input into two parts: command and arguments String command = inputParts[0].toUpperCase(); // Convert command to uppercase for case-insensitivity @@ -33,6 +35,7 @@ public static Command parseCommand(String userInput) { } + //allows bot to process the description of any command public static String parseDescription(String userInput) { String[] parts = userInput.split(" ", 2); // Split input into command and arguments if (parts.length > 1) { diff --git a/src/main/java/duke/Storage.java b/src/main/java/duke/Storage.java index 2267b3bc82..f8a648a71f 100644 --- a/src/main/java/duke/Storage.java +++ b/src/main/java/duke/Storage.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.List; +// Storage class to retrieve and write the task list public class Storage { public String filePath; @@ -16,6 +17,7 @@ public Storage(String filePath) { this.filePath = filePath; } + // if the file cant be found in the filepath, an exception will be thrown public TaskList load() throws DukeException { TaskList tasks = new TaskList(); File file = new File(filePath); @@ -26,7 +28,7 @@ public TaskList load() throws DukeException { return tasks; } - + // saves the task list at the file path specified public void save(TaskList tasks, String filePath) { TaskWriter.writeTasksToFile(tasks, filePath); } diff --git a/src/main/java/duke/Task.java b/src/main/java/duke/Task.java index 6509464adf..af2a16d421 100644 --- a/src/main/java/duke/Task.java +++ b/src/main/java/duke/Task.java @@ -1,5 +1,6 @@ package duke; public class Task { + // task object has 2 attributes, name of the task and whether it is marked protected String name; protected boolean isMarked; @@ -8,19 +9,24 @@ public Task(String name, boolean isMarked) { this.isMarked = isMarked; } + //gets the name of the task public String getName() { return name; } + //sets the name of the task + public void setName(String name) { this.name = name; } + //checks if the task is already marked public boolean isMarked() { return isMarked; } + // sets the task as marked public void setMarked(boolean marked) { isMarked = marked; } diff --git a/src/main/java/duke/TaskList.java b/src/main/java/duke/TaskList.java index 687537c170..78d6785dfa 100644 --- a/src/main/java/duke/TaskList.java +++ b/src/main/java/duke/TaskList.java @@ -1,6 +1,7 @@ package duke; import java.util.ArrayList; +// tasklist is the array list storing the tasks public class TaskList { protected ArrayList tasks; @@ -8,6 +9,7 @@ public TaskList() { this.tasks = new ArrayList<>(); } + //add task method allows a task to be added into the list public void addTask(Task task) { tasks.add(task); System.out.println("Got it. I've added this task:"); @@ -15,14 +17,18 @@ public void addTask(Task task) { System.out.println("Now you have " + tasks.size() + " tasks in the list."); } + //add task from storage allows the tasks to be added into the task list when the bot is started + public void addTaskFromStorage(Task task) { tasks.add(task); } + //checks if the task list is empty public boolean isEmpty() { return tasks.isEmpty(); } + // allows tasks to be deleted from the list if user inputs require it to do so public void deleteTask(int taskNumber) { Task task = tasks.get(taskNumber); tasks.remove(taskNumber); @@ -30,22 +36,26 @@ public void deleteTask(int taskNumber) { System.out.println("Now you have " + tasks.size() + " tasks in the list."); } + // set the task at index public void set(int index, Task task) { tasks.set(index, task); } + //shows the number of task in the task list currently public int size() { return tasks.size(); } + // get the task at specified index public Task get(int index) { return tasks.get(index); } - + // returns the tasks to an arraylist public ArrayList toArrayList() { return tasks; } + // mark the task at a specified index as done public void markTaskAsDone(int taskNumber) { Task task = tasks.get(taskNumber); task.setMarked(true); @@ -53,6 +63,8 @@ public void markTaskAsDone(int taskNumber) { System.out.println("Nice! I've marked this task as done:\n" + " " + tasks.get(taskNumber)); } + // unmarks the task at a specified index + public void unmarkTask(int taskNumber) { Task task = tasks.get(taskNumber); task.setMarked(false); @@ -60,6 +72,7 @@ public void unmarkTask(int taskNumber) { System.out.println("OK, I've marked this task as not done yet:\n" + " " + tasks.get(taskNumber)); } + // prints out each task in the line public void listOfTasks() { System.out.println("Here are the tasks in your list: "); if (!tasks.isEmpty()) { @@ -68,11 +81,18 @@ public void listOfTasks() { } } } - - // Add other methods for task list operations - - - + public void findTasksContainingKeyword(String keyword) { + ArrayList matchingTasks = new ArrayList<>(); + for (Task task : tasks) { + if (task.getName().contains(keyword)) { + matchingTasks.add(task); + } + } + System.out.println("Here are the matching tasks in your list:"); + for (int i = 0; i < matchingTasks.size(); i++) { + System.out.println((i + 1) + "." + matchingTasks.get(i)); + } + } public String toString() { return tasks.toString(); } diff --git a/src/main/java/duke/TaskReader.java b/src/main/java/duke/TaskReader.java index 7394c88ac3..d8ab002993 100644 --- a/src/main/java/duke/TaskReader.java +++ b/src/main/java/duke/TaskReader.java @@ -5,6 +5,7 @@ import java.time.format.DateTimeFormatter; import java.time.LocalDate; +// reads the task in from the stored txt file and returns it as a TaskList public class TaskReader { public static TaskList readTasksFromFile(String filename) { TaskList tasks = new TaskList(); @@ -23,7 +24,7 @@ public static TaskList readTasksFromFile(String filename) { return tasks; } - + //parses the task from each line in the txt file depending on if they are a todo, event or deadline private static Task parseTaskFromLine(String line) { // Parse a task from a line of text if (line.startsWith("[T]")) { @@ -52,21 +53,21 @@ private static Task parseTaskFromLine(String line) { return null; // Return null for unsupported task formats } - + //extracts the deadline of a deadline task private static String extractDeadline(String line) { // Extract the deadline from the line int startIndex = line.indexOf("(by:") + 5; int endIndex = line.lastIndexOf(")"); return line.substring(startIndex, endIndex).trim(); } - + //extract the start time of an event private static String extractStartTime(String line) { // Extract the start time from the line int startIndex = line.indexOf("(from:") + 7; int endIndex = line.indexOf("to:"); return line.substring(startIndex, endIndex).trim(); } - + //extracts the end time of an event task private static String extractEndTime(String line) { // Extract the end time from the line int startIndex = line.indexOf("to:") + 4; diff --git a/src/main/java/duke/TaskWriter.java b/src/main/java/duke/TaskWriter.java index c49e0b341a..2dbba01440 100644 --- a/src/main/java/duke/TaskWriter.java +++ b/src/main/java/duke/TaskWriter.java @@ -2,6 +2,8 @@ import java.io.FileWriter; import java.io.BufferedWriter; import java.io.IOException; + +// writes the tasks into a txt file given a tasklist of tasks public class TaskWriter { public static void writeTasksToFile(TaskList tasks, String filename) { try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) { diff --git a/src/main/java/duke/Todo.java b/src/main/java/duke/Todo.java index fd02d05854..d1d8e67208 100644 --- a/src/main/java/duke/Todo.java +++ b/src/main/java/duke/Todo.java @@ -1,6 +1,6 @@ package duke; public class Todo extends Task { - + //todo tasks have the same attributes as its parent Task public Todo(String name, boolean isMarked) { super(name, isMarked); } diff --git a/src/main/java/duke/Ui.java b/src/main/java/duke/Ui.java index 992f32ec11..20385faa37 100644 --- a/src/main/java/duke/Ui.java +++ b/src/main/java/duke/Ui.java @@ -1,55 +1,66 @@ package duke; import java.util.Scanner; + public class Ui { private Scanner scanner; - + //takes in user input public Ui() { scanner = new Scanner(System.in); } - + // ask for user input and finds the command of the user public String getUserInput() { System.out.print("Enter a command: "); return scanner.nextLine().trim(); } + // default welcome message public void showWelcomeMessage() { String name = "Johnnythesnake"; System.out.println("Hello, I'm " + name); System.out.println("What can I do for you? Aside from completing your CS2103 project for you"); } + //Exit message when user enters bye public void showExitMessage() { System.out.println("Goodbye! Have a great day!"); } + // shows the user the active tasks when they ask for it public void showTaskList(TaskList tasks) { tasks.listOfTasks(); } + // mark task as done public void showMarkedAsDone(int taskNumber) { System.out.println("Task " + (taskNumber + 1) + " marked as done."); } + // unmark task public void showUnmarked(int taskNumber) { System.out.println("Task " + (taskNumber + 1) + " unmarked."); } - + // shows the tasks added public void showTaskAdded() { System.out.println("Task added."); } + // shows which taks has been deleted public void showTaskDeleted(int taskNumber) { System.out.println("Task " + (taskNumber + 1) + " deleted."); } + // shows the user an error message depending on what he did wrong public void showError(String errorMessage) { + System.out.println("Error: " + errorMessage); } + // if issues arise from loading tasks, this message is shown public void showLoadingError() { System.out.println("Error loading tasks from storage."); } + public void closeScanner() { scanner.close(); } diff --git a/src/main/java/duke/UnknownInputException.java b/src/main/java/duke/UnknownInputException.java index 05c2a8ce00..3b94aaf1bf 100644 --- a/src/main/java/duke/UnknownInputException.java +++ b/src/main/java/duke/UnknownInputException.java @@ -1,4 +1,5 @@ package duke; +//if the user inputs an unknown input, an error message is returned public class UnknownInputException extends Exception{ public UnknownInputException() { super("OOPS!!! I'm sorry, but I don't know what that means :-(");