diff --git a/docs/README.md b/docs/README.md index 8077118eb..c9440b95e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,29 +1,142 @@ # User Guide +Duke is a cross-platform desktop task manager app that helps you keep track of your tasks through the command line interface. +Fast and lightweight, it is best suited for fast typists. -## Features - -### Feature-ABC +- [Set Up](#setup) +- [Quick Start](#quick-start) +- [Features](#features) + - [Getting help](#getting-help-help) + - [Adding a Todo Task](#adding-a-todo-task-todo) + - [Adding a Deadline Task](#adding-a-deadline-task-deadline) + - [Adding an Event Task](#adding-an-event-task-event) + - [Listing all Tasks](#listing-all-tasks-list) + - [Marking Task as Done](#marking-task-as-done-done) + - [Finding Tasks](#finding-tasks-find) + - [Deleting Tasks](#deleting-tasks-delete) + - [Exiting Duke](#exiting-duke-bye) + - [Auto Save](#auto-save) +- [Command Summary](#command-summary) -Description of the feature. +## Setup +1. Ensure that you have [Java 11](https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/downloads-list.html) installed in your desktop +2. Download the [latest version of Duke](https://github.com/flerovious/ip/releases/tag/A-Release) +3. You should have `ip.jar` downloaded. Now, copy the `ip.jar` to the folder you want to use for Duke +4. Open command prompt on Windows or terminal on Mac/Ubuntu +5. `cd` to the folder selected in step 3 +6. Run Duke with `java -jar ip.jar` in your command prompt or terminal -### Feature-XYZ +## Quick Start +1. On startup, you should see the following \ +![startup_screen](screenshots/startup_screen.png) +2. Type commands and press Enter to execute them. Enter the `help` command if you ever get lost +3. Refer to [Features](#features) below for details of each command -Description of the feature. +## Features +The following are the features of Duke -## Usage +### Getting help `help` +Lists all possible commands and their syntax \ +\ +Example usage: +```console +help +``` +Expected outcome: \ +![startup_screen](screenshots/command_outcomes/help.png) -### `Keyword` - Describe action +### Adding a Todo Task `todo` +Adds a Todo task which includes the title of the todo \ +\ +Example of usage: +```console +todo Prepare for CG2027 finals +``` +Expected outcome: \ +![startup_screen](screenshots/command_outcomes/todo.png) -Describe the action and its outcome. +### Adding a Deadline Task `deadline` +Adds a Deadline task which includes the title of the deadline and the due date in `yyyy-mm-dd` format \ +\ +Example of usage: +```console +deadline CS2113T weekly quiz /by 2021-10-01 +``` +Expected outcome: \ +![startup_screen](screenshots/command_outcomes/deadline.png) -Example of usage: +### Adding an Event Task `event` +Adds an Event task which includes the title of the event and the time of the event \ +\ +Example of usage: +```console +event CG2027 finals /at 2021-10-02 +``` +Expected outcome: \ +![startup_screen](screenshots/command_outcomes/event.png) -`keyword (optional arguments)` +### Listing all Tasks `list` +Shows a list of all tasks in the task list \ +\ +Example of usage: +```console +list +``` +Expected outcome: \ +![startup_screen](screenshots/command_outcomes/list.png) -Expected outcome: +### Marking Task as Done `done` +Marks the task at the given index as done \ +\ +Example of usage: +```console +done 1 +``` +Expected outcome: \ +![startup_screen](screenshots/command_outcomes/done.png) -Description of the outcome. +### Finding Tasks `find` +Finds all tasks in task list with titles that match the search keyword \ +\ +Example of usage: +```console +find finals +``` +Expected outcome: \ +![startup_screen](screenshots/command_outcomes/find.png) +### Deleting Tasks `delete` +Deletes the task at the given index \ +\ +Example of usage: +```console +delete 1 ``` -expected output +Expected outcome: \ +![startup_screen](screenshots/command_outcomes/delete.png) + +### Exiting Duke `bye` +Exits the program \ +\ +Example of usage: +```console +bye ``` +Expected outcome: \ +![startup_screen](screenshots/command_outcomes/exit.png) + +### Auto Save +All changes to Tasks in the task list are automatically saved to `data/duke.txt` relative to `ip.jar` whenever the tasks list is modified + +## Command Summary + +| Action | Format & Examples | +| :--- | :--- | +| **Help** | `help` | +| **Todo** | `todo `
ex: `todo Prepare for CG2027 finals` | +| **Deadline** | `deadline /by `
ex: `deadline CS2113T weekly quiz /by 2021-10-01` | +| **Event** | `event /at `
ex: `event CG2027 finals /at 2021-10-02` | +| **List** | `list` | +| **Done** | `done `
ex: `done 1` | +| **Find** | `find `
ex: `find finals` | +| **Delete** | `delete `
ex: `delete 1` | +| **Exit** | `bye` | \ No newline at end of file diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 000000000..c4192631f --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file diff --git a/docs/screenshots/command_outcomes/deadline.png b/docs/screenshots/command_outcomes/deadline.png new file mode 100644 index 000000000..ba2c6e71f Binary files /dev/null and b/docs/screenshots/command_outcomes/deadline.png differ diff --git a/docs/screenshots/command_outcomes/delete.png b/docs/screenshots/command_outcomes/delete.png new file mode 100644 index 000000000..39da08151 Binary files /dev/null and b/docs/screenshots/command_outcomes/delete.png differ diff --git a/docs/screenshots/command_outcomes/done.png b/docs/screenshots/command_outcomes/done.png new file mode 100644 index 000000000..c616bc8be Binary files /dev/null and b/docs/screenshots/command_outcomes/done.png differ diff --git a/docs/screenshots/command_outcomes/event.png b/docs/screenshots/command_outcomes/event.png new file mode 100644 index 000000000..28da15390 Binary files /dev/null and b/docs/screenshots/command_outcomes/event.png differ diff --git a/docs/screenshots/command_outcomes/exit.png b/docs/screenshots/command_outcomes/exit.png new file mode 100644 index 000000000..8815ff6ff Binary files /dev/null and b/docs/screenshots/command_outcomes/exit.png differ diff --git a/docs/screenshots/command_outcomes/find.png b/docs/screenshots/command_outcomes/find.png new file mode 100644 index 000000000..717973c7d Binary files /dev/null and b/docs/screenshots/command_outcomes/find.png differ diff --git a/docs/screenshots/command_outcomes/help.png b/docs/screenshots/command_outcomes/help.png new file mode 100644 index 000000000..82371149e Binary files /dev/null and b/docs/screenshots/command_outcomes/help.png differ diff --git a/docs/screenshots/command_outcomes/list.png b/docs/screenshots/command_outcomes/list.png new file mode 100644 index 000000000..01769ea5a Binary files /dev/null and b/docs/screenshots/command_outcomes/list.png differ diff --git a/docs/screenshots/command_outcomes/todo.png b/docs/screenshots/command_outcomes/todo.png new file mode 100644 index 000000000..1b444692f Binary files /dev/null and b/docs/screenshots/command_outcomes/todo.png differ diff --git a/docs/screenshots/startup_screen.png b/docs/screenshots/startup_screen.png new file mode 100644 index 000000000..e171a6add Binary files /dev/null and b/docs/screenshots/startup_screen.png differ 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/duke/Duke.java b/src/main/java/duke/Duke.java new file mode 100644 index 000000000..2b88c5de1 --- /dev/null +++ b/src/main/java/duke/Duke.java @@ -0,0 +1,35 @@ +package duke; + +import java.util.Scanner; + +import duke.command.Command; +import duke.command.CommandType; + +public class Duke { + + public static void main(String[] args) { + Ui.greetUserOnStart(); + executeDuke(); + Ui.greetUserOnEnd(); + } + + /** + * Retrieves data from backup (if any), then executes program until user exits with exit command + */ + private static void executeDuke() { + Storage.importData(); + + Scanner in = new Scanner(System.in); + String input = in.nextLine(); + Command command = Parser.parse(input); + while (command.getType() != CommandType.EXIT) { + try { + command.run(true); + } catch (DukeException e) { + System.out.println(e.getMessage()); + } + input = in.nextLine(); + command = Parser.parse(input); + } + } +} diff --git a/src/main/java/duke/DukeException.java b/src/main/java/duke/DukeException.java new file mode 100644 index 000000000..55378e376 --- /dev/null +++ b/src/main/java/duke/DukeException.java @@ -0,0 +1,12 @@ +package duke; + +public class DukeException extends Exception { + /** + * Class constructor for DukeException + * + * @param message Error message describing error + */ + public DukeException(String message) { + super(message); + } +} diff --git a/src/main/java/duke/Parser.java b/src/main/java/duke/Parser.java new file mode 100644 index 000000000..46438bd71 --- /dev/null +++ b/src/main/java/duke/Parser.java @@ -0,0 +1,81 @@ +package duke; + + +import duke.command.Command; +import duke.command.DoneCommand; +import duke.command.ExitCommand; +import duke.command.ListCommand; +import duke.command.TodoCommand; +import duke.command.DeadlineCommand; +import duke.command.EventCommand; +import duke.command.DeleteCommand; +import duke.command.InvalidCommand; +import duke.command.FindCommand; +import duke.command.HelpCommand; +import java.time.format.DateTimeParseException; + +public class Parser { + private static final String CMD_EXIT = "bye"; + private static final String CMD_LIST = "list"; + private static final String CMD_DONE = "done"; + private static final String CMD_TODO = "todo"; + private static final String CMD_DEADLINE = "deadline"; + private static final String CMD_EVENT = "event"; + private static final String CMD_DELETE = "delete"; + private static final String CMD_FIND = "find"; + private static final String CMD_HELP = "help"; + + /** + * @param input String input from user + * @return Command object corresponding to input command + */ + public static Command parse(String input) { + input = input.strip(); + Command command; + + if (input.equals(CMD_EXIT)) { + command = new ExitCommand(); + } else if (input.equals(CMD_HELP)) { + command = new HelpCommand(); + } else if (input.equals(CMD_LIST)) { + command = new ListCommand(); + } else if (input.startsWith(CMD_DONE)) { + String parsedInput = input.split(" ")[1]; + int taskNo = Integer.parseInt(parsedInput); + command = new DoneCommand(taskNo - 1); + } else if (input.startsWith(CMD_TODO)) { + String parsedInput = input.replaceFirst(CMD_TODO, ""); + String todo = parsedInput.strip(); + command = new TodoCommand(todo); + } else if (input.startsWith(CMD_DEADLINE)) { + String[] parsedInput = input.replaceFirst(CMD_DEADLINE, "").split("/by "); + String deadlineTitle = parsedInput[0].strip(); + String deadlineDue = parsedInput[1].strip(); + try { + command = new DeadlineCommand(deadlineTitle, deadlineDue); + } catch (DateTimeParseException e) { + command = new InvalidCommand("Deadline must be in format of yyyy-mm-dd"); + } + } else if (input.startsWith(CMD_EVENT)) { + String[] parsedInput = input.replaceFirst(CMD_EVENT, "").split("/at "); + String eventTitle = parsedInput[0].strip(); + String eventTime = parsedInput[1].strip(); + try { + command = new EventCommand(eventTitle, eventTime); + } catch (DateTimeParseException e) { + command = new InvalidCommand("Event must be in format of yyyy-mm-dd"); + } + } else if (input.startsWith(CMD_DELETE)) { + String parsedInput = input.split(" ")[1]; + int taskNo = Integer.parseInt(parsedInput); + command = new DeleteCommand(taskNo - 1); + } else if (input.startsWith(CMD_FIND)) { + String parsedInput = input.split(" ")[1]; + return new FindCommand(parsedInput); + } + else { + return new InvalidCommand("OOPS!!! I'm sorry, but I don't know what that means :-("); + } + return command; + } +} diff --git a/src/main/java/duke/Storage.java b/src/main/java/duke/Storage.java new file mode 100644 index 000000000..af95fd5a5 --- /dev/null +++ b/src/main/java/duke/Storage.java @@ -0,0 +1,152 @@ +package duke; + +import duke.command.Command; +import duke.command.DoneCommand; +import duke.command.TodoCommand; +import duke.command.DeadlineCommand; +import duke.command.EventCommand; +import duke.task.Task; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Scanner; + +public class Storage { + private static final String DATA_DIR_NAME = "data"; + private static final String DATA_FILE_NAME = "duke.txt"; + private static final String FILE_PATH = DATA_DIR_NAME + File.separator + DATA_FILE_NAME; + + private static final String TODO_CODE = "T"; + private static final String DEADLINE_CODE = "D"; + private static final String EVENT_CODE = "E"; + private static final String DONE = "X"; + private static final String DELIMITER = "#&#"; + private static final String NULL = "NULL"; + + /** + * Loads task data from FILE_PATH on startup + */ + public static void importData() { + try { + File directory = new File(DATA_DIR_NAME); + if (!directory.exists()) { + directory.mkdir(); + } + File file = new File(FILE_PATH); + if (!file.exists()) { + file.createNewFile(); + } + Scanner input = new Scanner(file); + while (input.hasNext()) { + decodeLine(input.nextLine()); + } + } catch (FileNotFoundException | DukeException e) { + System.out.println(e.getMessage()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Saves task data to DATA_FILE_NAME on exit + */ + public static void exportData() { + try { + FileWriter fileWriter = new FileWriter(FILE_PATH); + for (Task task : TaskList.getTasklist()) { + if (task == null) { + break; + } + String encodedTask = encodeLine(task); + fileWriter.write(encodedTask + System.lineSeparator()); + } + fileWriter.close(); + } catch (FileNotFoundException e) { + System.out.println("Data file missing!"); + } catch (IOException e) { + e.printStackTrace(); + } catch (DukeException e) { + System.out.println(e.getMessage()); + } + } + + /** + * Converts Task object to String to be saved in data file + * + * @param task Task to be encoded to String used in data file + * @return String of format <Time> + * @throws DukeException If an invalid task type is found + */ + private static String encodeLine(Task task) throws DukeException { + String taskType = NULL; + String status = NULL; + String title = NULL; + String time = NULL; + + switch (task.getTaskType()) { + case TODO: + taskType = TODO_CODE; + break; + case DEADLINE: + taskType = DEADLINE_CODE; + time = task.getStandardTime(); + break; + case EVENT: + taskType = EVENT_CODE; + time = task.getStandardTime(); + break; + default: + throw new DukeException("Invalid task found in tasklist"); + } + + status = task.getStatusIcon(); + title = task.getTitle(); + + return taskType + DELIMITER + status + DELIMITER + title + DELIMITER + time; + } + + /** + * Converts String in data file to Task and loads it to TaskManager + * + * @param line String of format <TaskType> <Status> <Title> <Time> to be decoded to Task used in data file + * @throws DukeException If the String is invalid and does not have any associated Task object + */ + private static void decodeLine(String line) throws DukeException { + String[] data = line.split(DELIMITER); + Command command; + + if (data.length != 4) { + throw new DukeException("Unable to load data. Some data is corrupted"); + } + + final String taskType = data[0]; + final String status = data[1]; + final String title = data[2]; + final String time = data[3]; + + switch (taskType) { + case TODO_CODE: + command = new TodoCommand(title); + break; + case DEADLINE_CODE: + command = new DeadlineCommand(title, time); + break; + case EVENT_CODE: + command = new EventCommand(title, time); + break; + default: + throw new DukeException("Unable to load data. Some data is corrupted"); + } + + command.run(false); + + // mark most recent task as done + if (status.equals(DONE)) { + int taskNo = TaskList.getTasklistSize(); + command = new DoneCommand(taskNo - 1); + command.run(false); + } + } +} diff --git a/src/main/java/duke/TaskList.java b/src/main/java/duke/TaskList.java new file mode 100644 index 000000000..7eeae532a --- /dev/null +++ b/src/main/java/duke/TaskList.java @@ -0,0 +1,144 @@ +package duke; + +import duke.task.Deadline; +import duke.task.Event; +import duke.task.Task; +import duke.task.Todo; + +import java.time.LocalDate; +import java.util.ArrayList; + +public class TaskList { + private static final ArrayList<Task> tasks = new ArrayList<>(); + + /** + * Adds Task to task list and saves addition to data file + * + * @param task Task object to be added + */ + public static void addTask(Task task) { + tasks.add(task); + Storage.exportData(); + } + + /** + * Adds a todo to task list, saves changes to data file and returns newly added todo + * + * @param todoName Name of todo to be added to task list + * @return Newly added deadline + * @throws DukeException If todo was empty + */ + public static Task addTodo(String todoName) throws DukeException { + if (todoName.isEmpty()) { + throw new DukeException("Todo cannot be empty"); + } + Todo todo = new Todo(todoName); + addTask(todo); + return todo; + } + + /** + * Adds a deadline to task list, saves changes to data file and returns newly added deadline + * + * @param deadlineName Name of deadline to be added to task list + * @param deadlineDue Due date of event to be added to task list + * @return Newly added deadline + */ + public static Task addDeadline(String deadlineName, LocalDate deadlineDue) { + Deadline deadline = new Deadline(deadlineName, deadlineDue); + addTask(deadline); + return deadline; + } + + /** + * Adds an event to task list, saves changes to data file and returns newly added event + * + * @param eventName Name of event to be added to task list + * @param eventTime Time of event to be added to task list + * @return Newly added event + */ + public static Task addEvent(String eventName, LocalDate eventTime) { + Event event = new Event(eventName, eventTime); + addTask(event); + return event; + } + + /** + * Prints list of Tasks in task list in a user-friendly format + */ + public static void listTasks() { + ArrayList<String> list = new ArrayList<>(); + for (Task task : tasks) { + list.add(task.toString()); + } + + if (list.isEmpty()) { + System.out.println("Your task list is empty!"); + } else { + System.out.println("Here are the tasks in your list:"); + Ui.printTaskList(list); + } + } + + /** + * Prints list of Tasks in task list that contain search keyword in a user-friendly format + * + * @param keyword Search keyword to check against titles of tasks + */ + public static void listMatchingTasks(String keyword) { + ArrayList<String> matches = new ArrayList<>(); + for (Task task : tasks) { + if (task.getTitle().contains(keyword)) { + matches.add(task.toString()); + } + } + if (matches.isEmpty()) { + System.out.println("No matching tasks found!"); + } else { + System.out.println("Here are the matching tasks in your list:"); + Ui.printTaskList(matches); + } + } + + /** + * Marks Task at specified index as done, changes to data file and returns Task + * + * @param taskNo Index of completed task + * @return Returns completed Task + */ + public static Task markTaskNoAsDone(int taskNo) { + Task task = tasks.get(taskNo); + task.markAsDone(); + Storage.exportData(); + return task; + } + + /** + * @return Size of task list + */ + public static int getTasklistSize() { + return tasks.size(); + } + + /** + * Returns task list containing all tasks in memory + * + * @return Task list + */ + public static ArrayList<Task> getTasklist() { + return tasks; + } + + + /** + * Deletes Task at specified index, saves changes to data file and returns Task + * + * @param taskNo Index of task in task list + * @return Task that has been deleted + */ + public static Task deleteTask(int taskNo) { + Task task = tasks.remove(taskNo); + Storage.exportData(); + return task; + } +} diff --git a/src/main/java/duke/Ui.java b/src/main/java/duke/Ui.java new file mode 100644 index 000000000..2a22d6cd2 --- /dev/null +++ b/src/main/java/duke/Ui.java @@ -0,0 +1,102 @@ +package duke; + +import duke.task.Task; + +import java.util.ArrayList; + +public class Ui { + private static final String INDENT = " "; + private static final String CURSOR = ">>> "; + + /** + * Print confirmation message to user that task has been added successfully to task list + * + * @param task Task that has been added to task list + */ + public static void printTaskAddedMessage(Task task) { + System.out.println("Got it. I've added this task:"); + System.out.println(INDENT + task); + System.out.printf("Now you have %d tasks in the list.", TaskList.getTasklistSize()); + System.out.println(); + } + + /** + * Print confirmation message to user that task has been removed successfully from task list + * + * @param task Task that has been deleted from task list + */ + public static void printTaskDeletedMessage(Task task) { + System.out.println("Noted. I've removed this task:"); + System.out.println(INDENT + task); + System.out.printf("Now you have %d tasks in the list", TaskList.getTasklistSize()); + System.out.println(); + } + + /** + * Print confirmation message to user that task has been marked as done + * + * @param task Task in task list that has been marked as done + */ + public static void printTaskDoneMessage(Task task) { + System.out.println("Nice! I've marked this task as done:"); + System.out.println(INDENT + task); + } + + /** + * Displays help message for all possible commands and their format + */ + public static void printHelpMessage() { + System.out.println("Add todo task"); + System.out.println(CURSOR + "todo <TASK_TITLE>"); + + System.out.println("Add deadline task"); + System.out.println(CURSOR + "deadline <TASK_TITLE> /by <DATE in yyyy-mm-dd format>"); + + System.out.println("Add event task"); + System.out.println(CURSOR + "event <TASK_TITLE> /at <DATE in yyyy-mm-dd format>"); + + System.out.println("List all tasks in task list"); + System.out.println(CURSOR + "list"); + + System.out.println("Mark task in task list as done"); + System.out.println(CURSOR + "done <TASK_NO>"); + + System.out.println("Delete task in task list"); + System.out.println(CURSOR + "delete <TASK_NO>"); + + System.out.println("Find tasks with matching titles"); + System.out.println(CURSOR + "find <KEYWORD>"); + + System.out.println(); + System.out.println("Refer to https://flerovious.github.io/ip/ for detailed user guide"); + } + + + /** + * Prints list of Tasks in task list in a user-friendly format + * + * @param tasks Task list to be printed + */ + public static void printTaskList(ArrayList<String> tasks) { + for (int i = 0; i < tasks.size(); ++i) { + String task = tasks.get(i); + System.out.printf("%d. %s", i + 1, task); + System.out.println(); + } + } + + /** + * Prints greeting message to user on exit + */ + public static void greetUserOnEnd() { + System.out.println("Bye. Hope to see you again soon!"); + } + + /** + * Prints greeting message to user on startup + */ + public static void greetUserOnStart() { + System.out.println("Hello! I'm Duke"); + System.out.println("What can I do for you?"); + } +} diff --git a/src/main/java/duke/command/Command.java b/src/main/java/duke/command/Command.java new file mode 100644 index 000000000..4b6b6570d --- /dev/null +++ b/src/main/java/duke/command/Command.java @@ -0,0 +1,19 @@ +package duke.command; + +import duke.DukeException; + +public interface Command { + + /** + * Interface that provides common functionality among all user input commands + * + * @param printMessage Print message to user on executing command + * @throws DukeException If exception is thrown by any of Command implementers + */ + void run(boolean printMessage) throws DukeException; + + /** + * @return Type of Command + */ + CommandType getType(); +} diff --git a/src/main/java/duke/command/CommandType.java b/src/main/java/duke/command/CommandType.java new file mode 100644 index 000000000..60d53a622 --- /dev/null +++ b/src/main/java/duke/command/CommandType.java @@ -0,0 +1,14 @@ +package duke.command; + +public enum CommandType { + EXIT, + LIST, + DONE, + TODO, + DEADLINE, + EVENT, + INVALID, + DELETE, + FIND, + HELP, +} \ No newline at end of file diff --git a/src/main/java/duke/command/DeadlineCommand.java b/src/main/java/duke/command/DeadlineCommand.java new file mode 100644 index 000000000..409cda22f --- /dev/null +++ b/src/main/java/duke/command/DeadlineCommand.java @@ -0,0 +1,44 @@ +package duke.command; + +import duke.TaskList; +import duke.task.Task; +import duke.Ui; +import java.time.LocalDate; + +public class DeadlineCommand implements Command { + private static final CommandType type = CommandType.DEADLINE; + private final String deadlineTitle; + private final LocalDate deadlineDue; + + /** + * Deadline command constructor + * + * @param deadlineTitle Title of deadline + * @param deadlineDue Due date of deadline in yyyy-mm-dd format + */ + public DeadlineCommand(String deadlineTitle, String deadlineDue) { + this.deadlineTitle = deadlineTitle; + this.deadlineDue = LocalDate.parse(deadlineDue); + } + + /** + * Adds deadline to task list and saves changes to data file + * + * @param printMessage Print message to user on executing command + */ + @Override + public void run(boolean printMessage) { + Task task = TaskList.addDeadline(deadlineTitle, deadlineDue); + if (printMessage) { + Ui.printTaskAddedMessage(task); + } + } + + /** + * @return Type of command + */ + @Override + public CommandType getType() { + return type; + } +} diff --git a/src/main/java/duke/command/DeleteCommand.java b/src/main/java/duke/command/DeleteCommand.java new file mode 100644 index 000000000..e834b04a0 --- /dev/null +++ b/src/main/java/duke/command/DeleteCommand.java @@ -0,0 +1,40 @@ +package duke.command; + +import duke.TaskList; +import duke.Ui; +import duke.task.Task; + +public class DeleteCommand implements Command { + private static final CommandType type = CommandType.DELETE; + private final int taskNo; + + /** + * Delete command constructor + * + * @param taskNo Task number of task stored in task list to be deleted + */ + public DeleteCommand(int taskNo) { + this.taskNo = taskNo; + } + + /** + * Deletes task in task list and saves changes to data file + * + * @param printMessage Print message to user on executing command + */ + @Override + public void run(boolean printMessage) { + Task task = TaskList.deleteTask(taskNo); + if (printMessage) { + Ui.printTaskDeletedMessage(task); + } + } + + /** + * @return Type of command + */ + @Override + public CommandType getType() { + return type; + } +} \ No newline at end of file diff --git a/src/main/java/duke/command/DoneCommand.java b/src/main/java/duke/command/DoneCommand.java new file mode 100644 index 000000000..719ed403d --- /dev/null +++ b/src/main/java/duke/command/DoneCommand.java @@ -0,0 +1,40 @@ +package duke.command; + +import duke.TaskList; +import duke.Ui; +import duke.task.Task; + +public class DoneCommand implements Command { + private static final CommandType type = CommandType.DONE; + private final int taskNo; + + /** + * Done command constructor + * + * @param taskNo Task number of task stored in task list to be marked as done + */ + public DoneCommand(int taskNo) { + this.taskNo = taskNo; + } + + /** + * Marks task at specified index of task list as done and saves changes to data file + * + * @param printMessage Print message to user on executing command + */ + @Override + public void run(boolean printMessage) { + Task task = TaskList.markTaskNoAsDone(taskNo); + if (printMessage) { + Ui.printTaskDoneMessage(task); + } + } + + /** + * @return Type of command + */ + @Override + public CommandType getType() { + return type; + } +} diff --git a/src/main/java/duke/command/EventCommand.java b/src/main/java/duke/command/EventCommand.java new file mode 100644 index 000000000..abf3afbf3 --- /dev/null +++ b/src/main/java/duke/command/EventCommand.java @@ -0,0 +1,45 @@ +package duke.command; + +import duke.TaskList; +import duke.Ui; +import duke.task.Task; + +import java.time.LocalDate; + +public class EventCommand implements Command { + private static final CommandType type = CommandType.EVENT; + private final String eventTitle; + private final LocalDate eventTime; + + /** + * Event command constructor + * + * @param eventTitle Title of event + * @param eventTime Time of event + */ + public EventCommand(String eventTitle, String eventTime) { + this.eventTitle = eventTitle; + this.eventTime = LocalDate.parse(eventTime); + } + + /** + * Adds event to task list and saves changes to data file + * + * @param printMessage Print message to user on executing command + */ + @Override + public void run(boolean printMessage) { + Task task = TaskList.addEvent(eventTitle, eventTime); + if (printMessage) { + Ui.printTaskAddedMessage(task); + } + } + + /** + * @return Type of command + */ + @Override + public CommandType getType() { + return type; + } +} diff --git a/src/main/java/duke/command/ExitCommand.java b/src/main/java/duke/command/ExitCommand.java new file mode 100644 index 000000000..8e2b39073 --- /dev/null +++ b/src/main/java/duke/command/ExitCommand.java @@ -0,0 +1,25 @@ +package duke.command; + +import duke.Ui; + +public class ExitCommand implements Command { + private static final CommandType type = CommandType.EXIT; + + /** + * Exit command constructor + * + * @param printMessage Print message to user on executing command + */ + @Override + public void run(boolean printMessage) { + Ui.greetUserOnEnd(); + } + + /** + * @return Type of command + */ + @Override + public CommandType getType() { + return type; + } +} diff --git a/src/main/java/duke/command/FindCommand.java b/src/main/java/duke/command/FindCommand.java new file mode 100644 index 000000000..e784c4e80 --- /dev/null +++ b/src/main/java/duke/command/FindCommand.java @@ -0,0 +1,27 @@ +package duke.command; + +import duke.TaskList; + +public class FindCommand implements Command { + private static final CommandType type = CommandType.FIND; + private final String keyword; + + /** + * Find command constructor + * + * @param keyword Search term to search through task titles + */ + public FindCommand(String keyword) { + this.keyword = keyword; + } + + @Override + public void run(boolean printMessage) { + TaskList.listMatchingTasks(keyword); + } + + @Override + public CommandType getType() { + return type; + } +} diff --git a/src/main/java/duke/command/HelpCommand.java b/src/main/java/duke/command/HelpCommand.java new file mode 100644 index 000000000..adf5d3900 --- /dev/null +++ b/src/main/java/duke/command/HelpCommand.java @@ -0,0 +1,26 @@ +package duke.command; + +import duke.DukeException; +import duke.Ui; + +public class HelpCommand implements Command { + + /** + * Displays help message for all possible commands and their format + * + * @param printMessage Print message to user on executing command. Value is irrelevant + * as values will be printed out anyways + */ + @Override + public void run(boolean printMessage) throws DukeException { + Ui.printHelpMessage(); + } + + /** + * @return Type of command + */ + @Override + public CommandType getType() { + return CommandType.HELP; + } +} \ No newline at end of file diff --git a/src/main/java/duke/command/InvalidCommand.java b/src/main/java/duke/command/InvalidCommand.java new file mode 100644 index 000000000..9fad1f6e2 --- /dev/null +++ b/src/main/java/duke/command/InvalidCommand.java @@ -0,0 +1,31 @@ +package duke.command; + +import duke.DukeException; + +public class InvalidCommand implements Command { + private static final CommandType type = CommandType.INVALID; + private final String message; + + public InvalidCommand(String message) { + this.message = message; + } + + /** + * Throws DukeException for running an invalid command + * + * @param printMessage Print message to user on executing command. Value is irrelevant + * @throws DukeException Thrown for running an invalid command + */ + @Override + public void run(boolean printMessage) throws DukeException { + throw new DukeException(message); + } + + /** + * @return Type of command + */ + @Override + public CommandType getType() { + return type; + } +} diff --git a/src/main/java/duke/command/ListCommand.java b/src/main/java/duke/command/ListCommand.java new file mode 100644 index 000000000..86cc199cf --- /dev/null +++ b/src/main/java/duke/command/ListCommand.java @@ -0,0 +1,26 @@ +package duke.command; + +import duke.TaskList; + +public class ListCommand implements Command { + private static final CommandType type = CommandType.LIST; + + /** + * Lists all Tasks in task list + * + * @param printMessage Print message to user on executing command. Value is irrelevant + * as values will be printed out anyways + */ + @Override + public void run(boolean printMessage) { + TaskList.listTasks(); + } + + /** + * @return Type of command + */ + @Override + public CommandType getType() { + return type; + } +} diff --git a/src/main/java/duke/command/TodoCommand.java b/src/main/java/duke/command/TodoCommand.java new file mode 100644 index 000000000..353e62627 --- /dev/null +++ b/src/main/java/duke/command/TodoCommand.java @@ -0,0 +1,43 @@ +package duke.command; + +import duke.DukeException; +import duke.TaskList; +import duke.Ui; +import duke.task.Task; + +public class TodoCommand implements Command { + private static final CommandType type = CommandType.TODO; + private final String todo; + + /** + * Todo command constructor + * + * @param todo Title of todo + */ + public TodoCommand(String todo) { + this.todo = todo; + } + + + /** + * Adds todo to task list and saves changes to data file + * + * @param printMessage Print message to user on executing command + * @throws DukeException If todo is empty + */ + @Override + public void run(boolean printMessage) throws DukeException { + Task task = TaskList.addTodo(todo); + if (printMessage) { + Ui.printTaskAddedMessage(task); + } + } + + /** + * @return Type of command + */ + @Override + public CommandType getType() { + return type; + } +} diff --git a/src/main/java/duke/task/Deadline.java b/src/main/java/duke/task/Deadline.java new file mode 100644 index 000000000..003d9cd9c --- /dev/null +++ b/src/main/java/duke/task/Deadline.java @@ -0,0 +1,54 @@ +package duke.task; + + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +public class Deadline extends Task { + private static final TaskType taskType = TaskType.DEADLINE; + private final LocalDate dueDate; + + /** + * Deadline constructor + * + * @param title Title of deadline + * @param dueDate Due date of deadline + */ + public Deadline(String title, LocalDate dueDate) { + super(title); + this.dueDate = dueDate; + } + + /** + * @return Type of Task + */ + @Override + public TaskType getTaskType() { + return taskType; + } + + /** + * @return String representation of Deadline for display + */ + @Override + public String toString() { + String SYMBOL = "D"; + return "[" + SYMBOL + "]" + super.toString() + " (by: " + getDisplayTime() + ")"; + } + + /** + * @return Due date of Deadline in yyyy-mm-dd format + */ + @Override + public String getStandardTime() { + return dueDate.toString(); + } + + /** + * @return Due date of Deadline in MMM dd yyyy format + */ + @Override + public String getDisplayTime() { + return dueDate.format(DateTimeFormatter.ofPattern("MMM dd yyyy")); + } +} diff --git a/src/main/java/duke/task/Event.java b/src/main/java/duke/task/Event.java new file mode 100644 index 000000000..7908b1a0a --- /dev/null +++ b/src/main/java/duke/task/Event.java @@ -0,0 +1,53 @@ +package duke.task; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +public class Event extends Task { + private static final TaskType taskType = TaskType.EVENT; + private final LocalDate timeslot; + + /** + * Event constructor + * + * @param title Title of event + * @param timeslot Time of event + */ + public Event(String title, LocalDate timeslot) { + super(title); + this.timeslot = timeslot; + } + + /** + * @return Type of Task + */ + @Override + public TaskType getTaskType() { + return taskType; + } + + /** + * @return String representation of Event for display + */ + @Override + public String toString() { + String SYMBOL = "E"; + return "[" + SYMBOL + "]" + super.toString() + " (at: " + getDisplayTime() + ")"; + } + + /** + * @return Due date of Deadline in yyyy-mm-dd format + */ + @Override + public String getStandardTime() { + return timeslot.toString(); + } + + /** + * @return Due date of Deadline in MMM dd yyyy format + */ + @Override + public String getDisplayTime() { + return timeslot.format(DateTimeFormatter.ofPattern("MMM dd yyyy")); + } +} diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java new file mode 100644 index 000000000..d2fc3a70d --- /dev/null +++ b/src/main/java/duke/task/Task.java @@ -0,0 +1,59 @@ +package duke.task; + +public abstract class Task { + private final String name; + private Boolean isDone; + + /** + * Task constructor + * + * @param title Title of task + */ + public Task(String title) { + this.name = title; + this.isDone = false; + } + + /** + * @return Title of task + */ + public String getTitle() { + return name; + } + + /** + * Returns an icon for task completion status + * + * @return Status icon of task + */ + public String getStatusIcon() { + return (isDone ? "X" : " "); + } + + /** + * Marks task as done + */ + public void markAsDone() { + isDone = true; + } + + /** + * @return Type of Task + */ + public abstract TaskType getTaskType(); + + /** + * @return Time of Task in MMM dd yyyy format + */ + public abstract String getDisplayTime(); + + @Override + public String toString() { + return "[" + getStatusIcon() + "] " + getTitle(); + } + + /** + * @return Time of Task in yyyy-mm-dd format + */ + public abstract String getStandardTime(); +} diff --git a/src/main/java/duke/task/TaskType.java b/src/main/java/duke/task/TaskType.java new file mode 100644 index 000000000..3389c7545 --- /dev/null +++ b/src/main/java/duke/task/TaskType.java @@ -0,0 +1,7 @@ +package duke.task; + +public enum TaskType { + TODO, + DEADLINE, + EVENT, +} diff --git a/src/main/java/duke/task/Todo.java b/src/main/java/duke/task/Todo.java new file mode 100644 index 000000000..e75053e23 --- /dev/null +++ b/src/main/java/duke/task/Todo.java @@ -0,0 +1,47 @@ +package duke.task; + +public class Todo extends Task { + private static final TaskType taskType = TaskType.TODO; + + /** + * Todo constructor + * + * @param title Title of todo + */ + public Todo(String title) { + super(title); + } + + /** + * @return Type of Task + */ + @Override + public TaskType getTaskType() { + return taskType; + } + + /** + * @return String representation of Todo for display + */ + @Override + public String toString() { + String SYMBOL = "T"; + return "[" + SYMBOL + "]" + super.toString(); + } + + /** + * @return Null since Todo does not have any time associated with it + */ + @Override + public String getStandardTime() { + return null; + } + + /** + * @return Null since Todo does not have any time associated with it + */ + @Override + public String getDisplayTime() { + return null; + } +}