From 6b1b712cc3b3834c224a77fe33313f9f721ca47c Mon Sep 17 00:00:00 2001 From: cheesengg Date: Mon, 9 Sep 2019 16:47:00 +0800 Subject: [PATCH 001/228] Team repo set-up --- src/main/java/Duke.java | 94 +++++++++- src/main/java/Duke/Commands/AddCommand.java | 72 ++++++++ src/main/java/Duke/Commands/ByeCommand.java | 31 ++++ src/main/java/Duke/Commands/Command.java | 24 +++ .../java/Duke/Commands/DeleteCommand.java | 40 +++++ src/main/java/Duke/Commands/DoneCommand.java | 45 +++++ src/main/java/Duke/Commands/FindCommand.java | 46 +++++ src/main/java/Duke/Commands/ListCommand.java | 34 ++++ .../java/Duke/Constant/Duke_Response.java | 35 ++++ src/main/java/Duke/DateFormatter.java | 165 ++++++++++++++++++ .../java/Duke/Exception/DukeException.java | 7 + src/main/java/Duke/Parser/Parser.java | 102 +++++++++++ src/main/java/Duke/Storage.java | 90 ++++++++++ src/main/java/Duke/Task/Deadline.java | 43 +++++ src/main/java/Duke/Task/Event.java | 43 +++++ src/main/java/Duke/Task/Task.java | 54 ++++++ src/main/java/Duke/Task/TaskList.java | 64 +++++++ src/main/java/Duke/Task/Todo.java | 41 +++++ src/main/java/Duke/Ui.java | 59 +++++++ src/main/java/Launcher.fxml | 19 ++ src/main/java/Launcher.java | 110 ++++++++++++ 21 files changed, 1210 insertions(+), 8 deletions(-) create mode 100644 src/main/java/Duke/Commands/AddCommand.java create mode 100644 src/main/java/Duke/Commands/ByeCommand.java create mode 100644 src/main/java/Duke/Commands/Command.java create mode 100644 src/main/java/Duke/Commands/DeleteCommand.java create mode 100644 src/main/java/Duke/Commands/DoneCommand.java create mode 100644 src/main/java/Duke/Commands/FindCommand.java create mode 100644 src/main/java/Duke/Commands/ListCommand.java create mode 100644 src/main/java/Duke/Constant/Duke_Response.java create mode 100644 src/main/java/Duke/DateFormatter.java create mode 100644 src/main/java/Duke/Exception/DukeException.java create mode 100644 src/main/java/Duke/Parser/Parser.java create mode 100644 src/main/java/Duke/Storage.java create mode 100644 src/main/java/Duke/Task/Deadline.java create mode 100644 src/main/java/Duke/Task/Event.java create mode 100644 src/main/java/Duke/Task/Task.java create mode 100644 src/main/java/Duke/Task/TaskList.java create mode 100644 src/main/java/Duke/Task/Todo.java create mode 100644 src/main/java/Duke/Ui.java create mode 100644 src/main/java/Launcher.fxml create mode 100644 src/main/java/Launcher.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 5d313334cc..67e685c6be 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,10 +1,88 @@ -public class Duke { +import Duke.Commands.Command; +import Duke.Exception.DukeException; +import Duke.Parser.Parser; +import Duke.Task.TaskList; +import Duke.Storage; +import Duke.Ui; + +import java.io.File; +import java.util.Scanner; +/** + *

Duke

+ * The Duke program implements a Task Manager for users to + * keep track of the tasks that they have to complete or attend to. + * + * @author Brian Lim + * @version 1.0 + * @since 2019-09-07 + */ +public class Duke{ + + + /** + * Stores and keeps track of all user's task. + */ + public TaskList tasks; + + /** + * User Interface that handles the response of Duke. + */ + public Ui ui; + + /** + * Stores filepath for Duke to write to and load from. + */ + public Storage storage; + + + public Duke(File filePath){ + ui = new Ui(); + storage = new Storage(filePath); + tasks = storage.load(); + } + + /** + * This is the main method which makes use of run method. + * A specific filepath is called in order to load previously stored + * tasks into the TaskList param when initiating the program. + *

+ * If the file is loaded successfully, all tasks that was stored previously + * before program exits is loaded into TaskList, else it will be empty. + *

+ * @param args Unused. + */ public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); + File currentDir = new File(System.getProperty("user.dir")); + File filePath = new File(currentDir.toString() + "\\src\\main\\data\\duke.txt"); + new Duke(filePath).run(); + } + + /** + * This method is used to start up the Duke program. + * The program will keep running till the user inputs the command + * 'Bye' and exits the while loop. + */ + public void run() { + boolean isExit = false; + Scanner sc = new Scanner(System.in); + ui.showWelcome(); + + while (!isExit) { + try { + String fullCommand = ui.readCommand(sc); + Command c = Parser.parse(fullCommand); + c.execute(tasks, ui, storage); + isExit = c.isExit(); + } catch (DukeException e) { + ui.setMessage(e.getMessage()); + } catch (NumberFormatException e){ + ui.setMessage(" Invalid Command\n"); + } finally { + System.out.println(ui.showLine()); + } + } + sc.close(); } -} + + +} \ No newline at end of file diff --git a/src/main/java/Duke/Commands/AddCommand.java b/src/main/java/Duke/Commands/AddCommand.java new file mode 100644 index 0000000000..eddb6938c1 --- /dev/null +++ b/src/main/java/Duke/Commands/AddCommand.java @@ -0,0 +1,72 @@ +package Duke.Commands; + +import Duke.Constant.Duke_Response; +import Duke.Storage; +import Duke.Task.*; +import Duke.Ui; +import Duke.DateFormatter; + + +public class AddCommand extends Command { + private String taskType; + private String description; + private String dateTime; + + /** + * Creates an AddCommand with the specified taskType and + * description. Used for Todo task. + * @param taskType The task type to be added + * @param description The description of task + */ + public AddCommand(String taskType, String description){ + this.taskType = taskType; + this.description = description; + this.dateTime = ""; + } + + /** + * Creates an AddCommand with the specified taskType, + * description and dateTime. Used for Deadline and Event tasks + * @param taskType The task type to be added + * @param description The description of task + * @param dateTime The date and time of task to either be completed or attend to + */ + public AddCommand(String taskType, String description, String dateTime){ + this.taskType = taskType; + this.description = description; + this.dateTime = dateTime; + } + + /** + * Append a new task to the TaskList. Sets message of Ui + * based on the task that has been added. + * @param tasks The list of task stored by Duke + * @param ui The user interface that handles messages + * @param storage The database to read files and write txt files + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) { + Task task; + DateFormatter dateFormatter = new DateFormatter(dateTime); + switch (taskType.toLowerCase()){ + case "todo": + task = new Todo(description); + tasks.add(task); + ui.setMessage(new Duke_Response().ADD + " " + task.toString() + + "\n Now you have " + tasks.size() + " tasks in your list.\n"); + break; + case "event": + task = new Event(description, dateFormatter.getDateTime()); + tasks.add(task); + ui.setMessage(new Duke_Response().ADD + " " + task.toString() + + "\n Now you have " + tasks.size() + " tasks in your list.\n"); + break; + case "deadline": + task = new Deadline(description, dateFormatter.getDateTime()); + tasks.add(task); + ui.setMessage(new Duke_Response().ADD + " " + task.toString() + + "\n Now you have " + tasks.size() + " tasks in your list.\n"); + break; + } + } +} diff --git a/src/main/java/Duke/Commands/ByeCommand.java b/src/main/java/Duke/Commands/ByeCommand.java new file mode 100644 index 0000000000..753e99a5a7 --- /dev/null +++ b/src/main/java/Duke/Commands/ByeCommand.java @@ -0,0 +1,31 @@ +package Duke.Commands; + +import Duke.Constant.Duke_Response; +import Duke.Storage; +import Duke.Task.TaskList; +import Duke.Ui; + +public class ByeCommand extends Command{ + + /** + * Write all the tasks in TaskList into the file in Storage Class. + * Sets message of Ui to show that it is shutting down. + * @param tasks The arraylist of task stored by Duke + * @param ui The user interface that handles messages + * @param storage The database to read files and write txt files + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) { + storage.write(tasks); + ui.setMessage(new Duke_Response().BYE); + } + + /** + * Exits Duke program + * @return Sets Boolean expression to true + */ + @Override + public boolean isExit() { + return true; + } +} diff --git a/src/main/java/Duke/Commands/Command.java b/src/main/java/Duke/Commands/Command.java new file mode 100644 index 0000000000..9735f4b4fd --- /dev/null +++ b/src/main/java/Duke/Commands/Command.java @@ -0,0 +1,24 @@ +package Duke.Commands; + +import Duke.Storage; +import Duke.Task.TaskList; +import Duke.Ui; + +public abstract class Command { + protected boolean quit; + + /** + * @param tasks The list of task stored by Duke + * @param ui The user interface that handles messages + * @param storage The database to read files and write txt files + */ + public abstract void execute(TaskList tasks, Ui ui, Storage storage); + + /** + * Duke continues to run. + * @return Sets boolean expression to false. + */ + public boolean isExit(){ + return false; + } +} diff --git a/src/main/java/Duke/Commands/DeleteCommand.java b/src/main/java/Duke/Commands/DeleteCommand.java new file mode 100644 index 0000000000..3f12dea304 --- /dev/null +++ b/src/main/java/Duke/Commands/DeleteCommand.java @@ -0,0 +1,40 @@ +package Duke.Commands; + +import Duke.Constant.Duke_Response; +import Duke.Storage; +import Duke.Task.Task; +import Duke.Task.TaskList; +import Duke.Ui; + +public class DeleteCommand extends Command{ + private int index; + + /** + * Creates DeleteCommand with the specified index + * to be deleted. Index starts from 1. + * @param index Index of task to be deleted. + */ + public DeleteCommand(int index){ + this.index = index; + } + + /** + * Deletes the task specified by user. Sets message of Ui + * to show if command is successfully carried out. + * @param tasks The list of task stored by Duke + * @param ui The user interface that handles messages + * @param storage The database to read files and write txt files + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) { + String message; + if(tasks.size() >= index) { + Task task = tasks.deleteTask(index); + message = new Duke_Response().DELETE_FOUND + " " + task.toString() + "\n"; + } else{ + message = new Duke_Response().NOT_FOUND; + } + + ui.setMessage(message); + } +} diff --git a/src/main/java/Duke/Commands/DoneCommand.java b/src/main/java/Duke/Commands/DoneCommand.java new file mode 100644 index 0000000000..bd3bc44626 --- /dev/null +++ b/src/main/java/Duke/Commands/DoneCommand.java @@ -0,0 +1,45 @@ +package Duke.Commands; + +import Duke.Constant.Duke_Response; +import Duke.Storage; +import Duke.Task.Task; +import Duke.Task.TaskList; +import Duke.Ui; + +public class DoneCommand extends Command{ + private int index; + + /** + * Creates a DoneCommand with the specified index + * to be mark as done. Index starts from 1. + * @param index Index of task to be mark as done. + */ + public DoneCommand(int index){ + this.index = index; + } + + /** + * Marks the task specified by user as done. Sets message of Ui + * to show if Command is successfully carried out. + * @param tasks The list of task stored by Duke + * @param ui The user interface that handles messages + * @param storage The database to read files and write txt files + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) { + String message; + + if(tasks.size() >= index){ + if(!tasks.isCompletedTask(index)) { + Task task = tasks.doneTask(index); + message = new Duke_Response().DONE_FOUND + " " + task.toString() + "\n"; + } else { + message = new Duke_Response().DONE_COMPLETED; + } + } else { + message = new Duke_Response().NOT_FOUND; + } + + ui.setMessage(message); + } +} diff --git a/src/main/java/Duke/Commands/FindCommand.java b/src/main/java/Duke/Commands/FindCommand.java new file mode 100644 index 0000000000..9cde11316d --- /dev/null +++ b/src/main/java/Duke/Commands/FindCommand.java @@ -0,0 +1,46 @@ +package Duke.Commands; + +import Duke.Constant.Duke_Response; +import Duke.Storage; +import Duke.Task.Task; +import Duke.Task.TaskList; +import Duke.Ui; + +import java.util.ArrayList; + +public class FindCommand extends Command{ + private String item; + + /** + * Creates FindCommand with the specified item to be queried. + * @param item String input specified by user to be queried. + */ + public FindCommand(String item){ + this.item = item; + } + + /** + * Finds all the tasks that contains the item String. Sets message + * of Ui to show if query was successful. + * @param tasks The list of task stored by Duke + * @param ui The user interface that handles messages + * @param storage The database to read files and write txt files + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) { + ArrayList foundTask = tasks.findTask(item); + String message; + + if(foundTask.isEmpty()){ + message = new Duke_Response().NOT_FOUND; + } else { + message = new Duke_Response().FIND_FOUND; + int counter = 1; + for(Task i : foundTask){ + message += " " + counter + "." + i.toString(); + counter++; + } + } + ui.setMessage(message); + } +} diff --git a/src/main/java/Duke/Commands/ListCommand.java b/src/main/java/Duke/Commands/ListCommand.java new file mode 100644 index 0000000000..01d7d086ef --- /dev/null +++ b/src/main/java/Duke/Commands/ListCommand.java @@ -0,0 +1,34 @@ +package Duke.Commands; + +import Duke.Constant.Duke_Response; +import Duke.Storage; +import Duke.Task.Task; +import Duke.Task.TaskList; +import Duke.Ui; + +public class ListCommand extends Command{ + + /** + * Lists all the tasks stored in Duke. Sets message of Ui + * to show all the tasks stored. Tasks are numbered starting from + * index 1. + * @param tasks The list of task stored by Duke + * @param ui The user interface that handles messages + * @param storage The database to read files and write txt files + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) { + String message; + if(tasks.isEmpty()) { + message = new Duke_Response().LIST_NOT_FOUND; + } else{ + message = new Duke_Response().LIST_FOUND; + int counter = 1; + for (Task i : tasks) { + message += " " + counter + "." + i.toString(); + counter++; + } + } + ui.setMessage(message); + } +} diff --git a/src/main/java/Duke/Constant/Duke_Response.java b/src/main/java/Duke/Constant/Duke_Response.java new file mode 100644 index 0000000000..9639d9ce7d --- /dev/null +++ b/src/main/java/Duke/Constant/Duke_Response.java @@ -0,0 +1,35 @@ +package Duke.Constant; + +public class Duke_Response { + + public final String LOGO = "Hello from\n" + + " ____ _ \n" + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; + + public final String SPACES = " __________________________________\n"; + + public final String GREET = " Hello! I'm Duke\n What can I do for you?\n"; + + public final String BYE = " Bye. Hope to see you again soon!\n"; + + public final String LIST_FOUND = " Here are the tasks in your list:\n"; + + public final String LIST_NOT_FOUND = " ☹ OOPS!!! Your List is currently empty.\n"; + + public final String DONE_FOUND = " Nice! I've marked this task as done:\n"; + + public final String DONE_COMPLETED = " ☹ OOPS!!! This task has already been completed\n"; + + public final String DELETE_FOUND = " Noted. I've removed this task:\n"; + + public final String FIND_FOUND = " Here are the matching tasks in your list:\n"; + + public final String NOT_FOUND = " ☹ OOPS!!! The task cannot be found. \n"; + + public final String EXCEPTION = " ☹ OOPS!!! That is an invalid input\n Please try again. \n"; + + public final String ADD = " Got it. I've added this task:\n"; +} diff --git a/src/main/java/Duke/DateFormatter.java b/src/main/java/Duke/DateFormatter.java new file mode 100644 index 0000000000..a63d78bed5 --- /dev/null +++ b/src/main/java/Duke/DateFormatter.java @@ -0,0 +1,165 @@ +package Duke; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +public class DateFormatter { + private String date; + private String time; + private final DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); + /** + * + * @param message the deadline or event time to be processed to give date and time params + */ + public DateFormatter(String message){ + String[] splitStr = message.split(" "); + if(splitStr.length == 2) { + date = formatDate(splitStr[0]); + time = formatTime(splitStr[1]); + } + + if(date == null || time == null){ + date = message; + time = null; + } + } + + + private String formatDate(String date){ + String[] splitDate = date.split("/"); + if(splitDate.length == 3) { + String day = dayFormat(splitDate[0]); + String month = monthFormat(splitDate[1]); + String year = splitDate[2]; + if (month == null || day == null || !isValidDate(splitDate[0], splitDate[1], splitDate[2])) + return null; + + return day + month + year + ", "; + } else { + return null; + } + } + + /** + * + * @param day the date to be appended with necessary suffix + * @return String of the day with its suffix + */ + private String dayFormat(String day){ + if(day.equals("1") || day.equals("21") || day.equals("31")){ + day = day + "st of "; + } else if(day.equals("2") || day.equals("22")){ + return day + "nd of "; + } else if(day.equals("3") || day.equals("23")){ + return day + "rd of "; + } else if (Integer.parseInt(day) > 31){ + return null; + } + + return day + "th of "; + } + + /** + * + * @param month the month to be converted + * @return the String format of month + */ + private String monthFormat(String month){ + switch (month){ + case "1": + return "January "; + case "2": + return"February "; + case "3": + return "March "; + case "4": + return "April "; + case "5": + return "May "; + case "6": + return "June "; + case "7": + return "July "; + case "8": + return "August "; + case "9": + return "September "; + case "10": + return "October "; + case "11": + return "November "; + case "12": + return "December "; + default: + return null; + } + } + + /** + * + * @param day to be converted to int to check if day is in range for a particular month + * @param month for reference to check day is in range for the month + * @param year to check for leap year exceptions + * @return {@code true} date can be found in the calendar + * {@code false} otherwise + */ + private boolean isValidDate(String day, String month, String year){ + int yr = Integer.parseInt(year); + int mth = Integer.parseInt(month); + int dy = Integer.parseInt(day); + + if(mth == 2){ + return (isLeap(yr) && dy <= 29) || (!isLeap(yr) && dy <= 28); + } else if(mth == 4|| mth == 6|| mth == 9 || mth == 11){ + return dy <= 30; + } else { + return dy <= 31; + } + } + + /** + * + * @param year to check whether its a leap year + * @return {@code true} if it is a leap year + * {@code false} otherwise + */ + private boolean isLeap(int year){ + return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0); + } + + /** + * + * @param time 24-Hour clock + * @return String of 12-Hour clock with correct suffix + */ + private String formatTime(String time){ + String hour = time.substring(0,2); + String min = time.substring(2,4); + String suffix = (Integer.parseInt(hour) < 12) ? "am" : "pm"; + + if(Integer.parseInt(hour) > 23 || Integer.parseInt(min) > 59) + return null; + + if(Integer.parseInt(hour) == 0) + hour = "12"; + else if(Integer.parseInt(hour) > 12) + hour = Integer.toString(Integer.parseInt(hour) - 12); + + if(min.equals("00")) + return hour + suffix; + else + return hour + "." + min + suffix; + } + + public String getDateTime(){ + if(this.time == null){ + return this.date; + } + + return this.date + this.time; + } + + public boolean isValidDateTime() { + return date != null && time != null; + } +} diff --git a/src/main/java/Duke/Exception/DukeException.java b/src/main/java/Duke/Exception/DukeException.java new file mode 100644 index 0000000000..1890d40474 --- /dev/null +++ b/src/main/java/Duke/Exception/DukeException.java @@ -0,0 +1,7 @@ +package Duke.Exception; + +public class DukeException extends Exception{ + public DukeException(String message){ + super(message); + } +} \ No newline at end of file diff --git a/src/main/java/Duke/Parser/Parser.java b/src/main/java/Duke/Parser/Parser.java new file mode 100644 index 0000000000..0327179043 --- /dev/null +++ b/src/main/java/Duke/Parser/Parser.java @@ -0,0 +1,102 @@ +package Duke.Parser; + +import Duke.Commands.*; +import Duke.Exception.DukeException; + +public class Parser { + + /** + * Parse the date and return AddCommand class for Event task type + * @param taskType The type of Task + * @param command Command to be parse to description and dateTime + * @return AddCommand for Event task type + */ + private static Command parseEvent(String taskType, String command) throws DukeException{ + String[] splitStr = command.split("/at ", 2); + if(splitStr.length == 1) throw new DukeException(" Invalid Command\n"); + + + + return new AddCommand(taskType, splitStr[0], splitStr[1]); + } + + /** + * Parse the date and return AddCommand class for Deadline task type + * @param taskType The type of Task + * @param command Command to be parse to description and dateTime + * @return AddCommand for Deadline task type + */ + private static Command parseDeadline(String taskType, String command) throws DukeException{ + String[] splitStr = command.split("/by ", 2); + if(splitStr.length == 1) throw new DukeException(" Invalid Command\n"); + + return new AddCommand(taskType, splitStr[0], splitStr[1]); + } + + /** + * Mark the task indicated by user to be done + * @param command The taskNo to be converted to an integer + * @return DoneCommand with the index of item to be mark as done + * @throws NumberFormatException if command has characters + */ + private static Command parseDone(String command) throws NumberFormatException{ + int index = Integer.parseInt(command); + + return new DoneCommand(index); + } + + /** + * Delete the task indicated by user + * @param command The taskNo to be converted to an integer + * @return DeleteCommand with the index of item to be deleted + * @throws NumberFormatException if command has characters. + */ + private static Command parseDelete(String command) throws NumberFormatException{ + int index = Integer.parseInt(command); + + return new DeleteCommand(index); + } + + /** + * Return the correct command given by user, Class method + * @param fullCommand Command input by user to be parse + * @return The correct Command class as defined by first word + * @throws NumberFormatException if command has characters. + * @throws DukeException if the command is invalid or there are missing parameters. + */ + public static Command parse(String fullCommand) throws NumberFormatException, DukeException{ + String[] splitStr = fullCommand.split(" ", 2); + + switch(splitStr.length) { + case 1: + switch (splitStr[0].toLowerCase()) { + case "list": + return new ListCommand(); + case "bye": + return new ByeCommand(); + default: + throw new DukeException(" Invalid Command\n"); + } + case 2: + if(!splitStr[1].isEmpty()) { + switch (splitStr[0].toLowerCase()) { + case "todo": + return new AddCommand(splitStr[0], splitStr[1]); + case "deadline": + return parseDeadline(splitStr[0], splitStr[1]); + case "event": + return parseEvent(splitStr[0], splitStr[1]); + case "find": + return new FindCommand(splitStr[1]); + case "done": + return parseDone(splitStr[1]); + case "delete": + return parseDelete(splitStr[1]); + default: + throw new DukeException(" Invalid Command\n"); + } + } + } + throw new DukeException(" Invalid Command\n"); + } +} diff --git a/src/main/java/Duke/Storage.java b/src/main/java/Duke/Storage.java new file mode 100644 index 0000000000..4587b5279d --- /dev/null +++ b/src/main/java/Duke/Storage.java @@ -0,0 +1,90 @@ +package Duke; + +import Duke.Task.*; + +import java.io.*; + +public class Storage { + private File filePath; + + /** + * Constructor for Storage Class + * Create directory and file in the event that it does not exist + * @param filePath File, the path of the duke.txt File + */ + public Storage(File filePath){ + this.filePath = filePath; + try { + if(!filePath.getParentFile().exists()) + filePath.getParentFile().mkdirs(); + if(!filePath.exists()) + filePath.createNewFile(); + } catch (IOException e){ + System.out.println("Unable to create file.\n"); + } + } + + /** + * Read all the tasks that are stored in the file. Loads and restore + * progress of Duke. + * @return TaskList with all the tasks that were stored in file. + */ + public TaskList load(){ + TaskList tasks = new TaskList(); + try { + FileReader rd = new FileReader(filePath); + BufferedReader br = new BufferedReader(rd); + + String message; + int counter = 0; + + while((message = br.readLine()) != null){ + String[] arrStr = message.split(" \\| "); + + if(arrStr.length == 3){ + tasks.add(new Todo(arrStr[2])); + } else if (arrStr[0].equals("D")){ + tasks.add(new Deadline(arrStr[2], arrStr[3])); + } else { + tasks.add(new Event(arrStr[2], arrStr[3])); + } + + if(arrStr[1].equals("1")){ + tasks.get(counter).markAsDone(); + } + + counter++; + } + + br.close(); + rd.close(); + + } catch (IOException e){ + System.out.println("Unable to load file.\n"); + } + + return tasks; + } + + /** + * Deletes old file and creates new file with the same filepath. + * Writes all the tasks that has been stored in TaskList to the new file + * for Duke. + * @param tasks The list of Task that is stored by Duke + */ + public void write(TaskList tasks){ + + try { + filePath.delete(); + filePath.createNewFile(); + FileWriter wr = new FileWriter(filePath, true); + + for(Task i : tasks){ + wr.write(i.writeToFile() + "\n"); + } + wr.close(); + } catch (IOException e){ + System.out.println(" BYE, sorry you suck."); + } + } +} diff --git a/src/main/java/Duke/Task/Deadline.java b/src/main/java/Duke/Task/Deadline.java new file mode 100644 index 0000000000..bfa72b3fb5 --- /dev/null +++ b/src/main/java/Duke/Task/Deadline.java @@ -0,0 +1,43 @@ +package Duke.Task; + +public class Deadline extends Task{ + public final String SYMBOL = "[D]"; + protected String by; + + /** + * Constructor for Deadline Task + * @param description The deadline's task name + * @param by The dateTime of the deadline + */ + public Deadline(String description, String by){ + super(description); + this.by = by; + } + + /** + * @return the expected format of String message for this task + */ + @Override + public String toString() { + return SYMBOL + super.toString() + " (by: " + this.by + ")\n"; + } + + /** + * Used when using storage.write + * For reference to store the correct task type for each task + * @return The Symbol to reference to their task type + */ + @Override + public String getSymbol() { + return this.SYMBOL; + } + + /** + * The String format to be written into the duke.txt File for each task + * @return String format for task to be written into the duke.txt File + */ + @Override + public String writeToFile() { + return String.format("D | %d | %s | %s", (isCompleted() ? 1 : 0), this.getDescription(), this.by); + } +} diff --git a/src/main/java/Duke/Task/Event.java b/src/main/java/Duke/Task/Event.java new file mode 100644 index 0000000000..e1cf66c438 --- /dev/null +++ b/src/main/java/Duke/Task/Event.java @@ -0,0 +1,43 @@ +package Duke.Task; + +public class Event extends Task { + public final String SYMBOL = "[E]"; + protected String at; + + /** + * Constructor for Event task + * @param description The event name + * @param date The dateTime of the event + */ + public Event(String description, String date){ + super(description); + this.at = date; + } + + /** + * @return return the expected format of String message for this task + */ + @Override + public String toString() { + return this.SYMBOL + super.toString() + " (at: " + this.at + ")\n"; + } + + /** + * Used when using storage.write + * For reference to store the correct task type for each task + * @return The Symbol to reference to their task type + */ + @Override + public String getSymbol() { + return this.SYMBOL; + } + + /** + * The String format to be written into the duke.txt File for each task + * @return String format for task to be written into the duke.txt File + */ + @Override + public String writeToFile() { + return String.format("E | %d | %s | %s", (isCompleted() ? 1 : 0), this.getDescription(), this.at); + } +} diff --git a/src/main/java/Duke/Task/Task.java b/src/main/java/Duke/Task/Task.java new file mode 100644 index 0000000000..54e5242d88 --- /dev/null +++ b/src/main/java/Duke/Task/Task.java @@ -0,0 +1,54 @@ +package Duke.Task; + +public abstract class Task { + private String description; + private boolean isCompleted = false; + + public Task(String description) { + this.description = description; + } + + /** + * To make task as done + */ + public void markAsDone() { + isCompleted = true; + } + + /** + * To check if task is done + * @return {@code true} Task is completed + * {@code false} Task is incomplete + */ + public boolean isCompleted() { + return isCompleted; + } + + /** + * Get the task description + * @return String of the task description + */ + public String getDescription(){ + return description; + } + + /** + * Get the corresponding Icon according to whether task is completed + * @return If task is complete get TICK, If task is incomplete get CROSS + */ + private String getStatusIcon(){ + return (isCompleted ? "\u2713" : "\u2718"); + } + + /** + * @return the expected format of String message for this task + */ + public String toString(){ + return "[" + getStatusIcon() + "] " + this.description; + } + + + public abstract String getSymbol(); + + public abstract String writeToFile(); +} diff --git a/src/main/java/Duke/Task/TaskList.java b/src/main/java/Duke/Task/TaskList.java new file mode 100644 index 0000000000..a8aed80345 --- /dev/null +++ b/src/main/java/Duke/Task/TaskList.java @@ -0,0 +1,64 @@ +package Duke.Task; + +import java.util.ArrayList; + +public class TaskList extends ArrayList { + + /** + * Get the task for index based on 1 + * @param index the index of task to be queried, index starts from 1 + * @return The task with index starting from 0 + */ + private Task getTask(int index){ + return this.get(index - 1); + } + + /** + * Delete Task based on user input + * @param index the index of task to be deleted, index starts from 1 + * @return The task that is deleted + */ + public Task deleteTask(int index){ + + return this.remove(index-1); + } + + /** + * + * @param index The index of task to check if it is already completed, index starts from 1 + * @return {@code true} The task has been marked as completed + * {@code false} The task has not been mark as completed + */ + public boolean isCompletedTask(int index){ + return getTask(index).isCompleted(); + } + + /** + * Set Task as done based on user input + * @param index the index of task to be set as done, index starts from 1 + * @return The task that is completed and set as done + */ + public Task doneTask(int index){ + Task refTask = this.getTask(index); + refTask.markAsDone(); + + return refTask; + } + + /** + * Finds all the task that contains the String and append task to new arraylist + * @param item String that contains the item user wants to find + * @return New ArrayList with task that contains the String user input + */ + public ArrayList findTask(String item){ + ArrayList foundTask = new ArrayList<>(); + for(Task i : this){ + if(i.getDescription().contains(item)) + foundTask.add(i); + } + + return foundTask; + } + + +} diff --git a/src/main/java/Duke/Task/Todo.java b/src/main/java/Duke/Task/Todo.java new file mode 100644 index 0000000000..eb8c7f4e8b --- /dev/null +++ b/src/main/java/Duke/Task/Todo.java @@ -0,0 +1,41 @@ +package Duke.Task; + +public class +Todo extends Task { + public final String SYMBOL = "[T]"; + + /** + * Constructor for Todo task + * @param description The deadline's task name + */ + public Todo(String description){ + super(description); + } + + /** + * @return the expected format of String message for this task + */ + @Override + public String toString() { + return SYMBOL + super.toString() + "\n"; + } + + /** + * Used when using storage.write + * For reference to store the correct task type for each task + * @return The Symbol to reference to their task type + */ + @Override + public String getSymbol() { + return this.SYMBOL; + } + + /** + * The String format to be written into the duke.txt File for each task + * @return String format for task to be written into the duke.txt File + */ + @Override + public String writeToFile() { + return String.format("T | %d | %s", (isCompleted() ? 1 : 0), this.getDescription()); + } +} diff --git a/src/main/java/Duke/Ui.java b/src/main/java/Duke/Ui.java new file mode 100644 index 0000000000..d9cdb2d395 --- /dev/null +++ b/src/main/java/Duke/Ui.java @@ -0,0 +1,59 @@ +package Duke; + +import Duke.Constant.Duke_Response; + +import java.util.Scanner; + +/** + * Reads in the command input by user amd + * returns the response by the Duke program. + * + */ +public class Ui { + + /** + * Stores the appropriate response based on users input command. + * Once user command is processed, Duke's response is stored using + * setMessage method to store the appropriate message. Use + * by showLine method to print out the response. + */ + private String message; + + /** + * A variable to access Duke_Response Class for all Duke's response related + * constants. + */ + private Duke_Response dr = new Duke_Response(); + + + /** + * Read in the command by user. + * @return String input by user. + */ + public String readCommand(Scanner sc){ + + return sc.nextLine(); + } + + /** + * Set appropriate response by Duke to be shown based on user's input. + * @param message the String that Duke will respond with based on user input. + */ + public void setMessage(String message) { + this.message = dr.SPACES + message + dr.SPACES; + } + + /** + * Prints out the greeting by Duke program when Duke starts running. + */ + public void showWelcome(){ + System.out.println(dr.LOGO+ dr.SPACES + dr.GREET + dr.SPACES); + } + + /** + * Prints out the Duke's response based on user's input. + */ + public String showLine(){ + return this.message; + } +} diff --git a/src/main/java/Launcher.fxml b/src/main/java/Launcher.fxml new file mode 100644 index 0000000000..79ed4ed891 --- /dev/null +++ b/src/main/java/Launcher.fxml @@ -0,0 +1,19 @@ + + + + + + + + + + + +