diff --git a/data/tasks.txt b/data/tasks.txt new file mode 100644 index 0000000000..1a5db500c6 --- /dev/null +++ b/data/tasks.txt @@ -0,0 +1,10 @@ +D | 1 | CS2105 Assignment 0 | 2021-08-29 2359 +D | 1 | PC1201 Test 1 (First Mock Test) | 2021-09-02 1400 +D | 1 | CS2103 Week 4 Quiz | 2021-08-30 2359 +D | 0 | CS3240 Week 4 Quiz | 2021-08-31 2000 +T | 0 | Vacuum room floor +T | 0 | Change bedsheet +T | 0 | Download files from LumiNUS +T | 0 | CS2103 Week 3 Deliverables (JUnit) +T | 0 | CS2103 Week 3 Deliverables (Jar) +T | 0 | CS2103 Week 3 Deliverables (Javadocs) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java deleted file mode 100644 index 5d313334cc..0000000000 --- a/src/main/java/Duke.java +++ /dev/null @@ -1,10 +0,0 @@ -public class Duke { - public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - } -} diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java new file mode 100644 index 0000000000..6bc85ada50 --- /dev/null +++ b/src/main/java/duke/Duke.java @@ -0,0 +1,62 @@ +package duke; + +import duke.command.Command; + +import java.io.IOException; + +/** + * The driver class that runs the program + */ +public class Duke { + private Ui ui; + private Parser parser; + private Storage storage; + private TaskList taskList; + + /** + * Initializes an instance of Duke class. + * @param pathName Folder name of the storage file + * @param fileName Name of the storage file + */ + public Duke(String pathName, String fileName) { + ui = new Ui(); + parser = new Parser(); + + try { + storage = new Storage(pathName, fileName); + taskList = storage.loadTasksFromFile(); + } catch (DukeException | IOException e) { + ui.displayError(e.getMessage()); + taskList = new TaskList(); + } + } + + /** + * Starts the execution of the program. + * @param args Command line arguments + */ + public static void main(String[] args) { + new Duke("data", "tasks.txt").run(); + } + + /** + * Executes the program. + */ + public void run() { + ui.displayWelcome(); + boolean isExit = false; + + while (!isExit) { + try { + String commandLine = ui.readCommand(); + Command command = parser.parse(commandLine); + command.execute(taskList, ui, storage); + isExit = command.isExit(); + } catch (DukeException e) { + ui.displayError(e.getMessage()); + } finally { + ui.displayLine(); + } + } + } +} diff --git a/src/main/java/duke/DukeException.java b/src/main/java/duke/DukeException.java new file mode 100644 index 0000000000..27ac300f88 --- /dev/null +++ b/src/main/java/duke/DukeException.java @@ -0,0 +1,14 @@ +package duke; + +/** + * A class to handle any exceptions during the program execution + */ +public class DukeException extends Exception { + /** + * Initializes and instance of DukeException class. + * @param errorMessage The error message. + */ + public DukeException(String errorMessage) { + super(errorMessage); + } +} diff --git a/src/main/java/duke/Parser.java b/src/main/java/duke/Parser.java new file mode 100644 index 0000000000..ed2049f930 --- /dev/null +++ b/src/main/java/duke/Parser.java @@ -0,0 +1,294 @@ +package duke; + +import duke.command.AddDeadlineCommand; +import duke.command.AddEventCommand; +import duke.command.AddToDoCommand; +import duke.command.Command; +import duke.command.DeleteCommand; +import duke.command.DoneCommand; +import duke.command.ExitCommand; +import duke.command.ListCommand; +import duke.command.PrintCommand; + +/** + * A class that contaisn methods to parse command line strings + */ +public class Parser { + /** + * Parses a command line string input on screen to get the details + * of the Command object + * @param commandLine The command line string to parse + * @return The Command object + * @throws DukeException If the command line string is not valid + */ + public Command parse(String commandLine) throws DukeException { + String[] commandLineParts = commandLine.split("\\s+", 2); + + String commandType; + String commandInfo; + + if (commandLineParts.length == 2) { + commandType = commandLineParts[0]; + commandInfo = commandLineParts[1]; + + // If user inputs extra text after "bye" or "list" commands + if ((commandType.equals("bye") || commandType.equals("list")) && !commandInfo.equals("")) { + throw new DukeException("INVALID COMMAND. Please try again!"); + } + } else { // for "bye" and "list" commands + commandType = commandLineParts[0]; + commandInfo = ""; + } + + Command command; + int taskNum; + String taskDescription; + String taskInfo; + String date; + + switch (commandType) { + case "bye": + command = new ExitCommand(commandType); + break; + case "list": + command = new ListCommand(commandType); + break; + case "done": + taskNum = getTaskNumFromCommand(commandInfo); + command = new DoneCommand(commandType, taskNum); + break; + case "delete": + taskNum = getTaskNumFromCommand(commandInfo); + command = new DeleteCommand(commandType, taskNum); + break; + case "todo": + taskDescription = getTaskDescriptionFromToDoCommand(commandInfo); + command = new AddToDoCommand(commandType, taskDescription); + break; + case "deadline": + taskInfo = getTaskInfoFromDeadlineCommand(commandInfo); + command = new AddDeadlineCommand(commandType, taskInfo); + break; + case "event": + taskInfo = getTaskInfoFromEventCommand(commandInfo); + command = new AddEventCommand(commandType, taskInfo); + break; + case "print": + date = getDateFromPrintCommand(commandInfo); + command = new PrintCommand(commandType, date); + break; + default: + throw new DukeException("INVALID COMMAND. Please try again!"); + } + + return command; + } + + /** + * Gets task number from the command information. + * @param commandInfo The command information + * @return The task number + * @throws DukeException If the information is not valid + */ + private int getTaskNumFromCommand(String commandInfo) throws DukeException { + if (commandInfo.trim().length() > 0) { + try { + return Integer.parseInt(commandInfo); + } catch (NumberFormatException e) { + throw new DukeException("Please enter a valid task number to be marked as done!"); + } + } else { + throw new DukeException("Please enter a task number to be marked as done!"); + } + } + + /** + * Gets task description from ToDo command information. + * @param commandInfo The ToDo command information + * @return The task description + * @throws DukeException If the information is not valid + */ + private String getTaskDescriptionFromToDoCommand(String commandInfo) throws DukeException { + if (commandInfo.trim().length() > 0) { + return commandInfo; + } else { + throw new DukeException("The description of a todo cannot be empty!"); + } + } + + /** + * + * @param commandInfo + * @return + * @throws DukeException + */ + private String getTaskInfoFromDeadlineCommand(String commandInfo) throws DukeException { + if (commandInfo.trim().length() > 0) { + String[] deadlineTaskDetails = commandInfo.split("/", 2); + + if (deadlineTaskDetails.length == 2) { + if (deadlineTaskDetails[0].trim().length() > 0) { + if (deadlineTaskDetails[1].trim().startsWith("by")) { + String beforeDateTime = deadlineTaskDetails[1].trim(); + String[] beforeDateTimeParts = beforeDateTime.split("\\s+", 2); + + if (beforeDateTimeParts.length == 2) { + return commandInfo; + } else { + throw new DukeException("INCOMPLETE COMMAND" + + System.lineSeparator() + "\t" + + "The date/time of a deadline cannot be empty!" + + System.lineSeparator() + "\t" + + "[Note: Enter /by before specifying the date/time]"); + } + } else { + throw new DukeException("WRONG COMMAND" + + System.lineSeparator() + "\t" + + "Enter /by before specifying the date!"); + } + } else { + if (deadlineTaskDetails[1].trim().startsWith("by")) { + String beforeDateTime = deadlineTaskDetails[1].trim(); + String[] beforeDateTimeParts = beforeDateTime.split("\\s+", 2); + + if (beforeDateTimeParts.length == 2) { + throw new DukeException("INCOMPLETE COMMAND" + + System.lineSeparator() + "\t" + + "The description of a deadline cannot be empty!"); + } else { + throw new DukeException("INCOMPLETE COMMAND" + + System.lineSeparator() + "\t" + + "The description of a deadline cannot be empty!" + + System.lineSeparator() + "\t" + + "The date/time of a deadline cannot be empty!" + + System.lineSeparator() + "\t" + + "[Note: Enter /by before specifying the date/time]"); + } + } else { + throw new DukeException("INCOMPLETE & WRONG COMMAND" + + System.lineSeparator() + "\t" + + "The description of a deadline cannot be empty!" + + System.lineSeparator() + "\t" + + "Enter /by before specifying the date/time!"); + } + } + } else { + throw new DukeException("INCOMPLETE COMMAND" + + System.lineSeparator() + "\t" + + "The date/time of a deadline cannot be empty!" + + System.lineSeparator() + "\t" + + "[Note: Enter /by before specifying the date/time]"); + } + } else { + throw new DukeException("INCOMPLETE COMMAND" + + System.lineSeparator() + "\t" + + "The description and date/time of a deadline cannot be empty!" + + System.lineSeparator() + "\t" + + "[Note: Enter /by before specifying the date/time]"); + } + } + + /** + * + * @param commandInfo + * @return + * @throws DukeException + */ + private String getTaskInfoFromEventCommand(String commandInfo) throws DukeException { + if (commandInfo.trim().length() > 0) { + String[] eventTaskDetails = commandInfo.split("/", 2); + + if (eventTaskDetails.length == 2) { + if (eventTaskDetails[0].trim().length() > 0) { + if (eventTaskDetails[1].trim().startsWith("at")) { + String startEndDateTime = eventTaskDetails[1].trim(); + String[] startEndDateTimeParts = startEndDateTime.split("\\s+", 2); + + if (startEndDateTimeParts.length == 2) { + return commandInfo; + } else { + throw new DukeException("INCOMPLETE COMMAND" + + System.lineSeparator() + "\t" + + "The date/time of an event cannot be empty!" + + System.lineSeparator() + "\t" + + "[Note: Enter /at before specifying the date/time]"); + } + } else { + throw new DukeException("WRONG COMMAND" + + System.lineSeparator() + "\t" + + "Enter /at before specifying the date!"); + } + } else { + if (eventTaskDetails[1].trim().startsWith("at")) { + String startEndDateTime = eventTaskDetails[1].trim(); + String[] startEndDateTimeParts = startEndDateTime.split("\\s+", 2); + + if (startEndDateTimeParts.length == 2) { + throw new DukeException("INCOMPLETE COMMAND" + + System.lineSeparator() + "\t" + + "The description of an event cannot be empty!"); + } else { + throw new DukeException("INCOMPLETE COMMAND" + + System.lineSeparator() + "\t" + + "The description of an event cannot be empty!" + + System.lineSeparator() + "\t" + + "The date/time of an event cannot be empty!" + + System.lineSeparator() + "\t" + + "[Note: Enter /at before specifying the date/time]"); + } + } else { + throw new DukeException("INCOMPLETE & WRONG COMMAND" + + System.lineSeparator() + "\t" + + "The description of an event cannot be empty!" + + System.lineSeparator() + "\t" + + "Enter /at before specifying the date/time!"); + } + } + } else { + throw new DukeException("INCOMPLETE COMMAND" + + System.lineSeparator() + "\t" + + "The date/time of an event cannot be empty!" + + System.lineSeparator() + "\t" + + "[Note: Enter /at before specifying the date/time]"); + } + } else { + throw new DukeException("INCOMPLETE COMMAND" + + System.lineSeparator() + "\t" + + "The description and date/time of an event cannot be empty!" + + System.lineSeparator() + "\t" + + "[Note: Enter /at before specifying the date/time]"); + } + } + + /** + * + * @param commandInfo + * @return + * @throws DukeException + */ + private String getDateFromPrintCommand(String commandInfo) throws DukeException { + if (commandInfo.trim().length() > 0) { + if (commandInfo.trim().startsWith("/on")) { + String[] specificDateParts = commandInfo.split("\\s+", 2); + + if (specificDateParts.length == 2) { + return specificDateParts[1]; + } else { + throw new DukeException("INCOMPLETE COMMAND" + + System.lineSeparator() + "\t" + + "The date is not specified!" + + System.lineSeparator() + "\t" + + "[Note: Enter /on before specifying the date]"); + } + } else { + throw new DukeException("WRONG COMMAND" + + System.lineSeparator() + "\t" + + "Enter /on before specifying the date!"); + } + } else { + throw new DukeException("INCOMPLETE COMMAND" + + System.lineSeparator() + "\t" + + "Enter /on before specifying the date!"); + } + } +} diff --git a/src/main/java/duke/Storage.java b/src/main/java/duke/Storage.java new file mode 100644 index 0000000000..110c5394d4 --- /dev/null +++ b/src/main/java/duke/Storage.java @@ -0,0 +1,169 @@ +package duke; + +import duke.task.Deadline; +import duke.task.Event; +import duke.task.Task; +import duke.task.TaskType; +import duke.task.TaskWithDateTime; +import duke.task.ToDo; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Queue; + +/** + * A class that contains methods to read from and write to the storage file + */ +public class Storage { + private String pathName; + private String fileName; + private File dataDirectory; + private File dataFile; + + /** + * Initializes an instance of Storage class. + * @param pathName Path of the file + * @param fileName Name of the file + * @throws DukeExceptio If initializing the directory fails + * @throws IOException If initializing the file fails + */ + public Storage(String pathName, String fileName) throws DukeException, IOException { + this.pathName = pathName; + this.fileName = fileName; + dataDirectory = initialiseDirectory(); + dataFile = initialiseFile(dataDirectory); + } + + /** + * Creates the directory for the storage file if the directory does not exist. + * @return The File object + * @throws DukeException If the directory cannot be created + */ + private File initialiseDirectory() throws DukeException { + File directory = new File(pathName); + boolean hasDirectory = directory.exists(); + + if (!hasDirectory) { + hasDirectory = directory.mkdir(); + } + + if (hasDirectory) { + return directory; + } else { + throw new DukeException("\t" + "Unable to initialise directory"); + } + } + + /** + * Creates the storage file if it does not exist. + * @param directory The directory of the storage file + * @return The File object + * @throws IOException If the file cannot be created + */ + private File initialiseFile(File directory) throws IOException { + File file = new File(directory + "/" + fileName); + boolean hasFile = file.exists(); + + if (!hasFile) { + hasFile = file.createNewFile(); + } + + if (hasFile) { + return file; + } else { + throw new IOException("\t" + "Unable to initialise file"); + } + } + + /** + * Loads tasks from the storage file. + * @return The list of tasks + * @throws IOException If the tasks cannot be loaded + */ + public TaskList loadTasksFromFile() throws IOException { + TaskList taskList = new TaskList(); + + FileReader fileReader = new FileReader(dataFile); + BufferedReader bufferedReader = new BufferedReader(fileReader); + String line; + + while ((line = bufferedReader.readLine()) != null) { + String[] taskDetails = line.trim().split("\\|"); + String type = taskDetails[0].trim(); + boolean isDone = (Integer.parseInt(taskDetails[1].trim()) == 1); + String description = taskDetails[2].trim(); + String dateTime; + + switch (type) { + case "T": + Task todoTask = new ToDo(TaskType.TODO, description, isDone); + taskList.add(todoTask); + break; + case "D": + dateTime = taskDetails[3].trim(); + Task deadlineTask = new Deadline(TaskType.DEADLINE, description, dateTime, isDone); + taskList.add(deadlineTask); + break; + case "E": + dateTime = taskDetails[3].trim(); + Task eventTask = new Event(TaskType.EVENT, description, dateTime, isDone); + taskList.add(eventTask); + break; + } + } + + bufferedReader.close(); + + return taskList; + } + + /** + * Saves the tasks to the storage file. + * @param taskList The list of tasks to be saved + * @throws IOException If the tasks cannot be saved + */ + public void saveTasksToFile(TaskList taskList) throws IOException { + FileWriter fileWriter = new FileWriter(dataFile,false); + BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); + + for (int i = 0; i < taskList.size(); i++) { + Task task = taskList.get(i); + + TaskType type = task.getType(); + boolean isDone = task.isDone(); + String description = task.getDescription(); + String dateTime; + + if (type == TaskType.TODO) { + dateTime = ""; + } else { + dateTime = ((TaskWithDateTime) task).getDateTimeInput(); + } + + String taskToSave = taskSaveFormat(type, isDone, description, dateTime); + bufferedWriter.write(taskToSave + System.lineSeparator()); + } + + bufferedWriter.close(); + } +` + /** + * Creates and returns the formatted task details to be saved. + * @param type Type of task + * @param isDone Flag to indicate if the task has been completed + * @param description The task description + * @param dateTime The date/time of the task + * @return The formatted task details + */ + private String taskSaveFormat(TaskType type, boolean isDone, String description, String dateTime) { + if (dateTime.equals("")) { + return type.getAbbr() + " | " + (isDone ? "1" : "0") + " | " + description; + } else { + return type.getAbbr() + " | " + (isDone ? "1" : "0") + " | " + description + " | " + dateTime; + } + } +} diff --git a/src/main/java/duke/TaskList.java b/src/main/java/duke/TaskList.java new file mode 100644 index 0000000000..085e0e8b63 --- /dev/null +++ b/src/main/java/duke/TaskList.java @@ -0,0 +1,67 @@ +package duke; + +import duke.task.Task; + +import java.util.ArrayList; +import java.util.List; + +/** + * A class representing the task collection + */ +public class TaskList { + private List tasks; + + /** + * Initializes an instance of TaskList class. + * Creates an ArrayList of tasks. + */ + public TaskList() { + tasks = new ArrayList(); + } + + /** + * Returns the number of tasks. + * @return The number of tasks + */ + public int size() { + return tasks.size(); + } + + /** + * Returns the Task object at a given index of the list of tasks. + * @param index The list index at which the Task has to be accessed + * @return The Task object + */ + public Task get(int index) { + return tasks.get(index); + } + + /** + * Adds a new Task + * @param task The Task to be added + */ + public void add(Task task) { + tasks.add(task); + } + + /** + * Removes a Task from the list at a given index. + * @param index The index at which the Task is to be removed + * @return The removed Task object + */ + public Task remove(int index) { + Task task = tasks.get(index); + tasks.remove(task); + return task; + } + + /** + * Removes a Task from the list. + * @param task The Task object to be removed + * @return The removed Task object + */ + public Task remove(Task task) { + tasks.remove(task); + return task; + } +} diff --git a/src/main/java/duke/Ui.java b/src/main/java/duke/Ui.java new file mode 100644 index 0000000000..b9c33a79f7 --- /dev/null +++ b/src/main/java/duke/Ui.java @@ -0,0 +1,244 @@ +package duke; + +import duke.task.Task; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Scanner; + +/** + * A class that contains methods to handle i/o operations through screen + */ +public class Ui { + /** + * Reads command line string from the user. + */ + public String readCommand() { + Scanner sc = new Scanner(System.in); + System.out.println("ENTER COMMAND:"); + System.out.print("\t"); + return sc.nextLine().trim(); + } + + /** + * Displays goodbye message on exiting. + */ + public void exit() { + String message = "\t" + "Bye. Hope to see you again soon!"; + displayResponse(message); + } + + /** + * Greets the user with a welcome message. + */ + public void displayWelcome() { + displayLine(); + displayWelcomeMessage(); + displayMenuOptions(); + displayLine(); + } + + /** + * Displays a message with proper formatting. + * @param message Message to be displayed + */ + public void displayResponse(String message) { + displayLine(); + System.out.println(message); + } + + /** + * Dis[lays an error message with proper formatting + * @param message Error message to be displayed + */ + public void displayError(String message) { + displayLine(); + System.out.println("ERROR MESSAGE:"); + System.out.println("\t" + "☹ " + message); + } + + /** + * Displays a line to seoarate different parts of a message + */ + public void displayLine() { + String horizontalLine = "____________________________________________________________"; + System.out.println(horizontalLine); + } + + /** + * Displays welcome message with proper formatting. + */ + private void displayWelcomeMessage() { + String message = "\t" + "Hello! I'm Duke, your Personal Assistant ChatBot." + + System.lineSeparator() + + "\t" + "What can I do for you?" + + System.lineSeparator(); + System.out.println(message); + } + + /** + * Displays the menu of options. + */ + private void displayMenuOptions() { + String format = "%-25s%s%n"; + + String menuOption1 = "\t" + "list:"; + String menuOption1Info = "List the tasks in your list"; + + String menuOption2 = "\t" + "todo ABC:"; + String menuOption2Info = "Add a todo [T] task, ABC, into your list"; + + String menuOption3 = "\t" + "deadline ABC /by XYZ:"; + String menuOption3Info = "Add a deadline [D] task, ABC, into your list " + + "and specify the date/time, XYZ, it needs to be completed by"; + + String menuOption4 = "\t" + "event ABC /at XYZ:"; + String menuOption4Info = "Add an event [E] task, ABC, into your list " + + "and specify the start and end date/time, XYZ"; + + String menuOption5 = "\t" + "done N:"; + String menuOption5Info = "Mark a task number, N, as done"; + + String menuOption6 = "\t" + "delete N:"; + String menuOption6Info = "Delete a task number, N, from your list"; + + String menuOption7 = "\t" + "print /on yyyy-mm-dd:"; + String menuOption7Info = "Print deadlines/events on a specific date"; + + String menuOption8 = "\t" + "bye:"; + String menuOption8Info = "Exit the ChatBot"; + + System.out.printf(format, menuOption1, menuOption1Info); + System.out.printf(format, menuOption2, menuOption2Info); + System.out.printf(format, menuOption3, menuOption3Info); + System.out.printf(format, menuOption4, menuOption4Info); + System.out.printf(format, menuOption5, menuOption5Info); + System.out.printf(format, menuOption6, menuOption6Info); + System.out.printf(format, menuOption7, menuOption7Info); + System.out.printf(format, menuOption8, menuOption8Info); + } + + /** + * Displays a message when a new task is added. + * @param task The task added + * @return + */ + public String taskAddedMessage(Task task) { + return "\t" + "Got it. I've added this task:" + + System.lineSeparator() + "\t\t" + task; + } + + /** + * Displays a message when a task is removed + * @param task The task removed + * @return + */ + public String taskDeletedMessage(Task task) { + return "\t" + "Noted. I've removed this task:" + + System.lineSeparator() + "\t\t" + task; + } + + /** + * Displays a message when a task has been executed. + * @param task The task executed + * @return + */ + public String taskDoneMessage(Task task) { + return "\t" + "Nice! I've marked this task as done:" + + System.lineSeparator() + "\t\t" + task; + } + + /** + * Gets a message containing the number of tasks. + * @param taskList List of tasks + * @return a string containing size of the list of tasks. + */ + public String getNumOfTasksInList(TaskList taskList) { + return "\t" + "Now you have " + taskList.size() + + (taskList.size() > 1 ? " tasks" : " task") + + " in the list."; + } + + /** + * Gets a message containing the list of tasks. + * @param taskList List of tasks + * @return a string containing the list of tasks + */ + public String getTasksInList(TaskList taskList) { + StringBuilder response = new StringBuilder("\t" + "Here are the tasks in your list:" + + System.lineSeparator() + + "\t" + "[Legend: T = todo, D = deadline, E = event]" + + System.lineSeparator() + + System.lineSeparator()); + + for (int i = 0; i < taskList.size(); i++) { + if (i != 0) { + response.append(System.lineSeparator()); + } + + response.append("\t\t").append(i + 1).append(".") + .append("\t").append(taskList.get(i).toString()); + } + + return response.toString(); + } + + /** + * Gets a message containing the list of tasks on a specified date. + * @param dateStr The date corresponding which the tasks have to be found. + * @param taskList List of all tasks + * @return a string containing the list of tasks on the given date + */ + public String getTasksOnDate(String dateStr, TaskList taskList) { + TaskList taskOnDateList = new TaskList(); + + for (int i = 0; i < taskList.size(); i++) { + if (taskList.get(i).isOnDate(dateStr)) { + taskOnDateList.add(taskList.get(i)); + } + } + + StringBuilder response; + + if (taskOnDateList.size() != 0) { + response = new StringBuilder("\t" + "Here are the tasks on this date (" + + processDateStr(dateStr) + "):" + + System.lineSeparator() + + "\t" + "[Legend: T = todo, D = deadline, E = event]" + + System.lineSeparator() + + System.lineSeparator()); + + for (int i = 0; i < taskOnDateList.size(); i++) { + if (i != 0) { + response.append(System.lineSeparator()); + } + + response.append("\t\t").append(i + 1).append(".") + .append("\t").append(taskOnDateList.get(i).toString()); + } + } else { + response = new StringBuilder("\t" + "There are no tasks on this date."); + } + + return response.toString(); + } + + /** + * Converts a given date from local format to "mmm d yyyy" format. + * @param dateStr A string containing date in local format + * @return A string containing date in "mmm d yyyy" format + */ + private String processDateStr(String dateStr) { + LocalDate date; + String processedDateStr; + + try { + date = LocalDate.parse(dateStr); + processedDateStr = date.format(DateTimeFormatter.ofPattern("MMM d yyyy")); + } catch (Exception e) { + processedDateStr = dateStr; + } + + return processedDateStr; + } +} diff --git a/src/main/java/duke/command/AddCommand.java b/src/main/java/duke/command/AddCommand.java new file mode 100644 index 0000000000..1d5faf7c7d --- /dev/null +++ b/src/main/java/duke/command/AddCommand.java @@ -0,0 +1,40 @@ +package duke.command; + +import duke.Storage; +import duke.TaskList; +import duke.Ui; + +/** + * An abstract class to represent add command operation + */ +public abstract class AddCommand extends Command { + private String taskDescription; + + /** + * Initializes the instance of AddCommand with task type and description. + * @param type Type of task + * @param taskDescription: Task description + */ + public AddCommand(String type, String taskDescription) { + super(type); + this.taskDescription = taskDescription; + } + + /** + * Returns task description. + * @return Task description + */ + public String getTaskDescription() { + return taskDescription; + } + + /** + * An abstract method to execute an AddCommand task. + * The method will be implemented in the derived classes. + * @param taskList List of tasks + * @param ui An instance of a class to handle i/o operations + * @param storage An instance of a class to read from and write to file + */ + @Override + public abstract void execute(TaskList taskList, Ui ui, Storage storage); +} diff --git a/src/main/java/duke/command/AddDeadlineCommand.java b/src/main/java/duke/command/AddDeadlineCommand.java new file mode 100644 index 0000000000..14005c505b --- /dev/null +++ b/src/main/java/duke/command/AddDeadlineCommand.java @@ -0,0 +1,61 @@ +package duke.command; + +import duke.DukeException; +import duke.Storage; +import duke.TaskList; +import duke.Ui; +import duke.task.Deadline; +import duke.task.Task; +import duke.task.TaskType; + +import java.io.IOException; + +/** + * A class that contains methods to add a Deadline command + */ +public class AddDeadlineCommand extends AddCommand { + private String taskDateTime; + + /** + * Initializes an instance of AddDeadlineCommand class. + * @param type Type of task + * @param taskInfo Further information about the task + */ + public AddDeadlineCommand(String type, String taskInfo) { + super(type, taskInfo.split("/", 2)[0].trim()); + + String taskByDateTime = taskInfo.split("/", 2)[1].trim(); + taskDateTime = taskByDateTime.split("\\s+", 2)[1].trim(); + } + + /** + * Executes the task + * @param taskList List of tasks + * @param ui An object to handle i/o operations through screen + * @param storage An object to read from and write to file + */ + @Override + public void execute(TaskList taskList, Ui ui, Storage storage) { + try { + addDeadlineTask(taskList, ui); + storage.saveTasksToFile(taskList); + } catch (DukeException | IOException e) { + ui.displayError(e.getMessage()); + } + } + + /** + * + * @param taskList List of tasks + * @param ui An object to handle i/o operations through screen + * @throws DukeException Any exception found + */ + public void addDeadlineTask(TaskList taskList, Ui ui) throws DukeException { + Task newDeadlineTask = new Deadline(TaskType.DEADLINE, super.getTaskDescription(), taskDateTime); + taskList.add(newDeadlineTask); + + String response = ui.taskAddedMessage(newDeadlineTask) + + System.lineSeparator() + ui.getNumOfTasksInList(taskList); + ui.displayResponse(response); + } +} diff --git a/src/main/java/duke/command/AddEventCommand.java b/src/main/java/duke/command/AddEventCommand.java new file mode 100644 index 0000000000..5d6eea2884 --- /dev/null +++ b/src/main/java/duke/command/AddEventCommand.java @@ -0,0 +1,61 @@ +package duke.command; + +import duke.DukeException; +import duke.Storage; +import duke.TaskList; +import duke.Ui; +import duke.task.Event; +import duke.task.Task; +import duke.task.TaskType; + +import java.io.IOException; + +/** + * A class that contains methods to add Event tasks + */ +public class AddEventCommand extends AddCommand { + private String taskDateTime; + + /** + * Initializes an instance of AddEventCommand class + * @param type Type of task + * @param taskInfo Further information about the task + */ + public AddEventCommand(String type, String taskInfo) { + super(type, taskInfo.split("/", 2)[0].trim()); + + String taskAtDateTime = taskInfo.split("/", 2)[1].trim(); + taskDateTime = taskAtDateTime.split("\\s+", 2)[1].trim(); + } + + /** + * Executes an Event task + * @param taskList List of tasks + * @param ui An object to handle i/o operations through screen + * @param storage An object to read from and write to file + */ + @Override + public void execute(TaskList taskList, Ui ui, Storage storage) { + try { + addEventTask(taskList, ui); + storage.saveTasksToFile(taskList); + } catch (DukeException | IOException e) { + ui.displayError(e.getMessage()); + } + } + + /** + * Adds an Event task + * @param taskList List of tasks + * @param ui An object to handle i/o operations through screen + * @throws DukeException Any exception + */ + public void addEventTask(TaskList taskList, Ui ui) throws DukeException { + Task newEventTask = new Event(TaskType.EVENT, super.getTaskDescription(), taskDateTime); + taskList.add(newEventTask); + + String response = ui.taskAddedMessage(newEventTask) + + System.lineSeparator() + ui.getNumOfTasksInList(taskList); + ui.displayResponse(response); + } +} diff --git a/src/main/java/duke/command/AddToDoCommand.java b/src/main/java/duke/command/AddToDoCommand.java new file mode 100644 index 0000000000..a6e23164cc --- /dev/null +++ b/src/main/java/duke/command/AddToDoCommand.java @@ -0,0 +1,57 @@ +package duke.command; + +import duke.DukeException; +import duke.Storage; +import duke.TaskList; +import duke.Ui; +import duke.task.Task; +import duke.task.TaskType; +import duke.task.ToDo; + +import java.io.IOException; + +/** + * A class that contains methods to add ToDo tasks to task list and a storage file. + */ +public class AddToDoCommand extends AddCommand { + /** + * Initializes an instance of AddToDoComman task. + * @param type Type of task + * @param taskDescription Task description + */ + public AddToDoCommand(String type, String taskDescription) { + super(type, taskDescription); + } + + /** + * Executes the operation of adding a new ToDo task to the list and + * saving it to the file. + * @param taskList The task list + * @param ui An object to handle i/o operations through screen + * @param storage An object to read from and write to storage file. + */ + @Override + public void execute(TaskList taskList, Ui ui, Storage storage) { + try { + addToDoTask(taskList, ui); + storage.saveTasksToFile(taskList); + } catch (DukeException | IOException e) { + ui.displayError(e.getMessage()); + } + } + + /** + * Creates a new ToDo task and adds it to the task list. + * @param taskList The task list + * @param ui An object to handle i/o operations through screen + * @throws DukeException If a new ToDo task cannot be created + */ + public void addToDoTask(TaskList taskList, Ui ui) throws DukeException { + Task newToDoTask = new ToDo(TaskType.TODO, super.getTaskDescription()); + taskList.add(newToDoTask); + + String response = ui.taskAddedMessage(newToDoTask) + + System.lineSeparator() + ui.getNumOfTasksInList(taskList); + ui.displayResponse(response); + } +} diff --git a/src/main/java/duke/command/Command.java b/src/main/java/duke/command/Command.java new file mode 100644 index 0000000000..99b7f178cb --- /dev/null +++ b/src/main/java/duke/command/Command.java @@ -0,0 +1,32 @@ +package duke.command; + +import duke.Storage; +import duke.TaskList; +import duke.Ui; + +/** + * An abstract class representing the command. + */ +public abstract class Command { + private String type; // Type of command + private boolean isExit; // If the user wants to exit + + public Command(String type) { + this.type = type; + this.isExit = false; + } + + public String getType() { + return type; + } + + public boolean isExit() { + return isExit; + } + + public void setExit() { + this.isExit = true; + } + + public abstract void execute(TaskList taskList, Ui ui, Storage storage); +} diff --git a/src/main/java/duke/command/DeleteCommand.java b/src/main/java/duke/command/DeleteCommand.java new file mode 100644 index 0000000000..7fc9ce055b --- /dev/null +++ b/src/main/java/duke/command/DeleteCommand.java @@ -0,0 +1,60 @@ +package duke.command; + +import duke.DukeException; +import duke.Storage; +import duke.TaskList; +import duke.Ui; +import duke.task.Task; + +import java.io.IOException; + +/** + * A class that contaisn methods to delete a task + */ +public class DeleteCommand extends Command { + private int taskNum; + + /** + * Initializes an instance of DeleteCommand class with task type and task number. + * @param type Task type + * @param taskNum Task number + */ + public DeleteCommand(String type, int taskNum) { + super(type); + this.taskNum = taskNum; + } + + /** + * Executes deleting the task from the task list, and updating the storage file. + * @param taskList The task list + * @param ui An object to handle i/o operations through screen + * @param storage An object to read from and write to storage file + */ + @Override + public void execute(TaskList taskList, Ui ui, Storage storage) { + try { + deleteTask(taskList, ui); + storage.saveTasksToFile(taskList); + } catch (DukeException | IOException e) { + ui.displayError(e.getMessage()); + } + } + + /** + * Deletes a task from the task list. + * @param taskList The task list + * @param ui An object to handle i/o operations through screen + * @throws DukeException If the task number is not valid + */ + public void deleteTask(TaskList taskList, Ui ui) throws DukeException { + if (taskNum > 0 && taskNum <= taskList.size()) { + Task taskDeleted = taskList.remove(taskNum - 1); + + String response = ui.taskDeletedMessage(taskDeleted) + + System.lineSeparator() + ui.getNumOfTasksInList(taskList); + ui.displayResponse(response); + } else { + throw new DukeException("Task not found. Please try again!"); + } + } +} \ No newline at end of file diff --git a/src/main/java/duke/command/DoneCommand.java b/src/main/java/duke/command/DoneCommand.java new file mode 100644 index 0000000000..7199e94375 --- /dev/null +++ b/src/main/java/duke/command/DoneCommand.java @@ -0,0 +1,60 @@ +package duke.command; + +import duke.DukeException; +import duke.Storage; +import duke.TaskList; +import duke.Ui; +import duke.task.Task; + +import java.io.IOException; + +/** + * A class that contains methods to handle Done command + */ +public class DoneCommand extends Command { + private int taskNum; + + /** + * Initializes an instanceof Done class with task type and task number. + * @param type Type of task + * @param taskNum Task number + */ + public DoneCommand(String type, int taskNum) { + super(type); + this.taskNum = taskNum; + } + + /** + * Executes the command of marking a task done, and updates the storage file. + * @param taskList The task list + * @param ui An object to handle i/o operations through screen + * @param storage An object to read from and write to storage file + */ + @Override + public void execute(TaskList taskList, Ui ui, Storage storage) { + try { + markDone(taskList, ui); + storage.saveTasksToFile(taskList); + } catch (DukeException | IOException e) { + ui.displayError(e.getMessage()); + } + } + + /** + * Marks the task as done. + * @param taskList The task list + * @param ui An object to handle i/o operations through screen + * @throws DukeException If the task number is not valid + */ + public void markDone(TaskList taskList, Ui ui) throws DukeException { + if (taskNum > 0 && taskNum <= taskList.size()) { + Task taskDone = taskList.get(taskNum - 1); + taskDone.setDone(); + + String response = ui.taskDoneMessage(taskDone); + ui.displayResponse(response); + } else { + throw new DukeException("Task not found. Please try again!"); + } + } +} diff --git a/src/main/java/duke/command/ExitCommand.java b/src/main/java/duke/command/ExitCommand.java new file mode 100644 index 0000000000..807a918c92 --- /dev/null +++ b/src/main/java/duke/command/ExitCommand.java @@ -0,0 +1,30 @@ +package duke.command; + +import duke.Storage; +import duke.TaskList; +import duke.Ui; + +/** + * A class to handle clean up operations on exiting the program + */ +public class ExitCommand extends Command { + /** + * Initializes an instance of ExitCommand class. + * @param type Type of command (Exit) + */ + public ExitCommand(String type) { + super(type); + } + + /** + * Executes clean up operations on exiting the program. + * @param taskList The task list + * @param ui An object to handle i/o operations through screen + * @param storage An object to read from and write to storage file + */ + @Override + public void execute(TaskList taskList, Ui ui, Storage storage) { + setExit(); + ui.exit(); + } +} diff --git a/src/main/java/duke/command/ListCommand.java b/src/main/java/duke/command/ListCommand.java new file mode 100644 index 0000000000..fdb93d7a1a --- /dev/null +++ b/src/main/java/duke/command/ListCommand.java @@ -0,0 +1,49 @@ +package duke.command; + +import duke.DukeException; +import duke.Storage; +import duke.TaskList; +import duke.Ui; + +/** + * A class to handle the command of listing the tasks + */ +public class ListCommand extends Command { + /** + * Initializes an instance of ListCommand class. + * @param type Type of task (List) + */ + public ListCommand(String type) { + super(type); + } + + /** + * Executes the command of listing the tasks. + * @param taskList The task list + * @param ui An object to handle i/o operations through screen + * @param storage An object to read from and write to the storage file + */ + @Override + public void execute(TaskList taskList, Ui ui, Storage storage) { + try { + displayTasksList(taskList, ui); + } catch (DukeException e) { + ui.displayError(e.getMessage()); + } + } + + /** + * Displays the tasks in proper format. + * @param taskList The task list + * @param ui An object to handle i/o operations through screen + * @throws DukeException If the task list is empty + */ + public void displayTasksList(TaskList taskList, Ui ui) throws DukeException { + if (taskList.size() != 0) { + String response = ui.getTasksInList(taskList); + ui.displayResponse(response); + } else { + throw new DukeException("There are no tasks in your list!"); + } + } +} diff --git a/src/main/java/duke/command/PrintCommand.java b/src/main/java/duke/command/PrintCommand.java new file mode 100644 index 0000000000..04bef46ca8 --- /dev/null +++ b/src/main/java/duke/command/PrintCommand.java @@ -0,0 +1,61 @@ +package duke.command; + +import duke.DukeException; +import duke.Storage; +import duke.TaskList; +import duke.Ui; + +/** + * A class to handle print command to print tasks corresponding to a given date. + */ +public class PrintCommand extends Command { + private String date; + + /** + * Initializes an instance of PrintCommand class. + * @param type Type of command + * @param date The specified date + */ + public PrintCommand(String type, String date) { + super(type); + this.date = date; + } + + /** + * Returns the specified date correspondign to which the tasks are to be printed + * @return The specified date + */ + public String getDate() { + return date; + } + + /** + * Executes the command of printing tasks corresponding to the given date. + * @param taskList The task list + * @param ui An object to handle i/o operations through screen + * @param storage An object to read from and write to the storage file + */ + @Override + public void execute(TaskList taskList, Ui ui, Storage storage) { + try { + printTasksOnDate(taskList, ui); + } catch (DukeException e) { + ui.displayError(e.getMessage()); + } + } + + /** + * Prints tasks corresponding to the given date. + * @param taskList The task list + * @param ui An object to handle i/o operations through screen + * @throws DukeException If no task on the given date is found + */ + public void printTasksOnDate(TaskList taskList, Ui ui) throws DukeException { + if (taskList.size() != 0) { + String response = ui.getTasksOnDate(date, taskList); + ui.displayResponse(response); + } else { + throw new DukeException("There are no tasks on this date!"); + } + } +} diff --git a/src/main/java/duke/task/Deadline.java b/src/main/java/duke/task/Deadline.java new file mode 100644 index 0000000000..6f5996e2bb --- /dev/null +++ b/src/main/java/duke/task/Deadline.java @@ -0,0 +1,47 @@ +package duke.task; + +/** + * A class to handle Deadline tasks + */ +public class Deadline extends TaskWithDateTime { + /** + * Initializes an instance of Deadline class with task type, task description, + * and the date/time by which the task has to be completed. + * @param type Type of task + * @param description Task description + * @param dateTimeInput Date/time by whuch the tas has to be completed + */ + public Deadline(TaskType type, String description, String dateTimeInput) { + super(type, description, dateTimeInput); + } + + /** + * Initializes an instance of Deadline class with task type, task description, + * date/time by which the task has to be completed and whether the task has been done. + * @param type Type of task + * @param description Task description + * @param dateTimeInput Date/time by whuch the tas has to be completed + * @param isDone A flag to indicate if the task has been done + */ + public Deadline(TaskType type, String description, String dateTimeInput, boolean isDone) { + super(type, description, dateTimeInput, isDone); + } + + /** + * Gets the date/time information by which the task is to be completed. + * @return Date/time information + */ + @Override + public String dateTimeInfo() { + return "(by: " + super.getDateTimeOutput() + ")"; + } + + /** + * Gets a string representation of the task. + * @return A string representation of the task + */ + @Override + public String toString() { + return "[" + TaskType.DEADLINE.getAbbr() + "] " + super.toString(); + } +} diff --git a/src/main/java/duke/task/Event.java b/src/main/java/duke/task/Event.java new file mode 100644 index 0000000000..1c92f5443c --- /dev/null +++ b/src/main/java/duke/task/Event.java @@ -0,0 +1,48 @@ +package duke.task; + +/** + * A class to handle Event tasks + */ +public class Event extends TaskWithDateTime { + /** + * Initializes an instance of Event class with task type, description, + * and the date/time at which the task is to be performed. + * @param type Type of task + * @param description Task description + * @param dateTimeInput Date/time at which the task is to be performed + */ + public Event(TaskType type, String description, String dateTimeInput) { + super(type, description, dateTimeInput); + } + + /** + * Initializes an instance of Event class with task type, description, + * date/time at which the task is to be performed and whether the task + * has been completed. + * @param type Type of task + * @param description Task description + * @param dateTimeInput Date/time at which the task is to be performed + * @param isDone A flag to indicate if the task has been completed + */ + public Event(TaskType type, String description, String dateTimeInput, boolean isDone) { + super(type, description, dateTimeInput, isDone); + } + + /** + * Gets date/time info of the task in output format. + * @return date/time info + */ + @Override + public String dateTimeInfo() { + return "(at: " + super.getDateTimeOutput() +")"; + } + + /** + * Gets a string representation of a task with date/time. + * @return A string representation of the task + */ + @Override + public String toString() { + return "[" + TaskType.EVENT.getAbbr() + "] " + super.toString(); + } +} diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java new file mode 100644 index 0000000000..2ebbd72f6b --- /dev/null +++ b/src/main/java/duke/task/Task.java @@ -0,0 +1,91 @@ +package duke.task; + +/** + * An abstract class that represents tasks + */ +public abstract class Task { + private TaskType type; + private String description; + private boolean isDone; + + /** + * Initializes an instance of Task class with task type and description. + * @param type Type of task + * @param description Task description + */ + public Task(TaskType type, String description) { + // By default, assume that the task has not been completed. + this(type, description, false); + } + + /** + * Initializes an instance of Task class with task type, description and + * a flag to indicate if the task has been completed. + * @param type Type of task + * @param description Task description + * @param isDone Flag to indicate if the task has been completed + */ + public Task(TaskType type, String description, boolean isDone) { + this.type = type; + this.description = description; + this.isDone = isDone; + } + + /** + * Gets the type of task. + * @return Type of task + */ + public TaskType getType() { + return type; + } + + /** + * Gets the task description. + * @return String containign the task description + */ + public String getDescription() { + return description; + } + + /** + * Gets a flag to indicate if the task has been completed. + * @return The boolean flag + */ + public boolean isDone() { + return isDone; + } + + /** + * Gets status icon for the task. + * @return The string representation of the status icon + */ + public String getStatusIcon() { + return (isDone ? "[✔]" : "[ ]"); // mark done task with ✔ + } + + /** + * Sets the isDone flag to true to indicate tat the task has been completed. + */ + public void setDone() { + this.isDone = true; + } + + /** + * Finds if the task is on a specified date. + * The function will be overridden in derived classes. + * @param dateStr The date by which the task is to be completed + * @return False because, by default, a task is not on a specified date + */ + public boolean isOnDate(String dateStr) { + return false; + } + + /** + * Gets a description of the task. + * @return A string containign description of the task + */ + @Override + public String toString() { + return getStatusIcon() + " " + description; + } +} diff --git a/src/main/java/duke/task/TaskType.java b/src/main/java/duke/task/TaskType.java new file mode 100644 index 0000000000..5d56a87583 --- /dev/null +++ b/src/main/java/duke/task/TaskType.java @@ -0,0 +1,39 @@ +package duke.task; + +/** + * An enumeration for different commands + */ +public enum TaskType { + TODO("todo", "T"), + DEADLINE("deadline", "D"), + EVENT("event", "E"); + + private final String label; + private final String abbr; + + /** + * Initializes an instance of TaskType enumeration. + * @param label Label of the enumeration (task type) + * @param abbr Abbreviation of the enumeration (task type) + */ + TaskType(String label, String abbr) { + this.label = label; + this.abbr = abbr; + } + + /** + * Gets the label of the task type. + * @return Label + */ + public String getLabel() { + return label; + } + + /** + * Gets the abbreviation of the task type. + * @return Abbreviation + */ + public String getAbbr() { + return abbr; + } +} diff --git a/src/main/java/duke/task/TaskWithDateTime.java b/src/main/java/duke/task/TaskWithDateTime.java new file mode 100644 index 0000000000..9910961244 --- /dev/null +++ b/src/main/java/duke/task/TaskWithDateTime.java @@ -0,0 +1,185 @@ +package duke.task; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +/** + * A class that represents tasks on a date/time + */ +public abstract class TaskWithDateTime extends Task { + private String dateTimeInput; + private String dateInput; + private String timeInput; + private LocalDate date; + private LocalTime time; + private String dateTimeOutput; // DateTime (of the task) to be printed + + /** + * Initializes an instance of TaskWithDateTime class with task type, description, and date/time. + * @param type Type of task + * @param description Task description + * @param dateTimeInput The input date/time by which the task has to be completed + */ + public TaskWithDateTime(TaskType type, String description, String dateTimeInput) { + this(type, description, dateTimeInput, false); + } + + /** + * Initializes an instance of TaskWithDateTime class with task type, description, + * date/time, and whether the task has been completed. + * @param type Type of task + * @param description Task description + * @param dateTimeInput The input date/time by which the task has to be completed + * @param isDone A flag to indicate if the task has been completed + */ + public TaskWithDateTime(TaskType type, String description, String dateTimeInput, boolean isDone) { + super(type, description, isDone); + this.dateTimeInput = dateTimeInput; + processDateTimeInput(); + } + + /** + * Processes the input date/time string to find the specific details of the + * date and time of the task. + */ + private void processDateTimeInput() { + boolean isTimeInputProper = true; + + String[] dateTimeInputParts = dateTimeInput.split("\\s+", 2); + + if (dateTimeInputParts.length == 2) { + dateInput = dateTimeInputParts[0].trim(); + timeInput = dateTimeInputParts[1].trim(); + + // Omit any additional whitespaces in between date and time inputs + dateTimeInput = dateInput + " " + timeInput; + } else { + dateInput = dateTimeInputParts[0].trim(); + timeInput = ""; + + // Omit any additional whitespaces that comes with date input + dateTimeInput = dateInput; + } + + // Process dateInput + try { + date = LocalDate.parse(dateInput); + } catch (Exception e) { + date = null; + } + + // Process timeInput + if (!timeInput.equals("")) { + try { + int timeInputInInt = Integer.parseInt(timeInput); + + if ((timeInputInInt < 0 || timeInputInInt > 2359)) { + isTimeInputProper = false; + time = null; + } else { + if (timeInput.length() != 4) { + isTimeInputProper = false; + time = null; + } else { + int hour = timeInputInInt / 100; + int min = timeInputInInt - (hour * 100); + + String timeInputInTimeFormat = ""; + + if (hour < 10) { + timeInputInTimeFormat += "0" + hour; + } else { + timeInputInTimeFormat += hour; + } + + if (min < 10) { + timeInputInTimeFormat += ":" + "0" + min; + } else { + timeInputInTimeFormat += ":" + min; + } + + DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_LOCAL_TIME; + time = LocalTime.parse(timeInputInTimeFormat, timeFormatter); + } + } + } catch (Exception e) { + time = null; + } + } else { + time = null; + } + + // Generate dateTimeOutput + dateTimeOutput = ""; + + if (date == null && time == null) { + dateTimeOutput = dateTimeInput; + } else { + if (date != null) { + dateTimeOutput += date.format(DateTimeFormatter.ofPattern("MMM d yyyy")); + } else { + dateTimeOutput += dateInput; + } + + if (time != null) { + dateTimeOutput += ", " + time.format(DateTimeFormatter.ofPattern("hh:mm a")); + } else { + if (!timeInput.equals("")) { + if (isTimeInputProper) { + dateTimeOutput += ", " + timeInput; + } else { + dateTimeOutput += ", " + timeInput + " [Note: Invalid time format]"; + } + } + } + } + } + + /** + * Gets input date/time string. + * @return Inout date/time string + */ + public String getDateTimeInput() { + return dateTimeInput; + } + + /** + * Gets the date/time information in output format. + * @return Output date/time string + */ + public String getDateTimeOutput() { + return dateTimeOutput; + } + + public abstract String dateTimeInfo(); + + /** + * Finds if the date/time of a task is equal to a specified date/time. + * @param dateStr The specified date/time + * @return A flag to indicate if the date/time of the task is same as the given value + */ + @Override + public boolean isOnDate(String dateStr) { + try { + LocalDate dateToSearch = LocalDate.parse(dateStr); + + if (date != null) { + return date.equals(dateToSearch); + } else { + return dateInput.equals(dateStr); + } + } catch (Exception e) { + return dateInput.equals(dateStr); + } + } + + /** + * Gets a string representation of the date/time info. + * @return A string representation of the date/time info + */ + @Override + public String toString() { + return super.toString() + " " + dateTimeInfo(); + } +} diff --git a/src/main/java/duke/task/ToDo.java b/src/main/java/duke/task/ToDo.java new file mode 100644 index 0000000000..e96ef2da92 --- /dev/null +++ b/src/main/java/duke/task/ToDo.java @@ -0,0 +1,35 @@ +package duke.task; + +/** + * A class that represents to do tasks + */ +public class ToDo extends Task { + /** + * Initializes an instance of ToDo class with task type and description. + * @param type Type of task + * @param description Task description + */ + public ToDo(TaskType type, String description) { + super(type, description); + } + + /** + * Initializes an instance of ToDo class with task type, description and + * whether the task has been completed. + * @param type Type of task + * @param description Task description + * @param isDone A flag to indicate if the task has been completed + */ + public ToDo(TaskType type, String description, boolean isDone) { + super(type, description, isDone); + } + + /** + * Gets a string representation of the ToDo task. + * @return A string representation of the ToDo task. + */ + @Override + public String toString() { + return "[" + TaskType.TODO.getAbbr() + "] " + super.toString(); + } +} diff --git a/src/test/java/duke/DukeTest.java b/src/test/java/duke/DukeTest.java new file mode 100644 index 0000000000..7e6f6756cb --- /dev/null +++ b/src/test/java/duke/DukeTest.java @@ -0,0 +1,4 @@ +package duke; + +public class DukeTest { +} diff --git a/src/test/java/task/DeadlineTest.java b/src/test/java/task/DeadlineTest.java new file mode 100644 index 0000000000..ee4c0556a8 --- /dev/null +++ b/src/test/java/task/DeadlineTest.java @@ -0,0 +1,19 @@ +package task; + +import duke.task.Deadline; +import duke.task.Task; +import duke.task.TaskType; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DeadlineTest { + @Test + public void toStringTest() { + Task deadlineOne = new Deadline(TaskType.DEADLINE,"CS2100 Lab 4", "2021-09-14"); + assertEquals("[D] [ ] CS2100 Lab 4 (by: Sep 14 2021)", deadlineOne.toString()); + + Task deadlineTwo = new Deadline(TaskType.DEADLINE,"CS2100 Assignment 1", "2021-09-15 1300"); + assertEquals("[D] [ ] CS2100 Assignment 1 (by: Sep 15 2021, 01:00 PM)", deadlineTwo.toString()); + } +} diff --git a/src/test/java/task/EventTest.java b/src/test/java/task/EventTest.java new file mode 100644 index 0000000000..302b73411e --- /dev/null +++ b/src/test/java/task/EventTest.java @@ -0,0 +1,16 @@ +package task; + +import duke.task.Event; +import duke.task.Task; +import duke.task.TaskType; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class EventTest { + @Test + public void toStringTest() { + Task event = new Event(TaskType.EVENT, "CS2103 tP Meeting", "2021-09-14 2100"); + assertEquals("[E] [ ] CS2103 tP Meeting (at: Sep 14 2021, 09:00 PM)", event.toString()); + } +} diff --git a/src/test/java/task/ToDoTest.java b/src/test/java/task/ToDoTest.java new file mode 100644 index 0000000000..7e8a9aba97 --- /dev/null +++ b/src/test/java/task/ToDoTest.java @@ -0,0 +1,16 @@ +package task; + +import duke.task.Task; +import duke.task.TaskType; +import duke.task.ToDo; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ToDoTest { + @Test + public void toStringTest() { + Task toDo = new ToDo(TaskType.TODO,"Vacuum room floor"); + assertEquals("[T] [ ] Vacuum room floor", toDo.toString()); + } +} diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 657e74f6e7..d95ef9dca2 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,7 +1,88 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| - + ____________________________________________________________ + Hello! I'm Duke + What can I do for you? + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Got it. I've added this task: + [T][ ] read book + Now you have 1 task in the list. + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Nice! I've marked this task as done: + [T][X] read book + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Got it. I've added this task: + [D][ ] return book (by: June 6th) + Now you have 2 tasks in the list. + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Got it. I've added this task: + [E][ ] project meeting (at: Aug 6th 2-4pm) + Now you have 3 tasks in the list. + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Got it. I've added this task: + [T][ ] join sports club + Now you have 4 tasks in the list. + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Here are the tasks in your list: + 1. [T][X] read book + 2. [D][ ] return book (by: June 6th) + 3. [E][ ] project meeting (at: Aug 6th 2-4pm) + 4. [T][ ] join sports club + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Nice! I've marked this task as done: + [T][X] join sports club + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Got it. I've added this task: + [T][ ] borrow book + Now you have 5 tasks in the list. + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Here are the tasks in your list: + 1. [T][X] read book + 2. [D][ ] return book (by: June 6th) + 3. [E][ ] project meeting (at: Aug 6th 2-4pm) + 4. [T][X] join sports club + 5. [T][ ] borrow book + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Got it. I've added this task: + [D][ ] return book (by: Sunday) + Now you have 6 tasks in the list. + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Got it. I've added this task: + [E][ ] project meeting (at: Mon 2-4pm) + Now you have 7 tasks in the list. + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Here are the tasks in your list: + 1. [T][X] read book + 2. [D][ ] return book (by: June 6th) + 3. [E][ ] project meeting (at: Aug 6th 2-4pm) + 4. [T][X] join sports club + 5. [T][ ] borrow book + 6. [D][ ] return book (by: Sunday) + 7. [E][ ] project meeting (at: Mon 2-4pm) + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Bye. Hope to see you again soon! + ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e69de29bb2..0e3b9235b0 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -0,0 +1,13 @@ +todo read book +done 1 +deadline return book /by June 6th +event project meeting /at Aug 6th 2-4pm +todo join sports club +list +done 4 +todo borrow book +list +deadline return book /by Sunday +event project meeting /at Mon 2-4pm +list +bye \ No newline at end of file