diff --git a/src/main/java/gopher/Gopher.java b/src/main/java/gopher/Gopher.java index e9996f1cac..907b151de2 100644 --- a/src/main/java/gopher/Gopher.java +++ b/src/main/java/gopher/Gopher.java @@ -11,6 +11,7 @@ import gopher.exception.MissingTaskNumberException; import gopher.exception.MissingTokenException; import gopher.exception.UnknownCommandException; +import gopher.message.Message; import gopher.parser.Parser; import gopher.storage.TaskManager; import gopher.task.Task; @@ -42,9 +43,9 @@ public Gopher() { /** * Executes the relevant actions when user input exit program command * - * @return response by gopher after successful action + * @return Message object indicating response by gopher after successful action */ - public static String executeExitCommand() { + public static Message executeExitCommand() { Platform.exit(); return UI.getExitMessage(); } @@ -52,9 +53,9 @@ public static String executeExitCommand() { /** * Executes the relevant actions when user input list tasks command * - * @return response by gopher after successful action + * @return Message object indicating response by gopher after successful action */ - public static String executeListTasksCommand() { + public static Message executeListTasksCommand() { return UI.getTaskListMessage(taskList); } @@ -62,9 +63,9 @@ public static String executeListTasksCommand() { * Executes the relevant actions when user input mark task as done command. * * @param userInput command input by the user - * @return response by gopher after successful action + * @return Message object indicating response by gopher after successful action */ - public static String executeMarkTaskCommand(String userInput) { + public static Message executeMarkTaskCommand(String userInput) { try { int[] taskNumbers = Parser.parseMarkCommand(userInput); taskList.markAsDone(taskNumbers); @@ -72,9 +73,9 @@ public static String executeMarkTaskCommand(String userInput) { for (int taskNumber : taskNumbers) { message.append(UI.getMarkAsDoneMessage(taskList.getTask(taskNumber))); } - return message.toString(); + return UI.getMessage(message.toString()); } catch (MissingTaskNumberException | InvalidTaskNumberException e) { - return e.getMessage(); + return UI.getErrorMessage(e); } finally { taskList.save(); } @@ -84,9 +85,9 @@ public static String executeMarkTaskCommand(String userInput) { * Executes the relevant actions when user input mark task as not done command. * * @param userInput command input by the user - * @return response by gopher after successful action + * @return Message object indicating response by gopher after successful action */ - public static String executeUnmarkTaskCommand(String userInput) { + public static Message executeUnmarkTaskCommand(String userInput) { try { int[] taskNumbers = Parser.parseUnmarkCommand(userInput); taskList.markAsUndone(taskNumbers); @@ -94,9 +95,9 @@ public static String executeUnmarkTaskCommand(String userInput) { for (int taskNumber : taskNumbers) { message.append(UI.getMarkAsUndoneMessage(taskList.getTask(taskNumber))); } - return message.toString(); + return UI.getMessage(message.toString()); } catch (MissingTaskNumberException | InvalidTaskNumberException e) { - return e.getMessage(); + return UI.getErrorMessage(e); } finally { taskList.save(); } @@ -106,9 +107,9 @@ public static String executeUnmarkTaskCommand(String userInput) { * Executes the relevant actions when user input delete task command. * * @param userInput command input by the user - * @return response by gopher after successful action + * @return Message object indicating response by gopher after successful action */ - public static String executeDeleteTaskCommand(String userInput) { + public static Message executeDeleteTaskCommand(String userInput) { try { int[] taskNumbers = Parser.parseDeleteCommand(userInput); StringBuilder message = new StringBuilder(); @@ -116,9 +117,9 @@ public static String executeDeleteTaskCommand(String userInput) { message.append(UI.getDeleteTaskMessage(taskList.getTask(taskNumber))); } taskList.delete(taskNumbers); - return message.toString(); + return UI.getMessage(message.toString()); } catch (MissingTaskNumberException | InvalidTaskNumberException e) { - return e.getMessage(); + return UI.getErrorMessage(e); } finally { taskList.save(); } @@ -128,9 +129,9 @@ public static String executeDeleteTaskCommand(String userInput) { * Executes the relevant actions when user input find task command. * * @param userInput command input by the user - * @return response by gopher after successful action + * @return Message object indicating response by gopher after successful action */ - public static String executeFindTaskCommand(String userInput) { + public static Message executeFindTaskCommand(String userInput) { String keyword = Parser.parseFindCommand(userInput); TaskList matchedTasks = taskList.find(keyword); return UI.getMatchedTasksMessage(matchedTasks); @@ -140,9 +141,9 @@ public static String executeFindTaskCommand(String userInput) { * Executes the relevant actions when user input create task command. * * @param userInput command input by the user - * @return response by gopher after successful action + * @return Message object indicating response by gopher after successful action */ - public static String executeCreateTaskCommand(String userInput) + public static Message executeCreateTaskCommand(String userInput) throws UnknownCommandException { try { Task task = Task.of(userInput); @@ -152,7 +153,7 @@ public static String executeCreateTaskCommand(String userInput) return UI.getInvalidDateWarning(); } catch (EmptyTaskDescriptionException | MissingTokenException | InvalidTokenException | InvalidDurationException e) { - return e.getMessage(); + return UI.getErrorMessage(e); } } @@ -160,9 +161,9 @@ public static String executeCreateTaskCommand(String userInput) * Executes the relevant actions when user input update task command. * * @param userInput command input by the user - * @return response by gopher after successful action + * @return Message object indicating response by gopher after successful action */ - public static String executeUpdateTaskCommand(String userInput) { + public static Message executeUpdateTaskCommand(String userInput) { try { String[] tokens = userInput.split(" "); return taskList.update(tokens); @@ -170,14 +171,14 @@ public static String executeUpdateTaskCommand(String userInput) { return UI.getInvalidDateWarning(); } catch (InvalidTokenException | MissingTaskNumberException | InvalidTaskNumberException | InvalidDurationException e) { - return e.getMessage(); + return UI.getErrorMessage(e); } } /** * Start the main event loop. */ - public static String getResponse(String userInput) + public static Message getResponse(String userInput) throws UnknownCommandException { if (userInput.equalsIgnoreCase("bye")) { return executeExitCommand(); diff --git a/src/main/java/gopher/exception/UnknownCommandException.java b/src/main/java/gopher/exception/UnknownCommandException.java index f83474cfc7..9fe255e74f 100644 --- a/src/main/java/gopher/exception/UnknownCommandException.java +++ b/src/main/java/gopher/exception/UnknownCommandException.java @@ -14,6 +14,21 @@ public UnknownCommandException(String command) { public String getMessage() { return "Sorry, but I can't recognize this command: " + this.command - + "\nPlease try again...\n\n"; + + "\nPlease try again...\n\n" + + """ + Currently I can understand the following commands: + 1. todo - Create a ToDo Task + 2. deadline - Create a Deadline Task + 3. event - Create an Event Task + 4. mark - Mark tasks as done + 5. unmark - Mark tasks as not done + 6. find - Find tasks based on keywords + 7. update - Update a task with provided information + 8. delete - Delete tasks from the task list + 9. bye - Exit the chatbot + + Note that the command is case-insensitive, + as long as the input characters match, + I would be able to respond to the given command"""; } } diff --git a/src/main/java/gopher/gui/DialogBox.java b/src/main/java/gopher/gui/DialogBox.java index f9f18be9b3..5ebf7fed19 100644 --- a/src/main/java/gopher/gui/DialogBox.java +++ b/src/main/java/gopher/gui/DialogBox.java @@ -2,8 +2,9 @@ import java.io.IOException; import java.util.Collections; -import java.util.regex.Pattern; +import gopher.message.Message; +import gopher.message.MessageType; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; @@ -54,21 +55,26 @@ private void flip() { } /** - * Render the background of the gopher dialog box based whether the message + * Renders the background of the gopher dialog box based whether the message * is a normal conversation or a warning * - * @param text text within the gopher's dialog box + * @param message text within the gopher's dialog box */ - private void renderBackground(String text) { - Pattern warningPattern = Pattern.compile("Please try again", - Pattern.CASE_INSENSITIVE); - if (warningPattern.matcher(text).find()) { + private void renderBackground(Message message) { + if (message.getType() == MessageType.ERROR) { dialog.getStyleClass().add("warning-color"); - } else { - dialog.getStyleClass().add("reply-color"); + return; } + dialog.getStyleClass().add("reply-color"); } + /** + * Creates a User Dialog Box to represent user's input to Gopher + * + * @param text input from the user + * @param img profile image for the user + * @return DialogBox Object that represents user's input + */ public static DialogBox getUserDialog(String text, Image img) { var db = new DialogBox(text, img); Circle clip = new Circle(32, 32, 32); @@ -76,8 +82,15 @@ public static DialogBox getUserDialog(String text, Image img) { return db; } - public static DialogBox getGopherDialog(String text, Image img) { - var db = new DialogBox(text, img); + /** + * Creates a Gopher Dialog Box to represent Gopher's response to user + * + * @param text response by Gopher + * @param img profile image for Gopher + * @return DialogBox Object that represents Gopher's response + */ + public static DialogBox getGopherDialog(Message text, Image img) { + var db = new DialogBox(text.toString(), img); db.flip(); db.renderBackground(text); return db; diff --git a/src/main/java/gopher/gui/MainWindow.java b/src/main/java/gopher/gui/MainWindow.java index 41a77d5cf5..de2c5a4010 100644 --- a/src/main/java/gopher/gui/MainWindow.java +++ b/src/main/java/gopher/gui/MainWindow.java @@ -2,6 +2,7 @@ import gopher.Gopher; import gopher.exception.UnknownCommandException; +import gopher.message.Message; import gopher.ui.UI; import javafx.fxml.FXML; import javafx.scene.control.Button; @@ -64,7 +65,7 @@ private void handleUserInput() { return; } try { - String response = gopher.getResponse(input); + Message response = gopher.getResponse(input); dialogContainer.getChildren().addAll( DialogBox.getUserDialog(input, userImage), DialogBox.getGopherDialog(response, gopherImage) diff --git a/src/main/java/gopher/message/Message.java b/src/main/java/gopher/message/Message.java new file mode 100644 index 0000000000..1af29c15f4 --- /dev/null +++ b/src/main/java/gopher/message/Message.java @@ -0,0 +1,35 @@ +package gopher.message; + +/** + * Represents message returned by Gopher when user input any commands. + * Contains information such as text, message type. + */ +public class Message { + private String text; + private MessageType type; + + /** + * Constructor for Message class. + * + * @param text text within the message + * @param type type of message, specified by MessageType Enum class + */ + public Message(String text, MessageType type) { + this.text = text; + this.type = type; + } + + /** + * Gets the type of the Message Object + * + * @return type of message + */ + public MessageType getType() { + return this.type; + } + + @Override + public String toString() { + return text; + } +} diff --git a/src/main/java/gopher/message/MessageType.java b/src/main/java/gopher/message/MessageType.java new file mode 100644 index 0000000000..dd08bedf08 --- /dev/null +++ b/src/main/java/gopher/message/MessageType.java @@ -0,0 +1,17 @@ +package gopher.message; + +/** + * Types of messages that Gopher would respond to the user + * @see #TEXT + * @see #ERROR + */ +public enum MessageType { + /** + * Normal text message + */ + TEXT, + /** + * Error message + */ + ERROR +} diff --git a/src/main/java/gopher/task/TaskList.java b/src/main/java/gopher/task/TaskList.java index 9ebe5e89d3..1e7399bb4f 100644 --- a/src/main/java/gopher/task/TaskList.java +++ b/src/main/java/gopher/task/TaskList.java @@ -8,6 +8,7 @@ import gopher.exception.InvalidTaskNumberException; import gopher.exception.InvalidTokenException; import gopher.exception.MissingTaskNumberException; +import gopher.message.Message; import gopher.storage.TaskManager; import gopher.ui.UI; @@ -64,7 +65,7 @@ public void add(Task task) { * @param tokens tokens from the update command * @return UI message showing the detail of the updated task */ - public String update(String[] tokens) + public Message update(String[] tokens) throws InvalidTokenException, MissingTaskNumberException, InvalidTaskNumberException, InvalidDurationException { try { diff --git a/src/main/java/gopher/ui/UI.java b/src/main/java/gopher/ui/UI.java index 1d18710ca0..29ef52cf21 100644 --- a/src/main/java/gopher/ui/UI.java +++ b/src/main/java/gopher/ui/UI.java @@ -1,18 +1,56 @@ package gopher.ui; import gopher.exception.UnknownCommandException; +import gopher.message.Message; +import gopher.message.MessageType; import gopher.task.Task; import gopher.task.TaskList; /** * Represents the UI that handles the user interactions and messages. + * Generally, it outputs Message Object which represents response generated by + * Gopher with relevant information such as text, message type etc. */ public class UI { + /** + * Convert a String text to a Message that can be returned by Gopher. + * + * @param text text to be contained in a message + * @return Message object with the given text as its content + */ + public static Message getMessage(String text) { + return new Message(text, MessageType.TEXT); + } + + /** + * Convert a String text that represents an error message to a Message object + * whose type is MessageType.ERROR. + * + * @param e exception caught by Gopher + * @return Message object of type MessageType.ERROR with the exception's error message as its content + */ + public static Message getErrorMessage(Exception e) { + return new Message(e.getMessage(), MessageType.ERROR); + } + + /** + * Overloading method for getErrorMessage, which takes in a String text + * and convert it to a Message of type MessageType.ERROR. + * + * @param text error message to be shown to the user + * @return Message object of type MessageType.ERROR with the given text as its content + */ + public static Message getErrorMessage(String text) { + return new Message(text, MessageType.ERROR); + } + /** * Get the greeting message to show to the user + * + * @return Message object with greeting message to the user */ - public static String getGreetMessage() { - return "Hi, nice to meet you! I am Gopher!\n" + public static Message getGreetMessage() { + String text = "Hi, nice to meet you! I am Gopher!\n" + "I will be your task managing assistant for today!\n" + "If you want me to handle any task-related issues, here are the available commands:\n\n" + """ @@ -26,128 +64,137 @@ public static String getGreetMessage() { 8. update X [name] [fields] [detail] - update task at position X with the specified name and fields 9. bye - End the interaction """; + return UI.getMessage(text); } /** * Get task visualization for the given TaskList. * * @param tasks TaskList object to be printed + * @return Message object containing task list details */ - public static String getTaskListMessage(TaskList tasks) { - return String.format("You currently have %d %s in the task list\n%s%s", + public static Message getTaskListMessage(TaskList tasks) { + String text = String.format("You currently have %d %s in the task list\n%s%s", tasks.getSize(), tasks.getSize() <= 1 ? "task" : "tasks", tasks, tasks.getSize() == 0 ? "Good job! There's no pending tasks to be done!" : ""); + return UI.getMessage(text); } /** * Get the matched tasks message based on the given matched TaskList. * * @param tasks TaskList object containing all the matched tasks + * @return Message object with the matched task list as content */ - public static String getMatchedTasksMessage(TaskList tasks) { + public static Message getMatchedTasksMessage(TaskList tasks) { if (tasks.getSize() == 0) { - return "Sorry, I can't find any tasks that matches your keyword..."; + return UI.getMessage("Sorry, I can't find any tasks that matches your keyword..."); } - return String.format("I have found %d matching %s in your task list:\n%s", + return UI.getMessage(String.format("I have found %d matching %s in your task list:\n%s", tasks.getSize(), tasks.getSize() == 1 ? "task" : "tasks", - tasks - ); + tasks)); } /** * Get the message when TaskList successfully add in a new task. * - * @param task task to be added + * @param task task to be added + * @return Message object that shows a task is successfully added */ - public static String getAddTaskMessage(Task task) { - return "Got it! I have added this task for you:\n" + task; + public static Message getAddTaskMessage(Task task) { + return UI.getMessage("Got it! I have added this task for you:\n" + task); } /** * Get the message when a given task is successfully mark as done. * * @param task task to be marked as done + * @return Message object that shows a task is successfully marked as done */ - public static String getMarkAsDoneMessage(Task task) { - return String.format("I've marked this task as done:\n%s\nWell done! Keep up the good work!", task); + public static Message getMarkAsDoneMessage(Task task) { + String text = String.format("I've marked this task as done:\n%s\nWell done! Keep up the good work!", + task); + return UI.getMessage(text); } /** * Get the message when a given task is successfully mark as not done. * * @param task task to be marked as not done + * @return Message object that shows a task is successfully marked as done */ - public static String getMarkAsUndoneMessage(Task task) { - return String.format("Ok, I've marked this task as not done yet:\n%s\n", task); + public static Message getMarkAsUndoneMessage(Task task) { + String text = String.format("Ok, I've marked this task as not done yet:\n%s\n", + task); + return UI.getMessage(text); } /** * Get the message when TaskList successfully delete a task. * - * @param task task to be deleted + * @param task task to be deleted + * @return Message object that shows a task is successfully deleted */ - public static String getDeleteTaskMessage(Task task) { - return String.format("Noted. I've removed this task:\n%s\n", task); + public static Message getDeleteTaskMessage(Task task) { + String text = String.format("Noted. I've removed this task:\n%s\n", + task); + return UI.getMessage(text); } /** * Get the exit message. + * + * @return Message object that shows a goodbye message */ - public static String getExitMessage() { - return "Bye. Hope to see you again soon!"; + public static Message getExitMessage() { + return UI.getMessage("Bye. Hope to see you again soon!"); } /** * Get the helping message when user encounters an UnknownCommandException. * * @param e UnknownCommandException thrown by the system + * @return Message object of type MessageType.Error with given exception's error message */ - public static String getUnknownCommandWarning(UnknownCommandException e) { - return e.getMessage() - + - """ - Currently I can understand the following commands: - 1. todo - Create a ToDo Task - 2. deadline - Create a Deadline Task - 3. event - Create an Event Task - 4. mark - Mark tasks as done - 5. unmark - Mark tasks as not done - 6. find - Find tasks based on keywords - 7. update - Update a task with provided information - 8. delete - Delete tasks from the task list - 9. bye - Exit the chatbot - - Note that the command is case-insensitive, - as long as the input characters match, - I would be able to respond to the given command"""; + public static Message getUnknownCommandWarning(UnknownCommandException e) { + return UI.getErrorMessage(e); } /** * Get the helping message when user inputs invalid date. + * + * @return Message object of type MessageType.Error warning user about invalid date or format */ - public static String getInvalidDateWarning() { - return ("Oops...Seems like you have provided me an invalid date...\n" + public static Message getInvalidDateWarning() { + String msg = ("Oops...Seems like you have provided me an invalid date...\n" + "Please try again with a valid date in correct format...\n" + "Currently I can read date inputs in the following formats:\n" + " 1. YYYY-MM-DD\n" + " 2. YYYY-MM-DD hh:mm"); + return UI.getErrorMessage(msg); } /** * Get the message when a given task is successfully updated with the given information. + * + * @return Message object that shows a task is successfully updated */ - public static String getUpdateTaskMessage(Task task) { - return String.format("Alright! I have already updated this task with the given information:\n%s", + public static Message getUpdateTaskMessage(Task task) { + String msg = String.format("Alright! I have already updated this task with the given information:\n%s", task); + return UI.getMessage(msg); } /** * Get the warning message when user inputs an update command without any information. + * + * @return Message object with type MessageType.Error that warns user when input task description is empty */ - public static String getEmptyUpdateCommandWarning() { - return "Sorry, I don't know how you want the task to be updated...\nPlease try again..."; + public static Message getEmptyUpdateCommandWarning() { + String msg = "Sorry, I don't know how you want the task to be updated...\nPlease try again..."; + return UI.getErrorMessage(msg); } }