tasks = this.getAllAsArray();
+ JsonArray tasksJson = new JsonArray();
+ for (Task task : tasks) {
+ if (task instanceof Event) {
+ tasksJson.add(parseEventAsJson((Event) task));
+ } else if (task instanceof Deadline) {
+ tasksJson.add(parseDeadlineAsJson((Deadline) task));
+ } else if (task instanceof ToDo) {
+ tasksJson.add(parseToDoAsJson((ToDo) task));
+ }
+ }
+ return tasksJson;
+ }
+
+ public Boolean containsTaskId(Integer taskId) {
+ return this.tasks.containsKey(taskId);
+ }
+
+}
diff --git a/src/main/java/duke/Ui.java b/src/main/java/duke/Ui.java
new file mode 100644
index 00000000..4cccc5ed
--- /dev/null
+++ b/src/main/java/duke/Ui.java
@@ -0,0 +1,155 @@
+package duke;
+
+
+import java.io.PrintStream;
+import java.nio.file.Path;
+import java.util.Scanner;
+
+import duke.command.Command;
+import duke.command.commandfactory.UiCommandFactory;
+import duke.dukeutility.enums.ResponseType;
+
+
+/**
+ * Handles terminal display.
+ */
+public class Ui {
+ private final UiCommandFactory uiCommandFactory = new UiCommandFactory();
+ private PrintStream out;
+ private Boolean isLoop = true;
+
+ private Ui() {
+ }
+ // Getters and Setters
+
+ public Ui(PrintStream ps) {
+ this.setPrintStream(ps);
+ }
+
+ private PrintStream getPrintStream() {
+ return this.out;
+ }
+
+ public void setPrintStream(PrintStream ps) {
+ this.out = ps;
+ }
+
+ private Boolean isLoop() {
+ return this.isLoop;
+ }
+
+ private void setIsLoop(Boolean p) {
+ this.isLoop = p;
+ }
+
+ private UiCommandFactory getUiCommandFactory() {
+ return this.uiCommandFactory;
+ }
+
+
+ // Outputs
+
+
+ public void printEntryMessage() {
+ String logo = " _ _ _ " + System.lineSeparator()
+ + "| | | | | | " + System.lineSeparator()
+ + "| |_ __ _ ___ | | __ _ __ ___ __ _ ___ | |_ ___ _ __ " + System.lineSeparator()
+ + "| __| / _` | / __| | |/ / | '_ ` _ \\ / _` | / __| | __| / _ \\ | '__|" + System.lineSeparator()
+ + "| |_ | (_| | \\__ \\ | < | | | | | | | (_| | \\__ \\ | |_ | __/ | | " + System.lineSeparator()
+ + " \\__| \\__,_| |___/ |_|\\_\\ |_| |_| |_| \\__,_| |___/ \\__| \\___| |_| " + System.lineSeparator();
+ this.getPrintStream().print("Hello from" + System.lineSeparator() + logo);
+ }
+
+ public void printInitialLoadTaskAttempt(Path path) {
+ if (path == null) {
+ this.getPrintStream().print("Import path empty. " + System.lineSeparator());
+ } else {
+ this.getPrintStream().print("Attempting to import tasks from " + path + "." + System.lineSeparator());
+ }
+ }
+
+ public void printBeginInputLoop() {
+ this.getPrintStream().print("How can i help you? (See README.md for usage)" + System.lineSeparator());
+ }
+
+
+ public void printTerminateMessage() {
+ this.getPrintStream().print("See you again!" + System.lineSeparator());
+ }
+
+ private void printEndOfResponse() {
+ this.getPrintStream().print("\t\t\t\t\t\t\t\t -" + System.lineSeparator());
+ }
+
+
+ private String getExitLoopMessage() {
+ return "ok bye" + System.lineSeparator();
+ }
+
+ protected void printCommandResponse(Command c) throws Exception {
+ assert (c != null);
+ ResponseType rt = c.getResponseType();
+
+ String output;
+
+ switch (rt) {
+ case EXIT_LOOP:
+ output = (this.getExitLoopMessage());
+ break;
+ case TASK_LIST_ALL:
+ case TASK_LIST_FIND:
+ case TASK_LIST_ONE:
+ case TASK_PROJECTION_ALL:
+ case TASK_PROJECTION_NOT_DONE:
+ case TASK_STATS_ALL:
+ case SCAN_DUPLICATE_DESCRIPTION:
+ case TASK_UPDATE_COMPLETE:
+ case TASK_UPDATE_INCOMPLETE:
+ case TASK_NOT_FOUND:
+ case TASK_DELETE_TASK:
+ case TASK_CREATE_TODO:
+ case TASK_CREATE_DEADLINE:
+ case TASK_CREATE_EVENT:
+ case ERROR_COMMAND_EXECUTION:
+ case ERROR_REQUEST_UNKNOWN:
+ case ERROR_REQUEST_INVALID_SYNTAX:
+ case ERROR_REQUEST_INVALID_PARAMETERS:
+ case ERROR_INVALID_READ_FILE_PATH:
+ case FILE_SAVED:
+ case FILE_READ:
+ output = c.getResponse();
+ break;
+ default:
+ throw new Exception("Unhandled response type [" + rt + "].");
+ }
+ this.getPrintStream().print(output);
+ }
+
+ /**
+ * cli session with request-response cycle.
+ *
+ * Text commands are separated by line breaks. Parsing and execution is delegated to
+ * After execution, command response will be displayed based on the type of the command returned.
+ * It is recommended highly to pass in non-null arguments in production environment.
+ *
+ * @param taskManager is required if commands wants to manipulate a task collection.
+ * @param frm is required if commands execute file operations.
+ * @throws Exception
+ * @see UiCommandFactory#executeTextCommand()
+ */
+ public void runTextCommandLoop(TaskManager taskManager, FileResourceManager frm) throws Exception {
+ this.printBeginInputLoop();
+ String textCommand;
+ Scanner in = new Scanner(System.in);
+ do {
+ textCommand = in.nextLine();
+ Command command = this.getUiCommandFactory().executeTextCommand(textCommand, taskManager, frm);
+ assert (command != null);
+ this.setIsLoop(!command.getResponseType().equals(ResponseType.EXIT_LOOP));
+ this.printCommandResponse(command);
+ this.printEndOfResponse();
+ } while (this.isLoop());
+ }
+
+
+}
diff --git a/src/main/java/duke/command/Command.java b/src/main/java/duke/command/Command.java
new file mode 100644
index 00000000..8cb89902
--- /dev/null
+++ b/src/main/java/duke/command/Command.java
@@ -0,0 +1,43 @@
+package duke.command;
+
+import java.util.List;
+
+import duke.dukeutility.enums.ResponseType;
+
+
+/**
+ * Abstract Class for commands.
+ * Commands executes core behaviors and resultant value(s) are stored for future use.
+ */
+public abstract class Command {
+ /* Array of args to record parameters and results for task creation. */
+ private List args;
+ /* Response type for users to identify the behavior that was executed in the command */
+ private ResponseType responseType;
+
+ protected Command(ResponseType rt, List args) {
+ this.setResponseType(rt);
+ this.setArgs(args);
+ }
+
+ private Command() {
+ }
+
+ public ResponseType getResponseType() {
+ return responseType;
+ }
+
+ protected void setResponseType(ResponseType rt) {
+ responseType = rt;
+ }
+
+ public List getArgs() {
+ return this.args;
+ }
+
+ protected void setArgs(List inputArgs) {
+ this.args = inputArgs;
+ }
+
+ public abstract String getResponse();
+}
diff --git a/src/main/java/duke/command/CommandJsonResponse.java b/src/main/java/duke/command/CommandJsonResponse.java
new file mode 100644
index 00000000..6541ba7a
--- /dev/null
+++ b/src/main/java/duke/command/CommandJsonResponse.java
@@ -0,0 +1,25 @@
+package duke.command;
+
+import java.util.List;
+
+import com.google.gson.JsonElement;
+
+import duke.dukeutility.enums.ResponseType;
+
+
+public abstract class CommandJsonResponse extends Command {
+ private JsonElement jsonArg;
+
+ protected CommandJsonResponse(ResponseType rt, List args, JsonElement jsonArg) {
+ super(rt, args);
+ this.setJsonArg(jsonArg);
+ }
+
+ public JsonElement getJsonArg() {
+ return this.jsonArg;
+ }
+
+ private void setJsonArg(JsonElement arg) {
+ this.jsonArg = arg;
+ }
+}
diff --git a/src/main/java/duke/command/commandfactory/CommandFactory.java b/src/main/java/duke/command/commandfactory/CommandFactory.java
new file mode 100644
index 00000000..919cc92a
--- /dev/null
+++ b/src/main/java/duke/command/commandfactory/CommandFactory.java
@@ -0,0 +1,7 @@
+package duke.command.commandfactory;
+
+/**
+ * @see duke.command.Command
+ */
+public abstract class CommandFactory {
+}
diff --git a/src/main/java/duke/command/commandfactory/ImportCommandFactory.java b/src/main/java/duke/command/commandfactory/ImportCommandFactory.java
new file mode 100644
index 00000000..d41ab292
--- /dev/null
+++ b/src/main/java/duke/command/commandfactory/ImportCommandFactory.java
@@ -0,0 +1,64 @@
+package duke.command.commandfactory;
+
+import static duke.dukeutility.parser.JsonTaskToObjectParser.jsonTaskToPojo;
+
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import com.google.gson.JsonObject;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.command.CommandJsonResponse;
+import duke.command.errorcommand.CommandExecutionError;
+import duke.command.errorcommand.CommandReadFileError;
+import duke.command.errorcommand.CommandUnknownRequest;
+import duke.command.systemcommand.CommandReadTasks;
+import duke.command.taskcommand.taskimport.CommandImportDeadline;
+import duke.command.taskcommand.taskimport.CommandImportEvent;
+import duke.command.taskcommand.taskimport.CommandImportToDo;
+import duke.task.model.Deadline;
+import duke.task.model.Event;
+import duke.task.model.Task;
+import duke.task.model.ToDo;
+
+public class ImportCommandFactory extends CommandFactory {
+
+
+ /**
+ * Extract tasks from file.
+ *
+ * @param path file of saved tasks
+ * @return command
+ */
+ public CommandJsonResponse executeExtractTasksFromFile(Path path) {
+ Reader reader;
+ try {
+ reader = Files.newBufferedReader(path,
+ StandardCharsets.UTF_8);
+ } catch (Exception e) {
+ return new CommandReadFileError("Invalid file read path. " + e);
+ }
+ return new CommandReadTasks(reader, path);
+ }
+
+ public Command executeImportJsonTask(JsonObject jsonObj, TaskManager taskManager) {
+ Task task;
+ try {
+ task = jsonTaskToPojo(jsonObj);
+ } catch (Exception e) {
+ return new CommandExecutionError(e, "Error transforming json to java object " + jsonObj.toString());
+ }
+ if (task instanceof Event) {
+ return new CommandImportEvent((Event) task, taskManager);
+ } else if (task instanceof Deadline) {
+ return new CommandImportDeadline((Deadline) task, taskManager);
+ } else if (task instanceof ToDo) {
+ return new CommandImportToDo((ToDo) task, taskManager);
+ }
+ return new CommandUnknownRequest("Unrecognised Task type.");
+ }
+
+}
diff --git a/src/main/java/duke/command/commandfactory/UiCommandFactory.java b/src/main/java/duke/command/commandfactory/UiCommandFactory.java
new file mode 100644
index 00000000..d6c8fa8e
--- /dev/null
+++ b/src/main/java/duke/command/commandfactory/UiCommandFactory.java
@@ -0,0 +1,306 @@
+package duke.command.commandfactory;
+
+import static duke.dukeutility.definition.CommandPromptsAndOptions.ADD_DEADLINE_DEADLINE_DELIMITER;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.ADD_EVENT_SCHEDULE_DELIMITER;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_ADD_DEADLINE;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_ADD_EVENT;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_ADD_TODO;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_DELETE_TASK;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_FIND_BY_KEYWORD_DESCRIPTION;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_LIST_ONE;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_PROJECTION_ALL;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_PROJECTION_NOT_DONE;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_UPDATE_DONE;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_UPDATE_NOT_DONE;
+import static duke.dukeutility.parser.DateParser.parseStringAsLocalDateTime;
+import static duke.dukeutility.validator.TextCommandValidator.isRequestAddDeadline;
+import static duke.dukeutility.validator.TextCommandValidator.isRequestAddEvent;
+import static duke.dukeutility.validator.TextCommandValidator.isRequestAddToDo;
+import static duke.dukeutility.validator.TextCommandValidator.isRequestDeleteTask;
+import static duke.dukeutility.validator.TextCommandValidator.isRequestExitLoop;
+import static duke.dukeutility.validator.TextCommandValidator.isRequestFind;
+import static duke.dukeutility.validator.TextCommandValidator.isRequestList;
+import static duke.dukeutility.validator.TextCommandValidator.isRequestMarkTaskAsDone;
+import static duke.dukeutility.validator.TextCommandValidator.isRequestMarkTaskAsIncomplete;
+import static duke.dukeutility.validator.TextCommandValidator.isRequestProjectionAll;
+import static duke.dukeutility.validator.TextCommandValidator.isRequestProjectionNotDone;
+import static duke.dukeutility.validator.TextCommandValidator.isRequestSave;
+import static duke.dukeutility.validator.TextCommandValidator.isRequestScanDuplicates;
+import static duke.dukeutility.validator.TextCommandValidator.isRequestSee;
+import static duke.dukeutility.validator.TextCommandValidator.isRequestStatisticsAll;
+
+import java.time.LocalDateTime;
+
+import duke.FileResourceManager;
+import duke.TaskManager;
+import duke.command.Command;
+import duke.command.errorcommand.CommandExecutionError;
+import duke.command.errorcommand.CommandInvalidRequestParameters;
+import duke.command.errorcommand.CommandInvalidTextCommandSyntax;
+import duke.command.errorcommand.CommandTaskNotFound;
+import duke.command.errorcommand.CommandUnknownRequest;
+import duke.command.systemcommand.CommandExitLoop;
+import duke.command.taskcommand.taskadd.CommandAddNewDeadline;
+import duke.command.taskcommand.taskadd.CommandAddNewEvent;
+import duke.command.taskcommand.taskadd.CommandAddNewToDo;
+import duke.command.taskcommand.taskquery.CommandListAll;
+import duke.command.taskcommand.taskquery.CommandListOne;
+import duke.command.taskcommand.taskquery.CommandListTasksWithKeyword;
+import duke.command.taskcommand.taskquery.CommandProjectionAll;
+import duke.command.taskcommand.taskquery.CommandProjectionNotDone;
+import duke.command.taskcommand.taskquery.CommandScanDuplicateDescriptions;
+import duke.command.taskcommand.taskquery.CommandStatsAll;
+import duke.command.taskcommand.taskupdate.CommandDeleteTask;
+import duke.command.taskcommand.taskupdate.CommandMarkTaskAsDone;
+import duke.command.taskcommand.taskupdate.CommandMarkTaskAsIncomplete;
+import duke.dukeexception.DukeParseDateTimeException;
+
+
+public class UiCommandFactory extends CommandFactory {
+
+ public Command executeTextCommand(String text, TaskManager taskManager, FileResourceManager frm) {
+ assert (text != null);
+ try {
+ if (isRequestExitLoop(text)) {
+ return this.executeCommandExitLoop();
+ } else if (isRequestList(text)) {
+ return new CommandListAll(taskManager);
+ } else if (isRequestMarkTaskAsDone(text)) {
+ return this.executeCommandMarkTaskComplete(text, taskManager);
+ } else if (isRequestMarkTaskAsIncomplete(text)) {
+ return this.executeCommandMarkTaskIncomplete(text, taskManager);
+ } else if (isRequestAddToDo(text)) {
+ return this.executeCommandAddToDo(text, taskManager);
+ } else if (isRequestAddDeadline(text)) {
+ return this.executeCommandAddDeadline(text, taskManager);
+ } else if (isRequestAddEvent(text)) {
+ return this.executeCommandAddEvent(text, taskManager);
+ } else if (isRequestDeleteTask(text)) {
+ return this.executeCommandDeleteTask(text, taskManager);
+ } else if (isRequestSave(text)) {
+ return frm.executeSave(taskManager);
+ } else if (isRequestSee(text)) {
+ return this.executeSeeTask(text, taskManager);
+ } else if (isRequestFind(text)) {
+ return this.executeCommandFindByKeywordInDescription(text, taskManager);
+ } else if (isRequestProjectionAll(text)) {
+ return this.executeCommandProjectionAll(text, taskManager);
+ } else if (isRequestProjectionNotDone(text)) {
+ return this.executeCommandProjectionNotDone(text, taskManager);
+ } else if (isRequestStatisticsAll(text)) {
+ return new CommandStatsAll(taskManager);
+ } else if (isRequestScanDuplicates(text)) {
+ return new CommandScanDuplicateDescriptions(taskManager);
+ } else {
+ return new CommandUnknownRequest(text);
+ }
+ } catch (Exception e) {
+ return new CommandExecutionError(e, "command execution @ cli");
+ }
+ }
+
+ private Command executeCommandExitLoop() {
+ return new CommandExitLoop();
+ }
+
+ private Command executeCommandAddToDo(String text, TaskManager taskManager) {
+ int minDescLength = 0;
+ String taskDescription = text.replaceFirst(PROMPT_ADD_TODO, "");
+ if (taskDescription.length() <= minDescLength) {
+ return new CommandInvalidRequestParameters("ToDo description is too short");
+ }
+ return new CommandAddNewToDo(taskManager, taskDescription);
+ }
+
+ private Command executeCommandAddDeadline(String text, TaskManager taskManager) {
+ String argLine;
+ String[] argList;
+ String taskDescription;
+ LocalDateTime deadline;
+ try {
+ argLine = text.replaceFirst(PROMPT_ADD_DEADLINE, "");
+ String addDlDlDelimiter = ADD_DEADLINE_DEADLINE_DELIMITER;
+ argList = argLine.split(addDlDlDelimiter);
+ int argsCount = 2;
+ if (argList.length != argsCount) {
+ String msg =
+ "Expected " + argsCount + " arguments delimited by \"" + addDlDlDelimiter + "\"";
+ return new CommandInvalidTextCommandSyntax(msg);
+ }
+ try {
+ taskDescription = argList[0];
+ deadline = parseStringAsLocalDateTime(argList[1]);
+ } catch (DukeParseDateTimeException e) {
+ return new CommandInvalidRequestParameters(e.getMessage());
+ }
+ } catch (Exception e) {
+ return new CommandInvalidTextCommandSyntax(e.getMessage());
+
+ }
+ return new CommandAddNewDeadline(taskManager, taskDescription, deadline);
+ }
+
+ private Command executeCommandAddEvent(String text, TaskManager taskManager) {
+
+ String argLine;
+ String[] argList;
+ String[] scheduleOptionList;
+ String taskDescription;
+ LocalDateTime from;
+ LocalDateTime to;
+ try {
+ argLine = text.replaceFirst(PROMPT_ADD_EVENT, "");
+ argList = argLine.split(ADD_EVENT_SCHEDULE_DELIMITER);
+ if (argList.length != 2) {
+ return new CommandInvalidTextCommandSyntax("Request line for adding event does not conform to syntax.");
+ }
+ taskDescription = argList[0];
+ scheduleOptionList = argList[1].split("-");
+ if (scheduleOptionList.length != 2) {
+ return new CommandInvalidTextCommandSyntax("Request line for adding event does not conform to syntax.");
+ }
+ try {
+ from = parseStringAsLocalDateTime(scheduleOptionList[0]);
+ to = parseStringAsLocalDateTime(scheduleOptionList[1]);
+ } catch (DukeParseDateTimeException e) {
+ return new CommandInvalidRequestParameters(e.getMessage());
+ }
+ } catch (Exception e) {
+ return new CommandInvalidRequestParameters(e.toString());
+ }
+ return new CommandAddNewEvent(taskManager, taskDescription, from, to);
+ }
+
+
+ private Command executeCommandMarkTaskComplete(String text, TaskManager taskManager) {
+ String argLine;
+ String[] argList;
+ Integer taskId;
+ try {
+ argLine = text.replaceFirst(PROMPT_UPDATE_DONE, "");
+ argList = argLine.split(" ");
+ if (argList.length != 1) {
+ return new CommandInvalidTextCommandSyntax("Invalid syntax.");
+ }
+ taskId = Integer.parseInt(argList[0]);
+ if (!taskManager.containsTaskId(taskId)) {
+ return new CommandTaskNotFound(argList[0]);
+ }
+ } catch (Exception e) {
+ return new CommandInvalidRequestParameters(e.toString());
+ }
+ return new CommandMarkTaskAsDone(taskManager, taskId);
+ }
+
+ private Command executeCommandMarkTaskIncomplete(String text, TaskManager taskManager) {
+ String argLine;
+ String[] argList;
+ Integer taskId;
+ try {
+ argLine = text.replaceFirst(PROMPT_UPDATE_NOT_DONE, "");
+ argList = argLine.split(" ");
+ if (argList.length != 1) {
+ return new CommandInvalidTextCommandSyntax("Invalid syntax.");
+ }
+ taskId = Integer.parseInt(argList[0]);
+ if (!taskManager.containsTaskId(taskId)) {
+ return new CommandTaskNotFound(argList[0]);
+ }
+ } catch (Exception e) {
+ return new CommandInvalidRequestParameters(e.toString());
+ }
+ return new CommandMarkTaskAsIncomplete(taskManager, taskId);
+ }
+
+ private Command executeSeeTask(String text, TaskManager taskManager) {
+ String argLine;
+ String[] argList;
+ Integer taskId;
+ try {
+ argLine = text.replaceFirst(PROMPT_LIST_ONE, "");
+ argList = argLine.split(" ");
+ if (argList.length != 1) {
+ return new CommandInvalidTextCommandSyntax("Invalid syntax.");
+ }
+ taskId = Integer.parseInt(argList[0]);
+ if (!taskManager.containsTaskId(taskId)) {
+ return new CommandTaskNotFound(argList[0]);
+ }
+ } catch (Exception e) {
+ return new CommandInvalidRequestParameters(e.toString());
+ }
+ return new CommandListOne(taskManager, taskId);
+ }
+
+ private Command executeCommandDeleteTask(String text, TaskManager taskManager) {
+ String argLine;
+ String[] argList;
+ Integer taskId;
+ try {
+ argLine = text.replaceFirst(PROMPT_DELETE_TASK, "");
+ argList = argLine.split(" ");
+ if (argList.length != 1) {
+ return new CommandInvalidTextCommandSyntax("Invalid syntax.");
+ }
+ taskId = Integer.parseInt(argList[0]);
+ if (!taskManager.containsTaskId(taskId)) {
+ return new CommandTaskNotFound(argList[0]);
+ }
+ } catch (Exception e) {
+ return new CommandInvalidRequestParameters(e.toString());
+ }
+ return new CommandDeleteTask(taskManager, taskId);
+ }
+
+
+ private Command executeCommandFindByKeywordInDescription(String text, TaskManager taskManager) {
+ String argLine;
+ String[] argList;
+ String keyword;
+ try {
+ argLine = text.replaceFirst(PROMPT_FIND_BY_KEYWORD_DESCRIPTION, "");
+ argList = argLine.split(" ");
+ if (argList.length != 1) {
+ return new CommandInvalidTextCommandSyntax("Invalid syntax. Keyword should not have spacing.");
+ }
+ keyword = argList[0];
+ } catch (Exception e) {
+ return new CommandInvalidRequestParameters(e.toString());
+ }
+ return new CommandListTasksWithKeyword(taskManager, keyword);
+ }
+
+ private Command executeCommandProjectionAll(String text, TaskManager taskManager) {
+ String argLine;
+ String[] argList;
+ int period;
+ try {
+ argLine = text.replaceFirst(PROMPT_PROJECTION_ALL, "");
+ argList = argLine.split(" ");
+ if (argList.length != 1) {
+ return new CommandInvalidTextCommandSyntax("Invalid syntax.");
+ }
+ period = Integer.parseInt(argList[0]);
+ } catch (Exception e) {
+ return new CommandInvalidRequestParameters(e.toString());
+ }
+ return new CommandProjectionAll(taskManager, period);
+ }
+
+ private Command executeCommandProjectionNotDone(String text, TaskManager taskManager) {
+ String argLine;
+ String[] argList;
+ int period;
+ try {
+ argLine = text.replaceFirst(PROMPT_PROJECTION_NOT_DONE, "");
+ argList = argLine.split(" ");
+ if (argList.length != 1) {
+ return new CommandInvalidTextCommandSyntax("Invalid syntax.");
+ }
+ period = Integer.parseInt(argList[0]);
+ } catch (Exception e) {
+ return new CommandInvalidRequestParameters(e.toString());
+ }
+ return new CommandProjectionNotDone(taskManager, period);
+ }
+}
diff --git a/src/main/java/duke/command/errorcommand/CommandExecutionError.java b/src/main/java/duke/command/errorcommand/CommandExecutionError.java
new file mode 100644
index 00000000..409ec7c5
--- /dev/null
+++ b/src/main/java/duke/command/errorcommand/CommandExecutionError.java
@@ -0,0 +1,16 @@
+package duke.command.errorcommand;
+
+import java.util.List;
+
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandExecutionError extends Command {
+ public CommandExecutionError(Exception e, String when) {
+ super(ResponseType.ERROR_COMMAND_EXECUTION, List.of("Error during execution of command ", e.toString()));
+ }
+
+ public String getResponse() {
+ return this.getArgs().get(1) + System.lineSeparator();
+ }
+}
diff --git a/src/main/java/duke/command/errorcommand/CommandInvalidRequestParameters.java b/src/main/java/duke/command/errorcommand/CommandInvalidRequestParameters.java
new file mode 100644
index 00000000..693a36ce
--- /dev/null
+++ b/src/main/java/duke/command/errorcommand/CommandInvalidRequestParameters.java
@@ -0,0 +1,17 @@
+package duke.command.errorcommand;
+
+import java.util.List;
+
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandInvalidRequestParameters extends Command {
+ public CommandInvalidRequestParameters(String message) {
+ super(ResponseType.ERROR_REQUEST_INVALID_PARAMETERS, List.of("Invalid request parameters", message));
+ }
+
+
+ public String getResponse() {
+ return "Invalid parameters: " + this.getArgs().get(1) + System.lineSeparator();
+ }
+}
diff --git a/src/main/java/duke/command/errorcommand/CommandInvalidTextCommandSyntax.java b/src/main/java/duke/command/errorcommand/CommandInvalidTextCommandSyntax.java
new file mode 100644
index 00000000..8536e021
--- /dev/null
+++ b/src/main/java/duke/command/errorcommand/CommandInvalidTextCommandSyntax.java
@@ -0,0 +1,16 @@
+package duke.command.errorcommand;
+
+import java.util.List;
+
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandInvalidTextCommandSyntax extends Command {
+ public CommandInvalidTextCommandSyntax(String message) {
+ super(ResponseType.ERROR_REQUEST_INVALID_SYNTAX, List.of("Invalid syntax", message));
+ }
+
+ public String getResponse() {
+ return this.getArgs().get(1) + System.lineSeparator();
+ }
+}
diff --git a/src/main/java/duke/command/errorcommand/CommandReadFileError.java b/src/main/java/duke/command/errorcommand/CommandReadFileError.java
new file mode 100644
index 00000000..a976b17f
--- /dev/null
+++ b/src/main/java/duke/command/errorcommand/CommandReadFileError.java
@@ -0,0 +1,17 @@
+package duke.command.errorcommand;
+
+import java.util.List;
+
+import duke.command.CommandJsonResponse;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandReadFileError extends CommandJsonResponse {
+ public CommandReadFileError(String message) {
+ super(ResponseType.ERROR_INVALID_READ_FILE_PATH, List.of(message), null);
+ }
+
+ @Override
+ public String getResponse() {
+ return "Read path not found/invalid. " + System.lineSeparator();
+ }
+}
diff --git a/src/main/java/duke/command/errorcommand/CommandTaskNotFound.java b/src/main/java/duke/command/errorcommand/CommandTaskNotFound.java
new file mode 100644
index 00000000..104dbb02
--- /dev/null
+++ b/src/main/java/duke/command/errorcommand/CommandTaskNotFound.java
@@ -0,0 +1,17 @@
+package duke.command.errorcommand;
+
+import java.util.List;
+
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandTaskNotFound extends Command {
+ public CommandTaskNotFound(String text) {
+ super(ResponseType.TASK_NOT_FOUND, List.of("Task Not Found ", text));
+ }
+
+ public String getResponse() {
+ return "Task Not Found: " + this.getArgs().get(1) + System.lineSeparator();
+ }
+}
+
diff --git a/src/main/java/duke/command/errorcommand/CommandUnknownRequest.java b/src/main/java/duke/command/errorcommand/CommandUnknownRequest.java
new file mode 100644
index 00000000..592ce121
--- /dev/null
+++ b/src/main/java/duke/command/errorcommand/CommandUnknownRequest.java
@@ -0,0 +1,16 @@
+package duke.command.errorcommand;
+
+import java.util.List;
+
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandUnknownRequest extends Command {
+ public CommandUnknownRequest(String text) {
+ super(ResponseType.ERROR_REQUEST_UNKNOWN, List.of("?", text));
+ }
+
+ public String getResponse() {
+ return "Unknown command. . ." + System.lineSeparator();
+ }
+}
diff --git a/src/main/java/duke/command/systemcommand/CommandExitLoop.java b/src/main/java/duke/command/systemcommand/CommandExitLoop.java
new file mode 100644
index 00000000..e688c674
--- /dev/null
+++ b/src/main/java/duke/command/systemcommand/CommandExitLoop.java
@@ -0,0 +1,19 @@
+package duke.command.systemcommand;
+
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_EXIT_LOOP;
+
+import java.util.List;
+
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandExitLoop extends Command {
+ public CommandExitLoop() {
+ super(ResponseType.EXIT_LOOP, List.of(PROMPT_EXIT_LOOP));
+ }
+
+ @Override
+ public String getResponse() {
+ return null;
+ }
+}
diff --git a/src/main/java/duke/command/systemcommand/CommandExportTasksToFile.java b/src/main/java/duke/command/systemcommand/CommandExportTasksToFile.java
new file mode 100644
index 00000000..8aaae2a8
--- /dev/null
+++ b/src/main/java/duke/command/systemcommand/CommandExportTasksToFile.java
@@ -0,0 +1,55 @@
+package duke.command.systemcommand;
+
+import static duke.dukeutility.enums.ResponseType.FILE_SAVED;
+import static duke.dukeutility.enums.ResponseType.FILE_SAVED_IO_ERROR;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.List;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.stream.JsonWriter;
+
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandExportTasksToFile extends Command {
+ /**
+ * Export tasks to file as JSON. Will return response type based on the execution.
+ *
+ * @param tasks task objects to write
+ * @param jw writer
+ */
+ public CommandExportTasksToFile(JsonArray tasks, Path writePath, JsonWriter jw) {
+ super(ResponseType.EXPORT_IN_PROGRESS, List.of("export", writePath.toString()));
+
+ new Gson().toJson(tasks, jw);
+ try {
+ jw.close();
+ this.setResponseType(FILE_SAVED);
+ } catch (IOException err) {
+ this.setResponseType(FILE_SAVED_IO_ERROR);
+
+ }
+
+
+ }
+
+ public String getResponse() {
+ String reply;
+ ResponseType rt = this.getResponseType();
+ switch (rt) {
+ case FILE_SAVED:
+ reply = "Saved task to file: ";
+ break;
+ case FILE_SAVED_IO_ERROR:
+ reply = "File save error . . . ";
+ break;
+ default:
+ reply = "Save did not complete to";
+
+ }
+ return reply + this.getArgs().get(1) + System.lineSeparator();
+ }
+}
diff --git a/src/main/java/duke/command/systemcommand/CommandReadTasks.java b/src/main/java/duke/command/systemcommand/CommandReadTasks.java
new file mode 100644
index 00000000..f5c9f4c5
--- /dev/null
+++ b/src/main/java/duke/command/systemcommand/CommandReadTasks.java
@@ -0,0 +1,27 @@
+package duke.command.systemcommand;
+
+import java.io.Reader;
+import java.nio.file.Path;
+import java.util.List;
+
+import com.google.gson.JsonParser;
+
+import duke.command.CommandJsonResponse;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandReadTasks extends CommandJsonResponse {
+ /**
+ * get tasks from reader and parse as json
+ *
+ * @param reader reader
+ * @param path path
+ */
+ public CommandReadTasks(Reader reader, Path path) {
+ super(ResponseType.FILE_READ, List.of("json", "tasks", path.toString()),
+ JsonParser.parseReader(reader).getAsJsonArray());
+ }
+
+ public String getResponse() {
+ return "Success reading file " + this.getArgs().get(0) + System.lineSeparator();
+ }
+}
diff --git a/src/main/java/duke/command/taskcommand/taskadd/CommandAddNewDeadline.java b/src/main/java/duke/command/taskcommand/taskadd/CommandAddNewDeadline.java
new file mode 100644
index 00000000..f10fe175
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskadd/CommandAddNewDeadline.java
@@ -0,0 +1,33 @@
+package duke.command.taskcommand.taskadd;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+import duke.task.model.Deadline;
+
+public class CommandAddNewDeadline extends Command {
+ /**
+ * Task manager will add a new deadline to its collection with provided parameters
+ *
+ * @param tm task manager
+ * @param desc of deadline
+ * @param deadline of deadline
+ */
+ public CommandAddNewDeadline(TaskManager tm, String desc, LocalDateTime dl) {
+ super(ResponseType.TASK_CREATING_IN_PROGRESS,
+ null);
+
+ Deadline deadline = tm.addNewDeadline(desc, dl);
+ this.setArgs(List.of("create", deadline.getTaskId().toString(), deadline.getTaskDescription()));
+ this.setResponseType(ResponseType.TASK_CREATE_DEADLINE);
+ }
+
+ public String getResponse() {
+ String id = this.getArgs().get(1);
+ String desc = this.getArgs().get(2);
+ return "Added Deadline [id #" + id + "]: " + desc + System.lineSeparator();
+ }
+}
diff --git a/src/main/java/duke/command/taskcommand/taskadd/CommandAddNewEvent.java b/src/main/java/duke/command/taskcommand/taskadd/CommandAddNewEvent.java
new file mode 100644
index 00000000..9ffcca78
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskadd/CommandAddNewEvent.java
@@ -0,0 +1,29 @@
+package duke.command.taskcommand.taskadd;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+import duke.task.model.Event;
+
+public class CommandAddNewEvent extends Command {
+
+ public CommandAddNewEvent(TaskManager tm, String desc, LocalDateTime from, LocalDateTime to) {
+ super(ResponseType.TASK_CREATING_IN_PROGRESS,
+ null);
+
+ Event ev = tm.addNewEvent(desc, from, to);
+
+ this.setArgs(List.of("create", ev.getTaskId().toString(), ev.getTaskDescription()));
+ this.setResponseType(ResponseType.TASK_CREATE_EVENT);
+ }
+
+ public String getResponse() {
+ String id = this.getArgs().get(1);
+ String desc = this.getArgs().get(2);
+ return "Added Event [id #" + id + "]: " + desc + System.lineSeparator();
+ }
+
+}
diff --git a/src/main/java/duke/command/taskcommand/taskadd/CommandAddNewToDo.java b/src/main/java/duke/command/taskcommand/taskadd/CommandAddNewToDo.java
new file mode 100644
index 00000000..3966c1cb
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskadd/CommandAddNewToDo.java
@@ -0,0 +1,35 @@
+package duke.command.taskcommand.taskadd;
+
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+import duke.task.model.ToDo;
+
+
+public class CommandAddNewToDo extends Command {
+
+ /**
+ * Task manager will add a new todo to its collection with provided parameters
+ *
+ * @param tm task manager
+ * @param desc of todo
+ */
+
+ public CommandAddNewToDo(TaskManager tm, String desc) {
+ super(ResponseType.TASK_CREATING_IN_PROGRESS,
+ null);
+ ToDo todo = tm.addNewToDo(desc);
+ this.setArgs(List.of("create", todo.getTaskId().toString(), todo.getTaskDescription()));
+ this.setResponseType(ResponseType.TASK_CREATE_TODO);
+ }
+
+ public String getResponse() {
+
+ String id = this.getArgs().get(1);
+ String desc = this.getArgs().get(2);
+
+ return "Added To Do [id #" + id + "]: " + desc + System.lineSeparator();
+ }
+}
diff --git a/src/main/java/duke/command/taskcommand/taskimport/CommandImportDeadline.java b/src/main/java/duke/command/taskcommand/taskimport/CommandImportDeadline.java
new file mode 100644
index 00000000..0558f0ef
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskimport/CommandImportDeadline.java
@@ -0,0 +1,26 @@
+package duke.command.taskcommand.taskimport;
+
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+import duke.task.model.Deadline;
+
+
+public class CommandImportDeadline extends Command {
+ /**
+ * Import a deadline to a task manager
+ *
+ * @param deadline deadline
+ * @param taskMgr task manager
+ */
+ public CommandImportDeadline(Deadline deadline, TaskManager taskMgr) {
+ super(ResponseType.TASK_IMPORT_DEADLINE,
+ List.of("create", deadline.getTaskDescription(), taskMgr.importTask(deadline).getTaskDescription()));
+ }
+
+ public String getResponse() {
+ return null;
+ }
+}
diff --git a/src/main/java/duke/command/taskcommand/taskimport/CommandImportEvent.java b/src/main/java/duke/command/taskcommand/taskimport/CommandImportEvent.java
new file mode 100644
index 00000000..3c31bf5b
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskimport/CommandImportEvent.java
@@ -0,0 +1,26 @@
+package duke.command.taskcommand.taskimport;
+
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+import duke.task.model.Event;
+
+
+public class CommandImportEvent extends Command {
+ /**
+ * Import a event to a task manager
+ *
+ * @param event event
+ * @param taskMgr task manager
+ */
+ public CommandImportEvent(Event event, TaskManager taskMgr) {
+ super(ResponseType.TASK_IMPORT_EVENT,
+ List.of("create", event.getTaskDescription(), taskMgr.importTask(event).getTaskDescription()));
+ }
+
+ public String getResponse() {
+ return null;
+ }
+}
diff --git a/src/main/java/duke/command/taskcommand/taskimport/CommandImportToDo.java b/src/main/java/duke/command/taskcommand/taskimport/CommandImportToDo.java
new file mode 100644
index 00000000..8d68ac56
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskimport/CommandImportToDo.java
@@ -0,0 +1,26 @@
+package duke.command.taskcommand.taskimport;
+
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+import duke.task.model.ToDo;
+
+
+public class CommandImportToDo extends Command {
+ /**
+ * Import a todo to a task manager
+ *
+ * @param toDo todo
+ * @param taskMgr task manager
+ */
+ public CommandImportToDo(ToDo toDo, TaskManager taskMgr) {
+ super(ResponseType.TASK_IMPORT_TODO,
+ List.of("create", toDo.getTaskDescription(), taskMgr.importTask(toDo).getTaskDescription()));
+ }
+
+ public String getResponse() {
+ return null;
+ }
+}
diff --git a/src/main/java/duke/command/taskcommand/taskquery/CommandListAll.java b/src/main/java/duke/command/taskcommand/taskquery/CommandListAll.java
new file mode 100644
index 00000000..c1cc3f31
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskquery/CommandListAll.java
@@ -0,0 +1,19 @@
+package duke.command.taskcommand.taskquery;
+
+import static duke.dukeutility.prettify.Prettify.prettifyTaskMgr;
+
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandListAll extends Command {
+ public CommandListAll(TaskManager taskMgr) {
+ super(ResponseType.TASK_LIST_ALL, List.of("list", prettifyTaskMgr(taskMgr)));
+ }
+
+ public String getResponse() {
+ return this.getArgs().get(1);
+ }
+}
diff --git a/src/main/java/duke/command/taskcommand/taskquery/CommandListOne.java b/src/main/java/duke/command/taskcommand/taskquery/CommandListOne.java
new file mode 100644
index 00000000..658f3528
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskquery/CommandListOne.java
@@ -0,0 +1,20 @@
+package duke.command.taskcommand.taskquery;
+
+import static duke.dukeutility.prettify.Prettify.prettifyTasks;
+
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandListOne extends Command {
+ public CommandListOne(TaskManager taskMgr, Integer taskId) {
+ super(ResponseType.TASK_LIST_FIND,
+ List.of("list", prettifyTasks(taskMgr.getTasksWithId(taskId)), taskId.toString()));
+ }
+
+ public String getResponse() {
+ return "See: " + this.getArgs().get(2) + System.lineSeparator() + this.getArgs().get(1);
+ }
+}
diff --git a/src/main/java/duke/command/taskcommand/taskquery/CommandListTasksWithKeyword.java b/src/main/java/duke/command/taskcommand/taskquery/CommandListTasksWithKeyword.java
new file mode 100644
index 00000000..f44af857
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskquery/CommandListTasksWithKeyword.java
@@ -0,0 +1,21 @@
+package duke.command.taskcommand.taskquery;
+
+import static duke.dukeutility.prettify.Prettify.prettifyTasks;
+
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandListTasksWithKeyword extends Command {
+ public CommandListTasksWithKeyword(TaskManager taskMgr, String keyword) {
+ super(ResponseType.TASK_LIST_FIND,
+ List.of("list", prettifyTasks(taskMgr.getTasksWithKeywordInDescription(keyword)), keyword));
+ }
+
+ public String getResponse() {
+ return "Query keyword in description: " + this.getArgs().get(2) + System.lineSeparator() +
+ this.getArgs().get(1);
+ }
+}
diff --git a/src/main/java/duke/command/taskcommand/taskquery/CommandProjectionAll.java b/src/main/java/duke/command/taskcommand/taskquery/CommandProjectionAll.java
new file mode 100644
index 00000000..139490f7
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskquery/CommandProjectionAll.java
@@ -0,0 +1,21 @@
+package duke.command.taskcommand.taskquery;
+
+import static duke.dukeutility.prettify.Prettify.prettifyTasks;
+
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandProjectionAll extends Command {
+ public CommandProjectionAll(TaskManager taskMgr, Integer period) {
+ super(ResponseType.TASK_PROJECTION_ALL,
+ List.of("list", prettifyTasks(taskMgr.getTasksForNextDaysAll(period)), period.toString()));
+ }
+
+ public String getResponse() {
+ return "All tasks for the next " + this.getArgs().get(2) + " days: " + System.lineSeparator() +
+ this.getArgs().get(1);
+ }
+}
diff --git a/src/main/java/duke/command/taskcommand/taskquery/CommandProjectionNotDone.java b/src/main/java/duke/command/taskcommand/taskquery/CommandProjectionNotDone.java
new file mode 100644
index 00000000..67aaafb6
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskquery/CommandProjectionNotDone.java
@@ -0,0 +1,21 @@
+package duke.command.taskcommand.taskquery;
+
+import static duke.dukeutility.prettify.Prettify.prettifyTasks;
+
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandProjectionNotDone extends Command {
+ public CommandProjectionNotDone(TaskManager taskMgr, Integer period) {
+ super(ResponseType.TASK_PROJECTION_NOT_DONE,
+ List.of("list", prettifyTasks(taskMgr.getTasksForNextDaysNotDone(period)), period.toString()));
+ }
+
+ public String getResponse() {
+ return "Incomplete tasks for the next " + this.getArgs().get(2) + " days: " + System.lineSeparator() +
+ this.getArgs().get(1);
+ }
+}
diff --git a/src/main/java/duke/command/taskcommand/taskquery/CommandScanDuplicateDescriptions.java b/src/main/java/duke/command/taskcommand/taskquery/CommandScanDuplicateDescriptions.java
new file mode 100644
index 00000000..b6d3fd67
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskquery/CommandScanDuplicateDescriptions.java
@@ -0,0 +1,21 @@
+package duke.command.taskcommand.taskquery;
+
+import static duke.dukeutility.prettify.Prettify.getScanDuplicatesDescription;
+
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandScanDuplicateDescriptions extends Command {
+ public CommandScanDuplicateDescriptions(TaskManager taskMgr) {
+ super(ResponseType.SCAN_DUPLICATE_DESCRIPTION,
+ List.of("stat", getScanDuplicatesDescription(taskMgr.getDuplicateDescriptionsAsArray())));
+ }
+
+ public String getResponse() {
+ return "Duplicates \"[Description]\":[...(id,type)] " + System.lineSeparator() +
+ this.getArgs().get(1);
+ }
+}
diff --git a/src/main/java/duke/command/taskcommand/taskquery/CommandStatsAll.java b/src/main/java/duke/command/taskcommand/taskquery/CommandStatsAll.java
new file mode 100644
index 00000000..70c3a95b
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskquery/CommandStatsAll.java
@@ -0,0 +1,19 @@
+package duke.command.taskcommand.taskquery;
+
+import static duke.dukeutility.prettify.Prettify.getStatisticsAll;
+
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandStatsAll extends Command {
+ public CommandStatsAll(TaskManager taskMgr) {
+ super(ResponseType.TASK_STATS_ALL, List.of("stat", getStatisticsAll(taskMgr.getAllAsArray())));
+ }
+
+ public String getResponse() {
+ return "Task Summary " + System.lineSeparator() + this.getArgs().get(1);
+ }
+}
diff --git a/src/main/java/duke/command/taskcommand/taskupdate/CommandDeleteTask.java b/src/main/java/duke/command/taskcommand/taskupdate/CommandDeleteTask.java
new file mode 100644
index 00000000..1f9888b6
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskupdate/CommandDeleteTask.java
@@ -0,0 +1,25 @@
+package duke.command.taskcommand.taskupdate;
+
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+
+public class CommandDeleteTask extends Command {
+ /**
+ * Delete a task by id of task manager
+ *
+ * @param taskMgr task manager to delete task from.
+ * @param id of task
+ */
+ public CommandDeleteTask(TaskManager taskMgr, Integer id) {
+ super(ResponseType.TASK_DELETE_TASK,
+ List.of("delete", id.toString(), taskMgr.deleteTaskById(id).toString()));
+ }
+
+ public String getResponse() {
+ return "Task Deleted: #" + this.getArgs().get(1) + System.lineSeparator();
+ }
+}
diff --git a/src/main/java/duke/command/taskcommand/taskupdate/CommandMarkTaskAsDone.java b/src/main/java/duke/command/taskcommand/taskupdate/CommandMarkTaskAsDone.java
new file mode 100644
index 00000000..eabb409b
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskupdate/CommandMarkTaskAsDone.java
@@ -0,0 +1,24 @@
+package duke.command.taskcommand.taskupdate;
+
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandMarkTaskAsDone extends Command {
+ /**
+ * get task by id in task manager and set task as done
+ *
+ * @param taskMgr task manager
+ * @param taskId id of task
+ */
+ public CommandMarkTaskAsDone(TaskManager taskMgr, Integer taskId) {
+ super(ResponseType.TASK_UPDATE_COMPLETE,
+ List.of("update", "done", "#" + taskMgr.getTaskByIdAndSetCompleted(taskId).getTaskId().toString()));
+ }
+
+ public String getResponse() {
+ return String.join(" ", this.getArgs()) + System.lineSeparator();
+ }
+}
diff --git a/src/main/java/duke/command/taskcommand/taskupdate/CommandMarkTaskAsIncomplete.java b/src/main/java/duke/command/taskcommand/taskupdate/CommandMarkTaskAsIncomplete.java
new file mode 100644
index 00000000..12300a89
--- /dev/null
+++ b/src/main/java/duke/command/taskcommand/taskupdate/CommandMarkTaskAsIncomplete.java
@@ -0,0 +1,24 @@
+package duke.command.taskcommand.taskupdate;
+
+import java.util.List;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+
+public class CommandMarkTaskAsIncomplete extends Command {
+ /**
+ * get task by id in task manager and set task as done
+ *
+ * @param taskMgr task manager
+ * @param taskId id of task
+ */
+ public CommandMarkTaskAsIncomplete(TaskManager taskMgr, Integer taskId) {
+ super(ResponseType.TASK_UPDATE_INCOMPLETE,
+ List.of("update", "not done", "#" + taskMgr.getTaskByIdAndSetIncomplete(taskId).getTaskId().toString()));
+ }
+
+ public String getResponse() {
+ return String.join(" ", this.getArgs()) + System.lineSeparator();
+ }
+}
diff --git a/src/main/java/duke/dukeexception/DukeException.java b/src/main/java/duke/dukeexception/DukeException.java
new file mode 100644
index 00000000..c1908d40
--- /dev/null
+++ b/src/main/java/duke/dukeexception/DukeException.java
@@ -0,0 +1,7 @@
+package duke.dukeexception;
+
+public abstract class DukeException extends Exception {
+ protected DukeException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/duke/dukeexception/DukeInvalidSyntaxException.java b/src/main/java/duke/dukeexception/DukeInvalidSyntaxException.java
new file mode 100644
index 00000000..27de10be
--- /dev/null
+++ b/src/main/java/duke/dukeexception/DukeInvalidSyntaxException.java
@@ -0,0 +1,7 @@
+package duke.dukeexception;
+
+public class DukeInvalidSyntaxException extends DukeException {
+ public DukeInvalidSyntaxException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/duke/dukeexception/DukeParseDateTimeException.java b/src/main/java/duke/dukeexception/DukeParseDateTimeException.java
new file mode 100644
index 00000000..92a7412e
--- /dev/null
+++ b/src/main/java/duke/dukeexception/DukeParseDateTimeException.java
@@ -0,0 +1,7 @@
+package duke.dukeexception;
+
+public class DukeParseDateTimeException extends DukeException {
+ public DukeParseDateTimeException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/duke/dukeutility/Helper.java b/src/main/java/duke/dukeutility/Helper.java
new file mode 100644
index 00000000..bf3f0b2b
--- /dev/null
+++ b/src/main/java/duke/dukeutility/Helper.java
@@ -0,0 +1,18 @@
+package duke.dukeutility;
+
+public class Helper {
+
+ /**
+ * Helper to combine array of strings.
+ *
+ * @param commands
+ * @return
+ */
+ public static String buildString(String... commands) {
+ StringBuilder commandBuilder = new StringBuilder();
+ for (String c : commands) {
+ commandBuilder.append(c);
+ }
+ return commandBuilder.toString();
+ }
+}
diff --git a/src/main/java/duke/dukeutility/config/DukeIo.java b/src/main/java/duke/dukeutility/config/DukeIo.java
new file mode 100644
index 00000000..696fe213
--- /dev/null
+++ b/src/main/java/duke/dukeutility/config/DukeIo.java
@@ -0,0 +1,28 @@
+package duke.dukeutility.config;
+
+
+import java.io.File;
+
+public class DukeIo {
+ public static final String RESOURCE_PATH = System.getProperty("user.home") + File.separator + "duke";
+
+ private static String pathStringDefaultTasksExportJsonPath = null;
+ private static String pathStringDefaultTasksImportPath = null;
+
+ public static String getDefaultTasksImportPathString() {
+ if (DukeIo.pathStringDefaultTasksImportPath == null) {
+ DukeIo.pathStringDefaultTasksImportPath = RESOURCE_PATH + File.separator + "tasks.json";
+ }
+ return DukeIo.pathStringDefaultTasksImportPath;
+
+ }
+
+ public static String getDefaultTasksExportPathString() {
+ if (DukeIo.pathStringDefaultTasksExportJsonPath == null) {
+ DukeIo.pathStringDefaultTasksExportJsonPath = RESOURCE_PATH + File.separator + "tasks.json";
+ }
+ return DukeIo.pathStringDefaultTasksExportJsonPath;
+ }
+}
+
+
diff --git a/src/main/java/duke/dukeutility/definition/CommandPromptsAndOptions.java b/src/main/java/duke/dukeutility/definition/CommandPromptsAndOptions.java
new file mode 100644
index 00000000..3b68447c
--- /dev/null
+++ b/src/main/java/duke/dukeutility/definition/CommandPromptsAndOptions.java
@@ -0,0 +1,28 @@
+package duke.dukeutility.definition;
+
+public class CommandPromptsAndOptions {
+ public static final String PROMPT_ADD_TODO = "todo ";
+
+ public static final String PROMPT_ADD_DEADLINE = "deadline ";
+ public static final String ADD_DEADLINE_DEADLINE_DELIMITER = " /by ";
+
+ public static final String PROMPT_ADD_EVENT = "event ";
+ public static final String ADD_EVENT_SCHEDULE_DELIMITER = " /at ";
+
+ public static final String PROMPT_LIST = "list";
+ public static final String PROMPT_STATISTICS_ALL = "stats:all";
+ public static final String PROMPT_LIST_ONE = "see ";
+ public static final String PROMPT_PROJECTION_ALL = "projection ";
+ public static final String PROMPT_PROJECTION_NOT_DONE = "projection:yet ";
+ public static final String PROMPT_UPDATE_DONE = "done ";
+ public static final String PROMPT_UPDATE_NOT_DONE = "undone ";
+
+ public static final String PROMPT_EXIT_LOOP = "bye";
+
+ public static final String PROMPT_DELETE_TASK = "delete ";
+
+ public static final String PROMPT_SAVE = "save";
+
+ public static final String PROMPT_FIND_BY_KEYWORD_DESCRIPTION = "find ";
+ public static final String PROMPT_SCAN_DUPLICATE_DESCRIPTION = "scan:duplicates";
+}
diff --git a/src/main/java/duke/dukeutility/definition/TaskField.java b/src/main/java/duke/dukeutility/definition/TaskField.java
new file mode 100644
index 00000000..3c5acbaa
--- /dev/null
+++ b/src/main/java/duke/dukeutility/definition/TaskField.java
@@ -0,0 +1,11 @@
+package duke.dukeutility.definition;
+
+public class TaskField {
+ public static final String TASK_FIELD_TYPE = "type";
+ public static final String TASK_FIELD_TASK_ID = "taskId";
+ public static final String TASK_FIELD_DESCRIPTION = "description";
+ public static final String TASK_FIELD_DEADLINE = "deadline";
+ public static final String TASK_FIELD_FROM = "from";
+ public static final String TASK_FIELD_TO = "to";
+ public static final String TASK_FIELD_DONE_STATUS = "done";
+}
diff --git a/src/main/java/duke/dukeutility/enums/JsonTaskType.java b/src/main/java/duke/dukeutility/enums/JsonTaskType.java
new file mode 100644
index 00000000..c6a79568
--- /dev/null
+++ b/src/main/java/duke/dukeutility/enums/JsonTaskType.java
@@ -0,0 +1,5 @@
+package duke.dukeutility.enums;
+
+public enum JsonTaskType {
+ ToDo, Deadline, Event
+}
diff --git a/src/main/java/duke/dukeutility/enums/ResponseType.java b/src/main/java/duke/dukeutility/enums/ResponseType.java
new file mode 100644
index 00000000..40769897
--- /dev/null
+++ b/src/main/java/duke/dukeutility/enums/ResponseType.java
@@ -0,0 +1,36 @@
+package duke.dukeutility.enums;
+
+/**
+ * @see duke.command.Command
+ */
+public enum ResponseType {
+ ECHO,
+ EXIT_LOOP,
+ ERROR_COMMAND_EXECUTION,
+ ERROR_REQUEST_INVALID_PARAMETERS,
+ ERROR_REQUEST_INVALID_SYNTAX,
+ ERROR_REQUEST_UNKNOWN,
+ ERROR_INVALID_READ_FILE_PATH,
+ EXPORT_IN_PROGRESS,
+ FILE_SAVED,
+ FILE_SAVED_IO_ERROR,
+ FILE_READ,
+ SCAN_DUPLICATE_DESCRIPTION,
+ TASK_CREATING_IN_PROGRESS,
+ TASK_CREATE_TODO,
+ TASK_CREATE_DEADLINE,
+ TASK_CREATE_EVENT,
+ TASK_DELETE_TASK,
+ TASK_LIST_ALL,
+ TASK_LIST_FIND,
+ TASK_LIST_ONE,
+ TASK_STATS_ALL,
+ TASK_PROJECTION_ALL,
+ TASK_PROJECTION_NOT_DONE,
+ TASK_IMPORT_TODO,
+ TASK_IMPORT_EVENT,
+ TASK_IMPORT_DEADLINE,
+ TASK_UPDATE_COMPLETE,
+ TASK_UPDATE_INCOMPLETE,
+ TASK_NOT_FOUND,
+}
diff --git a/src/main/java/duke/dukeutility/parser/DateParser.java b/src/main/java/duke/dukeutility/parser/DateParser.java
new file mode 100644
index 00000000..3d70a9b0
--- /dev/null
+++ b/src/main/java/duke/dukeutility/parser/DateParser.java
@@ -0,0 +1,54 @@
+package duke.dukeutility.parser;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+
+import duke.dukeexception.DukeParseDateTimeException;
+
+public class DateParser {
+ private static final String transitiveJsonAndTextPattern = "yyyy-MM-dd-HH-mm-ss";
+ private static final List patterns =
+ List.of("yyyyMMdd", "yyyyMMdd HH:mm", DateParser.transitiveJsonAndTextPattern);
+
+ public static String parseLocalDateTimeAsString(LocalDateTime ldt) {
+ return DateTimeFormatter.ofPattern(DateParser.transitiveJsonAndTextPattern).format(ldt);
+ }
+
+ /**
+ * format string as LocalDateTime
+ *
+ * @param dateTimeString
+ * @return date in LocalDateTime format.
+ * @throws DukeParseDateTimeException Formatting failed
+ */
+ public static LocalDateTime parseStringAsLocalDateTime(String dateTimeString) throws DukeParseDateTimeException {
+
+ LocalDateTime ldt = null;
+ for (String pattern : DateParser.patterns) {
+ try {
+ ldt = LocalDateTime.parse(dateTimeString, DateTimeFormatter.ofPattern(pattern));
+ } catch (Exception e) {
+ }
+ }
+
+ try {
+ ldt = parseStringAsLocalDate(dateTimeString).atTime(0, 0);
+ } catch (Exception e) {
+ }
+ if (ldt == null) {
+ throw new DukeParseDateTimeException(
+ "Date should be of the following format: " + String.join(", ", patterns));
+ }
+ return ldt;
+ }
+
+ public static LocalDate parseStringAsLocalDate(String dateString) {
+ return LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyyMMdd"));
+ }
+
+ public static String prettifyLocalDateTime(LocalDateTime ldt) {
+ return ldt.toString().replace("T", " ");
+ }
+}
diff --git a/src/main/java/duke/dukeutility/parser/JsonTaskToObjectParser.java b/src/main/java/duke/dukeutility/parser/JsonTaskToObjectParser.java
new file mode 100644
index 00000000..18de346e
--- /dev/null
+++ b/src/main/java/duke/dukeutility/parser/JsonTaskToObjectParser.java
@@ -0,0 +1,84 @@
+package duke.dukeutility.parser;
+
+import static duke.dukeutility.definition.TaskField.TASK_FIELD_DEADLINE;
+import static duke.dukeutility.definition.TaskField.TASK_FIELD_DESCRIPTION;
+import static duke.dukeutility.definition.TaskField.TASK_FIELD_DONE_STATUS;
+import static duke.dukeutility.definition.TaskField.TASK_FIELD_FROM;
+import static duke.dukeutility.definition.TaskField.TASK_FIELD_TASK_ID;
+import static duke.dukeutility.definition.TaskField.TASK_FIELD_TO;
+import static duke.dukeutility.parser.DateParser.parseStringAsLocalDateTime;
+import static duke.dukeutility.validator.JsonObjectValidator.isJsonTypeDeadline;
+import static duke.dukeutility.validator.JsonObjectValidator.isJsonTypeEvent;
+import static duke.dukeutility.validator.JsonObjectValidator.isJsonTypeToDo;
+import static duke.dukeutility.validator.JsonObjectValidator.isNotNullJsonPropertyTaskType;
+
+import java.time.LocalDateTime;
+
+import com.google.gson.JsonObject;
+
+import duke.task.model.Deadline;
+import duke.task.model.Event;
+import duke.task.model.Task;
+import duke.task.model.ToDo;
+
+public class JsonTaskToObjectParser extends Parser {
+ private JsonTaskToObjectParser() {
+ }
+
+ /**
+ * Converts a JSON formatted task to POJO.
+ *
+ * @param jsonObj task
+ * @return task object
+ * @throws Exception if not recognised as a task
+ */
+ public static Task jsonTaskToPojo(JsonObject jsonObj) throws Exception {
+ if (!isNotNullJsonPropertyTaskType(jsonObj)) {
+ throw new Exception("No task type");
+ } else if (isJsonTypeToDo(jsonObj)) {
+ Integer taskId = getJsonPropertyTaskId(jsonObj);
+ String taskDescription = getJsonPropertyTaskDescription(jsonObj);
+ Boolean done = getJsonPropertyDoneStatus(jsonObj);
+ return new ToDo(taskDescription, taskId, done);
+ } else if (isJsonTypeDeadline(jsonObj)) {
+ Integer taskId = getJsonPropertyTaskId(jsonObj);
+ String taskDescription = getJsonPropertyTaskDescription(jsonObj);
+ Boolean done = getJsonPropertyDoneStatus(jsonObj);
+ LocalDateTime deadline = getJsonPropertyDeadline(jsonObj);
+ return new Deadline(taskDescription, deadline, taskId, done);
+ } else if (isJsonTypeEvent(jsonObj)) {
+ Integer taskId = getJsonPropertyTaskId(jsonObj);
+ String taskDescription = getJsonPropertyTaskDescription(jsonObj);
+ Boolean done = getJsonPropertyDoneStatus(jsonObj);
+ LocalDateTime from = getJsonPropertyFrom(jsonObj);
+ LocalDateTime to = getJsonPropertyTo(jsonObj);
+ return new Event(taskDescription, from, to, taskId, done);
+ }
+ throw new Exception("Json object not recognised as a task Object");
+ }
+
+
+ public static Boolean getJsonPropertyDoneStatus(JsonObject jsonObj) {
+ return jsonObj.get(TASK_FIELD_DONE_STATUS).getAsBoolean();
+ }
+
+ public static String getJsonPropertyTaskDescription(JsonObject jsonObj) {
+ return jsonObj.get(TASK_FIELD_DESCRIPTION).getAsString();
+ }
+
+ public static LocalDateTime getJsonPropertyDeadline(JsonObject jsonObj) throws Exception {
+ return parseStringAsLocalDateTime(jsonObj.get(TASK_FIELD_DEADLINE).getAsString());
+ }
+
+ public static LocalDateTime getJsonPropertyFrom(JsonObject jsonObj) throws Exception {
+ return parseStringAsLocalDateTime(jsonObj.get(TASK_FIELD_FROM).getAsString());
+ }
+
+ public static LocalDateTime getJsonPropertyTo(JsonObject jsonObj) throws Exception {
+ return parseStringAsLocalDateTime(jsonObj.get(TASK_FIELD_TO).getAsString());
+ }
+
+ public static Integer getJsonPropertyTaskId(JsonObject jsonObj) {
+ return jsonObj.get(TASK_FIELD_TASK_ID).getAsInt();
+ }
+}
diff --git a/src/main/java/duke/dukeutility/parser/Parser.java b/src/main/java/duke/dukeutility/parser/Parser.java
new file mode 100644
index 00000000..1cd73ac3
--- /dev/null
+++ b/src/main/java/duke/dukeutility/parser/Parser.java
@@ -0,0 +1,6 @@
+package duke.dukeutility.parser;
+
+public class Parser {
+ protected Parser() {
+ }
+}
diff --git a/src/main/java/duke/dukeutility/parser/PathParser.java b/src/main/java/duke/dukeutility/parser/PathParser.java
new file mode 100644
index 00000000..2aef343f
--- /dev/null
+++ b/src/main/java/duke/dukeutility/parser/PathParser.java
@@ -0,0 +1,18 @@
+package duke.dukeutility.parser;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class PathParser extends Parser {
+
+ /**
+ * Helper for parsing string as path
+ */
+ public static Path stringToPath(String pathString) {
+ try {
+ return Paths.get(pathString);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/duke/dukeutility/parser/TaskToJsonParser.java b/src/main/java/duke/dukeutility/parser/TaskToJsonParser.java
new file mode 100644
index 00000000..221f67d0
--- /dev/null
+++ b/src/main/java/duke/dukeutility/parser/TaskToJsonParser.java
@@ -0,0 +1,73 @@
+package duke.dukeutility.parser;
+
+import static duke.dukeutility.definition.TaskField.TASK_FIELD_DEADLINE;
+import static duke.dukeutility.definition.TaskField.TASK_FIELD_DESCRIPTION;
+import static duke.dukeutility.definition.TaskField.TASK_FIELD_DONE_STATUS;
+import static duke.dukeutility.definition.TaskField.TASK_FIELD_FROM;
+import static duke.dukeutility.definition.TaskField.TASK_FIELD_TASK_ID;
+import static duke.dukeutility.definition.TaskField.TASK_FIELD_TO;
+import static duke.dukeutility.definition.TaskField.TASK_FIELD_TYPE;
+import static duke.dukeutility.parser.DateParser.parseLocalDateTimeAsString;
+
+import com.google.gson.JsonObject;
+
+import duke.dukeutility.enums.JsonTaskType;
+import duke.task.model.Deadline;
+import duke.task.model.Event;
+import duke.task.model.ToDo;
+
+
+public class TaskToJsonParser extends Parser {
+
+ private TaskToJsonParser() {
+ }
+
+ /**
+ * Format event as JSON
+ *
+ * @param event
+ * @return event as JSON
+ */
+ public static JsonObject parseEventAsJson(Event event) {
+ JsonObject obj = new JsonObject();
+ obj.addProperty(TASK_FIELD_TYPE, JsonTaskType.Event.toString());
+ obj.addProperty(TASK_FIELD_TASK_ID, event.getTaskId());
+ obj.addProperty(TASK_FIELD_DESCRIPTION, event.getTaskDescription());
+ obj.addProperty(TASK_FIELD_DONE_STATUS, event.isDone());
+ obj.addProperty(TASK_FIELD_FROM, parseLocalDateTimeAsString(event.getFrom()));
+ obj.addProperty(TASK_FIELD_TO, parseLocalDateTimeAsString(event.getTo()));
+ return obj;
+ }
+
+
+ /**
+ * Format deadline as JSON
+ *
+ * @param deadline
+ * @return deadline as JSON
+ */
+ public static JsonObject parseDeadlineAsJson(Deadline deadline) {
+ JsonObject obj = new JsonObject();
+ obj.addProperty(TASK_FIELD_TYPE, JsonTaskType.Deadline.toString());
+ obj.addProperty(TASK_FIELD_TASK_ID, deadline.getTaskId());
+ obj.addProperty(TASK_FIELD_DESCRIPTION, deadline.getTaskDescription());
+ obj.addProperty(TASK_FIELD_DONE_STATUS, deadline.isDone());
+ obj.addProperty(TASK_FIELD_DEADLINE, parseLocalDateTimeAsString(deadline.getDeadline()));
+ return obj;
+ }
+
+ /**
+ * Format toDo as JSON
+ *
+ * @param toDo
+ * @return toDo as JSON
+ */
+ public static JsonObject parseToDoAsJson(ToDo toDo) {
+ JsonObject obj = new JsonObject();
+ obj.addProperty(TASK_FIELD_TYPE, JsonTaskType.ToDo.toString());
+ obj.addProperty(TASK_FIELD_TASK_ID, toDo.getTaskId());
+ obj.addProperty(TASK_FIELD_DESCRIPTION, toDo.getTaskDescription());
+ obj.addProperty(TASK_FIELD_DONE_STATUS, toDo.isDone());
+ return obj;
+ }
+}
diff --git a/src/main/java/duke/dukeutility/prettify/Prettify.java b/src/main/java/duke/dukeutility/prettify/Prettify.java
new file mode 100644
index 00000000..e5f09e41
--- /dev/null
+++ b/src/main/java/duke/dukeutility/prettify/Prettify.java
@@ -0,0 +1,216 @@
+package duke.dukeutility.prettify;
+
+import static duke.dukeutility.Helper.buildString;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+
+import duke.TaskManager;
+import duke.task.model.Deadline;
+import duke.task.model.Event;
+import duke.task.model.Task;
+import duke.task.model.ToDo;
+
+public class Prettify {
+
+ private static char getTaskTypeSymbol(Task t) {
+ return t.getClass().getSimpleName().charAt(0);
+ }
+
+ private static String fillCell(String value, Integer lengthColMax) {
+ int lengthValue = value.length();
+ int lengthPad = lengthColMax - lengthValue;
+ return String.format("%s%s", value,
+ String.format("%" + (lengthPad > 0 ? lengthPad : "") + "s", (lengthPad > 0 ? " " : "")));
+ }
+
+ /**
+ * Generates All Tasks as String
+ * Column widths are inherited from header columns.
+ *
+ * @return String
+ */
+ public static String prettifyTaskMgr(TaskManager taskMgr) {
+ ArrayList tl = taskMgr.getAllAsArray();
+ return prettifyTasks(tl);
+
+ }
+
+ /**
+ * Present an array of tasks.
+ *
+ * @param tl
+ * @return
+ */
+ public static String prettifyTasks(ArrayList tl) {
+
+ StringBuilder generating = new StringBuilder();
+ // Title
+ int taskQty = tl.size();
+ generating.append((taskQty + " task" + (taskQty > 1 ? "s" : "") + " in list" + System.lineSeparator()));
+
+ // Header Values
+
+ String headerId = String.format(" %-4s ", "id#");
+ String headerDoneStatus = "Done ";
+ String headerTaskType = "Type ";
+ String headerDescription = "Task Description ";
+ String headerChronology = "Chronology";
+
+ generating.append(buildString(headerId, headerDoneStatus, headerTaskType, headerDescription, headerChronology,
+ System.lineSeparator()));
+
+ /* column width references */
+
+ int lengthColId = headerId.length();
+ int lengthColTaskType = headerTaskType.length();
+ int lengthColDoneStatus = headerDoneStatus.length();
+ int lengthColDesc = headerDescription.length();
+
+ // Body Values
+ for (Task t : tl) {
+ // fill column Id
+ String idValue = String.format("%4d", t.getTaskId()).replace(" ", "0");
+ String id = fillCell(idValue, lengthColId);
+ // fill column Done Status
+ String doneStatusValue = String.format("[%s]", t.isDone() ? "X" : " ");
+ String doneStatus = fillCell(doneStatusValue, lengthColDoneStatus);
+ // fill column Task Type Status
+ String taskTypeSymbolValue = String.format("[%s]", getTaskTypeSymbol(t));
+ String type = fillCell(taskTypeSymbolValue, lengthColTaskType);
+ // fill column Description
+ String descValueLong = t.getTaskDescription();
+ String descValue = descValueLong.substring(0, Math.min(descValueLong.length(), lengthColDesc - 1));
+ String desc = fillCell(descValue, lengthColDesc);
+ // fill column Chronology
+ String chronology = t.getChronologyString();
+
+ String line = buildString(id, doneStatus, type, desc, chronology, System.lineSeparator());
+ generating.append(line);
+ }
+ return generating.toString();
+ }
+
+ public static String getStatisticsAll(ArrayList tasks) {
+ // Tabulate
+ int col = 0;
+ int colDone = col++;
+ int colNotDone = col++;
+ int row = 0;
+ int rowToDo = row++;
+ int rowDeadline = row++;
+ int rowEvent = row++;
+
+
+ Integer[][] stats = new Integer[col][row];
+ for (Integer[] ints : stats) {
+ Arrays.fill(ints, 0);
+ }
+ for (Task t : tasks) {
+
+ Integer thisRow = null;
+ if (t instanceof ToDo) {
+ thisRow = rowToDo;
+ } else if (t instanceof Deadline) {
+ thisRow = rowDeadline;
+ } else if (t instanceof Event) {
+ thisRow = rowEvent;
+ }
+ Integer thisCol = null;
+ if (t.isDone()) {
+ thisCol = colDone;
+ } else {
+ thisCol = colNotDone;
+ }
+ assert (thisCol != null);
+ assert (thisRow != null);
+ if (thisCol != null && thisRow != null) {
+ stats[thisCol][thisRow]++;
+ }
+ }
+ int rowHeader = row++;
+ int colTaskType = col++;
+ String[][] table = new String[col][row];
+ for (String[] tableRow : table) {
+ Arrays.fill(tableRow, "");
+ }
+ table[0][rowHeader] = "Task Type ";
+ table[0][rowToDo] = "To Do";
+ table[0][rowDeadline] = "Deadline";
+ table[0][rowEvent] = "Event";
+
+ table[2][rowHeader] = "Incomplete ";
+ table[2][rowToDo] = stats[colNotDone][rowToDo].toString();
+ table[2][rowDeadline] = stats[colNotDone][rowDeadline].toString();
+ table[2][rowEvent] = stats[colNotDone][rowEvent].toString();
+
+ table[1][rowHeader] = "Complete ";
+ table[1][rowToDo] = stats[colDone][rowToDo].toString();
+ table[1][rowDeadline] = stats[colDone][rowDeadline].toString();
+ table[1][rowEvent] = stats[colDone][rowEvent].toString();
+
+
+ int[] colLength = new int[col];
+
+ colLength[colTaskType] = getMaxLength(table[colTaskType]);
+ colLength[colNotDone] = getMaxLength(table[colNotDone]);
+ colLength[colDone] = getMaxLength(table[colDone]);
+
+
+ for (int c = 0; c < col; c++) {
+ for (int r = 0; r < row; r++) {
+ table[c][r] = fillCell(table[c][r], colLength[c]);
+ }
+ }
+ StringBuilder lines = new StringBuilder();
+
+ lines.append(String.join("", getRowValue(table, rowHeader)) + System.lineSeparator());
+ lines.append(String.join("", getRowValue(table, rowToDo)) + System.lineSeparator());
+ lines.append(String.join("", getRowValue(table, rowDeadline)) + System.lineSeparator());
+ lines.append(String.join("", getRowValue(table, rowEvent)) + System.lineSeparator());
+ return lines.toString();
+ }
+
+ private static String getRowValue(String[][] table, int r) {
+ StringBuilder result = new StringBuilder();
+ for (int c = 0; c < table.length; c++) {
+ result.append(table[c][r]);
+ }
+ return result.toString();
+ }
+
+ private static int getMaxLength(String[] strings) {
+ int maxLength = 0;
+ for (String s : strings) {
+ maxLength = Math.max(maxLength, s.length());
+ }
+ return maxLength;
+
+ }
+
+ public static String getScanDuplicatesDescription(HashMap> descMap) {
+
+
+ StringBuilder result = new StringBuilder();
+
+ descMap.forEach((desc, dupe) -> result.append(
+ "\"" + desc + "\"" + ": " + stringifyTaskIdAndType(dupe) + System.lineSeparator()));
+ return result.toString();
+ }
+
+ public static String stringifyTaskIdAndType(ArrayList tasks) {
+ StringBuilder result = new StringBuilder();
+ result.append("[");
+ int size = tasks.size();
+ for (int i = 0; i < size; i++) {
+ Task task = tasks.get(i);
+ result.append(task.getTaskId().toString() + " (" + getTaskTypeSymbol(task) + ")");
+ if (i != size - 1) {
+ result.append(", ");
+ }
+ }
+ result.append("]");
+ return result.toString();
+ }
+}
diff --git a/src/main/java/duke/dukeutility/validator/JsonObjectValidator.java b/src/main/java/duke/dukeutility/validator/JsonObjectValidator.java
new file mode 100644
index 00000000..1805846d
--- /dev/null
+++ b/src/main/java/duke/dukeutility/validator/JsonObjectValidator.java
@@ -0,0 +1,37 @@
+package duke.dukeutility.validator;
+
+import static duke.dukeutility.definition.TaskField.TASK_FIELD_TYPE;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import duke.dukeutility.enums.JsonTaskType;
+
+public class JsonObjectValidator {
+
+ public static Boolean isNotNullJsonPropertyTaskType(JsonObject jsonObj) {
+ return jsonObj.has(TASK_FIELD_TYPE);
+ }
+
+ private static Boolean isJsonTypeOf(JsonObject jsonObj, JsonTaskType enumVal) {
+ JsonElement elementTaskType = jsonObj.get(TASK_FIELD_TYPE);
+ String taskType = elementTaskType.getAsString();
+ try {
+ return JsonTaskType.valueOf(taskType) == enumVal;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ public static Boolean isJsonTypeToDo(JsonObject jsonObj) {
+ return isJsonTypeOf(jsonObj, JsonTaskType.ToDo);
+ }
+
+ public static Boolean isJsonTypeDeadline(JsonObject jsonObj) {
+ return isJsonTypeOf(jsonObj, JsonTaskType.Deadline);
+ }
+
+ public static Boolean isJsonTypeEvent(JsonObject jsonObj) {
+ return isJsonTypeOf(jsonObj, JsonTaskType.Event);
+ }
+}
diff --git a/src/main/java/duke/dukeutility/validator/StringValidator.java b/src/main/java/duke/dukeutility/validator/StringValidator.java
new file mode 100644
index 00000000..0fbaeb24
--- /dev/null
+++ b/src/main/java/duke/dukeutility/validator/StringValidator.java
@@ -0,0 +1,17 @@
+package duke.dukeutility.validator;
+
+
+public class StringValidator {
+
+ public static Boolean isSubstring(String sentence, String keyword) {
+
+ String[] words = sentence.split("\\s+");
+ for (String word : words) {
+ if (word.equals(keyword)) {
+ return true;
+ }
+ }
+ return false;
+
+ }
+}
diff --git a/src/main/java/duke/dukeutility/validator/TextCommandValidator.java b/src/main/java/duke/dukeutility/validator/TextCommandValidator.java
new file mode 100644
index 00000000..4bf441f4
--- /dev/null
+++ b/src/main/java/duke/dukeutility/validator/TextCommandValidator.java
@@ -0,0 +1,89 @@
+package duke.dukeutility.validator;
+
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_ADD_DEADLINE;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_ADD_EVENT;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_ADD_TODO;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_DELETE_TASK;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_EXIT_LOOP;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_FIND_BY_KEYWORD_DESCRIPTION;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_LIST;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_LIST_ONE;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_PROJECTION_ALL;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_PROJECTION_NOT_DONE;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_SAVE;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_SCAN_DUPLICATE_DESCRIPTION;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_STATISTICS_ALL;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_UPDATE_DONE;
+import static duke.dukeutility.definition.CommandPromptsAndOptions.PROMPT_UPDATE_NOT_DONE;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * Text Command Validation methods
+ */
+public class TextCommandValidator {
+ public static Boolean isRequestExitLoop(String text) {
+ return text.equals(PROMPT_EXIT_LOOP);
+ }
+
+ public static Boolean isRequestList(String text) {
+ return text.equals(PROMPT_LIST);
+ }
+
+ public static Boolean isRequestStatisticsAll(String text) {
+ return text.equals(PROMPT_STATISTICS_ALL);
+ }
+
+ public static Boolean isRequestMarkTaskAsDone(String text) {
+ return text.startsWith(PROMPT_UPDATE_DONE);
+ }
+
+ public static Boolean isRequestMarkTaskAsIncomplete(String text) {
+ return text.startsWith(PROMPT_UPDATE_NOT_DONE);
+ }
+
+ public static Boolean isRequestScanDuplicates(String text) {
+ return text.equals(PROMPT_SCAN_DUPLICATE_DESCRIPTION);
+ }
+
+ public static Boolean isRequestAddToDo(String text) {
+ return text.startsWith(PROMPT_ADD_TODO);
+ }
+
+ public static Boolean isRequestAddDeadline(String text) {
+ return text.startsWith(PROMPT_ADD_DEADLINE);
+ }
+
+ public static Boolean isRequestAddEvent(String text) {
+ return text.startsWith(PROMPT_ADD_EVENT);
+ }
+
+ public static Boolean isRequestDeleteTask(String text) {
+ return text.startsWith(PROMPT_DELETE_TASK);
+ }
+
+ public static Boolean isRequestFind(String text) {
+ return text.startsWith(PROMPT_FIND_BY_KEYWORD_DESCRIPTION);
+ }
+
+ public static Boolean isRequestProjectionAll(String text) {
+ return text.startsWith(PROMPT_PROJECTION_ALL);
+ }
+
+ public static Boolean isRequestProjectionNotDone(String text) {
+ return text.startsWith(PROMPT_PROJECTION_NOT_DONE);
+ }
+
+ public static Boolean isParentDirectoryValid(Path p) {
+ return Files.exists(p.getParent());
+ }
+
+ public static Boolean isRequestSave(String text) {
+ return text.equals(PROMPT_SAVE);
+ }
+
+ public static Boolean isRequestSee(String text) {
+ return text.startsWith(PROMPT_LIST_ONE);
+ }
+}
diff --git a/src/main/java/duke/task/TaskComparator.java b/src/main/java/duke/task/TaskComparator.java
new file mode 100644
index 00000000..35f966b5
--- /dev/null
+++ b/src/main/java/duke/task/TaskComparator.java
@@ -0,0 +1,60 @@
+package duke.task;
+
+import java.time.LocalDate;
+
+import duke.task.model.Deadline;
+import duke.task.model.Event;
+import duke.task.model.Task;
+
+public class TaskComparator {
+
+ public static Boolean isSameDay(Task t, LocalDate targetDay) {
+ LocalDate tDate = null;
+ if (t instanceof Deadline) {
+ tDate = ((Deadline) t).getDeadline().toLocalDate();
+ } else if (t instanceof Event) {
+ tDate = ((Event) t).getFrom().toLocalDate();
+ }
+ return targetDay.equals(tDate);
+ }
+
+
+ public static LocalDate getStartDate(Task t) {
+ LocalDate tDate = null;
+ if (t instanceof Deadline) {
+ tDate = ((Deadline) t).getDeadline().toLocalDate();
+ } else if (t instanceof Event) {
+ tDate = ((Event) t).getFrom().toLocalDate();
+ }
+ return tDate;
+ }
+
+ public static Boolean isTaskWithinNextDays(Task t, Integer period) {
+ LocalDate today = LocalDate.now();
+ LocalDate finalDay = today.plusDays(period);
+ LocalDate tDate = getStartDate(t);
+ if (tDate == null) {
+ return false;
+ }
+ return !(tDate.isBefore(today) || tDate.isAfter(finalDay));
+ }
+
+ public static int compareTaskDate(Task a, Task b) {
+ LocalDate aDate = getStartDate(a);
+ LocalDate bDate = getStartDate(b);
+
+ if (aDate == null) {
+ aDate = LocalDate.MIN;
+ }
+ if (bDate == null) {
+ bDate = LocalDate.MIN;
+ }
+ if (aDate.isBefore(bDate)) {
+ return -1;
+ } else if (bDate.isAfter(aDate)) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+}
diff --git a/src/main/java/duke/task/aggregator/TaskList.java b/src/main/java/duke/task/aggregator/TaskList.java
new file mode 100644
index 00000000..cd9fee1a
--- /dev/null
+++ b/src/main/java/duke/task/aggregator/TaskList.java
@@ -0,0 +1,57 @@
+package duke.task.aggregator;
+
+import java.util.ArrayList;
+import java.util.concurrent.ConcurrentHashMap;
+
+import duke.task.model.Task;
+
+
+public class TaskList {
+ private final ConcurrentHashMap container = new ConcurrentHashMap<>();
+
+ public TaskList() {
+ }
+
+
+ public ConcurrentHashMap getContainer() {
+ return this.container;
+ }
+
+
+ public ArrayList getAllAsArray() {
+ return new ArrayList<>(this.getContainer().values());
+ }
+
+ private Integer getTaskKey(Task task) {
+ return task.getTaskId();
+ }
+
+ public void addTask(Task t) {
+ this.container.put(this.getTaskKey(t), t);
+ }
+
+ public Integer getSize() {
+ return this.getContainer().size();
+ }
+
+ public Boolean containsKey(Integer key) {
+ return this.getContainer().containsKey(key);
+ }
+
+ public Task getTaskById(Integer taskId) {
+ return this.getContainer().get(taskId);
+ }
+
+ /**
+ * Remove a task in a container by task id
+ *
+ * @param taskId
+ * @return
+ */
+ public Task removeTaskById(Integer taskId) {
+ Task task = this.getTaskById(taskId);
+ this.getContainer().remove(taskId);
+ return task;
+ }
+
+}
diff --git a/src/main/java/duke/task/model/Deadline.java b/src/main/java/duke/task/model/Deadline.java
new file mode 100644
index 00000000..013a9ff3
--- /dev/null
+++ b/src/main/java/duke/task/model/Deadline.java
@@ -0,0 +1,38 @@
+package duke.task.model;
+
+import static duke.dukeutility.parser.DateParser.prettifyLocalDateTime;
+
+import java.time.LocalDateTime;
+
+public final class Deadline extends Task {
+ private LocalDateTime deadline;
+
+ /**
+ * A deadline
+ *
+ * @param taskDescription
+ * @param deadline
+ * @param taskId
+ * @param done
+ */
+ public Deadline(String taskDescription, LocalDateTime deadline, Integer taskId, Boolean done) {
+ super(taskDescription, taskId, done);
+ this.setDeadline(deadline);
+ }
+
+ private Deadline() {
+ }
+
+ private void setDeadline(LocalDateTime deadline) {
+ this.deadline = deadline;
+ }
+
+ public LocalDateTime getDeadline() {
+ return this.deadline;
+ }
+
+
+ public String getChronologyString() {
+ return "By: " + prettifyLocalDateTime(this.getDeadline());
+ }
+}
diff --git a/src/main/java/duke/task/model/Event.java b/src/main/java/duke/task/model/Event.java
new file mode 100644
index 00000000..c43715fc
--- /dev/null
+++ b/src/main/java/duke/task/model/Event.java
@@ -0,0 +1,52 @@
+package duke.task.model;
+
+import static duke.dukeutility.parser.DateParser.prettifyLocalDateTime;
+
+import java.time.LocalDateTime;
+
+public final class Event extends Task {
+ private LocalDateTime from;
+ private LocalDateTime to;
+
+ /**
+ * An event.
+ *
+ * @param taskDescription
+ * @param from
+ * @param to
+ * @param taskId
+ * @param done
+ */
+ public Event(String taskDescription, LocalDateTime from, LocalDateTime to, Integer taskId, Boolean done) {
+ super(taskDescription, taskId, done);
+ this.setFrom(from);
+ this.setTo(to);
+ }
+
+ private Event() {
+ }
+
+ public LocalDateTime getTo() {
+ return this.to;
+ }
+
+ public LocalDateTime getFrom() {
+ return this.from;
+ }
+
+ private void setFrom(LocalDateTime from) {
+ this.from = from;
+ }
+
+ private void setTo(LocalDateTime to) {
+ this.to = to;
+ }
+
+ public String getChronologyString() {
+
+ return String.format("From: %s, To: %s", prettifyLocalDateTime(this.getFrom()),
+ prettifyLocalDateTime(this.getTo()));
+
+ }
+
+}
diff --git a/src/main/java/duke/task/model/Task.java b/src/main/java/duke/task/model/Task.java
new file mode 100644
index 00000000..3696ed38
--- /dev/null
+++ b/src/main/java/duke/task/model/Task.java
@@ -0,0 +1,53 @@
+package duke.task.model;
+
+
+/**
+ * Root class for tasks
+ */
+public abstract class Task implements Comparable {
+
+
+ private String taskDescription;
+ private Integer taskId;
+ private Boolean done;
+
+ protected Task() {
+ }
+
+ protected Task(String taskDescription, Integer taskId, Boolean done) {
+ this.setTaskDescription(taskDescription);
+ this.setTaskId(taskId);
+ this.setDoneStatus(done);
+ }
+
+ public String getTaskDescription() {
+ return this.taskDescription;
+ }
+
+ public void setTaskDescription(String taskDescription) {
+ this.taskDescription = taskDescription;
+ }
+
+ public Integer getTaskId() {
+ return this.taskId;
+ }
+
+ public void setTaskId(Integer taskId) {
+ this.taskId = taskId;
+ }
+
+ public Boolean isDone() {
+ return this.done;
+ }
+
+ public Boolean setDoneStatus(Boolean next) {
+ this.done = next;
+ return this.done;
+ }
+
+ public abstract String getChronologyString();
+
+ public int compareTo(Task u) {
+ return Integer.compare(this.getTaskId(), u.getTaskId());
+ }
+}
diff --git a/src/main/java/duke/task/model/ToDo.java b/src/main/java/duke/task/model/ToDo.java
new file mode 100644
index 00000000..d2d104fb
--- /dev/null
+++ b/src/main/java/duke/task/model/ToDo.java
@@ -0,0 +1,15 @@
+package duke.task.model;
+
+
+public final class ToDo extends Task {
+ private ToDo() {
+ }
+
+ public ToDo(String taskDescription, Integer taskId, Boolean done) {
+ super(taskDescription, taskId, done);
+ }
+
+ public String getChronologyString() {
+ return ("-");
+ }
+}
diff --git a/src/test/java/duke/integrationtest/TestIoAddTasks.java b/src/test/java/duke/integrationtest/TestIoAddTasks.java
new file mode 100644
index 00000000..75d5fac8
--- /dev/null
+++ b/src/test/java/duke/integrationtest/TestIoAddTasks.java
@@ -0,0 +1,280 @@
+package duke.integrationtest;
+
+import static duke.testhelper.help.Builder.buildCommandInputStream;
+import static duke.testhelper.help.Builder.buildExpectedResponse;
+import static duke.testhelper.help.Builder.buildString;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputAddedDeadline;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputAddedEvent;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputAddedToDo;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputBeginInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputEntry;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputExitInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputImportAttempt;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputList;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputReadPathNotFound;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputTerminate;
+import static duke.testhelper.help.codeundertest.PrettifyUnderTest.getExpectedTaskList;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandExit;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandLineAddDeadline;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandLineAddEvent;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandLineAddToDo;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandList;
+import static duke.testhelper.help.config.DukeIoTestPath.getDefaultTasksImportTestPathString;
+import static duke.testhelper.help.config.DukeIoTestPath.getDefaultTasksTestExportPathString;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+import duke.FileResourceManager;
+import duke.Main;
+import duke.TaskManager;
+import duke.mock.mocktask.MockDeadline;
+import duke.mock.mocktask.MockEvent;
+import duke.mock.mocktask.MockTask;
+import duke.mock.mocktask.MockToDo;
+import duke.testhelper.TestStream;
+import duke.testhelper.help.codeundertest.ParserUnderTest;
+
+public class TestIoAddTasks extends TestStream {
+
+ @Test
+ public void greet_addToDoList_exit() throws Exception {
+
+ // Arrange Input
+
+ /*
+ * Commands executed:
+ *
+ * add task 0 with task description
+ * list
+ * exit loop
+ */
+
+
+ String taskDesc0 = "taskDesc abc";
+
+ String storeCommand0 = generateTextCommandLineAddToDo(taskDesc0);
+ String listCommand = generateTextCommandList();
+ String exitCommand = generateTextCommandExit();
+
+ System.setIn(buildCommandInputStream(storeCommand0, listCommand, exitCommand));
+
+ // Arrange Expected Output
+ /*
+ * Should display:
+ * Entry Message
+ * Input Loop Message
+ * "Added todo" message
+ * tabled tasks list
+ * exit loop
+ * terminate
+ */
+
+ MockToDo expectedToDo1 = new MockToDo(taskDesc0, 0, false);
+ TaskManager tm = new TaskManager();
+ FileResourceManager frm =
+ new FileResourceManager(getDefaultTasksTestExportPathString(), getDefaultTasksImportTestPathString());
+
+ MockTask[] mockTasks = {expectedToDo1};
+ String out0 = getExpectedOutputEntry();
+ String out1 = getExpectedOutputImportAttempt(frm.getImportPath());
+ String out2 = getExpectedOutputReadPathNotFound();
+ String out3 = getExpectedOutputBeginInputLoop();
+ String out4 = getExpectedOutputAddedToDo(taskDesc0, 0);
+ String out5 = getExpectedOutputList(getExpectedTaskList(mockTasks));
+ String out6 = getExpectedOutputExitInputLoop();
+ String out7 = getExpectedOutputTerminate();
+ String expectedOutputResponse = buildExpectedResponse(out0, out1, out2, out3, out4, out5, out6, out7);
+
+ // Act
+ Main.run(this.getPrintStream(), tm, frm);
+ // Assert
+ assertEquals(expectedOutputResponse, this.getOutput());
+ }
+
+ @Test
+ public void greet_addEventList_exit() throws Exception {
+
+ /* Arrange Input
+ * Commands executed:
+ *
+ * add event 0 with task description
+ * list
+ * exit loop
+ */
+
+ String taskDesc0 = "event_desc_abc asfasfasf";
+ String fromDateString = "19990101";
+ String toDateString = "19990202";
+
+ String storeEventCommand0 =
+ generateTextCommandLineAddEvent(taskDesc0,
+ fromDateString, toDateString);
+
+ String listCommand = generateTextCommandList();
+ String exitCommand = generateTextCommandExit();
+
+ System.setIn(buildCommandInputStream(storeEventCommand0, listCommand, exitCommand));
+
+ /*
+ * Arrange Output
+ * Should display:
+ * Entry Message
+ * Input Loop Message
+ * "Added event" message
+ * tabled tasks list
+ * exit loop
+ * terminate
+ */
+
+ MockEvent expectedEvent =
+ new MockEvent(taskDesc0, 0, false, ParserUnderTest.parseStringAsLocalDateTime(fromDateString),
+ ParserUnderTest.parseStringAsLocalDateTime(toDateString));
+ MockTask[] mockEvents = {expectedEvent};
+
+ TaskManager tm = new TaskManager();
+ FileResourceManager frm =
+ new FileResourceManager(getDefaultTasksTestExportPathString(), getDefaultTasksImportTestPathString());
+
+ String out1 = getExpectedOutputEntry();
+ String out2 = getExpectedOutputImportAttempt(frm.getImportPath());
+ String out3 = getExpectedOutputReadPathNotFound();
+ String out4 = getExpectedOutputBeginInputLoop();
+ String out5 = getExpectedOutputAddedEvent(expectedEvent.getDesc(), 0);
+ String out6 = getExpectedOutputList(getExpectedTaskList(mockEvents));
+ String out7 = getExpectedOutputExitInputLoop();
+ String out8 = getExpectedOutputTerminate();
+
+ String expectedOutputResponse = buildString(out1, out2, out3, out4, out5, out6, out7, out8);
+
+ Main.run(this.getPrintStream(), tm, frm);
+ assertEquals(expectedOutputResponse, this.getOutput());
+ }
+
+ @Test
+ public void greet_addDeadlineList_exit() throws Exception {
+
+ /* Arrange Input
+ * Commands executed:
+ *
+ * add deadline 0 with task description
+ * list
+ * exit loop
+ */
+
+
+ String taskDesc0 = "deadline asfasfasf";
+ String byDateString = "20200101";
+
+ String storeDeadlineCommand0 =
+ generateTextCommandLineAddDeadline(taskDesc0,
+ byDateString);
+ String listCommand = generateTextCommandList();
+ String exitCommand = generateTextCommandExit();
+ System.setIn(buildCommandInputStream(storeDeadlineCommand0, listCommand, exitCommand));
+
+ /* Arrange Expected Output
+ *
+ * Should display:
+ * Entry Message
+ * Input Loop Message
+ * "Added event" message
+ * tabled tasks list
+ * exit loop
+ * terminate
+ */
+
+ TaskManager tm = new TaskManager();
+ FileResourceManager frm =
+ new FileResourceManager(getDefaultTasksTestExportPathString(), getDefaultTasksImportTestPathString());
+
+ MockDeadline expectedEvent =
+ new MockDeadline(taskDesc0, 0, false, ParserUnderTest.parseStringAsLocalDateTime(byDateString));
+ MockTask[] mockDeadlines = {expectedEvent};
+
+ String out0 = getExpectedOutputEntry();
+ String out1 = getExpectedOutputImportAttempt(frm.getImportPath());
+ String out2 = getExpectedOutputReadPathNotFound();
+ String out3 = getExpectedOutputBeginInputLoop();
+ String out4 = getExpectedOutputAddedDeadline(taskDesc0, 0);
+ String out5 = getExpectedOutputList(getExpectedTaskList(mockDeadlines));
+ String out6 = getExpectedOutputExitInputLoop();
+ String out7 = getExpectedOutputTerminate();
+
+ String expectedOutputResponse = buildExpectedResponse(out0, out1, out2, out3, out4, out5, out6, out7);
+ Main.run(this.getPrintStream(), tm, frm);
+ assertEquals(expectedOutputResponse, this.getOutput());
+ }
+
+ @Test
+ public void greet_addEachTaskType_list() throws Exception {
+ // Arrange Input
+
+ String task0ToDoDescription = "todo_desc asfasfasf";
+ String task1DeadlineDescription = "deadline_desc ndfrgndfndfn";
+ String task1DeadlineByString = "20010101";
+ String task2EventDescription = "event_desc_abc 213t12 3b52";
+ String task2EventFromDateString = "20200102";
+ String task2EventToDateString = "20200102";
+
+ String storeToDoCommand0 = generateTextCommandLineAddToDo(task0ToDoDescription);
+ String storeDeadlineCommand1 =
+ generateTextCommandLineAddDeadline(task1DeadlineDescription,
+ task1DeadlineByString);
+ String storeEventCommand2 =
+ generateTextCommandLineAddEvent(task2EventDescription,
+ task2EventFromDateString, task2EventToDateString);
+
+ String listCommand = generateTextCommandList();
+ String exitCommand = generateTextCommandExit();
+
+ System.setIn(buildCommandInputStream(storeToDoCommand0, storeDeadlineCommand1, storeEventCommand2, listCommand,
+ exitCommand));
+
+
+ /*
+ * Should display:
+ * Entry Message
+ * Input Loop Message
+ * "Added todo" message
+ * "Added deadline" message
+ * "Added event" message
+ * tabled tasks list
+ * exit loop
+ * terminate
+ */
+
+
+ MockToDo expectedToDo = new MockToDo(task0ToDoDescription, 0, false);
+
+ MockDeadline expectedDeadline = new MockDeadline(task1DeadlineDescription, 1, false,
+ ParserUnderTest.parseStringAsLocalDateTime(task1DeadlineByString));
+ MockEvent expectedEvent = new MockEvent(task2EventDescription, 2, false,
+ ParserUnderTest.parseStringAsLocalDateTime(task2EventFromDateString),
+ ParserUnderTest.parseStringAsLocalDateTime(task2EventToDateString));
+
+ MockTask[] mockEvents = {expectedToDo, expectedDeadline, expectedEvent};
+
+ TaskManager tm = new TaskManager();
+ FileResourceManager frm =
+ new FileResourceManager(getDefaultTasksTestExportPathString(), getDefaultTasksImportTestPathString());
+
+ String out0 = getExpectedOutputEntry();
+ String out1 = getExpectedOutputImportAttempt(frm.getImportPath());
+ String out2 = getExpectedOutputReadPathNotFound();
+ String out3 = getExpectedOutputBeginInputLoop();
+ String out4 = getExpectedOutputAddedToDo(task0ToDoDescription, 0);
+ String out5 = getExpectedOutputAddedDeadline(task1DeadlineDescription, 1);
+ String out6 = getExpectedOutputAddedEvent(task2EventDescription, 2);
+ String out7 = getExpectedOutputList(getExpectedTaskList(mockEvents));
+ String out8 = getExpectedOutputExitInputLoop();
+ String out9 = getExpectedOutputTerminate();
+
+ String expectedOutputResponse =
+ buildExpectedResponse(out0, out1, out2, out3, out4, out5, out6, out7, out8, out9);
+ Main.run(this.getPrintStream(), tm, frm);
+
+ assertEquals(expectedOutputResponse, this.getOutput());
+
+ }
+}
diff --git a/src/test/java/duke/integrationtest/TestIoFind.java b/src/test/java/duke/integrationtest/TestIoFind.java
new file mode 100644
index 00000000..d480d207
--- /dev/null
+++ b/src/test/java/duke/integrationtest/TestIoFind.java
@@ -0,0 +1,192 @@
+package duke.integrationtest;
+
+
+import static duke.testhelper.help.Builder.buildCommandInputStream;
+import static duke.testhelper.help.Builder.buildExpectedResponse;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputAddedToDo;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputBeginInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputEntry;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputExitInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputImportAttempt;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputListTasksWithKeywordDescription;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputReadPathNotFound;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputTerminate;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getMsgUnderTestErrorSpacedKeyword;
+import static duke.testhelper.help.codeundertest.PrettifyUnderTest.getExpectedTaskList;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.PROMPT_UNDER_TEST_FIND;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandExit;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandFindKeywordInDescription;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandLineAddToDo;
+import static duke.testhelper.help.config.DukeIoTestPath.getDefaultTasksImportTestPathString;
+import static duke.testhelper.help.config.DukeIoTestPath.getDefaultTasksTestExportPathString;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.junit.jupiter.api.Test;
+
+import duke.FileResourceManager;
+import duke.Main;
+import duke.TaskManager;
+import duke.mock.mocktask.MockTask;
+import duke.mock.mocktask.MockToDo;
+import duke.testhelper.TestStream;
+
+public class TestIoFind extends TestStream {
+ /**
+ * Test find routine.
+ */
+ @Test
+ public void greet_addToDoListTasksWithKeywordSave_exit() {
+
+ String keyword = "MAGIK";
+ String taskDesc0 = "nons afasf09qhy2gr";
+ String taskDesc1 = "aasfg " + keyword + " c124124";
+ String taskDesc2 = "aasfg " + keyword.toLowerCase() + " negdndetnjd";
+ String store0Command = generateTextCommandLineAddToDo(taskDesc0);
+ String store1Command = generateTextCommandLineAddToDo(taskDesc1);
+ String store2Command = generateTextCommandLineAddToDo(taskDesc2);
+ String findCommand = generateTextCommandFindKeywordInDescription(PROMPT_UNDER_TEST_FIND, keyword);
+ String exitCommand = generateTextCommandExit();
+
+ System.setIn(buildCommandInputStream(store0Command, store1Command, store2Command, findCommand, exitCommand));
+
+ /*
+ * Should display:
+ * Entry Message
+ * Input Loop Message
+ * "Added todo0" message
+ * "Added todo0" message
+ * queried tasks list
+ * exit loop
+ * terminate
+ */
+
+ MockToDo expectedTask1 = new MockToDo(taskDesc1, 1, false);
+ MockToDo expectedTask2 = new MockToDo(taskDesc2, 2, false);
+
+ MockTask[] mockTasks = {expectedTask1, expectedTask2}; // only task 1 should be displayed after query
+ TaskManager tm = new TaskManager();
+
+ String importPathString = getDefaultTasksTestExportPathString();
+ String exportPathString = getDefaultTasksImportTestPathString();
+ FileResourceManager frm = new FileResourceManager(importPathString, exportPathString);
+
+ String out0 = (getExpectedOutputEntry());
+ String out1 = (getExpectedOutputImportAttempt(frm.getImportPath()));
+ String out2 = (getExpectedOutputReadPathNotFound());
+ String out3 = (getExpectedOutputBeginInputLoop());
+ String out4 = (getExpectedOutputAddedToDo(taskDesc0, 0));
+ String out5 = (getExpectedOutputAddedToDo(taskDesc1, 1));
+ String out6 = (getExpectedOutputAddedToDo(taskDesc2, 2));
+ String out7 = (getExpectedOutputListTasksWithKeywordDescription(getExpectedTaskList(mockTasks), keyword));
+ String out8 = (getExpectedOutputExitInputLoop());
+ String out9 = (getExpectedOutputTerminate());
+ String expectedOutputResponse =
+ buildExpectedResponse(out0, out1, out2, out3, out4, out5, out6, out7, out8, out9);
+
+ try {
+ Main.run(this.getPrintStream(), tm, frm);
+ } catch (Exception e) {
+ fail(e.toString());
+ }
+
+ assertEquals(expectedOutputResponse, this.getOutput());
+ }
+
+ /**
+ * Test find routine.
+ */
+ @Test
+ public void greet_addToDoListTasksWithKeywordSaveExit_emptyResult() {
+
+ String keyword = "MAGIK";
+ String taskDesc0 = "nons afasf09qhy2gr";
+ String store0Command = generateTextCommandLineAddToDo(taskDesc0);
+ String findCommand = generateTextCommandFindKeywordInDescription(PROMPT_UNDER_TEST_FIND, keyword);
+ String exitCommand = generateTextCommandExit();
+
+ System.setIn(buildCommandInputStream(store0Command, findCommand, exitCommand));
+
+ /*
+ * Should display:
+ * Entry Message
+ * Input Loop Message
+ * "Added todo0" message
+ * queried tasks list
+ * exit loop
+ * terminate
+ */
+
+
+ MockTask[] mockTasks = {}; // no should be displayed after query
+ TaskManager tm = new TaskManager();
+ FileResourceManager frm =
+ new FileResourceManager(getDefaultTasksTestExportPathString(), getDefaultTasksImportTestPathString());
+
+ String out0 = (getExpectedOutputEntry());
+ String out1 = (getExpectedOutputImportAttempt(frm.getImportPath()));
+ String out2 = (getExpectedOutputReadPathNotFound());
+ String out3 = (getExpectedOutputBeginInputLoop());
+ String out4 = (getExpectedOutputAddedToDo(taskDesc0, 0));
+ String out5 = (getExpectedOutputListTasksWithKeywordDescription(getExpectedTaskList(mockTasks), keyword));
+ String out6 = (getExpectedOutputExitInputLoop());
+ String out7 = (getExpectedOutputTerminate());
+ String expectedOutputResponse = buildExpectedResponse(out0, out1, out2, out3, out4, out5, out6, out7);
+
+ try {
+ Main.run(this.getPrintStream(), tm, frm);
+ } catch (Exception e) {
+ fail(e.toString());
+ }
+ assertEquals(expectedOutputResponse, this.getOutput());
+ }
+
+ /**
+ * Test find routine with invalid keyword. Should not execute the search.
+ */
+ @Test
+ public void greet_addToDoListTasksWithInvalidKeywordSave_exit() {
+
+ String keyword = "MAGIK asfasf";
+ String taskDesc0 = "nons afasf09qhy2gr";
+ String store0Command = generateTextCommandLineAddToDo(taskDesc0);
+ String findCommand = generateTextCommandFindKeywordInDescription(PROMPT_UNDER_TEST_FIND, keyword);
+ String exitCommand = generateTextCommandExit();
+
+ System.setIn(buildCommandInputStream(store0Command, findCommand, exitCommand));
+
+ /*
+ * Should display:
+ * Entry Message
+ * Input Loop Message
+ * "Added todo0" message
+ * queried tasks list
+ * exit loop
+ * terminate
+ */
+
+ TaskManager tm = new TaskManager();
+ FileResourceManager frm =
+ new FileResourceManager(getDefaultTasksTestExportPathString(), getDefaultTasksImportTestPathString());
+
+ String out0 = (getExpectedOutputEntry());
+ String out1 = (getExpectedOutputImportAttempt(frm.getImportPath()));
+ String out2 = (getExpectedOutputReadPathNotFound());
+ String out3 = (getExpectedOutputBeginInputLoop());
+ String out4 = (getExpectedOutputAddedToDo(taskDesc0, 0));
+ String out5 = (getMsgUnderTestErrorSpacedKeyword());
+ String out6 = (getExpectedOutputExitInputLoop());
+ String out7 = (getExpectedOutputTerminate());
+ String expectedOutputResponse = buildExpectedResponse(out0, out1, out2, out3, out4, out5, out6, out7);
+
+ try {
+ Main.run(this.getPrintStream(), tm, frm);
+ } catch (Exception e) {
+ fail(e.toString());
+ }
+
+ assertEquals(expectedOutputResponse, this.getOutput());
+ }
+
+
+}
diff --git a/src/test/java/duke/integrationtest/TestIoList.java b/src/test/java/duke/integrationtest/TestIoList.java
new file mode 100644
index 00000000..506af84c
--- /dev/null
+++ b/src/test/java/duke/integrationtest/TestIoList.java
@@ -0,0 +1,141 @@
+package duke.integrationtest;
+
+import static duke.testhelper.help.Builder.buildCommandInputStream;
+import static duke.testhelper.help.Builder.buildExpectedResponse;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputAddedToDo;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputBeginInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputCommandDeleted;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputEntry;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputExitInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputImportAttempt;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputList;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputReadPathNotFound;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputTerminate;
+import static duke.testhelper.help.codeundertest.PrettifyUnderTest.getExpectedTaskList;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.PROMPT_UNDER_TEST_DELETE_TASK;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandDeleteTaskByTaskId;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandExit;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandLineAddToDo;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandList;
+import static duke.testhelper.help.config.DukeIoTestPath.getDefaultTasksImportTestPathString;
+import static duke.testhelper.help.config.DukeIoTestPath.getDefaultTasksTestExportPathString;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+import duke.FileResourceManager;
+import duke.Main;
+import duke.TaskManager;
+import duke.mock.mocktask.MockTask;
+import duke.mock.mocktask.MockToDo;
+import duke.testhelper.TestStream;
+
+public class TestIoList extends TestStream {
+
+ @Test
+ public void greet_addThenDeleteToDoList_exit() throws Exception {
+
+ /* Arrange Input
+ * Commands executed:
+ *
+ * add task 0 with task description
+ * delete task 0
+ * list
+ * exit loop
+ */
+
+
+ String taskDesc0 = "taskDesc abc";
+
+ String store0Command = generateTextCommandLineAddToDo(taskDesc0);
+ String delete0Command = generateTextCommandDeleteTaskByTaskId(PROMPT_UNDER_TEST_DELETE_TASK, 0);
+ String listCommand = generateTextCommandList();
+ String exitCommand = generateTextCommandExit();
+
+ System.setIn(buildCommandInputStream(store0Command, delete0Command, listCommand, exitCommand));
+
+ /* Arrange Expected Output
+ * Should display:
+ * Entry Message
+ * Input Loop Message
+ * "Added todo" message
+ * tabled tasks list
+ * exit loop
+ * terminate
+ */
+ TaskManager tm = new TaskManager();
+ FileResourceManager frm =
+ new FileResourceManager(getDefaultTasksTestExportPathString(), getDefaultTasksImportTestPathString());
+ MockTask[] mockTasks = {}; // since task is deleted
+ String out0 = (getExpectedOutputEntry());
+ String out1 = (getExpectedOutputImportAttempt(frm.getImportPath()));
+ String out2 = (getExpectedOutputReadPathNotFound());
+ String out3 = (getExpectedOutputBeginInputLoop());
+ String out4 = (getExpectedOutputAddedToDo(taskDesc0, 0));
+ String out5 = (getExpectedOutputCommandDeleted(0));
+ String out6 = (getExpectedOutputList(getExpectedTaskList(mockTasks)));
+ String out7 = (getExpectedOutputExitInputLoop());
+ String out8 = (getExpectedOutputTerminate());
+
+ String expectedOutputResponse = buildExpectedResponse(out0, out1, out2, out3, out4, out5, out6, out7, out8);
+ Main.run(this.getPrintStream(), tm, frm);
+ assertEquals(expectedOutputResponse, this.getOutput());
+ }
+
+
+ @Test
+ public void greet_add2ToDosDeleteList_exit() throws Exception {
+
+ /*
+ * Commands executed:
+ *
+ * add task 0 with task description
+ * add task 1 with task description
+ * delete task 0
+ * list
+ * exit loop
+ */
+
+ String taskDesc0 = "taskDesc abc";
+ String taskDesc1 = "taskDesc def";
+
+ String store0Command = generateTextCommandLineAddToDo(taskDesc0);
+ String store1Command = generateTextCommandLineAddToDo(taskDesc1);
+ String delete0Command = generateTextCommandDeleteTaskByTaskId(PROMPT_UNDER_TEST_DELETE_TASK, 0);
+ String listCommand = generateTextCommandList();
+ String exitCommand = generateTextCommandExit();
+
+ System.setIn(buildCommandInputStream(store0Command, store1Command, delete0Command, listCommand, exitCommand));
+
+ /*
+ * Should display:
+ * Entry Message
+ * Input Loop Message
+ * "Added todo" message
+ * tabled tasks list
+ * exit loop
+ * terminate
+ */
+ MockToDo expectedToDo1 = new MockToDo(taskDesc1, 1, false);
+ MockTask[] mockTasks = {expectedToDo1}; // since task0 is deleted
+
+ TaskManager tm = new TaskManager();
+ FileResourceManager frm =
+ new FileResourceManager(getDefaultTasksTestExportPathString(), getDefaultTasksImportTestPathString());
+ String out0 = (getExpectedOutputEntry());
+ String out1 = (getExpectedOutputImportAttempt(frm.getImportPath()));
+ String out2 = (getExpectedOutputReadPathNotFound());
+ String out3 = (getExpectedOutputBeginInputLoop());
+ String out4 = (getExpectedOutputAddedToDo(taskDesc0, 0));
+ String out5 = (getExpectedOutputAddedToDo(taskDesc1, 1));
+ String out6 = (getExpectedOutputCommandDeleted(0));
+ String out7 = (getExpectedOutputList(getExpectedTaskList(mockTasks)));
+ String out8 = (getExpectedOutputExitInputLoop());
+ String out9 = (getExpectedOutputTerminate());
+ String expectedOutputResponse =
+ buildExpectedResponse(out0, out1, out2, out3, out4, out5, out6, out7, out8, out9);
+ Main.run(this.getPrintStream(), tm, frm);
+ assertEquals(expectedOutputResponse, this.getOutput());
+ }
+
+}
diff --git a/src/test/java/duke/integrationtest/TestIoNegative.java b/src/test/java/duke/integrationtest/TestIoNegative.java
new file mode 100644
index 00000000..2434f71f
--- /dev/null
+++ b/src/test/java/duke/integrationtest/TestIoNegative.java
@@ -0,0 +1,52 @@
+package duke.integrationtest;
+
+import static duke.testhelper.help.Builder.buildCommandInputStream;
+import static duke.testhelper.help.Builder.buildExpectedResponse;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputBeginInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputCommandUnknown;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputEntry;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputExitInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputImportAttempt;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputReadPathNotFound;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputTerminate;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandExit;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandRandom;
+import static duke.testhelper.help.config.DukeIoTestPath.getDefaultTasksImportTestPathString;
+import static duke.testhelper.help.config.DukeIoTestPath.getDefaultTasksTestExportPathString;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+import duke.FileResourceManager;
+import duke.Main;
+import duke.TaskManager;
+import duke.testhelper.TestStream;
+
+public class TestIoNegative extends TestStream {
+
+ @Test
+ public void testUnknownCommand() throws Exception {
+
+ String randomTextCommand = generateTextCommandRandom("s0meUnknownPrompt");
+ String exitLoopCommand = generateTextCommandExit();
+ System.setIn(buildCommandInputStream(randomTextCommand, exitLoopCommand));
+
+ TaskManager tm = new TaskManager();
+ FileResourceManager frm =
+ new FileResourceManager(getDefaultTasksTestExportPathString(), getDefaultTasksImportTestPathString());
+ String out0 = getExpectedOutputEntry();
+ String out1 = getExpectedOutputImportAttempt(frm.getImportPath());
+ String out2 = getExpectedOutputReadPathNotFound();
+ String out3 = getExpectedOutputBeginInputLoop();
+ String out4 = getExpectedOutputCommandUnknown();
+ String out5 = getExpectedOutputExitInputLoop();
+ String out6 = getExpectedOutputTerminate();
+
+ String expectedOutputResponse = buildExpectedResponse(out0, out1, out2, out3, out4, out5, out6);
+
+ Main.run(this.getPrintStream(), tm, frm);
+
+ assertEquals(expectedOutputResponse, this.getOutput());
+ }
+
+}
diff --git a/src/test/java/duke/integrationtest/TestIoSave.java b/src/test/java/duke/integrationtest/TestIoSave.java
new file mode 100644
index 00000000..a18077d8
--- /dev/null
+++ b/src/test/java/duke/integrationtest/TestIoSave.java
@@ -0,0 +1,53 @@
+package duke.integrationtest;
+
+import static duke.testhelper.help.Builder.buildCommandInputStream;
+import static duke.testhelper.help.Builder.buildExpectedResponse;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputBeginInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputEntry;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputExitInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputImportAttempt;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputReadPathNotFound;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputSaved;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputTerminate;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.PROMPT_UNDER_TEST_SAVE;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandExit;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandSave;
+import static duke.testhelper.help.config.DukeIoTestPath.getDefaultTasksImportTestPathString;
+import static duke.testhelper.help.config.DukeIoTestPath.getDefaultTasksTestExportPathString;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+import duke.FileResourceManager;
+import duke.Main;
+import duke.TaskManager;
+import duke.testhelper.TestStream;
+
+public class TestIoSave extends TestStream {
+
+ @Test
+ public void saveMessage() throws Exception {
+ String saveCommand = generateTextCommandSave(PROMPT_UNDER_TEST_SAVE);
+ String exitLoopCommand = generateTextCommandExit();
+ System.setIn(buildCommandInputStream(saveCommand, exitLoopCommand));
+
+ TaskManager tm = new TaskManager();
+
+ String exportPath = getDefaultTasksTestExportPathString();
+ FileResourceManager frm = new FileResourceManager(exportPath, getDefaultTasksImportTestPathString());
+ String out0 = getExpectedOutputEntry();
+ String out1 = getExpectedOutputImportAttempt(frm.getImportPath());
+ String out2 = getExpectedOutputReadPathNotFound();
+ String out3 = getExpectedOutputBeginInputLoop();
+ String out4 = getExpectedOutputSaved(exportPath);
+ String out5 = getExpectedOutputExitInputLoop();
+ String out6 = getExpectedOutputTerminate();
+
+ String expectedOutputResponse = buildExpectedResponse(out0, out1, out2, out3, out4, out5, out6);
+
+ Main.run(this.getPrintStream(), tm, frm);
+
+ assertEquals(expectedOutputResponse, this.getOutput());
+ }
+
+}
diff --git a/src/test/java/duke/integrationtest/TestIoToggleDoneStatus.java b/src/test/java/duke/integrationtest/TestIoToggleDoneStatus.java
new file mode 100644
index 00000000..e705d3cf
--- /dev/null
+++ b/src/test/java/duke/integrationtest/TestIoToggleDoneStatus.java
@@ -0,0 +1,107 @@
+package duke.integrationtest;
+
+import static duke.testhelper.help.Builder.buildCommandInputStream;
+import static duke.testhelper.help.Builder.buildExpectedResponse;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputAddedToDo;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputBeginInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputEntry;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputExitInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputImportAttempt;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputList;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputReadPathNotFound;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputTaskSetCompleted;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputTaskSetIncomplete;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputTerminate;
+import static duke.testhelper.help.codeundertest.PrettifyUnderTest.getExpectedTaskList;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandExit;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandLineAddToDo;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandList;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandSetCompleted;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandSetIncomplete;
+import static duke.testhelper.help.config.DukeIoTestPath.getDefaultTasksImportTestPathString;
+import static duke.testhelper.help.config.DukeIoTestPath.getDefaultTasksTestExportPathString;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+import duke.FileResourceManager;
+import duke.Main;
+import duke.TaskManager;
+import duke.mock.mocktask.MockTask;
+import duke.mock.mocktask.MockToDo;
+import duke.testhelper.TestStream;
+
+public class TestIoToggleDoneStatus extends TestStream {
+
+ @Test
+ public void greet_addToDoToggleList_shouldBeSame() throws Exception {
+
+ // Arrange Input
+
+ /*
+ * Commands executed:
+ *
+ * add task 0 with task description
+ * list
+ * exit loop
+ */
+
+ // Arrange Expected Output
+ /*
+ * Should display:
+ * Entry Message
+ * Input Loop Message
+ * "Added todo" message
+ * tabled tasks list
+ * exit loop
+ * terminate
+ */
+
+ TaskManager tm = new TaskManager();
+ FileResourceManager frm =
+ new FileResourceManager(getDefaultTasksTestExportPathString(), getDefaultTasksImportTestPathString());
+
+
+ String taskDesc0 = "taskDesc abc";
+
+ String out0 = getExpectedOutputEntry();
+ String out1 = getExpectedOutputImportAttempt(frm.getImportPath());
+ String out2 = getExpectedOutputReadPathNotFound();
+ String out3 = getExpectedOutputBeginInputLoop();
+
+
+ String storeCommand = generateTextCommandLineAddToDo(taskDesc0);
+ String out4 = getExpectedOutputAddedToDo(taskDesc0, 0);
+
+
+ String setCompleteCommand = generateTextCommandSetCompleted(0);
+ String out5 = getExpectedOutputTaskSetCompleted(0);
+
+ String setIncompleteCommand = generateTextCommandSetIncomplete(0);
+ String out6 = getExpectedOutputTaskSetIncomplete(0);
+
+ String listCommand = generateTextCommandList();
+
+ MockToDo expectedToDo1 = new MockToDo(taskDesc0, 0, false);
+ MockTask[] mockTasks = {expectedToDo1};
+ String out7 = getExpectedOutputList(getExpectedTaskList(mockTasks));
+
+ String exitCommand = generateTextCommandExit();
+ String out8 = getExpectedOutputExitInputLoop();
+
+ String out9 = getExpectedOutputTerminate();
+
+
+ System.setIn(
+ buildCommandInputStream(storeCommand, setCompleteCommand, setIncompleteCommand, listCommand, exitCommand));
+
+ String expectedOutputResponse =
+ buildExpectedResponse(out0, out1, out2, out3, out4, out5, out6, out7, out8, out9);
+
+ // Act
+ Main.run(this.getPrintStream(), tm, frm);
+ // Assert
+ assertEquals(expectedOutputResponse, this.getOutput());
+ }
+
+}
diff --git a/src/test/java/duke/mock/mocktask/MockDeadline.java b/src/test/java/duke/mock/mocktask/MockDeadline.java
new file mode 100644
index 00000000..114ee5e3
--- /dev/null
+++ b/src/test/java/duke/mock/mocktask/MockDeadline.java
@@ -0,0 +1,26 @@
+package duke.mock.mocktask;
+
+import java.time.LocalDateTime;
+
+import duke.testhelper.help.codeundertest.ParserUnderTest;
+
+public class MockDeadline extends MockTask {
+ private final LocalDateTime by;
+
+ /**
+ * Mock deadline
+ *
+ * @param desc desc
+ * @param id id
+ * @param done done
+ * @param by by
+ */
+ public MockDeadline(String desc, Integer id, Boolean done, LocalDateTime by) {
+ super(desc, id, done);
+ this.by = by;
+ }
+
+ public String getbyDateString() {
+ return ParserUnderTest.prettifyLocalDateTime(this.by);
+ }
+}
diff --git a/src/test/java/duke/mock/mocktask/MockEvent.java b/src/test/java/duke/mock/mocktask/MockEvent.java
new file mode 100644
index 00000000..ae61cd79
--- /dev/null
+++ b/src/test/java/duke/mock/mocktask/MockEvent.java
@@ -0,0 +1,34 @@
+package duke.mock.mocktask;
+
+
+import java.time.LocalDateTime;
+
+import duke.testhelper.help.codeundertest.ParserUnderTest;
+
+public class MockEvent extends MockTask {
+ private final LocalDateTime from;
+ private final LocalDateTime to;
+
+ /**
+ * Mock event
+ *
+ * @param desc desc
+ * @param id id
+ * @param done done
+ * @param from from
+ * @param to to
+ */
+ public MockEvent(String desc, Integer id, Boolean done, LocalDateTime from, LocalDateTime to) {
+ super(desc, id, done);
+ this.from = (from);
+ this.to = (to);
+ }
+
+ public String getToDateString() {
+ return ParserUnderTest.prettifyLocalDateTime(this.to);
+ }
+
+ public String getFromDateString() {
+ return ParserUnderTest.prettifyLocalDateTime(this.from);
+ }
+}
diff --git a/src/test/java/duke/mock/mocktask/MockTask.java b/src/test/java/duke/mock/mocktask/MockTask.java
new file mode 100644
index 00000000..32169d6b
--- /dev/null
+++ b/src/test/java/duke/mock/mocktask/MockTask.java
@@ -0,0 +1,28 @@
+package duke.mock.mocktask;
+
+public abstract class MockTask {
+ private String desc;
+ private Integer id;
+ private Boolean done = false;
+
+ private MockTask() {
+ }
+
+ protected MockTask(String desc, Integer id, Boolean done) {
+ this.desc = desc;
+ this.id = id;
+ this.done = done;
+ }
+
+ public String getDesc() {
+ return this.desc;
+ }
+
+ public Boolean getDone() {
+ return this.done;
+ }
+
+ public Integer getId() {
+ return this.id;
+ }
+}
diff --git a/src/test/java/duke/mock/mocktask/MockToDo.java b/src/test/java/duke/mock/mocktask/MockToDo.java
new file mode 100644
index 00000000..b8895925
--- /dev/null
+++ b/src/test/java/duke/mock/mocktask/MockToDo.java
@@ -0,0 +1,8 @@
+package duke.mock.mocktask;
+
+public class MockToDo extends MockTask {
+
+ public MockToDo(String desc, Integer id, Boolean done) {
+ super(desc, id, done);
+ }
+}
diff --git a/src/test/java/duke/systemtest/SmokeTest.java b/src/test/java/duke/systemtest/SmokeTest.java
new file mode 100644
index 00000000..5f1a83b2
--- /dev/null
+++ b/src/test/java/duke/systemtest/SmokeTest.java
@@ -0,0 +1,25 @@
+package duke.systemtest;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+import duke.Ui;
+import duke.testhelper.TestStream;
+import duke.testhelper.help.codeundertest.OutputUnderTest;
+
+public class SmokeTest extends TestStream {
+ /**
+ * should display entry and exit message and terminates gently.
+ */
+ @Test
+ public void greetAndExit() {
+ String expectedEntryMessage = OutputUnderTest.getExpectedOutputEntry();
+ String expectedExitMessage = OutputUnderTest.getExpectedOutputTerminate();
+ String expectedOutput = expectedEntryMessage + expectedExitMessage;
+ Ui ui = new Ui(this.getPrintStream());
+ ui.printEntryMessage();
+ ui.printTerminateMessage();
+ assertEquals(expectedOutput, this.getOutput());
+ }
+}
diff --git a/src/test/java/duke/systemtest/SystemExportTest.java b/src/test/java/duke/systemtest/SystemExportTest.java
new file mode 100644
index 00000000..862ca553
--- /dev/null
+++ b/src/test/java/duke/systemtest/SystemExportTest.java
@@ -0,0 +1,249 @@
+package duke.systemtest;
+
+import static duke.dukeutility.config.DukeIo.getDefaultTasksImportPathString;
+import static duke.dukeutility.validator.TextCommandValidator.isParentDirectoryValid;
+import static duke.testhelper.help.Builder.buildCommandInputStream;
+import static duke.testhelper.help.Builder.buildString;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputAddedDeadline;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputAddedEvent;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputAddedToDo;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputBeginInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputCommandDeleted;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputEntry;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputExitInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputImportAttempt;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputList;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputListTasksWithKeywordDescription;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputReadPathNotFound;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputTaskSetCompleted;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputTerminate;
+import static duke.testhelper.help.codeundertest.ParserUnderTest.parseStringAsLocalDateTime;
+import static duke.testhelper.help.codeundertest.ParserUnderTest.stringToPath;
+import static duke.testhelper.help.codeundertest.PrettifyUnderTest.getExpectedTaskList;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.PROMPT_UNDER_TEST_DELETE_TASK;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.PROMPT_UNDER_TEST_EXIT_LOOP;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.PROMPT_UNDER_TEST_FIND;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.PROMPT_UNDER_TEST_SAVE;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandDeleteTaskByTaskId;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandExit;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandFindKeywordInDescription;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandLineAddDeadline;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandLineAddEvent;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandLineAddToDo;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandList;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandSave;
+import static duke.testhelper.help.codeundertest.TextCommandUnderTest.generateTextCommandSetCompleted;
+import static duke.testhelper.help.config.DukeIoTestPath.getResourceTestFolder;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import org.junit.jupiter.api.Test;
+
+import com.google.gson.JsonArray;
+
+import duke.FileResourceManager;
+import duke.Main;
+import duke.TaskManager;
+import duke.command.commandfactory.ImportCommandFactory;
+import duke.mock.mocktask.MockDeadline;
+import duke.mock.mocktask.MockEvent;
+import duke.mock.mocktask.MockTask;
+import duke.mock.mocktask.MockToDo;
+import duke.testhelper.TestStream;
+
+public class SystemExportTest extends TestStream {
+
+ /**
+ * Execute add tasks commands and save as export1
+ * import export1, save as export2
+ * export1 == export2 ? pass
+ */
+ @Test
+ public void idempotentExport() {
+ String thisTestSign = "saveTasksToJsonTestFile";
+ String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd-hh-mm-ss"));
+ String export1PathString = getResourceTestFolder() + "-added" + thisTestSign + date + ".json";
+ String export2PathString = getResourceTestFolder() + "-load" + thisTestSign + date + ".json";
+ FileResourceManager frm1 = new FileResourceManager(export1PathString, null);
+ TaskManager tm1 = new TaskManager();
+ // sets of add tasks textCommands
+ int countPerTaskType = 10;
+ int expectedTotalTaskCount = 0;
+
+ String[] addCommands = new String[countPerTaskType];
+ for (int i = 0; i < countPerTaskType; i++) {
+
+ String todoDesc = "tododesc" + i;
+
+ String deadlineDesc = "deadlinedesc";
+ String deadlineBy = "202002" + String.format("%2s", 19);
+
+ String eventDesc = "eventdesc";
+ String eventFrom = "20200202";
+ String eventTo = "20210202";
+
+ String addToDoCommand = generateTextCommandLineAddToDo(todoDesc);
+ expectedTotalTaskCount++;
+ String addDeadlineCommand = generateTextCommandLineAddDeadline(deadlineDesc,
+ deadlineBy);
+ expectedTotalTaskCount++;
+ String addEventCommand =
+ generateTextCommandLineAddEvent(eventDesc, eventFrom,
+ eventTo);
+ expectedTotalTaskCount++;
+
+ addCommands[i] = addToDoCommand + addDeadlineCommand + addEventCommand;
+ }
+
+ String in0 = String.join("", addCommands);
+ String in1 = generateTextCommandSetCompleted(5);
+ String in2 = (generateTextCommandSave(PROMPT_UNDER_TEST_SAVE));
+ String in3 = (generateTextCommandExit());
+ System.setIn(buildCommandInputStream(in0, in1, in2, in3));
+ try {
+ Main.run(this.getPrintStream(), tm1, frm1);
+ assertSame(tm1.getSize(), expectedTotalTaskCount, "expected amount " + expectedTotalTaskCount
+ + ", actual " + tm1.getSize() + System.lineSeparator());
+ } catch (Exception e) {
+ fail(e.toString());
+ }
+
+ String secondIn0 = generateTextCommandSave(PROMPT_UNDER_TEST_SAVE);
+ String secondIn1 = generateTextCommandSave(PROMPT_UNDER_TEST_EXIT_LOOP);
+
+ System.setIn(buildCommandInputStream(secondIn0, secondIn1));
+ FileResourceManager frm2 = new FileResourceManager(export2PathString, export1PathString);
+
+ TaskManager tm2 = new TaskManager();
+ try {
+ Main.run(this.getPrintStream(), tm2, frm2);
+ } catch (Exception e) {
+ fail(e.toString());
+ }
+ assertEquals(30, tm2.getSize());
+ try {
+ JsonArray export1 =
+ new ImportCommandFactory().executeExtractTasksFromFile(frm1.getExportPath()).getJsonArg()
+ .getAsJsonArray();
+ JsonArray export2 =
+ new ImportCommandFactory().executeExtractTasksFromFile(frm2.getExportPath()).getJsonArg()
+ .getAsJsonArray();
+ assertNotNull(export1);
+ assertNotNull(export2);
+ assertEquals(30, export1.size());
+ assertEquals(30, export2.size());
+ assertEquals(export1, export2);
+ } catch (Exception e) {
+ fail("Failure during comparing exports. " + e + this.getOutput());
+ }
+ }
+
+
+ private void writeToFile(String pathString, String... data) throws Exception {
+ Path exportPath = stringToPath(pathString);
+ try {
+ if (exportPath == null) {
+ throw new Exception("Export path validation failed.");
+ }
+ Files.createDirectories(exportPath.getParent());
+ if (!isParentDirectoryValid(exportPath)) {
+ throw new Exception("Export path validation failed.");
+ }
+ } catch (Exception e) {
+ throw new IOException("Export path validation failed.");
+ }
+ Files.write(exportPath, buildString(data).getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE);
+ }
+
+ /**
+ * This method generates 1) the input and 2) its expected output for system level test. No assertions required.
+ *
+ * @throws Exception Unable to generate files, may impact on test phase.
+ */
+ @Test
+ public void generateExpectedTestFileInActualEnvironment() throws Exception {
+ String importPathString = getDefaultTasksImportPathString();
+
+ String loadInputPath =
+ String.join(File.separator, new String[] {"src", "test", "resources", "linux-test", "input.txt"});
+ String expectedOutputPath =
+ String.join(File.separator, new String[] {"src", "test", "resources", "linux-test", "expected.txt"});
+
+ String out0 = (getExpectedOutputEntry());
+
+ String out1 = (getExpectedOutputImportAttempt(stringToPath(importPathString)));
+ String out2 = (getExpectedOutputReadPathNotFound());
+
+ String out3 = (getExpectedOutputBeginInputLoop());
+
+ String todoDesc = "tododesc";
+
+ String deadlineDesc = "deadlinedesc";
+ String deadlineBy = "202002" + String.format("%2s", 19);
+
+ String eventDesc = "eventdesc asdasdasd";
+ String eventFrom = "20200202";
+ String eventTo = "20210202";
+
+ String in0 = generateTextCommandLineAddToDo(todoDesc);
+ String out4 = (getExpectedOutputAddedToDo(todoDesc, 0));
+
+ String in1 = generateTextCommandLineAddDeadline(deadlineDesc,
+ deadlineBy);
+ String out5 = (getExpectedOutputAddedDeadline(deadlineDesc, 1));
+
+ String in2 =
+ generateTextCommandLineAddEvent(eventDesc, eventFrom,
+ eventTo);
+ String out6 = (getExpectedOutputAddedEvent(eventDesc, 2));
+
+ String in3 = generateTextCommandList();
+
+ MockTask[] allMockTasks = new MockTask[] {new MockToDo(todoDesc, 0, false),
+ new MockDeadline(deadlineDesc, 1, false, parseStringAsLocalDateTime(deadlineBy)),
+ new MockEvent(eventDesc, 2, false, parseStringAsLocalDateTime(eventFrom),
+ parseStringAsLocalDateTime(eventTo))};
+ String out7 = (getExpectedOutputList(getExpectedTaskList(allMockTasks)));
+
+ String in4 = generateTextCommandDeleteTaskByTaskId(PROMPT_UNDER_TEST_DELETE_TASK, 0);
+ String out8 = (getExpectedOutputCommandDeleted(0));
+
+ String in5 = generateTextCommandList();
+
+ MockTask[] remainingMockTasks =
+ new MockTask[] {new MockDeadline(deadlineDesc, 1, false, parseStringAsLocalDateTime(deadlineBy)),
+ new MockEvent(eventDesc, 2, false, parseStringAsLocalDateTime(eventFrom),
+ parseStringAsLocalDateTime(eventTo))};
+ String out9 = (getExpectedOutputList(getExpectedTaskList(remainingMockTasks)));
+
+ String in6 = generateTextCommandSetCompleted(2);
+ String out10 = getExpectedOutputTaskSetCompleted(2);
+
+ String keyword = "eventdesc";
+ String in7 = generateTextCommandFindKeywordInDescription(PROMPT_UNDER_TEST_FIND, keyword);
+ MockTask[] selectedMockTasks = new MockTask[] {
+ new MockEvent(eventDesc, 2, true, parseStringAsLocalDateTime(eventFrom),
+ parseStringAsLocalDateTime(eventTo))};
+ String out11 =
+ getExpectedOutputListTasksWithKeywordDescription(getExpectedTaskList(selectedMockTasks), keyword);
+
+ String in8 = generateTextCommandExit();
+ String out12 = (getExpectedOutputExitInputLoop());
+
+ String out13 = (getExpectedOutputTerminate());
+
+ writeToFile(loadInputPath, in0, in1, in2, in3, in4, in5, in6, in7, in8);
+ writeToFile(expectedOutputPath, out0, out1, out2, out3, out4, out5, out6, out7, out8, out9, out10, out11, out12,
+ out13);
+ }
+}
diff --git a/src/test/java/duke/testhelper/TestStream.java b/src/test/java/duke/testhelper/TestStream.java
new file mode 100644
index 00000000..0d5f5a54
--- /dev/null
+++ b/src/test/java/duke/testhelper/TestStream.java
@@ -0,0 +1,46 @@
+package duke.testhelper;
+
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+
+public class TestStream {
+
+ private ByteArrayOutputStream outputStreamCaptor;
+ private PrintStream printStream;
+
+ protected PrintStream getPrintStream() {
+ return this.printStream;
+ }
+
+ protected void setPrintStream(PrintStream ps) {
+ this.printStream = ps;
+ }
+
+ protected void setOutputStreamCaptor(ByteArrayOutputStream baos) {
+ this.outputStreamCaptor = baos;
+ }
+
+ protected ByteArrayOutputStream getOutputStreamCaptor() {
+ return this.outputStreamCaptor;
+ }
+
+ // helper class
+ protected String getOutput() {
+ return this.outputStreamCaptor.toString();
+ }
+
+ @BeforeEach
+ public void setOutputStream() {
+ this.setOutputStreamCaptor(new ByteArrayOutputStream());
+ this.setPrintStream(new PrintStream(this.getOutputStreamCaptor()));
+ }
+
+ @AfterEach
+ public void unsetStreams() {
+ this.setOutputStreamCaptor(null);
+ this.setPrintStream(null);
+ }
+}
diff --git a/src/test/java/duke/testhelper/help/Builder.java b/src/test/java/duke/testhelper/help/Builder.java
new file mode 100644
index 00000000..de360251
--- /dev/null
+++ b/src/test/java/duke/testhelper/help/Builder.java
@@ -0,0 +1,36 @@
+package duke.testhelper.help;
+
+import java.io.ByteArrayInputStream;
+
+public class Builder {
+
+
+ public static ByteArrayInputStream buildCommandInputStream(String... commands) {
+ return new ByteArrayInputStream(buildString(commands).getBytes());
+ }
+
+ /**
+ * Helper to combine array of strings.
+ *
+ * @param commands
+ * @return
+ */
+ public static String buildString(String... commands) {
+ StringBuilder commandBuilder = new StringBuilder();
+ for (String c : commands) {
+ commandBuilder.append(c);
+ }
+ return commandBuilder.toString();
+ }
+
+ /**
+ * Helper to build expected output response.
+ *
+ * @param responses
+ * @return output response
+ */
+ public static String buildExpectedResponse(String... responses) {
+ return buildString(responses);
+ }
+
+}
diff --git a/src/test/java/duke/testhelper/help/codeundertest/OutputUnderTest.java b/src/test/java/duke/testhelper/help/codeundertest/OutputUnderTest.java
new file mode 100644
index 00000000..6a5427f3
--- /dev/null
+++ b/src/test/java/duke/testhelper/help/codeundertest/OutputUnderTest.java
@@ -0,0 +1,109 @@
+package duke.testhelper.help.codeundertest;
+
+import java.nio.file.Path;
+
+public class OutputUnderTest {
+ private static final String LOGO = " _ _ _ "
+ + System.lineSeparator()
+ + "| | | | | | "
+ + System.lineSeparator()
+ + "| |_ __ _ ___ | | __ _ __ ___ __ _ ___ | |_ ___ _ __ "
+ + System.lineSeparator()
+ + "| __| / _` | / __| | |/ / | '_ ` _ \\ / _` | / __| | __| / _ \\ | '__|"
+ + System.lineSeparator()
+ + "| |_ | (_| | \\__ \\ | < | | | | | | | (_| | \\__ \\ | |_ | __/ | | "
+ + System.lineSeparator()
+ + " \\__| \\__,_| |___/ |_|\\_\\ |_| |_| |_| \\__,_| |___/ \\__| \\___| |_| "
+ + System.lineSeparator();
+
+ private static final String RESPONSE_TERMINATOR_UNDER_TEST = "\t\t\t\t\t\t\t\t -" + System.lineSeparator();
+
+ public static String getExpectedOutputEntry() {
+ return "Hello from" + System.lineSeparator() + LOGO;
+ }
+
+ public static String getExpectedOutputTerminate() {
+ return "See you again!" + System.lineSeparator();
+ }
+
+ public static String getExpectedOutputBeginInputLoop() {
+ return "How can i help you? (See README.md for usage)" + System.lineSeparator();
+ }
+
+ public static String getExpectedOutputImportAttempt(Path path) {
+ return "Attempting to import tasks from " + path + "." + System.lineSeparator();
+ }
+
+ public static String getExpectedOutputReadPathNotFound() {
+ return "Read path not found/invalid. " + System.lineSeparator();
+ }
+
+ public static String getExpectedOutputSaved(String pathString) {
+ return getExpectedOutputTemplate("Saved task to file: " + pathString);
+ }
+
+ public static String getExpectedOutputTemplate(String text) {
+ return text + System.lineSeparator() + RESPONSE_TERMINATOR_UNDER_TEST;
+ }
+
+
+ public static String getExpectedOutputExitInputLoop() {
+ return getExpectedOutputTemplate("ok bye");
+ }
+
+ public static String getExpectedOutputAddedToDo(String desc, Integer id) {
+ return getExpectedOutputTemplate("Added To Do [id #" + id + "]: " + desc);
+ }
+
+ public static String getExpectedOutputAddedDeadline(String desc, Integer id) {
+ return getExpectedOutputTemplate("Added Deadline [id #" + id + "]: " + desc);
+ }
+
+ public static String getExpectedOutputAddedEvent(String desc, Integer id) {
+ return getExpectedOutputTemplate("Added Event [id #" + id + "]: " + desc);
+
+ }
+
+ public static String getExpectedOutputList(String list) {
+ return list + RESPONSE_TERMINATOR_UNDER_TEST;
+ }
+
+ public static String getExpectedOutputStatsAll(String stats) {
+ return "Task Summary " + System.lineSeparator() + stats + RESPONSE_TERMINATOR_UNDER_TEST;
+ }
+
+ public static String getExpectedOutputListTasksWithKeywordDescription(String list, String keyword) {
+ String info = "Query keyword in description: " + keyword;
+ return info + System.lineSeparator() + list + RESPONSE_TERMINATOR_UNDER_TEST;
+ }
+
+ public static String getExpectedOutputListTasksWithinPeriod(String list, Integer period) {
+ String info = "All tasks for the next " + period + " days: ";
+ return info + System.lineSeparator() + list + RESPONSE_TERMINATOR_UNDER_TEST;
+ }
+
+ public static String getExpectedOutputTaskSetCompleted(Integer taskId) {
+ return getExpectedOutputTemplate("update done #" + taskId.toString());
+ }
+
+ public static String getExpectedOutputTaskSetIncomplete(Integer taskId) {
+ return getExpectedOutputTemplate("update not done #" + taskId.toString());
+ }
+
+ public static String getExpectedOutputCommandUnknown() {
+ return getExpectedOutputTemplate("Unknown command. . .");
+ }
+
+ public static String getExpectedOutputCommandDeleted(Integer taskId) {
+ return getExpectedOutputTemplate("Task Deleted: #" + taskId);
+ }
+
+ public static String getMsgUnderTestErrorSpacedKeyword() {
+ String text = "Invalid syntax. Keyword should not have spacing.";
+ return getExpectedOutputTemplate(text);
+ }
+
+ public static String getMsgUnderTestErrorParseStringAsLocalDate() {
+ return getExpectedOutputTemplate("Invalid parameters: java.lang.Exception: Parse as LocalDateTime failed.");
+ }
+}
diff --git a/src/test/java/duke/testhelper/help/codeundertest/ParserUnderTest.java b/src/test/java/duke/testhelper/help/codeundertest/ParserUnderTest.java
new file mode 100644
index 00000000..071e48d1
--- /dev/null
+++ b/src/test/java/duke/testhelper/help/codeundertest/ParserUnderTest.java
@@ -0,0 +1,67 @@
+package duke.testhelper.help.codeundertest;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+
+
+public class ParserUnderTest {
+ private static final String transitiveJsonAndTextPattern = "yyyy-MM-dd-HH-mm-ss";
+ private static final List patterns =
+ List.of("yyyyMMdd", "yyyyMMdd HH:mm", ParserUnderTest.transitiveJsonAndTextPattern);
+
+ public static String parseLocalDateTimeAsString(LocalDateTime ldt) {
+ return DateTimeFormatter.ofPattern(ParserUnderTest.transitiveJsonAndTextPattern).format(ldt);
+ }
+
+ /**
+ * Test Helper
+ * Format string as LocalDateTime. Multiple patterns will be attempted to match string.
+ *
+ * @param dateTimeString
+ * @return date
+ * @throws Exception if fail to format.
+ */
+ public static LocalDateTime parseStringAsLocalDateTime(String dateTimeString) throws Exception {
+ LocalDateTime ldt = null;
+ for (String pattern : ParserUnderTest.patterns) {
+ try {
+ ldt = LocalDateTime.parse(dateTimeString, DateTimeFormatter.ofPattern(pattern));
+ } catch (Exception e) {
+ }
+ }
+ try {
+ ldt = parseStringAsLocalDate(dateTimeString).atTime(0, 0);
+ } catch (Exception e) {
+ }
+ if (ldt == null) {
+ throw new Exception("Parse as LocalDateTime failed.");
+ }
+ return ldt;
+ }
+
+ public static LocalDate parseStringAsLocalDate(String dateString) {
+ return LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyyMMdd"));
+ }
+
+ public static String prettifyLocalDateTime(LocalDateTime ldt) {
+ return ldt.toString().replace("T", " ");
+ }
+
+ /**
+ * Helper for parsing string as path
+ *
+ * @param pathString
+ * @return
+ */
+ public static Path stringToPath(String pathString) {
+ try {
+ return Paths.get(pathString);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+}
diff --git a/src/test/java/duke/testhelper/help/codeundertest/PrettifyUnderTest.java b/src/test/java/duke/testhelper/help/codeundertest/PrettifyUnderTest.java
new file mode 100644
index 00000000..ee6f33c4
--- /dev/null
+++ b/src/test/java/duke/testhelper/help/codeundertest/PrettifyUnderTest.java
@@ -0,0 +1,204 @@
+package duke.testhelper.help.codeundertest;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import duke.mock.mocktask.MockDeadline;
+import duke.mock.mocktask.MockEvent;
+import duke.mock.mocktask.MockTask;
+import duke.mock.mocktask.MockToDo;
+import duke.task.model.Deadline;
+import duke.task.model.Event;
+import duke.task.model.Task;
+import duke.task.model.ToDo;
+
+public class PrettifyUnderTest {
+
+ private static String getTaskCharCodeUnderTest(MockTask task) {
+ if (task instanceof MockToDo) {
+ return "T";
+ }
+ if (task instanceof MockEvent) {
+ return "E";
+ }
+ if (task instanceof MockDeadline) {
+ return "D";
+ }
+ return " ";
+ }
+
+ private static String getTaskChronologyString(MockTask task) {
+ if (task instanceof MockToDo) {
+ return "-";
+ }
+ if (task instanceof MockEvent) {
+ return "From: " + ((MockEvent) task).getFromDateString() + ", To: " + ((MockEvent) task).getToDateString();
+ }
+ if (task instanceof MockDeadline) {
+ return "By: " + ((MockDeadline) task).getbyDateString();
+ }
+ return " ";
+ }
+
+ private static String fillCellUnderTest(String value, Integer lengthColMax) {
+ int lengthValue = value.length();
+ int lengthPad = lengthColMax - lengthValue;
+ return String.format("%s%s", value,
+ String.format("%" + (lengthPad > 0 ? lengthPad : "") + "s", (lengthPad > 0 ? " " : "")));
+ }
+
+ public static String getExpectedTaskList(MockTask... mockTasks) {
+
+ int taskQty = mockTasks.length;
+ StringBuilder generating = new StringBuilder();
+ generating.append((taskQty + " task" + (taskQty > 1 ? "s" : "") + " in list" + System.lineSeparator()));
+ /* header values */
+
+ String headerId = String.format(" %-4s ", "id#");
+ String headerDoneStatus = "Done ";
+ String headerTaskType = "Type ";
+ String headerDescription = "Task Description ";
+ String headerChronology = "Chronology";
+
+ /* append headers */
+
+ generating.append(headerId);
+ generating.append(headerDoneStatus);
+ generating.append(headerTaskType);
+ generating.append(headerDescription);
+ generating.append(headerChronology);
+ generating.append(System.lineSeparator());
+
+ /* column width references */
+
+ int lengthColId = headerId.length();
+ int lengthColTaskType = headerTaskType.length();
+ int lengthColDoneStatus = headerDoneStatus.length();
+ int lengthColDesc = headerDescription.length();
+
+ for (MockTask task : mockTasks) {
+ // fill column Id
+ String idValue = String.format("%4d", task.getId()).replace(" ", "0");
+ String columnId = fillCellUnderTest(idValue, lengthColId);
+
+ // fill column Done Status
+ String doneStatusValue = String.format("[%s]", task.getDone() ? "X" : " ");
+ String columnDoneStatus = fillCellUnderTest(doneStatusValue, lengthColDoneStatus);
+ // fill column Task Type Status
+ String taskTypeSymbolValue = String.format("[%s]", getTaskCharCodeUnderTest(task));
+ String columnTaskType = fillCellUnderTest(taskTypeSymbolValue, lengthColTaskType);
+ // fill column Description
+ String descValueLong = task.getDesc();
+ String descValue = descValueLong.substring(0, Math.min(descValueLong.length(), lengthColDesc - 1));
+ String columnDescription = fillCellUnderTest(descValue, lengthColDesc);
+ // fill column Chronology
+ String columnChronology = getTaskChronologyString(task);
+
+ generating.append(columnId);
+ generating.append(columnDoneStatus);
+ generating.append(columnTaskType);
+ generating.append(columnDescription);
+ generating.append(columnChronology);
+ generating.append(System.lineSeparator());
+ }
+ String generated = generating.toString();
+ return generated;
+ }
+
+ public static String getExpectedStatisticsAll(ArrayList tasks) {
+ // Tabulate
+ int col = 0;
+ int colDone = col++;
+ int colNotDone = col++;
+ int row = 0;
+ int rowToDo = row++;
+ int rowDeadline = row++;
+ int rowEvent = row++;
+
+
+ Integer[][] stats = new Integer[col][row];
+ for (Integer[] ints : stats) {
+ Arrays.fill(ints, 0);
+ }
+ for (Task t : tasks) {
+
+ Integer thisRow = null;
+ if (t instanceof ToDo) {
+ thisRow = rowToDo;
+ } else if (t instanceof Deadline) {
+ thisRow = rowDeadline;
+ } else if (t instanceof Event) {
+ thisRow = rowEvent;
+ }
+ Integer thisCol = null;
+ if (t.isDone()) {
+ thisCol = colDone;
+ } else {
+ thisCol = colNotDone;
+ }
+ assert (thisCol != null);
+ assert (thisRow != null);
+ if (thisCol != null && thisRow != null) {
+ stats[thisCol][thisRow]++;
+ }
+ }
+ int rowHeader = row++;
+ int colTaskType = col++;
+ String[][] table = new String[col][row];
+ for (String[] tableRow : table) {
+ Arrays.fill(tableRow, "");
+ }
+ table[0][rowHeader] = "Task Type ";
+ table[0][rowToDo] = "To Do";
+ table[0][rowDeadline] = "Deadline";
+ table[0][rowEvent] = "Event";
+
+ table[2][rowHeader] = "Incomplete ";
+ table[2][rowToDo] = stats[colNotDone][rowToDo].toString();
+ table[2][rowDeadline] = stats[colNotDone][rowDeadline].toString();
+ table[2][rowEvent] = stats[colNotDone][rowEvent].toString();
+
+ table[1][rowHeader] = "Complete ";
+ table[1][rowToDo] = stats[colDone][rowToDo].toString();
+ table[1][rowDeadline] = stats[colDone][rowDeadline].toString();
+ table[1][rowEvent] = stats[colDone][rowEvent].toString();
+
+
+ int[] colLength = new int[col];
+
+ colLength[colTaskType] = getMaxLength(table[colTaskType]);
+ colLength[colNotDone] = getMaxLength(table[colNotDone]);
+ colLength[colDone] = getMaxLength(table[colDone]);
+
+
+ for (int c = 0; c < col; c++) {
+ for (int r = 0; r < row; r++) {
+ table[c][r] = fillCellUnderTest(table[c][r], colLength[c]);
+ }
+ }
+ StringBuilder lines = new StringBuilder();
+
+ lines.append(String.join("", getRowValue(table, rowHeader)) + System.lineSeparator());
+ lines.append(String.join("", getRowValue(table, rowToDo)) + System.lineSeparator());
+ lines.append(String.join("", getRowValue(table, rowDeadline)) + System.lineSeparator());
+ lines.append(String.join("", getRowValue(table, rowEvent)) + System.lineSeparator());
+ return lines.toString();
+ }
+
+ public static String getRowValue(String[][] table, int r) {
+ StringBuilder result = new StringBuilder();
+ for (int c = 0; c < table.length; c++) {
+ result.append(table[c][r]);
+ }
+ return result.toString();
+ }
+
+ private static int getMaxLength(String[] strings) {
+ int maxLength = 0;
+ for (String s : strings) {
+ maxLength = Math.max(maxLength, s.length());
+ }
+ return maxLength;
+
+ }
+}
diff --git a/src/test/java/duke/testhelper/help/codeundertest/TextCommandUnderTest.java b/src/test/java/duke/testhelper/help/codeundertest/TextCommandUnderTest.java
new file mode 100644
index 00000000..ec8c500b
--- /dev/null
+++ b/src/test/java/duke/testhelper/help/codeundertest/TextCommandUnderTest.java
@@ -0,0 +1,92 @@
+package duke.testhelper.help.codeundertest;
+
+public class TextCommandUnderTest {
+ public static final String PROMPT_UNDER_TEST_EXIT_LOOP = "bye";
+ public static final String PROMPT_UNDER_TEST_LIST = "list";
+ public static final String PROMPT_UNDER_TEST_STATS_ALL = "stats:all";
+ public static final String PROMPT_UNDER_TEST_SCAN_DUPLICATE_DESCRIPTION = "scan:duplicates";
+ public static final String PROMPT_UNDER_TEST_PROJECTION = "projection ";
+
+ public static final String PROMPT_UNDER_TEST_MARK_AS_DONE = "done ";
+ public static final String PROMPT_UNDER_TEST_MARK_AS_INCOMPLETE = "undone ";
+
+ public static final String PROMPT_UNDER_TEST_ADD_TO_DO = "todo ";
+
+ public static final String PROMPT_UNDER_TEST_ADD_DEADLINE = "deadline ";
+ public static final String DELIMITER_DEADLINE_DEADLINE = " /by ";
+
+ public static final String PROMPT_UNDER_TEST_ADD_EVENT = "event ";
+ public static final String DELIMITER_EVENT_EVENT = " /at ";
+ public static final String DELIMITER_EVENT_TO = "-";
+
+ public static final String PROMPT_UNDER_TEST_DELETE_TASK = "delete ";
+
+ public static final String PROMPT_UNDER_TEST_SAVE = "save";
+
+ public static final String PROMPT_UNDER_TEST_FIND = "find ";
+
+ private static String singleArgumentCommand(String text) {
+ return text + System.lineSeparator();
+ }
+
+ public static String generateTextCommandExit() {
+ return singleArgumentCommand(PROMPT_UNDER_TEST_EXIT_LOOP);
+ }
+
+ public static String generateTextCommandStatsAll() {
+ return singleArgumentCommand(PROMPT_UNDER_TEST_STATS_ALL);
+ }
+
+ public static String generateTextCommandRandom(String text) {
+ return singleArgumentCommand(text);
+ }
+
+ public static String generateTextCommandList() {
+ return singleArgumentCommand(PROMPT_UNDER_TEST_LIST);
+ }
+
+ public static String generateTextCommandSetCompleted(Integer taskId) {
+ return PROMPT_UNDER_TEST_MARK_AS_DONE + taskId + System.lineSeparator();
+ }
+
+ public static String generateTextCommandSetIncomplete(Integer taskId) {
+ return PROMPT_UNDER_TEST_MARK_AS_INCOMPLETE + taskId + System.lineSeparator();
+ }
+
+ public static String generateTextCommandScanDuplicateDescription() {
+ return PROMPT_UNDER_TEST_SCAN_DUPLICATE_DESCRIPTION + System.lineSeparator();
+ }
+
+ public static String generateTextCommandLineAddToDo(String description) {
+ return PROMPT_UNDER_TEST_ADD_TO_DO + description + System.lineSeparator();
+ }
+
+ public static String generateTextCommandLineAddDeadline(String description,
+ String deadlineString) {
+ return PROMPT_UNDER_TEST_ADD_DEADLINE + description + DELIMITER_DEADLINE_DEADLINE + deadlineString +
+ System.lineSeparator();
+ }
+
+ public static String generateTextCommandLineAddEvent(String desc,
+ String from,
+ String to) {
+ return PROMPT_UNDER_TEST_ADD_EVENT + desc + DELIMITER_EVENT_EVENT + from + DELIMITER_EVENT_TO + to +
+ System.lineSeparator();
+ }
+
+ public static String generateTextCommandDeleteTaskByTaskId(String invoke, Integer taskId) {
+ return invoke + taskId + System.lineSeparator();
+ }
+
+ public static String generateTextCommandSave(String invoke) {
+ return singleArgumentCommand(invoke);
+ }
+
+ public static String generateTextCommandFindKeywordInDescription(String invoke, String keyword) {
+ return invoke + keyword + System.lineSeparator();
+ }
+
+ public static String generateTextCommandProjection(Integer days) {
+ return PROMPT_UNDER_TEST_PROJECTION + days + System.lineSeparator();
+ }
+}
diff --git a/src/test/java/duke/testhelper/help/config/DukeIoTestPath.java b/src/test/java/duke/testhelper/help/config/DukeIoTestPath.java
new file mode 100644
index 00000000..20ff3fdb
--- /dev/null
+++ b/src/test/java/duke/testhelper/help/config/DukeIoTestPath.java
@@ -0,0 +1,35 @@
+package duke.testhelper.help.config;
+
+
+import java.io.File;
+
+public class DukeIoTestPath {
+
+ private static final String resourceTestFolder =
+ String.join(File.separator, new String[] {System.getProperty("user.home"), "duke", "test"});
+
+ private static String testPathStringDefaultTasksExportJsonPath = null;
+ private static String testPathStringDefaultTasksImportPath = null;
+
+ public static String getDefaultTasksTestExportPathString() {
+ if (DukeIoTestPath.testPathStringDefaultTasksExportJsonPath == null) {
+ DukeIoTestPath.testPathStringDefaultTasksExportJsonPath =
+ DukeIoTestPath.resourceTestFolder + File.separator + "exports" + File.separator + "tasks.json";
+ }
+ return DukeIoTestPath.testPathStringDefaultTasksExportJsonPath;
+ }
+
+ public static String getResourceTestFolder() {
+ return DukeIoTestPath.resourceTestFolder;
+ }
+
+ public static String getDefaultTasksImportTestPathString() {
+ if (DukeIoTestPath.testPathStringDefaultTasksImportPath == null) {
+ DukeIoTestPath.testPathStringDefaultTasksImportPath =
+ DukeIoTestPath.resourceTestFolder + File.separator + "imports" + File.separator + "tasks.json";
+ }
+ return DukeIoTestPath.testPathStringDefaultTasksImportPath;
+ }
+
+
+}
diff --git a/src/test/java/duke/unittest/UiTest.java b/src/test/java/duke/unittest/UiTest.java
new file mode 100644
index 00000000..8b7fc49b
--- /dev/null
+++ b/src/test/java/duke/unittest/UiTest.java
@@ -0,0 +1,140 @@
+package duke.unittest;
+
+import static duke.testhelper.help.Builder.buildCommandInputStream;
+import static duke.testhelper.help.Builder.buildExpectedResponse;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputBeginInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputExitInputLoop;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputListTasksWithinPeriod;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputStatsAll;
+import static duke.testhelper.help.codeundertest.OutputUnderTest.getExpectedOutputTemplate;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.time.LocalDateTime;
+
+import org.junit.jupiter.api.Test;
+
+import duke.TaskManager;
+import duke.Ui;
+import duke.mock.mocktask.MockDeadline;
+import duke.mock.mocktask.MockEvent;
+import duke.task.model.Deadline;
+import duke.task.model.Event;
+import duke.task.model.ToDo;
+import duke.testhelper.TestStream;
+import duke.testhelper.help.codeundertest.PrettifyUnderTest;
+import duke.testhelper.help.codeundertest.TextCommandUnderTest;
+
+public class UiTest extends TestStream {
+
+ @Test
+ public void project_withinNextDays_filteredAndSorted() throws Exception {
+ int period = 30;
+ // create some tasks spanning across different days in task manager, expect filter range in period of days.
+
+ Ui ui = new Ui(this.getPrintStream());
+ TaskManager tm = new TaskManager();
+
+ // Add tasks to task manager and mock expected tasks
+
+ // task 0
+ String toDoDesc = "todo should not appear";
+ tm.addNewToDo(toDoDesc);
+
+ // task 1
+ String deadlineDesc = "due in " + period + " days";
+ LocalDateTime dldl = LocalDateTime.now().plusDays(period);
+ tm.addNewDeadline(deadlineDesc, dldl);
+ MockDeadline task1 = new MockDeadline(deadlineDesc, 1, false, dldl);
+
+ // task 2
+ tm.addNewDeadline("assignment due beyond period", LocalDateTime.now().plusDays(period + 200));
+
+ // task 3
+ String eventDesc = "event start today";
+ LocalDateTime from = LocalDateTime.now();
+ LocalDateTime to = LocalDateTime.now().plusDays(period + 1);
+ tm.addNewEvent(eventDesc, from, to);
+ MockEvent task3 = new MockEvent(eventDesc, 3, false, from, to);
+
+ // build commands
+ String out0 = getExpectedOutputBeginInputLoop();
+ String in0 = TextCommandUnderTest.generateTextCommandProjection(period);
+
+ String expectedList = PrettifyUnderTest.getExpectedTaskList(task3, task1);
+ String out1 = getExpectedOutputListTasksWithinPeriod(expectedList, period);
+
+ String in1 = TextCommandUnderTest.generateTextCommandExit();
+ String out2 = getExpectedOutputExitInputLoop();
+
+ // set commands to input stream
+ System.setIn(buildCommandInputStream(in0, in1));
+ ui.runTextCommandLoop(tm, null);
+
+ String expectedOutput = buildExpectedResponse(out0, out1, out2);
+ assertEquals(expectedOutput, this.getOutput());
+ }
+
+ /**
+ * create a collection of tasks, summarise by task type and completion status.
+ */
+ @Test
+ public void stats_showSummaryAll() throws Exception {
+
+ TaskManager tm = new TaskManager();
+ int expectedCountToDo = 0;
+ int expectedCountDeadline = 0;
+ int expectedCountEvent = 0;
+ LocalDateTime date = LocalDateTime.now();
+ ToDo task0 = tm.addNewToDo("todo done" + expectedCountToDo++);
+ task0.setDoneStatus(true);
+ Deadline task1 = tm.addNewDeadline("deadline" + expectedCountDeadline++, date);
+ Event task2 = tm.addNewEvent("event" + expectedCountEvent++, date, date);
+
+ String out0 = getExpectedOutputBeginInputLoop();
+ String in0 = TextCommandUnderTest.generateTextCommandStatsAll();
+ String stats = PrettifyUnderTest.getExpectedStatisticsAll(tm.getAllAsArray());
+ String out1 = getExpectedOutputStatsAll(stats);
+ String in1 = TextCommandUnderTest.generateTextCommandExit();
+ String out2 = getExpectedOutputExitInputLoop();
+ System.setIn(buildCommandInputStream(in0, in1));
+ String expectedOutput = buildExpectedResponse(out0, out1, out2);
+ new Ui(this.getPrintStream()).runTextCommandLoop(tm, null);
+ assertEquals(expectedOutput, this.getOutput());
+ }
+
+ /**
+ * Check and show task ids of duplicates.
+ */
+ @Test
+ public void scan_checkDuplicateDescription() throws Exception {
+ TaskManager tm = new TaskManager();
+ LocalDateTime date = LocalDateTime.now();
+
+ tm.addNewEvent("task0", date, date);
+ tm.addNewToDo("task0");
+ tm.addNewDeadline("task0", date);
+
+ tm.addNewEvent("task1", date, date);
+ tm.addNewToDo("task1");
+ tm.addNewDeadline("task1", date);
+
+
+ tm.addNewDeadline("unique desc", date);
+
+ String out0 = getExpectedOutputBeginInputLoop();
+
+ String in0 = TextCommandUnderTest.generateTextCommandScanDuplicateDescription();
+ String dupes =
+ "Duplicates \"[Description]\":[...(id,type)] " + System.lineSeparator() + "\"" + "task0" +
+ "\"" + ": [0 (E), 1 (T), 2 (D)]" +
+ System.lineSeparator() + "\"" + "task1" + "\"" + ": [3 (E), 4 (T), 5 (D)]";
+ String out1 = getExpectedOutputTemplate(dupes);
+ String in1 = TextCommandUnderTest.generateTextCommandExit();
+ String out2 = getExpectedOutputExitInputLoop();
+
+ System.setIn(buildCommandInputStream(in0, in1));
+ String expectedOutput = buildExpectedResponse(out0, out1, out2);
+ new Ui(this.getPrintStream()).runTextCommandLoop(tm, null);
+ assertEquals(expectedOutput, this.getOutput());
+ }
+}
diff --git a/src/test/java/duke/unittest/taskmanagertest/ExportTasksTest.java b/src/test/java/duke/unittest/taskmanagertest/ExportTasksTest.java
new file mode 100644
index 00000000..98a582f0
--- /dev/null
+++ b/src/test/java/duke/unittest/taskmanagertest/ExportTasksTest.java
@@ -0,0 +1,35 @@
+package duke.unittest.taskmanagertest;
+
+import static duke.testhelper.help.config.DukeIoTestPath.getDefaultTasksTestExportPathString;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+import duke.FileResourceManager;
+import duke.TaskManager;
+import duke.command.Command;
+import duke.dukeutility.enums.ResponseType;
+import duke.testhelper.TestStream;
+
+
+public class ExportTasksTest extends TestStream {
+ /**
+ * This test checks if file path is writable.
+ */
+ @Test
+ public void addToDos_export_shouldBuffer() {
+ TaskManager tm = new TaskManager();
+
+ String desc0 = "desc0";
+ String desc1 = "desc1";
+ tm.addNewToDo(desc0);
+ tm.addNewToDo(desc1);
+ assertEquals(desc0, tm.getTaskById(0).getTaskDescription());
+ assertEquals(desc1, tm.getTaskById(1).getTaskDescription());
+
+ FileResourceManager frm = new FileResourceManager(getDefaultTasksTestExportPathString(), null);
+ Command c = frm.executeSave(tm);
+ assertEquals(ResponseType.FILE_SAVED, c.getResponseType());
+ }
+
+}
diff --git a/src/test/java/duke/unittest/taskmanagertest/ImportTasksTest.java b/src/test/java/duke/unittest/taskmanagertest/ImportTasksTest.java
new file mode 100644
index 00000000..a1f97f2c
--- /dev/null
+++ b/src/test/java/duke/unittest/taskmanagertest/ImportTasksTest.java
@@ -0,0 +1,58 @@
+package duke.unittest.taskmanagertest;
+
+import static duke.testhelper.help.config.DukeIoTestPath.getDefaultTasksTestExportPathString;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+import com.google.gson.JsonArray;
+
+import duke.FileResourceManager;
+import duke.TaskManager;
+import duke.command.Command;
+import duke.command.CommandJsonResponse;
+import duke.dukeutility.enums.ResponseType;
+import duke.testhelper.TestStream;
+
+
+public class ImportTasksTest extends TestStream {
+
+ /**
+ * Save tasks from task manager 1 to a file, extract tasks from file and load (import) into task manager 2.
+ * The tasks in each manager should be the same.
+ * That is, exported data and imported data should be idempotent.
+ */
+ @Test
+ public void addToDos_exportExtractLoad() {
+
+ // add new tasks to task manager 1
+ TaskManager tm1 = new TaskManager();
+
+ String desc0 = "desc0";
+ String desc1 = "desc1";
+ tm1.addNewToDo(desc0);
+ tm1.addNewToDo(desc1);
+ assertEquals(desc0, tm1.getTaskById(0).getTaskDescription());
+ assertEquals(desc1, tm1.getTaskById(1).getTaskDescription());
+
+ String exportPathString = getDefaultTasksTestExportPathString();
+ String importPathString = exportPathString;
+ FileResourceManager frm = new FileResourceManager(exportPathString, importPathString);
+
+ // export
+ Command c = frm.executeSave(tm1);
+ assertEquals(ResponseType.FILE_SAVED, c.getResponseType());
+ // extract
+ CommandJsonResponse reading = frm.executeExtractTasksFromFile();
+ assertEquals(ResponseType.FILE_READ, reading.getResponseType());
+ // load / import
+ JsonArray tasksFromFile = (JsonArray) reading.getJsonArg();
+
+ TaskManager tm2 = new TaskManager();
+ frm.importTasks(tasksFromFile, tm2);
+
+ // compares tasks
+ assertEquals(tm2.getTaskById(0).getTaskDescription(), tm1.getTaskById(0).getTaskDescription());
+ assertEquals(tm2.getTaskById(1).getTaskDescription(), tm1.getTaskById(1).getTaskDescription());
+ }
+}
diff --git a/src/test/java/duke/unittest/taskmanagertest/TaskManagerTest.java b/src/test/java/duke/unittest/taskmanagertest/TaskManagerTest.java
new file mode 100644
index 00000000..559356e7
--- /dev/null
+++ b/src/test/java/duke/unittest/taskmanagertest/TaskManagerTest.java
@@ -0,0 +1,71 @@
+package duke.unittest.taskmanagertest;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.time.LocalDateTime;
+import org.junit.jupiter.api.Test;
+
+import duke.TaskManager;
+import duke.task.model.Event;
+import duke.testhelper.TestStream;
+import duke.testhelper.help.codeundertest.ParserUnderTest;
+
+public class TaskManagerTest extends TestStream {
+
+
+ /**
+ * Add todos to a task manager.
+ */
+ @Test
+ public void addToDos() {
+ TaskManager tm = new TaskManager();
+
+ String desc0 = "desc0";
+ String desc1 = "desc1";
+ tm.addNewToDo(desc0);
+ tm.addNewToDo(desc1);
+ assertEquals(desc0, tm.getTaskById(0).getTaskDescription());
+ assertEquals(desc1, tm.getTaskById(1).getTaskDescription());
+ }
+
+ /**
+ * Add events to a task manager.
+ */
+ @Test
+ public void addEvents() throws Exception {
+ TaskManager tm = new TaskManager();
+
+ String desc0 = "desc0";
+ String desc1 = "desc1";
+ tm.addNewEvent(desc0, ParserUnderTest.parseStringAsLocalDateTime("20210101"),
+ ParserUnderTest.parseStringAsLocalDateTime("20210101"));
+
+ LocalDateTime from1 = ParserUnderTest.parseStringAsLocalDateTime("20210101");
+ LocalDateTime to1 = ParserUnderTest.parseStringAsLocalDateTime("20210101");
+ tm.addNewEvent(desc1, from1, to1);
+
+ assertEquals(desc0, tm.getTaskById(0).getTaskDescription());
+ assertEquals(desc1, tm.getTaskById(1).getTaskDescription());
+
+ assertEquals(from1, ((Event) tm.getTaskById(1)).getFrom());
+ assertEquals(to1, ((Event) tm.getTaskById(1)).getTo());
+ }
+
+ /**
+ * Add find tasks in a task manager.
+ */
+ @Test
+ public void findTasksByDescription() throws Exception {
+ TaskManager tm = new TaskManager();
+
+ String keyword = "MAGIK";
+ LocalDateTime from0 = ParserUnderTest.parseStringAsLocalDateTime("20210101");
+ LocalDateTime to0 = ParserUnderTest.parseStringAsLocalDateTime("20210202");
+ LocalDateTime from1 = ParserUnderTest.parseStringAsLocalDateTime("20210101");
+ LocalDateTime to1 = ParserUnderTest.parseStringAsLocalDateTime("20210202");
+ tm.addNewEvent("desc0", from0, to0);
+ tm.addNewEvent("desc1 " + keyword + " a", from1, to1); // with keyword
+
+ assertEquals(1, tm.getTasksWithKeywordInDescription(keyword).size());
+ }
+}
diff --git a/src/test/java/duke/unittest/taskmanagertest/ToggleDoneTest.java b/src/test/java/duke/unittest/taskmanagertest/ToggleDoneTest.java
new file mode 100644
index 00000000..98144fb6
--- /dev/null
+++ b/src/test/java/duke/unittest/taskmanagertest/ToggleDoneTest.java
@@ -0,0 +1,31 @@
+package duke.unittest.taskmanagertest;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+import duke.TaskManager;
+import duke.testhelper.TestStream;
+
+public class ToggleDoneTest extends TestStream {
+
+
+ /**
+ * Add todos to a task manager.
+ */
+ @Test
+ public void addToDosSetUnsetDone() {
+ TaskManager tm = new TaskManager();
+
+ String desc0 = "desc0";
+ tm.addNewToDo(desc0);
+ assertEquals(desc0, tm.getTaskById(0).getTaskDescription());
+
+ tm.getTaskByIdAndSetCompleted(0);
+ assertTrue(tm.getTaskById(0).isDone());
+ tm.getTaskByIdAndSetIncomplete(0);
+ assertFalse(tm.getTaskById(0).isDone());
+ }
+}
diff --git a/src/test/java/duke/unittest/tasktest/ComparisonTest.java b/src/test/java/duke/unittest/tasktest/ComparisonTest.java
new file mode 100644
index 00000000..707a38d7
--- /dev/null
+++ b/src/test/java/duke/unittest/tasktest/ComparisonTest.java
@@ -0,0 +1,25 @@
+package duke.unittest.tasktest;
+
+import static duke.testhelper.help.codeundertest.ParserUnderTest.parseStringAsLocalDate;
+import static duke.testhelper.help.codeundertest.ParserUnderTest.parseStringAsLocalDateTime;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import duke.task.TaskComparator;
+import duke.task.model.Deadline;
+import duke.testhelper.TestStream;
+
+public class ComparisonTest extends TestStream {
+
+ @Test
+ public void shouldBeSameDay() throws Exception {
+ LocalDateTime dl = parseStringAsLocalDateTime("20200101 00:50");
+ Deadline deadline = new Deadline("writing assignment", dl, 0, false);
+ LocalDate targetDate = parseStringAsLocalDate("20200101");
+ Assertions.assertTrue(TaskComparator.isSameDay(deadline, targetDate));
+ }
+}
+
diff --git a/src/test/java/duke/unittest/tasktest/EventTest.java b/src/test/java/duke/unittest/tasktest/EventTest.java
new file mode 100644
index 00000000..4b187252
--- /dev/null
+++ b/src/test/java/duke/unittest/tasktest/EventTest.java
@@ -0,0 +1,29 @@
+package duke.unittest.tasktest;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+import duke.TaskManager;
+import duke.command.Command;
+import duke.command.commandfactory.UiCommandFactory;
+import duke.command.errorcommand.CommandInvalidRequestParameters;
+import duke.testhelper.help.codeundertest.TextCommandUnderTest;
+
+
+public class EventTest {
+ @Test
+ void createEventTest_expectInvalidDateStringToReturnCommandError() {
+ String desc = "event1";
+ String fromString = "nonsense day1";
+ String toString = "asdasdasd asdasd ";
+ int id = 1;
+ boolean done = false;
+
+ String textCommand = TextCommandUnderTest.generateTextCommandLineAddEvent(desc, fromString, toString);
+ Command c = new UiCommandFactory().executeTextCommand(textCommand, new TaskManager(), null);
+
+ assertTrue(c instanceof CommandInvalidRequestParameters);
+ }
+
+}
diff --git a/src/test/java/duke/unittest/tasktest/aggregator/TaskListTest.java b/src/test/java/duke/unittest/tasktest/aggregator/TaskListTest.java
new file mode 100644
index 00000000..b636170c
--- /dev/null
+++ b/src/test/java/duke/unittest/tasktest/aggregator/TaskListTest.java
@@ -0,0 +1,31 @@
+package duke.unittest.tasktest.aggregator;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+import duke.task.aggregator.TaskList;
+import duke.task.model.ToDo;
+import duke.testhelper.TestStream;
+
+public class TaskListTest extends TestStream {
+ /**
+ * Adds tasks to task manager.
+ */
+ @Test
+ public void addToDos() {
+
+ TaskList tl = new TaskList();
+ String task0Description = "task 0";
+ tl.addTask(new ToDo(task0Description, 0, false));
+ assertEquals(task0Description, tl.getTaskById(0).getTaskDescription());
+ String task1Description = "task 1";
+ tl.addTask(new ToDo(task1Description, 1, false));
+ assertEquals(task1Description, tl.getTaskById(1).getTaskDescription());
+ assertTrue(tl.containsKey(0));
+ assertTrue(tl.containsKey(1));
+ assertFalse(tl.containsKey(2));
+ }
+}
diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT
deleted file mode 100644
index 657e74f6..00000000
--- a/text-ui-test/EXPECTED.TXT
+++ /dev/null
@@ -1,7 +0,0 @@
-Hello from
- ____ _
-| _ \ _ _| | _____
-| | | | | | | |/ / _ \
-| |_| | |_| | < __/
-|____/ \__,_|_|\_\___|
-
diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt
deleted file mode 100644
index e69de29b..00000000
diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat
deleted file mode 100644
index 08737446..00000000
--- a/text-ui-test/runtest.bat
+++ /dev/null
@@ -1,21 +0,0 @@
-@ECHO OFF
-
-REM create bin directory if it doesn't exist
-if not exist ..\bin mkdir ..\bin
-
-REM delete output from previous run
-if exist ACTUAL.TXT del ACTUAL.TXT
-
-REM compile the code into the bin folder
-javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\*.java
-IF ERRORLEVEL 1 (
- echo ********** BUILD FAILURE **********
- exit /b 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
-
-REM compare the output to the expected output
-FC ACTUAL.TXT EXPECTED.TXT
diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh
deleted file mode 100644
index c9ec8700..00000000
--- a/text-ui-test/runtest.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env bash
-
-# create bin directory if it doesn't exist
-if [ ! -d "../bin" ]
-then
- mkdir ../bin
-fi
-
-# delete output from previous run
-if [ -e "./ACTUAL.TXT" ]
-then
- rm ACTUAL.TXT
-fi
-
-# compile the code into the bin folder, terminates if error occurred
-if ! javac -cp ../src/main/java -Xlint:none -d ../bin ../src/main/java/*.java
-then
- echo "********** BUILD FAILURE **********"
- exit 1
-fi
-
-# run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT
-java -classpath ../bin Duke < input.txt > ACTUAL.TXT
-
-# convert to UNIX format
-cp EXPECTED.TXT EXPECTED-UNIX.TXT
-dos2unix ACTUAL.TXT EXPECTED-UNIX.TXT
-
-# compare the output to the expected output
-diff ACTUAL.TXT EXPECTED-UNIX.TXT
-if [ $? -eq 0 ]
-then
- echo "Test result: PASSED"
- exit 0
-else
- echo "Test result: FAILED"
- exit 1
-fi
\ No newline at end of file