diff --git a/.gitignore b/.gitignore index 2873e189e..cf1399567 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ bin/ /text-ui-test/ACTUAL.TXT text-ui-test/EXPECTED-UNIX.TXT + +data/ diff --git a/README.md b/README.md index 90aa7f092..7ecd21748 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ Prerequisites: JDK 17, update Intellij to the most recent version. 1. Open Intellij (if you are not in the welcome screen, click `File` > `Close Project` to close the existing project first) 1. Open the project into Intellij as follows: - 1. Click `Open`. - 1. Select the project directory, and click `OK`. - 1. If there are any further prompts, accept the defaults. + 1. Click `Open`. + 1. Select the project directory, and click `OK`. + 1. If there are any further prompts, accept the defaults. 1. Configure the project to use **JDK 17** (not other versions) as explained in [here](https://www.jetbrains.com/help/idea/sdk.html#set-up-jdk).
In the same dialog, set the **Project language level** field to the `SDK default` option. 3. After that, locate the `src/main/java/Duke.java` file, right-click it, and choose `Run Duke.main()` (if the code editor is showing compile errors, try restarting the IDE). If the setup is correct, you should see something like the below as the output: @@ -21,4 +21,4 @@ Prerequisites: JDK 17, update Intellij to the most recent version. | | | | | | | |/ / _ \ | |_| | |_| | < __/ |____/ \__,_|_|\_\___| - ``` + ``` \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 47b9f984f..f4bdee04d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,30 +1,209 @@ -# Duke User Guide +# TulipTask -// Update the title above to match the actual product name +## Overview -// Product screenshot goes here +TulipTask allows users to manage tasks, including to-dos, events, and deadlines. It provides a command-line interface where users can add, delete, mark task as done, and list tasks. The tasks are saved to a file so they persist across sessions. -// Product intro goes here +--- -## Adding deadlines +## Features -// Describe the action and its outcome. +- **Add Tasks** + - **To-Do**: A basic task without any time constraints. + - **Deadline**: A task with a specific deadline. + - **Event**: A task that has a defined start and end time. -// Give examples of usage +- **Manage Tasks** + - Mark tasks as done or not done. + - Delete tasks from the task list. -Example: `keyword (optional arguments)` +- **File Storage** + - Tasks are saved to and loaded from a file, making them persistent between sessions. -// A description of the expected outcome goes here +- **Task Searching** + - You can search for tasks based on keywords in the task description. + +--- + +## Commands + +### 1. `todo ` +Adds a To-Do task to the task list. + +- **Example**: + ``` + todo Read a book + ``` + +### 2. `deadline /by ` +Adds a Deadline task to the task list. + +- **Example**: + ``` + deadline Submit assignment /by Sunday + ``` + +### 3. `event /from /to ` +Adds an Event task to the task list. + +- **Example**: + ``` + event Project meeting /from Monday 2pm /to Monday 4pm + ``` + +### 4. `list` +Displays all tasks in the list along with their statuses. + +- **Example**: + ``` + list + ``` + +### 5. `mark ` +Marks a specific task as done based on its task number. + +- **Example**: + ``` + mark 2 + ``` + +### 6. `unmark ` +Marks a specific task as not done based on its task number. + +- **Example**: + ``` + unmark 3 + ``` + +### 7. `delete ` +Deletes a specific task based on its task number. + +- **Example**: + ``` + delete 4 + ``` + +### 8. `find ` +Finds and lists tasks that contain the specified keyword in their description. + +- **Example**: + ``` + find book + ``` + +### 9. `save` +Manually saves the current task list to the file. + +- **Example**: + ``` + save + ``` + +### 10. `load` +Loads tasks from the file if they exist. + +- **Example**: + ``` + load + ``` + +### 11. `bye` +Exits the application, automatically saving all tasks to the file. + +- **Example**: + ``` + bye + ``` + +--- + +## Task Types + +### 1. **To-Do Task** +- A basic task with no specific time or deadline. +- **Format**: `[T][status] description` + +### 2. **Deadline Task** +- A task that must be completed by a specific deadline. +- **Format**: `[D][status] description (by: deadline)` + +### 3. **Event Task** +- A task that occurs within a specific time range. +- **Format**: `[E][status] description (from: start time to: end time)` + +### Status +- `X` means the task is done. +- ` ` means the task is not done. + +--- + +## File Storage + +- Tasks are saved in a file located at `./data/data.txt`. +- Tasks are loaded automatically when the application starts, if the file exists. +- If the data directory or file does not exist, they will be created automatically. + +--- + +## Running the Application + +1. **Compile and Run**: + - Ensure all the required classes (`Task`, `ToDo`, `Deadline`, `Event`, `TaskList`, `Ui`, `Storage`, `InputParser`) are compiled. + - Run the `Ui` class which provides the main interaction loop for the application. + +2. **Interacting with the App**: + - Upon starting, you will be greeted with a welcome message, and you can enter commands as described above. + +3. **Exiting**: + - Use the `bye` command to save all tasks and exit the application. + +--- + +## Example Usage ``` -expected output -``` +Hello, I'm TulipTask +What can I do for you today? + +> todo Read a book +Okay! I have added this task: +[T][ ] Read a book +You currently have 1 task in your list. -## Feature ABC +> deadline Submit assignment /by Sunday +Okay! I have added this task: +[D][ ] Submit assignment (by: Sunday) +You currently have 2 tasks in your list. + +> event Project meeting /from Monday 2pm /to Monday 4pm +Okay! I have added this task: +[E][ ] Project meeting (from: Monday 2pm to: Monday 4pm) +You currently have 3 tasks in your list. + +> list +Here are your current tasks: +1. [T][ ] Read a book +2. [D][ ] Submit assignment (by: Sunday) +3. [E][ ] Project meeting (from: Monday 2pm to: Monday 4pm) + +> mark 1 +Great job! I have marked this task as done: +[T][X] Read a book + +> find assignment +Here are the matching tasks in your list: +[D][ ] Submit assignment (by: Sunday) + +> bye +Bye! Hope to see you again soon :) +``` -// Feature details +--- +## Future Enhancements -## Feature XYZ +- **Task Editing**: Add functionality to modify existing tasks. +- **Recurring Tasks**: Implement support for tasks that repeat on a regular schedule. +- **Priority Levels**: Allow users to assign priority levels to tasks. -// Feature details \ No newline at end of file +--- diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java new file mode 100644 index 000000000..fb71f9bd4 --- /dev/null +++ b/src/main/java/Deadline.java @@ -0,0 +1,28 @@ +/** + * The Deadline class represents a task that has a specific deadline. + * It extends the Task class by adding a due date (deadline) to the task. + */ +public class Deadline extends Task { + protected String by; + + /** + * Constructs a Deadline task with a description and a deadline date. + * + * @param description The description of the task. + * @param by The deadline for the task. + */ + public Deadline(String description, String by) { + super(description); + this.by = by; + } + + /** + * Returns a string representation of the deadline task. + * The format is [D] followed by the task description, status, and the deadline. + * + * @return A string in the format [D][status] description (by: deadline). + */ + public String toString() { + return String.format("[D]%s (by: %s)", super.toString(), this.by); + } +} 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/Event.java b/src/main/java/Event.java new file mode 100644 index 000000000..15cf89dad --- /dev/null +++ b/src/main/java/Event.java @@ -0,0 +1,31 @@ +/** + * The Event class represents a task that occurs over a specific time period. + * It extends the Task class by adding a start time and an end time. + */ +public class Event extends Task { + protected String from; + protected String to; + + /** + * Constructs an Event task with a description, start time, and end time. + * + * @param description The description of the event. + * @param from The start time of the event. + * @param to The end time of the event. + */ + public Event(String description, String from, String to) { + super(description); + this.from = from; + this.to = to; + } + + /** + * Returns a string representation of the event task. + * The format is [E] followed by the task description, status, and the event's time period. + * + * @return A string in the format [E][status] description (from: start time to: end time). + */ + public String toString() { + return String.format("[E]%s (from: %s to: %s)", super.toString(), this.from, this.to); + } +} diff --git a/src/main/java/InputParser.java b/src/main/java/InputParser.java new file mode 100644 index 000000000..6528a13a4 --- /dev/null +++ b/src/main/java/InputParser.java @@ -0,0 +1,58 @@ +import java.util.HashMap; + +/** + * The InputParser class is responsible for parsing user input into commands and arguments. + * It takes a raw input string and splits it into meaningful components such as the command and its arguments. + */ +public class InputParser { + public static final String COMMAND = "command"; + public static final String ARGUMENT = "argument"; + + /** + * Parses the user's input into a command and associated arguments. + * The first word in the input is considered the command, and the rest is treated as arguments. + * Arguments that start with "/" are treated as named arguments. + * + * @param input The raw input string from the user. + * @return A HashMap containing the parsed command and its arguments. + */ + public static HashMap parseCommands(String input) { + HashMap commandArguments = new HashMap<>(); + String[] splitInput = input.split(" "); + + // check if input is empty + if (splitInput.length == 0) { + commandArguments.put(InputParser.COMMAND, ""); + return commandArguments; + } + + // set first element as command + commandArguments.put(InputParser.COMMAND, splitInput[0]); + + String argumentDescription = InputParser.ARGUMENT; + StringBuilder argument = new StringBuilder(); + + // parse remaining input + for (int i = 1; i < splitInput.length; i++) { + String arg = splitInput[i]; + + if (arg.startsWith("/")) { + if (!argumentDescription.isEmpty()) { + commandArguments.put(argumentDescription, argument.toString().strip()); + } + + argumentDescription = arg; + argument.setLength(0); + } else { + argument.append(" ").append(arg); + } + } + + // add last argument + if (!argument.isEmpty()) { + commandArguments.put(argumentDescription, argument.toString().strip()); + } + + return commandArguments; + } +} diff --git a/src/main/java/Storage.java b/src/main/java/Storage.java new file mode 100644 index 000000000..492a9fdbc --- /dev/null +++ b/src/main/java/Storage.java @@ -0,0 +1,73 @@ +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +/** + * The Storage class handles saving and loading tasks from a file. + * It provides methods to save tasks to a text file and load tasks from it. + */ +public class Storage { + static Path directoryPath = Path.of("./data"); + static Path filePath = directoryPath.resolve("data.txt"); + + /** + * Saves the provided list of tasks to a file. + * If the directory or file does not exist, they are created. + * + * @param taskList The list of tasks to be saved. + */ + public static void saveTasks(ArrayList taskList) { + try { + if (!Files.exists(directoryPath)) { + Files.createDirectories(directoryPath); + System.out.println("Directory created: " + directoryPath); + } + + if (!Files.exists(filePath)) { + Files.createFile(filePath); + System.out.println("File created: " + filePath); + } + + try (var writer = new FileWriter(filePath.toFile())) { + for (var item : taskList) { + writer.write(item + System.lineSeparator()); + } + System.out.println("Task list data saved to file: " + filePath); + } + + } catch (IOException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + + /** + * Loads the tasks from the file into a list of strings. + * + * @return A list of strings representing the tasks. Returns null if an error occurs or the file does not exist. + */ + public static List loadTasks() { + List taskList; + + if (!Files.exists(directoryPath)) { + System.out.println("Data directory does not exist"); + } + + try { + if (Files.exists(filePath)) { + taskList = Files.readAllLines(filePath); + return taskList; + } else { + System.out.println("Data file does not exist: " + filePath); + } + } catch (IOException e) { + System.out.println("An error occurred while reading the file: " + e.getMessage()); + } + return null; + } +} + + + diff --git a/src/main/java/Task.java b/src/main/java/Task.java new file mode 100644 index 000000000..6eed34ea3 --- /dev/null +++ b/src/main/java/Task.java @@ -0,0 +1,61 @@ +/** + * The Task class represents a general task with a description and a completion status. + * It serves as the base class for different types of tasks such as ToDo, Deadline, and Event. + */ +public class Task { + protected String description; + protected boolean isDone; + + /** + * Constructs a new Task with the specified description. + * The task is initially marked as not done. + * + * @param description The description of the task. + */ + public Task(String description) { + this.description = description; + this.isDone = false; + } + + /** + * Returns the status icon of the task. "X" if the task is done, otherwise a space (" "). + * + * @return A string representing the status icon of the task. + */ + public String getStatusIcon() { + return (isDone ? "X" : " "); // mark done task with X + } + + /** + * Marks the task as done by setting its status to true. + */ + public void markAsDone() { + this.isDone = true; + } + + /** + * Marks the task as not done by setting its status to false. + */ + public void markAsNotDone() { + this.isDone = false; + } + + /** + * Returns the description of the task. + * + * @return The description of the task. + */ + public String getDescription() { + return description; + } + + /** + * Returns a string representation of the task. + * The format is [statusIcon] followed by the task description. + * + * @return A string representing the task, including its status and description. + */ + public String toString() { + return String.format("[%s] %s", this.getStatusIcon(), this.getDescription()); + } +} diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java new file mode 100644 index 000000000..72cddd4db --- /dev/null +++ b/src/main/java/TaskList.java @@ -0,0 +1,279 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; + +/** + * The TaskList class manages a list of tasks. It allows tasks to be added, deleted, marked as done or not done, + * and supports operations like loading tasks from a file or saving them to a file. + */ +public class TaskList { + public ArrayList taskList; + protected int taskIndex; + public static final int INVALID_INDEX = -1; + + public TaskList() { + this.taskList = new ArrayList<>(); + } + + /** + * Adds a new task to the task list. + * + * @param task The task to be added. + */ + public void addTask(Task task) { + System.out.println("--------------------------------------------"); + this.taskList.add(task); + System.out.println("Okay! I have added this task: "); + System.out.println(task.toString()); + System.out.printf("You currently have %d tasks in your list \n", taskList.size()); + System.out.println("--------------------------------------------"); + } + + /** + * Deletes a task from the task list. + * + * @param commandArguments A HashMap containing the command arguments, including the task index. + */ + public void deleteTask(HashMap commandArguments) { + String argument = commandArguments.get("argument"); + getTaskIndex(argument); + Task task = taskList.get(this.taskIndex); + System.out.println("--------------------------------------------"); + this.taskList.remove(task); + System.out.println("Okay! I have removed this task: "); + System.out.println(task.toString()); + System.out.printf("You currently have %d tasks in your list \n", taskList.size()); + System.out.println("--------------------------------------------"); + } + + /** + * Lists all tasks in the task list. + */ + public void listTasks() { + System.out.println("--------------------------------------------"); + System.out.println("Here are your current tasks: "); + for (int i = 0; i < taskList.size(); i++) { + System.out.println(i + 1 + "." + this.taskList.get(i)); + } + System.out.println("--------------------------------------------"); + } + + /** + * Adds a new ToDo task to the task list. + * + * @param commandArguments A HashMap containing the command arguments, including the task description. + * @throws TulipTaskException.InvalidTaskDescriptionException if the task description is invalid. + */ + public void addToDo(HashMap commandArguments) throws TulipTaskException.InvalidTaskDescriptionException { + String argument = commandArguments.get("argument"); + if (argument == null) { + throw new TulipTaskException.InvalidTaskDescriptionException(); + } + + ToDo task = new ToDo(commandArguments.get("argument")); + addTask(task); + } + + /** + * Adds a new Deadline task to the task list. + * + * @param commandArguments A HashMap containing the command arguments, including the task description and deadline. + * @throws TulipTaskException.InvalidDeadlineException if the deadline is invalid. + * @throws TulipTaskException.InvalidTaskDescriptionException if the task description is invalid. + */ + public void addDeadline(HashMap commandArguments) throws TulipTaskException.InvalidDeadlineException, TulipTaskException.InvalidTaskDescriptionException { + String argument = commandArguments.get("argument"); + String by = commandArguments.get("/by"); + + if (argument == null) { + throw new TulipTaskException.InvalidTaskDescriptionException(); + } + + if (by == null) { + throw new TulipTaskException.InvalidDeadlineException(); + } + + Deadline task = new Deadline(argument, by); + addTask(task); + } + + /** + * Adds a new Event task to the task list. + * + * @param commandArguments A HashMap containing the command arguments, including the task description, start time, and end time. + * @throws TulipTaskException.InvalidTaskDescriptionException if the task description is invalid. + * @throws TulipTaskException.InvalidStartDateException if the start date is invalid. + * @throws TulipTaskException.InvalidEndDateException if the end date is invalid. + */ + public void addEvent(HashMap commandArguments) throws TulipTaskException.InvalidTaskDescriptionException, TulipTaskException.InvalidStartDateException, TulipTaskException.InvalidEndDateException { + String argument = commandArguments.get("argument"); + String from = commandArguments.get("/from"); + String to = commandArguments.get("/to"); + + if (argument == null) { + throw new TulipTaskException.InvalidTaskDescriptionException(); + } + + if (from == null) { + throw new TulipTaskException.InvalidStartDateException(); + } + + if (to == null) { + throw new TulipTaskException.InvalidEndDateException(); + } + + Event task = new Event(argument, from, to); + addTask(task); + } + + /** + * Gets the index of a task based on the provided index string. + * + * @param indexString The string representing the task index. + */ + public void getTaskIndex(String indexString) { + int index = Integer.parseInt(indexString) - 1; + + if (index < 0 || index > taskList.size() - 1) { + this.taskIndex = INVALID_INDEX; + return; + } + + this.taskIndex = index; + } + + /** + * Marks a task as done. + * + * @param commandArguments A HashMap containing the command arguments, including the task index. + * @throws TulipTaskException.InvalidTaskIndexException if the task index is invalid. + */ + public void markTaskAsDone(HashMap commandArguments) throws TulipTaskException.InvalidTaskIndexException { + String argument = commandArguments.get("argument"); + getTaskIndex(argument); + + if (this.taskIndex == INVALID_INDEX) { + throw new TulipTaskException.InvalidTaskIndexException(); + } + + Task task = taskList.get(this.taskIndex); + task.markAsDone(); + System.out.println("--------------------------------------------"); + System.out.println("Great job! I have marked this task as done: "); + System.out.println(task); + System.out.println("--------------------------------------------"); + } + + /** + * Marks a task as not done. + * + * @param commandArguments A HashMap containing the command arguments, including the task index. + * @throws TulipTaskException.InvalidTaskIndexException if the task index is invalid. + */ + public void markTaskAsNotDone(HashMap commandArguments) throws TulipTaskException.InvalidTaskIndexException { + String argument = commandArguments.get("argument"); + getTaskIndex(argument); + + if (this.taskIndex == INVALID_INDEX) { + throw new TulipTaskException.InvalidTaskIndexException(); + } + + Task task = taskList.get(this.taskIndex); + task.markAsNotDone(); + System.out.println("--------------------------------------------"); + System.out.println("Okay, I have marked this task as not done: "); + System.out.println(task); + System.out.println("--------------------------------------------"); + } + + /** + * Saves the tasks to a file. + */ + public void saveTaskToFile() { + System.out.println("--------------------------------------------"); + Storage.saveTasks(this.taskList); + System.out.println("--------------------------------------------"); + } + + /** + * Loads tasks from a file. + */ + public void loadTaskFromFile() { + List list = Storage.loadTasks(); + for (int i = 0; i < Objects.requireNonNull(list).size(); i++) { + parseTask(list.get(i)); + } + System.out.println("--------------------------------------------"); + System.out.println("Tasks have been successfully loaded!"); + System.out.println("--------------------------------------------"); + } + + /** + * Parses a task from a string. + * + * @param line The string containing the task information. + */ + public void parseTask(String line) { + String type = line.substring(1, 2); + boolean completed = line.charAt(4) == 'X'; + + switch (type) { + case "T" -> { + String description = line.substring(7); + ToDo task = new ToDo(description); + this.taskList.add(task); + if (completed) { + task.markAsDone(); + } + + } + case "D" -> { + int deadlineIndex = line.indexOf("(by:"); + String description = line.substring(7, deadlineIndex).trim(); + String deadline = line.substring(deadlineIndex + 5, line.length() - 1); + Deadline task = new Deadline(description, deadline); + this.taskList.add(task); + if (completed) { + task.markAsDone(); + } + + } + case "E" -> { + int eventIndex = line.indexOf("(from:"); + String description = line.substring(7, eventIndex).trim(); + String timeInfo = line.substring(eventIndex + 6, line.length() - 1); // Extract time info + + String[] timeParts = timeInfo.split(" to: "); + String eventStart = timeParts[0].trim(); + String eventEnd = timeParts[1].trim(); + Event task = new Event(description, eventStart, eventEnd); + this.taskList.add(task); + if (completed) { + task.markAsDone(); + } + } + } + } + + /** + * Finds tasks that match a given argument. + * + * @param commandArguments A HashMap containing the command arguments, including the search keyword. + */ + public void findTask(HashMap commandArguments) { + String argument = commandArguments.get("argument"); + + System.out.println("--------------------------------------------"); + System.out.println("Here are the matching tasks in your list: "); + + for (Task task : taskList) { + if (task.description.contains(argument)) { + System.out.println(task); + } + } + + System.out.println("--------------------------------------------"); + + } +} diff --git a/src/main/java/ToDo.java b/src/main/java/ToDo.java new file mode 100644 index 000000000..2086df9a6 --- /dev/null +++ b/src/main/java/ToDo.java @@ -0,0 +1,24 @@ +/** + * The ToDo class represents a task without any specific time constraints. + * It extends the Task class and provides a simple to-do task. + */ +public class ToDo extends Task { + /** + * Constructs a ToDo task with a given description. + * + * @param description The description of the to-do task. + */ + public ToDo(String description) { + super(description); + } + + /** + * Returns a string representation of the to-do task. + * The format is [T] followed by the task's status and description. + * + * @return A string in the format [T][status] description. + */ + public String toString() { + return String.format("[T]%s", super.toString()); + } +} diff --git a/src/main/java/TulipTask.java b/src/main/java/TulipTask.java new file mode 100644 index 000000000..b4a971347 --- /dev/null +++ b/src/main/java/TulipTask.java @@ -0,0 +1,12 @@ +public class TulipTask { + + /** + * Runs the TulipTask program + * @param args - Unused + */ + public static void main(String[] args) { + Ui ui = new Ui(); + ui.run(); + } +} + diff --git a/src/main/java/TulipTaskException.java b/src/main/java/TulipTaskException.java new file mode 100644 index 000000000..ac124010f --- /dev/null +++ b/src/main/java/TulipTaskException.java @@ -0,0 +1,11 @@ +public class TulipTaskException { + public static class InvalidDeadlineException extends Exception {} + + public static class InvalidStartDateException extends Exception {} + + public static class InvalidEndDateException extends Exception {} + + public static class InvalidTaskDescriptionException extends Exception {} + + public static class InvalidTaskIndexException extends Exception {} +} diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java new file mode 100644 index 000000000..2b20b2280 --- /dev/null +++ b/src/main/java/Ui.java @@ -0,0 +1,184 @@ +import java.util.HashMap; +import java.util.Scanner; + +/** + * The Ui class handles user interactions by accepting input commands and managing the task list. + * It provides methods for loading, saving, and modifying tasks, and facilitates communication between + * the user and the task list. + */ +public class Ui { + public TaskList taskList; + + public Ui() { + taskList = new TaskList(); + + try { + taskList.loadTaskFromFile(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } + + /** + * Matches the user's command with the corresponding task list operation. + * + * @param command The user's command as a string. + * @param commandArguments A HashMap containing command arguments for specific tasks. + * @return true if the program should continue accepting input, false if the user entered "bye". + */ + public boolean matchCommand(String command, HashMap commandArguments) { + final String goodByeMessage = "--------------------------------------------\n" + + "Bye! Hope to see you again soon :)\n" + + "--------------------------------------------"; + + final String unrecognizedCommand = "--------------------------------------------\n" + + "Unrecognized command!\n" + + "--------------------------------------------\n"; + + switch (command) { + case "list": + taskList.listTasks(); + break; + + case "mark": + try { + taskList.markTaskAsDone(commandArguments); + } catch (TulipTaskException.InvalidTaskIndexException e) { + System.out.println("--------------------------------------------"); + System.out.printf("Invalid task index! Please input a number between 1 and %d \n", taskList.taskList.size()); + System.out.println("--------------------------------------------"); + } + break; + + case "unmark": + try { + taskList.markTaskAsNotDone(commandArguments); + } catch (TulipTaskException.InvalidTaskIndexException e) { + System.out.println("--------------------------------------------"); + System.out.printf("Invalid task index! Please input a number between 1 and %d \n", taskList.taskList.size()); + System.out.println("--------------------------------------------"); + } + break; + + case "todo": + try { + taskList.addToDo(commandArguments); + } catch (TulipTaskException.InvalidTaskDescriptionException e) { + System.out.println("--------------------------------------------"); + System.out.println("Task description was not given :("); + System.out.println("--------------------------------------------"); + } + break; + + case "deadline": + try { + taskList.addDeadline(commandArguments); + } catch (TulipTaskException.InvalidTaskDescriptionException e) { + System.out.println("--------------------------------------------"); + System.out.println("Task description was not given :("); + System.out.println("--------------------------------------------"); + } catch (TulipTaskException.InvalidDeadlineException e) { + System.out.println("--------------------------------------------"); + System.out.println("Task deadline was not given, add a deadline by using /by to indicate task end date!"); + System.out.println("--------------------------------------------"); + } + break; + + case "event": + try { + taskList.addEvent(commandArguments); + } catch (TulipTaskException.InvalidTaskDescriptionException e) { + System.out.println("--------------------------------------------"); + System.out.println("Task description was not given :("); + System.out.println("--------------------------------------------"); + } catch (TulipTaskException.InvalidStartDateException e) { + System.out.println("--------------------------------------------"); + System.out.println("Event start date was not given, add a start date by using /from to indicate task start date!"); + System.out.println("--------------------------------------------"); + } catch (TulipTaskException.InvalidEndDateException e) { + System.out.println("--------------------------------------------"); + System.out.println("Event end date was not given, add a end date by using /to to indicate task end date!"); + System.out.println("--------------------------------------------"); + } + break; + + case "delete": + taskList.deleteTask(commandArguments); + break; + + case "save": + taskList.saveTaskToFile(); + break; + + case "load": + taskList.loadTaskFromFile(); + break; + + case "find": + taskList.findTask(commandArguments); + break; + + case "bye": + taskList.saveTaskToFile(); + System.out.println(goodByeMessage); + return false; + + default: + System.out.println(unrecognizedCommand); + break; + } + return true; + } + + /** + * Accepts and processes commands entered by the user in an interactive loop. + * The loop continues until the user enters the "bye" command. + */ + public void commandEntry() { + HashMap commandArguments; + String input; + Scanner scanner = new Scanner(System.in); + + boolean isAcceptingInput = true; + + while (isAcceptingInput) { + input = scanner.nextLine(); + commandArguments = InputParser.parseCommands(input); + String command = commandArguments.get(InputParser.COMMAND); + + try { + isAcceptingInput = matchCommand(command, commandArguments); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } + } + + /** + * Displays a welcome message to the user when the program starts. + */ + public void displayWelcome() { + String logo = " \n" + + "--.-- | o --.-- | \n" + + " | . .| .,---. | ,---.,---.|__/ \n" + + " | | || || | | ,---|`---.| \\ \n" + + " ` `---'`---'`|---' ` `---^`---'` `\n" + + " |"; + + final String welcomeMessage = "--------------------------------------------\n" + + "Hello, I'm TulipTask\n" + + "What can I do for you today?\n" + + "--------------------------------------------"; + + System.out.println(logo); + System.out.println(welcomeMessage); + } + + /** + * Starts the user interface by displaying the welcome message and then accepting commands from the user. + */ + public void run() { + displayWelcome(); + commandEntry(); + } +} diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 657e74f6e..9ae68aa1f 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,7 +1,63 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| - + +--.-- | o --.-- | + | . .| .,---. | ,---.,---.|__/ + | | || || | | ,---|`---.| \ + ` `---'`---'`|---' ` `---^`---'` ` + | +-------------------------------------------- +Hello, I'm TulipTask +What can I do for you today? +-------------------------------------------- +-------------------------------------------- +Okay! I have added this task: +[T][ ] borrow book +You currently have 1 tasks in your list +-------------------------------------------- +-------------------------------------------- +Here are your current tasks: +1.[T][ ] borrow book +-------------------------------------------- +-------------------------------------------- +Okay! I have added this task: +[D][ ] return book (by: Friday) +You currently have 2 tasks in your list +-------------------------------------------- +-------------------------------------------- +Okay! I have added this task: +[E][ ] project meeting (from: Mon 2pm to: 4pm) +You currently have 3 tasks in your list +-------------------------------------------- +Invalid command +-------------------------------------------- +Here are your current tasks: +1.[T][ ] borrow book +2.[D][ ] return book (by: Friday) +3.[E][ ] project meeting (from: Mon 2pm to: 4pm) +-------------------------------------------- +-------------------------------------------- +Great job! I have marked this task as done: +[T][X] borrow book +-------------------------------------------- +-------------------------------------------- +Here are your current tasks: +1.[T][X] borrow book +2.[D][ ] return book (by: Friday) +3.[E][ ] project meeting (from: Mon 2pm to: 4pm) +-------------------------------------------- +-------------------------------------------- +Great job! I have marked this task as done: +[D][X] return book (by: Friday) +-------------------------------------------- +-------------------------------------------- +Okay, I have marked this task as not done: +[T][ ] borrow book +-------------------------------------------- +-------------------------------------------- +Here are your current tasks: +1.[T][ ] borrow book +2.[D][X] return book (by: Friday) +3.[E][ ] project meeting (from: Mon 2pm to: 4pm) +-------------------------------------------- +-------------------------------------------- +Bye! Hope to see you again soon :) +-------------------------------------------- diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e69de29bb..62d76c6d1 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -0,0 +1,12 @@ +todo borrow book +list +deadline return book /by Friday +event project meeting /from Mon 2pm /to 4pm +test +list +mark 1 +list +mark 2 +unmark 1 +list +bye \ No newline at end of file diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index 087374464..58d636d61 100644 --- a/text-ui-test/runtest.bat +++ b/text-ui-test/runtest.bat @@ -15,7 +15,7 @@ IF ERRORLEVEL 1 ( REM no error here, errorlevel == 0 REM run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT -java -classpath ..\bin Duke < input.txt > ACTUAL.TXT +java -classpath ..\bin TulipTask < input.txt > ACTUAL.TXT REM compare the output to the expected output FC ACTUAL.TXT EXPECTED.TXT diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh index c9ec87003..5739aa622 100644 --- a/text-ui-test/runtest.sh +++ b/text-ui-test/runtest.sh @@ -20,7 +20,7 @@ then fi # run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT -java -classpath ../bin Duke < input.txt > ACTUAL.TXT +java -classpath ../bin TulipTask < input.txt > ACTUAL.TXT # convert to UNIX format cp EXPECTED.TXT EXPECTED-UNIX.TXT