diff --git a/.classpath b/.classpath
new file mode 100644
index 00000000..225833aa
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,12 @@
+
+
+ * initialize the ui, fileAccess and taskList + * load the progress into taskList + */ + public Duke(String filepath) { + ui = new Ui(); + fileAccess = new FileAccess(filepath); + myList = new TaskList(); + + try { + String progress = fileAccess.loadProgressFromFile(); + new LoadDuke(myList, progress).run(); + } catch (UnableToLoadProcessException e) { + Message.msgUnableToLoadProgress(); + } + } + + /** + * Start the Duke program + */ + public void initialize() { + StartDuke.run(); + new RunDuke(myList, ui, fileAccess).run(); + } + + /** + * End the Duke program + */ + public void end() { + new EndDuke(fileAccess).run(); + } + + /** + * Starting point of the program + */ + public static void main(String[] args) { + Duke duke = new Duke("src\\resources\\progress.txt"); + duke.initialize(); + duke.end(); + } +} diff --git a/src/main/java/duke/EndDuke.java b/src/main/java/duke/EndDuke.java new file mode 100644 index 00000000..6e9db128 --- /dev/null +++ b/src/main/java/duke/EndDuke.java @@ -0,0 +1,47 @@ +package duke; + +import duke.exception.UnableToLoadBuddhaException; +import duke.storage.FileAccess; +import duke.ui.Message; + +/** + * Duke class that executes when Duke is ending + * + * @author Kang Teng + * @version 8.0 + * @since 2021-09-01 + */ + +public class EndDuke { + + private static FileAccess fileAccess; + + /** + * Constructor + */ + public EndDuke(FileAccess fileAccess) { + this.fileAccess = fileAccess; + } + + /** + * Start the end sequence + */ + public static void run() { + showByeMessage(); + } + + /** + * Show the Bye Message + *
+ * called when Duke program ends + */ + public static void showByeMessage() { + try { + Message.msgBye(); + String buddhaText = fileAccess.readBuddhaText(); + Message.msgBuddha(buddhaText); + } catch (UnableToLoadBuddhaException e) { + Message.msgUnableToLoadBuddha(); + } + } +} diff --git a/src/main/java/duke/LoadDuke.java b/src/main/java/duke/LoadDuke.java new file mode 100644 index 00000000..926ef410 --- /dev/null +++ b/src/main/java/duke/LoadDuke.java @@ -0,0 +1,152 @@ +package duke; + +import java.time.LocalDate; +import java.time.LocalTime; + +import duke.action.ParseDateTime; +import duke.action.ParseProgress; +import duke.exception.UnableToLoadProcessException; +import duke.task.TaskList; +import duke.task.TaskPriority; +import duke.ui.Message; + +/** + * Duke class that executes when Duke is loading progress + * + * @author Kang Teng + * @version 8.0 + * @since 2021-09-01 + */ + +public class LoadDuke { + + private TaskList myList; + private String progress; + private String[] sentences; + + /** + * Constructor + */ + public LoadDuke(TaskList myList, String progress) { + this.myList = myList; + this.progress = progress; + } + + /** + * Execute the load + */ + public void run() throws UnableToLoadProcessException { + try { + splitStringByTask(); + createTaskFromSentence(); + } catch (Exception e) { + Message.msgError(e); + throw new UnableToLoadProcessException(); + } + } + + /** + * Calls to parser to split progress.txt into sentences + * Each sentence represents a task in String + */ + private void splitStringByTask() throws Exception { + sentences = ParseProgress.splitProgressIntoSentence(progress); + } + + /** + * Loop through the sentences and read each sentence + * Generate task from each sentence + */ + private void createTaskFromSentence() throws Exception { + for (int i = 0; i < sentences.length - 1; i++) { + String[] phrases = ParseProgress.splitSentenceByBarSeparator(sentences[i]); + addTaskFromPhrases(phrases); + } + } + + /** + * Add task into taskList based on each sentence + */ + private void addTaskFromPhrases(String[] phrases) throws Exception { + + String taskIndexInString = phrases[0]; + int taskIndex = Integer.parseInt(taskIndexInString); + + String taskTypeInString = phrases[1]; + + String isDoneInString = phrases[2]; + + String taskDetail = phrases[3]; + + String taskPriorityInString = phrases[4]; + int taskPriorityInInt = Integer.parseInt(taskPriorityInString); + TaskPriority taskPriority = TaskPriority.convertIntToPriority(taskPriorityInInt); + + String taskDateInString = "null"; + LocalDate taskDate; + + String taskStartTimeInString = "null"; + LocalTime taskTimeStart; + + String taskEndTimeInString = "null"; + LocalTime taskTimeEnd; + + int i = 5; + while (true) { + if (phrases[i].equals(";\r")) { + break; + } + + switch (i) { + case 5: + taskDateInString = phrases[5]; + break; + case 6: + taskStartTimeInString = phrases[6]; + break; + case 7: + taskEndTimeInString = phrases[7]; + break; + default: + break; + } + i++; + } + + switch (taskTypeInString) { + case "T": + myList.addItemToDos(taskDetail); + break; + case "E": + taskDate = ParseDateTime.toDate(taskDateInString); + if (taskEndTimeInString.equals("null") && taskStartTimeInString.equals("null")) { + myList.addItemEvent(taskDetail, taskDate); + } else if (taskEndTimeInString.equals("null")) { + taskTimeStart = ParseDateTime.toTime(taskStartTimeInString); + myList.addItemEvent(taskDetail, taskDate, taskTimeStart); + } else { + taskTimeStart = ParseDateTime.toTime(taskStartTimeInString); + taskTimeEnd = ParseDateTime.toTime(taskEndTimeInString); + myList.addItemEvent(taskDetail, taskDate, taskTimeStart, taskTimeEnd); + } + break; + case "D": + taskDate = ParseDateTime.toDate(taskDateInString); + if (taskStartTimeInString.equals("null")) { + myList.addItemDeadline(taskDetail, taskDate); + } else { + taskTimeStart = ParseDateTime.toTime(taskStartTimeInString); + myList.addItemDeadline(taskDetail, taskDate, taskTimeStart); + } + break; + default: + break; + } + + if (isDoneInString.equals("1")) { + myList.setTaskDone(taskIndex); + } + + myList.setTaskPriority(taskIndex, taskPriority); + } +} diff --git a/src/main/java/duke/RunDuke.java b/src/main/java/duke/RunDuke.java new file mode 100644 index 00000000..c6e3c907 --- /dev/null +++ b/src/main/java/duke/RunDuke.java @@ -0,0 +1,118 @@ +package duke; + +import java.util.Scanner; + +import duke.action.Parser; +import duke.command.Command; +import duke.storage.FileAccess; +import duke.task.TaskList; +import duke.ui.Message; +import duke.ui.Ui; + +/** + * Duke class that run the main Duke program + * + * @author Kang Teng + * @version 8.0 + * @since 2021-09-01 + */ + +public class RunDuke { + + private static TaskList myList; + private static Ui ui; + private static FileAccess fileAccess; + private static Parser parser; + private static Command cmd; + private static Scanner scanner; + + /** + * Constructor + */ + public RunDuke(TaskList myList, Ui ui, FileAccess fileAccess) { + this.myList = myList; + this.ui = ui; + this.fileAccess = fileAccess; + parser = new Parser(); + cmd = new Command(parser); + scanner = new Scanner(System.in); + } + + /** + * Execute the run + */ + public void run() { + + boolean isDukeRunning = true; + + while (isDukeRunning) { + String userInput = ui.requestUserInput(scanner); + if (userInput.isEmpty()) { + Message.msgInvalidInput(); + } else { + String userCommand = parser.processUserCommand(userInput); + isDukeRunning = canProcessCommand(userCommand, userInput); + } + } + } + + /** + * Read user command and execute respective methods accordingly + *
+ * Accepted user input: bye, list, set, done, todo, save + * Accepted user input: find, info, event, delete, deadline + *
+ * method returns true for all commands and non-accepted user input + * method return false for bye command. + * + * @param userCommand String that represents the command type by user + * @param userInput String that represents the full user input + * @return boolean false if the command is "bye"; true if otherwise + */ + private static boolean canProcessCommand(String userCommand, String userInput) { + + assert !userCommand.isEmpty() : "userCommand should not be empty"; + assert !userInput.isEmpty() : "userInput should not be empty"; + + switch (userCommand) { + case "bye": + return false; + case "list": + cmd.showFullList(myList); + return true; + case "set": + cmd.setPriorityTask(myList, scanner); + return true; + case "done": + cmd.markTaskDone(myList, userInput); + return true; + case "todo": + cmd.addTaskToDo(myList, userInput); + return true; + case "save": + cmd.saveTask(myList, fileAccess); + return true; + case "find": + cmd.findTask(myList, userInput); + return true; + case "info": + cmd.showInfo(); + return true; + case "event": + cmd.addTaskEvent(myList, userInput); + return true; + case "undone": + cmd.markTaskUnDone(myList, userInput); + return true; + case "delete": + cmd.deleteTask(myList, userInput); + return true; + case "deadline": + cmd.addTaskDeadline(myList, userInput); + return true; + default: + cmd.showInvalidCommand(); + return true; + } + } +} diff --git a/src/main/java/duke/StartDuke.java b/src/main/java/duke/StartDuke.java new file mode 100644 index 00000000..c59fdd63 --- /dev/null +++ b/src/main/java/duke/StartDuke.java @@ -0,0 +1,24 @@ +package duke; + +import duke.ui.Message; + +/** + * Duke class that executes when Duke is initialized + * + * @author Kang Teng + * @version 8.0 + * @since 2021-09-01 + */ +public class StartDuke { + + public static void run() { + showGreetMessage(); + } + + /** + * Show the opening Greet Message in System.out.println + */ + public static void showGreetMessage() { + Message.msgGreet(); + } +} diff --git a/src/main/java/duke/action/ParseDateTime.java b/src/main/java/duke/action/ParseDateTime.java new file mode 100644 index 00000000..3bc69f9c --- /dev/null +++ b/src/main/java/duke/action/ParseDateTime.java @@ -0,0 +1,147 @@ +package duke.action; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.DateTimeParseException; +import java.util.Locale; + +/** + * Handle date and time related functions + *
+ * Conversion between String and LocalDate/LocalTime + * String manipulation + * + * @author Kang Teng + * @version 8.0 + * @since 2021-09-01 + */ + +public class ParseDateTime { + + /** + * Convert date from String to LocalDate + * + * @param date TaskDate of the task + * @return LocalDate + * @throws DateTimeParseException If format of the date is not accepted + */ + public static LocalDate toDate(String date) { + + LocalDate formattedDate; + DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder() + .parseCaseInsensitive() + .parseLenient() + .appendPattern("[yyyy-MM-dd]") + .appendPattern("[M-d-yyyy]") + .appendPattern("[M-dd-yyyy]") + .appendPattern("[MM-d-yyyy]") + .appendPattern("[MM-dd-yyyy]") + .appendPattern("[M/d/yyyy]") + .appendPattern("[M/dd/yyyy]") + .appendPattern("[MM/d/yyyy]") + .appendPattern("[MM/dd/yyyy]") + .appendPattern("[d-M-yyyy]") + .appendPattern("[d-MM-yyyy]") + .appendPattern("[dd-M-yyyy]") + .appendPattern("[dd-MM-yyyy]") + .appendPattern("[d/M/yyyy]") + .appendPattern("[d/MM/yyyy]") + .appendPattern("[dd/M/yyyy]") + .appendPattern("[dd/MM/yyyy]") + .appendPattern("[MMM dd yyyy]"); + + DateTimeFormatter formatter = builder.toFormatter(Locale.ENGLISH); + + try { + formattedDate = LocalDate.parse(date, formatter); + return formattedDate; + } catch (DateTimeParseException e) { + throw e; + } + } + + /** + * Convert time from String to LocalTime + * + * @param time String that describes taskDate of the task + * @return LocalTime + * @throws DateTimeParseException If format of the date is not accepted + */ + public static LocalTime toTime(String time) { + LocalTime localTime = LocalTime.parse(time); + return localTime; + } + + /** + * Split Date and Time by empty space " " + * + * @param dateAndTime String that contains both date and time + * @return String[] + */ + public static String[] splitDateAndTime(String dateAndTime) { + return dateAndTime.split(" "); + } + + /** + * Check if the string contains date and time + *
+ * return 1 if the string contains only string representation of a Date + * return 2 if the string contains string representation of a Date and a Time + * return 3 if the string contains string representation of a Date and 2 Time + * + * @param dateAndTime String representation of date and time + * @return int 1 or 2 or 3 + */ + public static int isDateAndTime(String dateAndTime) { + String[] split = dateAndTime.split(" "); + if (split.length == 1) { + return 1; + } else if (split.length == 2) { + return 2; + } else { + return 3; + } + } + + /** + * Extract string representation of date from string array + * + * @param split String Array of date and time + * @return String Date + */ + public static String toExtractDateFromSplitDateAndTime(String[] split) { + return split[0]; + } + + /** + * Extract string representation of time from string array + * + * @param split String Array of date and time + * @return String Time + */ + public static String toExtractTimeFromSplitDateAndTime(String[] split) { + return split[1]; + } + + /** + * Extract string representation of start time from string array + * + * @param split String Array of date and time + * @return String TimeStart + */ + public static String toExtractTimeStartFromSplitDateAndTime(String[] split) { + return split[1]; + } + + /** + * Extract string representation of end time from string array + * + * @param split String Array of date and time + * @return String TimeEnd + */ + public static String toExtractTimeEndFromSplitDateAndTime(String[] split) { + return split[2]; + } +} diff --git a/src/main/java/duke/action/ParseProgress.java b/src/main/java/duke/action/ParseProgress.java new file mode 100644 index 00000000..0f5591c9 --- /dev/null +++ b/src/main/java/duke/action/ParseProgress.java @@ -0,0 +1,35 @@ +package duke.action; + +/** + * Handle progress related string + *
+ * Splitting of string (describes the progress) loaded from progress file into arrays + * String manipulation + * + * @author Kang Teng + * @version 8.0 + * @since 2021-09-01 + */ + +public class ParseProgress { + + /** + * Convert date from String to LocalDate + * + * @param progress String that is loaded from progress.txt + * @return String[] String array that has been split based on \n + */ + public static String[] splitProgressIntoSentence(String progress) { + return progress.split("\\n", -1); + } + + /** + * Convert date from String to LocalDate + * + * @param sentence String that contains the task information + * @return String[] String array that has been split based on | + */ + public static String[] splitSentenceByBarSeparator(String sentence) { + return sentence.split("\\|", -1); + } +} diff --git a/src/main/java/duke/action/Parser.java b/src/main/java/duke/action/Parser.java new file mode 100644 index 00000000..4e8e21ea --- /dev/null +++ b/src/main/java/duke/action/Parser.java @@ -0,0 +1,80 @@ +package duke.action; + +/** + * Make sense of user input and return the user command + * + * @author Kang Teng + * @version 8.0 + * @since 2021-09-01 + */ + +public class Parser { + + public Parser() { + + } + + /** + * Convert date from String to LocalDate + * + * @param userInput String + * @return String that describe the command specified by user + */ + public String processUserCommand(String userInput) { + + if (userInput.isEmpty()) { + return "invalid"; + } + + if (userInput.equals("bye")) { + return "bye"; + } else if (userInput.equals("list")) { + return "list"; + } else if (userInput.equals("set")) { + return "set"; + } else if (userInput.equals("info")) { + return "info"; + } else if (userInput.equals("save")) { + return "save"; + } + + String userInputStartWith = getFirstWord(userInput); + + switch (userInputStartWith) { + case "done": + return "done"; + case "todo": + return "todo"; + case "find": + return "find"; + case "event": + return "event"; + case "delete": + return "delete"; + case "undone": + return "undone"; + case "deadline": + return "deadline"; + default: + return "invalid"; + } + } + + /** + * Convert date from String to LocalDate + * + * @param firstWord String + * @return String that represents the first word of a line of string + */ + private String getFirstWord(String firstWord) { + + int index = firstWord.indexOf(' '); + + if (index > -1) { + return firstWord.substring(0, index).trim(); + } else { + return "invalid"; + } + } + +} diff --git a/src/main/java/duke/command/CmdAddTask.java b/src/main/java/duke/command/CmdAddTask.java new file mode 100644 index 00000000..e8f6bc96 --- /dev/null +++ b/src/main/java/duke/command/CmdAddTask.java @@ -0,0 +1,428 @@ +package duke.command; + +import java.time.LocalDate; +import java.time.LocalTime; + +import duke.action.ParseDateTime; +import duke.task.TaskList; +import duke.task.TaskType; +import duke.ui.Message; + +/** + * Command class that handle adding task + *
+ * add 3 types of class: TODO, DEADLINE and EVENT.
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+
+public class CmdAddTask {
+
+ /**
+ * Add a task of todo type into TaskList
+ *
+ * @param myList TaskList that contains the list of task
+ * @param userInput String
+ */
+ public static void addTaskToDo(TaskList myList, String userInput) {
+
+ assert myList != null : "mylist should not be empty";
+ assert userInput != null : "userInput should not be empty";
+
+ if (userInput.length() <= 5) {
+ Message.msgInvalidInputMissingDescription();
+ return;
+ }
+
+ myList.addItemToDos(userInput.substring(5));
+
+ int lastTaskIndex = myList.getNumOfItem() - 1;
+ String taskTypeInString = getTaskTypeInString(myList, lastTaskIndex);
+ String isDoneInString = getIsDoneInString(myList, lastTaskIndex);
+ String taskDetail = getTaskDetail(myList, lastTaskIndex);
+ int numOfItem = lastTaskIndex + 1;
+
+ Message.msgAssignTaskToDo(taskTypeInString, isDoneInString, taskDetail, numOfItem);
+ }
+
+ /**
+ * Add a task of event type into TaskList
+ *
+ * @param myList TaskList that contains the list of task
+ * @param userInput String
+ */
+ public static void addTaskEvent(TaskList myList, String userInput) {
+
+ assert myList != null : "mylist should not be empty";
+ assert userInput != null : "userInput should not be empty";
+
+ if (userInput.length() <= 6) {
+ Message.msgInvalidInputMissingDescription();
+ return;
+ }
+
+ if (!userInput.contains("/at")) {
+ Message.msgInvalidInputMissingDate();
+ return;
+ }
+
+ try {
+ String taskDetail = userInput.substring(6, userInput.indexOf("/"));
+ String dateAndTime = userInput.substring(userInput.indexOf("/") + 4);
+ String date;
+ String timeStart;
+ String timeEnd;
+
+ String[] split = ParseDateTime.splitDateAndTime(dateAndTime);
+ date = ParseDateTime.toExtractDateFromSplitDateAndTime(split);
+
+ if (ParseDateTime.isDateAndTime(dateAndTime) == 1) {
+ toAddTaskEvent_localDate(myList, taskDetail, date);
+ } else if (ParseDateTime.isDateAndTime(dateAndTime) == 2) {
+ timeStart = ParseDateTime.toExtractTimeStartFromSplitDateAndTime(split);
+ toAddTaskEvent_localDate_localTime(myList, taskDetail, date, timeStart);
+ } else {
+ timeStart = ParseDateTime.toExtractTimeStartFromSplitDateAndTime(split);
+ timeEnd = ParseDateTime.toExtractTimeEndFromSplitDateAndTime(split);
+ toAddTaskEvent_localDate_localTime(myList, taskDetail, date, timeStart, timeEnd);
+ }
+
+ } catch (Exception e) {
+ Message.msgInvalidInputWrongDateTimeStartEndFormat();
+ }
+ }
+
+ /**
+ * Add a task of deadline type into TaskList
+ *
+ * @param myList TaskList that contains the list of task
+ * @param userInput String
+ */
+ public static void addTaskDeadline(TaskList myList, String userInput) {
+
+ assert myList != null : "mylist should not be empty";
+ assert userInput != null : "userInput should not be empty";
+
+ if (userInput.length() <= 9) {
+ Message.msgInvalidInputMissingDescription();
+ return;
+ }
+
+ if (!userInput.contains("/by")) {
+ Message.msgInvalidInputMissingDate();
+ return;
+ }
+
+ try {
+ String taskDetail = userInput.substring(9, userInput.indexOf("/"));
+ String dateAndTime = userInput.substring(userInput.indexOf("/") + 4);
+ String date;
+ String time;
+
+ String[] split = ParseDateTime.splitDateAndTime(dateAndTime);
+ date = ParseDateTime.toExtractDateFromSplitDateAndTime(split);
+
+ if (ParseDateTime.isDateAndTime(dateAndTime) == 1) {
+ toAddTaskDeadline_localDate(myList, taskDetail, date);
+ } else if (ParseDateTime.isDateAndTime(dateAndTime) == 2) {
+ time = ParseDateTime.toExtractTimeFromSplitDateAndTime(split);
+ toAddTaskDeadline_localDate_localTime(myList, taskDetail, date, time);
+ } else {
+ Message.msgInvalidInputWrongDateTimeFormat();
+ }
+
+ } catch (Exception e) {
+ Message.msgInvalidInputWrongDateTimeFormat();
+ }
+ }
+
+ /**
+ * Add a task of Event type into TaskList
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskDetail String that represents the task detail
+ * @param date String that represents the date of the event
+ */
+ private static void toAddTaskEvent_localDate(TaskList myList, String taskDetail, String date) {
+
+ assert myList != null : "mylist should not be empty";
+ assert taskDetail != null : "taskDetail should not be empty";
+ assert date != null : "date should not be empty";
+
+ LocalDate taskDate = ParseDateTime.toDate(date);
+
+ if (taskDate == null) {
+ Message.msgInvalidInputWrongDateTimeFormat();
+ return;
+ }
+
+ myList.addItemEvent(taskDetail, taskDate);
+
+ int lastTaskIndex = myList.getNumOfItem() - 1;
+ String taskTypeInString = getTaskTypeInString(myList, lastTaskIndex);
+ String isDoneInString = getIsDoneInString(myList, lastTaskIndex);
+ String dateInString = getTaskEventDateInString(myList, lastTaskIndex);
+ int numOfItem = lastTaskIndex + 1;
+
+ Message.msgAssignTaskEventTaskDate(taskTypeInString, isDoneInString,
+ taskDetail, dateInString, numOfItem);
+ }
+
+ /**
+ * Add a task of Event type into TaskList
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskDetail String that represents the task detail
+ * @param date String that represents the date of the event
+ * @param timeStart String that represents the start time of the event
+ */
+ private static void toAddTaskEvent_localDate_localTime(TaskList myList, String taskDetail,
+ String date, String timeStart) {
+
+ assert myList != null : "mylist should not be empty";
+ assert taskDetail != null : "taskDetail should not be empty";
+ assert date != null : "date should not be empty";
+ assert timeStart != null : "timeStart should not be empty";
+
+ LocalDate taskDate = ParseDateTime.toDate(date);
+ LocalTime taskTimeStart = ParseDateTime.toTime(timeStart);
+
+ if (taskDate == null) {
+ Message.msgInvalidInputMissingDate();
+ return;
+ }
+
+ if (taskTimeStart == null) {
+ Message.msgInvalidInputWrongDateTimeFormat();
+ return;
+ }
+
+ myList.addItemEvent(taskDetail, taskDate, taskTimeStart);
+
+ int lastTaskIndex = myList.getNumOfItem() - 1;
+ String taskTypeInString = getTaskTypeInString(myList, lastTaskIndex);
+ String isDoneInString = getIsDoneInString(myList, lastTaskIndex);
+ String dateInString = getTaskEventDateInString(myList, lastTaskIndex);
+ int numOfItem = lastTaskIndex + 1;
+ String getTimeStartInString = getTaskEventTimeStartInString(myList, lastTaskIndex);
+
+ Message.msgAssignTaskEventTaskDateTaskTimeStart(taskTypeInString, isDoneInString,
+ taskDetail, dateInString, getTimeStartInString, numOfItem);
+ }
+
+ /**
+ * Add a task of Event type into TaskList
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskDetail String that represents the task detail
+ * @param date String that represents the date of the event
+ * @param timeStart String that represents the start time of the event
+ * @param timeEnd String that represents the end time of the event
+ */
+ private static void toAddTaskEvent_localDate_localTime(TaskList myList, String taskDetail,
+ String date, String timeStart, String timeEnd) {
+
+ assert myList != null : "mylist should not be empty";
+ assert taskDetail != null : "taskDetail should not be empty";
+ assert date != null : "date should not be empty";
+ assert timeStart != null : "timeStart should not be empty";
+ assert timeEnd != null : "timeEnd should not be empty";
+
+ LocalDate taskDate = ParseDateTime.toDate(date);
+ LocalTime taskTimeStart = ParseDateTime.toTime(timeStart);
+ LocalTime taskTimeEnd = ParseDateTime.toTime(timeEnd);
+
+ if (taskDate == null) {
+ Message.msgInvalidInputMissingDate();
+ return;
+ }
+
+ if (taskTimeStart == null || taskTimeEnd == null) {
+ Message.msgInvalidInputWrongDateTimeFormat();
+ return;
+ }
+
+ if (taskTimeStart.isAfter(taskTimeEnd)) {
+ Message.msgInvalidInputTimeStartLaterThanTimeEnd();
+ return;
+ }
+
+ myList.addItemEvent(taskDetail, taskDate, taskTimeStart, taskTimeEnd);
+
+ int lastTaskIndex = myList.getNumOfItem() - 1;
+ String taskTypeInString = getTaskTypeInString(myList, lastTaskIndex);
+ String isDoneInString = getIsDoneInString(myList, lastTaskIndex);
+ String dateInString = getTaskEventDateInString(myList, lastTaskIndex);
+ String getTimeStartInString = getTaskEventTimeStartInString(myList, lastTaskIndex);
+ String getTimeEndInString = getTaskEventTimeEndInString(myList, lastTaskIndex);
+ int numOfItem = lastTaskIndex + 1;
+
+ Message.msgAssignEventTaskDateTimeStartEnd(taskTypeInString, isDoneInString,
+ taskDetail, dateInString, getTimeStartInString, getTimeEndInString, numOfItem);
+ }
+
+ /**
+ * Add a task of Deadline type into TaskList
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskDetail String that represents the task detail
+ * @param date String that represents the date of the deadline
+ */
+ private static void toAddTaskDeadline_localDate(TaskList myList, String taskDetail, String date) {
+
+ assert myList != null : "mylist should not be empty";
+ assert taskDetail != null : "taskDetail should not be empty";
+ assert date != null : "date should not be empty";
+
+ LocalDate taskDate = ParseDateTime.toDate(date);
+
+ if (taskDate == null) {
+ Message.msgInvalidInputWrongDateTimeFormat();
+ return;
+ }
+
+ myList.addItemDeadline(taskDetail, taskDate);
+
+ int lastTaskIndex = myList.getNumOfItem() - 1;
+ String taskTypeInString = getTaskTypeInString(myList, lastTaskIndex);
+ String isDoneInString = getIsDoneInString(myList, lastTaskIndex);
+ String dateInString = getTaskDeadlineDateInString(myList, lastTaskIndex);
+ int numOfItem = lastTaskIndex + 1;
+
+ Message.msgAssignTaskDeadlineTaskDate(taskTypeInString, isDoneInString, taskDetail, dateInString, numOfItem);
+ }
+
+ /**
+ * Add a task of Event type into TaskList
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskDetail String that represents the task detail
+ * @param date String that represents the date of the deadline
+ * @param time String that represents the time of the deadline
+ */
+ private static void toAddTaskDeadline_localDate_localTime(TaskList myList, String taskDetail,
+ String date, String time) {
+
+ assert myList != null : "mylist should not be empty";
+ assert taskDetail != null : "taskDetail should not be empty";
+ assert date != null : "date should not be empty";
+ assert time != null : "time should not be empty";
+
+ LocalDate taskDate = ParseDateTime.toDate(date);
+ LocalTime taskTime = ParseDateTime.toTime(time);
+
+ if (taskDate == null) {
+ Message.msgInvalidInputMissingDate();
+ return;
+ }
+
+ if (taskTime == null) {
+ Message.msgInvalidInputWrongDateTimeFormat();
+ return;
+ }
+
+ myList.addItemDeadline(taskDetail, taskDate, taskTime);
+
+ int lastTaskIndex = myList.getNumOfItem() - 1;
+ String taskTypeInString = getTaskTypeInString(myList, lastTaskIndex);
+ String isDoneInString = getIsDoneInString(myList, lastTaskIndex);
+ String dateInString = getTaskDeadlineDateInString(myList, lastTaskIndex);
+ String timeInString = getTaskDeadlineTimeInString(myList, lastTaskIndex);
+ int numOfItem = lastTaskIndex + 1;
+
+ Message.msgAssignTaskDeadlineTaskDateTaskTime(taskTypeInString,
+ isDoneInString, taskDetail, dateInString, timeInString, numOfItem);
+ }
+
+ /**
+ * Get TaskType of a task using myList and its task index.
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskIndex Int that represents the index of the task
+ * @return String representation of TaskType of a task in tasklist
+ */
+ private static String getTaskTypeInString(TaskList myList, int taskIndex) {
+ TaskType taskType = myList.getTaskType(taskIndex);
+ return TaskType.taskTypeToString(taskType);
+ }
+
+ /**
+ * Get isDone status of a task in String
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskIndex Int that represents the index of the task
+ * @return String representation of isDone of a task in tasklist
+ */
+ private static String getIsDoneInString(TaskList myList, int taskIndex) {
+ boolean isDone = myList.getTaskDoneStatus(taskIndex);
+ return (isDone ? "X" : " ");
+ }
+
+ /**
+ * Get taskDetail of a task
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskIndex Int that represents the index of the task
+ * @return String representation of taskDetail of a task in tasklist
+ */
+ private static String getTaskDetail(TaskList myList, int taskIndex) {
+ return myList.getTaskDetail(taskIndex);
+ }
+
+ /**
+ * Get date of an EVENT task in String
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskIndex Int that represents the index of the task
+ * @return String representation of date of a task in tasklist
+ */
+ private static String getTaskEventDateInString(TaskList myList, int taskIndex) {
+ return myList.getTaskEventTaskDateInString(taskIndex);
+ }
+
+ /**
+ * Get start time of an EVENT task in String
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskIndex Int that represents the index of the task
+ * @return String representation of start time of a task in tasklist
+ */
+ private static String getTaskEventTimeStartInString(TaskList myList, int taskIndex) {
+ return myList.getTaskEventTaskTimeStartInString(taskIndex);
+ }
+
+ /**
+ * Get end time of an EVENT task in String
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskIndex Int that represents the index of the task
+ * @return String representation of end time of a task in tasklist
+ */
+ private static String getTaskEventTimeEndInString(TaskList myList, int taskIndex) {
+ return myList.getTaskEventTaskTimeEndInString(taskIndex);
+ }
+
+ /**
+ * Get date of an DEADLINE task in String
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskIndex Int that represents the index of the task
+ * @return String representation of date of a task in tasklist
+ */
+ private static String getTaskDeadlineDateInString(TaskList myList, int taskIndex) {
+ return myList.getTaskDeadLineTaskDateInString(taskIndex);
+ }
+
+ /**
+ * Get start time of an DEADLINE task in String
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskIndex Int that represents the index of the task
+ * @return String representation of start time of a task in tasklist
+ */
+ private static String getTaskDeadlineTimeInString(TaskList myList, int taskIndex) {
+ return myList.getTaskDeadLineTaskTimeInString(taskIndex);
+ }
+}
diff --git a/src/main/java/duke/command/CmdDelete.java b/src/main/java/duke/command/CmdDelete.java
new file mode 100644
index 00000000..4d458dc0
--- /dev/null
+++ b/src/main/java/duke/command/CmdDelete.java
@@ -0,0 +1,48 @@
+package duke.command;
+
+import duke.task.TaskList;
+import duke.ui.Message;
+
+/**
+ * Command class that delete a task from a tasklist
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+
+public class CmdDelete {
+
+ /**
+ * Execute the delete task command
+ * Remove a task from a tasklist
+ *
+ * @param myList TaskList that contains the list of task
+ * @param userInput String
+ */
+ public static void run(TaskList myList, String userInput) {
+
+ assert myList != null : "mylist should not be empty";
+ assert userInput != null : "userInput should not be empty";
+
+ if (myList.getNumOfItem() == 0) {
+ Message.msgTaskListIsEmpty();
+ return;
+ }
+
+ try {
+ int taskIndex = Integer.parseInt(userInput.substring(7)) - 1;
+ int numOfTaskAfterDelete = myList.getNumOfItem() - 1;
+
+ if (taskIndex >= myList.getNumOfItem() || taskIndex < 0) {
+ Message.msgInvalidTaskNumber();
+ return;
+ }
+
+ Message.msgRemoveItem(myList, taskIndex, numOfTaskAfterDelete);
+ myList.removeItem(taskIndex);
+ } catch (Exception e) {
+ Message.msgInvalidTaskNumber();
+ }
+ }
+}
diff --git a/src/main/java/duke/command/CmdFind.java b/src/main/java/duke/command/CmdFind.java
new file mode 100644
index 00000000..73ae34b0
--- /dev/null
+++ b/src/main/java/duke/command/CmdFind.java
@@ -0,0 +1,93 @@
+package duke.command;
+
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import duke.task.TaskList;
+import duke.ui.Message;
+import duke.ui.MsgTaskDetail;
+
+/**
+ * Command class that find a task from a tasklist
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+
+public class CmdFind {
+
+ /**
+ * Execute the find task command
+ * Find a task based on the keyword input by the user
+ *
+ * @param myList TaskList that contains the list of task
+ * @param userInput String
+ */
+ public static void run(TaskList myList, String userInput) {
+
+ assert myList != null : "mylist should not be empty";
+ assert userInput != null : "userInput should not be empty";
+
+ if (myList.getNumOfItem() == 0) {
+ Message.msgTaskListIsEmpty();
+ return;
+ }
+
+ if (userInput.length() <= 5) {
+ Message.msgInvalidFindTerm();
+ return;
+ }
+
+ String searchTerm = userInput.substring(5);
+ ArrayList
+ * Expected input should be 1 to 3
+ *
+ * @param userInputPriorityS
+ * @return boolean True if userInput is "1" to "3"; False otherwise
+ */
+ private static boolean hasValidPriorityNumber(String userInputPriorityS) {
+
+ assert userInputPriorityS != null : "userInputPriorityS should not be empty";
+
+ try {
+ TaskPriority taskPriority = TaskPriority.convertStringToPriority(userInputPriorityS);
+ if (taskPriority == TaskPriority.HIGH) {
+ return true;
+ } else if (taskPriority == TaskPriority.MEDIUM) {
+ return true;
+ } else if (taskPriority == TaskPriority.LOW) {
+ return true;
+ }
+ } catch (Exception e) {
+ Message.msgInvalidPriority();
+ return false;
+ }
+ Message.msgInvalidPriority();
+ return false;
+ }
+
+ /**
+ * Update the priority of the task based on the taskPriority
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskIndex int that indicates the task number
+ * @param taskPriority TaskPriority(new one) that want to be set
+ */
+ private static void toUpdatePriority(TaskList myList, int taskIndex, TaskPriority taskPriority) {
+
+ assert myList != null : "mylist should not be empty";
+ assert taskIndex >= 0 : "taskIndex should be equal or more than 0";
+ assert taskPriority != null : "taskPriority should not be empty";
+
+ myList.setTaskPriority(taskIndex, taskPriority);
+ String taskPriorityInString = getTaskPriorityInString(myList, taskIndex);
+ Message.msgSetPriority(taskIndex + 1, taskPriorityInString);
+ }
+
+ /**
+ * Get priority of the task in String
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskIndex Int that represents the index of the task in tasklist
+ * @return String that represents the priority of the task
+ */
+ private static String getTaskPriorityInString(TaskList myList, int taskIndex) {
+
+ assert myList != null : "mylist should not be empty";
+ assert taskIndex >= 0 : "taskIndex should be equal or more than 0";
+
+ TaskPriority taskPriority = myList.getTaskPriority(taskIndex);
+ return TaskPriority.convertPriorityToString(taskPriority);
+ }
+}
diff --git a/src/main/java/duke/command/CmdSave.java b/src/main/java/duke/command/CmdSave.java
new file mode 100644
index 00000000..3d6a8d00
--- /dev/null
+++ b/src/main/java/duke/command/CmdSave.java
@@ -0,0 +1,200 @@
+package duke.command;
+
+import duke.storage.FileAccess;
+import duke.task.TaskList;
+import duke.task.TaskPriority;
+import duke.task.TaskType;
+
+/**
+ * Command class that save all the task from the current taskList to progress.txt
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+
+public class CmdSave {
+
+ private static FileAccess fileAccess;
+ private static TaskList myList;
+ private static StringBuilder sb;
+
+ private static String taskTypeInString;
+ private static String isDoneInString;
+ private static String taskDetail;
+ private static String taskPriorityInString;
+ private static String taskDate;
+ private static String timeStart;
+ private static String timeEnd;
+
+ /**
+ * Constructor
+ */
+ public CmdSave(TaskList myList, FileAccess fileAccess) {
+ this.myList = myList;
+ this.fileAccess = fileAccess;
+ sb = new StringBuilder();
+ }
+
+ /**
+ * Execute the save
+ */
+ public static void run() {
+ String listOfTaskString = generateListOfTaskInString();
+ fileAccess.saveProgressIntoFile(listOfTaskString);
+ }
+
+ /**
+ * Read a list of task and convert it into string
+ *
+ * calls the following methods to generate the string
+ * setStringToNull();
+ * appendBasic(taskIndex);
+ * appendAdvance(taskIndex);
+ * appendEnd();
+ *
+ * @return String that represents the string to be saved in text
+ */
+ private static String generateListOfTaskInString() {
+
+ for (int taskIndex = 0; taskIndex < myList.getNumOfItem(); taskIndex++) {
+ setStringToNull();
+ appendBasic(taskIndex);
+ appendAdvance(taskIndex);
+ appendEnd();
+ }
+ return sb.toString();
+ }
+
+ /**
+ * set the private variables to "null"
+ *
+ * taskTypeInString = "null";
+ * isDoneInString = "null";
+ * taskDetail = "null";
+ * taskPriorityInString = "null";
+ * taskDate = "null";
+ * timeStart = "null";
+ * timeEnd = "null";
+ *
+ * @return StringBuilder
+ */
+ private static void setStringToNull() {
+ taskTypeInString = "null";
+ isDoneInString = "null";
+ taskDetail = "null";
+ taskPriorityInString = "null";
+ taskDate = "null";
+ timeStart = "null";
+ timeEnd = "null";
+ }
+
+ /**
+ * append basic variables to the string builder
+ *
+ * taskIndex
+ * taskType
+ * isDone
+ * taskDetail
+ * taskPriority
+ *
+ * @return StringBuilder
+ */
+ private static StringBuilder appendBasic(int taskIndex) {
+
+ taskTypeInString = TaskType.taskTypeToString(myList.getTaskType(taskIndex));
+
+ boolean isDone = myList.getTaskDoneStatus(taskIndex);
+ isDoneInString = (isDone ? "1" : "0");
+
+ taskDetail = myList.getTaskDetail(taskIndex);
+
+ TaskPriority taskPriority = myList.getTaskPriority(taskIndex);
+ taskPriorityInString = taskPriority.toStringInNumber();
+
+ assert taskTypeInString != null : "taskTypeInString should not be empty";
+ assert taskDetail != null : "taskDetail should not be empty";
+ assert taskPriority != null : "taskPriority should not be empty";
+
+ sb.append(taskIndex).append("|");
+ sb.append(taskTypeInString).append("|");
+ sb.append(isDoneInString).append("|");
+ sb.append(taskDetail).append("|");
+ sb.append(taskPriorityInString).append("|");
+
+ return sb;
+ }
+
+ /**
+ * append advance variables to the string builder based on the variable types
+ *
+ * date`
+ * start time
+ * end time
+ *
+ * depending on the taskType, different String is appended
+ *
+ * @return StringBuilder
+ */
+ private static StringBuilder appendAdvance(int taskIndex) {
+
+ switch (taskTypeInString) {
+ case "D":
+ appendDeadline(taskIndex);
+ break;
+ case "E":
+ appendEvent(taskIndex);
+ break;
+ default:
+ break;
+ }
+
+ return sb;
+ }
+
+ /**
+ * append date and start time to DEADLINE type task
+ *
+ * @return StringBuilder
+ */
+ private static StringBuilder appendDeadline(int taskIndex) {
+
+ taskDate = myList.getTaskDeadLineTaskDateInString(taskIndex);
+
+ timeStart = myList.getTaskDeadLineTaskTimeInString(taskIndex);
+
+ sb.append(taskDate).append("|");
+ sb.append(timeStart).append("|");
+
+ return sb;
+ }
+
+ /**
+ * append date, start time, and end time to EVENT type task
+ *
+ * @return StringBuilder
+ */
+ private static StringBuilder appendEvent(int taskIndex) {
+
+ taskDate = myList.getTaskEventTaskDateInString(taskIndex);
+
+ timeStart = myList.getTaskEventTaskTimeStartInString(taskIndex);
+ timeEnd = myList.getTaskEventTaskTimeEndInString(taskIndex);
+
+ sb.append(taskDate).append("|");
+ sb.append(timeStart).append("|");
+ sb.append(timeEnd).append("|");
+
+ return sb;
+ }
+
+ /**
+ * append ;\n to the StringBuilder
+ *
+ * @return StringBuilder
+ */
+ private static StringBuilder appendEnd() {
+ sb.append(";\n");
+ return sb;
+ }
+}
diff --git a/src/main/java/duke/command/Command.java b/src/main/java/duke/command/Command.java
new file mode 100644
index 00000000..eba13984
--- /dev/null
+++ b/src/main/java/duke/command/Command.java
@@ -0,0 +1,150 @@
+package duke.command;
+
+import java.util.Scanner;
+
+import duke.action.Parser;
+import duke.storage.FileAccess;
+import duke.task.TaskList;
+import duke.ui.Message;
+
+/**
+ * Core Command class
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+
+public class Command {
+
+ private static Parser parser;
+
+ /**
+ * Constructor
+ */
+ public Command(Parser parser) {
+ this.parser = parser;
+ }
+
+ // Basic processCommand Method <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+ /**
+ * Show info of all the command Duke can accept
+ */
+ public void showInfo() {
+ Message.msgShowDukeCommandList();
+ }
+
+ /**
+ * Show full list of tasks
+ *
+ * @param myList TaskList that contains the list of task
+ */
+ public void showFullList(TaskList myList) {
+ CmdList.run(myList);
+ }
+
+ /**
+ * Ask user which task to set priority and change the priority accordingly
+ * -- Ask user which task to be changed
+ * -- Ask user what is the new priority
+ * -- Update the task with new priority
+ *
+ * @param myList TaskList that contains the list of task
+ * @param scanner Scanner for user input
+ */
+ public void setPriorityTask(TaskList myList, Scanner scanner) {
+ CmdPriority.run(myList, scanner);
+ }
+
+ /**
+ * Mark a task as done
+ *
+ * @param myList TaskList that contains the list of task
+ * @param userInput String that the user type
+ */
+ public void markTaskDone(TaskList myList, String userInput) {
+ CmdMarkTaskDone.run(myList, userInput);
+ }
+
+ /**
+ * Mark a task as undone
+ *
+ * @param myList TaskList that contains the list of task
+ * @param userInput String that the user type
+ */
+ public void markTaskUnDone(TaskList myList, String userInput) {
+ CmdMarkTaskUnDone.run(myList, userInput);
+ }
+
+ /**
+ * Add a task of ToDo type into the list of task
+ *
+ * @param myList TaskList that contains the list of task
+ * @param userInput String that the user type
+ */
+ public void addTaskToDo(TaskList myList, String userInput) {
+ CmdAddTask.addTaskToDo(myList, userInput);
+ }
+
+ /**
+ * Save the current task list and output a text file
+ *
+ * @param myList TaskList that contains the list of task
+ */
+ public void saveTask(TaskList myList, FileAccess fileAccess) {
+ new CmdSave(myList, fileAccess).run();
+ }
+
+ /**
+ * Find the Task requested
+ *
+ * @param myList TaskList that contains the list of task
+ */
+ public void findTask(TaskList myList, String userInput) {
+ CmdFind.run(myList, userInput);
+ }
+
+ /**
+ * Add a task of Event type into TaskList
+ *
+ * Identify the task date and time that the user input
+ * Calls for respective AddTaskEvent_XXX to create a task object in TaskList afterwards
+ *
+ * @param myList TaskList that contains the list of task
+ * @param userInput String that the user type
+ */
+ public void addTaskEvent(TaskList myList, String userInput) {
+ CmdAddTask.addTaskEvent(myList, userInput);
+ }
+
+ /**
+ * Delete a task from the user task
+ *
+ * @param myList TaskList that contains the list of task
+ * @param userInput String that represents the user input
+ */
+ public void deleteTask(TaskList myList, String userInput) {
+ CmdDelete.run(myList, userInput);
+ }
+
+ /**
+ * Add a task of Deadline type into TaskList
+ *
+ * Identify the task date and time that the user input
+ * Calls for respective AddTaskEvent_XXX to create a task object in TaskList afterwards
+ *
+ * @param myList TaskList that contains the list of task
+ * @param userInput String that represents the user input
+ */
+ public void addTaskDeadline(TaskList myList, String userInput) {
+ CmdAddTask.addTaskDeadline(myList, userInput);
+ }
+
+ /**
+ * Show invalid command
+ */
+ public void showInvalidCommand() {
+ Message.msgInvalidInput();
+ }
+}
diff --git a/src/main/java/duke/exception/UnableToLoadBuddhaException.java b/src/main/java/duke/exception/UnableToLoadBuddhaException.java
new file mode 100644
index 00000000..9d396772
--- /dev/null
+++ b/src/main/java/duke/exception/UnableToLoadBuddhaException.java
@@ -0,0 +1,11 @@
+package duke.exception;
+
+/**
+ * Exception class that is called when buddha.txt fails to load
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+public class UnableToLoadBuddhaException extends Exception {
+}
diff --git a/src/main/java/duke/exception/UnableToLoadProcessException.java b/src/main/java/duke/exception/UnableToLoadProcessException.java
new file mode 100644
index 00000000..30fa4a42
--- /dev/null
+++ b/src/main/java/duke/exception/UnableToLoadProcessException.java
@@ -0,0 +1,12 @@
+package duke.exception;
+
+/**
+ * Exception class that is called when progress.txt fails to load
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+public class UnableToLoadProcessException extends Exception {
+
+}
diff --git a/src/main/java/duke/storage/FileAccess.java b/src/main/java/duke/storage/FileAccess.java
new file mode 100644
index 00000000..0672a892
--- /dev/null
+++ b/src/main/java/duke/storage/FileAccess.java
@@ -0,0 +1,125 @@
+package duke.storage;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+
+import duke.exception.UnableToLoadBuddhaException;
+import duke.exception.UnableToLoadProcessException;
+import duke.ui.Message;
+import duke.ui.Ui;
+
+/**
+ * Handles file handling related functions
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+
+public class FileAccess {
+ private String filepath;
+ private File progressFile;
+ private Ui ui;
+
+ /**
+ * Constructor
+ *
+ * @param filepath
+ */
+ public FileAccess(String filepath) {
+ this.filepath = filepath;
+ progressFile = new File(this.filepath);
+ }
+
+ /**
+ * Save progress of the current task
+ *
+ * @param stringToBeWritten String that needs to be outputed
+ */
+ public void saveProgressIntoFile(String stringToBeWritten) {
+
+ assert !stringToBeWritten.isEmpty() : "stringToBeWritten should not be empty";
+
+ try {
+ FileWriter fw = new FileWriter(filepath);
+ fw.write(stringToBeWritten);
+ fw.close();
+ Message.msgSave();
+ } catch (Exception e) {
+ Message.msgError(e);
+ }
+ }
+
+ /**
+ * Load existing progress of the task
+ *
+ * @return String that represents a list of task details
+ */
+ public static String loadProgressFromFile() throws UnableToLoadProcessException {
+ String progress = "";
+ String pathRoot = System.getProperty("user.dir");
+ // e.g. pathRoot = D:\My Files\School Documents\Repository\Duke
+
+ String pathRssFolder = "src" + File.separator + "resources";
+ // pathRssFolder = src\resources
+
+ String pathFileName = "progress.txt";
+ // pathFileName = progress.txt
+
+ String filePath = pathRoot + File.separator + pathRssFolder + File.separator + pathFileName;
+ // e.g.
+ // filePath = D:\My Files\School
+ // Documents\Repository\Duke\src\main\resources\progress.txt
+
+ try {
+ FileReader fr = new FileReader(filePath);
+ BufferedReader br = new BufferedReader(fr);
+ StringBuilder sb = new StringBuilder();
+ String line = br.readLine();
+
+ while (line != null) {
+ sb.append(line);
+ sb.append(System.lineSeparator());
+ line = br.readLine();
+ }
+ progress = sb.toString();
+ br.close();
+ } catch (Exception e) {
+ throw new UnableToLoadProcessException();
+ }
+ return progress;
+ }
+
+ /**
+ * Read Buddah.txt
+ *
+ * @return String that contains the content in Buddha.txt
+ */
+ public String readBuddhaText() throws UnableToLoadBuddhaException {
+ String buddhaText = "";
+ String pathRoot = System.getProperty("user.dir");
+ String pathRssFolder = "src" + File.separator + "resources";
+ String pathFileName = "buddha.txt";
+ String filePath = pathRoot + File.separator + pathRssFolder + File.separator + pathFileName;
+
+ try {
+ FileReader fr = new FileReader(filePath);
+ BufferedReader br = new BufferedReader(fr);
+ StringBuilder sb = new StringBuilder();
+ String line = br.readLine();
+
+ while (line != null) {
+ sb.append(line);
+ sb.append(System.lineSeparator());
+ line = br.readLine();
+ }
+ buddhaText = sb.toString();
+ br.close();
+ } catch (Exception e) {
+ throw new UnableToLoadBuddhaException();
+ }
+ return buddhaText;
+ }
+}
diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java
new file mode 100644
index 00000000..7670ed13
--- /dev/null
+++ b/src/main/java/duke/task/Task.java
@@ -0,0 +1,111 @@
+package duke.task;
+
+/**
+ * Abstract class for Task
+ *
+ * A task object correspond to a single task object.
+ * The class object can be of the type todo, event, or deadline.
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+
+public abstract class Task {
+ protected String taskDetail;
+ protected boolean isDone;
+ protected TaskType taskType;
+ protected TaskPriority taskPriority;
+
+ /**
+ * Create an abstract Task object
+ */
+ public Task(String taskDetail) {
+ this.taskDetail = taskDetail;
+ this.taskPriority = TaskPriority.LOW;
+ }
+
+ // Getter <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+ /**
+ * Return the task detail
+ *
+ * @return String that represents the task detail
+ */
+ public String getTaskDetail() {
+ return taskDetail;
+ }
+
+ /**
+ * Return the boolean done status that represents if a task is done
+ *
+ * @return boolean that represents the done status of a task
+ */
+ public boolean getDoneStatus() {
+ return isDone;
+ }
+
+ /**
+ * Return the TaskType
+ *
+ * @return TaskType that represents the type of task
+ */
+ public TaskType getTaskType() {
+ return taskType;
+ }
+
+
+ /**
+ * Return the TaskPriority
+ *
+ * @return TaskPriority that represents the priority of task
+ */
+ public TaskPriority getTaskPriority() {
+ return taskPriority;
+ }
+
+ // Setter <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+ /**
+ * Modified the task detail
+ *
+ * @param modifiedTaskDetail String that represent the new task detail
+ */
+ public void setTask(String modifiedTaskDetail) {
+ taskDetail = modifiedTaskDetail;
+ }
+
+ /**
+ * Set the task as completed
+ * Change the done status to completed
+ */
+ public void setTaskCompleted() {
+ isDone = true;
+ }
+
+ /**
+ * Set the task as completed
+ * Change the done status to completed
+ */
+ public void setTaskInCompleted() {
+ isDone = false;
+ }
+
+ /**
+ * Modified the type of the task
+ *
+ * @param taskType String that represent the new task type
+ */
+ public void setTypeOfTask(TaskType taskType) {
+ this.taskType = taskType;
+ }
+
+ /**
+ * Set thr priority of a task
+ *
+ * @param taskPriority TaskPriority that represent the new priority
+ */
+ public void setPriority(TaskPriority taskPriority) {
+ this.taskPriority = taskPriority;
+ }
+}
diff --git a/src/main/java/duke/task/TaskDeadline.java b/src/main/java/duke/task/TaskDeadline.java
new file mode 100644
index 00000000..b31c105c
--- /dev/null
+++ b/src/main/java/duke/task/TaskDeadline.java
@@ -0,0 +1,100 @@
+package duke.task;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+
+/**
+ * Create an instance of deadline class
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+public class TaskDeadline extends Task {
+ private LocalDate taskDate;
+ private LocalTime taskTime;
+
+ /**
+ * Constructor
+ */
+ public TaskDeadline(String taskDetail, LocalDate taskDate) {
+ super(taskDetail);
+ this.isDone = false;
+ this.taskType = TaskType.DEADLINE;
+ this.taskDate = taskDate;
+ }
+
+ /**
+ * Constructor
+ */
+ public TaskDeadline(String taskDetail, LocalDate taskDate, LocalTime localTime) {
+ super(taskDetail);
+ this.isDone = false;
+ this.taskType = TaskType.DEADLINE;
+ this.taskDate = taskDate;
+ this.taskTime = localTime;
+ }
+
+ /**
+ * Return LocalDate of a task
+ *
+ * @return LocalDate that represents the taskDate
+ */
+ public LocalDate getLocalDate() {
+ return taskDate;
+ }
+
+ /**
+ * Return LocalDate of a task in String
+ *
+ * @return String that represents the taskDate
+ */
+ public String getLocalDateToString() {
+ return String.valueOf(taskDate);
+ }
+
+ /**
+ * Return day from LocalDate of a task in String
+ *
+ * @return String that represents the day of taskDate
+ */
+ public String getLocalDateDayToString() {
+ return String.valueOf(taskDate.getDayOfMonth());
+ }
+
+ /**
+ * Return month from LocalDate of a task in String
+ *
+ * @return String that represents the month of taskDate
+ */
+ public String getLocalDateMonthToString() {
+ return String.valueOf(taskDate.getMonth());
+ }
+
+ /**
+ * Return year from LocalDate of a task in String
+ *
+ * @return String that represents the year of taskDate
+ */
+ public String getLocalDateYearToString() {
+ return String.valueOf(taskDate.getYear());
+ }
+
+ /**
+ * Return LocalTime of a task
+ *
+ * @return LocalTime that represents the taskTime
+ */
+ public LocalTime getLocalTime() {
+ return taskTime;
+ }
+
+ /**
+ * Return LocalTime of a task in String
+ *
+ * @return String that represents the taskTime
+ */
+ public String getLocalTime_toString() {
+ return String.valueOf(taskTime);
+ }
+}
diff --git a/src/main/java/duke/task/TaskEvent.java b/src/main/java/duke/task/TaskEvent.java
new file mode 100644
index 00000000..8cc42c77
--- /dev/null
+++ b/src/main/java/duke/task/TaskEvent.java
@@ -0,0 +1,136 @@
+package duke.task;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+
+/**
+ * Create an instance of event class
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+
+public class TaskEvent extends Task {
+
+ private LocalDate taskDate;
+ private LocalTime taskTimeStart;
+ private LocalTime taskTimeEnd;
+
+ /**
+ * Constructor
+ */
+ public TaskEvent(String taskDetail, LocalDate taskDate) {
+ super(taskDetail);
+ this.isDone = false;
+ this.taskType = TaskType.EVENT;
+ this.taskDate = taskDate;
+ }
+
+ /**
+ * Constructor
+ */
+ public TaskEvent(String taskDetail, LocalDate taskDate, LocalTime taskTimeStart) {
+ super(taskDetail);
+ this.isDone = false;
+ this.taskType = TaskType.EVENT;
+ this.taskDate = taskDate;
+ this.taskTimeStart = taskTimeStart;
+ }
+
+ /**
+ * Constructor
+ */
+ public TaskEvent(String taskDetail, LocalDate taskDate, LocalTime taskTimeStart, LocalTime taskTimeEnd) {
+ super(taskDetail);
+ this.isDone = false;
+ this.taskType = TaskType.EVENT;
+ this.taskDate = taskDate;
+ this.taskTimeStart = taskTimeStart;
+ this.taskTimeEnd = taskTimeEnd;
+ }
+
+ /**
+ * Return LocalDate of a task
+ *
+ * @return LocalDate that represents the taskDate
+ */
+ public LocalDate getLocalDate() {
+ return taskDate;
+ }
+
+ /**
+ * Return LocalDate of a task in String
+ *
+ * @return String that represents the taskDate
+ */
+ public String getLocalDate_toString() {
+ return String.valueOf(taskDate);
+ }
+
+ /**
+ * Return day from LocalDate of a task in String
+ *
+ * @return String that represents the day of taskDate
+ */
+ public String getLocalDateDayToString() {
+ return String.valueOf(taskDate.getDayOfMonth());
+ }
+
+ /**
+ * Return month from LocalDate of a task in String
+ *
+ * @return String that represents the month of taskDate
+ */
+ public String getLocalDateMonthToString() {
+ return String.valueOf(taskDate.getMonth());
+ }
+
+ /**
+ * Return year from LocalDate of a task in String
+ *
+ * @return String that represents the year of taskDate
+ */
+ public String getLocalDateYearToString() {
+ return String.valueOf(taskDate.getYear());
+ }
+
+ /**
+ * Return start time of LocalTime of a task
+ *
+ * @return LocalTime that represents the start time of taskTime
+ */
+ public LocalTime getLocalTimeStart() {
+ return taskTimeStart;
+ }
+
+ /**
+ * Return end time of LocalTime of a task
+ *
+ * @return LocalTime that represents the end time of taskTime
+ */
+ public LocalTime getLocalTimeEnd() {
+ return taskTimeEnd;
+ }
+
+ /**
+ * Return start time of LocalTime of a task in String
+ *
+ * @return String that represents the start time of taskTime
+ */
+ public String getLocalTimeStart_toString() {
+ return String.valueOf(taskTimeStart);
+ }
+
+ /**
+ * Return end time of LocalTime of a task in String
+ *
+ * @return String that represents the start time of taskTime
+ */
+ public String getLocalTimeEnd_toString() {
+ return String.valueOf(taskTimeEnd);
+ }
+}
+
+
+
diff --git a/src/main/java/duke/task/TaskList.java b/src/main/java/duke/task/TaskList.java
new file mode 100644
index 00000000..3e479eda
--- /dev/null
+++ b/src/main/java/duke/task/TaskList.java
@@ -0,0 +1,318 @@
+package duke.task;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Create an instance of list of task
+ *
+ * Create task object
+ * Manipulate task object creation, modification and deletion
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+
+public class TaskList {
+ private List
+ * 1 -> HIGH
+ * 2 -> MEDIUM
+ * 3 -> LOW
+ * any other number -> INVALID
+ *
+ * @param priority Int that indicates the priority
+ * @return TaskPriority
+ */
+ public static TaskPriority convertIntToPriority(int priority) {
+ switch (priority) {
+ case 1:
+ return HIGH;
+ case 2:
+ return MEDIUM;
+ case 3:
+ return LOW;
+ default:
+ return INVALID;
+ }
+ }
+
+ /**
+ * Convert String value to Priority
+ *
+ * "1" -> HIGH
+ * "2" -> MEDIUM
+ * "3" -> LOW
+ * any other number -> INVALID
+ *
+ * @param priority String that indicates the priority
+ * @return TaskPriority
+ */
+ public static TaskPriority convertStringToPriority(String priority) {
+ switch (priority) {
+ case "1":
+ return HIGH;
+ case "2":
+ return MEDIUM;
+ case "3":
+ return LOW;
+ default:
+ return INVALID;
+ }
+ }
+
+ /**
+ * Convert TaskPriority to Int
+ *
+ * 1 <- HIGH
+ * 2 <- MEDIUM
+ * 3 <- LOW
+ * 0 <- INVALID
+ *
+ * @param task TaskPriority that indicates the TaskPriority
+ * @return int
+ */
+ public static int convertPriorityToInt(TaskPriority task) {
+ switch (task) {
+ case LOW:
+ return 3;
+ case MEDIUM:
+ return 2;
+ case HIGH:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+
+ /**
+ * Convert TaskPriority to String
+ *
+ * @param task TaskPriority that indicates the TaskPriority
+ * @return String value of TaskPriority
+ */
+ public static String convertPriorityToString(TaskPriority task) {
+ switch (task) {
+ case LOW:
+ return "LOW";
+ case MEDIUM:
+ return "MEDIUM";
+ case HIGH:
+ return "HIGH";
+ default:
+ return "INVALID";
+ }
+ }
+
+ /**
+ * Convert TaskPriority to String
+ */
+ public String toStringInNumber() {
+ switch (this) {
+ case LOW:
+ return "3";
+ case MEDIUM:
+ return "2";
+ case HIGH:
+ return "1";
+ default:
+ return "0";
+ }
+ }
+}
diff --git a/src/main/java/duke/task/TaskToDos.java b/src/main/java/duke/task/TaskToDos.java
new file mode 100644
index 00000000..a05ba941
--- /dev/null
+++ b/src/main/java/duke/task/TaskToDos.java
@@ -0,0 +1,21 @@
+package duke.task;
+
+/**
+ * Create an instance of todo class
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+
+public class TaskToDos extends Task {
+
+ /**
+ * Constructor
+ */
+ public TaskToDos(String taskDetail) {
+ super(taskDetail);
+ this.isDone = false;
+ this.taskType = TaskType.TODOS;
+ }
+}
diff --git a/src/main/java/duke/task/TaskType.java b/src/main/java/duke/task/TaskType.java
new file mode 100644
index 00000000..1b177045
--- /dev/null
+++ b/src/main/java/duke/task/TaskType.java
@@ -0,0 +1,34 @@
+package duke.task;
+
+/**
+ * Define task type
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+
+public enum TaskType {
+ TODOS, DEADLINE, EVENT;
+
+ /**
+ * Constructor
+ */
+ public static String taskTypeToString(TaskType taskType) {
+ String s = "";
+ switch (taskType) {
+ case TODOS:
+ s = "T";
+ break;
+ case DEADLINE:
+ s = "D";
+ break;
+ case EVENT:
+ s = "E";
+ break;
+ default:
+ throw new IllegalStateException("Unexpected value: " + taskType);
+ }
+ return s;
+ }
+}
diff --git a/src/main/java/duke/ui/Message.java b/src/main/java/duke/ui/Message.java
new file mode 100644
index 00000000..f418948f
--- /dev/null
+++ b/src/main/java/duke/ui/Message.java
@@ -0,0 +1,545 @@
+package duke.ui;
+
+import duke.task.TaskList;
+
+/**
+ * Handle all the message methods
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+
+public class Message {
+
+ // Starting Messages <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+ /**
+ * Display greet message at the start
+ */
+ public static void msgGreet() {
+ String logo = " ____ _ \n" + "| _ \\ _ _| | _____ \n" + "| | | | | | | |/ / _ \\\n"
+ + "| |_| | |_| | < __/\n" + "|____/ \\__,_|_|\\_\\___|\n";
+ System.out.println("Hello from\n" + logo);
+ System.out.println(">>> Copyright (c) Teng Kang Teng (A0211547L NUS) <<<");
+ System.out.println(">>> Version 0.2 <<<\n");
+ System.out.println("Hello! I'm Duke" + System.lineSeparator() + "What can I do for you?");
+ System.out.println("Enter \"Info\" to show all Duke commands. ");
+ System.out.println("_________________________________");
+ }
+
+ // Assignment Messages <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+ /**
+ * Display message when a task is assigned
+ *
+ * @param taskTypeInString String that describes the task type
+ * @param isDoneInString String that describes the isDone status
+ * @param taskDetail String that describes the task detail
+ * @param numOfItem Int that describes the number of items in taskList
+ */
+ public static void msgAssignTaskToDo(String taskTypeInString, String isDoneInString,
+ String taskDetail, int numOfItem) {
+
+ System.out.println(" Got it. I've added this task: ");
+ System.out.println(" [" + taskTypeInString + "][" + isDoneInString + "] " + taskDetail);
+ System.out.println(" Now you have " + numOfItem + " tasks in the list.");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message when a deadline task is assigned
+ *
+ * @param taskTypeInString String that describes the task type
+ * @param isDoneInString String that describes the isDone status
+ * @param taskDetail String that describes the task detail
+ * @param dateInString String that describes the task date
+ * @param numOfItem Int that describes the number of items in taskList
+ */
+ public static void msgAssignTaskDeadlineTaskDate(String taskTypeInString, String isDoneInString,
+ String taskDetail, String dateInString, int numOfItem) {
+
+ System.out.println(" Got it. I've added this task: ");
+ System.out.println(
+ " [" + taskTypeInString + "][" + isDoneInString + "] "
+ + taskDetail + "(by: " + dateInString + ")");
+ System.out.println(" Now you have " + numOfItem + " tasks in the list.");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message when a deadline task is assigned
+ *
+ * @param taskTypeInString String that describes the task type
+ * @param isDoneInString String that describes the isDone status
+ * @param taskDetail String that describes the task detail
+ * @param dateInString String that describes the task date
+ * @param timeInString String that describes the task time
+ * @param numOfItem Int that describes the number of items in taskList
+ */
+ public static void msgAssignTaskDeadlineTaskDateTaskTime(String taskTypeInString, String isDoneInString,
+ String taskDetail, String dateInString,
+ String timeInString, int numOfItem) {
+
+ System.out.println(" Got it. I've added this task: ");
+ System.out.println(
+ " [" + taskTypeInString + "][" + isDoneInString + "] "
+ + taskDetail + "(by: " + dateInString + " " + timeInString + ")");
+ System.out.println(" Now you have " + numOfItem + " tasks in the list.");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message when an event task is assigned
+ *
+ * @param taskTypeInString String that describes task type
+ * @param isDoneInString String that describes is done status
+ * @param taskDetail String that describes task detail
+ * @param dateInString String that describes task date
+ * @param numOfItem Int that describes the number of tasks
+ */
+ public static void msgAssignTaskEventTaskDate(String taskTypeInString, String isDoneInString,
+ String taskDetail, String dateInString, int numOfItem) {
+
+ System.out.println(" Got it. I've added this task: ");
+ System.out.println(" [" + taskTypeInString + "]["
+ + isDoneInString + "] "
+ + taskDetail + "(at: " + dateInString + ")");
+ System.out.println(" Now you have " + numOfItem + " tasks in the list.");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message when an event task is assigned
+ *
+ * @param taskTypeInString String that describes task type
+ * @param isDoneInString String that describes is done status
+ * @param taskDetail String that describes task detail
+ * @param dateInString String that describes task date
+ * @param timeStartInString String that describes the start time
+ * @param numOfItem Int that describes the number of tasks
+ */
+ public static void msgAssignTaskEventTaskDateTaskTimeStart(String taskTypeInString,
+ String isDoneInString,
+ String taskDetail,
+ String dateInString,
+ String timeStartInString,
+ int numOfItem) {
+
+ System.out.println(" Got it. I've added this task: ");
+ System.out.println(" [" + taskTypeInString + "][" + isDoneInString + "] " + taskDetail);
+ System.out.println(" (at: " + dateInString + ", from: " + timeStartInString + ")");
+ System.out.println(" Now you have " + numOfItem + " tasks in the list.");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message when an event task is assigned
+ *
+ * @param taskTypeInString String that describes task type
+ * @param isDoneInString String that describes is done status
+ * @param taskDetail String that describes task detail
+ * @param dateInString String that describes task date
+ * @param timeStartInString String that describes the start time
+ * @param timeEndInString String that describes the end time
+ * @param numOfItem Int that describes the number of tasks
+ */
+ public static void msgAssignEventTaskDateTimeStartEnd(String taskTypeInString,
+ String isDoneInString,
+ String taskDetail,
+ String dateInString,
+ String timeStartInString,
+ String timeEndInString,
+ int numOfItem) {
+
+ System.out.println(" Got it. I've added this task: ");
+ System.out.println(" [" + taskTypeInString + "][" + isDoneInString + "] " + taskDetail);
+ System.out.println(" (at: " + dateInString + ", from: " + timeStartInString
+ + " to " + timeEndInString + ")");
+ System.out.println(" Now you have " + numOfItem + " tasks in the list.");
+ System.out.println("_________________________________");
+ }
+
+ // FileAccess Messages <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+ /**
+ * Display message when task is saved
+ */
+ public static void msgSave() {
+ System.out.println(" Progress Saved!");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message when task is loaded
+ */
+ public static void msgSLoad() {
+ System.out.println(" Progress loaded!");
+ System.out.println("_________________________________");
+ }
+
+ // Set Messages <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+ /**
+ * Display message to ask user which task they want to set priority
+ */
+ public static void msgAskUserSetTaskPriority() {
+ System.out.println(" Which task do you want to set priority?");
+ }
+
+ /**
+ * Display message to ask user what is the new priority
+ */
+ public static void msgAskUserWhatPriority() {
+ System.out.println(" What is it's priority? choose 1 to 3");
+ System.out.println(" 1: Very urgent >>> 3: Chin Cai not that urgent");
+ }
+
+ /**
+ * Display message to tell user that the new priority for a task is set successfully
+ *
+ * @param taskNumber Int that describes the task number in the TaskList
+ * @param taskPriorityInString String that describes the priority of the task
+ */
+ public static void msgSetPriority(int taskNumber, String taskPriorityInString) {
+ System.out.println(" Done! The new task priority is set");
+ System.out.println(" Priority of Task #" + taskNumber + " has been set to " + taskPriorityInString);
+ System.out.println("_________________________________");
+ }
+
+ // Find Messages <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+ /**
+ * Display message to tell user that the term that the user try to find is not found
+ */
+ public static void msgInvalidFindTerm() {
+ System.out.println(" Sorry :( Cannot find what you are looking for ~ ");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message to show the opening message of "find"
+ */
+ public static void msgTaskFoundOpeningMsg() {
+ System.out.println(" Here are the matching tasks in your list:");
+ }
+
+ // Other Messages <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+ /**
+ * Display message when a task is marked as done
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskNumber Int that represents the task number
+ */
+ public static void msgMarkDone(TaskList myList, int taskNumber) {
+ System.out.println(" Naisuuuu! This task is marked as done: ");
+ msgBlankBeforeTaskDetail();
+ new MsgTaskDetail(myList, taskNumber).showTaskDetail();
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message when a task is marked as not done
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskNumber Int that represents the task number
+ */
+ public static void msgMarkUnDone(TaskList myList, int taskNumber) {
+ System.out.println(" Okie! This task is marked as not done: ");
+ msgBlankBeforeTaskDetail();
+ new MsgTaskDetail(myList, taskNumber).showTaskDetail();
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display [x] where x is the int parameter
+ *
+ * Used in CmdList function to show the following:
+ * 1.
+ * 2.
+ * 3.
+ * etc.
+ *
+ * @param index Int that will be put inside the bracket
+ */
+ public static void msgShowBracketWithIndex(int index) {
+ System.out.print(" " + index + ".");
+ }
+
+ /**
+ * Display blanks
+ */
+ public static void msgBlankBeforeTaskDetail() {
+ System.out.print(" ");
+ }
+
+ /**
+ * Display dash lines separator
+ */
+ public static void msgDashLines() {
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display TODO task description
+ */
+ public static void msgTaskTodo(String taskTypeInString, String isDoneInString,
+ String taskDetail, String taskPriorityInString) {
+ System.out.println("[" + taskTypeInString + "]["
+ + isDoneInString + "] " + taskDetail + " [" + taskPriorityInString + "]");
+ }
+
+ /**
+ * Display EVENT task description
+ */
+ public static void msgTaskEvent(String taskTypeInString, String isDoneInString, String taskDetail,
+ String year, String month, String day, String taskPriorityInString) {
+ System.out.println("[" + taskTypeInString + "][" + isDoneInString + "] "
+ + taskDetail + " [" + taskPriorityInString + "]");
+ System.out.println(" (at " + year + " " + month + " " + day + ")");
+ }
+
+ /**
+ * Display EVENT task description
+ */
+ public static void msgTaskEvent(String taskTypeInString,
+ String isDoneInString,
+ String taskDetail,
+ String year,
+ String month,
+ String day,
+ String timeStart,
+ String taskPriorityInString) {
+ System.out.println("[" + taskTypeInString + "]["
+ + isDoneInString + "] " + taskDetail + " [" + taskPriorityInString + "]");
+ System.out.print(" (at " + year + " " + month + " " + day);
+ System.out.println(" ; from: " + timeStart + ")");
+ }
+
+ /**
+ * Display EVENT task description
+ */
+ public static void msgTaskEvent(String taskTypeInString, String isDoneInString, String taskDetail,
+ String year, String month, String day, String timeStart,
+ String timeEnd, String taskPriorityInString) {
+ System.out.println("[" + taskTypeInString + "][" + isDoneInString + "] "
+ + taskDetail + " [" + taskPriorityInString + "]");
+ System.out.print(" (at " + year + " " + month + " " + day);
+ System.out.println(" ; from: " + timeStart + " to " + timeEnd + ")");
+ }
+
+ /**
+ * Display DEADLINE task description
+ */
+ public static void msgTaskDeadline(String taskTypeInString, String isDoneInString, String taskDetail,
+ String year, String month, String day, String taskPriorityInString) {
+ System.out.println("[" + taskTypeInString + "][" + isDoneInString + "] "
+ + taskDetail + " [" + taskPriorityInString + "]");
+ System.out.println(" by: " + year + " " + month + " " + day + ")");
+ }
+
+ /**
+ * Display DEADLINE task description
+ */
+ public static void msgTaskDeadline(String taskTypeInString, String isDoneInString, String taskDetail,
+ String year, String month, String day,
+ String timeStart, String taskPriorityInString) {
+ System.out.println("[" + taskTypeInString + "][" + isDoneInString + "] "
+ + taskDetail + " [" + taskPriorityInString + "]");
+ System.out.println(" by: " + year + " " + month + " " + day + " " + timeStart + ")");
+ }
+
+
+ /**
+ * Display message when a task is removed
+ */
+ public static void msgRemoveItem(TaskList myList, int taskNumber, int numOfTaskAfterDelete) {
+
+ System.out.println(" Noted. I've removed this task:");
+ msgBlankBeforeTaskDetail();
+ new MsgTaskDetail(myList, taskNumber).showTaskDetail();
+ System.out.println(" Now you have " + numOfTaskAfterDelete + " tasks in the list.");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display arrow head
+ */
+ public static void msgArrowHead() {
+ System.out.print(">> ");
+ }
+
+ /**
+ * Display full list of Duke command
+ */
+ public static void msgShowDukeCommandList() {
+ System.out.println(">> Full List of Duke Command Available:");
+ System.out.println(" 1. todo (task description)");
+ System.out.println(" >> add a TODO task");
+ System.out.println(" 2. event (task description)");
+ System.out.println(" >> add a EVENT task");
+ System.out.println(" 3. event (task description)/at (date)");
+ System.out.println(" >> add a EVENT task");
+ System.out.println(" 4. event (task description)/at (date) (time)");
+ System.out.println(" >> add a EVENT task");
+ System.out.println(" 5. deadline (task description)");
+ System.out.println(" >> add a DEADLINE task");
+ System.out.println(" 6. deadline (task description)/by (date)");
+ System.out.println(" >> add a DEADLINE task");
+ System.out.println(" 7. deadline (task description)/by (date) (time start) (time end)");
+ System.out.println(" >> add a DEADLINE task");
+ System.out.println(" 8. list");
+ System.out.println(" >> show full list of task");
+ System.out.println(" 9. set");
+ System.out.println(" >> change priority of a task");
+ System.out.println(" 10. done (task number)");
+ System.out.println(" >> mark a task as completed");
+ System.out.println(" 11. find (keyword)");
+ System.out.println(" >> find a task based on keyword");
+ System.out.println(" 12. info");
+ System.out.println(" >> display full list of Duke Command");
+ System.out.println(" 13. delete (task number)");
+ System.out.println(" >> delete a task");
+ System.out.println(" 14. save");
+ System.out.println(" >> save all the tasks");
+ System.out.println(" 15. bye");
+ System.out.println(" >> end your friendly Duke chat box");
+ System.out.println("_________________________________");
+ }
+ // Error Messages <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+ /**
+ * Display message when a progress file fail to load
+ */
+ public static void msgUnableToLoadProgress() {
+ System.out.println(" >> Fail to load progress. New Task List is created <<");
+ System.out.println("_________________________________");
+ }
+
+
+ /**
+ * Display message when a task is marked as done
+ *
+ * @param e Exception error
+ */
+ public static void msgError(Exception e) {
+ System.out.println("Error Occurs: " + e);
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message that remind user about invalid input
+ */
+ public static void msgInvalidInput() {
+ System.out.println(" Sorry :( Invalid Input. Try Again ~ ");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message that remind user about invalid input
+ * Description of the task is missing
+ */
+ public static void msgInvalidInputMissingDescription() {
+ System.out.println(" OOPS!!! The description cannot be empty.");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message that remind user about invalid input
+ * Date of the task is missing
+ */
+ public static void msgInvalidInputMissingDate() {
+ System.out.println(" OOPS!!! The date cannot be empty.");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message that remind user about invalid input
+ * Time of the task is missing
+ */
+ public static void msgInvalidInputMissingTime() {
+ System.out.println(" OOPS!!! The time cannot be empty.");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message that remind user about invalid input
+ * The task number is not found
+ */
+ public static void msgInvalidTaskNumber() {
+ System.out.println(" OOPS!!! The task number is invalid.");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message that remind user about invalid input
+ * The priority is invalid
+ */
+ public static void msgInvalidPriority() {
+ System.out.println(" OOPS!!! The priority is invalid. Choose 1, 2 or 3");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message that remind user about invalid input
+ * Format of the date is unaccepted
+ */
+ public static void msgInvalidInputWrongDateTimeFormat() {
+ System.out.println(" OOPS!!! Please follow this format:");
+ System.out.println(" /by yyyy-mm-dd hh:mm");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message that remind user about invalid input
+ * Format of the date and time is unaccepted
+ */
+ public static void msgInvalidInputWrongDateTimeStartEndFormat() {
+ System.out.println(" OOPS!!! Please follow this format:");
+ System.out.println(" /at yyyy-mm-dd hh:mm hh:mm:");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message that remind user about invalid input
+ * Start time should be before End time
+ */
+ public static void msgInvalidInputTimeStartLaterThanTimeEnd() {
+ System.out.println(" OOPS!!! Event start time cannot be later than end time!");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message about task list being empty
+ */
+ public static void msgTaskListIsEmpty() {
+ System.out.println(" OOPS!!! The task list is empty.");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display message when buddha.txt fails to load
+ */
+ public static void msgUnableToLoadBuddha() {
+ System.out.println(" >> Buddha Protection is under maintenance <<");
+ System.out.println("_________________________________");
+ }
+
+ // Ending Messages <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+ /**
+ * Display message before the end of program
+ */
+ public static void msgBye() {
+ System.out.println("Bye. Hope to see you again soon!");
+ System.out.println("_________________________________");
+ }
+
+ /**
+ * Display buddha.txt before the end of program
+ */
+ public static void msgBuddha(String buddhaText) {
+ System.out.println(buddhaText);
+ }
+}
diff --git a/src/main/java/duke/ui/MsgTaskDetail.java b/src/main/java/duke/ui/MsgTaskDetail.java
new file mode 100644
index 00000000..0e32401f
--- /dev/null
+++ b/src/main/java/duke/ui/MsgTaskDetail.java
@@ -0,0 +1,155 @@
+package duke.ui;
+
+import duke.task.TaskList;
+import duke.task.TaskPriority;
+import duke.task.TaskType;
+
+/**
+ * Ui class that display message about a task
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+
+public class MsgTaskDetail {
+
+ private static TaskList myList;
+ private static int taskIndex;
+ private static String taskTypeInString;
+ private static String isDoneInString;
+ private static String taskDetail;
+ private static String taskPriorityInString;
+ private static String year;
+ private static String month;
+ private static String day;
+ private static String timeStart;
+ private static String timeEnd;
+
+ /**
+ * Constructor
+ */
+ public MsgTaskDetail(TaskList myList, int taskIndex) {
+ this.myList = myList;
+ this.taskIndex = taskIndex;
+ taskTypeInString = getTaskTypeInString(myList, taskIndex);
+ isDoneInString = getIsDoneInString(myList, taskIndex);
+ taskDetail = getTaskDetail(myList, taskIndex);
+ taskPriorityInString = getTaskPriority(myList, taskIndex);
+ }
+
+ /**
+ * Show task detail based on the task type
+ */
+ public static void showTaskDetail() {
+ TaskType taskType = myList.getTaskType(taskIndex);
+
+ switch (taskType) {
+ case TODOS:
+ showTaskTodo();
+ break;
+ case EVENT:
+ showTaskEvent(myList, taskIndex);
+ break;
+ case DEADLINE:
+ showTaskDeadline(myList, taskIndex);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Show task detail of TODO type
+ */
+ private static void showTaskTodo() {
+ Message.msgTaskTodo(taskTypeInString, isDoneInString, taskDetail, taskPriorityInString);
+ }
+
+ /**
+ * Show task detail of EVENT type
+ */
+ private static void showTaskEvent(TaskList myList, int taskIndex) {
+ year = myList.getTaskEventTaskDateYearInString(taskIndex);
+ month = myList.getTaskEventTaskDateMonthInString(taskIndex);
+ day = myList.getTaskEventTaskDateDayInString(taskIndex);
+ timeStart = myList.getTaskEventTaskTimeStartInString(taskIndex);
+ timeEnd = myList.getTaskEventTaskTimeEndInString(taskIndex);
+
+ if (timeStart.equals("null") && timeEnd.equals("null")) {
+ Message.msgTaskEvent(taskTypeInString, isDoneInString, taskDetail,
+ year, month, day, taskPriorityInString);
+ } else if (timeEnd.equals("null")) {
+ Message.msgTaskEvent(taskTypeInString, isDoneInString, taskDetail,
+ year, month, day, timeStart, taskPriorityInString);
+ } else {
+ Message.msgTaskEvent(taskTypeInString, isDoneInString, taskDetail,
+ year, month, day, timeStart, timeEnd, taskPriorityInString);
+ }
+ }
+
+ /**
+ * Show task detail of DEADLINE type
+ */
+ private static void showTaskDeadline(TaskList myList, int taskIndex) {
+ year = myList.getTaskDeadLineTaskDateYearInString(taskIndex);
+ month = myList.getTaskDeadLineTaskDateMonthInString(taskIndex);
+ day = myList.getTaskDeadLineTaskDateDayInString(taskIndex);
+ timeStart = myList.getTaskDeadLineTaskTimeInString(taskIndex);
+
+ if (timeStart.equals("null")) {
+ Message.msgTaskDeadline(taskTypeInString, isDoneInString, taskDetail,
+ year, month, day, taskPriorityInString);
+ } else {
+ Message.msgTaskDeadline(taskTypeInString, isDoneInString, taskDetail,
+ year, month, day, timeStart, taskPriorityInString);
+ }
+ }
+
+ /**
+ * Get task type in string
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskIndex Int that represents the index of the task
+ * @return String that describes the task type
+ */
+ private static String getTaskTypeInString(TaskList myList, int taskIndex) {
+ TaskType taskType = myList.getTaskType(taskIndex);
+ return TaskType.taskTypeToString(taskType);
+ }
+
+ /**
+ * Get isDone status in string
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskIndex Int that represents the index of the task
+ * @return String that describes the is done status
+ */
+ private static String getIsDoneInString(TaskList myList, int taskIndex) {
+ boolean isDone = myList.getTaskDoneStatus(taskIndex);
+ return (isDone ? "X" : " ");
+ }
+
+ /**
+ * Get task detail in string
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskIndex Int that represents the index of the task
+ * @return String that describes the task detail
+ */
+ private static String getTaskDetail(TaskList myList, int taskIndex) {
+ return myList.getTaskDetail(taskIndex);
+ }
+
+ /**
+ * Get task priority in string
+ *
+ * @param myList TaskList that contains the list of task
+ * @param taskIndex Int that represents the index of the task
+ * @return String that describes the priority of a task
+ */
+ private static String getTaskPriority(TaskList myList, int taskIndex) {
+ TaskPriority taskPriority = myList.getTaskPriority(taskIndex);
+ return TaskPriority.convertPriorityToString(taskPriority);
+ }
+}
diff --git a/src/main/java/duke/ui/Ui.java b/src/main/java/duke/ui/Ui.java
new file mode 100644
index 00000000..5f861b0e
--- /dev/null
+++ b/src/main/java/duke/ui/Ui.java
@@ -0,0 +1,37 @@
+package duke.ui;
+
+
+import java.util.Scanner;
+
+/**
+ * Interface class for User Interface
+ *
+ * @author Kang Teng
+ * @version 8.0
+ * @since 2021-09-01
+ */
+
+public class Ui {
+
+ public Ui() {
+
+ }
+
+ /**
+ * request user input and read the input string
+ *
+ * @param scanner Scanner that read user input
+ */
+ public String requestUserInput(Scanner scanner) {
+
+ String userInput = "";
+
+ try {
+ Message.msgArrowHead();
+ userInput = scanner.nextLine();
+ } catch (Exception e) {
+ Message.msgError(e);
+ }
+ return userInput;
+ }
+}
diff --git a/src/resources/FutureImporvement.txt b/src/resources/FutureImporvement.txt
new file mode 100644
index 00000000..a92d8f62
--- /dev/null
+++ b/src/resources/FutureImporvement.txt
@@ -0,0 +1,6 @@
+Level 8:
+1. date time should accept other format. for now cannot.
+2. Stretch goal: Use dates and times in more meaningful ways. e.g., add a command to print deadlines/events occurring on a specific date.
+3. save the time and date
+4. JUnit Test buggy
+5. Read JUnit Basic
\ No newline at end of file
diff --git a/src/resources/buddha.txt b/src/resources/buddha.txt
new file mode 100644
index 00000000..d792d29f
--- /dev/null
+++ b/src/resources/buddha.txt
@@ -0,0 +1,24 @@
+//
+// _oo0oo_
+// o8888888o
+// 88" . "88
+// (| -_- |)
+// 0\ = /0
+// ___/`---'\___
+// .' \\| |// '.
+// / \\||| : |||// \
+// / _||||| -:- |||||- \
+// | | \\\ - /// | |
+// | \_| ''\---/'' |_/ |
+// \ .-\__ '-' ___/-. /
+// ___'. .' /--.--\ `. .'___
+// ."" '< `.___\_<|>_/___.' >' "".
+// | | : `- \`.;`\ _ /`;.`/ - ` : | |
+// \ \ `_. \_ __\ /__ _/ .-` / /
+// =====`-.____`.___ \_____/___.-`___.-'=====
+// `=---='
+//
+//
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Buddha Protect Me Say Bye to All Bug
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\ No newline at end of file
diff --git a/src/resources/progress.txt b/src/resources/progress.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/src/resources/progress_backup.txt b/src/resources/progress_backup.txt
new file mode 100644
index 00000000..cf18a6ab
--- /dev/null
+++ b/src/resources/progress_backup.txt
@@ -0,0 +1,5 @@
+0|E|0|project meeting|1|2001-01-25|null|null|;
+1|E|0|project meeting|3|2002-06-25|18:00|null|;
+2|E|0|project meeting|3|2002-06-25|18:00|19:00|;
+3|D|0|return book|3|2010-01-25|null|;
+4|D|0|return book|3|2011-02-25|06:00|;
diff --git a/src/test/java/duke/SampleTest.java b/src/test/java/duke/SampleTest.java
new file mode 100644
index 00000000..51694fe4
--- /dev/null
+++ b/src/test/java/duke/SampleTest.java
@@ -0,0 +1,64 @@
+package duke;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class SampleTest {
+ @Test
+ @DisplayName("Sample JUnit Test")
+ @Disabled("Sample Test")
+ public void dummyTest() {
+ assertEquals(2, 2);
+ }
+
+ @Test
+ @Disabled("Sample Test")
+ public void dummyFailTest() {
+ assertEquals(2, 1);
+ }
+
+ @Test
+ @Disabled("Sample Test")
+ public void shouldShowSimpleAssertion() {
+ assertEquals(1, 1);
+ assertEquals(1, 2);
+ }
+
+ @Test
+ @DisplayName("Should check all items in the list")
+ @Disabled("Sample Test")
+ public void shouldCheckAllItemsInTheList() {
+ List