diff --git a/docs/README.md b/docs/README.md index 8077118eb..30d885366 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,29 +1,237 @@ # User Guide +##Getting Started +### Preparations +Ensure that `ip.jar` is located within a folder of its own. +Open up a Terminal and ensure to the directory is the same as the folder `ip.jar` is located in. +### Initialising Duke +Enter the following into the terminal to initialise Duke application. +``` +java -jar ip.jar +``` +## Features and Usage +### Feature List +- `help` +- `todo` +- `deadline` +- `event` +- `list` +- `done` +- `delete` +- `bye` + +*All commands are not case-sensitive:* + +`dEAdLine`, `deadline`, and `Deadline` All mean: `deadline`. +___ +--- + +### List Commands: `help` +Prints all commands available. + +**Example of usage:** + +*input:* +``` +help +``` +--- +--- + +### Add ToDo: `todo` +Adds a new ToDo to the task list. A ToDo is a task with a description of the task. + +**Arguments:** +1. `` - Description of the ToDo task. + +**Format:** `todo ` + +**Example of usage:** + +*input:* +``` +todo Eat apples +``` +*output:* +``` +Got it. I've added this task: +1.[T][ ] Eat apples +Now you have 1 tasks in the list. +``` +--- +--- +### Add Deadline: `deadline` +Adds a new Deadline to the task list. A Deadline is a task with a description of the task and a deadline. + +**Arguments:** +1. `` - Description of the Deadline task. +2. `` - DateTime the deadline should be done by. + +**Format:** +- `deadline /by ` + +`` *is accepted in the following formats:* +- `Custom input` +- `dd/mm/yyyy` +- `dd/mm/yyyy hhmm` + +**Example of usage:** + +*input:* +``` +deadline IEM2 Assignment /by This Friday +``` +*output:* +``` +Got it. I've added this task: +2.[D][ ] IEM2 Assignment (by: This Friday) +Now you have 2 tasks in the list. +``` +___ +*input:* +``` +deadLine CS2113T ip submission /by 01/10/2021 2359 +``` +*output:* +``` +Got it. I've added this task: +3.[D][ ] CS2113T ip Submission (by: Oct 1 2021 11:59 PM) +Now you have 3 tasks in the list. +``` +___ +--- +### Add Event: `event` +Adds a new Event to the task list. An Event is a task with a description of the task and a event. + +**Arguments:** +1. `` - Description of the Event task. +2. `` - DateTime or Location the Event should be happening at. -## Features +**Format:** +- `event /at ` -### Feature-ABC +`` is accepted in the following formats: +- `Custom input` +- `dd/mm/yyyy` +- `dd/mm/yyyy hhmm` -Description of the feature. +**Example of usage:** -### Feature-XYZ +*input:* +``` +event Dance show /at Esplanade +``` +*output:* +``` +Got it. I've added this task: +4.[E][ ] Dance show (at: Esplanade) +Now you have 4 tasks in the list. +``` +--- +*input:* +``` +Event No Time To Die premiere /at 30/09/2021 +``` +*output:* +``` +Got it. I've added this task: +5.[E][ ] No Time To Die premiere (at: Sep 30 2021) +Now you have 5 tasks in the list. +``` +___ +--- +### List Tasks: `list` +Prints all tasks in the task list. + +**Arguments:** +None + +**Format:** +- `list` + +**Example of usage:** + +*input* +``` +list +``` +*output:* +``` +Here are the tasks in your list: +1.[T][ ] Eat apples +2.[D][ ] IEM2 Assignment (by: This Friday) +3.[D][ ] CS2113T ip Submission (by: Oct 1 2021 11:59 PM) +4.[E][ ] Dance show (at: Esplanade) +5.[E][ ] No Time To Die premiere (at: Sep 30 2021) + +``` +--- +--- +### Mark Task as Done: `done` +Marks a Task in the Task List as done. + +**Arguments:** +1. `` - Task index with respect to the list. + +**Format:** +- `done ` + +`` *should only be a number from the list* + +**Example of usage:** + +*input:* +``` +done 4 +``` +*output:* +``` +Nice, I've marked this task as Done: + [E][X] Dance show (at: Esplanade) +``` +___ +--- +### Remove Task from Task List: `delete` +Delete a Task from the Task List. -Description of the feature. +**Arguments:** +1. `` - Task index with respect to the list. -## Usage +**Format:** +- `delete ` -### `Keyword` - Describe action +*`` should only be a number from the list* -Describe the action and its outcome. +**Example of usage:** -Example of usage: +*input:* +``` +delete 3 +``` +*output:* +``` +Noted! I've removed this task: +3.[D][ ] CS2113T ip Submission (by: Oct 1 2021 11:59PM) +Now you have 4 tasks in the list. +``` +___ +--- +### Remove Task from Task List: `bye` +Exits Duke application. -`keyword (optional arguments)` +**Arguments:** + None -Expected outcome: +**Format:** +- `bye` -Description of the outcome. +**Example of usage:** +*input:* +``` +bye +``` +*output:* ``` -expected output +Bye. try not to procrastinate! ``` +___ \ No newline at end of file diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 000000000..b84971359 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-leap-day \ No newline at end of file diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java deleted file mode 100644 index 5d313334c..000000000 --- a/src/main/java/Duke.java +++ /dev/null @@ -1,10 +0,0 @@ -public class Duke { - public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - } -} diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java new file mode 100644 index 000000000..64a09a11f --- /dev/null +++ b/src/main/java/duke/Duke.java @@ -0,0 +1,73 @@ +package duke; + +import duke.DukeExceptions.EmptyCommand; +import duke.DukeExceptions.InvalidCommandException; +import duke.task.Task; + +import java.io.FileNotFoundException; +import java.util.Scanner; +import java.util.ArrayList; + +public class Duke { + + private final Storage storage; + private TaskList tasksLs; + private final Ui ui; + + private final Scanner in = new Scanner(System.in); + + /** + * A constructor to initiate Duke. + * + * @param filepath Filepath when initiating. + */ + public Duke(String filepath) { + this.tasksLs = new TaskList(new ArrayList()); + this.storage = new Storage(filepath); + this.ui = new Ui(); + } + + /** + * Runs Duke object until user exits with . + */ + private void run() { + ui.greetMessage(); + String input = ""; + try { + tasksLs = storage.loadFile(tasksLs.getList()); + } catch (FileNotFoundException e) { + storage.createFile(); + } + + boolean closeDuke = false; + do { + try { + input = getInput(); + String parsed = new Parser(tasksLs, ui).parse(input); + System.out.println(parsed); + storage.autoSave(tasksLs.getList()); + closeDuke = input.trim().equals("bye"); + } catch (InvalidCommandException | EmptyCommand e) { + System.out.println(e); + } + } while (!closeDuke); + } + + /** + * Prompts user for input. + * + * @return String input by user. + */ + private String getInput() { + return in.nextLine(); + } + + /** + * application. + * + * @param args to start Duke Application. + */ + public static void main(String[] args) { + new Duke("duke.txt").run(); + } +} diff --git a/src/main/java/duke/DukeExceptions/DukeException.java b/src/main/java/duke/DukeExceptions/DukeException.java new file mode 100644 index 000000000..35394b006 --- /dev/null +++ b/src/main/java/duke/DukeExceptions/DukeException.java @@ -0,0 +1,12 @@ +package duke.DukeExceptions; + +public class DukeException extends Exception { + /** + * convert to new default Exception message. + * + * @return error Message. + */ + public String toString() { + return "Something Went Wrong"; + } +} diff --git a/src/main/java/duke/DukeExceptions/EmptyCommand.java b/src/main/java/duke/DukeExceptions/EmptyCommand.java new file mode 100644 index 000000000..98bdb2530 --- /dev/null +++ b/src/main/java/duke/DukeExceptions/EmptyCommand.java @@ -0,0 +1,15 @@ +package duke.DukeExceptions; + +public class EmptyCommand extends DukeException { + + /** + * @return Empty input Message. + */ + public String toString() { + return ("\t______________________________________________________________________\n" + + "\tNo command detected. Command was empty :)\n" + + "\t______________________________________________________________________\n" + + "\tKey in [help] to list available commands\n" + + "\t______________________________________________________________________\n"); + } +} diff --git a/src/main/java/duke/DukeExceptions/InvalidCommandException.java b/src/main/java/duke/DukeExceptions/InvalidCommandException.java new file mode 100644 index 000000000..7a1183fe4 --- /dev/null +++ b/src/main/java/duke/DukeExceptions/InvalidCommandException.java @@ -0,0 +1,31 @@ +package duke.DukeExceptions; + +public class InvalidCommandException extends DukeException { + private String thisError; + + /** + * Default Constructor. + */ + public InvalidCommandException() { + this.thisError = ("\t______________________________________________________________________\n" + + "\tOOOPS!!! I'm sorry, but I don't know what that means. EPIC SADS :-(\n" + + "\t______________________________________________________________________\n" + + "\tKey in [help] to list available commands\n" + + "\t______________________________________________________________________\n\t"); + } + + /** + * Constructor with custom errorMessage. + * + * @param errorMessage error Message to train Elgle. + */ + public InvalidCommandException(String errorMessage) { + this.thisError = ("\t______________________________________________________________________\n\t" + + errorMessage + + "\n\t______________________________________________________________________\n\t"); + } + + public String toString() { + return (this.thisError); + } +} diff --git a/src/main/java/duke/DukeExceptions/InvalidValueException.java b/src/main/java/duke/DukeExceptions/InvalidValueException.java new file mode 100644 index 000000000..ec0777b50 --- /dev/null +++ b/src/main/java/duke/DukeExceptions/InvalidValueException.java @@ -0,0 +1,22 @@ +package duke.DukeExceptions; + +import duke.Duke; + +public class InvalidValueException extends DukeException { + private String errorMessage; + + public InvalidValueException(String expectedMessage) { + this.errorMessage = ("\t______________________________________________________________________\n\t" + + expectedMessage + + "\n\t______________________________________________________________________\n\t"); + } + + /** + * convert to new default Exception message. + * + * @return error Message. + */ + public String toString() { + return this.errorMessage; + } +} diff --git a/src/main/java/duke/Parser.java b/src/main/java/duke/Parser.java new file mode 100644 index 000000000..09d18aba5 --- /dev/null +++ b/src/main/java/duke/Parser.java @@ -0,0 +1,228 @@ +package duke; + +import duke.DukeExceptions.*; +import duke.task.Deadline; +import duke.task.Event; +import duke.task.Task; +import duke.task.ToDo; + +import java.time.format.DateTimeParseException; + +public class Parser { + private final TaskList taskList; + private final Ui ui; + + /** + * Constructor to create Parser object. + * + * @param taskList TaskList that is currently in use. + * @param ui Ui object. + */ + Parser(TaskList taskList, Ui ui) { + this.taskList = taskList; + this.ui = ui; + } + + /** + * Breakdown user input to run user commands. + * + * @param userInput String input from user. + * @return Executed command ui. + * @throws InvalidCommandException if there are no recognisable command. + * @throws EmptyCommand if the input is empty. + */ + public String parse(String userInput) throws InvalidCommandException, EmptyCommand { + try { + if (userInput.trim().equals("")) + throw new EmptyCommand(); + String[] command = userInput.split(" "); + switch (command[0].trim().toLowerCase()) { + case "help": + return parseHelp(); + case "bye": + return parseBye(); + case "done": + return parseDone(userInput); + case "delete": + return parseDelete(userInput); + case "todo": + return parseTodo(userInput); + case "deadline": + return parseDeadline(userInput); + case "event": + return parseEvent(userInput); + case "list": + return parseList(); + case "find": + return parseFind(userInput); + default: + throw new InvalidCommandException(); + } + } catch (DukeException e) { + return e.toString(); + } catch (DateTimeParseException e) { + return ui.dateTimeFormat(); + } catch (StringIndexOutOfBoundsException e) { + return new InvalidValueException("Please check if you input Date / Time").toString(); + } + } + + /** + * execute command + * + * @return list of all commands available + */ + public String parseHelp() { + return ui.helpList(); + } + + /** + * Execute command. + * + * @return "bye" message. + */ + public String parseBye() { + return ui.byeMessage(); + } + + /** + * Execute command. + * + * @param command Input from user. + * @return "done" message. + * @throws InvalidValueException if user input is in the wrong format. + */ + public String parseDone(String command) throws InvalidValueException { + validate(command); + String statusMessage = taskList.markAsDone(command); + return ui.doneMessage(statusMessage); + } + + /** + * Execute command. + * + * @param command Input from user. + * * @return "deleted" message. + * * @throws InvalidValueException if user input is in the wrong format. + */ + public String parseDelete(String command) throws InvalidValueException { + validate(command); + int index = getIndex(command); + Task targetTask = taskList.deleteTask(index); + return ui.deleteMessage(taskList.getList(), index, targetTask); + } + + /** + * Execute command. + * + * @param command Input from user. + * @return String acknowledging new addition. + * @throws InvalidValueException if user input is in the wrong format. + */ + public String parseTodo(String command) throws InvalidValueException { + if (command.split(" ").length == 1) + throw new InvalidValueException("Todo: Missing Description, Please Try Again"); + taskList.addTask(new ToDo(TaskList.getItem(command))); + return ui.acknowledgeAddition(taskList.getList()); + } + + /** + * Execute command. + * + * @param command Input from user. + * @return String acknowledging new addition. + * @throws InvalidValueException if user input is in the wrong format. + */ + public String parseDeadline(String command) throws InvalidValueException { + if (command.split(" ").length == 1) + throw new InvalidValueException("Deadline: Missing Description / Time"); + if (command.split("/").length == 3) + throw new InvalidValueException("Please input Date in the following format:
"); + taskList.addTask(new Deadline(taskList.getDescription(command), taskList.getMoreDetails(command))); + return ui.acknowledgeAddition(taskList.getList()); + } + + /** + * Execute command. + * + * @param command Input from user. + * @return String acknowledging new addition. + * @throws InvalidValueException if user input is in the wrong format. + */ + public String parseEvent(String command) throws InvalidValueException { + if (command.split(" ").length == 1) + throw new InvalidValueException("Event: Missing Description / Time"); + if (command.split("/").length == 3) + throw new InvalidValueException("Please input Date in the following format:
"); + taskList.addTask(new Event(taskList.getDescription(command), taskList.getMoreDetails(command))); + return ui.acknowledgeAddition(taskList.getList()); + } + + /** + * Execute "list" command. + * + * @return List in form of String. + */ + public String parseList() { + return ui.printList(taskList); + } + + /** + * Reetrieve index in command as integer. + * + * @param command Input from user. + * @return Extracted Integer. + */ + private static int getIndex(String command) { + String index = command.substring(command.indexOf(" ") + 1); + return Integer.parseInt(index.trim()); + } + + /** + * Checks if input is numeric. + * + * @param validate Input that requires validation. + * @return true for input that is numeric and false for non numeric. + */ + private boolean isNumeric(String validate) { + try { + Integer.parseInt(validate); + } catch (NumberFormatException e) { + return false; + } + return true; + } + + /** + * Throw all possible Exceptions that might crash the programme. + * + * @param command Input from user. + * @throws InvalidValueException if user input is in the wrong format. + */ + private void validate(String command) throws InvalidValueException { + String[] temp; + temp = command.split(" "); + if (temp.length == 1) { + throw new InvalidValueException("Missing Item Number"); + } else if (temp.length > 2) { + throw new InvalidValueException("Please be specific :) Expected 1 item number"); + } else if (!isNumeric(temp[1])) { + throw new InvalidValueException("Oops, could you input item as a number please"); + } else if (getIndex(command) > this.taskList.getList().size() | getIndex(command) < 1) { + throw new InvalidValueException(String.format("Input Number was more that [1 - %d] tasks in the list.", taskList.getList().size())); + } + } + + /** + * Execute "find" command. + * + * @param command Input from user. + * @return List of all items found with keyword. + */ + public String parseFind(String command) throws InvalidValueException { + if (taskList.getList().size() == 0) + return ui.printList(taskList); + String keyword = TaskList.getKeyword(command); + return ui.findResults(keyword, taskList); + } +} \ No newline at end of file diff --git a/src/main/java/duke/Storage.java b/src/main/java/duke/Storage.java new file mode 100644 index 000000000..849287ef4 --- /dev/null +++ b/src/main/java/duke/Storage.java @@ -0,0 +1,127 @@ +package duke; + +import duke.task.Deadline; +import duke.task.Event; +import duke.task.Task; +import duke.task.ToDo; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Scanner; + +public class Storage { + + private String filepath; + private TaskList currentData; + + public static final String SAVEFILE_SEPERATOR = "\\|"; + + /** + * Constructor to create Storage object. + * + * @param filepath intended filepath to store data. + */ + Storage(String filepath) { + this.filepath = filepath; + } + + /** + * Read file and extract file into TaskList. + * + * @param taskList Most Recent ArrayList taskList. + * @return Latest TaskList. + * @throws FileNotFoundException if file has never been created. + */ + public TaskList loadFile(ArrayList taskList) throws FileNotFoundException { + File f = new File(this.filepath); + Scanner s = new Scanner(f); + currentData = new TaskList(taskList); + while (s.hasNext()) { + currentData = loadCommands(s.nextLine(), currentData.getList()); + } + return currentData; + } + + /** + * Creates a new file. + */ + public void createFile() { + File f = new File(this.filepath); + try { + f.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Convert stored line of data into current TaskList. + * + * @param taskDetails Saved data from save file. + * @param taskList Current ArrayList task List. + * @return Current TaskList. + */ + private static TaskList loadCommands(String taskDetails, ArrayList taskList) { + String[] taskBreakdown = taskDetails.split(SAVEFILE_SEPERATOR); + String taskType = taskBreakdown[0].trim(); + String completionStatus = taskBreakdown[1].trim(); + String task = taskBreakdown[2].trim(); + Task savedTask; + switch (taskType) { + case "T": + savedTask = new ToDo(task); + break; + case "D": + savedTask = new Deadline(task, taskBreakdown[3].trim()); + break; + case "E": + savedTask = new Event(task, taskBreakdown[3].trim()); + break; + default: + savedTask = null; + } + if (completionStatus.equals("1")) { + savedTask.markAsDone(); + } + taskList.add(savedTask); + return new TaskList(taskList); + } + + /** + * Input stored data into save file. + * + * @param filePath filePath of save file. + * @param textToAdd String to be written. + * @throws IOException when Run into execution. + */ + private void writeToFile(String filePath, String textToAdd) throws IOException { + FileWriter dukeIn = new FileWriter(filePath); + dukeIn.write(textToAdd); + dukeIn.close(); + } + + /** + * Automatically ArrayList Tasks. + * + * @param taskArrayList current ArrayList. + */ + public void autoSave(ArrayList taskArrayList) { + String dukeUpdate = ""; + for (Task task : taskArrayList) { + if (task != null) { + String completionStatus = task.isDone() ? "1" : "0"; + dukeUpdate = dukeUpdate + task.getType() + " | " + completionStatus + " | " + task.getTask(); + dukeUpdate = (task instanceof Deadline || task instanceof Event) ? dukeUpdate + " | " + task.getMoreDetails() : dukeUpdate; + dukeUpdate = dukeUpdate + "\n"; + } + } + try { + writeToFile(this.filepath, dukeUpdate); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/duke/TaskList.java b/src/main/java/duke/TaskList.java new file mode 100644 index 000000000..90f8273e5 --- /dev/null +++ b/src/main/java/duke/TaskList.java @@ -0,0 +1,161 @@ +package duke; + +import duke.DukeExceptions.InvalidValueException; +import duke.task.Task; + +import java.util.ArrayList; + +public class TaskList { + private ArrayList list; + + /** + * Constructor to create TaskList object. + * + * @param list is the current list of Task. + */ + TaskList(ArrayList list) { + this.list = list; + } + + public int notDoneCount() { + int unmarked = 0; + for (Task task : list) { + unmarked += (task.isDone()) ? 0 : 1; + } + return unmarked; + } + + /** + * Adds task to TaskList. + * + * @param newTask that user wants to add. + */ + public void addTask(Task newTask) { + this.list.add(newTask); + } + + /** + * Retrieves list of Tasks stored as ArrayList. + * + * @return list of Tasks stored in TaskList object. + */ + public ArrayList getList() { + return list; + } + + /** + * Sets isDone of tasks specified to true. + * + * @param command input by user. + * @return task specified as done. + */ + public String markAsDone(String command) { + int index = getIndex(command) - 1; + Task completedTask = list.get(index); + if (completedTask.isDone()) + return "Done Previously"; + completedTask.markAsDone(); + list.get(index).markAsDone(); + return completedTask.toString(); + } + + /** + * Deletes tasks from TaskList. + * + * @param index number of the task in list. + * @return deleted task. + */ + public Task deleteTask(int index) { + Task targetTask = list.get(index - 1); + list.remove(index - 1); + return targetTask; + } + + /** + * Retrieves the target items after user command + * + * @param command target items (Description or find target). + * @return target items. + */ + public static String getItem(String command) throws InvalidValueException { + String item = ""; + if (command.contains(" ")) + item = command.substring((command.indexOf(" ") + 1)).trim(); + if (item.equals("")) + throw new InvalidValueException("You forgot to include Task description"); + return item; + } + + /** + * Retrieves keyword from command + * + * @param command Input from user + * @return Keyword required to find + * @throws InvalidValueException Whenever user never inputs keywords + */ + public static String getKeyword(String command) throws InvalidValueException { + String keyword = ""; + if (command.contains(" ")) + keyword = command.substring((command.indexOf(" ") + 1)).trim(); + if (keyword.equals("")) + throw new InvalidValueException("Find: Missing keyword to search, Please Try Again"); + return keyword; + } + + /** + * Retrieves the description of task in user input. + * + * @param command input from user. + * @return description of task. + * @throws InvalidValueException when missing demarcators, or missing description in command. + */ + public String getDescription(String command) throws InvalidValueException { + if (!command.contains("/")) + throw new InvalidValueException("Missing detail demarcator: or "); + String desc = command.substring(command.indexOf(" ") + 1, command.indexOf("/")).trim(); + if (desc.equals("")) + throw new InvalidValueException("Missing Description in command"); + return desc; + } + + /** + * Retrieves extra details needed. + * + * @param command input from user. + * @return extra details required. + * @throws InvalidValueException when missing extra details required in command. + */ + public String getMoreDetails(String command) throws InvalidValueException { + String moreDetails = command.substring(command.indexOf("/") + 4); + if (moreDetails.trim().equals("") | moreDetails.trim().contains("\t")) + throw new InvalidValueException("Missing Required Extra Details"); + return moreDetails; + } + + /** + * Retrieve list of items containing the keyword. + * + * @param keyword Keyword input by user. + * @return result List of items found with keyword. + */ + public String find(String keyword) { + int count = 0; + String result = ""; + for (Task task : list) { + count += 1; + result += (task.getTask().contains(keyword)) ? String.format("\t%d. ", count) + task + "\n" : ""; + } + return result; + } + + /** + * Retrieve user input item as integer. + * + * @param command input from user + * @return index found in input + */ + private static int getIndex(String command) { + String index = command.substring(command.indexOf(" ") + 1); + return Integer.parseInt(index.trim()); + } +} diff --git a/src/main/java/duke/Ui.java b/src/main/java/duke/Ui.java new file mode 100644 index 000000000..d77627d82 --- /dev/null +++ b/src/main/java/duke/Ui.java @@ -0,0 +1,151 @@ +package duke; + +import duke.task.Task; + +import java.util.ArrayList; + +public class Ui { + public static final String LOGO = "\t\t\t\t ____ _ \n" + + "\t\t\t\t| _ \\ _ _| | _____ \n" + + "\t\t\t\t| | | | | | | |/ / _ \\\n" + + "\t\t\t\t| |_| | |_| | < __/\n" + + "\t\t\t\t|____/ \\__,_|_|\\_\\___|\n"; + public static final String LINE = "\t______________________________________________________________________\n\t\t"; + public static final String BYE = LINE + + "Bye. try not to procrastinate!\n" + + LINE; + public static final String GREETING = LINE + + "Hello! I'm Anderson\n\t\t" + + "What do you need to do?\n" + + LINE; + + /** + * prints message to greet user. + */ + public void greetMessage() { + System.out.println(LOGO + GREETING); + } + + /** + * Retrieves bye Message. + * + * @return bye Message. + */ + public String byeMessage() { + return BYE; + } + + /** + * Acknowledge marking task as done. + * + * @param completedTask Task targeted to be marked. + * @return Message on completion of marking done. + */ + public String doneMessage(String completedTask) { + if (completedTask.equals("Done Previously")) { + return (LINE + + "This task has previously been completed\n" + + LINE); + } + return (LINE + + "Nice, I've marked this task as Done:\n\t" + + "\t\t" + completedTask + "\n" + + LINE); + } + + /** + * Acknowledge deletion of task from list of tasks. + * + * @param taskList ArrayList of Task. + * @param taskNumber Index number of target Task. + * @param targetTask Task to remove. + * @return Acknowledgement message. + */ + public String deleteMessage(ArrayList taskList, int taskNumber, Task targetTask) { + return (LINE + "Noted! I've removed this task:" + + String.format("\n\t\t%d.", taskNumber) + targetTask + String.format("\n\t\tNow you have %d tasks in the list.\n", taskList.size()) + LINE); + } + + /*** + * Retrieves list in String form. + * + * @param taskList current TaskList. + * @return String of list. + */ + public String printList(TaskList taskList) { + int count = 0; + String outputString = ""; + if (taskList.getList().size() == 0) { + outputString = (LINE + "\tThere is no task in List\n" + LINE); + } else { + outputString = (LINE + "Here are the tasks in your list:\n"); + for (Task task : taskList.getList()) { + count++; + outputString += ("\t\t" + count + "." + task + "\n"); + } + outputString += String.format("\n\t\tAs of now, %d task(s) remain not marked Done.\n", taskList.notDoneCount()) + LINE; + } + return outputString; + } + + /** + * Retrieve acknowledgement message of new tasks to list. + * + * @param taskArrayList ArrayList of tasks. + * @return Acknowledgement of addition message. + */ + public String acknowledgeAddition(ArrayList taskArrayList) { + return (LINE + + "Got it. I've added this task:\n" + + String.format("\t\t%d.", taskArrayList.size()) + taskArrayList.get(taskArrayList.size() - 1) + "\n" + + String.format("\t\tNow you have %d tasks in the list.\n", taskArrayList.size()) + + LINE); + } + + public String helpList() { + return (LINE + + "Here are the list of commands Available in Duke:\n" + + LINE + + "bye : closes Programme\n\t\t" + + "list : lists out every Task stored in the savefile\n\t\t" + + "todo : Adds a new ToDo to the Task List\n\t\t" + + "deadline : Adds a new Deadline to the Task List\n\t\t" + + "event : Adds a new Event to the Task List\n\t\t" + + "find : Lists all tasks that contains a keyword\n\t\t" + + "done : Mark a task as done\n\t\t" + + "delete : Delete task from Task List\n" + + LINE); + } + + /** + * Retrieves list of tasks containing keywords. + * + * @param keyword Extracted keyword from user. + * @param taskList Current TaskList object. + * @return list of tasks containing keywords. + */ + public String findResults(String keyword, TaskList taskList) { + String results = taskList.find(keyword); + if (results.equals("")) { + return (LINE + + "No description matches [" + keyword + "]:\n" + + LINE); + } + return (LINE + + "Find Results of [" + keyword + "]:\n" + + results + + LINE); + } + + /** + * Retrieves correct format for Date/Time input. + * + * @return Correct format for Date/Time input. + */ + public String dateTimeFormat() { + return (LINE + + "Date / Time input format should be: dd/mm/yyyy hhmmss" + + LINE); + } + +} diff --git a/src/main/java/duke/task/Deadline.java b/src/main/java/duke/task/Deadline.java new file mode 100644 index 000000000..025408dfd --- /dev/null +++ b/src/main/java/duke/task/Deadline.java @@ -0,0 +1,101 @@ +package duke.task; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +public class Deadline extends Task { + + protected String by; + protected String type = "D"; + protected LocalDate date; + protected LocalTime time; + + /** + * Constructor to create Deadline object. + * + * @param description Deadline description. + * @param by The time the deadline is due. + */ + public Deadline(String description, String by) { + super(description); + this.by = by; + if (by.trim().contains("/")) { + String formattedBy = getCorrectFormat(by); + String[] tempStr = formattedBy.split(" "); + this.date = LocalDate.parse(tempStr[0]); + if (tempStr.length == 2) + this.time = LocalTime.parse(tempStr[1]); + } + } + + /** + * Retrieve correct format to parse into LocalDate and LocalTime. + * + * @param by stored by String. + * @return correct format to parse into LocalDate and Local Time. + */ + private String getCorrectFormat(String by) { + + StringBuilder toParse = new StringBuilder(); + String[] dateTime = by.split(" "); + String[] tempDate = dateTime[0].trim().split("/"); + String toStore = ""; + if (tempDate.length == 3) { + for (int i = 2; i > 0; i--) { + toParse.append(tempDate[i]).append("-"); + } + toParse.append(tempDate[0]); + toStore += toParse + " "; + } + if (dateTime.length > 1) { + toParse = new StringBuilder(); + int missingDigits = 6 - dateTime[1].trim().length(); + for (int i = 0; i < dateTime[1].trim().length(); i++) { + char c = dateTime[1].charAt(i); + toParse.append((i != 0 && i % 2 == 0) ? ":" + c : c); + } + for (int i = 0; i < missingDigits; i++) { + /* fill in missing '0's and ':'s int correct orientation */ + toParse.append((missingDigits % 2 == i % 2) ? ":0" : "0"); + } + toStore += toParse; + } + return toStore; + } + + private String displayDateTime() { + String outputString = date.format(DateTimeFormatter.ofPattern("MMM d yyyy")) + " "; + if (time != null) { + outputString += time.format(DateTimeFormatter.ofPattern("hh:mm a")); + } + return outputString + ")"; + } + + /** + * Retrieve MoreDetails (timings) of deadlines. + * + * @return timings of the Deadline. + */ + public String getMoreDetails() { + return this.by; + } + + /** + * Retrieve the task type. + * + * @return Task type: "D". + */ + public String getType() { + return type; + } + + /** + * Overrides string representation to display. + * + * @return string representation to display. + */ + public String toString() { + return (by.contains("/")) ? ("[D]" + super.toString() + " (by: " + displayDateTime()) : ("[D]" + super.toString() + " (by: " + by + ")"); + } +} \ No newline at end of file diff --git a/src/main/java/duke/task/Event.java b/src/main/java/duke/task/Event.java new file mode 100644 index 000000000..8615b1abb --- /dev/null +++ b/src/main/java/duke/task/Event.java @@ -0,0 +1,98 @@ +package duke.task; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +public class Event extends Task { + + protected String at; + protected String type = "E"; + protected LocalDate date; + protected LocalTime time; + + /** + * Constructor to create Event object. + * + * @param description Event description. + * @param at Event timings. + */ + public Event(String description, String at) { + super(description); + this.at = at; + if (at.trim().contains("/")) { + String formattedBy = getCorrectFormat(at); + String[] tempStr = formattedBy.split(" "); + this.date = LocalDate.parse(tempStr[0]); + if (tempStr.length == 2) + this.time = LocalTime.parse(tempStr[1]); + } + } + + /** + * Retrieve correct format to parse into LocalDate and LocalTime. + * + * @param by stored by String. + * @return correct format to parse into LocalDate and Local Time. + */ + private String getCorrectFormat(String by) { + + StringBuilder toParse = new StringBuilder(); + String[] dateTime = by.split(" "); + String[] tempDate = dateTime[0].trim().split("/"); + String toStore = ""; + if (tempDate.length == 3) { + for (int i = 2; i > 0; i--) { + toParse.append(tempDate[i]).append("-"); + } + toParse.append(tempDate[0]); + toStore += toParse + " "; + } + + if (dateTime.length > 1) { + toParse = new StringBuilder(); + int missingDigits = 6 - dateTime[1].trim().length(); + for (int i = 0; i < dateTime[1].trim().length(); i++) { + char c = dateTime[1].charAt(i); + toParse.append((i != 0 && i % 2 == 0) ? ":" + c : c); + } + for (int i = 0; i < missingDigits; i++) { + /** fill in missing '0's and ':'s int correct orientation */ + toParse.append((missingDigits % 2 == i % 2) ? ":0" : "0"); + } + toStore += toParse; + } + return toStore; + } + + private String displayDateTime() { + String outputString = date.format(DateTimeFormatter.ofPattern("MMM d yyyy")) + " "; + if (time != null) { + outputString += time.format(DateTimeFormatter.ofPattern("hh:mm a")); + } + return outputString + ")"; + } + + /** + * Retrieve More details (timings) of events. + * + * @return timings of the Event. + */ + public String getMoreDetails() { + return this.at; + } + + /** + * Retrieve the task type. + * + * @return Task type: "E". + */ + public String getType() { + return type; + } + + @Override + public String toString() { + return (at.contains("/")) ? ("[E]" + super.toString() + " (at: " + displayDateTime()) : ("[E]" + super.toString() + " (at: " + at + ")"); + } +} \ No newline at end of file diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java new file mode 100644 index 000000000..05adcb2bf --- /dev/null +++ b/src/main/java/duke/task/Task.java @@ -0,0 +1,79 @@ +package duke.task; + +public class Task { + protected String task; + protected boolean isDone; + protected String type; + + /** + * Constructor to create Task object + * + * @param task Description of the task + */ + public Task(String task) { + this.task = task; + this.isDone = false; + } + + /** + * Retrieves "[X]" for tasks marked done or "[ ]" for tasks not marked done. + * + * @return Either "[X]" or "[ ]". + */ + public String getStatusIcon() { + return (isDone ? "[X] " : "[ ] "); + } + + /** + * Records if task is marked done. + * + * @return Status of the task. + */ + public boolean isDone() { + return isDone; + } + + /** + * Retrieve more details, usually timings (if any) of deadlines or events. + * + * @return timings (if any) of the task. + */ + public String getMoreDetails() { + return ""; + } + + /** + * Retrieve description of the task. + * + * @return description of the task. + */ + public String getTask() { + return task; + } + + /** + * Retrieve the task type. + * + * @return Task type. + */ + public String getType() { + return type; + } + + /** + * set isDone to true. + */ + public void markAsDone() { + this.isDone = true; + } + + /** + * Overrides string representation to display. + * + * @return string representation to display. + */ + public String toString() { + return this.getStatusIcon() + this.task; + } + +} \ No newline at end of file diff --git a/src/main/java/duke/task/ToDo.java b/src/main/java/duke/task/ToDo.java new file mode 100644 index 000000000..58a6fbf87 --- /dev/null +++ b/src/main/java/duke/task/ToDo.java @@ -0,0 +1,29 @@ +package duke.task; + +public class ToDo extends Task { + + protected String type = "T"; + + /** + * Constructor to create ToDo object. + * + * @param description ToDo description. + */ + public ToDo(String description) { + super(description); + } + + /** + * Retrieve the task type. + * + * @return Task type: "T". + */ + public String getType() { + return type; + } + + @Override + public String toString() { + return "[T]" + super.toString(); + } +} \ No newline at end of file diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 657e74f6e..af11dcd18 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,7 +1,68 @@ -Hello from - ____ _ -| _ \ _ _| | _____ + Hello from + ____ _ +| _ \ _ _| | _____ | | | | | | | |/ / _ \ | |_| | |_| | < __/ |____/ \__,_|_|\_\___| + ____________________________________________________________ + Hello! I'm Anderson + What do you need to do? + ____________________________________________________________ + + ____________________________________________________________ + Got it. I've added this task: + 1.[T][ ] AAA AA AAAA A + Now you have 1 tasks in the list. + ____________________________________________________________ + + ____________________________________________________________ + Got it. I've added this task: + 2.[D][ ] B BB BBB BBBB (by: January) + Now you have 2 tasks in the list. + ____________________________________________________________ + + ____________________________________________________________ + Got it. I've added this task: + 3.[E][ ] CC CCCC C CCC (at: Noon) + Now you have 3 tasks in the list. + ____________________________________________________________ + + ____________________________________________________________ + Got it. I've added this task: + 4.[T][ ] BigBoooom + Now you have 4 tasks in the list. + ____________________________________________________________ + + ____________________________________________________________ + Here are the tasks in your list: + + 1.[T][ ] AAA AA AAAA A + 2.[D][ ] B BB BBB BBBB (by: January) + 3.[E][ ] CC CCCC C CCC (at: Noon) + 4.[T][ ] BigBoooom + ____________________________________________________________ + + ____________________________________________________________ + Nice! I've marked this task as done: + [E][X] CC CCCC C CCC (at: Noon) + ____________________________________________________________ + + ____________________________________________________________ + Nice! I've marked this task as done: + [T][X] BigBoooom + ____________________________________________________________ + + ____________________________________________________________ + Here are the tasks in your list: + + 1.[T][ ] AAA AA AAAA A + 2.[D][ ] B BB BBB BBBB (by: January) + 3.[E][X] CC CCCC C CCC (at: Noon) + 4.[T][X] BigBoooom + ____________________________________________________________ + + ____________________________________________________________ + Bye. try not to procrastinate! + ____________________________________________________________ + diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e69de29bb..9c7e276fe 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -0,0 +1,9 @@ +ToDo AAA AA AAAA A +Deadline B BB BBB BBBB /by January +Event CC CCCC C CCC /at Noon +ToDo BigBoooom +list +done 3 +done 4 +list +byE \ No newline at end of file