diff --git a/docs/README.md b/docs/README.md index 8077118eb..7c98ffa2a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,29 +1,111 @@ -# User Guide +# Nano User Guide -## Features +Nano is the chatbot for individual project for CS2113, AY22/23 Semester 2. -### Feature-ABC +Nano is named after the nano machine from the fantasy wuxia novel Nano Machine! -Description of the feature. +## Table of Contents -### Feature-XYZ +- [Nano User Guide](#nano-user-guide) + - [Features](#features) + - [Task Creation](#task-creation) + - [Task Management](#task-management) + - [Commands](#commands) + - [add - Add new task](#add---add-new-task) + - [list - Display your Task List](#list---display-your-task-list) + - [mark - Tag task as done](#mark---tag-task-as-done) + - [unmark - Tag task as undone](#unmark---tag-task-as-undone) + - [delete - Delete a Task](#delete---delete-a-task) + - [find - Query for a task](#find---look-for-a-task) + - [exit - Nano goes to sleep](#exit---nano-goes-to-sleep) -Description of the feature. +## Features -## Usage +Nano has a variety of features for you to manage your tasks efficiently via CLI. -### `Keyword` - Describe action +### Task Creation -Describe the action and its outcome. +Keep track of your tasks in a list. -Example of usage: +Nano can manage up to three types of tasks: +1. Todo - regular todo tasks +2. Deadline - tasks that with a deadline +3. Event - tasks that have a start and end time -`keyword (optional arguments)` +### Task Management -Expected outcome: +Nano can help you mark, unmark, list, find, and save your tasks easily! -Description of the outcome. +- Nano marks your tasks to indicated that you have completed it. +- Nano can list out all your current tasks and its details. +- Nano allows you to look for specific tasks using a keyword. +- Nano can save your task list. + +## Commands + +### add - Add new task + +Add a new task(Todo, Deadline, Event). Nano will automatically detect the type of task for you. + +Syntax: + +``/add `` + +``/add by/`` + +``/add from/ to/`` + +### list - Display your task list + +Nano will show you your list of tasks. +The list contains all the task details as well + +Syntax: + +``/list`` + +### mark - Tag task as done +Nano marks a task in the task list as done + +Syntax: +``/mark `` + + +### unmark - Tag task as undone + +Nano marks a task in the task list as not done. + +Syntax: +``/unmark `` + + +### delete - Delete a Task + +Nano deletes a task from your task list. + +Syntax: +``delete `` + +### find - Look for a task + +Nano will look for the tasks containing a keyword and display them to you. + +Syntax: + +``/find `` + +### help - Displays all commands + +Nano reminds you of all his features and their syntax + +Syntax: +``/help`` + +### exit - Nano goes to sleep + +Nano enters into sleeping mode. + +Syntax: + +``/exit`` -``` -expected output -``` 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/nano/Nano.java b/src/main/java/nano/Nano.java new file mode 100644 index 000000000..6c820a812 --- /dev/null +++ b/src/main/java/nano/Nano.java @@ -0,0 +1,44 @@ +package nano; + +import nano.data.TaskList; +import nano.data.exception.NanoCommandException; +import nano.parser.Parser; +import nano.storage.Storage; +import nano.ui.Ui; + +import java.io.IOException; + +public class Nano { + + private static Storage storage; + private static Ui ui; + private static TaskList tasks; + + public Nano(String filePath) { + //chatbot startup + ui = new Ui(); + storage = new Storage(filePath); + tasks = new TaskList(storage); + } + + /** + * + */ + public void run() { + while (true) { + String userInput = ui.getUserInput(); + try { + Parser.executeCommand(userInput, tasks); + storage.saveTaskFile(tasks.getTaskList()); + } catch (NanoCommandException commandException) { + Ui.displayUnknownCommandMessage(); + } catch (IOException e) { + System.out.println("Error saving file."); + } + } + } + + public static void main(String[] args) { + new Nano("data/tasks.txt").run(); + } +} \ No newline at end of file diff --git a/src/main/java/nano/data/TaskList.java b/src/main/java/nano/data/TaskList.java new file mode 100644 index 000000000..7ee41b600 --- /dev/null +++ b/src/main/java/nano/data/TaskList.java @@ -0,0 +1,186 @@ +package nano.data; + +import nano.ui.Ui; +import nano.storage.Storage; +import nano.data.task.Deadline; +import nano.data.task.Event; +import nano.data.task.Task; +import nano.data.task.Todo; + +import java.util.ArrayList; + +public class TaskList { + private static final int TASK_NAME_INDEX = 0; + private static final int TASK_TYPE_INDEX = 1; + private static final int TASK_START_DATE_INDEX = 2; + private static final int TASK_DUE_DATE_INDEX = 2; + private static final int TASK_END_DATE_INDEX = 3; + private static final int TASK_INDEX_ERROR = -1; + private final ArrayList tasks; + + public TaskList() { + tasks = new ArrayList<>(); + } + + public TaskList(Storage storage) { + tasks = new ArrayList<>(); + storage.getUserData(tasks); + + } + + /** + * Delete task from task list. + * + * @param taskName Name of task to delete. + */ + public void deleteTask(String taskName) { + int taskIndex = getTaskIndex(taskName); + if (taskIndex == TASK_INDEX_ERROR) { + Ui.displayTaskNotFoundMessage(); + return; + } + + tasks.remove(taskIndex); + Task.deleteTask(); + System.out.println("Deleted " + taskName); + } + + /** + * Set task as uncompleted. + * + * @param taskName Name of task to unmark. + */ + public void unmarkTask(String taskName) { + int taskIndex = getTaskIndex(taskName); + if (taskIndex == TASK_INDEX_ERROR) { + Ui.displayTaskNotFoundMessage(); + return; + } + + if (tasks.get(taskIndex).isCompleted()) { + tasks.get(taskIndex).setUndone(); + Ui.displayUnmarkTaskMessage(taskName); + } else { + Ui.displayTaskAlreadyUndoneMessage(taskName); + } + } + + /** + * Set task as completed. + * + * @param taskName Name of task to mark. + */ + public void markTask(String taskName) { + int taskIndex = getTaskIndex(taskName); + if (taskIndex == TASK_INDEX_ERROR) { + Ui.displayTaskNotFoundMessage(); + return; + } + + if (!tasks.get(taskIndex).isCompleted()) { + tasks.get(taskIndex).setDone(); + Ui.displayMarkTaskMessage(taskName); + } else { + Ui.displayTaskAlreadyDoneMessage(taskName); + } + } + + /** + * Returns index of task in task list. + * + * @param taskName Name of task. + * @return Index of task. + */ + private int getTaskIndex(String taskName) { + for (Task task : tasks) { + if (task.getTaskName().equals(taskName)) { + return tasks.indexOf(task); + } + } + return TASK_INDEX_ERROR; + } + + /** + * Adds task to task list. + * + * @param taskDetails Details of task added + */ + public void addTask(String[] taskDetails) { + if (isInList(taskDetails[TASK_NAME_INDEX])) { + System.out.println(taskDetails[TASK_NAME_INDEX] + " is already in the list!"); + return; + } + + Task newTask; + switch (taskDetails[TASK_TYPE_INDEX]) { + case "deadline": + newTask = new Deadline(taskDetails[TASK_NAME_INDEX], taskDetails[TASK_DUE_DATE_INDEX]); + break; + case "event": + newTask = new Event(taskDetails[TASK_NAME_INDEX], taskDetails[TASK_START_DATE_INDEX], + taskDetails[TASK_END_DATE_INDEX]); + break; + default: + newTask = new Todo(taskDetails[TASK_NAME_INDEX]); + break; + } + tasks.add(newTask); + System.out.println("Added " + taskDetails[TASK_NAME_INDEX]); + } + + /** + * Check if task is found in task list. + * + * @param taskName Name of task. + * @return true if task is in task list. Returns false otherwise. + */ + public boolean isInList(String taskName) { + for (Task task : tasks) { + if (task.getTaskName().equals(taskName)) { + return true; + } + } + return false; + } + + /** + * Get lists of task + * + * @return Task list. + */ + public ArrayList getTaskList() { + return tasks; + } + + /** + * Finds and displays all tasks containing a keyword. + * + * @param keyword Keyword used in search. + */ + public void findTasks(String keyword) { + + if (isInvalidKeyword(keyword)) { + Ui.displayKeywordError(); + return; + } + + keyword = keyword.trim(); + ArrayList searchList = new ArrayList<>(); + for (Task task : tasks) { + if (task.getTaskName().contains(keyword)) { + searchList.add(task); + } + } + + Ui.displayFindTaskMessage(searchList.size(), keyword); + Ui.displayTaskList(searchList); + } + + private static boolean isInvalidKeyword(String keyword) { + if (keyword == null) { + return true; + } + + return keyword.trim().length() == 0; + } +} \ No newline at end of file diff --git a/src/main/java/nano/data/exception/NanoCommandException.java b/src/main/java/nano/data/exception/NanoCommandException.java new file mode 100644 index 000000000..64e4f873d --- /dev/null +++ b/src/main/java/nano/data/exception/NanoCommandException.java @@ -0,0 +1,4 @@ +package nano.data.exception; + +public class NanoCommandException extends Exception { +} diff --git a/src/main/java/nano/data/exception/NanoInputFormatException.java b/src/main/java/nano/data/exception/NanoInputFormatException.java new file mode 100644 index 000000000..c77c98b71 --- /dev/null +++ b/src/main/java/nano/data/exception/NanoInputFormatException.java @@ -0,0 +1,4 @@ +package nano.data.exception; + +public class NanoInputFormatException extends Exception{ +} diff --git a/src/main/java/nano/data/task/Deadline.java b/src/main/java/nano/data/task/Deadline.java new file mode 100644 index 000000000..953102305 --- /dev/null +++ b/src/main/java/nano/data/task/Deadline.java @@ -0,0 +1,15 @@ +package nano.data.task; + +public class Deadline extends Task{ + private static final String TASK_TYPE_TAG = "[D]"; + private String dueDate; + public Deadline(String name, String dueDate) { + super(name); + this.dueDate = dueDate; + } + + + public String toString() { + return TASK_TYPE_TAG + super.toString() + " (by: " + dueDate + ")"; + } +} diff --git a/src/main/java/nano/data/task/Event.java b/src/main/java/nano/data/task/Event.java new file mode 100644 index 000000000..78a56aeea --- /dev/null +++ b/src/main/java/nano/data/task/Event.java @@ -0,0 +1,17 @@ +package nano.data.task; + +public class Event extends Task { + private static final String TASK_TYPE_TAG = "[E]"; + private String startDate; + private String endDate; + + public Event(String name, String startDate, String endDate) { + super(name); + this.startDate = startDate; + this.endDate = endDate; + } + + public String toString() { + return TASK_TYPE_TAG + super.toString() + " (from: " + startDate + ", to: " + endDate + ")"; + } +} diff --git a/src/main/java/nano/data/task/Task.java b/src/main/java/nano/data/task/Task.java new file mode 100644 index 000000000..9741cdc3c --- /dev/null +++ b/src/main/java/nano/data/task/Task.java @@ -0,0 +1,63 @@ +package nano.data.task; + +public class Task { + public static final String TASK_COMPLETED_MARK = "[x] "; + public static final String TASK_UNCOMPLETED_MARK = "[] "; + private String name; + private boolean isCompleted; + private static int taskCount = 0; + private static int completedTaskCount = 0; + + public Task(String name) { + this.name = name; + this.isCompleted = false; + taskCount += 1; + } + + public void setDone() { + this.isCompleted = true; + completedTaskCount += 1; + } + + public void setUndone() { + this.isCompleted = false; + completedTaskCount -= 1; + } + + public String getTaskName() { + return this.name; + } + + public boolean isCompleted() { + return this.isCompleted; + } + + public static int getTaskCount() { + return taskCount; + } + + public static int getCompletedTaskCount() { + + return completedTaskCount; + } + + public static int getUncompletedTaskCount() { + return taskCount - completedTaskCount; + } + + private String todoMark() { + if (isCompleted()) { + return TASK_COMPLETED_MARK; + } else { + return TASK_UNCOMPLETED_MARK; + } + } + + public String toString() { + return todoMark() + getTaskName(); + } + + public static void deleteTask() { + taskCount -= 1; + } +} \ No newline at end of file diff --git a/src/main/java/nano/data/task/Todo.java b/src/main/java/nano/data/task/Todo.java new file mode 100644 index 000000000..be87de3d4 --- /dev/null +++ b/src/main/java/nano/data/task/Todo.java @@ -0,0 +1,14 @@ +package nano.data.task; + +public class Todo extends Task{ + private static final String TASK_TYPE_TAG = "[T]"; + + public Todo(String name) { + super(name); + } + + @Override + public String toString() { + return TASK_TYPE_TAG + super.toString(); + } +} diff --git a/src/main/java/nano/parser/Parser.java b/src/main/java/nano/parser/Parser.java new file mode 100644 index 000000000..56ae06b9c --- /dev/null +++ b/src/main/java/nano/parser/Parser.java @@ -0,0 +1,134 @@ +package nano.parser; + +import nano.data.TaskList; +import nano.ui.Ui; +import nano.data.exception.NanoCommandException; +import nano.data.exception.NanoInputFormatException; + +import java.util.Arrays; + +public class Parser { + private static final int COMMAND_INDEX = 0; + private static final int TASK_NAME_INDEX = 1; + + private static final int TASK_TYPE_INDEX = 2; + private static final int TASK_START_DATE_INDEX = 3; + private static final int TASK_DUE_DATE_INDEX = 3; + private static final int TASK_END_DATE_INDEX = 4; + private static final int USER_INPUT_MAX_ARG_COUNT = 4; + + /** + * Executes command entered by user. + * + * @param userInput Input entered by user. + * @param tasks Task list + * @throws NanoCommandException If unknown command is given. + */ + public static void executeCommand(String userInput, TaskList tasks) throws NanoCommandException { + String[] userInputs; + try { + userInputs = processInput(userInput); + } catch (NanoInputFormatException inputException) { + Ui.displayInputErrorMessage(); + return; + } + + switch (userInputs[COMMAND_INDEX]) { + case "list": + Ui.displayTaskListMessage(tasks.getTaskList()); + break; + case "add": + tasks.addTask(Arrays.copyOfRange(userInputs, 1, USER_INPUT_MAX_ARG_COUNT + 1)); + break; + case "delete": + tasks.deleteTask(userInputs[TASK_NAME_INDEX]); + break; + case "mark": + tasks.markTask(userInputs[TASK_NAME_INDEX]); + break; + case "unmark": + tasks.unmarkTask(userInputs[TASK_NAME_INDEX]); + break; + case "find": + tasks.findTasks(userInputs[TASK_NAME_INDEX]); + break; + case "help": + Ui.displayCommandList(); + break; + case "exit": + Ui.displayExitMessage(); + System.exit(0); + default: + throw new NanoCommandException(); + } + Ui.printHorizontalLine(); + } + + /** + * Returns processed input entered by user to separate command and the details. + * + * @param userInput Input entered by user. + * @return Processed input. + * @throws NanoInputFormatException If user input does not follow the correct format. + */ + private static String[] processInput(String userInput) throws NanoInputFormatException { + userInput = userInput.trim(); + if (!userInput.startsWith("/")) { + throw new NanoInputFormatException(); + } + userInput = userInput.replaceFirst("/", ""); + String[] userInputs = new String[USER_INPUT_MAX_ARG_COUNT + 1]; + String[] commandAndName = userInput.split("\\s+", 2); + System.arraycopy(commandAndName, 0, userInputs, 0, commandAndName.length); + + if (commandAndName.length == 2) { + processTaskDetails(userInput, userInputs); + } + return userInputs; + } + + /** + * Process tasks into its details based on its task type. + * + * @param userInput Input entered by user. + * @param userInputs Array of Strings to store processed input. + * @throws NanoInputFormatException If tasks details are in an invalid format. + */ + private static void processTaskDetails(String userInput, String[] userInputs) throws NanoInputFormatException { + if (isDeadline(userInput)) { + getDeadline(userInput, userInputs); + } else if (isEvent(userInput)) { + getEvent(userInput, userInputs); + } else if (userInput.contains("/")) { + throw new NanoInputFormatException(); + } else { + getTodo(userInputs); + } + } + + private static void getTodo(String[] userInputs) { + userInputs[TASK_TYPE_INDEX] = "todo"; + } + + private static void getEvent(String userInput, String[] userInputs) { + userInputs[TASK_TYPE_INDEX] = "event"; + userInputs[TASK_NAME_INDEX] = userInput.substring(userInput.indexOf(" "), userInput.indexOf("from/")).trim(); + userInputs[TASK_START_DATE_INDEX] = userInput.substring(userInput.indexOf("from/") + 5, + userInput.indexOf("to/")).trim(); + userInputs[TASK_END_DATE_INDEX] = userInput.substring(userInput.indexOf("to/") + 3).trim(); + } + + private static void getDeadline(String userInput, String[] userInputs) { + userInputs[TASK_TYPE_INDEX] = "deadline"; + userInputs[TASK_NAME_INDEX] = userInput.substring(userInput.indexOf(" "), userInput.indexOf("by/")).trim(); + userInputs[TASK_DUE_DATE_INDEX] = userInput.substring(userInput.indexOf("by/") + 3).trim(); + } + + private static boolean isDeadline(String task) { + return task.contains("by/"); + } + + private static boolean isEvent(String task) { + return task.contains("from/") && task.contains("to/"); + } +} \ No newline at end of file diff --git a/src/main/java/nano/storage/Storage.java b/src/main/java/nano/storage/Storage.java new file mode 100644 index 000000000..5e2bfa338 --- /dev/null +++ b/src/main/java/nano/storage/Storage.java @@ -0,0 +1,124 @@ +package nano.storage; + +import nano.ui.Ui; +import nano.data.task.Deadline; +import nano.data.task.Event; +import nano.data.task.Task; +import nano.data.task.Todo; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; + +import java.util.ArrayList; +import java.util.Scanner; + +public class Storage { + + private static final File defaultFile = new File("data/tasks.txt"); + private final File taskFile; + + public Storage() { + taskFile = defaultFile; + } + + public Storage(String taskFile) { + this.taskFile = new File(taskFile); + } + + /** + * Reads froms task text datafile and adds tasks into a list. + * + * @param tasks List of tasks. + */ + public void getUserData(ArrayList tasks){ + if (taskFile.exists()) { + try { + Scanner s = new Scanner(taskFile); + while (s.hasNext()) { + readTaskFile(s.nextLine(),tasks); + } + } catch (FileNotFoundException e) { + System.out.println("Error reading task file."); + } + } else { + System.out.println("User task file not detected. Creating new task file....."); + createTaskFile(); + } + } + + /** + * Processes task details from task text datafile and add task to a list. + * + * @param taskDetails Details of task to add. + * @param tasks List of tasks. + */ + private static void readTaskFile(String taskDetails, ArrayList tasks) { + Task newTask; + String taskName; + if (taskDetails.charAt(taskDetails.length() - 1) == ')') { + taskName = taskDetails.substring(taskDetails.indexOf(" ") + 1, taskDetails.lastIndexOf(" (")); + } else { + taskName = taskDetails.substring(taskDetails.indexOf(" ") + 1); + } + + switch (taskDetails.substring(1, 2)) { + case "D": + newTask = new Deadline(taskName, taskDetails.substring(taskDetails.indexOf("by:") + 4, + taskDetails.lastIndexOf(')'))); + break; + case "E": + newTask = new Event(taskName, taskDetails.substring(taskDetails.indexOf("from:") + 5, + taskDetails.indexOf(", to:")).trim(), + taskDetails.substring(taskDetails.indexOf("to:") + 4, taskDetails.lastIndexOf(')')).trim()); + break; + default: + newTask = new Todo(taskName); + break; + } + tasks.add(newTask); + + if (taskDetails.contains("[x]")) { + tasks.get(tasks.size() - 1).setDone(); + } + } + + /** + * Creates directories and files to store task list. + * Only created when task text datafile does not exist. + */ + private void createTaskFile() { + try { + if (taskFile.getParentFile().mkdirs()) { + System.out.println("Creating directories....."); + } else { + System.out.println("Unable to create directories. User data may not be saved."); + } + + if (taskFile.createNewFile()) { + System.out.println("Task file created!"); + } else { + System.out.println("Unable to create task file. User data may not be saved."); + } + + } catch (IOException e) { + System.out.println("Error detected while creating user task file. User data may not be saved."); + } + Ui.printHorizontalLine(); + } + + /** + * Saves task lists into a text datafile. + * + * @param tasks List of tasks. + * @throws IOException If unable to write to text datafile. + */ + public void saveTaskFile(ArrayList tasks) throws IOException { + FileWriter fileWriter = new FileWriter(taskFile); + for (Task task : tasks) { + fileWriter.write(task.toString() + System.lineSeparator()); + } + fileWriter.close(); + } +} \ No newline at end of file diff --git a/src/main/java/nano/ui/Ui.java b/src/main/java/nano/ui/Ui.java new file mode 100644 index 000000000..a6f00fe3b --- /dev/null +++ b/src/main/java/nano/ui/Ui.java @@ -0,0 +1,205 @@ +package nano.ui; + +import nano.data.task.Task; + +import java.util.ArrayList; +import java.util.Scanner; + +public class Ui { + + private static final String HORIZONTAL_LINE = "_______________________________________________________________________"; + private static final String NANO_LOGO = "| \\ || / \\ | \\ ||| __ |\n" + + "||\\\\ || / _ \\ ||\\\\ ||| | | |\n" + + "|| \\\\|| // \\\\ || \\\\||| |__| |\n" + + "|| \\_|// \\\\|| \\_||______|\n"; + private static final String MESSAGE_TASK_NOT_FOUND = "Task not found!"; + private static final String MESSAGE_TASK_MARKED = "Great job completing "; + private static final String MESSAGE_TASK_ALREADY_DONE = " is already done."; + private static final String MESSAGE_TASK_ALREADY_UNDONE = " is already not done."; + private static final String MESSAGE_TASK_UNMARKED = " set to undone!"; + private static final String MESSAGE_HELP_COMMAND = "Enter \"/help\" for full command list"; + private static final String MESSAGE_EXIT = "Sleep mode activated."; + private static final String MESSAGE_HELP_LIST_COMMAND = "/list : Displays list of tasks"; + private static final String MESSAGE_HELP_ADD_EVENT = "/add from/ to/" + + " : Add new event"; + private static final String MESSAGE_HELP_ADD_DEADLINE = "/add by/ : Add new deadline"; + private static final String MESSAGE_HELP_ADD_TODO = "/add : Add new Todo"; + private static final String MESSAGE_HELP_DELETE_TASK = "/delete : Delete task \"Task_Name\""; + private static final String MESSAGE_HELP_MARK_TASK = "/mark : Set \"Task_Name\" as completed"; + private static final String MESSAGE_HELP_UNMARK_TASK = "/unmark : Set \"Task_Name\" as " + + "undone"; + private static final String MESSAGE_HELP_FIND_TASK = "/find : Find and displays all tasks " + + "with keyword"; + private static final String MESSAGE_HELP_HELP = "/help : Displays list of all commands"; + private static final String MESSAGE_HELP_EXIT = "/exit : Exit chatbot"; + public static final String MESSAGE_INVALID_KEYWORD = "Invalid keyword entered!"; + + private final Scanner in; + public Ui() { + this.in = new Scanner(System.in); + displayWelcomeMessage(); + } + + /** + * Displays header message when displaying list of tasks found using find command. + * + * @param numOfTask number of tasks in list. + * @param keyword keyword used in search. + */ + public static void displayFindTaskMessage(int numOfTask, String keyword) { + System.out.println("There are " + numOfTask + " tasks with \"" + keyword +"\":"); + } + + /** + * Displays error message when an invalid keyword is used for find command. + */ + public static void displayKeywordError() { + System.out.println(MESSAGE_INVALID_KEYWORD); + } + + /** + * Returns input entered by user. + * + * @return Input by user. + */ + public String getUserInput() { + return in.nextLine(); + } + + /** + * Displays the startup message of NANO chatbot. + */ + public static void displayWelcomeMessage() { + printHorizontalLine(); + System.out.println(NANO_LOGO); + System.out.println("Serial number: 034-4532-5893....."); + System.out.println("Activating the 7th generation Nano Machine of the Chan Corporation....."); + printHorizontalLine(); + System.out.println("How may I assist you?"); + printHorizontalLine(); + } + + /** + * Display a horizontal line. + * This improves visual readability of output by separating chunks of text. + */ + public static void printHorizontalLine() { + System.out.println(HORIZONTAL_LINE); + } + + /** + * Displays a list of tasks with numbering. + * + * @param tasks List of tasks. + */ + public static void displayTaskList(ArrayList tasks) { + int counter = 1; + for (Task task : tasks) { + System.out.println(counter + ". " +task.toString()); + counter += 1; + } + } + + /** + * Displays lists of tasks with list command. + * It also informs user how many tasks are completed and uncompleted. + * + * @param tasks List of tasks. + */ + public static void displayTaskListMessage(ArrayList tasks) { + System.out.println("You have completed " + Task.getCompletedTaskCount() + " tasks. " + + Task.getUncompletedTaskCount() + " more to go!"); + displayTaskList(tasks); + } + + /** + * Displays exit message after exit command. + */ + public static void displayExitMessage() { + System.out.println(MESSAGE_EXIT); + } + + /** + * Displays details and formats for all commands. + */ + public static void displayCommandList() { + // list,add,mark,unmark,help,exit + printHorizontalLine(); + System.out.println(MESSAGE_HELP_LIST_COMMAND); + System.out.println(MESSAGE_HELP_ADD_EVENT); + System.out.println(MESSAGE_HELP_ADD_DEADLINE); + System.out.println(MESSAGE_HELP_ADD_TODO); + System.out.println(MESSAGE_HELP_DELETE_TASK); + System.out.println(MESSAGE_HELP_MARK_TASK); + System.out.println(MESSAGE_HELP_UNMARK_TASK); + System.out.println(MESSAGE_HELP_FIND_TASK); + System.out.println(MESSAGE_HELP_HELP); + System.out.println(MESSAGE_HELP_EXIT); + } + + /** + * Displays how to use help command when user enters an invalid input. + */ + public static void displayHelpMessage() { + System.out.println(MESSAGE_HELP_COMMAND); + } + + /** + * Displays message when task does not exist in the list. + */ + public static void displayTaskNotFoundMessage() { + System.out.println(MESSAGE_TASK_NOT_FOUND); + } + + /** + * Displays message when task has been unmarked. + * + * @param taskName Name of task unmarked. + */ + public static void displayUnmarkTaskMessage(String taskName) { + System.out.println(taskName + MESSAGE_TASK_UNMARKED); + } + + /** + * Displays message when task is already undone. + * + * @param taskName Name of task being unmarked. + */ + public static void displayTaskAlreadyUndoneMessage(String taskName) { + System.out.println(taskName + MESSAGE_TASK_ALREADY_UNDONE); + } + + /** + * Displays message when task is marked. + * + * @param taskName Name of task marked. + */ + public static void displayMarkTaskMessage(String taskName) { + System.out.println(MESSAGE_TASK_MARKED + taskName + '!'); + } + + /** + * Displays message when task is already done. + * + * @param taskName Name of task being marked. + */ + public static void displayTaskAlreadyDoneMessage(String taskName) { + System.out.println(taskName + MESSAGE_TASK_ALREADY_DONE); + } + + /** + * Displays message when user enters an invalid input. + */ + public static void displayInputErrorMessage() { + System.out.println("Input error!"); + displayHelpMessage(); + } + + /** + * Displays message when user enters an unknown command. + */ + public static void displayUnknownCommandMessage() { + System.out.println("Unknown command!"); + displayHelpMessage(); + } +} \ No newline at end of file