diff --git a/data/task-data.txt b/data/task-data.txt new file mode 100644 index 000000000..e69de29bb diff --git a/docs/README.md b/docs/README.md index 47b9f984f..f867d28ba 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,30 +1,210 @@ -# Duke User Guide +# Tommi User Guide -// Update the title above to match the actual product name +**Tommi** is a chatbot designed to help users efficiently manage and track their tasks. +With Tommi, users can easily create, edit, save, and load a list of tasks at any time. -// Product screenshot goes here +Tasks are categorized into three types: +- **To-dos**: Simple tasks that need to be completed. +- **Events**: Tasks that have a defined start and end. +- **Deadlines**: Tasks with a target completion. -// Product intro goes here -## Adding deadlines -// Describe the action and its outcome. +## Adding To-do -// Give examples of usage +You can add to-do tasks to your task list. A to-do includes only a description and does not have any time-related information. -Example: `keyword (optional arguments)` +Example: `todo [task description]` -// A description of the expected outcome goes here +Outcome: A new to-do task is added to your list. +Example usage: ``` -expected output +todo read book ``` -## Feature ABC +Expected output: +``` +____________________________________________________________ +Sure. I've added the task: +[T][ ] read book +There are now 2 tasks in the list. +____________________________________________________________ +``` + + +## Adding Deadlines + +You can add deadlines to your task list. A deadline task includes a +description and a specific completion target. + +Example: `deadline [task description] /by [target]` + +Outcome: A new deadline task is added to your list. + +Example usage: +``` +deadline submit cs2113 IP /by Friday 2359 +``` + +Expected output: +``` +____________________________________________________________ +Sure. I've added the task: +[D][ ] submit cs2113 IP (by: 11/10/2024 2359) +There are now 3 tasks in the list. +____________________________________________________________ +``` + +## Adding Events + +You can add events to your task list. An event includes a description, a start, and an end. + +Example: `event [task description] /from [start] /to [end]` + +Outcome: A new event task is added to your list. + +Example usage: +``` +event attend CS2113 award ceremony /from 12/10/2024 /to 17/10/2028 +``` + +Expected output: +``` +____________________________________________________________ +Sure. I've added the task: +[E][ ] attend CS2113 award ceremony (from: 12/10/2024 to 17/10/2028) +There are now 3 tasks in the list. +____________________________________________________________ +``` + +## Listing Tasks + +You can list all tasks currently in your task list. This command will show each task with its type, description, and any associated time information. + +Example: `list` + +Outcome: A list of all tasks is displayed. + +Example usage: +``` +list +``` + +Expected output: +``` +____________________________________________________________ +Here are the tasks in your list: +1. [D][ ] submit cs2113 IP (by: 11/10/2024 2359) + +2. [E][ ] attend CS2113 award ceremony (from: 12/10/2024 to 17/10/2028) +____________________________________________________________ +``` + +## Marking a Task as Done + +You can mark a task as done by specifying its index in the task list. + +Example: `mark [task index]` + +Outcome: The specified task is marked as done. + +Example usage: +``` +mark 2 +``` -// Feature details +Expected output: +``` +____________________________________________________________ +Awesomesauce! I've marked this task as done: +[D][X] submit cs2113 IP (by: 11/10/2024 2359) +____________________________________________________________ +``` + +## Unmarking a Task as Undone + +You can unmark a task as undone by specifying its index in the task list. + +Example: `unmark [task index]` + +Outcome: The specified task is marked as undone. +Example usage: +``` +unmark 2 +``` + +Expected output: +``` +____________________________________________________________ +OK, I've marked this task as undone: +[D][ ] submit cs2113 IP (by: 11/10/2024 2359) +____________________________________________________________ +``` -## Feature XYZ +## Deleting a Task + +You can delete a task from your task list by specifying its index. + +Example: `delete [task index]` + +Outcome: The specified task is removed from your list. + +Example usage: +``` +delete 2 +``` + +Expected output: +``` +____________________________________________________________ +I've removed the task: +[D][ ] submit cs2113 IP (by: 11/10/2024 2359) + +There are now 2 tasks in the list. +____________________________________________________________ +``` -// Feature details \ No newline at end of file +## Searching for a Task + +You can search for tasks in your task list by providing a keyword. The search will return tasks that match the keyword. + +Example: `search [keyword]` + +Outcome: A list of tasks that match the search keyword is displayed. + +Example usage: +``` +search lunch +``` + +Expected output: +``` +____________________________________________________________ +Here are the matching results: +1: [D][ ] eat lunch (by: 2pm) +____________________________________________________________ +``` + +## Exiting the Program + +You can exit the program by using the `bye` command. + +Example: `bye` + +Outcome: The program terminates, and a goodbye message is displayed. + +Example usage: +``` +bye +``` + +Expected output: +``` +____________________________________________________________ +Bye. Hope to see you again soon! +____________________________________________________________ + +Process finished with exit code 0 +``` diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java deleted file mode 100644 index 5d313334c..000000000 --- a/src/main/java/Duke.java +++ /dev/null @@ -1,10 +0,0 @@ -public class Duke { - public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - } -} diff --git a/src/main/java/tommi/Parser.java b/src/main/java/tommi/Parser.java new file mode 100644 index 000000000..fdf696569 --- /dev/null +++ b/src/main/java/tommi/Parser.java @@ -0,0 +1,227 @@ +package tommi; + +import tommi.Task.Deadline; +import tommi.Task.Event; +import tommi.Task.ToDo; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Scanner; + +/** + * Represents Parser of all chat input from the user + */ +public class Parser { + + public static final String BYE_STRING = "bye"; + public static final String LIST_STRING = "list"; + public static final String MARK_STRING = "mark"; + public static final String UNMARK_STRING = "unmark"; + public static final String SEARCH_STRING = "search"; + public static final String DELETE_STRING = "delete"; + public static final String TODO_STRING = "todo"; + public static final String DEADLINE_STRING = "deadline"; + public static final String EVENT_STRING = "event"; + + /** + * Process input and ask for next as long as input is not bye command + * + * @param scanner scanner used for chat + */ + public static void readInputStrings(Scanner scanner) { + String input = scanner.nextLine(); + while (!input.equals(BYE_STRING)) { + processInputCases(input); + input = scanner.nextLine(); + } + } + + /** + * Switch statements for all possibilities of input from the user + * + * @param input String input from user + * @throws IllegalArgumentException If user does not use any of the commands + * @throws RuntimeException If search fails to find save file + */ + public static void processInputCases(String input) { + try { + if (input.equals(LIST_STRING)) { + TaskList.listTasks(); + return; + } + + String[] words = input.split(" "); + checkCommandHasContent(words); + + switch (words[0]) { + case MARK_STRING: + tryMarkTask(words); + trySaveTaskData(); + break; + case UNMARK_STRING: + tryUnmarkTask(words); + trySaveTaskData(); + break; + case SEARCH_STRING: + ArrayList foundResults = Storage.search(words[1]); + Ui.printLine(); + Ui.printSearchResults(foundResults); + Ui.printLine(); + break; + case DELETE_STRING: + tryDeleteTask(words); + trySaveTaskData(); + break; + case TODO_STRING: + TaskList.addTask(new ToDo(false, input.substring(5))); + trySaveTaskData(); + break; + case DEADLINE_STRING: + String deadlineContent = input.substring(9); + checkIllegalDeadlineUsage(deadlineContent); + String[] deadlineParts = deadlineContent.split(" /by ", 2); + TaskList.addTask(new Deadline(false, deadlineParts[0], deadlineParts[1])); + trySaveTaskData(); + break; + case EVENT_STRING: + String eventContent = input.substring(6); + checkIllegalEventUsage(eventContent); + String[] eventParts = input.split(" /from ", 2); + String[] timeParts = eventParts[1].split(" /to ", 2); + TaskList.addTask(new Event(false, eventParts[0].substring(6), timeParts[0], timeParts[1])); + trySaveTaskData(); + break; + default: + throw new IllegalArgumentException( + """ + ____________________________________________________________ + ERROR: Please use a command as shown in the user guide. + ____________________________________________________________""" + ); + } + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + /** + * Throw IllegalArgumentException if "event" command is used without /from or /to + * + * @param eventContent String of input after keyword "event" + * @throws IllegalArgumentException If "event" command is used without /from or /to + */ + private static void checkIllegalEventUsage(String eventContent) { + if (!eventContent.contains(" /from ") || !eventContent.contains(" /to ")) { + throw new IllegalArgumentException( + """ + ____________________________________________________________ + ERROR: Please use keyword "/from" and "/to" in the event. + ____________________________________________________________"""); + } + } + + /** + * Throw IllegalArgumentException if "deadline" command is used without /by + * + * @param deadlineContent String of input after keyword "deadline" + * @throws IllegalArgumentException If "deadline" command is used without /by + */ + private static void checkIllegalDeadlineUsage(String deadlineContent) { + if (!deadlineContent.contains(" /by ")) { + throw new IllegalArgumentException( + """ + ____________________________________________________________ + ERROR: Please use keyword "/by" in the deadline. + ____________________________________________________________"""); + } + } + + /** + * Try and catch for deleting task + * + * @param words User input split into strings separated by " " + * @throws IllegalArgumentException If index is not in TaskList + * @throws NumberFormatException If the input is not an integer + */ + private static void tryDeleteTask(String[] words) { + try { + int taskIndex = Integer.parseInt(words[1]) - 1; + TaskList.deleteTask(taskIndex); + } catch (NumberFormatException e) { + Ui.printLine(); + System.out.println("ERROR: Please use an integer index to delete"); + Ui.printLine(); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + + /** + * Try and catch for unmarking task + * + * @param words User input split into strings separated by " " + * @throws IllegalArgumentException If index is not in TaskList + * @throws NumberFormatException If the input is not an integer + */ + private static void tryUnmarkTask(String[] words) { + try { + int taskIndex = Integer.parseInt(words[1]) - 1; + TaskList.unmarkTask(taskIndex); + } catch (NumberFormatException e) { + Ui.printLine(); + System.out.println("ERROR: Please use an integer index to unmark"); + Ui.printLine(); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + + /** + * Try and catch for marking task + * + * @param words User input split into strings separated by " " + * @throws IllegalArgumentException If index is not in TaskList + * @throws NumberFormatException If the input is not an integer + */ + private static void tryMarkTask(String[] words) { + try { + int taskIndex = Integer.parseInt(words[1]) - 1; + TaskList.markTask(taskIndex); + } catch (NumberFormatException e) { + Ui.printLine(); + System.out.println("ERROR: Please use an integer index to mark"); + Ui.printLine(); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } + + /** + * Check if command is used with any content + * + * @param words User input split into strings separated by " " + * @throws IllegalArgumentException If the command has no information + */ + private static void checkCommandHasContent(String[] words) { + if (words.length <= 1 || words[1].isEmpty()) { + throw new IllegalArgumentException( + """ + ____________________________________________________________ + ERROR: Please provide necessary information for the command used. + ____________________________________________________________""" + ); + } + } + + // Try and save the updated TaskList + private static void trySaveTaskData() { + try { + Storage.saveTaskData(TaskList.getTaskList()); + } catch (IOException e) { + System.out.println("Error: " + e.getMessage()); + } + } +} diff --git a/src/main/java/tommi/Storage.java b/src/main/java/tommi/Storage.java new file mode 100644 index 000000000..1b11db8d0 --- /dev/null +++ b/src/main/java/tommi/Storage.java @@ -0,0 +1,182 @@ +package tommi; + +import tommi.Task.Deadline; +import tommi.Task.Event; +import tommi.Task.Task; +import tommi.Task.ToDo; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.Scanner; +import java.io.FileWriter; +import java.io.IOException; + +public class Storage { + + public static String FILE_PATH = "data/task-data.txt"; + + /** + * Print all tasks in the save file and + * update the current TaskList with the save file data + * + * @throws FileNotFoundException If error accessing save file + */ + public static void loadTaskData() throws FileNotFoundException{ + File taskDataFile = new File(FILE_PATH); + if (!taskDataFile.exists()) { + createSaveFile(); // Create the file if it doesn't exist + return; // Exit early since there's no data to load + } + printSaveFile(); + updateTaskList(); + } + + public static void createSaveFile() { + try { + // Create the data directory if it doesn't exist + File directory = new File("data"); + if (!directory.exists()) { + directory.mkdirs(); // Create the directory + } + + // Create the save file if it doesn't exist + File taskDataFile = new File(FILE_PATH); + if (!taskDataFile.exists()) { + taskDataFile.createNewFile(); + } + + System.out.println("Save file successfully created."); + } catch (IOException e) { + System.out.println("Error creating save file: " + e.getMessage()); + } + } + + /** + * Clear the current save file and update it with the current TaskList + * + * @param taskList current TaskList + * @throws IOException If file cannot be opened + */ + public static void saveTaskData(ArrayList taskList) throws IOException{ + clearSaveFile(); + updateSaveFile(taskList); + } + + /** + * Clear the current save file + * + * @throws IOException If file cannot be opened + */ + public static void clearSaveFile() throws IOException { + FileWriter fw = new FileWriter(FILE_PATH); + fw.write(""); + fw.close(); + } + + /** + * Update the current save file with the current TaskList + * + * @param taskList current TaskList + * @throws IOException If file cannot be opened + */ + public static void updateSaveFile(ArrayList taskList) throws IOException { + for (Task task : taskList) { + FileWriter fw = new FileWriter(FILE_PATH, true); + fw.write(task.toString() + "\n"); + fw.close(); + } + } + + /** + * Print the entire current save file using Scanner + * + * @throws FileNotFoundException If file cannot be opened + */ + public static void printSaveFile() throws FileNotFoundException{ + // assign file to object + File taskDataFile = new File(FILE_PATH); + // use scanner to print file contents + Scanner s = new Scanner(taskDataFile); + while (s.hasNext()) { + System.out.println(s.nextLine()); + } + } + + /** + * Update the current TaskList with the save file contents + * + * @throws FileNotFoundException If file cannot be opened + * @throws IllegalArgumentException If the task type is not Deadline, Event or ToDo + */ + public static void updateTaskList() throws FileNotFoundException{ + //for each line in text file + File taskDataFile = new File(FILE_PATH); + Scanner s = new Scanner(taskDataFile); + while (s.hasNext()) { + String task = s.nextLine(); + boolean isDone = checkIsDone(task); + + char taskType = task.charAt(1); + switch (taskType) { + case 'D': + String[] deadlineParts = task.substring(7).split("\\(by:", 2); + TaskList.addTaskWithoutMessage(new Deadline(isDone, deadlineParts[0], + deadlineParts[1].substring(0, deadlineParts[1].length() - 1))); + break; + case 'E': + String[] eventParts = task.substring(7).split("\\(from:", 2); + String[] timeParts = eventParts[1].split("to", 2); + TaskList.addTaskWithoutMessage(new Event(isDone, eventParts[0], timeParts[0], + timeParts[1].substring(0, timeParts[1].length() - 1))); + break; + case 'T': + String todoContent = task.substring(7); + TaskList.addTaskWithoutMessage(new ToDo(isDone, todoContent)); + break; + default: + throw new IllegalArgumentException( + """ + ____________________________________________________________ + Error in save file formatting! + ____________________________________________________________""" + ); + } + } + } + + /** + * Check if a Task String from save file is done + * + * @param task Task that is represented as a string in the save file + * @return boolean representing whether the task is done or not + */ + public static boolean checkIsDone(String task) { + return task.charAt(4) == 'X'; + } + + /** + * Check if keyword is in any of the lines of the save file and + * return an ArrayList of all the Strings that contain it + * + * @param keyword Keyword we are searching for + * @return ArrayList of the Strings of tasks that contain the keyword + * @throws FileNotFoundException If file cannot be opened + */ + public static ArrayList search(String keyword) throws FileNotFoundException{ + // go through task list and search for the word + ArrayList savedTaskList = new ArrayList<>(); + + // return an arraylist of the tasks + File taskDataFile = new File(FILE_PATH); + Scanner s = new Scanner(taskDataFile); + while (s.hasNext()) { + String textLine = s.nextLine(); + if (textLine.contains(keyword)) { + savedTaskList.add(textLine); + } + } + return savedTaskList; + } + +} diff --git a/src/main/java/tommi/Task/Deadline.java b/src/main/java/tommi/Task/Deadline.java new file mode 100644 index 000000000..15c3f8468 --- /dev/null +++ b/src/main/java/tommi/Task/Deadline.java @@ -0,0 +1,31 @@ +package tommi.Task; + +/** + * Represents a Deadline that is a child class of Task. Contains a + * by string with the user input time deadline is due + */ +public class Deadline extends Task{ + + protected String by; + + public Deadline(boolean isDone, String taskName, String by) { + super(isDone, taskName); + this.by = by; + } + + /** + * Returns a new copy of Deadline object with updated isDone value + * + * @param newIsDone new isDone value + * @return New copy of Deadline with updated isDone + */ + @Override + public Deadline updateIsDone(boolean newIsDone) { + return new Deadline(newIsDone, this.taskName, this.by); + } + + @Override + public String toString() { + return "[D]" + super.toString() + " (by: " + by + ")"; + } +} diff --git a/src/main/java/tommi/Task/Event.java b/src/main/java/tommi/Task/Event.java new file mode 100644 index 000000000..2a14a5a28 --- /dev/null +++ b/src/main/java/tommi/Task/Event.java @@ -0,0 +1,34 @@ +package tommi.Task; + +/** + * Represents an Event that is a child class of Task. Contains a + * from string and a to string with the user input time + * event starts and ends + */ +public class Event extends Task{ + + protected String from; + protected String to; + + public Event(boolean isDone, String taskName, String from, String to) { + super(isDone, taskName); + this.from = from; + this.to = to; + } + + /** + * Returns a new copy of Event object with updated isDone value + * + * @param newIsDone new isDone value + * @return New copy of Event with updated isDone + */ + @Override + public Event updateIsDone(boolean newIsDone) { + return new Event(newIsDone, this.taskName, this.from, this.to); + } + + @Override + public String toString() { + return "[E]" + super.toString() + " (from: " + this.from + " to " + this.to + ")"; + } +} diff --git a/src/main/java/tommi/Task/Task.java b/src/main/java/tommi/Task/Task.java new file mode 100644 index 000000000..2438d1812 --- /dev/null +++ b/src/main/java/tommi/Task/Task.java @@ -0,0 +1,29 @@ +package tommi.Task; + +/** + * Represents a parent class of Task to use in TaskList. All tasks + * contain an isDone to check if it is done and a taskName for user to read + */ +public abstract class Task { + + protected final boolean isDone; + protected final String taskName; + + public Task(boolean isDone, String taskName) { + this.isDone = isDone; + this.taskName = taskName; + } + + /** + * Abstract updateIsDone method to be overwritten in child classes + * + * @param newIsDone new isDone value + * @return New copy of Task with updated isDone + */ + public abstract Task updateIsDone(boolean newIsDone); + + @Override + public String toString() { + return ("[" + (isDone ? "X" : " ") + "] " + taskName); + } +} diff --git a/src/main/java/tommi/Task/ToDo.java b/src/main/java/tommi/Task/ToDo.java new file mode 100644 index 000000000..d2ee42d61 --- /dev/null +++ b/src/main/java/tommi/Task/ToDo.java @@ -0,0 +1,27 @@ +package tommi.Task; + +/** + * Represents a ToDo that is a child class of Task. + */ +public class ToDo extends Task { + + public ToDo(boolean isDone, String taskName) { + super(isDone, taskName); + } + + /** + * Returns a new copy of ToDo object with updated isDone value + * + * @param newIsDone new isDone value + * @return New copy of ToDo with updated isDone + */ + @Override + public ToDo updateIsDone(boolean newIsDone) { + return new ToDo(newIsDone, this.taskName); + } + + @Override + public String toString() { + return "[T]" + super.toString(); + } +} diff --git a/src/main/java/tommi/TaskList.java b/src/main/java/tommi/TaskList.java new file mode 100644 index 000000000..3bff0f3ec --- /dev/null +++ b/src/main/java/tommi/TaskList.java @@ -0,0 +1,107 @@ +package tommi; + +import tommi.Task.Task; + +import java.util.ArrayList; + +public class TaskList { + + private static final ArrayList tasks = new ArrayList<>(); // Array to store tasks + + /** + * Return the current ArrayList of Task for saving in save file + * + * @return current ArrayList of Task + */ + public static ArrayList getTaskList() { + return tasks; + } + + // print the task list using Ui method + public static void listTasks() { + Ui.printTaskList(tasks); + } + + /** + * Add a Task to the current TaskList. Print the task added + * with its index in the ArrayList of Task + * + * @param task Task to be added + */ + public static void addTask(Task task) { + tasks.add(task); + Ui.printAddTask(task, tasks); + } + + /** + * Add a Task to the current TaskList. To be used when adding save file content + * back into empty TaskList when starting program + * + * @param task Task to be added + */ + public static void addTaskWithoutMessage(Task task) { + tasks.add(task); + } + + /** + * Delete a Task from the current TaskList. Print the task deleted + * with its index in the ArrayList of Task. + * + * @param index index of ArrayList of Task to be deleted + * @throws IllegalArgumentException If index given is not in ArrayList of Task + */ + public static void deleteTask(int index) { + if (index >= 0 && index < tasks.size()) { + Ui.printDeleteTask(tasks, index); + tasks.remove(index); + } else { + throw new IllegalArgumentException( + """ + ____________________________________________________________ + ERROR: Cannot delete task as it is out of scope! + ____________________________________________________________"""); + } + } + + /** + * Mark a Task from the current TaskList as done. Print the task marked + * with its index in the ArrayList of Task. + * + * @param index index of ArrayList of Task to be marked + * @throws IllegalArgumentException If index given is not in ArrayList of Task + */ + public static void markTask(int index) { + if (index >= 0 && index < tasks.size()) { + Task updatedTask = tasks.get(index).updateIsDone(true); + tasks.set(index, updatedTask); + Ui.printMarkTask(tasks, index); + } else { + throw new IllegalArgumentException( + """ + ____________________________________________________________ + ERROR: Cannot mark task as it is out of scope! + ____________________________________________________________"""); + } + } + + /** + * Unmark a Task from the current TaskList as done. Print the task unmarked + * with its index in the ArrayList of Task. + * + * @param index index of ArrayList of Task to be unmarked + * @throws IllegalArgumentException If index given is not in ArrayList of Task + */ + public static void unmarkTask(int index) { + if (index >= 0 && index < tasks.size()) { + Task updatedTask = tasks.get(index).updateIsDone(false); + tasks.set(index, updatedTask); + Ui.printUnmarkTask(tasks, index); + } else { + throw new IllegalArgumentException( + """ + ____________________________________________________________ + ERROR: Cannot unmark task as it is out of scope! + ____________________________________________________________"""); + } + } +} diff --git a/src/main/java/tommi/Tommi.java b/src/main/java/tommi/Tommi.java new file mode 100644 index 000000000..107566eda --- /dev/null +++ b/src/main/java/tommi/Tommi.java @@ -0,0 +1,22 @@ +package tommi; + +import java.io.FileNotFoundException; +import java.util.Scanner; + +public class Tommi { + + /** + * Main method that runs. Handles printing of the intro message and exit message, + * and ensure Parser handles intermediate inputs + * + * @param args not used + * @throws FileNotFoundException If Scanner has Error + */ + public static void main(String[] args) throws FileNotFoundException { + Scanner scanner = new Scanner(System.in); + + Ui.printIntroMessage(); + Parser.readInputStrings(scanner); + Ui.printExitMessage(); + } +} diff --git a/src/main/java/tommi/Ui.java b/src/main/java/tommi/Ui.java new file mode 100644 index 000000000..5fe868607 --- /dev/null +++ b/src/main/java/tommi/Ui.java @@ -0,0 +1,138 @@ +package tommi; + +import tommi.Task.Task; + +import java.awt.*; +import java.io.FileNotFoundException; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Scanner; + +public class Ui { + + /** + * Print the intro message with ASCII art, and current save file data. + * + * @throws FileNotFoundException If loading save file fails + */ + public static void printIntroMessage() throws FileNotFoundException { + String introFirstSection = """ + ______ \s + /_ __/__ __ _ __ _ (_) + / / / _ \\/ ' \\/ ' \\/ /\s + /_/ \\___/_/_/_/_/_/_/_/ \s + ____________________________________________________________ + Hello! I'm Tommi! + Here's your last-saved task list: + """; + System.out.println(introFirstSection); + + Storage.loadTaskData(); + + String introSecondSection = """ + ____________________________________________________________ + How can I help you? + ____________________________________________________________ + """; + System.out.println(introSecondSection); + } + + public static void printExitMessage() { + printLine(); + System.out.println("Bye. Hope to see you again soon!"); + printLine(); + } + + /** + * Print the entire TaskList with indexes. + * + * @param tasks Represents TaskList + */ + public static void printTaskList(ArrayList tasks) { + printLine(); + System.out.println("Here are the tasks in your list:"); + for (int i = 0; i < tasks.size(); i++) { + System.out.println((i + 1) + ". " + tasks.get(i)); + } + printLine(); + } + + /** + * Print the task Added with index and current number of tasks in list + * + * @param tasks Represents TaskList + * @param task Represents Task that was added + */ + public static void printAddTask(Task task, ArrayList tasks) { + printLine(); + System.out.println("Sure. I've added the task: " + System.lineSeparator() + + task + System.lineSeparator() + + "There are now " + tasks.size() + " tasks in the list."); + printLine(); + } + + /** + * Print the task Deleted with its index and current number of tasks in list + * + * @param tasks Represents TaskList + * @param index Represents index of Task that was deleted + */ + public static void printDeleteTask(ArrayList tasks, int index) { + printLine(); + System.out.println("I've removed the task: " + System.lineSeparator() + + tasks.get(index) + System.lineSeparator()); + System.out.println( "There are now " + (tasks.size() - 1) + " tasks in the list."); + printLine(); + } + + /** + * Print the task Marked with its index and current number of tasks in list + * + * @param tasks Represents TaskList + * @param index Represents index of Task that was marked + */ + public static void printMarkTask(ArrayList tasks, int index) { + Ui.printLine(); + System.out.println("Awesomesauce! I've marked this task as done:" + + tasks.get(index)); + Ui.printLine(); + } + + /** + * Print the task Unmarked with its index and current number of tasks in list + * + * @param tasks Represents TaskList + * @param index Represents index of Task that was unmarked + */ + public static void printUnmarkTask(ArrayList tasks, int index) { + Ui.printLine(); + System.out.println("OK, I've marked this task as undone:" + + tasks.get(index)); + Ui.printLine(); + } + + /** + * Print the ArrayList of Strings in save file containing the keyword. + * If no matches let the user know through a special message. + * + * @param foundResults Represents collection of strings in save file with keyword + */ + public static void printSearchResults(ArrayList foundResults) { + if (foundResults.isEmpty()) { + System.out.println("No results found!"); + return; + } + + System.out.println("Here are the matching results: "); + int index = 1; + for (String result : foundResults) { + System.out.println(index + ": " + result); + index++; + } + + } + + public static void printLine() { + System.out.println("____________________________________________________________"); + } +}