diff --git a/docs/README.md b/docs/README.md index 8077118eb..da752f906 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,29 +1,142 @@ -# User Guide +# User Guide of Elvin -## Features +This is Elvin, the best personal task management system you will ever use! -### Feature-ABC +## Quick Start -Description of the feature. +1. Ensure that you have `Java 11` installed on your laptop or computer. +2. Download the latest version of the JAR file. +3. Move the file to a folder that you want to use for the application +4. Open up CLI and traverse until you reach your app folder. +5. Type in `java -jar "Elvin.jar"`. +6. The app will create a data folder and text file and it will close again. -### Feature-XYZ +## Features -Description of the feature. +### Add Todo : `todo` -## Usage +Add a todo task to the the list of tasks. -### `Keyword` - Describe action +**Format:** `todo DESCRIPTION` -Describe the action and its outcome. +Example: -Example of usage: +``` +todo borrow book +``` + + +### Add Deadline : `deadline` + +Add a deadline task to the list of task with specific deadline. + +**Format:** `deadline DESCRIPTION /by DEADLINE` + + +Example: + +``` +deadline homework /by Sunday +``` + + +### Add Event : `event` + +Add a event task to the list of task with a time period marked by from and to. + +**Format:** `event DESCRIPTION /from START /to END` + +Example: + +``` +event midterm exam /from 15:00 /to 17:00 +``` + + +### Delete Task : `delete` + +Delete task from list of task based on index. + +**Format:** `delete INDEX` + +Example: + +``` +delete 2 +``` + + +### List Task : `list` + +List all tasks in the list of tasks. + +**Format:** `list` + +Example: -`keyword (optional arguments)` +``` +list +``` + + +### Mark Task : `mark` + +Mark a task as done based on index. + +**Format:** `mark INDEX` + +Example: + +``` +mark 2 +``` + + +### Unmark Task : `unmark` + +Unmark a task as done based on index. + +**Format:** `unmark INDEX` + +Example: + +``` +unmark 5 +``` + + +### Find Task : `find` + +List all tasks that contains the given string + +**Format:** `find DESCRIPTION` + +Example: + +``` +find book +``` + +### EXIT : `bye` + +Exit the app -Expected outcome: +**Format:** `bye` -Description of the outcome. + +Example: ``` -expected output +bye ``` + +### Save Data +The data is saved in the hard disk automatically after any command that changes the data. There is no need to save manually. + +### Edit Data +The data is edited in the hard disk automatically after any command that changes the data. +If you want to edit the data manually, you can use the app to edit it. + +## FAQ +Q: How do I transfer my data to another Computer? +A: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous Elvin folder with same relative location. diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java new file mode 100644 index 000000000..106005371 --- /dev/null +++ b/src/main/java/Deadline.java @@ -0,0 +1,33 @@ +public class Deadline extends Task { + protected String by; + + public Deadline(String description, String by) throws DukeException { + super(description); + if(!by.contains("by ")) { + throw new DukeException("☹ OOPS!!! The description of a deadline must contain \"by\" time."); + }else if(by.replace("by ", "").isBlank()) { + throw new DukeException("☹ OOPS!!! The time of a deadline cannot be empty."); + } + this.by = by.replace("by ", ""); + } + + /** + * Converts the Deadline object into a string. + * + * @return String format of the object. + */ + @Override + public String toString() { + return "[D]" + super.toString() + " (by: " + by + ")"; + } + + /** + * Converts the object into a string to be stored in file. + * + * @return String format of the object to be stored in file. + */ + @Override + public String toFile() { + return "D | " + super.toFile() + " | " + this.by; + } +} 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/DukeException.java b/src/main/java/DukeException.java new file mode 100644 index 000000000..e3a149d74 --- /dev/null +++ b/src/main/java/DukeException.java @@ -0,0 +1,9 @@ +public class DukeException extends Exception { + protected String LINE = "_______________________________________________"; + public DukeException(String message) { + super(message); + System.out.println(LINE); + System.out.println(message); + System.out.println(LINE); + } +} diff --git a/src/main/java/Elvin.java b/src/main/java/Elvin.java new file mode 100644 index 000000000..78564aaa9 --- /dev/null +++ b/src/main/java/Elvin.java @@ -0,0 +1,90 @@ +import java.util.ArrayList; +import java.util.Scanner; + +public class Elvin { + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + TaskList tasks = new TaskList(); + Storage storage = new Storage(); + Ui ui = new Ui(); + Parser parser = new Parser(); + storage.readFromFile(tasks); + ui.printGreet(); + while(true) { + String input = scanner.nextLine(); + ArrayList parsedInput; + try { + parsedInput = parser.parse(input); + } catch(DukeException e) { + continue; + } + if(parsedInput.get(0).equals("bye")) { + break; + } else if(parsedInput.get(0).equals("list")) { + ui.printList(tasks); + } else if(parsedInput.get(0).equals("mark")) { + int index = Integer.parseInt(parsedInput.get(1)); + try { + tasks.markTask(index); + storage.writeToFile(tasks); + ui.printMark(tasks.get(index)); + } catch(IndexOutOfBoundsException e) { + ui.print("☹ OOPS!!! The index is out of bound."); + } + } else if(parsedInput.get(0).equals("unmark")) { + int index = Integer.parseInt(parsedInput.get(1)); + try { + tasks.unmarkTask(index); + storage.writeToFile(tasks); + ui.printUnmark(tasks.get(index)); + } catch(IndexOutOfBoundsException e) { + ui.print("☹ OOPS!!! The index is out of bound."); + } + } else if(parsedInput.get(0).equals("todo")) { + Todo todo; + try { + todo = new Todo(parsedInput.get(1)); + } catch(DukeException e) { + continue; + } + tasks.addTask(todo); + storage.writeToFile(tasks); + ui.printAddition(todo, tasks.size()); + } else if(parsedInput.get(0).equals("deadline")) { + Deadline deadline; + try { + deadline = new Deadline(parsedInput.get(1), parsedInput.get(2)); + } catch (DukeException e) { + continue; + } + tasks.addTask(deadline); + storage.writeToFile(tasks); + ui.printAddition(deadline, tasks.size()); + } else if(parsedInput.get(0).equals("event")) { + Event event; + try { + event = new Event(parsedInput.get(1), parsedInput.get(2), parsedInput.get(3)); + } catch(DukeException e) { + continue; + } + tasks.addTask(event); + storage.writeToFile(tasks); + ui.printAddition(event, tasks.size()); + } else if(parsedInput.get(0).equals("delete")) { + int index = Integer.parseInt(parsedInput.get(1)); + try { + ui.printDeletion(tasks.get(index), tasks.size()-1); + tasks.deleteTask(index); + storage.writeToFile(tasks); + } catch(IndexOutOfBoundsException e) { + ui.print("☹ OOPS!!! The index is out of bound."); + } + } else if(parsedInput.get(0).equals("find")) { + TaskList temp = tasks.find(parsedInput.get(1)); + ui.printFoundTasks(temp); + } + } + scanner.close(); + ui.printExit(); + } +} diff --git a/src/main/java/Event.java b/src/main/java/Event.java new file mode 100644 index 000000000..55bdcbb25 --- /dev/null +++ b/src/main/java/Event.java @@ -0,0 +1,38 @@ +public class Event extends Task { + protected String by; + protected String from; + public Event(String description, String from, String by) throws DukeException { + super(description); + if(!from.contains("from ")) { + throw new DukeException("☹ OOPS!!! The description of a event must contain \"from\" time."); + } else if(!by.contains("to ")) { + throw new DukeException("☹ OOPS!!! The description of a event must contain \"to\" time."); + } else if(from.replace("from ", "").isBlank()){ + throw new DukeException("☹ OOPS!!! The start time of a event cannot be empty."); + } else if(by.replace("to ", "").isBlank()) { + throw new DukeException("☹ OOPS!!! The end time of a event cannot be empty."); + } + this.from = from.replace("from ", ""); + this.by = by.replace("to ", ""); + } + + /** + * Converts the Deadline object into a string. + * + * @return String format of the object. + */ + @Override + public String toString() { + return "[E]" + super.toString() + " (from: " + this.from + " to: " + this.by + ")"; + } + + /** + * Converts the object into a string to be stored in file. + * + * @return String format of the object to be stored in file. + */ + @Override + public String toFile() { + return "E | " + super.toFile() + " | " + this.from + " | " + this.by; + } +} diff --git a/src/main/java/Parser.java b/src/main/java/Parser.java new file mode 100644 index 000000000..ac835699e --- /dev/null +++ b/src/main/java/Parser.java @@ -0,0 +1,59 @@ +import java.util.ArrayList; +public class Parser { + /** + * Parse the input command. + * + * @param input The input command. + * @return The parsed input. + */ + public ArrayList parse(String input) throws DukeException { + ArrayList result = new ArrayList(); + String[] temp = input.split(" "); + result.add(temp[0]); + if(temp[0].equals("todo")) { + try { + result.add(input.substring(5)); + } catch(StringIndexOutOfBoundsException e) { + throw new DukeException("☹ OOPS!!! The description of a todo cannot be empty."); + } + } else if(temp[0].equals("deadline")) { + try { + result.add(input.split(" /")[0].substring(9)); + result.add(input.split(" /")[1]); + } catch(StringIndexOutOfBoundsException e) { + throw new DukeException("☹ OOPS!!! The description of a deadline cannot be empty."); + } catch(ArrayIndexOutOfBoundsException e) { + throw new DukeException("☹ OOPS!!! The description of a deadline should use / mark time."); + } + } else if(temp[0].equals("event")) { + try { + result.add(input.split(" /")[0].substring(6)); + result.add(input.split(" /")[1]); + result.add(input.split(" /")[2]); + } catch(ArrayIndexOutOfBoundsException e) { + throw new DukeException("☹ OOPS!!! The description of a event should use / mark start time and end time."); + } catch(StringIndexOutOfBoundsException e) { + throw new DukeException("☹ OOPS!!! The description of a event cannot be empty."); + } + } else if(temp[0].equals("mark")||temp[0].equals("unmark")||temp[0].equals("delete")) { + try { + result.add(temp[1]); + } catch(ArrayIndexOutOfBoundsException e) { + throw new DukeException("☹ OOPS!!! The index of instruction " + temp[0] + " cannot be empty."); + } + } else if(temp[0].equals("find")) { + try { + result.add(input.substring(5)); + } catch (StringIndexOutOfBoundsException e) { + throw new DukeException("☹ OOPS!!! The description of a find cannot be empty."); + } + } else if(temp[0].equals("bye")||temp[0].equals("list")) { + if(temp.length!=1){ + throw new DukeException("☹ OOPS!!! The instruction " + temp[0] + " cannot have other words."); + } + } else { + throw new DukeException("☹ OOPS!!! I'm sorry, but I don't know what that means :-("); + } + return result; + } +} diff --git a/src/main/java/Storage.java b/src/main/java/Storage.java new file mode 100644 index 000000000..7001eceef --- /dev/null +++ b/src/main/java/Storage.java @@ -0,0 +1,61 @@ +import java.io.FileWriter; +import java.io.IOException; +import java.io.File; +import java.io.FileReader; +import java.util.Scanner; +public class Storage { + /** + * Write the task list to the file + * + * @param tasks The task list to be written to the file + */ + public void writeToFile(TaskList tasks) { + try { + FileWriter fw = new FileWriter("data/duke.txt"); + for (int i=0;i tasks; + public TaskList(){ + this.tasks = new ArrayList(); + } + + /** + * Add the task to the list + * + * @param task The task list to be added to the list + */ + public void addTask(Task task){ + this.tasks.add(task); + } + + /** + * Delete the task with the index + * + * @param index The index of task to be deleted + */ + public void deleteTask(int index) throws IndexOutOfBoundsException{ + this.tasks.remove(index-1); + } + + /** + * Mark the task with the index as done + * + * @param index The index of task to be marked as done + */ + public void markTask(int index) throws IndexOutOfBoundsException{ + this.tasks.get(index-1).markAsDone(); + } + + /** + * Unark the task with the index as done + * + * @param index The index of task to be unmarked as done + */ + public void unmarkTask(int index) throws IndexOutOfBoundsException{ + this.tasks.get(index-1).unmarkAsDone(); + } + + /** + * Find the task with the description + * + * @param description The description of task to be found + * @return The task list with the description + */ + public TaskList find(String description){ + TaskList temp = new TaskList(); + for(Task task : this.tasks){ + if(task.toString().contains(description)){ + temp.addTask(task); + } + } + return temp; + } + + /** + * Get the task with the index + * + * @param index The index of task to be get + * @return The task with the index + */ + public Task get(int index){ + return this.tasks.get(index-1); + } + + /** + * Get the size of the list + * + * @return The size of the list + */ + public int size(){ + return this.tasks.size(); + } +} diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java new file mode 100644 index 000000000..d3759490e --- /dev/null +++ b/src/main/java/Todo.java @@ -0,0 +1,15 @@ +public class Todo extends Task{ + public Todo(String description) throws DukeException{ + super(description); + } + + @Override + public String toString() { + return "[T]" + super.toString(); + } + + @Override + public String toFile() { + return "T | " + super.toFile(); + } +} diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java new file mode 100644 index 000000000..737b7bcef --- /dev/null +++ b/src/main/java/Ui.java @@ -0,0 +1,98 @@ +public class Ui { + protected final static String LINE = "_______________________________________________"; + protected final static String GREET = "Hello! I'm Elwin\n" + "What can I do for you?"; + protected final static String EXIT = "Bye. Hope to see you again soon!"; + protected final static String LIST = "Here are the tasks in your list:"; + protected final static String MARK = "Nice! I've marked this task as done:"; + protected final static String UNMARK = "OK, I've marked this task as not done yet:"; + protected final static String FIND = "Here are the matching tasks in your list:"; + /** + * Print the message + * + * @param message The message to be printed + */ + public void print(String message) { + System.out.println(LINE); + System.out.println(message); + System.out.println(LINE); + } + + /** + * Print the list of tasks + * + * @param tasks the task list + */ + public void printList(TaskList tasks) { + System.out.println(LINE); + System.out.println(LIST); + for(int i = 0; i < tasks.size(); i++){ + System.out.println((i+1) + "." + tasks.get(i+1).toString()); + } + System.out.println(LINE); + } + + /** + * Print the list of found tasks + * + * @param tasks the task list + */ + public void printFoundTasks(TaskList tasks) { + System.out.println(LINE); + System.out.println(FIND); + for(int i = 0; i < tasks.size(); i++){ + System.out.println((i+1) + "." + tasks.get(i+1).toString()); + } + System.out.println(LINE); + } + /** + * Print when the task is marked as done + * + * @param task The task which is marked as done + */ + public void printMark(Task task) { + print(UNMARK+"\n "+task.toString()); + } + + /** + * Print when the task is unmarked as done + * + * @param task The task which is unmarked as done + */ + public void printUnmark(Task task) { + print(MARK+"\n "+task.toString()); + } + + /** + * Print the greet message + */ + public void printGreet() { + print(GREET); + } + + /** + * Print the exit message + */ + public void printExit() { + print(EXIT); + } + + /** + * Print the message when one task is added + * + * @param task The task which is added + * @param size The size of the list + */ + public void printAddition(Task task, int size) { + print("Got it. I've added this task:\n "+task.toString()+"\nNow you have "+size+" tasks in the list."); + } + + /** + * Print the message when one task is deleted + * + * @param task The task which is deleted + * @param size The size of the list + */ + public void printDeletion(Task task, int size) { + print("Noted. I've removed this task:\n "+task.toString()+"\nNow you have "+size+" tasks in the list."); + } +}