diff --git a/.gitignore b/.gitignore
index 2873e189e..e9ad70d95 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,5 @@ bin/
/text-ui-test/ACTUAL.TXT
text-ui-test/EXPECTED-UNIX.TXT
+/data/
+text-ui-test/data/KenergeticBot.txt
diff --git a/README.md b/README.md
index 8715d4d91..db3ad882d 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Duke project template
+# KenergeticBot 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.
@@ -13,12 +13,10 @@ Prerequisites: JDK 11, update Intellij to the most recent version.
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:
+3. After that, locate the `src/main/java/KenergeticBot.java` file, right-click it, and choose `Run KenergeticBot.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
- ____ _
- | _ \ _ _| | _____
- | | | | | | | |/ / _ \
- | |_| | |_| | < __/
- |____/ \__,_|_|\_\___|
+ ____________________________________________________________
+ Hello! I'm KenergeticBot
+ What can I do for you?
+ ____________________________________________________________
```
diff --git a/docs/README.md b/docs/README.md
index 8077118eb..67b4c742c 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,29 +1,136 @@
# User Guide
+## Hi there! I am KenergeticBot
+I am a personal Task managing chatbot, able to store tasks such as To dos, Deadlines and Events.
+
+## 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/KenergeticBot.java` file, right-click it, and choose `Run KenergeticBot.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! I'm KenergeticBot
+ What can I do for you?
+ ____________________________________________________________
+
## Features
-### Feature-ABC
+> **Notes about command format:**
+> - Words encased in `{ }` are the arguments to be supplied by user.
+ e.g. `deadline {Description} /by {Deadline Date & Time}`, `Description` and `Deadline Date & Time` are arguments to be specified by user.
+> - Parameters need to be in the exact format as specified.
+ e.g. `event {Description} /from {Event Start Date & Time} /to {Event End Date & Time}`, `/from` must come before `/to`.
+### Here are some of the things I can do!
+
+### Task Creation
+
+Create 3 types of Tasks:
+
+1. Todo: Tasks which are not time sensitive.
+
+ Format: `todo {Description}`
+
+ Example:
`todo read book`
+2. Deadline: Tasks which are time sensitive, able to indicate deadline using /by.
+
+ Format: `deadline {Description} /by {Deadline Date & Time}`
+
+ Example:
`deadline return book /by Sunday`
+3. Event: Tasks which are happening at a specific time frame, using /from and /to.
+
+ Format: `event {Description} /from {Event Start Date & Time} /to {Event End Date & Time}`
+
+ Example:
`event project meeting /from Mon 2pm /to 4pm`
+
+
+### Task Viewing
+
+Lists all the task in the task list.
+
+Format: `list`
+
-Description of the feature.
+ list
+ ____________________________________________________________
+ Here are the tasks in your list:
+ 1.[T][ ] borrow book
+ 2.[D][ ] return book (by: Sunday)
+ ____________________________________________________________
-### Feature-XYZ
-Description of the feature.
+### Task Marking
-## Usage
+Keep track of Task completion.
+1. '[X]' Indicates Tasks that are completed, using mark command.
+2. '[ ]' Indicates Tasks that are not completed, using unmark command.
-### `Keyword` - Describe action
+Format: `mark {task index}`
-Describe the action and its outcome.
+Example:
-Example of usage:
+ mark 2
+ ____________________________________________________________
+ Nice! I've marked this task as done:
+ [D][X] return book (by: Sunday)
+ ____________________________________________________________
-`keyword (optional arguments)`
-Expected outcome:
+Format: `unmark {task index}`
-Description of the outcome.
+Example:
+ unmark 2
+ ____________________________________________________________
+ OK, I've marked this task as not done yet:
+ [D][ ] return book (by: Sunday)
+ ____________________________________________________________
+
+
+### Task Saving
+Store and retrieve your tasks into a dedicated save file.
```
-expected output
+ Loading previous list
+ Successfully wrote to the file.
```
+
+### Task Finding
+
+Search for keyword using the Find function.
+
+Format: `find {keyword}`
+
+ find book
+ ____________________________________________________________
+ Here are the matching tasks in your list:
+ 1.[T][ ] borrow book
+ 2.[D][ ] return book (by: Sunday)
+ ____________________________________________________________
+
+
+### Task Deletion
+
+Remove stored Tasks using the Delete function.
+
+Format: `delete {task index}`
+
+ delete 2
+ ____________________________________________________________
+ Noted. I've removed this task:
+ [D][ ] return book (by: Sunday)
+ Now you have 1 tasks in the list.
+ ____________________________________________________________
+
+
+### End Program
+Terminates the chatbot program.
+
+Format: `bye`
+
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/KenergeticBot.java b/src/main/java/KenergeticBot.java
new file mode 100644
index 000000000..4e96749fd
--- /dev/null
+++ b/src/main/java/KenergeticBot.java
@@ -0,0 +1,56 @@
+import kenergeticbot.TaskList;
+import kenergeticbot.command.Command;
+import kenergeticbot.fileaccess.Storage;
+import kenergeticbot.ui.TextUi;
+import kenergeticbot.Parser;
+import kenergeticbot.command.ExitCommand;
+
+/**
+ * Entry point of the KenergeticBot chatbot.
+ * Initializes the application and starts the interaction with the user.
+ */
+public class KenergeticBot {
+ public static final String filePath = "data/KenergeticBot.txt";
+
+ private TextUi ui;
+ private Storage storage;
+ public TaskList taskList;
+
+ public static void main(String[] args) {
+ new KenergeticBot().run();
+ }
+
+ /**
+ * Sets up the required objects, loads up the data from the storage file, and prints the welcome message.
+ */
+ private void start(String filePath, TaskList taskList, TextUi ui) {
+ this.storage = new Storage(filePath, ui);
+ storage.loadPreviousList(taskList, ui);
+ ui.printGreetingMessage();
+ }
+
+ /** Runs the program until termination. */
+ public void run() {
+ this.taskList = new TaskList();
+ this.ui = new TextUi();
+ start(filePath, taskList, ui);
+ runCommandLoopUntilExitCommand();
+ exit(ui);
+ }
+
+ /** Reads the user command and executes it, until the user issues the exit command. */
+ public void runCommandLoopUntilExitCommand() {
+ do {
+ String item = ui.getUserCommand();
+ Command c = Parser.parseCommand(taskList, item);
+ c.execute(taskList, ui);
+ } while (!ExitCommand.isExit());
+ storage.saveList(taskList, ui);
+ }
+
+ /** Prints the Goodbye message and exits. */
+ private static void exit(TextUi ui) {
+ ui.printExitMessage();
+ System.exit(0);
+ }
+}
diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..72fcd5b64
--- /dev/null
+++ b/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: KenergeticBot
+
diff --git a/src/main/java/kenergeticbot/Parser.java b/src/main/java/kenergeticbot/Parser.java
new file mode 100644
index 000000000..65ab5a553
--- /dev/null
+++ b/src/main/java/kenergeticbot/Parser.java
@@ -0,0 +1,167 @@
+package kenergeticbot;
+
+import kenergeticbot.command.AddCommand;
+import kenergeticbot.command.Command;
+import kenergeticbot.command.DeleteCommand;
+import kenergeticbot.command.ExitCommand;
+import kenergeticbot.command.FindCommand;
+import kenergeticbot.command.IncorrectCommand;
+import kenergeticbot.command.ListCommand;
+import kenergeticbot.command.MarkCommand;
+import kenergeticbot.command.UnmarkCommand;
+import kenergeticbot.exceptionhandler.KenergeticBotException;
+import java.text.ParseException;
+
+import static kenergeticbot.exceptionhandler.KenergeticBotException.*;
+
+public class Parser{
+
+ /**
+ * Parses user input into command for execution.
+ *
+ * @param userInput full user input string
+ * @param taskList The arraylist object created that stores current tasks
+ * @return the command based on the user input
+ * @throws KenergeticBotException if input does not match any known command
+ */
+ public static Command parseCommand(TaskList taskList, String userInput) {
+ String command[] = userInput.split(" ");
+ switch (command[0].toLowerCase()) {
+ case ListCommand.COMMAND_WORD:
+ return new ListCommand();
+ case MarkCommand.COMMAND_WORD:
+ return prepareMark(taskList,userInput);
+ case UnmarkCommand.COMMAND_WORD:
+ return prepareUnmark(taskList,userInput);
+ case DeleteCommand.COMMAND_WORD:
+ return prepareDelete(taskList,userInput);
+ case ExitCommand.COMMAND_WORD:
+ return new ExitCommand();
+ case FindCommand.COMMAND_WORD:
+ return prepareFind(userInput);
+ default:
+ try{
+ return new AddCommand(userInput);
+ } catch (KenergeticBotException e) {
+ return new IncorrectCommand(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Parses arguments in the context of the mark task command.
+ *
+ * @param userInput full command args string
+ * @param taskList The arraylist object created that stores current tasks
+ * @return the prepared command
+ */
+ private static Command prepareMark(TaskList taskList, String userInput) {
+ try {
+ final int listIndex = parseArgsAsDisplayedIndex(taskList ,userInput, "mark");
+ return new MarkCommand(listIndex);
+ } catch (KenergeticBotException e) {
+ return new IncorrectCommand(e.getMessage());
+ } catch (ParseException e) {
+ return new IncorrectCommand(MESSAGE_INVALID_COMMAND_FORMAT + MarkCommand.MESSAGE_USAGE);
+ } catch (NumberFormatException nfe) {
+ return new IncorrectCommand(MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+ }
+
+ /**
+ * Parses arguments in the context of the unmark task command.
+ *
+ * @param userInput full command args string
+ * @param taskList The arraylist object created that stores current tasks
+ * @return the prepared command
+ */
+ private static Command prepareUnmark(TaskList taskList, String userInput) {
+ try {
+ final int listIndex = parseArgsAsDisplayedIndex(taskList, userInput, "unmark");
+ return new UnmarkCommand(listIndex);
+ } catch (KenergeticBotException e) {
+ return new IncorrectCommand(e.getMessage());
+ } catch (ParseException e) {
+ return new IncorrectCommand(MESSAGE_INVALID_COMMAND_FORMAT + UnmarkCommand.MESSAGE_USAGE);
+ } catch (NumberFormatException nfe) {
+ return new IncorrectCommand(MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+ }
+
+ /**
+ * Parses arguments in the context of the delete task command.
+ *
+ * @param userInput full command args string
+ * @param taskList The arraylist object created that stores current tasks
+ * @return the prepared command
+ */
+ private static Command prepareDelete(TaskList taskList, String userInput) {
+ try {
+ final int listIndex = parseArgsAsDisplayedIndex(taskList, userInput, "delete");
+ return new DeleteCommand(listIndex);
+ } catch (KenergeticBotException e) {
+ return new IncorrectCommand(e.getMessage());
+ } catch (ParseException e) {
+ return new IncorrectCommand(MESSAGE_INVALID_COMMAND_FORMAT + DeleteCommand.MESSAGE_USAGE);
+ } catch (NumberFormatException nfe) {
+ return new IncorrectCommand(MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+ }
+
+ /**
+ * Parses arguments in the context of the mark task command.
+ *
+ * @param userInput full command args string
+ * @return the prepared command
+ */
+ private static Command prepareFind(String userInput) {
+ try {
+ final String listKeyword = parseArgsAsDisplayedKeyword(userInput, "find");
+ return new FindCommand(listKeyword);
+ } catch (KenergeticBotException e) {
+ return new IncorrectCommand(e.getMessage());
+ } catch (ParseException e) {
+ return new IncorrectCommand(MESSAGE_INVALID_COMMAND_FORMAT + MarkCommand.MESSAGE_USAGE);
+ } catch (NumberFormatException nfe) {
+ return new IncorrectCommand(MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+ }
+
+ /**
+ * Parses the given arguments string to identify task index number.
+ *
+ * @param userInput arguments string to parse as index number
+ * @param command expected String name of the command called
+ * @param taskList The arraylist object created that stores current tasks
+ * @return the parsed index number
+ * @throws ParseException if no region of the args string could be found for the index
+ * @throws NumberFormatException the args string region is not a valid number
+ */
+ private static int parseArgsAsDisplayedIndex(TaskList taskList, String userInput, String command) throws ParseException, NumberFormatException, KenergeticBotException {
+ String formattedString = userInput.replace(command, "").trim();
+ int listIndex = Integer.parseInt(formattedString);
+ if (formattedString.isEmpty()) {
+ throw new KenergeticBotException(COMMAND_TYPO_NO_NUMBER);
+ } else if (listIndex > taskList.getSize()) {
+ throw new KenergeticBotException(OUT_OF_RANGE);
+ }
+ return listIndex;
+ }
+
+ /**
+ * Parses the given arguments string to identify task keyword.
+ *
+ * @param userInput arguments string to parse as keyword
+ * @param command expected String name of command to be called
+ * @return the parsed keyword
+ * @throws ParseException if the keyword is not in an expected format
+ * @throws KenergeticBotException if no keyword is found
+ */
+ private static String parseArgsAsDisplayedKeyword(String userInput, String command) throws ParseException, KenergeticBotException {
+ String keywordString = userInput.replace(command, "").trim();
+ if (keywordString.isEmpty()) {
+ throw new KenergeticBotException(COMMAND_TYPO_NO_KEYWORD);
+ }
+ return keywordString;
+ }
+}
diff --git a/src/main/java/kenergeticbot/TaskList.java b/src/main/java/kenergeticbot/TaskList.java
new file mode 100644
index 000000000..590522198
--- /dev/null
+++ b/src/main/java/kenergeticbot/TaskList.java
@@ -0,0 +1,27 @@
+package kenergeticbot;
+
+import kenergeticbot.task.Task;
+import java.util.ArrayList;
+
+/**
+ * Contains the task list e.g., it has operations to add/delete tasks in the list
+ */
+public class TaskList {
+ protected static ArrayList taskList;
+ public TaskList() {
+ taskList = new ArrayList();
+ }
+ public int getSize() {
+ return taskList.size();
+ }
+ public Task getTask(int taskID) {
+ return taskList.get(taskID);
+ }
+ public void removeTask(int taskID) {
+ taskList.remove(taskID);
+ }
+
+ public void addTask(Task task) {
+ taskList.add(task);
+ }
+}
diff --git a/src/main/java/kenergeticbot/command/AddCommand.java b/src/main/java/kenergeticbot/command/AddCommand.java
new file mode 100644
index 000000000..8aea8bf9c
--- /dev/null
+++ b/src/main/java/kenergeticbot/command/AddCommand.java
@@ -0,0 +1,148 @@
+package kenergeticbot.command;
+
+import kenergeticbot.TaskList;
+import kenergeticbot.exceptionhandler.KenergeticBotException;
+import kenergeticbot.task.Deadline;
+import kenergeticbot.task.Event;
+import kenergeticbot.task.Task;
+import kenergeticbot.task.Todo;
+import kenergeticbot.ui.TextUi;
+import static kenergeticbot.common.Messages.SEPARATING_LINE;
+
+import static kenergeticbot.exceptionhandler.KenergeticBotException.*;
+
+public class AddCommand extends Command {
+ private static String item = null;
+ private final String taskType;
+
+ /**
+ * Convenience constructor using input string.
+ * @param userInput User's input used to determine the type of task to be created
+ * @throws KenergeticBotException if input does not match any known command
+ */
+ public AddCommand(String userInput) throws KenergeticBotException {
+ AddCommand.item = userInput;
+ if (BooleanChecks.checkTextForTodo(userInput)) {
+ this.taskType = "T";
+ } else if (BooleanChecks.checkTextForDeadline(userInput)) {
+ this.taskType = "D";
+ } else if (BooleanChecks.checkTextForEvent(userInput)) {
+ this.taskType = "E";
+ }else {
+ throw new KenergeticBotException(INVALID_COMMAND);
+ }
+ }
+
+ @Override
+ public void execute(TaskList taskList, TextUi ui){
+ switch (taskType) {
+ case "T":
+ try {
+ addTodo(taskList, item, ui);
+ } catch (KenergeticBotException e) { //throws exception when the todo command encounters a problem, the error message is tagged to the thrown exception
+ ui.showToUser(SEPARATING_LINE, e.getMessage(), SEPARATING_LINE);
+ }
+ break;
+ case "D":
+ try {
+ addDeadline(taskList, item, ui);
+ } catch (KenergeticBotException e) { //throws exception when the deadline command encounters a problem, the error message is tagged to the thrown exception
+ ui.showToUser(SEPARATING_LINE, e.getMessage(), SEPARATING_LINE);
+ }
+ break;
+ case "E":
+ try {
+ addEvent(taskList, item, ui);
+ } catch (KenergeticBotException e) { //throws exception when the event command encounters a problem, the error message is tagged to the thrown exception
+ ui.showToUser(SEPARATING_LINE, e.getMessage(), SEPARATING_LINE);
+ }
+ break;
+ }
+ }
+
+ /**
+ * Creates a "Todo" object and adds to the taskList
+ * @param taskList The arraylist object created to store the newly created "Todo" Task object
+ * @param userInput User's input containing the details used to create the "Todo" Task object
+ * @param ui The TextUI object created to handle I/O with the user
+ * @throws KenergeticBotException if userInput does not contain sufficient information required to create "Todo" Task object
+ */
+ public static void addTodo(TaskList taskList ,String userInput, TextUi ui) throws KenergeticBotException {
+ String formattedString = userInput.replace("todo", "").trim();
+ if (formattedString.isEmpty()) {
+ throw new KenergeticBotException(TODO_MISSING_DESCRIPTION);
+ }
+ Task newTask = new Todo(formattedString);
+ taskList.addTask(newTask);
+ ui.printAddedTaskMessage(taskList, newTask);
+ }
+
+ /**
+ * Creates a "Deadline" object and adds to the taskList
+ * @param taskList The arraylist object created to store the newly created "Deadline" Task object
+ * @param userInput User's input containing the details used to create the "Deadline" Task object
+ * @param ui The TextUI object created to handle I/O with the user
+ * @throws KenergeticBotException if userInput does not contain sufficient information required to create "Deadline" Task object
+ */
+ public static void addDeadline(TaskList taskList, String userInput, TextUi ui) throws KenergeticBotException {
+ String[] formattedString = userInput.replace("deadline", "").trim().split("/");
+ switch (formattedString.length) { //no default case needed since finding exceptions
+ case 1: //no break; is needed since throwing exception
+ if (formattedString[0].isEmpty()) {
+ throw new KenergeticBotException(DEADLINE_MISSING_DESCRIPTION);
+ } else {
+ throw new KenergeticBotException(DEADLINE_MISSING_DATE_INTERMEDIATE);
+ }
+ case 2: //no break; is needed since throwing exception
+ if (!formattedString[1].contains("by")) {
+ throw new KenergeticBotException(COMMAND_TYPO_DEADLINE_BY);
+ } else if (formattedString[1].replace("by", "").trim().isEmpty()) {
+ throw new KenergeticBotException(DEADLINE_MISSING_DATE);
+ }
+ }
+ String deadlineDate = "(" + formattedString[1].replace("by", "by:") + ")";
+ Task newTask = new Deadline(formattedString[0], deadlineDate);
+ taskList.addTask(newTask);
+ ui.printAddedTaskMessage(taskList, newTask);
+ }
+
+ //
+ /**
+ * Creates an "Event" object and adds to the taskList
+ * @param taskList The arraylist object created to store the newly created "Event" Task object
+ * @param userInput User's input containing the details used to create the "Event" Task object
+ * @param ui The TextUI object created to handle I/O with the user
+ * @throws KenergeticBotException if userInput does not contain sufficient information required to create "Event" Task object
+ */
+ public static void addEvent(TaskList taskList, String userInput, TextUi ui) throws KenergeticBotException {
+ String[] formattedString = userInput.replace("event", "").trim().split("/");
+ switch(formattedString.length) { //no default case needed since finding exceptions
+ case 1: //no break; is needed since throwing exception
+ if (formattedString[0].isEmpty()) {
+ throw new KenergeticBotException(EVENT_MISSING_DESCRIPTION);
+ } else {
+ throw new KenergeticBotException(EVENT_MISSING_START_INTERMEDIATE);
+ }
+ case 2: //no break; is needed since throwing exception
+ if (!formattedString[1].contains("from")) {
+ throw new KenergeticBotException(COMMAND_TYPO_EVENT_FROM);
+ } else if (formattedString[1].replace("from", "").trim().isEmpty()){
+ throw new KenergeticBotException(EVENT_MISSING_START);
+ } else {
+ throw new KenergeticBotException(EVENT_MISSING_END_INTERMEDIATE);
+ }
+ case 3: //no break; is needed since throwing exception
+ if (!formattedString[2].contains("to")) {
+ throw new KenergeticBotException(COMMAND_TYPO_EVENT_TO);
+ } else if (formattedString[2].replace("to", "").trim().isEmpty()){
+ throw new KenergeticBotException(EVENT_MISSING_END);
+ }
+ }
+ String eventFrom = formattedString[1].replace("from", "from:");
+ String eventTo = formattedString[2].replace("to", "to:");
+ String dateTime = "(" + eventFrom + eventTo + ")";
+ Task newTask = new Event(formattedString[0], dateTime);
+ taskList.addTask(newTask);
+ ui.printAddedTaskMessage(taskList, newTask);
+ }
+}
diff --git a/src/main/java/kenergeticbot/command/BooleanChecks.java b/src/main/java/kenergeticbot/command/BooleanChecks.java
new file mode 100644
index 000000000..ebed4da19
--- /dev/null
+++ b/src/main/java/kenergeticbot/command/BooleanChecks.java
@@ -0,0 +1,18 @@
+package kenergeticbot.command;
+
+public class BooleanChecks {
+ //Returns True if the text contains "todo", False if not
+ public static boolean checkTextForTodo(String item) {
+ return item.startsWith("todo");
+ }
+
+ //Returns True if the text contains "deadline", False if not
+ public static boolean checkTextForDeadline(String item) {
+ return item.startsWith("deadline");
+ }
+
+ //Returns True if the text contains "event", False if not
+ public static boolean checkTextForEvent(String item) {
+ return item.startsWith("event");
+ }
+}
diff --git a/src/main/java/kenergeticbot/command/Command.java b/src/main/java/kenergeticbot/command/Command.java
new file mode 100644
index 000000000..7ee619e5a
--- /dev/null
+++ b/src/main/java/kenergeticbot/command/Command.java
@@ -0,0 +1,17 @@
+package kenergeticbot.command;
+
+import kenergeticbot.TaskList;
+import kenergeticbot.ui.TextUi;
+
+/**
+ * Represents an executable command.
+ */
+public class Command {
+
+ /**
+ * Executes the command and returns the result.
+ */
+ public void execute(TaskList taskList, TextUi ui) {
+ throw new UnsupportedOperationException("This method is to be implemented by child classes");
+ };
+}
diff --git a/src/main/java/kenergeticbot/command/DeleteCommand.java b/src/main/java/kenergeticbot/command/DeleteCommand.java
new file mode 100644
index 000000000..20a171d89
--- /dev/null
+++ b/src/main/java/kenergeticbot/command/DeleteCommand.java
@@ -0,0 +1,29 @@
+package kenergeticbot.command;
+
+import kenergeticbot.TaskList;
+import kenergeticbot.ui.TextUi;
+
+import static kenergeticbot.common.Messages.SEPARATING_LINE;
+
+/**
+ * Deletes a task identified using it's last displayed index from the task list.
+ */
+public class DeleteCommand extends Command {
+ public static final String COMMAND_WORD = "delete";
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Deletes the task identified by the index number used in the last task listing.\n"
+ + "Parameters: INDEX\n"
+ + "Example: " + COMMAND_WORD + " 1";
+ private final int listIndex;
+ public DeleteCommand(int listIndex) {
+ this.listIndex = listIndex;
+ }
+
+ @Override
+ public void execute(TaskList taskList, TextUi ui) {
+ ui.printDeleteTaskMessage(taskList, listIndex);
+ taskList.removeTask(listIndex - 1);
+ ui.showToUser(SEPARATING_LINE);
+ }
+
+}
diff --git a/src/main/java/kenergeticbot/command/ExitCommand.java b/src/main/java/kenergeticbot/command/ExitCommand.java
new file mode 100644
index 000000000..199230952
--- /dev/null
+++ b/src/main/java/kenergeticbot/command/ExitCommand.java
@@ -0,0 +1,21 @@
+package kenergeticbot.command;
+
+import kenergeticbot.TaskList;
+import kenergeticbot.ui.TextUi;
+
+/**
+ * Terminates the program.
+ */
+public class ExitCommand extends Command{
+ protected static boolean isExit = false;
+ public static final String COMMAND_WORD = "bye";
+
+ @Override
+ public void execute(TaskList taskList, TextUi ui) {
+ isExit = true;
+ }
+
+ public static boolean isExit() {
+ return isExit;
+ }
+}
diff --git a/src/main/java/kenergeticbot/command/FindCommand.java b/src/main/java/kenergeticbot/command/FindCommand.java
new file mode 100644
index 000000000..75904f1a8
--- /dev/null
+++ b/src/main/java/kenergeticbot/command/FindCommand.java
@@ -0,0 +1,32 @@
+package kenergeticbot.command;
+
+import kenergeticbot.TaskList;
+import kenergeticbot.ui.TextUi;
+
+import static kenergeticbot.common.Messages.FIND_TASK_MESSAGE;
+import static kenergeticbot.common.Messages.SEPARATING_LINE;
+
+/**
+ * Finds a task identified using a keyword.
+ */
+public class FindCommand extends Command {
+ public static final String COMMAND_WORD = "find";
+ private final String keyword;
+ public FindCommand(String keyword) {
+ this.keyword = "(.*)" + keyword + "(.*)";
+ }
+
+ @Override
+ public void execute(TaskList taskList, TextUi ui) {
+ ui.showToUser(SEPARATING_LINE, FIND_TASK_MESSAGE);
+ int j = 1;
+ for (int i = 0; i < taskList.getSize(); i++) {
+ String task = String.valueOf(taskList.getTask(i));
+ if (task.matches(keyword)) {
+ ui.showToUser(" " + j + "." + taskList.getTask(i));
+ j++;
+ }
+ }
+ ui.showToUser(SEPARATING_LINE);
+ }
+}
diff --git a/src/main/java/kenergeticbot/command/IncorrectCommand.java b/src/main/java/kenergeticbot/command/IncorrectCommand.java
new file mode 100644
index 000000000..982d626ff
--- /dev/null
+++ b/src/main/java/kenergeticbot/command/IncorrectCommand.java
@@ -0,0 +1,21 @@
+package kenergeticbot.command;
+
+import kenergeticbot.TaskList;
+import kenergeticbot.ui.TextUi;
+import static kenergeticbot.common.Messages.SEPARATING_LINE;
+
+/**
+ * Represents an incorrect command. Upon execution, produces some feedback to the user.
+ */
+public class IncorrectCommand extends Command{
+ public final String feedbackToUser;
+
+ public IncorrectCommand(String feedbackToUser) {
+ this.feedbackToUser = feedbackToUser;
+ }
+
+ @Override
+ public void execute(TaskList taskList, TextUi ui) {
+ ui.showToUser(SEPARATING_LINE, feedbackToUser, SEPARATING_LINE);
+ }
+}
diff --git a/src/main/java/kenergeticbot/command/ListCommand.java b/src/main/java/kenergeticbot/command/ListCommand.java
new file mode 100644
index 000000000..f67f62c7e
--- /dev/null
+++ b/src/main/java/kenergeticbot/command/ListCommand.java
@@ -0,0 +1,20 @@
+package kenergeticbot.command;
+
+import kenergeticbot.TaskList;
+import kenergeticbot.ui.TextUi;
+
+/**
+ * Lists all tasks in the task list to the user.
+ */
+public class ListCommand extends Command {
+ public static final String COMMAND_WORD = "list";
+ @Override
+ public void execute(TaskList taskList, TextUi ui) {
+ ui.printLine();
+ System.out.println(" Here are the tasks in your list:");
+ for (int i = 0; i < taskList.getSize(); i++) {
+ System.out.printf(" %d.%s\n", i+1, taskList.getTask(i));
+ }
+ ui.printLine();
+ }
+}
diff --git a/src/main/java/kenergeticbot/command/MarkCommand.java b/src/main/java/kenergeticbot/command/MarkCommand.java
new file mode 100644
index 000000000..d975545a1
--- /dev/null
+++ b/src/main/java/kenergeticbot/command/MarkCommand.java
@@ -0,0 +1,25 @@
+package kenergeticbot.command;
+
+import kenergeticbot.TaskList;
+import kenergeticbot.ui.TextUi;
+
+/**
+ * Marks a task identified using it's last displayed index from the task list.
+ */
+public class MarkCommand extends Command {
+
+ public static final String COMMAND_WORD = "mark";
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Marks the task identified by the index number used in the last task listing as done.\n"
+ + "Parameters: INDEX\n"
+ + "Example: " + COMMAND_WORD + " 1";
+ private final int listIndex;
+ public MarkCommand(int listIndex) {
+ this.listIndex = listIndex;
+ }
+ @Override
+ public void execute(TaskList taskList, TextUi ui){
+ taskList.getTask(listIndex - 1).mark();
+ ui.printMarkTaskMessage(taskList, listIndex);
+ }
+}
diff --git a/src/main/java/kenergeticbot/command/UnmarkCommand.java b/src/main/java/kenergeticbot/command/UnmarkCommand.java
new file mode 100644
index 000000000..d5328a6e8
--- /dev/null
+++ b/src/main/java/kenergeticbot/command/UnmarkCommand.java
@@ -0,0 +1,24 @@
+package kenergeticbot.command;
+
+import kenergeticbot.TaskList;
+import kenergeticbot.ui.TextUi;
+
+/**
+ * Unmarks a task identified using it's last displayed index from the task list.
+ */
+public class UnmarkCommand extends Command {
+ public static final String COMMAND_WORD = "unmark";
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Marks the task identified by the index number used in the last task listing as not done.\n"
+ + "Parameters: INDEX\n"
+ + "Example: " + COMMAND_WORD + " 1";
+ private final int listIndex;
+ public UnmarkCommand(int listIndex) {
+ this.listIndex = listIndex;
+ }
+ @Override
+ public void execute(TaskList taskList, TextUi ui) {
+ taskList.getTask(listIndex - 1).unmark();
+ ui.printUnmarkTaskMessage(taskList, listIndex);
+ }
+}
diff --git a/src/main/java/kenergeticbot/common/Messages.java b/src/main/java/kenergeticbot/common/Messages.java
new file mode 100644
index 000000000..c589037ef
--- /dev/null
+++ b/src/main/java/kenergeticbot/common/Messages.java
@@ -0,0 +1,17 @@
+package kenergeticbot.common;
+
+/**
+ * Container for user visible messages.
+ */
+public class Messages {
+ public static String SEPARATING_LINE = " ____________________________________________________________";
+ public static String GREETING_MESSAGE = " Hello! I'm KenergeticBot\n" + " What can I do for you?";
+ public static String GOODBYE_MESSAGE = " Bye. Hope to see you again soon!";
+ public static String ADD_TASK_MESSAGE = " Got it. I've added this task:";
+ public static String DELETE_TASK_MESSAGE = " Noted. I've removed this task:";
+ public static String MARK_TASK_MESSAGE = " Nice! I've marked this task as done:";
+ public static String UNMARK_TASK_MESSAGE = " OK, I've marked this task as not done yet:";
+ public static String TASK_IN_LIST_MESSAGE_PART_1 = " Now you have ";
+ public static String TASK_IN_LIST_MESSAGE_PART_2 = " tasks in the list.";
+ public static String FIND_TASK_MESSAGE = " Here are the matching tasks in your list:";
+}
diff --git a/src/main/java/kenergeticbot/exceptionhandler/KenergeticBotException.java b/src/main/java/kenergeticbot/exceptionhandler/KenergeticBotException.java
new file mode 100644
index 000000000..fdcbc5418
--- /dev/null
+++ b/src/main/java/kenergeticbot/exceptionhandler/KenergeticBotException.java
@@ -0,0 +1,30 @@
+package kenergeticbot.exceptionhandler;
+
+/**
+ * Represents error handling messages
+ */
+public class KenergeticBotException extends Exception {
+ public static final String INVALID_COMMAND = " ☹ OOPS!!! I'm sorry, but I don't know what that means :-(";
+ public static final String TODO_MISSING_DESCRIPTION = " \u02D9\u25E0\u02D9 OOPS!!! The description of a todo cannot be empty.";
+ public static final String DEADLINE_MISSING_DESCRIPTION = " \u02D9\u25E0\u02D9 OOPS!!! The description of a deadline cannot be empty.";
+ public static final String DEADLINE_MISSING_DATE = " \uD83D\uDCC5 OOPS!!! The date of a deadline cannot be empty.";
+ public static final String DEADLINE_MISSING_DATE_INTERMEDIATE = " \uD83D\uDCC5 OOPS!!! The date of a deadline cannot be empty. Please use the command /by";
+ public static final String EVENT_MISSING_DESCRIPTION = " \u02D9\u25E0\u02D9 OOPS!!! The description of a event cannot be empty.";
+ public static final String EVENT_MISSING_START = " ⩇:⩇⩇ OOPS!!! The start time of a event cannot be empty.";
+ public static final String EVENT_MISSING_END = " OOPS!!! The end time of a event cannot be empty.";
+ public static final String EVENT_MISSING_START_INTERMEDIATE = " ⩇:⩇⩇ OOPS!!! The start time of a event cannot be empty. Please use the command /from";
+ public static final String EVENT_MISSING_END_INTERMEDIATE = " OOPS!!! The end time of a event cannot be empty. Please use the command /to";
+ public static final String OUT_OF_RANGE = " OOPS!!! Looks like you tried on an item not in the list";
+ public static final String COMMAND_TYPO = " ¯\\_(ツ)_/¯ OOPS!!! There may be a typo in the command used.";
+ public static final String COMMAND_TYPO_NO_NUMBER = COMMAND_TYPO + " Please use the command with an integer number";
+ public static final String COMMAND_TYPO_NO_KEYWORD = COMMAND_TYPO + " Please use the command with a keyword";
+ public static final String COMMAND_TYPO_DEADLINE_BY = COMMAND_TYPO + " Please use the command /by";
+ public static final String COMMAND_TYPO_EVENT_FROM = COMMAND_TYPO + " Please use the command /from";
+ public static final String COMMAND_TYPO_EVENT_TO = COMMAND_TYPO + " Please use the command /to";
+ public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n";
+ public static final String MESSAGE_INVALID_TASK_DISPLAYED_INDEX = "The task index provided is invalid";
+
+ public KenergeticBotException(String errMSG) {
+ super(errMSG);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/kenergeticbot/fileaccess/Storage.java b/src/main/java/kenergeticbot/fileaccess/Storage.java
new file mode 100644
index 000000000..76d769138
--- /dev/null
+++ b/src/main/java/kenergeticbot/fileaccess/Storage.java
@@ -0,0 +1,179 @@
+package kenergeticbot.fileaccess;
+
+import kenergeticbot.TaskList;
+import kenergeticbot.task.Deadline;
+import kenergeticbot.task.Event;
+import kenergeticbot.task.Task;
+import kenergeticbot.task.Todo;
+import kenergeticbot.ui.TextUi;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+/**
+ * Deals with loading tasks from the file and saving tasks in the file
+ */
+public class Storage {
+
+ protected String filePath;
+ public static final String folderPath = "data";
+
+ public Storage(String filePath, TextUi ui) {
+ this.filePath = filePath;
+ initializeStorage(ui);
+ }
+
+ /**
+ * Checks if the storage file exists, creates the file if not
+ * @param ui The TextUI object created to handle I/O with the user
+ * @throws IOException if the file exists but unable to access
+ */
+ public void initializeStorage(TextUi ui) {
+ File f = new File(filePath);
+ checkFolderExist(ui);
+ try {
+ if (f.createNewFile()) {
+ ui.showToUser("File created: " + f.getName());
+ } else {
+ ui.showToUser("File already exists.");
+ }
+ } catch (IOException e) {
+ ui.showToUser("An error occurred." + e.getMessage());
+ }
+ ui.showToUser("Save file is at: " + f.getAbsolutePath());
+ }
+
+ /**
+ * Checks if the storage folder to store the storage file exists, creates the folder if not
+ * @param ui The TextUI object created to handle I/O with the user
+ */
+ public void checkFolderExist(TextUi ui) {
+ File f = new File(folderPath);
+ if (f.mkdir()) {
+ ui.showToUser("Directory is created");
+ } else {
+ ui.showToUser("Directory already exist");
+ }
+ }
+
+ /**
+ * Loads the storage data file into a TaskList object.
+ * Calls readFromFile method
+ * @param taskList The arraylist object created that stores current tasks
+ * @throws FileNotFoundException if unable to locate storage file using pathfile
+ */
+ public void loadPreviousList(TaskList taskList, TextUi ui) {
+ try {
+ readFromFile(filePath, taskList, ui);
+ } catch (FileNotFoundException e) {
+ ui.showToUser(e.getMessage());
+ }
+ }
+
+ /**
+ * Access the storage data file to create the appropriate Task object
+ * Creates a scanner to scan the storage data file, parses the text to determine respective Task type, isDone status and description
+ * @param filePath The location of the data storage file
+ * @param taskList The arraylist object created that stores current tasks
+ */
+ public void readFromFile(String filePath, TaskList taskList, TextUi ui) throws FileNotFoundException {
+ File f = new File(filePath); // create a File for the given file path
+ if (f.length() == 0) {
+ return;
+ }
+ Scanner s = new Scanner(f);
+ ArrayList previousTaskList = new ArrayList();
+ while (s.hasNext()) {
+ previousTaskList.add(s.nextLine());
+ }
+ s.close();
+
+ for (String task : previousTaskList) {
+ String[] taskVariables = task.split(" \\| ");
+ String taskType = taskVariables[0];
+ String taskMark = taskVariables[1];
+ String taskDescription = taskVariables[2];
+
+ switch (taskType) {
+ case "T" :
+ Task previousTodo = new Todo(taskDescription, isMark(taskMark));
+ taskList.addTask(previousTodo);
+ ui.showToUser("adding:" + previousTodo);
+ break;
+ case "D" :
+ String taskDeadline = taskVariables[3];
+ Task previousDeadline = new Deadline(taskDescription, taskDeadline, isMark(taskMark));
+ taskList.addTask(previousDeadline);
+ ui.showToUser("adding:" + previousDeadline);
+ break;
+ case "E" :
+ String taskEventDateTime = taskVariables[3];
+ Task previousEvent = new Event(taskDescription, taskEventDateTime, isMark(taskMark));
+ taskList.addTask(previousEvent);
+ ui.showToUser("adding:" + previousEvent);
+ break;
+ default :
+ throw new IllegalStateException("Unexpected value: " + taskType);
+ }
+ }
+ try {
+ new FileWriter(filePath, false).close();
+ } catch (IOException e) {
+ ui.showToUser(e.getMessage());
+ }
+ }
+
+ /**
+ * Writes a String into a data file for storage.
+ * If data file does not exist, the method creates data file
+ * If data file already exist, the method edits the data file
+ * @param textToAdd The intended data to be stored into the data file
+ * @throws IOException if the file exists but unable to access
+ */
+ public void writeToFile(String textToAdd, TextUi ui) {
+ File f = new File(filePath);
+ if (f.length() == 0) { //if file is empty
+ try {
+ FileWriter saveFileWriter = new FileWriter(filePath);
+ saveFileWriter.write(textToAdd);
+ saveFileWriter.close();
+ ui.showToUser("Successfully wrote to the file.");
+ } catch (IOException e) {
+ ui.showToUser(e.getMessage());
+ }
+ } else { //if file is not empty
+ try {
+ FileWriter saveFileWriter = new FileWriter(filePath, true);
+ saveFileWriter.write(textToAdd);
+ saveFileWriter.close();
+ ui.showToUser("Successfully wrote to the file.");
+ } catch (IOException e) {
+ ui.showToUser(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Saves the TaskList object into a data file for storage, iterating through the list.
+ */
+ public void saveList(TaskList taskList, TextUi ui) {
+ for (int i = 0; i < taskList.getSize(); i++) {
+ System.out.println(taskList.getTask(i));
+ writeToFile(taskList.getTask(i).printTaskToSave(), ui);
+ }
+ }
+
+ /**
+ * Checks if the string has the task marked as done or not done
+ * @param stringInput The String that stores the done status of the task
+ * @return True is task is done, False if not done
+ */
+ public boolean isMark(String stringInput) {
+ boolean isDone = stringInput.equals("1");
+ return isDone;
+ }
+}
diff --git a/src/main/java/kenergeticbot/task/Deadline.java b/src/main/java/kenergeticbot/task/Deadline.java
new file mode 100644
index 000000000..5f7c76e94
--- /dev/null
+++ b/src/main/java/kenergeticbot/task/Deadline.java
@@ -0,0 +1,32 @@
+package kenergeticbot.task;
+
+/**
+ * Represents a Deadline Task
+ * Contains Task Deadline, Task Description and Task Type = [T]
+ */
+public class Deadline extends Task {
+ protected String deadline;
+ public Deadline(String description, String deadline) {
+ super(description);
+ this.deadline = deadline;
+ this.taskType = "[D]";
+ }
+ public Deadline(String description, String deadline, boolean isDone) {
+ super(description);
+ this.deadline = deadline;
+ this.taskType = "[D]";
+ this.isDone = isDone;
+ }
+
+ public String getDeadline() {
+ return deadline;
+ }
+
+ public String toString() {
+ return taskType + super.toString() + deadline;
+ }
+ public String printTaskToSave() {
+ String task = taskType.replace("[", "").replace("]","");
+ return task + super.printTaskToSave() + " | " + deadline + "\n";
+ }
+}
diff --git a/src/main/java/kenergeticbot/task/Event.java b/src/main/java/kenergeticbot/task/Event.java
new file mode 100644
index 000000000..d8b8a5a3b
--- /dev/null
+++ b/src/main/java/kenergeticbot/task/Event.java
@@ -0,0 +1,29 @@
+package kenergeticbot.task;
+
+/**
+ * Represents an Event Task
+ * Contains Task DateTime, Task Description and Task Type = [T]
+ */
+public class Event extends Task {
+ protected String dateTime;
+ public Event(String description, String dateTime) {
+ super(description);
+ this.dateTime = dateTime;
+ this.taskType = "[E]";
+ }
+ public Event(String description, String dateTime, boolean isDone) {
+ super(description);
+ this.dateTime = dateTime;
+ this.taskType = "[E]";
+ this.isDone = isDone;
+ }
+
+ public String toString() {
+ return taskType + super.toString() + dateTime;
+ }
+
+ public String printTaskToSave() {
+ String task = taskType.replace("[", "").replace("]","");
+ return task + super.printTaskToSave() + " | " + dateTime + "\n";
+ }
+}
diff --git a/src/main/java/kenergeticbot/task/Task.java b/src/main/java/kenergeticbot/task/Task.java
new file mode 100644
index 000000000..8f4fdb2b5
--- /dev/null
+++ b/src/main/java/kenergeticbot/task/Task.java
@@ -0,0 +1,40 @@
+package kenergeticbot.task;
+
+/**
+ * Represents an executable Task
+ */
+public class Task {
+ protected String description;
+ protected boolean isDone;
+ protected String taskType;
+
+ public Task(String description) {
+ this.description = description;
+ this.isDone = false;
+ }
+
+ public String getStatusIcon() {
+ return (isDone ? "[X]" : "[ ]"); // mark done task with X
+ }
+
+ public String getTaskType() {
+ return taskType;
+ }
+
+ public void mark() {
+ this.isDone = true;
+ }
+
+ public void unmark() {
+ this.isDone = false;
+ }
+
+ public String toString() {
+ return getStatusIcon() + " " + description;
+ }
+
+ public String printTaskToSave() {
+ int mark = isDone ? 1 : 0;
+ return " | " + mark + " | " + description;
+ }
+}
diff --git a/src/main/java/kenergeticbot/task/Todo.java b/src/main/java/kenergeticbot/task/Todo.java
new file mode 100644
index 000000000..13578617c
--- /dev/null
+++ b/src/main/java/kenergeticbot/task/Todo.java
@@ -0,0 +1,25 @@
+package kenergeticbot.task;
+
+/**
+ * Represents a Todo Task
+ * Contains Task Description and Task Type = [T]
+ */
+public class Todo extends Task {
+ public Todo(String description) {
+ super(description);
+ this.taskType = "[T]";
+ }
+ public Todo(String description, boolean isDone) {
+ super(description);
+ this.taskType = "[T]";
+ this.isDone = isDone;
+ }
+
+ public String toString() {
+ return taskType + super.toString();
+ }
+ public String printTaskToSave() {
+ String task = taskType.replace("[", "").replace("]","");
+ return task + super.printTaskToSave() + "\n";
+ }
+}
diff --git a/src/main/java/kenergeticbot/ui/TextUi.java b/src/main/java/kenergeticbot/ui/TextUi.java
new file mode 100644
index 000000000..691b58713
--- /dev/null
+++ b/src/main/java/kenergeticbot/ui/TextUi.java
@@ -0,0 +1,88 @@
+package kenergeticbot.ui;
+
+import kenergeticbot.TaskList;
+import kenergeticbot.task.Task;
+
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.Scanner;
+
+import static kenergeticbot.common.Messages.ADD_TASK_MESSAGE;
+import static kenergeticbot.common.Messages.DELETE_TASK_MESSAGE;
+import static kenergeticbot.common.Messages.GOODBYE_MESSAGE;
+import static kenergeticbot.common.Messages.GREETING_MESSAGE;
+import static kenergeticbot.common.Messages.MARK_TASK_MESSAGE;
+import static kenergeticbot.common.Messages.SEPARATING_LINE;
+import static kenergeticbot.common.Messages.TASK_IN_LIST_MESSAGE_PART_1;
+import static kenergeticbot.common.Messages.TASK_IN_LIST_MESSAGE_PART_2;
+import static kenergeticbot.common.Messages.UNMARK_TASK_MESSAGE;
+
+public class TextUi {
+
+ private final Scanner in;
+ private final PrintStream out;
+
+ public TextUi() {
+ this(System.in, System.out);
+ }
+ public TextUi(InputStream in, PrintStream out) {
+ this.in = new Scanner(in);
+ this.out = out;
+ }
+
+ public void printLine() {
+ System.out.println(SEPARATING_LINE);
+ }
+
+ /**
+ * Reads the text entered by the user.
+ * @return command (full line) entered by the user
+ */
+ public String getUserCommand() {
+ String fullInputLine = in.nextLine();
+ return fullInputLine;
+ }
+ public void printGreetingMessage() {
+ showToUser(SEPARATING_LINE,
+ GREETING_MESSAGE,
+ SEPARATING_LINE);
+ }
+
+ public void printExitMessage() {
+ showToUser(SEPARATING_LINE,
+ GOODBYE_MESSAGE,
+ SEPARATING_LINE);
+ }
+
+ public void printAddedTaskMessage(TaskList taskList, Task newTask) {
+ showToUser(SEPARATING_LINE,
+ ADD_TASK_MESSAGE,
+ " " + newTask,
+ TASK_IN_LIST_MESSAGE_PART_1 + taskList.getSize() + TASK_IN_LIST_MESSAGE_PART_2,
+ SEPARATING_LINE);
+ }
+
+ public void printDeleteTaskMessage(TaskList taskList, int listIndex) {
+ showToUser(SEPARATING_LINE,
+ DELETE_TASK_MESSAGE,
+ " " + taskList.getTask(listIndex - 1),
+ TASK_IN_LIST_MESSAGE_PART_1 + (taskList.getSize() - 1) + TASK_IN_LIST_MESSAGE_PART_2);
+ }
+
+ public void printMarkTaskMessage(TaskList taskList, int listIndex) {
+ showToUser(SEPARATING_LINE, MARK_TASK_MESSAGE,
+ " " + taskList.getTask(listIndex - 1), SEPARATING_LINE);
+ }
+
+ public void printUnmarkTaskMessage(TaskList taskList, int listIndex) {
+ showToUser(SEPARATING_LINE, UNMARK_TASK_MESSAGE,
+ " " + taskList.getTask(listIndex - 1), SEPARATING_LINE);
+ }
+
+ /** Shows message(s) to the user */
+ public void showToUser(String... message) {
+ for (String m : message) {
+ System.out.println(m);
+ }
+ }
+}
diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT
index 657e74f6e..6af8d43f6 100644
--- a/text-ui-test/EXPECTED.TXT
+++ b/text-ui-test/EXPECTED.TXT
@@ -1,7 +1,88 @@
-Hello from
- ____ _
-| _ \ _ _| | _____
-| | | | | | | |/ / _ \
-| |_| | |_| | < __/
-|____/ \__,_|_|\_\___|
-
+ ____________________________________________________________
+ Hello! I'm KenergeticBot
+ What can I do for you?
+ ____________________________________________________________
+ ____________________________________________________________
+ Got it. I've added this task:
+ [T][ ] borrow book
+ Now you have 1 tasks in the list.
+ ____________________________________________________________
+ ____________________________________________________________
+ Here are the tasks in your list:
+ 1.[T][ ] borrow book
+ ____________________________________________________________
+ ____________________________________________________________
+ Got it. I've added this task:
+ [D][ ] return book (by: Sunday)
+ Now you have 2 tasks in the list.
+ ____________________________________________________________
+ ____________________________________________________________
+ Got it. I've added this task:
+ [E][ ] project meeting (from: Mon 2pm to: 4pm)
+ Now you have 3 tasks in the list.
+ ____________________________________________________________
+ ____________________________________________________________
+ Nice! I've marked this task as done:
+ [D][X] return book (by: Sunday)
+ ____________________________________________________________
+ ____________________________________________________________
+ Here are the tasks in your list:
+ 1.[T][ ] borrow book
+ 2.[D][X] return book (by: Sunday)
+ 3.[E][ ] project meeting (from: Mon 2pm to: 4pm)
+ ____________________________________________________________
+ ____________________________________________________________
+ OK, I've marked this task as not done yet:
+ [D][ ] return book (by: Sunday)
+ ____________________________________________________________
+ ____________________________________________________________
+ Here are the tasks in your list:
+ 1.[T][ ] borrow book
+ 2.[D][ ] return book (by: Sunday)
+ 3.[E][ ] project meeting (from: Mon 2pm to: 4pm)
+ ____________________________________________________________
+ ____________________________________________________________
+ ??? OOPS!!! The description of a todo cannot be empty.
+ ____________________________________________________________
+ ____________________________________________________________
+ ? OOPS!!! The date of a deadline cannot be empty.
+ ____________________________________________________________
+ ____________________________________________________________
+ ¯\_(ツ)_/¯ OOPS!!! There may be a typo in the command used. Please use the command /by
+ ____________________________________________________________
+ ____________________________________________________________
+ ? OOPS!!! The date of a deadline cannot be empty. Please use the command /by
+ ____________________________________________________________
+ ____________________________________________________________
+ ? OOPS!!! The date of a deadline cannot be empty. Please use the command /by
+ ____________________________________________________________
+ ____________________________________________________________
+ ??? OOPS!!! The description of a deadline cannot be empty.
+ ____________________________________________________________
+ ____________________________________________________________
+ ? OOPS!!! The end time of a event cannot be empty.
+ ____________________________________________________________
+ ____________________________________________________________
+ ¯\_(ツ)_/¯ OOPS!!! There may be a typo in the command used. Please use the command /to
+ ____________________________________________________________
+ ____________________________________________________________
+ ? OOPS!!! The end time of a event cannot be empty. Please use the command /to
+ ____________________________________________________________
+ ____________________________________________________________
+ ? OOPS!!! The end time of a event cannot be empty. Please use the command /to
+ ____________________________________________________________
+ ____________________________________________________________
+ ⩇:⩇⩇ OOPS!!! The start time of a event cannot be empty.
+ ____________________________________________________________
+ ____________________________________________________________
+ ¯\_(ツ)_/¯ OOPS!!! There may be a typo in the command used. Please use the command /from
+ ____________________________________________________________
+ ____________________________________________________________
+ ⩇:⩇⩇ OOPS!!! The start time of a event cannot be empty. Please use the command /from
+ ____________________________________________________________
+ ____________________________________________________________
+ ??? OOPS!!! The description of a event cannot be empty.
+ ____________________________________________________________
+ ____________________________________________________________
+ Bye. Hope to see you again soon!
+ ____________________________________________________________
diff --git a/text-ui-test/data/KenergeticBot.txt b/text-ui-test/data/KenergeticBot.txt
new file mode 100644
index 000000000..617554ad9
--- /dev/null
+++ b/text-ui-test/data/KenergeticBot.txt
@@ -0,0 +1,18 @@
+T | 0 | borrow book
+D | 0 | return book | (by: Sunday)
+E | 0 | project meeting | (from: Mon 2pm to: 4pm)
+T | 0 | borrow book
+D | 0 | return book | (by: Sunday)
+E | 0 | project meeting | (from: Mon 2pm to: 4pm)
+T | 0 | borrow book
+D | 0 | return book | (by: Sunday)
+E | 0 | project meeting | (from: Mon 2pm to: 4pm)
+T | 0 | borrow book
+D | 0 | return book | (by: Sunday)
+E | 0 | project meeting | (from: Mon 2pm to: 4pm)
+T | 0 | borrow book
+D | 0 | return book | (by: Sunday)
+E | 0 | project meeting | (from: Mon 2pm to: 4pm)
+T | 0 | borrow book
+D | 0 | return book | (by: Sunday)
+E | 0 | project meeting | (from: Mon 2pm to: 4pm)
diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt
index e69de29bb..ba52efa0a 100644
--- a/text-ui-test/input.txt
+++ b/text-ui-test/input.txt
@@ -0,0 +1,25 @@
+todo borrow book
+list
+deadline return book /by Sunday
+event project meeting /from Mon 2pm /to 4pm
+mark 2
+list
+unmark 2
+list
+todo
+deadline return book /by
+deadline return book /b
+deadline return book /
+deadline return book
+deadline
+event project meeting /from Mon 2pm /to
+event project meeting /from Mon 2pm /t
+event project meeting /from Mon 2pm /
+event project meeting /from Mon 2pm
+event project meeting /from
+event project meeting /fr
+event project meeting
+event
+find book
+delete 2
+bye
\ No newline at end of file
diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat
index 087374464..d1f753472 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 KenergeticBot < input.txt > ACTUAL.TXT
REM compare the output to the expected output
FC ACTUAL.TXT EXPECTED.TXT