diff --git a/docs/README.md b/docs/README.md index 8077118eb..058a1f807 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,29 +1,201 @@ # User Guide +Nova is a command-line (CLI) chatbot application that helps you keep track of your tasks. + ## Features -### Feature-ABC +### Adding tasks to your list + +You can add three different types of tasks: +1. todo +2. deadline +3. event + +### Printing your list of tasks + +You can view the tasks listed currently + +### Mark your tasks + +You can mark/unmark your tasks if you have completed/yet to complete them. + +### Find tasks by keyword -Description of the feature. +You can find tasks that matches a specific keyword in your list -### Feature-XYZ +### Delete your tasks -Description of the feature. +You can delete specific tasks from the list + +### Save your tasks + +Your tasks are saved after you exit the program and loaded once you reopen ## Usage -### `Keyword` - Describe action +### `list` - Displaying the current list of tasks + +Prints out the tasks in the list + +Example of usage: + +`list` + +Expected outcome: + +Nova will acknowledge and display the updated list + +``` +Here are all of your 3 tasks: +1.[T][ ] run +2.[D][ ] eat (by: 14 July 2023 6pm) +3.[E][ ] sleep ( from 1 June to 2 June) +``` + +### `todo` - Adds a new task of type: Todo + +Adds a new task and updates the current number of tasks in the list + +Example of usage: + +`todo {description}` + e.g. {todo read} + +Expected outcome: + +Nova will acknowledge the added task and display the updated number of tasks + +``` +I have added this task: +[T][ ] read +You now have 4 tasks in the list. +``` + +### `deadline` - Adds a new task of type: deadline + +Adds a new task with a deadline and updates the current number of tasks in the list + +Example of usage: + +`deadline {description /by deadline}` +e.g. {deadline eat /by 14 July 2023 6pm} + +Expected outcome: + +Nova will acknowledge the added task and display the updated number of tasks + +``` +I have added this task: +[D][ ] eat (by: 14 July 2023 6pm) +You now have 5 tasks in the list. +``` + +### `event` - Adds a new task of type: event + +Adds a new task regarding an event and updates the current number of tasks in the list + +Example of usage: + +`event {description /from date /to date}` +e.g. {event sleep /from 1 June /to 2 June} + +Expected outcome: + +Nova will acknowledge the added task and display the updated number of tasks + +``` +I have added this task: +[E][ ] sleep ( from 1 June to 2 June) +You now have 6 tasks in the list. +``` + +### `mark` - Mark a specific task by index + +Marks a task according to its index in the list + +Example of usage: + +`mark {index}` + +Expected outcome: + +Nova will acknowledge and display the marked task + +``` +Nice! This task is completed +[D][X] eat (by: 14 July 2023 6pm) +``` + +### `unmark` - Unmarks a specific task by index -Describe the action and its outcome. +Unmarks a task according to its index in the list Example of usage: -`keyword (optional arguments)` +`unmark {index}` Expected outcome: -Description of the outcome. +Nova will acknowledge and display the unmarked task ``` -expected output +Alright, this task has yet to be complete +[D][ ] eat (by: 14 July 2023 6pm) ``` + +### `delete` - Deletes a specific task by index + +Deletes a task according to its index in the list + +Example of usage: + +`delete {index}` + +Expected outcome: + +Nova will acknowledge, delete the unmarked task and display the updated number of tasks + +``` +Noted. I have deleted this task +[D][ ] eat (by: 14 July 2023 6pm) +You now have 1 tasks in the list. +``` + + +### `find` - Deletes a specific task by index + +Find tasks that matches a specific keyword in your list + +Example of usage: + +`find {keyword}` + +Expected outcome: + +Nova will acknowledge, search for the related tasks and display accordingly + +``` +Here are the matching tasks in your list: +1.[D][ ] eat (by: 14 July 2023 6pm) +2.[T][ ] eat +``` + +### `bye` - Exits the application + +Quits the program + +Example of usage: + +`bye` + +Expected outcome: + +Nova will greet you farewell + +``` +Goodbye. Hope to see u again :) +``` + + + + diff --git a/ip.jar b/ip.jar new file mode 100644 index 000000000..f695de9e4 Binary files /dev/null and b/ip.jar differ diff --git a/nova_data/nova_inputs.txt b/nova_data/nova_inputs.txt new file mode 100644 index 000000000..210809b71 --- /dev/null +++ b/nova_data/nova_inputs.txt @@ -0,0 +1,2 @@ +[T][ ] fly +[D][ ] return book (by: Sunday) 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/nova/Deadline.class b/src/main/java/nova/Deadline.class new file mode 100644 index 000000000..23d611231 Binary files /dev/null and b/src/main/java/nova/Deadline.class differ diff --git a/src/main/java/nova/Deadline.java b/src/main/java/nova/Deadline.java new file mode 100644 index 000000000..fb12d644c --- /dev/null +++ b/src/main/java/nova/Deadline.java @@ -0,0 +1,26 @@ +package nova; + +public class Deadline extends Tasks { + + protected String by; + + /** + * Creates a new Deadline object + * + * @param description the description of the task + * @param by the deadline of the task + */ + public Deadline(String description, String by) { + super(description); + this.by = by; + } + + /** + * Returns the string corresponding to the task icon and its deadline + */ + @Override + public String toString() { + return "[D]" + super.toString() + "(by:" + by + ")"; + } + +} diff --git a/src/main/java/nova/Duke.class b/src/main/java/nova/Duke.class new file mode 100644 index 000000000..27b29b1a0 Binary files /dev/null and b/src/main/java/nova/Duke.class differ diff --git a/src/main/java/nova/Event.class b/src/main/java/nova/Event.class new file mode 100644 index 000000000..cf9f9d129 Binary files /dev/null and b/src/main/java/nova/Event.class differ diff --git a/src/main/java/nova/Event.java b/src/main/java/nova/Event.java new file mode 100644 index 000000000..09a06b582 --- /dev/null +++ b/src/main/java/nova/Event.java @@ -0,0 +1,28 @@ +package nova; + +public class Event extends Tasks { + protected String start; + protected String end; + + /** + * Creates a new Event object + * + * @param description the description of the task + * @param start the start time of the event + * @param end the end time of the event + */ + public Event(String description, String start, String end) { + super(description); + this.start = start; + this.end = end; + } + + /** + * Returns the string corresponding to the task icon and the start, end time of + * the event + */ + @Override + public String toString() { + return "[E]" + super.toString() + "(" + "from: " + start + "to: " + end + ")"; + } +} diff --git a/src/main/java/nova/Nova.java b/src/main/java/nova/Nova.java new file mode 100644 index 000000000..405cc8ab3 --- /dev/null +++ b/src/main/java/nova/Nova.java @@ -0,0 +1,76 @@ +package nova; + +import java.io.FileNotFoundException; +import nova.exception.EmptyInputsException; +import nova.exception.ExceptionChecker; + +public class Nova { + + public static void main(String[] args) throws EmptyInputsException { + try { + Ui.greet_user(); + Storage.checkFile(); + } catch (FileNotFoundException e) { + System.out.println("File does not exist."); + } + + String[] command = Parser.getCommand(); + + while (!"bye".equals(command[0])) { + try { + switch (command[0]) { + case "todo": + Tasklist.todo(command[1]); + break; + case "deadline": + String[] d = command[1].split("/by", 2); + String d_description = d[0]; + String d_by = d[1]; + ExceptionChecker.checkEmptyString(d_description); + ExceptionChecker.checkEmptyString(d_by); + Tasklist.deadline(d_description, d_by); + break; + case "event": + String[] er = command[1].split("/from|/to", 3); + String e_description = er[0]; + String e_start = er[1]; + String e_end = er[2]; + ExceptionChecker.checkEmptyString(e_description); + ExceptionChecker.checkEmptyString(e_start); + ExceptionChecker.checkEmptyString(e_end); + Tasklist.event(e_description, e_start, e_end); + break; + case "list": + Tasklist.list(); + break; + case "mark": + Integer m_index = Integer.valueOf(command[1]); + Tasklist.markTask(m_index); + break; + case "unmark": + Integer u_index = Integer.valueOf(command[1]); + Tasklist.unmarkTask(u_index); + break; + case "delete": + Integer d_index = Integer.valueOf(command[1]); + Tasklist.delete(d_index); + break; + case "find": + String keyword = command[1]; + Tasklist.find(keyword); + break; + default: + System.out.println("Command not recognised. Please try again"); + break; + } + } catch (ArrayIndexOutOfBoundsException e) { + System.out.println("Command is incomplete. Please try again!"); + } catch (EmptyInputsException a) { + System.out.println(a.getMessage()); + } + command = Parser.getCommand(); + } + Ui.goodbye_user(); + Tasklist.saveFile(); + } +} \ No newline at end of file diff --git a/src/main/java/nova/Parser.java b/src/main/java/nova/Parser.java new file mode 100644 index 000000000..7f445fca4 --- /dev/null +++ b/src/main/java/nova/Parser.java @@ -0,0 +1,16 @@ +package nova; + +import java.util.Scanner; + +public class Parser { + private static Scanner scan = new Scanner(System.in); + private static String input; + private static String[] command; + + public static String[] getCommand() { + input = scan.nextLine(); + command = input.split(" ", 2); + return command; + } + +} diff --git a/src/main/java/nova/Storage.java b/src/main/java/nova/Storage.java new file mode 100644 index 000000000..a06f3b3ce --- /dev/null +++ b/src/main/java/nova/Storage.java @@ -0,0 +1,33 @@ +package nova; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; + +public class Storage { + + private static final String directoryPath = "nova_data"; + private static final String filePath = "nova_data/nova_inputs.txt"; + + /** + * Creates a new data file and folder if necessary. + */ + public static void findFile() throws IOException { + File directory = new File(directoryPath); + if (!directory.exists()) { + directory.mkdir(); + } + File saveFile = new File(filePath); + if (!saveFile.exists()) { + saveFile.createNewFile(); + } + } + + public static void checkFile() throws FileNotFoundException { + try { + findFile(); + } catch (IOException e) { + System.out.println("Error saving file!"); + } + } +} diff --git a/src/main/java/nova/Tasklist.java b/src/main/java/nova/Tasklist.java new file mode 100644 index 000000000..2b72a578d --- /dev/null +++ b/src/main/java/nova/Tasklist.java @@ -0,0 +1,174 @@ +package nova; + +import java.io.IOException; +import java.io.FileWriter; + +import java.util.ArrayList; + +public class Tasklist { + private static final String filePath = "nova_data/nova_inputs.txt"; + + private static ArrayList listOfTasks = new ArrayList(); + private static int counter = 0; + + public static void print_action() { + System.out.println("\nI have added this task: "); + System.out.println(listOfTasks.get(counter - 1).toString()); + + System.out.println("You now have " + counter + " tasks in the list."); + } + + /** + * Adds a new task of type todo into the list of tasks. + * + * @param description The description of the task. + * @throws IndexOutOfBoundsException If some input parameters are missing + */ + public static void todo(String description) { + try { + Tasks t = new ToDo(description); + listOfTasks.add(t); + counter++; + print_action(); + } catch (IndexOutOfBoundsException e) { + System.out.println(":( There is an error (Index is out of bounds/negative)"); + } + } + + /** + * Adds a new task of type deadline into the list of tasks. + * + * @param description The description of the task. + * @param by The deadline of the task. + * @throws IndexOutOfBoundsException If some input parameters are missing + */ + public static void deadline(String description, String by) { + try { + Deadline d = new Deadline(description, by); + listOfTasks.add(d); + counter++; + Tasklist.print_action(); + } catch (IndexOutOfBoundsException e) { + System.out.println(":( There is an error (Index is out of bounds/negative)"); + } + } + + /** + * Adds a new task of type event into the list of tasks. + * + * @param description The description of the task. + * @param start The starting time of the task. + * @param end The ending time of the task. + * @throws IndexOutOfBoundsException If some parameters are missing + */ + public static void event(String description, String start, String end) { + try { + Event e = new Event(description, start, end); + listOfTasks.add(e); + counter++; + Tasklist.print_action(); + } catch (IndexOutOfBoundsException e) { + System.out.println(":( There is an error (Index is out of bounds/negative)"); + } + + } + + /** + * Prints out the tasks in the list + */ + public static void list() { + if (listOfTasks.isEmpty()) { + System.out.println("There are no tasks listed currently"); + } else { + System.out.println("Here are all of your " + counter + " tasks: "); + for (int i = 0; i < counter; i++) { + System.out.println(i + 1 + "." + listOfTasks.get(i).toString()); + } + } + } + + /** + * Deletes a task according to its index in the list + * + * @param index The index of the task. + * @throws IndexOutOfBoundsException If index provided is not within the list + */ + public static void delete(int index) { + try { + Tasks currentTask = listOfTasks.get(index - 1); + System.out.println("\n"); + System.out.println("Noted. I have deleted this task"); + System.out.println(currentTask.toString()); + listOfTasks.remove(index - 1); + counter--; + System.out.println("You now have " + counter + " tasks in the list."); + } catch (IndexOutOfBoundsException e) { + System.out.println(":( There is an error (Index is out of bounds/negative)"); + } + } + + /** + * Find tasks that matches a specific keyword in you + * + * @param keyword The keyword of the t + * + */ + public static void find(String keyword) { + if (listOfTasks.isEmpty()) { + System.out.println("There are no tasks listed currently"); + } else { + int index = 1; + for (int i = 0; i < listOfTasks.size(); i++) { + if (listOfTasks.get(i).description.contains(keyword)) { + if (index == 1) { + System.out.println("Here are the matching tasks in your list: "); + } + System.out.println(index + "." + listOfTasks.get(i).toString()); + index++; + } + } + } + } + + /** + * Marks a task as done based on the its index in the printed list of tasks. + * + * @param index The index of the task. + */ + public static void markTask(int index) { + try { + listOfTasks.get(index - 1).markAsDone(); + System.out.println("Nice! This task is completed"); + System.out.println(listOfTasks.get(index - 1).toString()); + } catch (IndexOutOfBoundsException e) { + System.out.println(":( There is an error (Index is out of bounds/negative)"); + } + } + + /** + * Marks a task as undone based on the its index in the printed list of tasks. + * + * @param index The index of the task. + */ + public static void unmarkTask(int index) { + try { + listOfTasks.get(index - 1).markAsUnDone(); + System.out.println("Alright, this task has yet to be complete"); + System.out.println(listOfTasks.get(index - 1).toString()); + } catch (IndexOutOfBoundsException e) { + System.out.println(":( There is an error (Index is out of bounds/negative)"); + } + } + + public static void saveFile() { + try { + FileWriter writer = new FileWriter(filePath); + for (int i = 0; i < listOfTasks.size(); i++) { + writer.write(listOfTasks.get(i).toString() + '\n'); + } + writer.close(); + } catch (IOException e) { + System.out.println("Error: Tasks were not saved. Please try again"); + } + } +} \ No newline at end of file diff --git a/src/main/java/nova/Tasks.class b/src/main/java/nova/Tasks.class new file mode 100644 index 000000000..f0dd5548f Binary files /dev/null and b/src/main/java/nova/Tasks.class differ diff --git a/src/main/java/nova/Tasks.java b/src/main/java/nova/Tasks.java new file mode 100644 index 000000000..9b17eda04 --- /dev/null +++ b/src/main/java/nova/Tasks.java @@ -0,0 +1,49 @@ +package nova; + +public class Tasks { + + protected String description; + protected boolean isDone; + + /** + * Constructor for a new Tasks object. Stores a description and status of the + * task. Status of the task is initialised as not done + * + * @param description the description of the new task + */ + public Tasks(String description) { + this.description = description; + this.isDone = false; + } + + /** + * A string represents the task icon + * + * @return the string representing the task icon + */ + public String getStatusIcon() { + return (isDone ? "[X]" : "[ ]"); // mark done task with X + } + + /** + * Set the task status as done + */ + public void markAsDone() { + this.isDone = true; + } + + /** + * Set the task status as not done + */ + public void markAsUnDone() { + this.isDone = false; + } + + /** + * Returns the string corresponding to the task icon and its description + */ + @Override + public String toString() { + return getStatusIcon() + " " + description; + } +} diff --git a/src/main/java/nova/ToDo.class b/src/main/java/nova/ToDo.class new file mode 100644 index 000000000..c4b105083 Binary files /dev/null and b/src/main/java/nova/ToDo.class differ diff --git a/src/main/java/nova/ToDo.java b/src/main/java/nova/ToDo.java new file mode 100644 index 000000000..d483b1244 --- /dev/null +++ b/src/main/java/nova/ToDo.java @@ -0,0 +1,21 @@ +package nova; + +public class ToDo extends Tasks { + + /** + * Creates a new Todo object + * + * @param description the description of the task + */ + public ToDo(String description) { + super(description); + } + + /** + * Returns the string corresponding to the task icon and its description + */ + @Override + public String toString() { + return "[T]" + super.toString(); + } +} diff --git a/src/main/java/nova/Ui.class b/src/main/java/nova/Ui.class new file mode 100644 index 000000000..1293040fc Binary files /dev/null and b/src/main/java/nova/Ui.class differ diff --git a/src/main/java/nova/Ui.java b/src/main/java/nova/Ui.java new file mode 100644 index 000000000..a71ffc9d3 --- /dev/null +++ b/src/main/java/nova/Ui.java @@ -0,0 +1,27 @@ +package nova; + +public class Ui { + public static final String LOGO = " __ _ __ _ _ __\n" + + "( ( \\ / \\ / )( \\ / _\\ \n" + + "/ /( O )\\ \\/ // \\ \n" + + "\\_)__) \\__/ \\__/ \\_/\\_/ \n"; + + public static final String WELCOME_MESSAGE = "Hello! I'm your assistant \n"; + public static final String GREETING_MESAGE = "\nHow can i help u? \n"; + public static final String FAREWELL_MESSAGE = "Goodbye. Hope to see u again :) \n"; + + /** + * Prints a welcome message + */ + public static void greet_user() { + System.out.println(WELCOME_MESSAGE + LOGO + GREETING_MESAGE); + } + + /** + * Prints an exit message + */ + public static void goodbye_user() { + System.out.println(FAREWELL_MESSAGE); + } + +} diff --git a/src/main/java/nova/exception/EmptyInputsException.java b/src/main/java/nova/exception/EmptyInputsException.java new file mode 100644 index 000000000..fab3e55d9 --- /dev/null +++ b/src/main/java/nova/exception/EmptyInputsException.java @@ -0,0 +1,8 @@ +package nova.exception; + +public class EmptyInputsException extends Exception { + @Override + public String getMessage() { + return "One of your inputs is empty. Please try again"; + } +} \ No newline at end of file diff --git a/src/main/java/nova/exception/ExceptionChecker.java b/src/main/java/nova/exception/ExceptionChecker.java new file mode 100644 index 000000000..f76bd5b2f --- /dev/null +++ b/src/main/java/nova/exception/ExceptionChecker.java @@ -0,0 +1,12 @@ +package nova.exception; + +/** + * An exception for the issue when one of the task inputs is missing + */ +public class ExceptionChecker { + public static void checkEmptyString(String string) throws EmptyInputsException { + if (string.isEmpty()) { + throw new EmptyInputsException(); + } + } +}