diff --git a/docs/README.md b/docs/README.md index 8077118eb..45d134c89 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,29 +1,496 @@ -# User Guide +# Duke User Guide -## Features +Duke is a Command Line Interface program that let users keep track of their tasks. -### Feature-ABC +## Quick Start -Description of the feature. +1. Ensure Java `11` is installed. +2. Download [IP.jar](https://github.com/kum-wh/ip/releases). +3. Navigate to file path in terminal. +4. To launch **Duke**, enter `java -jar IP.jar`. -### Feature-XYZ +## Command List -Description of the feature. +Command | Use +------- | --- +`ToDo` | Add **ToDo** Task +`Deadline` | Add **Deadline** Task +`Event` | Add **Event** Task +`Done` | Set a Task as **completed** +`Delete` | Remove a Task +`List` | View Task +`Find` | Find Tasks with a specific **Keyword** +`Date` | Find Tasks with a specific **Date** +`Bye` | Exit Program +`Echo` | Repeat Input +`!Echo` | Repeat Input in Grafiti ASCII Art +`!help` | View commands functions +`!list` | View **list** commands description +`!event` | View **event** commands description +`!deadline` | View **deadline** commands description -## Usage +## Notes -### `Keyword` - Describe action +* Words in `UPPER_CASE` are parameters to be entered by user. +* Program is **not** case sensitive. +* `INPUT` represent input by user. +* `TASK_DESCRIPTION` represent description of a task. +* `TASK_DEADLINE` represent date of a task either in words or `DATE` and `TIME` format. +* `TASK_TIMING` represent timing of a task either in words or `DATE` and `TIME` format. +* `TASK_INDEX` represent index number of a task. Index number can be viewed by viewing list. +* `KEYWORD` represent word input by user. +* `TIME` represents date input by user in `HH:MM` format. + * `HH` represents hours. + * `MM` represents minutes. +* `DATE` represents date input by user in `yyyy-mm-dd` fomat. + * `yyyy` represents year. + * `mm` represents months. + * `dd` represents days. +* Tasks are represented as `TASK_TYPE`,`STATUS`,`TASK_DESCRIPTION`,`TASK_DATE`. + * `TASK_TYPE` is `T` for ToDo, `D` for Deadline and `E` for Event. + * `STATUS` is `X` if completed. + * `TASK_DATE` is TASK_DEADLINE for Deadline and TASK_TIMING for Event. -Describe the action and its outcome. +## Features -Example of usage: +### Adding a Task -`keyword (optional arguments)` +Multiple tasks can be added in one line. -Expected outcome: +#### Adding a ToDo Task -Description of the outcome. +Adds a task without any specific dates to list. +Command Format: `todo TASK_DESCRIPTION` + +* `TASK_DESCRIPTION` cannot be empty. + +Examples: +* `todo watch twitch videos` +* `todo watch youtube videos` + +Demo: + +``` +todo watch twitch videos todo watch youtube videos + +____________________________________________________________ +Got it. I've added this task: +[T][ ]watch twitch videos +Now you have 1 tasks in the list. +Got it. I've added this task: +[T][ ]watch youtube videos +Now you have 2 tasks in the list. +____________________________________________________________ +``` + +#### Adding a DeadLine Task + +Adds a task with a duedate as deadline to list. + +Command Format | Command +-------------- | ------- +Without Date and Time | `deadline TASK_DESCRIPTION by TASK_DEADLINE` +Without Date | `deadline TASK_DESCRIPTION by TIME` +Without Time | `deadline TASK_DESCRIPTION by DATE` +With Date and Time | `deadline TASK_DESCCRIPTION by TIME DATE` + +* `TASK_DESCRIPTION` and `TASK_DEADLINE` cannot be empty. +* Word `by` is required in input to indicated `TASK_DEADLINE`. +* No specific ordering of time and date as long as input pattern is followed. + +Examples: +* `deadline homework1 by 23:59` +* `deadline homework2 by 2020-10-10` +* `deadline homework3 by 20:00 2021-10-20` + +Demo: + +``` +deadline homework1 by 23:59 deadline homework2 by 2020-10-10 deadline homework3 by 20:00 2021-10-20 + +____________________________________________________________ +Got it. I've added this task: +[D][ ]homework1(by: 11:59 PM ) +Now you have 3 tasks in the list. +Got it. I've added this task: +[D][ ]homework2(by: Oct 10 2020) +Now you have 4 tasks in the list. +Got it. I've added this task: +[D][ ]homework3(by: 08:00 PM Oct 20 2021) +Now you have 5 tasks in the list. +____________________________________________________________ +``` + +View details on adding Deadline task in program. + +Command Format: `!deadline` + +Demo: + +``` +____________________________________________________________ +deadline command requires a end time indicated using "by"[end time] +[timing]: HH:MM YYYY-MM-DD +____________________________________________________________ +``` + +#### Adding a Event Task + +Adds a task occuring at a specific date and time as event to list. + +Command Format | Command +-------------- | ------- +Without Date and Time | `event TASK_DESCRIPTION at TASK_TIMING` +Without Date | `event TASK_DESCRIPTION at TIME` +Without Time | `event TASK_DESCRIPTION at DATE` +With Date and Time | `event TASK_DESCCRIPTION at TIME DATE` + + +* `TASK_DESCRIPTION` and `TASK_TIMING` cannot be empty. +* Word `at` is required in input to indicated `TASK_DEADLINE`. +* No specific ordering of `TIME` and `DATE` as long as input pattern is followed. + +Examples: +* `event g2 vs SEN at 21:00` +* `event 100T vs Gambit at 2021-08-01` +* `event paperex vs Bren at 2021-08-01 08:00` + +Demo: + +``` +event g2 vs SEN at 21:00 event 100T vs Gambit at 2021-08-01 event paperex vs Bren at 2021-08-01 08:00 + +____________________________________________________________ +Got it. I've added this task: +[E][ ]g2 vs en(at: 09:00 PM ) +Now you have 6 tasks in the list. +Got it. I've added this task: +[E][ ]100t vs gambit(at: Aug 01 2021) +Now you have 7 tasks in the list. +Got it. I've added this task: +[E][ ]paperex vs bren(at: 08:00 AM Aug 01 2021) +Now you have 8 tasks in the list. +____________________________________________________________ +``` + +View details on adding Event task in program. + +Command Format: `!event` + +Demo: + +``` +____________________________________________________________ +event command requires a timing indicated using "at" [timing] +[timing]: HH:MM YYYY-MM-DD +____________________________________________________________ +``` + +### Setting a task as complete + +Sets tasks in list as done. + +Command Format: `done TASK_INDEX` + +* `TASK_INDEX` cannot be empty. +* `TASK_INDEX` must be a integer. +* Use `,` to seperate multiple tasks. + +Examples: +* `done 1,2,3` + +Demo: + +``` +done 1,2,3 + +____________________________________________________________ +Nice! I've marked this task as done: +[T][X]watch twitch videos +[T][X]watch youtube videos +[D][X]homework1(by: 11:59 PM ) +Here are the tasks in your list: +1. [T][X]watch twitch videos +2. [T][X]watch youtube videos +3. [D][X]homework1(by: 11:59 PM ) +4. [D][ ]homework2(by: Oct 10 2020) +5. [D][ ]homework3(by: 08:00 PM Oct 20 2021) +6. [E][ ]g2 vs en(at: 09:00 PM ) +7. [E][ ]100t vs gambit(at: Aug 01 2021) +8. [E][ ]paperex vs bren(at: 08:00 AM Aug 01 2021) +____________________________________________________________ +``` + +### Delete a Task + +Deletes tasks from list + +Command Format: `delete TASK_INDEX` + +* `TASK_INDEX` cannot be empty. +* `TASK_INDEX` must be an integer. +* Use `,` to seperate multiple tasks. + +Examples: +* `delete 2,4,5` + +Demo: + +``` +delete 2,4,5 + +____________________________________________________________ +Noted. I've removed this task: +[D][ ]homework3(by: 08:00 PM Oct 20 2021) +Now you have 7 tasks in the list. +Noted. I've removed this task: +[D][ ]homework2(by: Oct 10 2020) +Now you have 6 tasks in the list. +Noted. I've removed this task: +[T][X]watch youtube videos +Now you have 5 tasks in the list. +____________________________________________________________ +``` + +### Delete all Task + +Deletes all tasks from list. + +Command Format: `clear` + +Demo: + +``` +clear + +____________________________________________________________ +List Cleared. All tasks removed. +____________________________________________________________ +``` + +### View Tasks + +Lists all task in list. + +Command Format: `list` + +Demo: + +``` +list + +____________________________________________________________ +Here are the tasks in your list: +1. [T][X]watch twitch videos +2. [D][X]homework1(by: 11:59 PM ) +3. [E][ ]g2 vs en(at: 09:00 PM ) +4. [E][ ]100t vs gambit(at: Aug 01 2021) +5. [E][ ]paperex vs bren(at: 08:00 AM Aug 01 2021) +____________________________________________________________ ``` -expected output + +View all list commands in program. + +Command Format: `!list` + +Demo: + ``` +Command Format: `!list` + +!list + +____________________________________________________________ +list displays all tasks +list todo displays all todo tasks +list event displays all event tasks +list deadline displays all deadline tasks +____________________________________________________________ +``` + +#### Viewing Todo Tasks + +Lists all ToDo task in list + +Command Format: `list todo` + +Demo: + +``` +list todo + +____________________________________________________________ +Here are the ToDo tasks in your list: +1. [T][X]watch twitch videos +____________________________________________________________ +``` + +#### Viewing DeadLine Tasks + +Lists all Deadline task in list. + +Command Format: `list deadline` + +Demo: + +``` +list deadline + +____________________________________________________________ +Here are the Deadline tasks in your list: +1. [D][X]homework1(by: 11:59 PM ) +____________________________________________________________ +``` + +#### Viewing Event Tasks + +Lists all Event task in list. + +Command Format: `list event` + +Demo: + +``` +list event + +____________________________________________________________ +Here are the Event tasks in your list: +1. [E][ ]g2 vs en(at: 09:00 PM ) +2. [E][ ]100t vs gambit(at: Aug 01 2021) +3. [E][ ]paperex vs bren(at: 08:00 AM Aug 01 2021) +____________________________________________________________ +``` + +### Finding Task By KeyWords + +Lists all tasks with a specific keyword in its description in list. + +Command Format: `find KEYWORD` + +* `KEYWORD` must not be empty. + +Examples: +* `find g2` + +Demo: + +``` +find g2 + +____________________________________________________________ +Here are the matching tasks in your list: +1. [E][ ]g2 vs en(at: 09:00 PM ) +____________________________________________________________ +``` + +### Finding Task By Date + +Lists all tasks with a specific date in list. + +Command Format: `date DATE` + +* `DATE` must not be empty. +* `DATE` must be in the format of `yyyy-mm-dd`. + +Examples: +* `date 2021-08-01` + +Demo: + +``` +date 2021-08-01 + +____________________________________________________________ +Here are the tasks with matching dates in your list: +1. [E][ ]100t vs gambit(at: Aug 01 2021) +2. [E][ ]paperex vs bren(at: 08:00 AM Aug 01 2021) +____________________________________________________________ +``` + +### Echo User Input + +Prints user input on terminal + +Command Format: `echo INPUT` + +Demo: + +``` +echo hi + +____________________________________________________________ +hi +____________________________________________________________ +``` + +Draws user input on terminial. + +Command Format: `!echo INPUT` + +Examples: +* `!echo hi` + +Demo: + +``` +!echo hi + +____________________________________________________________ +HI + ___ ___ .___ + / | \ | | +/ ~ \| | +\ Y /| | + \___|___/ |___| +____________________________________________________________ +``` + +### Command Guide + +Command Format: `!help` + +Demo: + +``` +!help + +____________________________________________________________ +List of Commands: + echo - Repeat whatever was typed - !echo to repeat in art form + list - Display List - !list for details + todo - Add ToDo Task + event - Add Event Task - !event for details + deadline - Add Deadline Task - !deadline for details + clear - Clear list + find - Find Task With a specific word + date - Find Task with a specific date + bye - Shut Down +____________________________________________________________ +``` + +### Exit Program + +Exits program. + +Command Format: `bye` + +Demo: + +``` +bye + +____________________________________________________________ +____________________________________________________________ +Bye. Hope to see you again soon! +_______________.___.___________ +\______ \__ | |\_ _____/ + | | _// | | | __)_ + | | \\____ | | \ + |________// ______|/_________/ +``` +## Storage + +Duke saves all tasks into a text file `duke.txt` automatically. + +**Do Not manually edit the text file as that might corrupt the data and crash the program.** diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 000000000..c4192631f --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file diff --git a/duke.txt b/duke.txt new file mode 100644 index 000000000..016b62a8a --- /dev/null +++ b/duke.txt @@ -0,0 +1,5 @@ +[T];[X];watch twitch videos +[D];[X];homework1;11:59 +[E];[ ];g2 vs en;09:00 +[E];[ ];100t vs gambit; 2021-08-01 +[E];[ ];paperex vs bren;08:00 2021-08-01 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/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 000000000..2c9a9745c --- /dev/null +++ b/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: duke.Duke + diff --git a/src/main/java/duke/ArtBot/ArtBot.java b/src/main/java/duke/ArtBot/ArtBot.java new file mode 100644 index 000000000..3b1be8242 --- /dev/null +++ b/src/main/java/duke/ArtBot/ArtBot.java @@ -0,0 +1,215 @@ +package duke.ArtBot; + +import duke.ErrorHandling.CommandException; +import duke.ErrorHandling.ErrorStaticString; +import java.util.ArrayList; + +/** + * Convert string into graffiti form and print it + */ +public class ArtBot implements ArtInterface { + + private static final int SIZE_OF_ARRAY = 5; + private final String userInput; + + /** + * Constructor for ArtBot + * Assign string to draw + * + * @param userInput String to be drawn + */ + public ArtBot(String userInput){ + this.userInput = userInput; + } + + /** + * Each Drawn version of a letter take up 5 line + * Convert letter into drawn version of string stored in Logo Class + * Split each drawn version into array of 5 string separated by each line + * + * @param letter Letter to convert into array of string + * @return Array of string representing a letter + */ + private String[] getLogo(String letter){ + String[] letterArt; + switch(letter) { + case "A": + letterArt = Logo.A.split("\n"); + break; + case "B": + letterArt = Logo.B.split("\n"); + break; + case "C": + letterArt = Logo.C.split("\n"); + break; + case "D": + letterArt = Logo.D.split("\n"); + break; + case "E": + letterArt = Logo.E.split("\n"); + break; + case "F": + letterArt = Logo.F.split("\n"); + break; + case "G": + letterArt = Logo.G.split("\n"); + break; + case "H": + letterArt = Logo.H.split("\n"); + break; + case "I": + letterArt = Logo.I.split("\n"); + break; + case "J": + letterArt = Logo.J.split("\n"); + break; + case "K": + letterArt = Logo.K.split("\n"); + break; + case "L": + letterArt = Logo.L.split("\n"); + break; + case "M": + letterArt = Logo.M.split("\n"); + break; + case "N": + letterArt = Logo.N.split("\n"); + break; + case "O": + letterArt = Logo.O.split("\n"); + break; + case "P": + letterArt = Logo.P.split("\n"); + break; + case "Q": + letterArt = Logo.Q.split("\n"); + break; + case "R": + letterArt = Logo.R.split("\n"); + break; + case "S": + letterArt = Logo.S.split("\n"); + break; + case "T": + letterArt = Logo.T.split("\n"); + break; + case "U": + letterArt = Logo.U.split("\n"); + break; + case "V": + letterArt = Logo.V.split("\n"); + break; + case "W": + letterArt = Logo.W.split("\n"); + break; + case "X": + letterArt = Logo.X.split("\n"); + break; + case "Y": + letterArt = Logo.Y.split("\n"); + break; + case "Z": + letterArt = Logo.Z.split("\n"); + break; + case "0": + letterArt = Logo.ZERO.split("\n"); + break; + case "1": + letterArt = Logo.One.split("\n"); + break; + case "2": + letterArt = Logo.Two.split("\n"); + break; + case "3": + letterArt = Logo.THREE.split("\n"); + break; + case "4": + letterArt = Logo.FOUR.split("\n"); + break; + case "5": + letterArt = Logo.FIVE.split("\n"); + break; + case "6": + letterArt = Logo.SIX.split("\n"); + break; + case "7": + letterArt = Logo.SEVEN.split("\n"); + break; + case "8": + letterArt = Logo.EIGHT.split("\n"); + break; + case "9": + letterArt = Logo.NINE.split("\n"); + break; + default: + letterArt = null; + break; + } + return letterArt; + } + + /** + * Convert each letter of string into drawn form + * + * @param inputArrayOfLetter array of Char(letters) + * @return list of string array where each string array is drawn version of a letter + * @throws CommandException if char is anything other than A-Z,0-9 + */ + private ArrayList getLetterInArtForm(String[] inputArrayOfLetter) throws CommandException{ + ArrayList listToStoreLetterInArtForm = new ArrayList<>(); + for(String s:inputArrayOfLetter){ + String[] letterInArtForm = getLogo(s); + if(letterInArtForm == null){ + throw new CommandException(ErrorStaticString.ERROR_ARTBOT_LETTER_NOT_FOUND); + } + listToStoreLetterInArtForm.add(letterInArtForm); + } + return listToStoreLetterInArtForm; + } + + /** + * Merge same index of string in each string array + * First String in First String Array with First String in Second String Array and so on... + * + * @param arrayToMerge list of String Array to merge + * @return String Array of 5 String after all have been merged + */ + private String[] mergeArray(ArrayList arrayToMerge){ + String[] arrayToReturn = new String[5]; + for(int i = 0; i < 5; i++){ + StringBuilder sb = new StringBuilder(); + for (String[] strings : arrayToMerge) { + String temp = strings[i]; + sb.append(temp); + } + arrayToReturn[i] = sb.toString(); + } + return arrayToReturn; + } + + /** + * Print a array of 5 Strings + * + * @param array Array to print + */ + private void printArray(String[] array){ + for(int i = 0; i < SIZE_OF_ARRAY; i++){ + System.out.println(array[i]); + } + } + + /** + * Handle interaction of other classes to echo a string in drawn form + */ + public void drawArt() { + String[] letterArray = userInput.split("(?!^)"); + ArrayList letterInArtFormList = null; + try { + letterInArtFormList = getLetterInArtForm(letterArray); + } catch (CommandException e) { + e.handleException(); + } + String[] mergeLetterHorizontallyArray = mergeArray(letterInArtFormList); + printArray(mergeLetterHorizontallyArray); + } +} diff --git a/src/main/java/duke/ArtBot/ArtInterface.java b/src/main/java/duke/ArtBot/ArtInterface.java new file mode 100644 index 000000000..2169cb880 --- /dev/null +++ b/src/main/java/duke/ArtBot/ArtInterface.java @@ -0,0 +1,7 @@ +package duke.ArtBot; + +import duke.ErrorHandling.CommandException; + +public interface ArtInterface { + void drawArt() throws CommandException; +} diff --git a/src/main/java/duke/ArtBot/Logo.java b/src/main/java/duke/ArtBot/Logo.java new file mode 100644 index 000000000..27b2da165 --- /dev/null +++ b/src/main/java/duke/ArtBot/Logo.java @@ -0,0 +1,201 @@ +package duke.ArtBot; + +/** + * Store Images formed by Strings + */ +public class Logo { + public static final String divider = "____________________________________________________________\n"; + public static final String dividerWithoutNewLine = "____________________________________________________________"; + public static final String logo = " ____ _ \n" + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; + public static final String bye ="_______________.___.___________\n" + + "\\______ \\__ | |\\_ _____/\n" + + " | | _// | | | __)_ \n" + + " | | \\\\____ | | \\\n" + + " |________// ______|/_________/\n"; + public static final String A = " _____ \n" + + " / _ \\ \n" + + " / /_\\ \\ \n" + + "/ | \\\n" + + "\\____|____/\n"; + public static final String B = "__________ \n" + + "\\______ \\\n" + + " | | _/\n" + + " | | \\\n" + + " |________/\n"; + public static final String C = "_________ \n" + + "\\_ ___ \\ \n" + + "/ \\ \\/ \n" + + "\\ \\____\n" + + " \\________/\n"; + public static final String D = "________ \n" + + "\\______ \\ \n" + + " | | \\ \n" + + " | ` \\\n" + + "/_________/\n"; + public static final String E = "___________\n" + + "\\_ _____/\n" + + " | __)_ \n" + + " | \\\n" + + "/_________/"; + public static final String F = "___________\n" + + "\\_ _____/\n" + + " | __) \n" + + " | \\ \n" + + " \\_____/ \n"; + public static final String G = " ________ \n" + + " / _____/ \n" + + "/ \\ ___ \n" + + "\\ \\_\\ \\\n" + + " \\________/"; + public static final String H = " ___ ___ \n" + + " / | \\ \n" + + "/ ~ \\\n" + + "\\ Y /\n" + + " \\___|___/ "; + public static final String I = ".___ \n" + + "| |\n" + + "| |\n" + + "| |\n" + + "|___|"; + public static final String J = " ____.\n" + + " | |\n" + + " | |\n" + + "/\\__| |\n" + + "\\________|"; + public static final String K = " ____ __.\n" + + "| |/ _|\n" + + "| < \n" + + "| | \\ \n" + + "|____|___\\"; + public static final String L = ".____ \n" + + "| | \n" + + "| | \n" + + "| |___ \n" + + "|________\\"; + public static final String M = " _____ \n" + + " / \\ \n" + + " / \\ / \\ \n" + + "/ Y \\\n" + + "\\____|____/"; + public static final String N = " _______ \n" + + " \\ \\ \n" + + " / | \\ \n" + + "/ | \\\n" + + "\\____|____/"; + public static final String O = "________ \n" + + "\\_____ \\ \n" + + " / | \\ \n" + + "/ | \\\n" + + "\\_______ /"; + public static final String P = "__________ \n" + + "\\______ \\\n" + + " | ___/\n" + + " | | \n" + + " |____| "; + public static final String Q = "________ \n" + + "\\_____ \\ \n" + + " / / \\ \\ \n" + + "/ \\_/. \\\n" + + "\\_____\\ \\_/"; + public static final String R = "__________ \n" + + "\\______ \\\n" + + " | _/\n" + + " | | \\\n" + + " |____|___/"; + public static final String S = " _________\n" + + " / _____/\n" + + " \\_____ \\ \n" + + " / \\\n" + + "/_________/"; + public static final String T = "___________\n" + + "\\__ ___/\n" + + " | | \n" + + " | | \n" + + " |____| "; + public static final String U = " ____ ___ \n" + + "| | \\\n" + + "| | /\n" + + "| | / \n" + + "|______/ "; + public static final String V = "____ ____\n" + + "\\ \\ / /\n" + + " \\ Y / \n" + + " \\ / \n" + + " \\___/ "; + public static final String W = " __ __ \n" + + "/ \\ / \\\n" + + "\\ \\/\\/ /\n" + + " \\ / \n" + + " \\__/\\ / "; + public static final String X = "____ ___\n" + + "\\ \\/ /\n" + + " \\ / \n" + + " / \\ \n" + + "/___/\\ \\"; + public static final String Y = "_____.___.\n" + + "\\__ | |\n" + + " / | |\n" + + " \\____ |\n" + + " / ______|"; + public static final String Z = "__________\n" + + "\\____ /\n" + + " / / \n" + + " / /_ \n" + + "/_______ \\"; + public static final String ZERO = "_______ \n" + + "\\ _ \\ \n" + + "/ /_\\ \\ \n" + + "\\ \\_/ \\\n" + + " \\______/"; + public static final String One = " ____ \n" + + "/_ |\n" + + " | |\n" + + " | |\n" + + " |___|"; + public static final String Two = "________ \n" + + "\\_____ \\ \n" + + " / ____/ \n" + + "/ \\ \n" + + "\\________\\"; + public static final String THREE = "________ \n" + + "\\_____ \\ \n" + + " _(__ < \n" + + " / \\\n" + + "/________/"; + public static final String FOUR = " _____ \n" + + " / | | \n" + + " / | |_\n" + + "/ ^ /\n" + + "\\____ |"; + public static final String FIVE = " .________\n" + + " | ____/\n" + + " |____ \\ \n" + + " / \\\n" + + "/________/"; + public static final String SIX = " ________\n" + + " / _____/\n" + + "/ __ \\ \n" + + "\\ |__\\ \\\n" + + " \\_______/"; + public static final String SEVEN = "_________ \n" + + "\\______ \\\n" + + " / /\n" + + " / / \n" + + " /____/ "; + public static final String EIGHT = " ______ \n" + + " / __ \\ \n" + + " > < \n" + + "/ -- \\\n" + + "\\________/"; + public static final String NINE = " ________ \n" + + "/ __ \\\n" + + "\\____ /\n" + + " / / \n" + + " /____/"; + + +} \ No newline at end of file diff --git a/src/main/java/duke/Command/AddDeadlineCommand.java b/src/main/java/duke/Command/AddDeadlineCommand.java new file mode 100644 index 000000000..26c3d7172 --- /dev/null +++ b/src/main/java/duke/Command/AddDeadlineCommand.java @@ -0,0 +1,45 @@ +package duke.Command; + +import duke.ErrorHandling.CommandException; +import duke.ErrorHandling.ErrorStaticString; +import duke.TaskList.TaskList; + +/** + * Represent a command to add deadline task + */ +public class AddDeadlineCommand extends Command{ + + private final TaskList listManager; + + /** + * Constructor for Add Deadline Command + * + * @param taskInput Command input by user to process + * @param listManager Tasklist to interact with list of task + */ + public AddDeadlineCommand(String taskInput, TaskList listManager){ + super(taskInput); + this.listManager = listManager; + } + + /** + * Filter out deadline command, description and date and time of deadline + * Add deadline task to list via TaskList + * + * @throws CommandException if date and time of deadline is empty or if description is empty + */ + @Override + public void executeCommand() throws CommandException { + String taskDescription = taskInput.replaceFirst(COMMAND_ADD_DEADLINE, EMPTY_STRING).trim(); + if(!taskDescription.contains(DEADLINE_DATE)){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_DEADLINE_TIME); + } + int startOfDeadlineDate = taskDescription.indexOf(DEADLINE_DATE); + String deadlineDescription = taskDescription.substring(START_OF_STRING,startOfDeadlineDate).trim(); + if(deadlineDescription.isEmpty()){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_DEADLINE_INPUT); + } + String inputWithoutDescription = taskDescription.replaceFirst(deadlineDescription, EMPTY_STRING).replaceFirst(DEADLINE_DATE,EMPTY_STRING).strip(); + listManager.addDeadline(deadlineDescription, inputWithoutDescription, false); + } +} diff --git a/src/main/java/duke/Command/AddEventCommand.java b/src/main/java/duke/Command/AddEventCommand.java new file mode 100644 index 000000000..6efc7a729 --- /dev/null +++ b/src/main/java/duke/Command/AddEventCommand.java @@ -0,0 +1,45 @@ +package duke.Command; + +import duke.ErrorHandling.CommandException; +import duke.ErrorHandling.ErrorStaticString; +import duke.TaskList.TaskList; + +/** + * Represent a command to add Event task + */ +public class AddEventCommand extends Command{ + + private final TaskList listManager; + + /** + * Constructor for Add Deadline Command + * + * @param taskInput Command input by user to process + * @param listManager Tasklist to interact with list of task + */ + public AddEventCommand(String taskInput, TaskList listManager){ + super(taskInput); + this.listManager = listManager; + } + + /** + * Filter out event command, description and date and time of event + * Add event task to list via TaskList + * + * @throws CommandException if date and time of event is empty or if description is empty + */ + @Override + public void executeCommand() throws CommandException { + String taskDescription = taskInput.replaceFirst(COMMAND_ADD_EVENT, EMPTY_STRING).trim(); + if(!taskDescription.contains(EVENT_TIME)){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_EVENT_TIME); + } + int startOfEventTime = taskDescription.indexOf(EVENT_TIME); + String eventDescription = taskDescription.substring(START_OF_STRING,startOfEventTime).trim(); + if(eventDescription.isEmpty()){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_EVENT_INPUT); + } + String inputWithoutDescription = taskDescription.replaceFirst(eventDescription, EMPTY_STRING).replaceFirst(EVENT_TIME,EMPTY_STRING).strip(); + listManager.addEvent(eventDescription, inputWithoutDescription,false); + } +} diff --git a/src/main/java/duke/Command/AddToDoCommand.java b/src/main/java/duke/Command/AddToDoCommand.java new file mode 100644 index 000000000..5edf6d23f --- /dev/null +++ b/src/main/java/duke/Command/AddToDoCommand.java @@ -0,0 +1,37 @@ +package duke.Command; + +import duke.ErrorHandling.CommandException; +import duke.ErrorHandling.ErrorStaticString; +import duke.TaskList.TaskList; + +/** + * Represent a command to add ToDo task + */ +public class AddToDoCommand extends Command{ + + private final TaskList listManager; + + /** + * Constructor for Add ToDo Command + * + * @param taskInput Command input by user to process + * @param listManager Tasklist to interact with list of task + */ + public AddToDoCommand(String taskInput, TaskList listManager){ + super(taskInput); + this.listManager = listManager; + } + + /** + * Filter out ToDo command and description + * @throws CommandException if description is empty + */ + @Override + public void executeCommand() throws CommandException{ + String removeCommand = taskInput.replaceFirst(COMMAND_ADD_TODO, EMPTY_STRING).trim(); + if(removeCommand.isEmpty()){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_TODO_INPUT); + } + listManager.addTodo(removeCommand,false); + } +} diff --git a/src/main/java/duke/Command/ArtCommand.java b/src/main/java/duke/Command/ArtCommand.java new file mode 100644 index 000000000..0760bc9d1 --- /dev/null +++ b/src/main/java/duke/Command/ArtCommand.java @@ -0,0 +1,35 @@ +package duke.Command; + +import duke.ArtBot.ArtBot; +import duke.ErrorHandling.CommandException; +import duke.ErrorHandling.ErrorStaticString; + +/** + * Represent a command that echo string in graffiti form + */ +public class ArtCommand extends CommandGuide{ + + /** + * Constructor for ArtCommand + * + * @param userInput Command input by user to process + */ + public ArtCommand(String userInput){ + super(userInput); + } + + /** + * Filter out string to echo in graffiti and hand over drawing to artbot class + * + * @throws CommandException if input is empty + */ + public void handleArtCommand() throws CommandException{ + String removeCommand = taskInput.replaceFirst(COMMAND_ECHO_ART,EMPTY_STRING).trim().toUpperCase(); + if(removeCommand.isEmpty()){ + throw new CommandException(ErrorStaticString.ERROR_ARTBOT_INPUT_EMPTY); + } + System.out.println(removeCommand); + ArtBot artBot = new ArtBot(removeCommand); + artBot.drawArt(); + } +} diff --git a/src/main/java/duke/Command/ClearCommand.java b/src/main/java/duke/Command/ClearCommand.java new file mode 100644 index 000000000..f46b707dd --- /dev/null +++ b/src/main/java/duke/Command/ClearCommand.java @@ -0,0 +1,29 @@ +package duke.Command; + +import duke.TaskList.TaskList; + +/** + * Represent a command that clears all task in list + */ +public class ClearCommand extends Command{ + + private final TaskList taskList; + + /** + * Constructor for ClearCommand + * @param taskInput Command input by user to process + * @param taskList Tasklist to interact with list of task + */ + public ClearCommand(String taskInput, TaskList taskList){ + super(taskInput); + this.taskList = taskList; + } + + /** + * Clear list in Tasklist + */ + @Override + public void executeCommand(){ + taskList.clearTask(); + } +} diff --git a/src/main/java/duke/Command/Command.java b/src/main/java/duke/Command/Command.java new file mode 100644 index 000000000..5dd1b8815 --- /dev/null +++ b/src/main/java/duke/Command/Command.java @@ -0,0 +1,66 @@ +package duke.Command; + +import duke.ErrorHandling.CommandException; + +/** + * Represent a general structure for all commands + */ +public abstract class Command { + protected static final String COMMAND_HELP = "!help"; + protected static final String COMMAND_LIST_HELP = "!list"; + protected static final String COMMAND_EVENT_HELP = "!event"; + protected static final String COMMAND_ECHO_ART = "!echo"; + protected static final String COMMAND_DEADLINE_HELP = "!deadline"; + protected static final String COMMAND_VIEW_LIST = "list"; + protected static final String COMMAND_ECHO = "echo"; + protected static final String COMMAND_COMPLETE_TASK = "done"; + protected static final String COMMAND_DATE_TASK = "date"; + protected static final String COMMAND_ADD_TODO = "todo"; + protected static final String COMMAND_ADD_EVENT = "event"; + protected static final String COMMAND_ADD_DEADLINE = "deadline"; + protected static final String COMMAND_DELETE = "delete"; + protected static final String COMMAND_FIND_WORD = "find"; + protected static final String EVENT_TIME = "at "; + protected static final String DEADLINE_DATE = "by "; + protected static final String MESSAGE_TASK_COMPLETE = "Nice! I've marked this task as done: "; + protected static final String DATE_PATTERN = "\\d{4}-\\d{1,2}-\\d{1,2}"; + protected static final String EMPTY_STRING = ""; + protected static final String SEPARATOR = ","; + protected static final int START_OF_STRING = 0; + + + protected static final String MESSAGE_HELP = "List of Commands:\n" + + " echo - Repeat whatever was typed - !echo to repeat in art form\n" + + " list - Display List - !list for details\n" + + " todo - Add ToDo Task\n" + + " event - Add Event Task - !event for details\n" + + " deadline - Add Deadline Task - !deadline for details\n" + + " clear - Clear list\n" + + " find - Find Task With a specific word\n" + + " date - Find Task with a specific date\n" + + " bye - Shut Down"; + protected static final String MESSAGE_LIST_HELP = "list displays all tasks\n" + + "list todo displays all todo tasks\n" + + "list event displays all event tasks\n" + + "list deadline displays all deadline tasks"; + protected static final String MESSAGE_EVENT_HELP = "event command requires a timing indicated using \"at\" [timing]\n" + + "[timing]: HH:MM YYYY-MM-DD"; + protected static final String MESSAGE_DEADLINE_HELP = "deadline command requires a end time indicated using \"by\"[end time]\n" + + "[timing]: HH:MM YYYY-MM-DD"; + + protected String taskInput; + + /** + * Constructor for Command + * @param taskInput Command input to process + */ + public Command(String taskInput){ + this.taskInput = taskInput; + } + + /** + * A function to perform what the command is supposed to do + * @throws CommandException when error encountered for specific command + */ + public abstract void executeCommand() throws CommandException; +} diff --git a/src/main/java/duke/Command/CommandGuide.java b/src/main/java/duke/Command/CommandGuide.java new file mode 100644 index 000000000..b2bb220eb --- /dev/null +++ b/src/main/java/duke/Command/CommandGuide.java @@ -0,0 +1,48 @@ +package duke.Command; + +import duke.ErrorHandling.CommandException; + +/** + * Represent multiple simple one word commands that mainly just print out messages + */ +public class CommandGuide extends Command{ + + /** + * Constructor for CommandGuide + * + * @param taskInput Command input by user + */ + public CommandGuide(String taskInput){ + super(taskInput); + } + + /** + * Print out a fixed message depending on user input or hand over processing of input to ArtCommand + */ + @Override + public void executeCommand(){ + if(taskInput.startsWith(COMMAND_ECHO_ART)){ + ArtCommand artCommand = new ArtCommand(taskInput); + try { + artCommand.handleArtCommand(); + } catch (CommandException e) { + e.handleException(); + } + return; + } + switch(taskInput) { + case COMMAND_HELP: + System.out.println(MESSAGE_HELP); + break; + case COMMAND_LIST_HELP: + System.out.println(MESSAGE_LIST_HELP); + break; + case COMMAND_EVENT_HELP: + System.out.println(MESSAGE_EVENT_HELP); + break; + case COMMAND_DEADLINE_HELP: + System.out.println(MESSAGE_DEADLINE_HELP); + break; + } + } +} diff --git a/src/main/java/duke/Command/DeleteCommand.java b/src/main/java/duke/Command/DeleteCommand.java new file mode 100644 index 000000000..752d6636b --- /dev/null +++ b/src/main/java/duke/Command/DeleteCommand.java @@ -0,0 +1,60 @@ +package duke.Command; + +import duke.ErrorHandling.CommandException; +import duke.ErrorHandling.ErrorStaticString; +import duke.TaskList.TaskList; +import java.util.ArrayList; +import java.util.Collections; + +/** + * Represent a command that remove task from list + */ +public class DeleteCommand extends Command{ + + private final TaskList listManager; + + /** + * Constructor for DeleteCommand + * + * @param userInput Command input by user to process + * @param listManager Tasklist to interact with list of task + */ + public DeleteCommand(String userInput, TaskList listManager){ + super(userInput); + this.listManager = listManager; + } + + /** + * Handle removing multiple task from list + * Extract index of task separated with ",' and put into a list + * Convert index of task into int by parsing + * Sort int list into decreasing order so that the correct task will be deleted + * Removal of task is handled in Tasklist and according to the order by Sorted int list + * + * @throws CommandException if task to delete is empty or if deleting a task that non-existent + */ + @Override + public void executeCommand()throws CommandException { + String removeCommand = taskInput.replaceFirst(COMMAND_DELETE,EMPTY_STRING).trim(); + if(removeCommand.isEmpty()){ + throw new CommandException(ErrorStaticString.ERROR_DELETE_TASK_EMPTY); + } + String[] taskDoneArray = removeCommand.split(SEPARATOR); + ArrayList intArray = new ArrayList<>(); + for (String s: taskDoneArray){ + try { + int taskDoneIndex = Integer.parseInt(s) - 1; + intArray.add(taskDoneIndex); + if (taskDoneIndex > listManager.getListSize() || taskDoneIndex < 0) { + throw new CommandException(ErrorStaticString.ERROR_DELETE_TASK); + } + }catch (NumberFormatException e){ + System.out.println(ErrorStaticString.ERROR_DELETE_INPUT_FORMAT); + } + } + Collections.sort(intArray, Collections.reverseOrder()); + for (Integer i: intArray) { + listManager.deleteTask(i); + } + } +} diff --git a/src/main/java/duke/Command/DoneCommand.java b/src/main/java/duke/Command/DoneCommand.java new file mode 100644 index 000000000..b19139f75 --- /dev/null +++ b/src/main/java/duke/Command/DoneCommand.java @@ -0,0 +1,58 @@ +package duke.Command; + +import duke.ErrorHandling.CommandException; +import duke.ErrorHandling.ErrorStaticString; +import duke.TaskList.TaskList; +import java.util.ArrayList; + +/** + * Represent a command that set task as completed + */ +public class DoneCommand extends Command{ + + private final TaskList listManager; + + /** + * Constructor for DoneCommand + * + * @param userInput Command input by user to process + * @param listManager Tasklist to interact with list of task + */ + public DoneCommand(String userInput, TaskList listManager){ + super(userInput); + this.listManager = listManager; + } + + /** + * Handle setting multiple tasks as completed + * Filter out Command and split index of task into array of string by "," + * Convert index of task in string into integer + * Set each task as done in TaskList class + * + * @throws CommandException if task to set as complete is empty or if task to set as complete does not exist + */ + @Override + public void executeCommand() throws CommandException{ + String removeCommand = taskInput.replaceFirst(COMMAND_COMPLETE_TASK,EMPTY_STRING).trim(); + if(removeCommand.isEmpty()){ + throw new CommandException(ErrorStaticString.ERROR_DONE_TASK_EMPTY); + } + String[] taskDoneArray = removeCommand.split(SEPARATOR); + System.out.println(MESSAGE_TASK_COMPLETE); + ArrayList intArray = new ArrayList<>(); + for (String s: taskDoneArray) { + try { + int taskDoneIndex = Integer.parseInt(s) - 1; + intArray.add(taskDoneIndex); + if (taskDoneIndex > listManager.getListSize() || taskDoneIndex < 0) { + throw new CommandException(ErrorStaticString.ERROR_DONE_TASK_NOT_IN_LIST); + } + }catch (NumberFormatException e){ + System.out.println(ErrorStaticString.ERROR_DONE_INPUT_FORMAT); + } + } + for(Integer i: intArray){ + listManager.completeTask(i, false); + } + } +} diff --git a/src/main/java/duke/Command/EchoCommand.java b/src/main/java/duke/Command/EchoCommand.java new file mode 100644 index 000000000..ef4502cf5 --- /dev/null +++ b/src/main/java/duke/Command/EchoCommand.java @@ -0,0 +1,33 @@ +package duke.Command; + +import duke.ErrorHandling.CommandException; +import duke.ErrorHandling.ErrorStaticString; + +/** + * Represent a command the echo back what was input by user + */ +public class EchoCommand extends Command{ + + /** + * Constructor for Echo Command + * + * @param userInput Command input by user to process + */ + public EchoCommand(String userInput){ + super(userInput); + } + + /** + * Remove command from string and echo back remaining string + * + * @throws CommandException if string to echo is empty + */ + public void executeCommand() throws CommandException { + String removeCommand = taskInput.replaceFirst(COMMAND_ECHO, EMPTY_STRING).trim(); + if(removeCommand.isEmpty()){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_ECHO_INPUT); + } + System.out.println(removeCommand); + } + +} diff --git a/src/main/java/duke/Command/FindDateCommand.java b/src/main/java/duke/Command/FindDateCommand.java new file mode 100644 index 000000000..a7c79d6a4 --- /dev/null +++ b/src/main/java/duke/Command/FindDateCommand.java @@ -0,0 +1,81 @@ +package duke.Command; + +import duke.ErrorHandling.CommandException; +import duke.ErrorHandling.ErrorStaticString; +import duke.TaskList.TaskList; +import java.time.LocalDate; +import java.time.format.DateTimeParseException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Represent a command that filter out task with a specific date and print to user + */ +public class FindDateCommand extends Command{ + + private final TaskList taskList; + + /** + * Constructor for FindDateCommand + * + * @param taskInput Command input by user to process + * @param taskList Tasklist to interact with list of task + */ + public FindDateCommand(String taskInput, TaskList taskList){ + super(taskInput); + this.taskList = taskList; + } + + /** + * Filter out date to search and convert to LocalDate object + * Pass searching of date to TaskList + * + * @throws CommandException if list is empty or if date to search is empty + */ + @Override + public void executeCommand() throws CommandException { + if(taskList.getListSize() == 0){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_LIST); + } + taskInput = taskInput.replaceFirst(COMMAND_DATE_TASK,EMPTY_STRING).trim(); + if(taskInput.isEmpty()){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_DATE_INPUT); + } + try { + LocalDate localDate = LocalDate.parse(convertStringToDate()); + taskList.printDate(localDate); + }catch (DateTimeParseException e ){ + System.out.println(ErrorStaticString.ERROR_DATE_TIME_PARSE); + } + } + + /** + * Find first instance of a date by finding a string in a pattern:4int-2int-2int + * + * @param stringToSearch String that contain date + * @return Null if no date is found or return a matcher object that found date + */ + private Matcher findDate(String stringToSearch){ + Pattern pattern = Pattern.compile(DATE_PATTERN); + Matcher matcher = pattern.matcher(stringToSearch); + if(matcher.find()){ + return matcher; + } + return null; + } + + /** + * Extract string containing date + * + * @return string containing date or Empty String if no date found + */ + private String convertStringToDate(){ + Matcher dateMatcher = findDate(taskInput); + if(dateMatcher != null){ + int startIndexOfDate = dateMatcher.start(); + int endIndexOfDate = dateMatcher.end(); + return taskInput.substring(startIndexOfDate,endIndexOfDate); + } + return EMPTY_STRING; + } +} diff --git a/src/main/java/duke/Command/FindKeywordCommand.java b/src/main/java/duke/Command/FindKeywordCommand.java new file mode 100644 index 000000000..d82dd9e2d --- /dev/null +++ b/src/main/java/duke/Command/FindKeywordCommand.java @@ -0,0 +1,41 @@ +package duke.Command; + +import duke.ErrorHandling.CommandException; +import duke.ErrorHandling.ErrorStaticString; +import duke.TaskList.TaskList; + +/** + * Represent a command that filter out tasks containing a word and print to user + */ +public class FindKeywordCommand extends Command{ + + private final TaskList taskList; + + /** + * Constructor for FindKeywordCommand + * + * @param taskInput Command input by user to process + * @param taskList Tasklist to interact with list of task + */ + public FindKeywordCommand(String taskInput, TaskList taskList){ + super(taskInput); + this.taskList = taskList; + } + + /** + * Filter out the word to search and pass the searching of the word to TaskList + * + * @throws CommandException if list is empty or if word to search is empty + */ + @Override + public void executeCommand() throws CommandException{ + if(taskList.getListSize() == 0){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_LIST); + } + taskInput = taskInput.replaceFirst(COMMAND_FIND_WORD,EMPTY_STRING).trim(); + if(taskInput.isEmpty()){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_WORD_INPUT); + } + taskList.printWord(taskInput); + } +} diff --git a/src/main/java/duke/Command/ListCommand.java b/src/main/java/duke/Command/ListCommand.java new file mode 100644 index 000000000..6e45fcc90 --- /dev/null +++ b/src/main/java/duke/Command/ListCommand.java @@ -0,0 +1,59 @@ +package duke.Command; + +import duke.ErrorHandling.CommandException; +import duke.ErrorHandling.ErrorStaticString; +import duke.TaskList.TaskList; + +/** + * Represent a command that handle showing all tasks to user + */ +public class ListCommand extends Command{ + + private final TaskList listManager; + + /** + * Constructor for ListCommand + * + * @param userInput Command Input by user to process + * @param listManager Tasklist to interact with list of task + */ + public ListCommand(String userInput, TaskList listManager){ + super(userInput); + this.listManager = listManager; + } + + /** + * Process list input to print whole list or list of a certain type + * Remove command by replacing command with empty string + * Remove need for using separators + * + * @throws CommandException if list is empty + */ + public void executeCommand() throws CommandException { + if(listManager.getListSize() == 0){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_LIST); + } + String removeCommand = taskInput.replaceFirst(COMMAND_VIEW_LIST,EMPTY_STRING).trim(); + if(removeCommand.contains(COMMAND_ADD_TODO)){ + try { + listManager.printToDo(); + }catch (CommandException e){ + e.handleException(); + } + }else if(removeCommand.contains(COMMAND_ADD_EVENT)) { + try { + listManager.printEvent(); + }catch (CommandException e){ + e.handleException(); + } + }else if(removeCommand.contains(COMMAND_ADD_DEADLINE)){ + try { + listManager.printDeadline(); + }catch (CommandException e){ + e.handleException(); + } + }else { + listManager.printList(); + } + } +} diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java new file mode 100644 index 000000000..3949b76ff --- /dev/null +++ b/src/main/java/duke/Duke.java @@ -0,0 +1,61 @@ +package duke; + +import duke.ErrorHandling.CommandException; +import duke.Parser.Parser; +import duke.Storage.Storage; +import duke.TaskList.TaskList; +import duke.Ui.Ui; + +/** + * Main Class of the Duke program + * Handle the integration of classes to provide the necessary functions to the user + */ +public class Duke { + + private final TaskList tasks; + private final Ui ui; + + /** + * Constructor for Duke class + * Creates an instance of all the necessary class for the program to run + */ + public Duke(){ + ui = new Ui(); + Storage storage = new Storage(); + tasks = new TaskList(storage.load()); + } + + /** + * Main function of Duke + * Integrate Ui class that handles taking in input of user with + * Parser class that handles response of input + * Loop\ until system is terminated + */ + public void run(){ + ui.Greetings(); + boolean isExit = false; + do{ + try { + String fullCommand = ui.readCommand(); + ui.showLine(); + Parser parser = new Parser(fullCommand, tasks); + isExit = parser.isExit(); + if(!isExit) { + parser.handleInput(); + } + }catch(CommandException e){ + ui.showError(e.getErrorMessage()); + }finally { + ui.showLine(); + } + }while (!isExit); + ui.Farewell(); + } + + /** + * Starts the programs + */ + public static void main(String[] args) { + new Duke().run(); + } +} diff --git a/src/main/java/duke/ErrorHandling/CommandException.java b/src/main/java/duke/ErrorHandling/CommandException.java new file mode 100644 index 000000000..f7c9b65be --- /dev/null +++ b/src/main/java/duke/ErrorHandling/CommandException.java @@ -0,0 +1,34 @@ +package duke.ErrorHandling; + +/** + * Represent error resulting from input of user + */ +public class CommandException extends Exception{ + + private final String errorMessage; + + /** + * Constructor for CommandException + * Assign error message of this instance of exception + * + * @param errorMessage Error message to print + */ + public CommandException(String errorMessage){ + this.errorMessage = errorMessage; + } + + /** + * Print Error Message + */ + public void handleException(){ + System.out.println(errorMessage); + } + + /** + * Get Error Message of error + * @return Error Message + */ + public String getErrorMessage(){ + return errorMessage; + } +} diff --git a/src/main/java/duke/ErrorHandling/ErrorStaticString.java b/src/main/java/duke/ErrorHandling/ErrorStaticString.java new file mode 100644 index 000000000..b19d32eb0 --- /dev/null +++ b/src/main/java/duke/ErrorHandling/ErrorStaticString.java @@ -0,0 +1,47 @@ +package duke.ErrorHandling; + +/** + * Contain Error Messages + */ +public class ErrorStaticString { + public static final String ERROR_EMPTY_INPUT = "☹ OOPS!!! Input cannot be empty."; + public static final String ERROR_UNKNOWN_COMMAND = "☹ OOPS!!! I'm sorry, but I don't know what that means :-(\n" + "" + + "Defaulting to Echo. Type !help to see the list of Commands\n"; + + public static final String ERROR_EMPTY_LIST = "☹ OOPS!!! List is empty. Add tasks to the list."; + public static final String ERROR_EMPTY_TODO_LIST = "☹ OOPS!!! There is no To Do task in list. Add To Do tasks to the list."; + public static final String ERROR_EMPTY_EVENT_LIST = "☹ OOPS!!! There is no Event task in list. Add Events to the list."; + public static final String ERROR_EMPTY_DEADLINE_LIST = "☹ OOPS!!! There is no Deadline task in list. Add Deadlines to the list."; + public static final String ERROR_EMPTY_DATE_SEARCH_LIST = "☹ OOPS!!! No tasks with date found."; + public static final String ERROR_EMPTY_WORD_SEARCH_LIST = "☹ OOPS!!! No tasks with input word found."; + + public static final String ERROR_EMPTY_TODO_INPUT = "☹ OOPS!!! The description of a todo cannot be empty."; + public static final String ERROR_EMPTY_EVENT_INPUT = "☹ OOPS!!! The description of a event cannot be empty."; + public static final String ERROR_EMPTY_DEADLINE_INPUT = "☹ OOPS!!! The description of a deadline cannot be empty."; + public static final String ERROR_EMPTY_ECHO_INPUT = "☹ OOPS!!! The description of a echo cannot be empty."; + + public static final String ERROR_EMPTY_EVENT_TIME = "☹ OOPS!!! The timing of the event not detected, use [at] to indicated date and time."; + public static final String ERROR_EMPTY_DEADLINE_TIME = "☹ OOPS!!! The due date of a deadline not detected, use [by] to indicated date and time."; + + public static final String ERROR_DONE_TASK_NOT_IN_LIST ="☹ OOPS!!! Task done not found in list"; + public static final String ERROR_DONE_TASK_EMPTY ="☹ OOPS!!! Cannot set task as complete without index."; + public static final String ERROR_DONE_INPUT_FORMAT = "☹ OOPS!!! Use only , and numbers to separate task to set as done."; + + public static final String ERROR_DELETE_TASK ="☹ OOPS!!! Cannot remove task that does not exist."; + public static final String ERROR_DELETE_TASK_EMPTY ="☹ OOPS!!! Cannot remove task without index."; + public static final String ERROR_DELETE_INPUT_FORMAT = "☹ OOPS!!! Use only , and numbers to separate task to delete."; + + public static final String ERROR_ARTBOT_LETTER_NOT_FOUND = "☹ OOPS!!! Something went wrong, character input cannot be drawn.\n" + + "Do not input space or symbols."; + public static final String ERROR_ARTBOT_INPUT_EMPTY = "☹ OOPS!!! Input cannot be empty."; + + public static final String ERROR_FILE_MESSAGE_CREATION = "☹ OOPS!!! Something went wrong with creating files"; + public static final String ERROR_FILE_MESSAGE_READING = "☹ OOPS!!! Something went wrong with reading the files"; + public static final String ERROR_FILE_MESSAGE_WRITING = "☹ OOPS!!! Something went wrong with writing to the files"; + public static final String ERROR_FILE_MESSAGE_CLEARING = "☹ OOPS!!! Something went wrong with clearing contents of the files"; + + public static final String ERROR_DATE_TIME_PARSE = "☹ OOPS!!! Something went wrong with reading date or time\n" + + "Input will be read in as String\n" + "Format of Date: YYYY-MM-DD\n" + "Format of Time: HH:MM"; + public static final String ERROR_EMPTY_DATE_INPUT = "☹ OOPS!!! Date Searched cannot be Empty."; + public static final String ERROR_EMPTY_WORD_INPUT = "☹ OOPS!!! Word Searched cannot be Empty."; +} diff --git a/src/main/java/duke/Parser/Parser.java b/src/main/java/duke/Parser/Parser.java new file mode 100644 index 000000000..f81336d68 --- /dev/null +++ b/src/main/java/duke/Parser/Parser.java @@ -0,0 +1,282 @@ +package duke.Parser; + +import duke.Command.*; +import duke.ErrorHandling.CommandException; +import duke.ErrorHandling.ErrorStaticString; +import duke.TaskList.TaskList; +import java.util.Objects; + +/** + * Main Class handling processing of input by user + */ +public class Parser{ + + private static final String COMMAND_VIEW_LIST = "list"; + private static final String COMMAND_ECHO = "echo"; + private static final String COMMAND_COMPLETE_TASK = "done"; + private static final String COMMAND_ADD_TODO = "todo"; + private static final String COMMAND_ADD_EVENT = "event"; + private static final String COMMAND_ADD_DEADLINE = "deadline"; + private static final String COMMAND_DELETE = "delete"; + private static final String COMMAND_EXIT = "bye"; + private static final String COMMAND_DATE_TASK = "date"; + private static final String COMMAND_FIND_WORD = "find"; + private static final String COMMAND_CLEAR_WORD = "clear"; + private static final String EMPTY_STRING = ""; + private static final String COMMAND_GUIDE_INDICATOR = "!"; + private static final String SPLITTER = ";"; + + private String userInput; + private final TaskList listManager; + + /** + * Constructor for Parser + * + * @param userInput User input to process + * @param listManager Tasklist to interact with list of task + */ + public Parser(String userInput, TaskList listManager){ + this.userInput = userInput; + this.listManager = listManager; + } + + /** + * Extract Command Category by checking starting string in input + * + * @param userInput Single line of String containing one command + * @return String representing task category + */ + private String taskCategory(String userInput) { + if (userInput.startsWith(COMMAND_VIEW_LIST)) { + return COMMAND_VIEW_LIST; + } + if (userInput.startsWith(COMMAND_ADD_DEADLINE)) { + return COMMAND_ADD_DEADLINE; + } + if (userInput.startsWith(COMMAND_ADD_TODO)) { + return COMMAND_ADD_TODO; + } + if (userInput.startsWith(COMMAND_ADD_EVENT)) { + return COMMAND_ADD_EVENT; + } + if (userInput.startsWith(COMMAND_COMPLETE_TASK)) { + return COMMAND_COMPLETE_TASK; + } + if (userInput.startsWith(COMMAND_ECHO)) { + return COMMAND_ECHO; + } + if (userInput.startsWith(COMMAND_DELETE)) { + return COMMAND_DELETE; + } + if (userInput.startsWith(COMMAND_DATE_TASK)) { + return COMMAND_DATE_TASK; + } + if(userInput.startsWith(COMMAND_FIND_WORD)){ + return COMMAND_FIND_WORD; + } + if(userInput.startsWith(COMMAND_CLEAR_WORD)){ + return COMMAND_CLEAR_WORD; + } + return null; + } + + /** + * Check if there is ToDo Command in input + * + * @return if ToDo Command is present + */ + private boolean isTodo(){ + if(userInput.contains(COMMAND_ADD_TODO)){ + userInput = userInput.replaceAll(COMMAND_ADD_TODO,SPLITTER + COMMAND_ADD_TODO); + return true; + } + return false; + } + + /** + * Check if there is Event Command in input + * + * @return if Event Command is present + */ + private boolean isEvent(){ + if(userInput.contains(COMMAND_ADD_EVENT)){ + userInput = userInput.replaceAll(COMMAND_ADD_EVENT,SPLITTER + COMMAND_ADD_EVENT); + return true; + } + return false; + } + + /** + * Check if there is DeadLine Command in input + * + * @return if DeadLine Command is present + */ + private boolean isDeadline(){ + if(userInput.contains(COMMAND_ADD_DEADLINE)){ + userInput = userInput.replaceAll(COMMAND_ADD_DEADLINE,SPLITTER + COMMAND_ADD_DEADLINE); + return true; + } + return false; + } + + /** + * Check if Command input is list + * + * @return if Command is list + */ + private boolean isList(){ + return userInput.startsWith(COMMAND_VIEW_LIST); + } + + /** + * Check if Command input is exit + * + * @return if Command is exit + */ + public boolean isExit(){ + return userInput.startsWith(COMMAND_EXIT); + } + + /** + * Does initial checking of input before handing further checking to another function + * Check if input is empty + * Check if input begin with "!" + * + * @throws CommandException if input empty + */ + public void handleInput() throws CommandException{ + if(userInput.isEmpty()){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_INPUT); + } + if(userInput.startsWith(COMMAND_GUIDE_INDICATOR)){ + CommandGuide commandGuide = new CommandGuide(userInput); + commandGuide.executeCommand(); + }else{ + splitInputIfThereMoreThanOneCommand(); + } + } + + /** + * Check if Command is adding task to list + * if adding task to list, split command according to adding command word + * Allows for adding of multiple tasks in one line + * Splitting input into multiple commands if command is for adding in task + */ + private void splitInputIfThereMoreThanOneCommand() { + userInput = userInput.replaceAll(SPLITTER,EMPTY_STRING); + boolean isAddingTask = false; + if (!isList()) { + Boolean isTodo = isTodo(); + Boolean isEvent = isEvent(); + Boolean isDeadline = isDeadline(); + isAddingTask = isTodo || isEvent || isDeadline; + } + if(isAddingTask) { + String[] commandList = userInput.split(SPLITTER); + for (int i = 1; i < commandList.length; i++) { + handleCommand(commandList[i]); + } + }else{ + handleCommand(userInput); + } + } + + /** + * Handle One Command by Creating an instance of Command + * Hand execution of Command to instance of Command + * + * @param inputCommand String representing one Command, and it's relevant input + */ + private void handleCommand(String inputCommand){ + String commandCategory = taskCategory(inputCommand); + try { + switch (Objects.requireNonNull(commandCategory)) { + case COMMAND_VIEW_LIST: + ListCommand listCommand = new ListCommand(inputCommand, listManager); + try { + listCommand.executeCommand(); + } catch (CommandException e) { + e.handleException(); + } + break; + case COMMAND_COMPLETE_TASK: + DoneCommand doneCommand = new DoneCommand(inputCommand, listManager); + try { + doneCommand.executeCommand(); + listManager.printList(); + } catch (CommandException e) { + e.handleException(); + } + break; + case COMMAND_ADD_EVENT: + AddEventCommand addEvent = new AddEventCommand(inputCommand, listManager); + try { + addEvent.executeCommand(); + } catch (CommandException e) { + e.handleException(); + } + break; + case COMMAND_ADD_TODO: + AddToDoCommand addToDo = new AddToDoCommand(inputCommand, listManager); + try { + addToDo.executeCommand(); + } catch (CommandException e) { + e.handleException(); + } + break; + case COMMAND_ADD_DEADLINE: + AddDeadlineCommand addDeadline = new AddDeadlineCommand(inputCommand, listManager); + try { + addDeadline.executeCommand(); + } catch (CommandException e) { + e.handleException(); + } + break; + case COMMAND_ECHO: + EchoCommand echoCommand = new EchoCommand(inputCommand); + try { + echoCommand.executeCommand(); + } catch (CommandException e) { + e.handleException(); + } + break; + case COMMAND_DELETE: + DeleteCommand deleteCommand = new DeleteCommand(inputCommand, listManager); + try { + deleteCommand.executeCommand(); + } catch (CommandException e) { + e.handleException(); + } + break; + case COMMAND_DATE_TASK: + FindDateCommand findDateCommand = new FindDateCommand(inputCommand, listManager); + try { + findDateCommand.executeCommand(); + }catch (CommandException e){ + e.handleException(); + } + break; + case COMMAND_FIND_WORD: + FindKeywordCommand findKeywordCommand = new FindKeywordCommand(inputCommand, listManager); + try { + findKeywordCommand.executeCommand(); + }catch (CommandException e){ + e.handleException(); + } + break; + case COMMAND_CLEAR_WORD: + ClearCommand clearCommand = new ClearCommand(inputCommand, listManager); + clearCommand.executeCommand(); + break; + } + }catch(NullPointerException e){ + System.out.println(ErrorStaticString.ERROR_UNKNOWN_COMMAND); + EchoCommand echoCommand = new EchoCommand(inputCommand); + try { + echoCommand.executeCommand(); + } catch (CommandException echoE) { + echoE.handleException(); + } + } + } +} diff --git a/src/main/java/duke/Storage/FileRead.java b/src/main/java/duke/Storage/FileRead.java new file mode 100644 index 000000000..b3bc9db1d --- /dev/null +++ b/src/main/java/duke/Storage/FileRead.java @@ -0,0 +1,80 @@ +package duke.Storage; + +import duke.ErrorHandling.ErrorStaticString; +import duke.TaskList.TaskList; +import duke.task.Task; +import java.io.File; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.Scanner; + +/** + * Handle reading from file and + * Making sense of String from file + */ +public class FileRead extends Storage{ + + private final File file; + private final TaskList listManager; + private final ArrayList taskList; + + /** + * Constructor for FileRead + * Creates new arraylist to store task from text file + * Create Tasklist to interact with arraylist after processing string in text file + * + * @param file file to read from + */ + public FileRead(File file){ + taskList = new ArrayList<>(); + listManager = new TaskList(taskList); + this.file = file; + } + + /** + * Read from file and store each line into arraylist + * + * @param inputFile file to read from + * @return list of String from file + */ + private ArrayList readFile(File inputFile){ + ArrayList list = new ArrayList<>(); + try { + Scanner scanner = new Scanner(inputFile); + while(scanner.hasNext()){ + list.add(scanner.nextLine()); + } + } catch (FileNotFoundException e) { + System.out.println(ErrorStaticString.ERROR_FILE_MESSAGE_READING); + } + return list; + } + + /** + * Process String from files into task + * + * @return list of task from file + */ + public ArrayList convertFileToTask() { + ArrayList stringList = readFile(file); + int taskIndex = 0; + for (String s : stringList) { + String[] splitString = s.split(FILE_SEPARATOR); + switch (splitString[FILE_TASK_TYPE_POSITION]){ + case FILE_TODO_STATUS: + listManager.addTodo(splitString[FILE_TASK_DESCRIPTION_POSITION], true); + break; + case FILE_EVENT_STATUS: + listManager.addEvent(splitString[FILE_TASK_DESCRIPTION_POSITION],splitString[FILE_TASK_DETAIL_POSITION], true); + break; + case FILE_DEADLINE_STATUS: + listManager.addDeadline(splitString[FILE_TASK_DESCRIPTION_POSITION],splitString[FILE_TASK_DETAIL_POSITION],true); + } + if (splitString[FILE_TASK_COMPLETE_POSITION].equals(FILE_COMPLETE_STATUS)){ + listManager.completeTask(taskIndex, true); + } + taskIndex += 1; + } + return taskList; + } +} diff --git a/src/main/java/duke/Storage/FileWrite.java b/src/main/java/duke/Storage/FileWrite.java new file mode 100644 index 000000000..e3d0251e6 --- /dev/null +++ b/src/main/java/duke/Storage/FileWrite.java @@ -0,0 +1,27 @@ +package duke.Storage; + +import duke.ErrorHandling.ErrorStaticString; +import java.io.IOException; + +/** + * Handles writing string to file + */ +public class FileWrite extends Storage{ + + /** + * Append new string to file or + * Overwrite existing file with new string + * + * @param s String to write to file + * @param isAppend Boolean to indicate whether to overwrite file with new content or append to current file + */ + public void writeToFile(String s, boolean isAppend){ + try { + java.io.FileWriter fileWriter = new java.io.FileWriter(file, isAppend); + fileWriter.write(s); + fileWriter.close(); + } catch (IOException e) { + System.out.println(ErrorStaticString.ERROR_FILE_MESSAGE_WRITING); + } + } +} diff --git a/src/main/java/duke/Storage/Storage.java b/src/main/java/duke/Storage/Storage.java new file mode 100644 index 000000000..b67636afb --- /dev/null +++ b/src/main/java/duke/Storage/Storage.java @@ -0,0 +1,102 @@ +package duke.Storage; + +import duke.ErrorHandling.ErrorStaticString; +import duke.task.Task; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; + +/** + * Handle interaction between Duke and text file + * Create file if file is not found + * Contain function to write to file + * Contain function to read from file + */ +public class Storage { + + protected static final String FILE_NAME = "duke.txt"; + protected static final String FILE_CREATED = "File created: "; + protected static final String FILE_MESSAGE_AT = " at "; + protected static final String FILE_SEPARATOR = ";"; + protected static final String FILE_TODO_STATUS = "[T]"; + protected static final String FILE_DEADLINE_STATUS = "[D]"; + protected static final String FILE_EVENT_STATUS = "[E]"; + protected static final String FILE_COMPLETE_STATUS = "[X]"; + protected static final String EMPTY_STRING = ""; + protected static final int FILE_TASK_TYPE_POSITION = 0; + protected static final int FILE_TASK_COMPLETE_POSITION = 1; + protected static final int FILE_TASK_DESCRIPTION_POSITION = 2; + protected static final int FILE_TASK_DETAIL_POSITION = 3; + + protected File file; + + /** + * Constructor for Storage + * Create duke.txt file if not found + * Print file name and location if created + */ + public Storage(){ + try{ + file = new File(FILE_NAME); + if(file.createNewFile()){ + System.out.println(FILE_CREATED + file.getName() + FILE_MESSAGE_AT + file.getAbsolutePath()); + } + }catch(IOException e){ + System.out.println(ErrorStaticString.ERROR_FILE_MESSAGE_CREATION); + } + } + + /** + * Load task from text file into list + * + * @return list of task from text file + */ + public ArrayList load(){ + FileRead fileReader = new FileRead(file); + return fileReader.convertFileToTask(); + } + + /** + * Write new task at end of text file + * + * @param t Task to write into text file + */ + public void appendTask(Task t){ + StringBuilder stringBuilder = new StringBuilder(); + FileWrite fileWrite = new FileWrite(); + stringBuilder.append(t.toFile()); + stringBuilder.append(System.lineSeparator()); + String stringToWrite = stringBuilder.toString(); + fileWrite.writeToFile(stringToWrite, true); + } + + /** + * Write all tasks in list to text file + * + * @param list list of task to get task to write to text file + */ + public void writeTask(ArrayList list){ + StringBuilder stringBuilder = new StringBuilder(); + for(Task t: list) { + stringBuilder.append(t.toFile()); + stringBuilder.append(System.lineSeparator()); + } + String stringToWrite = stringBuilder.toString(); + FileWrite fileWrite = new FileWrite(); + fileWrite.writeToFile(stringToWrite, false); + } + + /** + * Write empty string to text file to clear its content + */ + public void writeClearTask(){ + try { + FileWriter fileWriter = new FileWriter(file,false); + fileWriter.write(EMPTY_STRING); + fileWriter.close(); + } catch (IOException e) { + System.out.println(ErrorStaticString.ERROR_FILE_MESSAGE_CLEARING); + } + } +} diff --git a/src/main/java/duke/TaskList/TaskList.java b/src/main/java/duke/TaskList/TaskList.java new file mode 100644 index 000000000..a7d2364fc --- /dev/null +++ b/src/main/java/duke/TaskList/TaskList.java @@ -0,0 +1,313 @@ +package duke.TaskList; + +import duke.ErrorHandling.CommandException; +import duke.ErrorHandling.ErrorStaticString; +import duke.Storage.Storage; +import duke.task.Deadline; +import duke.task.Event; +import duke.task.Task; +import duke.task.ToDo; +import java.time.LocalDate; +import java.util.ArrayList; + +/** + * Serve as an interface for Arraylist storing tasks + * Responsible for manipulation and interaction of Arraylist + */ +public class TaskList implements TaskListInterface { + + private static final String MESSAGE_TASK_ADDED = "Got it. I've added this task: "; + private static final String MESSAGE_TASK_IN_LIST = " tasks in the list."; + private static final String MESSAGE_LIST_TASK = "Here are the tasks in your list:"; + private static final String MESSAGE_LIST_TODO = "Here are the ToDo tasks in your list:"; + private static final String MESSAGE_LIST_EVENT = "Here are the Event tasks in your list:"; + private static final String MESSAGE_LIST_DEADLINE = "Here are the Deadline tasks in your list:"; + private static final String MESSAGE_LIST_FIND = "Here are the matching tasks in your list:"; + private static final String MESSAGE_LIST_FIND_DATE = "Here are the tasks with matching dates in your list:"; + private static final String MESSAGE_LIST_CLEAR = "List Cleared. All tasks removed."; + private static final String MESSAGE_TASK_NOW = "Now you have "; + private static final String MESSAGE_DELETE = "Noted. I've removed this task: "; + private static final String MESSAGE_SPACER = ". "; + private static final String EMPTY_STRING = ""; + + private final ArrayList list; + + /** + * Constructor for list class to assign arraylist to be manipulated + * + * @param list Arraylist that store tasks + */ + public TaskList(ArrayList list){ + this.list = list; + } + + /** + * Loops through list of task and print each task + * + * @param listToPrint Arraylist containing tasks to print + */ + private void printer(ArrayList listToPrint){ + for(int i = 0; i < listToPrint.size(); i++){ + int itemIndex= i + 1; + System.out.println(itemIndex + MESSAGE_SPACER + listToPrint.get(i).toString()); + } + } + + /** + * Print all task in list + */ + public void printList(){ + System.out.println(MESSAGE_LIST_TASK); + printer(list); + } + + /** + * Print all task with a specific date + * Sort out task with same date into new list + * Print new list + * + * @param dateSearched Date being search as LocalDate object + * @throws CommandException if no task with date searched was found + */ + public void printDate(LocalDate dateSearched) throws CommandException{ + boolean haveDate = false; + ArrayList listOfTaskWithDate = new ArrayList<>(); + for (Task t: list){ + String date = t.getDate(t.convertStringToDate(), true); + if(!date.equals(EMPTY_STRING)) { + LocalDate localDate = LocalDate.parse(date); + if (dateSearched.equals(localDate)) { + haveDate = true; + listOfTaskWithDate.add(t); + } + } + } + if(!haveDate){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_DATE_SEARCH_LIST); + } + System.out.println(MESSAGE_LIST_FIND_DATE); + printer(listOfTaskWithDate); + } + + /** + * Print all tasks containing a specific string + * Sort out all tasks containing the string to a new list + * Print the new list + * + * @param wordSearch String to be searched + * @throws CommandException if no tasks with the word to be searched was found + */ + public void printWord(String wordSearch) throws CommandException{ + boolean haveWord = false; + ArrayList listOfTaskWithWord = new ArrayList<>(); + for(Task t : list){ + if(t.getDescription().contains(wordSearch)){ + listOfTaskWithWord.add(t); + haveWord = true; + } + } + if(!haveWord){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_WORD_SEARCH_LIST); + } + System.out.println(MESSAGE_LIST_FIND); + printer(listOfTaskWithWord); + } + + /** + * Print all Todo task in list + * Sort out all Todo task into new list + * Print new list + * + * @throws CommandException if no Todo task is found in list + */ + public void printToDo() throws CommandException { + boolean haveToDo = false; + ArrayList listOfToDo = new ArrayList<>(); + for(Task t: list){ + if(t instanceof ToDo){ + haveToDo = true; + listOfToDo.add(t); + } + } + if(!haveToDo){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_TODO_LIST); + } + System.out.println(MESSAGE_LIST_TODO); + printer(listOfToDo); + } + + /** + * Print all Event Task in list + * Sort out Event Task into a new list + * Print new list + * + * @throws CommandException if Event task is not found in list + */ + public void printEvent() throws CommandException{ + boolean haveEvent = false; + ArrayList listOfEvent = new ArrayList<>(); + for (Task t : list) { + if (t instanceof Event) { + haveEvent = true; + listOfEvent.add(t); + } + } + if(!haveEvent){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_EVENT_LIST); + } + System.out.println(MESSAGE_LIST_EVENT); + printer(listOfEvent); + } + + /** + * Print all Deadline task list + * Sort out Deadline task into new list + * Print new list + * + * @throws CommandException if Deadline task is not found in list + */ + public void printDeadline() throws CommandException{ + boolean haveDeadline = false; + ArrayList listOfDeadline = new ArrayList<>(); + for (Task task : list) { + if (task instanceof Deadline) { + haveDeadline = true; + listOfDeadline.add(task); + } + } + if(!haveDeadline){ + throw new CommandException(ErrorStaticString.ERROR_EMPTY_DEADLINE_LIST); + } + System.out.println(MESSAGE_LIST_DEADLINE); + printer(listOfDeadline); + } + + /** + * Print message when task is added + * + * @param t Task added to the list + */ + private void printAddItem(Task t){ + System.out.println(MESSAGE_TASK_ADDED + System.lineSeparator() + t.toString() + System.lineSeparator() + MESSAGE_TASK_NOW + + list.size() + MESSAGE_TASK_IN_LIST); + } + + /** + * Add ToDo task to list + * Print task added + * Write task to text file + * + * @param description Description of the task + * @param isFromFile Boolean variable representing if task added is from text file + */ + public void addTodo(String description, boolean isFromFile){ + Task t = new ToDo(description); + list.add(t); + if(!isFromFile) { + printAddItem(t); + Storage storage = new Storage(); + storage.appendTask(t); + } + } + + /** + * Add Event Task to list + * Print task added + * Write task to text file + * + * @param description Description of event + * @param eventDateTime Date and Time of event in String + * @param isFromFile Boolean variable representing if task added is from text file + */ + public void addEvent (String description, String eventDateTime, boolean isFromFile){ + Task t = new Event(description, eventDateTime); + list.add(t); + if (!isFromFile) { + printAddItem(t); + Storage storage = new Storage(); + storage.appendTask(t); + } + } + + /** + * Add Deadline Task to list + * Print task added + * Write task to text file + * + * @param description Description of deadline + * @param deadlineDateTime Date and Time of deadline in String + * @param isFromFile Boolean variable representing if task added is from text file + */ + public void addDeadline(String description, String deadlineDateTime, boolean isFromFile){ + Task t = new Deadline(description, deadlineDateTime); + list.add(t); + if (!isFromFile) { + printAddItem(t); + Storage storage = new Storage(); + storage.appendTask(t); + } + } + + /** + * Set task as done + * Print out task set as done + * Write whole list to text file to update task as done + * + * @param t Index of Task to set as done + * @param isFromFile Boolean variable representing if task added is from text file + */ + public void completeTask(int t, boolean isFromFile){ + Task doneTask = list.get(t); + doneTask.setDone(); + if (!isFromFile) { + System.out.println(doneTask.toString()); + Storage storage = new Storage(); + storage.writeTask(list); + } + } + + /** + * Remove task from list + * Print task deleted + * Write whole list text file to remove task in text file + * + * @param t Index of Task to delete + */ + public void deleteTask(int t){ + Task removeTask = list.get(t); + list.remove(t); + printDeleteTask(removeTask); + Storage storage = new Storage(); + storage.writeTask(list); + } + + /** + * Print task deleted message + * @param t Task to delete + */ + private void printDeleteTask(Task t){ + System.out.println(MESSAGE_DELETE + System.lineSeparator() + t.toString() + System.lineSeparator() + + MESSAGE_TASK_NOW + list.size() + MESSAGE_TASK_IN_LIST); + } + + /** + * Remove all task in list + * Print list is empty + * Write empty string to text file to clear text file + */ + public void clearTask(){ + System.out.println(MESSAGE_LIST_CLEAR); + list.clear(); + Storage storage = new Storage(); + storage.writeClearTask(); + } + + /** + * To get the number of tasks stored in the arraylist + * + * @return size of the arraylist + */ + public int getListSize(){ + return list.size(); + } +} diff --git a/src/main/java/duke/TaskList/TaskListInterface.java b/src/main/java/duke/TaskList/TaskListInterface.java new file mode 100644 index 000000000..2ba478dbf --- /dev/null +++ b/src/main/java/duke/TaskList/TaskListInterface.java @@ -0,0 +1,20 @@ +package duke.TaskList; + +import duke.ErrorHandling.CommandException; +import java.time.LocalDate; + +public interface TaskListInterface { + void printList() throws CommandException; + void printDate(LocalDate dateSearched) throws CommandException; + void printWord(String wordSearch) throws CommandException; + void printToDo() throws CommandException; + void printEvent() throws CommandException; + void printDeadline() throws CommandException; + void addTodo(String description, boolean isFromFile); + void addEvent(String description, String eventDateTime, boolean isFromFile); + void addDeadline(String description, String deadlineDateTime, boolean isFromFile); + void completeTask(int t, boolean isFromFile); + void deleteTask(int t); + void clearTask(); + int getListSize(); +} diff --git a/src/main/java/duke/Ui/Ui.java b/src/main/java/duke/Ui/Ui.java new file mode 100644 index 000000000..7cbde14bd --- /dev/null +++ b/src/main/java/duke/Ui/Ui.java @@ -0,0 +1,66 @@ +package duke.Ui; + +import duke.ArtBot.Logo; +import java.util.Scanner; + +/** + * Handles Interaction between user and program + * Contains function that greets user when program start + * Contains function that bid farewell to user when program ends + * Contains function that tell user what went wrong when an error is encountered + * Contains function that print a line for readability + */ +public class Ui { + + private static final String MESSAGE_HI = "Hello! I'm Duke\n" + "What can I do for you?\n" + "!help for Command List\n"; + private static final String MESSAGE_BYE = "Bye. Hope to see you again soon!\n"; + + /** + * Called at start of program + * Greet user with message + * Handles message that is printed to user + */ + public void Greetings(){ + System.out.println(Logo.logo + Logo.divider + MESSAGE_HI + Logo.dividerWithoutNewLine); + } + + /** + * Called when program exit + * Print a farewell message to user + * Handles message to be printed to user + */ + public void Farewell(){ + System.out.println(MESSAGE_BYE + Logo.bye); + } + + /** + * Called before input is process and after + * Draw a line before and after response of input + * Improve readability of program + */ + public void showLine(){ + System.out.println(Logo.dividerWithoutNewLine); + } + + /** + * Read in input from user + * Remove Spaces and convert to lower case + * + * @return input from user in String + */ + public String readCommand(){ + Scanner in = new Scanner(System.in); + return in.nextLine().toLowerCase().trim(); + } + + /** + * Called when error encountered + * Print error message to user + * + * @param error Error Message to print + */ + public void showError(String error){ + System.out.println(error); + } +} + diff --git a/src/main/java/duke/task/Deadline.java b/src/main/java/duke/task/Deadline.java new file mode 100644 index 000000000..db1b1baa2 --- /dev/null +++ b/src/main/java/duke/task/Deadline.java @@ -0,0 +1,163 @@ +package duke.task; + +import duke.ErrorHandling.ErrorStaticString; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Represent a DeadLine Task + */ +public class Deadline extends Task{ + + private static final String DATE_SEPARATOR = "-"; + private static final String DATE_SEPARATOR_NEW = "/"; + private static final String TIME_SEPARATOR = ":"; + private static final String TIME_SEPARATOR_NEW = "."; + private static final String TASK_SYMBOL = "[D]"; + private String deadlineDateTime; + + /** + * Constructor for DeadLine Task + * Set description of DeadLine + * Set Date and Time of DeadLine + */ + public Deadline(String description, String deadlineDateTime){ + super(description); + this.deadlineDateTime = deadlineDateTime; + } + + /** + * Find first instance of a date by finding a string in a pattern:4int-2int-2int + * + * @param stringToSearch String that contain date + * @return Null if no date is found or return a matcher object that found date + */ + private Matcher findDate(String stringToSearch){ + Pattern pattern = Pattern.compile(DATE_PATTERN); + Matcher matcher = pattern.matcher(stringToSearch); + if(matcher.find()){ + return matcher; + } + return null; + } + + /** + * Find first instance of time by finding a fixed pattern:2int:2int + * + * @param stringToSearch String that contain time + * @return null if no time found or return matcher object that found time + */ + private Matcher findTime(String stringToSearch){ + Pattern pattern = Pattern.compile(TIME_PATTERN); + Matcher matcher = pattern.matcher(stringToSearch); + if(matcher.find()){ + return matcher; + } + return null; + } + + /** + * Extract string containing date + * + * @return string containing date or Empty String if no date found + */ + @Override + public String convertStringToDate(){ + Matcher dateMatcher = findDate(deadlineDateTime); + if(dateMatcher != null){ + int startIndexOfDate = dateMatcher.start(); + int endIndexOfDate = dateMatcher.end(); + return deadlineDateTime.substring(startIndexOfDate,endIndexOfDate); + } + return EMPTY_STRING; + } + + /** + * Extract string containing Time + * + * @return string containing time or Empty String if no time found + */ + private String convertStringToTime(){ + Matcher timeMatcher = findTime(deadlineDateTime); + if(timeMatcher != null){ + int startIndexOfTime = timeMatcher.start(); + int endIndexOfTime = timeMatcher.end(); + return deadlineDateTime.substring(startIndexOfTime,endIndexOfTime); + } + return EMPTY_STRING; + } + + /** + * Process date in string form and reformat it + * + * @param date String containing date of task + * @param isForFile Boolean variable to decide format of date return + * @return String of reformatted date depending on whether it being printed or save into text file + */ + @Override + public String getDate(String date, boolean isForFile) { + if(!date.isEmpty()) { + try { + LocalDate parseDate = LocalDate.parse(date); + if (isForFile){ + return parseDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + } + return parseDate.format(DateTimeFormatter.ofPattern("MMM dd yyyy")); + }catch (DateTimeParseException e){ + System.out.println(ErrorStaticString.ERROR_DATE_TIME_PARSE); + deadlineDateTime = deadlineDateTime.replaceAll(DATE_SEPARATOR,DATE_SEPARATOR_NEW); + } + } + return EMPTY_STRING; + } + + /** + * Process Time in string form and reformat it + * + * @param time String containing time of task + * @param isForFile Boolean variable to decide format of date return + * @return String of reformatted time depending on whether it being printed or save into text file + */ + private String getTime(String time, boolean isForFile) { + if(!time.isEmpty()) { + try { + LocalTime parseTime = LocalTime.parse(time); + if(isForFile){ + return parseTime.format(DateTimeFormatter.ofPattern("hh:mm")); + } + return parseTime.format(DateTimeFormatter.ofPattern("hh:mm a")); + }catch (DateTimeParseException e){ + System.out.println(ErrorStaticString.ERROR_DATE_TIME_PARSE); + deadlineDateTime = deadlineDateTime.replaceAll(TIME_SEPARATOR,TIME_SEPARATOR_NEW); + } + } + if(getDate(convertStringToDate(),false).equals(EMPTY_STRING)) { + return deadlineDateTime; + } + return EMPTY_STRING; + } + + /** + * Format string to print to user + * + * @return Formatted String containing date and time if present + */ + @Override + public String toString(){ + return TASK_SYMBOL + super.toString() + "(by: " + getTime(convertStringToTime(),false) + " " + getDate(convertStringToDate(),false) + ")"; + } + + /** + * Format string to write to text file + * + * @return Formatted String containing date and time if present + */ + @Override + public String toFile(){ + return TASK_SYMBOL + SEPARATOR + super.toFile() + SEPARATOR + getTime(convertStringToTime(),true) + " " + getDate(convertStringToDate(),true); + } +} diff --git a/src/main/java/duke/task/Event.java b/src/main/java/duke/task/Event.java new file mode 100644 index 000000000..2926ac4ba --- /dev/null +++ b/src/main/java/duke/task/Event.java @@ -0,0 +1,163 @@ +package duke.task; + +import duke.ErrorHandling.ErrorStaticString; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Represent a Event Task + */ +public class Event extends Task{ + + private static final String DATE_SEPARATOR = "-"; + private static final String DATE_SEPARATOR_NEW = "/"; + private static final String TIME_SEPARATOR = ":"; + private static final String TIME_SEPARATOR_NEW = "."; + private static final String TASK_SYMBOL = "[E]"; + private String eventDateTime; + + /** + * Constructor for Event Task + * Set description of event + * Set Date and Time of Event + */ + public Event(String description, String eventDateTime){ + super(description); + this.eventDateTime = eventDateTime; + } + + /** + * Find first instance of a date by finding a string in a pattern:4int-2int-2int + * + * @param stringToSearch String that contain date + * @return Null if no date is found or return a matcher object that found date + */ + private Matcher findDate(String stringToSearch){ + Pattern pattern = Pattern.compile(DATE_PATTERN); + Matcher matcher = pattern.matcher(stringToSearch); + if(matcher.find()){ + return matcher; + } + return null; + } + + /** + * Find first instance of time by finding a fixed pattern:2int:2int + * + * @param stringToSearch String that contain time + * @return null if no time found or return matcher object that found time + */ + private Matcher findTime(String stringToSearch){ + Pattern pattern = Pattern.compile(TIME_PATTERN); + Matcher matcher = pattern.matcher(stringToSearch); + if(matcher.find()){ + return matcher; + } + return null; + } + + /** + * Extract string containing date + * + * @return string containing date or Empty String if no date found + */ + @Override + public String convertStringToDate(){ + Matcher dateMatcher = findDate(eventDateTime); + if(dateMatcher != null){ + int startIndexOfDate = dateMatcher.start(); + int endIndexOfDate = dateMatcher.end(); + return eventDateTime.substring(startIndexOfDate,endIndexOfDate); + } + return EMPTY_STRING; + } + + /** + * Extract string containing Time + * + * @return string containing time or Empty String if no time found + */ + private String convertStringToTime(){ + Matcher timeMatcher = findTime(eventDateTime); + if(timeMatcher != null){ + int startIndexOfTime = timeMatcher.start(); + int endIndexOfTime = timeMatcher.end(); + return eventDateTime.substring(startIndexOfTime,endIndexOfTime); + } + return EMPTY_STRING; + } + + /** + * Process date in string form and reformat it + * + * @param date String containing date of task + * @param isForFile Boolean variable to decide format of date return + * @return String of reformatted date depending on whether it being printed or save into text file + */ + @Override + public String getDate(String date, boolean isForFile) { + if(!date.isEmpty()) { + try { + LocalDate parseDate = LocalDate.parse(date); + if(isForFile){ + return parseDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + } + return parseDate.format(DateTimeFormatter.ofPattern("MMM dd yyyy")); + }catch (DateTimeParseException e){ + System.out.println(ErrorStaticString.ERROR_DATE_TIME_PARSE); + eventDateTime = eventDateTime.replaceAll(DATE_SEPARATOR,DATE_SEPARATOR_NEW); + } + } + return EMPTY_STRING; + } + + /** + * Process Time in string form and reformat it + * + * @param time String containing time of task + * @param isForFile Boolean variable to decide format of date return + * @return String of reformatted time depending on whether it being printed or save into text file + */ + private String getTime(String time, boolean isForFile) { + if(!time.isEmpty()) { + try { + LocalTime parseTime = LocalTime.parse(time); + if(isForFile){ + return parseTime.format(DateTimeFormatter.ofPattern("hh:mm")); + } + return parseTime.format(DateTimeFormatter.ofPattern("hh:mm a")); + }catch (DateTimeParseException e){ + System.out.println(ErrorStaticString.ERROR_DATE_TIME_PARSE); + eventDateTime = eventDateTime.replaceAll(TIME_SEPARATOR,TIME_SEPARATOR_NEW); + } + } + if(getDate(convertStringToDate(),false).equals(EMPTY_STRING)) { + return eventDateTime; + } + return EMPTY_STRING; + } + + /** + * Format string to print to user + * + * @return Formatted String containing date and time if present + */ + @Override + public String toString(){ + return TASK_SYMBOL + super.toString() + "(at: " + getTime(convertStringToTime(),false) + " " + getDate(convertStringToDate(), false) + ")"; + } + + /** + * Format string to write to text file + * + * @return Formatted String containing date and time if present + */ + @Override + public String toFile(){ + return TASK_SYMBOL + SEPARATOR + super.toFile() + SEPARATOR + getTime(convertStringToTime(),true) + " " + getDate(convertStringToDate(),true); + } +} diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java new file mode 100644 index 000000000..bf9cca16d --- /dev/null +++ b/src/main/java/duke/task/Task.java @@ -0,0 +1,88 @@ +package duke.task; + +/** + * Represent a task to be done with a description of task + */ +public class Task implements TaskInterface { + + private static final String COMPLETE_STATUS_ICON = "[X]"; + private static final String INCOMPLETE_STATUS_ICON = "[ ]"; + protected static final String DATE_PATTERN = "\\d{4}-\\d{1,2}-\\d{1,2}"; + protected static final String TIME_PATTERN = "\\d{2}:\\d{2}"; + protected static final String EMPTY_STRING = ""; + protected static final String SEPARATOR = ";"; + + private final String description; + private boolean isDone; + + /** + * Constructor for Task + * Set description of task + * Set tasks to be incomplete by default + * + * @param description description of task + */ + public Task(String description){ + this.description = description; + this.isDone = false; + } + + /** + * Set task as complete + */ + public void setDone(){ + isDone = true; + } + + /** + * Get date of task, Empty String by default + * + * @param date String containing date of task + * @param isForFile Boolean variable to decide format of date return + * @return Empty String by default representing no date in task + */ + public String getDate(String date, boolean isForFile){return EMPTY_STRING;} + + /** + * Convert String into LocalDate + * + * @return Empty String by default representing no date in task + */ + public String convertStringToDate(){return EMPTY_STRING;} + + /** + * Get description of task + * + * @return String description of task + */ + public String getDescription(){ + return description; + } + + /** + * Convert completion status of task into string form + * + * @return String representing if task is done + */ + public String getStatusIcon(){ + return(isDone ? COMPLETE_STATUS_ICON : INCOMPLETE_STATUS_ICON); + } + + /** + * Set Task to print completion status and its description when printed + * + * @return String format of when task is printed + */ + public String toString(){ + return getStatusIcon() + description; + } + + /** + * Set format of task to be saved into text file + * + * @return String format of when task is saved into text file + */ + public String toFile(){ + return getStatusIcon() + SEPARATOR + description; + } +} diff --git a/src/main/java/duke/task/TaskInterface.java b/src/main/java/duke/task/TaskInterface.java new file mode 100644 index 000000000..0875f7d8f --- /dev/null +++ b/src/main/java/duke/task/TaskInterface.java @@ -0,0 +1,11 @@ +package duke.task; + +public interface TaskInterface { + void setDone(); + String getDate(String date, boolean isForFile); + String convertStringToDate(); + String getDescription(); + String getStatusIcon(); + String toString(); + String toFile(); +} diff --git a/src/main/java/duke/task/ToDo.java b/src/main/java/duke/task/ToDo.java new file mode 100644 index 000000000..0f48fb4a8 --- /dev/null +++ b/src/main/java/duke/task/ToDo.java @@ -0,0 +1,38 @@ +package duke.task; + +/** + * Represent one of the task object + */ +public class ToDo extends Task{ + + private static final String TASK_SYMBOL = "[T]"; + + /** + * Constructor for ToDo task + * + * @param description Description of task + */ + public ToDo(String description){ + super(description); + } + + /** + * Format string to print task to user + * + * @return Formatted String + */ + @Override + public String toString() { + return TASK_SYMBOL + super.toString(); + } + + /** + * Format string to save in text file + * + * @return Formatted String + */ + @Override + public String toFile(){ + return TASK_SYMBOL + SEPARATOR + super.toFile(); + } +} diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 657e74f6e..204938f76 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,7 +1,217 @@ -Hello from - ____ _ -| _ \ _ _| | _____ + ____ _ +| _ \ _ _| | _____ | | | | | | | |/ / _ \ | |_| | |_| | < __/ |____/ \__,_|_|\_\___| +____________________________________________________________ +Hello! I'm Duke +What can I do for you? +!help for Command List +____________________________________________________________ +____________________________________________________________ +hi +____________________________________________________________ +____________________________________________________________ +HI + ___ ___ .___ + / | \ | | +/ ~ \| | +\ Y /| | + \___|___/ |___| +____________________________________________________________ +____________________________________________________________ + ☹ OOPS!!! List is empty. Add tasks to the list. +____________________________________________________________ +____________________________________________________________ +List Cleared. All tasks removed. +____________________________________________________________ +____________________________________________________________ +☹ OOPS!!! List is empty. Add tasks to the list. +____________________________________________________________ +____________________________________________________________ +☹ OOPS!!! List is empty. Add tasks to the list. +____________________________________________________________ +____________________________________________________________ +Got it. I've added this task: +[T][ ]watch et livestream +Now you have 1 tasks in the list. +Got it. I've added this task: +[E][ ]watch hankyuu livestream(at: midnight ) +Now you have 2 tasks in the list. +____________________________________________________________ +____________________________________________________________ +Got it. I've added this task: +[T][ ]watch haxxnini livestream +Now you have 3 tasks in the list. +____________________________________________________________ +____________________________________________________________ +☹ OOPS!!! The due date of a deadline not detected, use [by] to indicated date and time. +____________________________________________________________ +____________________________________________________________ +Got it. I've added this task: +[D][ ]reach legend(by: this season ) +Now you have 4 tasks in the list. +____________________________________________________________ +____________________________________________________________ +Got it. I've added this task: +[D][ ]reach gold(by: 08:00 PM ) +Now you have 5 tasks in the list. +____________________________________________________________ +____________________________________________________________ +Got it. I've added this task: +[D][ ]reach silver(by: Oct 10 2020) +Now you have 6 tasks in the list. +____________________________________________________________ +____________________________________________________________ +Got it. I've added this task: +[D][ ]reach bronze(by: 08:00 PM Oct 10 2020) +Now you have 7 tasks in the list. +____________________________________________________________ +____________________________________________________________ +Here are the tasks in your list: +1. [D][ ]reach silver(by: Oct 10 2020) +2. [D][ ]reach bronze(by: 08:00 PM Oct 10 2020) +____________________________________________________________ +____________________________________________________________ +☹ OOPS!!! Something went wrong with reading date or time +Format of Date: YYYY-MM-DD +Format of Time: HH:MM +____________________________________________________________ +____________________________________________________________ +☹ OOPS!!! The timing of the event not detected, use [at] to indicated date and time. +____________________________________________________________ +____________________________________________________________ +Got it. I've added this task: +[E][ ]g2 vs sentinel(at: 10pm ) +Now you have 8 tasks in the list. +____________________________________________________________ +____________________________________________________________ +Got it. I've added this task: +[E][ ]g2 vs sentinel(at: 10:00 PM ) +Now you have 9 tasks in the list. +____________________________________________________________ +____________________________________________________________ +Got it. I've added this task: +[E][ ]g2 vs sentinel(at: 10:00 PM Oct 10 2020) +Now you have 10 tasks in the list. +____________________________________________________________ +____________________________________________________________ +Here are the matching tasks in your list: +1. [E][ ]g2 vs sentinel(at: 10pm ) +2. [E][ ]g2 vs sentinel(at: 10:00 PM ) +3. [E][ ]g2 vs sentinel(at: 10:00 PM Oct 10 2020) +____________________________________________________________ +____________________________________________________________ +☹ OOPS!!! No tasks with input word found. +____________________________________________________________ +____________________________________________________________ +Here are the tasks in your list: +1. [T][ ]watch et livestream +2. [E][ ]watch hankyuu livestream(at: midnight ) +3. [T][ ]watch haxxnini livestream +4. [D][ ]reach legend(by: this season ) +5. [D][ ]reach gold(by: 08:00 PM ) +6. [D][ ]reach silver(by: Oct 10 2020) +7. [D][ ]reach bronze(by: 08:00 PM Oct 10 2020) +8. [E][ ]g2 vs sentinel(at: 10pm ) +9. [E][ ]g2 vs sentinel(at: 10:00 PM ) +10. [E][ ]g2 vs sentinel(at: 10:00 PM Oct 10 2020) +____________________________________________________________ +____________________________________________________________ +Here are the tasks in your list: +1. [T][ ]watch et livestream +2. [T][ ]watch haxxnini livestream +____________________________________________________________ +____________________________________________________________ +Here are the tasks in your list: +1. [D][ ]reach legend(by: this season ) +2. [D][ ]reach gold(by: 08:00 PM ) +3. [D][ ]reach silver(by: Oct 10 2020) +4. [D][ ]reach bronze(by: 08:00 PM Oct 10 2020) +____________________________________________________________ +____________________________________________________________ +Here are the tasks in your list: +1. [E][ ]watch hankyuu livestream(at: midnight ) +2. [E][ ]g2 vs sentinel(at: 10pm ) +3. [E][ ]g2 vs sentinel(at: 10:00 PM ) +4. [E][ ]g2 vs sentinel(at: 10:00 PM Oct 10 2020) +____________________________________________________________ +____________________________________________________________ +Nice! I've marked this task as done: +[T][X]watch et livestream +[E][X]watch hankyuu livestream(at: midnight ) +[T][X]watch haxxnini livestream +Here are the tasks in your list: +1. [T][X]watch et livestream +2. [E][X]watch hankyuu livestream(at: midnight ) +3. [T][X]watch haxxnini livestream +4. [D][ ]reach legend(by: this season ) +5. [D][ ]reach gold(by: 08:00 PM ) +6. [D][ ]reach silver(by: Oct 10 2020) +7. [D][ ]reach bronze(by: 08:00 PM Oct 10 2020) +8. [E][ ]g2 vs sentinel(at: 10pm ) +9. [E][ ]g2 vs sentinel(at: 10:00 PM ) +10. [E][ ]g2 vs sentinel(at: 10:00 PM Oct 10 2020) +____________________________________________________________ +____________________________________________________________ +Noted. I've removed this task: +[E][X]watch hankyuu livestream(at: midnight ) +Now you have 9 tasks in the list. +Noted. I've removed this task: +[T][X]watch et1231 livestream +Now you have 8 tasks in the list. +____________________________________________________________ +____________________________________________________________ +Here are the tasks in your list: +1. [T][X]watch haxxnini livestream +2. [D][ ]reach legend(by: this season ) +3. [D][ ]reach gold(by: 08:00 PM ) +4. [D][ ]reach silver(by: Oct 10 2020) +5. [D][ ]reach bronze(by: 08:00 PM Oct 10 2020) +6. [E][ ]g2 vs sentinel(at: 10pm ) +7. [E][ ]g2 vs sentinel(at: 10:00 PM ) +8. [E][ ]g2 vs sentinel(at: 10:00 PM Oct 10 2020) +____________________________________________________________ +____________________________________________________________ +☹ OOPS!!! Input cannot be empty. +____________________________________________________________ +____________________________________________________________ +☹ OOPS!!! I'm sorry, but I don't know what that means :-( +Defaulting to Echo. Type !help to see the list of Commands +random command +____________________________________________________________ +____________________________________________________________ +List of Commands: + echo - Repeat whatever was typed - !echo to repeat in art form + list - Display List - !list for details + todo - Add ToDo Task + event - Add Event Task - !event for details + deadline - Add Deadline Task - !deadline for details + clear - Clear list + find - Find Task With a specific word + date - Find Task with a specific date + bye - Shut Down +____________________________________________________________ +____________________________________________________________ +list displays all tasks +list todo displays all todo tasks +list event displays all event tasks +list deadline displays all deadline tasks +____________________________________________________________ +____________________________________________________________ +event command requires a timing indicated using "at" [timing] +[timing]: HH:MM YYYY-MM-DD +____________________________________________________________ +____________________________________________________________ +deadline command requires a end time indicated using "by"[end time] +[timing]: HH:MM YYYY-MM-DD +____________________________________________________________ +____________________________________________________________ +____________________________________________________________ +Bye. Hope to see you again soon! +_______________.___.___________ +\______ \__ | |\_ _____/ + | | _// | | | __)_ + | | \\____ | | \ + |________// ______|/_________/ \ No newline at end of file diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e69de29bb..1e1ed6d4a 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -0,0 +1,37 @@ +echo Hi +!echo hi +list +clear +find hi +date 2020-10-10 +todo watch et livestream event watch hankyuu livestream at midnight +todo watch haxxnini livestream +deadline reach radiant +deadline reach legend by this season +deadline reach gold by 20:00 +deadline reach silver by 2020-10-10 +deadline reach bronze by 20:00 2020-10-10 +date 2020-10-10 +date 2020\10\10 +event G2 vs Sentinel +event G2 vs Sentinel at 10pm +event G2 vs Sentinel at 22:00 +event G2 vs Sentinel at 22:00 2020-10-10 +find G2 +find hi +list +list todo +list deadline +list event +done 1,2,3 +delete 1,2 +list + +random command +clear +list +!help +!list +!event +!deadline +bye \ No newline at end of file diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index 087374464..c5ec8c787 100644 --- a/text-ui-test/runtest.bat +++ b/text-ui-test/runtest.bat @@ -4,7 +4,7 @@ REM create bin directory if it doesn't exist if not exist ..\bin mkdir ..\bin REM delete output from previous run -if exist ACTUAL.TXT del ACTUAL.TXT +del ACTUAL.txt REM compile the code into the bin folder javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\*.java @@ -15,7 +15,7 @@ IF ERRORLEVEL 1 ( REM no error here, errorlevel == 0 REM run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT -java -classpath ..\bin Duke < input.txt > ACTUAL.TXT +java -classpath ..\bin Duke < input.txt > ACTUAL.txt REM compare the output to the expected output -FC ACTUAL.TXT EXPECTED.TXT +FC ACTUAL.txt EXPECTED.txt \ No newline at end of file diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh deleted file mode 100644 index c9ec87003..000000000 --- a/text-ui-test/runtest.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -# create bin directory if it doesn't exist -if [ ! -d "../bin" ] -then - mkdir ../bin -fi - -# delete output from previous run -if [ -e "./ACTUAL.TXT" ] -then - rm ACTUAL.TXT -fi - -# compile the code into the bin folder, terminates if error occurred -if ! javac -cp ../src/main/java -Xlint:none -d ../bin ../src/main/java/*.java -then - echo "********** BUILD FAILURE **********" - exit 1 -fi - -# run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT -java -classpath ../bin Duke < input.txt > ACTUAL.TXT - -# convert to UNIX format -cp EXPECTED.TXT EXPECTED-UNIX.TXT -dos2unix ACTUAL.TXT EXPECTED-UNIX.TXT - -# compare the output to the expected output -diff ACTUAL.TXT EXPECTED-UNIX.TXT -if [ $? -eq 0 ] -then - echo "Test result: PASSED" - exit 0 -else - echo "Test result: FAILED" - exit 1 -fi \ No newline at end of file