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