diff --git a/README.md b/README.md
index 8715d4d91..cc6375c6b 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,114 @@
-# Duke project template
-
-This is a project template for a greenfield Java project. It's named after the Java mascot _Duke_. Given below are instructions on how to use it.
-
-## Setting up in Intellij
-
-Prerequisites: JDK 11, 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. Configure the project to use **JDK 11** (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:
- ```
- Hello from
- ____ _
- | _ \ _ _| | _____
- | | | | | | | |/ / _ \
- | |_| | |_| | < __/
- |____/ \__,_|_|\_\___|
- ```
+
+# User Guide for Ken
+
+```
+K K EEEEE N N
+K K E NN N
+KKK EEEE N N N
+K K E N NN
+K K EEEEE N N
+```
+## Features
+Ken is a CLI chatbot that helps you manage your tasks efficiently. Easily add and delete tasks, deadline and events, save them, and use Ken to manage them easily.
+
+## Usage
+
+### `todo, deadline, event` - Add a Task
+
+To add a task, use one of the following commands:
+
+- `todo [task description]`: Adds a todo task.
+- `deadline [task description] /by [deadline]`: Adds a deadline task, with when it is due by.
+- `event [task description] /from [start date] /to [end date]`: Adds an event task, with the duration of the event.
+
+#### Example of usage :
+
+`todo activity`
+
+`deadline project /by Friday`
+
+`event lunch /from 2pm /to 4pm`
+
+
+#### Expected outcome:
+
+```
+Got it. I've added this task:
+ [T][ ] activity
+Now you have 1 tasks in the list.
+```
+```
+Got it. I've added this task:
+[D][ ] project by: Friday
+Now you have 4 tasks in the list.
+```
+```
+Got it. I've added this task:
+[E][ ] lunch from: 2pm to: 4pm
+Now you have 5 tasks in the list.
+```
+
+
+### `list` - Viewing all tasks
+
+To view a list of all your tasks and their corresponding information, use this command
+
+`list`
+
+#### Expected outcome:
+
+
+```
+Here are the tasks in your list:
+ 1.[T][ ] studying for test
+ 2.[D][ ] project by: Friday
+ 3.[E][ ] lunch from: 2pm to: 4pm
+```
+
+
+### `delete` - Removing tasks
+
+To delete a task, use the delete command followed by the task number:
+
+`delete 2`
+
+#### Expected outcome:
+
+
+```
+Got it. I've removed this task:
+ [D][ ] project by: Friday
+Now you have 2 tasks in the list.
+```
+### `find` - Searching for tasks by keywords
+
+To find a particular task and their corresponding information from the list by using any part of description, use this command
+
+`find lunch`
+
+#### Expected outcome:
+
+
+```
+Here are the matching tasks in your list:
+2. [E][ ] lunch ( from: 2pm to: 4pm )
+```
+
+
+### `mark` - Searching for tasks by keywords
+
+To mark a task as done, use the mark command followed by the task number:
+
+#### Example of usage :
+
+`mark 2`
+
+#### Expected outcome:
+
+```
+Nice! I've marked this task as done:
+ [X] lunch from: 2pm to: 4pm
+```
+
+
+
diff --git a/data/ken.txt b/data/ken.txt
new file mode 100644
index 000000000..4d6d5c8ef
--- /dev/null
+++ b/data/ken.txt
@@ -0,0 +1 @@
+T | 0 | it works!!!!!!
diff --git a/docs/README.md b/docs/README.md
index 8077118eb..12a567bd2 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,29 +1,139 @@
-# User Guide
+# User Guide for Ken
+```
+K K EEEEE N N
+K K E NN N
+KKK EEEE N N N
+K K E N NN
+K K EEEEE N N
+```
## Features
+Ken is a CLI chatbot that helps you manage your tasks efficiently. Easily add and delete tasks, deadline and events, save them, and use Ken to manage them easily.
-### Feature-ABC
+- Add tasks of different types: Todo, Deadline, Event
+- List all your tasks
+- Mark tasks as done
+- Unmark tasks
+- Delete tasks
+- Find tasks
-Description of the feature.
+## Usage
-### Feature-XYZ
+### `todo, deadline, event` - Add a Task
-Description of the feature.
+To add a task, use one of the following commands:
-## Usage
+- `todo [task description]`: Adds a todo task.
+- `deadline [task description] /by [deadline]`: Adds a deadline task, with when it is due by.
+- `event [task description] /from [start date] /to [end date]`: Adds an event task, with the duration of the event.
+
+#### Example of usage :
+
+`todo activity`
+
+`deadline project /by Friday`
+
+`event lunch /from 2pm /to 4pm`
+
+
+#### Expected outcome:
+
+```
+Got it. I've added this task:
+ [T][ ] activity
+Now you have 1 tasks in the list.
+```
+```
+Got it. I've added this task:
+[D][ ] project by: Friday
+Now you have 4 tasks in the list.
+```
+```
+Got it. I've added this task:
+[E][ ] lunch from: 2pm to: 4pm
+Now you have 5 tasks in the list.
+```
-### `Keyword` - Describe action
-Describe the action and its outcome.
+### `list` - Viewing all tasks
-Example of usage:
+To view a list of all your tasks and their corresponding information, use this command
+
+`list`
-`keyword (optional arguments)`
+#### Expected outcome:
-Expected outcome:
-Description of the outcome.
+```
+Here are the tasks in your list:
+ 1.[T][ ] studying for test
+ 2.[D][ ] project by: Friday
+ 3.[E][ ] lunch from: 2pm to: 4pm
+```
+
+
+### `delete` - Removing tasks
+
+To delete a task, use the delete command followed by the task number:
+
+`delete 2`
+
+#### Expected outcome:
+
```
-expected output
+Got it. I've removed this task:
+ [D][ ] project by: Friday
+Now you have 2 tasks in the list.
```
+### `find` - Searching for tasks by keywords
+
+To find a particular task and their corresponding information from the list by using any part of description, use this command
+
+`find lunch`
+
+#### Expected outcome:
+
+
+```
+Here are the matching tasks in your list:
+2. [E][ ] lunch ( from: 2pm to: 4pm )
+```
+
+
+### `mark` - Marking tasks as completed
+
+To mark a task as done, use the mark command followed by the task number:
+
+#### Example of usage :
+
+`mark 2`
+
+#### Expected outcome:
+
+```
+Nice! I've marked this task as done:
+ [X] lunch from: 2pm to: 4pm
+```
+
+
+### `unmark` - Unmarking tasks as uncompleted
+
+To unmark a previously marked task, use the unmark command followed by the task number:
+
+#### Example of usage :
+
+`unmark 2`
+
+#### Expected outcome:
+
+```
+Nice! I've unmarked this task as done:
+ [ ] lunch from: 2pm to: 4pm
+```
+
+
+### `bye` - Terminating Ken
+
+When you've finished organizing your tasks, simply enter
+`bye`
diff --git a/ken.txt b/ken.txt
new file mode 100644
index 000000000..798985379
--- /dev/null
+++ b/ken.txt
@@ -0,0 +1,2 @@
+D | 1 | ip | by: friday
+T | 0 | studying for test | null
diff --git a/pullreq1.txt b/pullreq1.txt
new file mode 100644
index 000000000..18d1d885f
--- /dev/null
+++ b/pullreq1.txt
@@ -0,0 +1 @@
+Pull request 1
diff --git a/src/main/java/AddCommand.java b/src/main/java/AddCommand.java
new file mode 100644
index 000000000..9a0be0daa
--- /dev/null
+++ b/src/main/java/AddCommand.java
@@ -0,0 +1,86 @@
+public class AddCommand {
+ /**
+ * Handles the addition of a task to the task list.
+ *
+ * @param taskType The type of the task (e.g., "T" for Todo).
+ * @param taskDescription The description of the task.
+ * @param taskList The TaskList to which the task will be added.
+ * @throws EmptyDescriptionException If the task description is empty.
+ * @throws MissingInfoException If required information is missing for a task type.
+ */
+ public static void AddTask(String taskType, String taskDescription, TaskList taskList) throws EmptyDescriptionException, MissingInfoException {
+ if (taskDescription.isEmpty()) {
+ throw new EmptyDescriptionException("Hey!! Description cannot be empty for a " + taskType + " task.");
+ }
+ taskType = taskType.substring(0, 1).toUpperCase();
+ String[] dateInfo = CommandParser.extractDateInfo(taskDescription);
+ if (isMissingInfo(taskType, dateInfo)) {
+ throw new MissingInfoException(taskType);
+ }
+ taskDescription = dateInfo[0];
+ addTaskToList(taskType, taskDescription, dateInfo[1], taskList);
+ displayTaskAddedMessage(taskType, taskDescription, dateInfo[1], taskList);
+ }
+
+ /**
+ * Checks if required information is missing for a task type.
+ *
+ * @param taskType The type of the task.
+ * @param dateInfo An array containing task description and date information.
+ * @return True if required information is missing, otherwise false.
+ */
+ private static boolean isMissingInfo(String taskType, String[] dateInfo) {
+ if (taskType.equals("D") && dateInfo[1] == null) {
+ return true;
+ } else return taskType.equals("E") && (dateInfo[1] == null || dateInfo[1].isEmpty());
+ }
+
+ /**
+ * Adds a task to the task list.
+ *
+ * @param taskType The type of the task.
+ * @param taskDescription The description of the task.
+ * @param dateInfo The date information for the task.
+ * @param taskList The TaskList to which the task will be added.
+ */
+ private static void addTaskToList(String taskType, String taskDescription, String dateInfo, TaskList taskList) {
+ taskList.getTaskTypes().add(taskType);
+ taskList.getTaskDates().add(dateInfo);
+ taskList.getTaskDescriptions().add(taskDescription.trim());
+ taskList.getTaskDoneStatus().add(false);
+ }
+
+ /**
+ * Displays a message confirming the addition of a task.
+ *
+ * @param taskType The type of the task.
+ * @param taskDescription The description of the task.
+ * @param dateInfo The date information for the task.
+ * @param taskList The TaskList to which the task was added.
+ */
+ private static void displayTaskAddedMessage(String taskType, String taskDescription, String dateInfo, TaskList taskList) {
+ System.out.println(" Got it. I've added this task:");
+ String dateInfoText = dateInfo != null ? " " + dateInfo : "";
+ System.out.println(" [" + taskType + "][ ] " + taskDescription + dateInfoText);
+ System.out.println(" Now you have " + taskList.getTaskDescriptions().size() + " tasks in the list.");
+ }
+
+ /**
+ * Handles adding a task and saves tasks after adding it.
+ *
+ * @param taskType The type of the task (e.g., "T" for Todo).
+ * @param taskDescription The description of the task.
+ * @param taskList The TaskList to which the task will be added.
+ * @throws KenException If there's an issue with the task or task list handling.
+ */
+ public static void handleAddTask(String taskType, String taskDescription, TaskList taskList) throws KenException {
+ AddTask(taskType, taskDescription, taskList);
+ Storage.saveTasks(taskList); // Save tasks after deleting
+ }
+
+ public static class MissingInfoException extends KenException {
+ public MissingInfoException(String taskType) {
+ super("Hey!! Don't leave the description or date empty for a " + taskType + " task.");
+ }
+ }
+}
diff --git a/src/main/java/CommandParser.java b/src/main/java/CommandParser.java
new file mode 100644
index 000000000..aeb7069d4
--- /dev/null
+++ b/src/main/java/CommandParser.java
@@ -0,0 +1,150 @@
+/**
+ * This class is responsible for parsing and processing user commands for the Ken chatbot.
+ * It defines constants for various supported commands and provides methods to handle
+ * user input and extract task information from it.
+ */
+public class CommandParser {
+
+ /**
+ * Command keyword for terminating the chatbot.
+ */
+ public static final String COMMAND_BYE = "bye";
+
+ /**
+ * Command keyword for listing tasks.
+ */
+ public static final String COMMAND_LIST = "list";
+
+ /**
+ * Command keyword for adding a to-do task.
+ */
+ public static final String COMMAND_TODO = "todo";
+
+ /**
+ * Command keyword for adding a deadline task.
+ */
+ public static final String COMMAND_DEADLINE = "deadline";
+
+ /**
+ * Command keyword for adding an event task.
+ */
+ public static final String COMMAND_EVENT = "event";
+
+ /**
+ * Command keyword for deleting a task.
+ */
+ public static final String COMMAND_DELETE = "delete";
+
+ /**
+ * Command keyword for marking a task as done.
+ */
+ public static final String COMMAND_MARK = "mark";
+
+ /**
+ * Command keyword for marking a task as done.
+ */
+ public static final String COMMAND_UNMARK = "unmark";
+
+ /**
+ * Command keyword for finding tasks by keyword.
+ */
+ public static final String COMMAND_FIND = "find";
+
+
+ /**
+ * Processes the user's command, extracts task type and description, and performs
+ * the corresponding action (e.g., adding, deleting, marking) on the task list.
+ *
+ * @param userInput The user's input command.
+ * @param taskList The task list to which the command should be applied.
+ * @throws KenException If there's an issue with the user's command or task handling.
+ */
+ public static void processUserCommand(String userInput, TaskList taskList) throws KenException {
+ String[] parts = userInput.split(" ", 2);
+
+ if (parts.length != 2) {
+ handleInvalidCommand(parts[0]);
+ } else {
+ String taskType = parts[0].trim();
+ String taskDescription = parts[1].trim();
+
+ if (taskType.equalsIgnoreCase(COMMAND_TODO) || taskType.equalsIgnoreCase(COMMAND_DEADLINE) || taskType.equalsIgnoreCase(COMMAND_EVENT)) {
+ AddCommand.handleAddTask(taskType, taskDescription, taskList);
+ } else if (taskType.equalsIgnoreCase(COMMAND_DELETE)) {
+ DeleteCommand.handleDeleteTask(taskDescription, taskList);
+ } else if (taskType.equalsIgnoreCase(COMMAND_MARK)) {
+ MarkCommand.handleMarkTask(taskDescription, taskList);
+ } else if (taskType.equalsIgnoreCase(COMMAND_UNMARK)) {
+ MarkCommand.handleUnmarkTask(taskDescription, taskList);
+ } else {
+ throw new InvalidCommandException();
+ }
+ }
+ }
+
+ private static void handleInvalidCommand(String command) throws InvalidCommandException, EmptyDescriptionException, WrongFormatException {
+ if (command.equalsIgnoreCase(COMMAND_DELETE)) {
+ throw new WrongFormatException();
+ } else if (command.equalsIgnoreCase(COMMAND_TODO) || command.equalsIgnoreCase(COMMAND_DEADLINE) || command.equalsIgnoreCase(COMMAND_EVENT)) {
+ throw new EmptyDescriptionException("Hey!! Description cannot be empty for a " + command + " task.");
+ } else {
+ throw new InvalidCommandException();
+ }
+ }
+
+ /**
+ * Extracts date information from a task description, if present, and returns
+ * an array containing the task description and date information.
+ *
+ * @param description The task description that may contain date information.
+ * @return An array containing the task description and date information.
+ * @throws AddCommand.MissingInfoException If there's an issue with the date information extraction.
+ */
+ public static String[] extractDateInfo(String description) throws AddCommand.MissingInfoException {
+ if (description.contains("/from") && description.contains("/to")) {
+ return extractEventDateInfo(description);
+ } else if (description.contains("/by")) {
+ return extractDeadlineDateInfo(description);
+ } else {
+ return new String[]{description, null};
+ }
+ }
+
+ /**
+ * Extracts date information for an event task from the given description.
+ *
+ * @param description The task description that contains date information for an event task.
+ * @return An array containing the task description and date information.
+ * @throws AddCommand.MissingInfoException If there's an issue with the date information extraction.
+ */
+ private static String[] extractEventDateInfo(String description) throws AddCommand.MissingInfoException {
+ String[] parts = description.split(" /from | /to ");
+ if (parts.length > 2) {
+ String startDate = parts[1];
+ String endDate = parts[2];
+ if (endDate.isEmpty()) {
+ throw new AddCommand.MissingInfoException("/to date cannot be empty");
+ }
+ String dateInfo = " from: " + startDate + " to: " + endDate;
+ return new String[]{parts[0], dateInfo};
+ } else {
+ throw new AddCommand.MissingInfoException("Invalid date format for event task");
+ }
+ }
+
+ /**
+ * Extracts date information for a deadline task from the given description.
+ *
+ * @param description The task description that contains date information for a deadline task.
+ * @return An array containing the task description and date information.
+ */
+ private static String[] extractDeadlineDateInfo(String description) {
+ String[] parts = description.split(" /by ");
+ if (parts.length > 1) {
+ String deadlineDate = parts[1];
+ String dateInfo = " by: " + deadlineDate;
+ return new String[]{parts[0], dateInfo};
+ }
+ return new String[]{description, null};
+ }
+}
diff --git a/src/main/java/DeleteCommand.java b/src/main/java/DeleteCommand.java
new file mode 100644
index 000000000..e5c1d7d2b
--- /dev/null
+++ b/src/main/java/DeleteCommand.java
@@ -0,0 +1,38 @@
+
+
+public class DeleteCommand {
+ /**
+ * Handles the deletion of a task from the task list.
+ *
+ * @param taskDescription The description of the task to be deleted.
+ * @param taskList The TaskList from which the task will be deleted.
+ * @throws KenException If there is an error while handling the task deletion.
+ */
+ public static void DeleteTask(String taskDescription, TaskList taskList) throws KenException {
+ try {
+ int taskIndex = Integer.parseInt(taskDescription.trim()) - 1;
+ if (taskIndex >= 0 && taskIndex < taskList.getTaskDescriptions().size()) {
+ String deletedTaskDescription = taskList.getTaskDescriptions().get(taskIndex);
+ printDeletedTaskInfo(taskList, taskIndex, deletedTaskDescription);
+ Storage.deleteTask(taskIndex, taskList);
+ System.out.println("Now you have " + taskList.getTaskDescriptions().size() + " tasks in the list.");
+ } else {
+ throw new TaskNotFoundException();
+ }
+ } catch (NumberFormatException e) {
+ throw new WrongFormatException();
+ }
+ }
+
+ public static void handleDeleteTask(String taskDescription, TaskList taskList) throws KenException {
+ DeleteTask(taskDescription, taskList);
+ Storage.saveTasks(taskList); // Save tasks after deleting
+ }
+
+ private static void printDeletedTaskInfo(TaskList taskList, int taskIndex, String deletedTaskDescription) {
+ System.out.println("Got it. I've removed this task:");
+ System.out.println(" [" + taskList.getTaskTypes().get(taskIndex)
+ + "][ ] " + deletedTaskDescription
+ + (taskList.getTaskDates().get(taskIndex) != null ? " " + taskList.getTaskDates().get(taskIndex) : ""));
+ }
+}
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/EmptyDescriptionException.java b/src/main/java/EmptyDescriptionException.java
new file mode 100644
index 000000000..cd8abef1f
--- /dev/null
+++ b/src/main/java/EmptyDescriptionException.java
@@ -0,0 +1,5 @@
+public class EmptyDescriptionException extends KenException {
+ public EmptyDescriptionException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/FindCommand.java b/src/main/java/FindCommand.java
new file mode 100644
index 000000000..fb14927de
--- /dev/null
+++ b/src/main/java/FindCommand.java
@@ -0,0 +1,42 @@
+import java.util.ArrayList;
+
+public class FindCommand {
+ /**
+ * Finds tasks containing a specified keyword and returns them in a list.
+ *
+ * @param keyword The keyword to search for in task descriptions.
+ * @return A list of matching tasks.
+ */
+ public static ArrayList findTasksByKeyword(String keyword) {
+ ArrayList matchingTasks = new ArrayList<>();
+ for (int i = 0; i < TaskList.taskDescriptions.size(); i++) {
+ String description = TaskList.taskDescriptions.get(i);
+ if (description.contains(keyword)) {
+ String matchingTask = "[" + TaskList.taskTypes.get(i) + "]" + TaskList.taskToString(i);
+ matchingTasks.add((i + 1) + ". " + matchingTask); // Include the task number
+ }
+ }
+ return matchingTasks;
+ }
+
+ /**
+ * Handles the "find" command, searching for tasks with a specified keyword.
+ *
+ * @param userInput The user input string containing the "find" command and keyword.
+ */
+ public static void handleFindCommand(String userInput) {
+ String keyword = userInput.substring(CommandParser.COMMAND_FIND.length()).trim();
+ ArrayList matchingTasks = findTasksByKeyword(keyword);
+
+ Ui.printLine();
+ if (matchingTasks.isEmpty()) {
+ System.out.println("No matching tasks found.");
+ } else {
+ System.out.println("Here are the matching tasks in your list:");
+ for (String matchingTask : matchingTasks) {
+ System.out.println(matchingTask);
+ }
+ }
+ Ui.printLine();
+ }
+}
diff --git a/src/main/java/Ken.java b/src/main/java/Ken.java
new file mode 100644
index 000000000..25d607f1e
--- /dev/null
+++ b/src/main/java/Ken.java
@@ -0,0 +1,69 @@
+import java.util.Scanner;
+
+/**
+ * Ken initializes its components, including the user interface, storage for task data, and the task list.
+ * It loads tasks from a file upon startup and
+ * provides a run loop to process user commands until the "bye" command is entered.
+ */
+public class Ken {
+ private Storage storage;
+ private TaskList taskList;
+ private Ui ui;
+
+ /**
+ * Constructs a Ken object with the specified file path.
+ *
+ * @param filePath The path to the file where task data is stored.
+ */
+ public Ken(String filePath) {
+ ui = new Ui();
+ storage = new Storage(filePath);
+ taskList = new TaskList();
+
+ // Load tasks from the file when the chatbot starts up
+ storage.loadTasks(taskList);
+ }
+
+ /**
+ * The main method to start the Ken chatbot.
+ *
+ * @param args The command-line arguments (not used).
+ * @throws KenException If there is an exception during chatbot initialization or execution.
+ */
+ public static void main(String[] args) throws KenException {
+ Ken ken = new Ken("ken.txt");
+ ken.run();
+ }
+
+ public void run() throws KenException {
+ Ui.printLine();
+ Ui.printWelcomeMessage();
+ Ui.printLine();
+
+ Scanner scanner = new Scanner(System.in);
+
+ while (true) {
+ String userInput = scanner.nextLine();
+ Ui.printLine();
+
+ if (userInput.toLowerCase().startsWith(CommandParser.COMMAND_FIND)) {
+ FindCommand.handleFindCommand(userInput);
+ } else if (userInput.equalsIgnoreCase(CommandParser.COMMAND_BYE)) {
+ Ui.printGoodbyeMessage();
+ break;
+ } else {
+ try {
+ CommandParser.processUserCommand(userInput, taskList);
+ } catch (KenException e) {
+ if (userInput.equalsIgnoreCase(CommandParser.COMMAND_LIST)) {
+ ListCommand.listTasks(taskList);
+ } else {
+ System.out.println("Error: " + e.getMessage());
+ }
+ }
+ }
+ Ui.printLine();
+ }
+ scanner.close();
+ }
+}
diff --git a/src/main/java/KenException.java b/src/main/java/KenException.java
new file mode 100644
index 000000000..04d235fa8
--- /dev/null
+++ b/src/main/java/KenException.java
@@ -0,0 +1,23 @@
+public class KenException extends Exception {
+ public KenException(String message) {
+ super(message);
+ }
+}
+
+class InvalidCommandException extends KenException {
+ public InvalidCommandException() {
+ super("Hmm, what's that? Please use 'todo,' 'deadline,' 'event,' 'delete [number],' or 'mark [number].");
+ }
+}
+
+class TaskNotFoundException extends KenException {
+ public TaskNotFoundException() {
+ super("I can't find this task. Please provide a valid task number.");
+ }
+}
+
+class WrongFormatException extends KenException {
+ public WrongFormatException() {
+ super("Wrong format!! Please provide the number of the task.");
+ }
+}
diff --git a/src/main/java/ListCommand.java b/src/main/java/ListCommand.java
new file mode 100644
index 000000000..6e12dec2d
--- /dev/null
+++ b/src/main/java/ListCommand.java
@@ -0,0 +1,17 @@
+public class ListCommand {
+ /**
+ * Lists all the tasks in the task list.
+ *
+ * @param taskList The TaskList to be listed.
+ */
+ public static void listTasks(TaskList taskList) {
+ System.out.println(" Here are the tasks in your list:");
+ int numTasks = taskList.getTaskDescriptions().size(); // Get the number of tasks
+
+ for (int i = 0; i < numTasks; i++) {
+ char doneSymbol = taskList.getTaskDoneStatus().get(i) ? 'X' : ' ';
+ String dateInfo = taskList.getTaskDates().get(i) != null ? taskList.getTaskDates().get(i) : "";
+ System.out.println(" " + (i + 1) + ".[" + taskList.getTaskTypes().get(i) + "][" + doneSymbol + "] " + taskList.getTaskDescriptions().get(i) + dateInfo);
+ }
+ }
+}
diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..104a0b4f9
--- /dev/null
+++ b/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: Ken
+
diff --git a/src/main/java/MarkCommand.java b/src/main/java/MarkCommand.java
new file mode 100644
index 000000000..eb94246d4
--- /dev/null
+++ b/src/main/java/MarkCommand.java
@@ -0,0 +1,77 @@
+public class MarkCommand {
+ /**
+ * Handles the marking or unmarking of a task as completed in the task list.
+ *
+ * @param taskDescription The description of the task to be marked or unmarked.
+ * @param taskList The TaskList in which the task will be marked or unmarked.
+ * @param markAsDone Set to true to mark the task as done, false to unmark it.
+ * @throws KenException If there is an error while handling the task completion or unmarking.
+ */
+ private static void markOrUnmarkTask(String taskDescription, TaskList taskList, boolean markAsDone) throws KenException {
+ int taskIndex = getTaskIndex(taskDescription, taskList);
+ boolean currentStatus = taskList.getTaskDoneStatus().get(taskIndex);
+
+ if (shouldMarkOrUnmark(currentStatus, markAsDone)) {
+ taskList.getTaskDoneStatus().set(taskIndex, markAsDone);
+ displayMarkedOrUnmarkedMessage(markAsDone, taskList, taskIndex);
+ } else {
+ System.out.println("This task is already " + (markAsDone ? "marked as done." : "unmarked."));
+ }
+ }
+
+ public static int getTaskIndex(String taskDescription, TaskList taskList) throws KenException {
+ try {
+ int taskIndex = Integer.parseInt(taskDescription.trim()) - 1;
+ if (taskIndex >= 0 && taskIndex < taskList.getTaskDescriptions().size()) {
+ return taskIndex;
+ } else {
+ throw new TaskNotFoundException();
+ }
+ } catch (NumberFormatException e) {
+ throw new WrongFormatException();
+ }
+ }
+
+ private static boolean shouldMarkOrUnmark(boolean currentStatus, boolean markAsDone) {
+ return (markAsDone && !currentStatus) || (!markAsDone && currentStatus);
+ }
+
+ private static void displayMarkedOrUnmarkedMessage(boolean markAsDone, TaskList taskList, int taskIndex) {
+ String status = markAsDone ? "marked as done" : "unmarked";
+ String statusSymbol = markAsDone ? "X" : " ";
+ System.out.println("Nice! I've " + status + " this task:");
+ System.out.println(" [" + statusSymbol + "] " + taskList.getTaskDescriptions().get(taskIndex) + (taskList.getTaskDates().get(taskIndex) != null ? taskList.getTaskDates().get(taskIndex) : ""));
+ }
+
+ /**
+ * Handles the marking of a task as completed in the task list.
+ *
+ * @param taskDescription The description of the task to be marked as completed.
+ * @param taskList The TaskList in which the task will be marked.
+ * @throws KenException If there is an error while handling the task completion.
+ */
+ public static void MarkTask(String taskDescription, TaskList taskList) throws KenException {
+ markOrUnmarkTask(taskDescription, taskList, true);
+ }
+
+ /**
+ * Handles the unmarking of a task as incomplete in the task list.
+ *
+ * @param taskDescription The description of the task to be unmarked.
+ * @param taskList The TaskList in which the task will be unmarked.
+ * @throws KenException If there is an error while handling the task unmarking, such as an invalid task number.
+ */
+ public static void UnmarkTask(String taskDescription, TaskList taskList) throws KenException {
+ markOrUnmarkTask(taskDescription, taskList, false);
+ }
+
+ public static void handleMarkTask(String taskDescription, TaskList taskList) throws KenException {
+ MarkTask(taskDescription, taskList);
+ Storage.saveTasks(taskList); // Save tasks after marking
+ }
+
+ public static void handleUnmarkTask(String taskDescription, TaskList taskList) throws KenException {
+ UnmarkTask(taskDescription, taskList);
+ Storage.saveTasks(taskList); // Save tasks after unmarking
+ }
+}
diff --git a/src/main/java/Storage.java b/src/main/java/Storage.java
new file mode 100644
index 000000000..4dfd93639
--- /dev/null
+++ b/src/main/java/Storage.java
@@ -0,0 +1,86 @@
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+
+/**
+ * The Storage class handles loading and saving tasks to a data file.
+ */
+public class Storage {
+ private static String DATA_FILE_PATH = "ken.txt";
+
+ /**
+ * Constructs a Storage object with a specified file path.
+ *
+ * @param filePath The path to the data file.
+ */
+ public Storage(String filePath) {
+ DATA_FILE_PATH = filePath;
+ }
+
+ /**
+ * Loads tasks from the data file and adds them to the given TaskList.
+ *
+ * @param taskList The TaskList to which tasks will be loaded.
+ */
+ public void loadTasks(TaskList taskList) {
+ File file = new File(DATA_FILE_PATH);
+
+ if (file.exists()) {
+ try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ taskList.parseAndAddTask(line);
+ }
+ } catch (IOException e) {
+ System.out.println("Error loading tasks from the data file.");
+ }
+ }
+ }
+
+ /**
+ * Saves tasks from the given TaskList to the data file.
+ *
+ * @param taskList The TaskList containing tasks to be saved.
+ */
+ public static void saveTasks(TaskList taskList) {
+ File file = new File(DATA_FILE_PATH);
+
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
+ for (int i = 0; i < taskList.getTaskDescriptions().size(); i++) {
+ String taskType = taskList.getTaskTypes().get(i);
+ String doneStatus = taskList.getTaskDoneStatus().get(i) ? "1" : "0";
+ String description = taskList.getTaskDescriptions().get(i);
+ String date = taskList.getTaskDates().get(i);
+
+ // Use the same separator character "|" for consistency
+ writer.write(taskType + " | " + doneStatus + " | " + description + " | " + date);
+ writer.newLine();
+ }
+ } catch (IOException e) {
+ System.out.println("Error saving tasks to the data file.");
+ }
+ }
+
+ /**
+ * Deletes a task at the specified index in the TaskList and saves the updated list to the data file.
+ *
+ * @param taskIndex The index of the task to be deleted.
+ * @param taskList The TaskList from which the task will be deleted.
+ */
+ public static void deleteTask(int taskIndex, TaskList taskList) {
+ if (taskIndex >= 0 && taskIndex < TaskList.taskDescriptions.size()) {
+ TaskList.taskDescriptions.remove(taskIndex);
+ TaskList.taskDoneStatus.remove(taskIndex);
+ TaskList.taskTypes.remove(taskIndex);
+ TaskList.taskDates.remove(taskIndex);
+
+ // Call saveTasks to save the tasks after deleting
+ saveTasks(taskList);
+ } else {
+ System.out.println("Task not found. Nothing was deleted.");
+ }
+ }
+}
diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java
new file mode 100644
index 000000000..16b071f47
--- /dev/null
+++ b/src/main/java/TaskList.java
@@ -0,0 +1,122 @@
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The TaskList class manages the task-related data and provides methods to manipulate tasks.
+ */
+public class TaskList {
+ /**
+ * A list to store task descriptions.
+ */
+ public static List taskDescriptions = new ArrayList<>();
+
+ /**
+ * A list to store task completion status (true for completed, false for incomplete).
+ */
+ public static List taskDoneStatus = new ArrayList<>();
+
+ /**
+ * A list to store task types (e.g., "T" for Todo, "D" for Deadline, "E" for Event).
+ */
+ public static List taskTypes = new ArrayList<>();
+
+ /**
+ * A list to store task dates (optional for some task types).
+ */
+ public static List taskDates = new ArrayList<>();
+
+ /**
+ * Parses a task description from a string and adds it to the task lists.
+ *
+ * @param line The string containing task information.
+ */
+ public void parseAndAddTask(String line) {
+ String[] parts = line.split(" \\| ");
+ if (parts.length >= 3) {
+ taskTypes.add(parts[0]);
+ taskDoneStatus.add(parts[1].equals("1"));
+ taskDescriptions.add(parts[2]);
+
+ if (parts[0].equals("T")) {
+ taskDates.add(null); // Set the date to null for Todo tasks
+ } else if (parts.length >= 4) {
+ taskDates.add(parts[3]); // Set the date for Deadline and Event tasks
+ } else {
+ taskDates.add(null); // Handle the case where the date is missing for Deadline and Event tasks
+ }
+ }
+ }
+
+ /**
+ * Retrieves the list of task descriptions.
+ *
+ * @return The list of task descriptions.
+ */
+ public List getTaskDescriptions() {
+ return taskDescriptions;
+ }
+
+ /**
+ * Retrieves the list of task completion statuses.
+ *
+ * @return The list of task completion statuses.
+ */
+ public List getTaskDoneStatus() {
+ return taskDoneStatus;
+ }
+
+ /**
+ * Retrieves the list of task types.
+ *
+ * @return The list of task types.
+ */
+ public List getTaskTypes() {
+ return taskTypes;
+ }
+
+ /**
+ * Retrieves the list of task dates.
+ *
+ * @return The list of task dates.
+ */
+ public List getTaskDates() {
+ return taskDates;
+ }
+
+ /**
+ * Converts a task at the specified index into a formatted string.
+ *
+ * @param index The index of the task to be converted.
+ * @return The formatted string representing the task.
+ */
+ public static String taskToString(int index) {
+ String taskType = taskTypes.get(index);
+ String doneStatus = taskDoneStatus.get(index) ? "[X]" : "[ ]";
+ String description = taskDescriptions.get(index);
+ String date = taskDates.get(index);
+
+ switch (taskType) {
+ case "T":
+ return doneStatus + " " + description;
+ case "D":
+ if (date != null) {
+ return doneStatus + " " + description + " (" + date + ")";
+ } else {
+ return doneStatus + " " + description;
+ }
+ case "E":
+ if (date != null) {
+ String[] dateParts = date.split(" to ");
+ if (dateParts.length == 2) {
+ return doneStatus + " " + description + " (" + dateParts[0] + " to " + dateParts[1] + ")";
+ } else if (dateParts.length == 1) {
+ return doneStatus + " " + description + " (" + dateParts[0] + " )";
+ }
+ } else {
+ return doneStatus + " " + description;
+ }
+ default:
+ return "Unknown task type: " + taskType;
+ }
+ }
+}
diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java
new file mode 100644
index 000000000..a7df0bbb5
--- /dev/null
+++ b/src/main/java/Ui.java
@@ -0,0 +1,40 @@
+/**
+ * This class represents the user interface (UI) for the Ken chatbot.
+ * It provides methods for displaying welcome and goodbye messages, as well
+ * as a horizontal line separator for a cleaner UI presentation.
+ */
+public class Ui {
+ /**
+ * Displays the welcome message when the chatbot starts.
+ */
+ public static void printWelcomeMessage() {
+ printKEN();
+ System.out.println(" Hello! I'm Ken");
+ System.out.println(" What would you like to do?");
+ }
+
+ /**
+ * Displays the goodbye message when the chatbot is exiting.
+ */
+ public static void printGoodbyeMessage() {
+ System.out.println("Bye for now!");
+ }
+
+ /**
+ * Prints a horizontal line separator to separate different sections of the output.
+ */
+ public static void printLine() {
+ System.out.println(" ____________________________________________________________");
+ }
+
+ /**
+ * Prints the ASCII art representation of the chatbot's name "KEN."
+ */
+ private static void printKEN() {
+ System.out.println(" K K EEEEE N N");
+ System.out.println(" K K E NN N");
+ System.out.println(" KKK EEEE N N N");
+ System.out.println(" K K E N NN");
+ System.out.println(" K K EEEEE N N");
+ }
+}