diff --git a/docs/README.md b/docs/README.md index 8077118eb..d405a0c0d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,29 +1,118 @@ -# User Guide +# GermaBot User Guide + +GermaBot is a task list bot. You can add, delete, find and list the stored tasks. GermaBot recognizes 3 different type +of tasks: Todo tasks, deadline tasks and event tasks. +GermaBot is also capable of saving files to your local hard disk, to the `/src/data/GermaBotData.txt` file. ## Features -### Feature-ABC +> ## Notes about the command format. +> - Words in `UPPER_CASE` are the parameters to be supplied by the user. +> - Extra parameters that do not take in any parameters (such as `list` and `bye`) will be ignored. +> e.g. if the input is `list 123`, it will be interpreted as `list`. + + + +### Adding Todo tasks : `todo` +Adds a todo task to the task list. -Description of the feature. +Format: `todo TASK_NAME` -### Feature-XYZ +### Adding Deadline tasks : `deadline` +Adds a deadline task to the task list. -Description of the feature. +Format: `deadline TASK_NAME /by DEADLINE` + +Example: +``` +deadline Read a book /by 4th July +``` -## Usage +### Adding Event tasks : `event` +Adds an event task to the task list. -### `Keyword` - Describe action +Format: `event TASK_NAME /from STARTDATE /to ENDDATE` -Describe the action and its outcome. +Example: +``` +event Dad's party /from 6pm /to 12am +``` -Example of usage: +### Listing all tasks : `list` +Shows the list of the current tasks, including the details of the task. -`keyword (optional arguments)` +Example input: +``` +list +``` +Example output: +``` +Gotcha! Here are your tasks: +1. [T][X] Read a book +2. [D][ ] Finish IP (by: 23rd November) +3. [E][X] Dad's birthday party (from: 6pm to: 12am) +``` + +### Deleting tasks : `delete` +Deletes a task from the task list. + +Format: `delete TASK_NUMBER` + +Example: +``` +delete 2 +``` +Example output: +``` +Okay! I've removed this task from your To Do List: +[D][X] Finish IP (by: tmr) +Now you have, let me count... 4 items left in your To Do List! +``` -Expected outcome: +### Finding tasks : `find` +Finds a task containing certain keywords. -Description of the outcome. +Format: `find KEYWORDS` +Example: ``` -expected output +find book ``` +Example output: +``` +Gotcha! Finding tasks containing 'book'... +1. [T][X] Read a book +``` + +### Marking tasks as done : `mark` +Marks a task as done. + +Format: `mark TASK_NUMBER` + +Example: +``` +mark 2 +``` +Example output: +``` +Good job! I'll mark this task as done: [X] Finish IP +``` + +### Marking tasks as undone : `unmark` +Marks a task as undone. + +Format: `unmark TASK_NUMBER` + +Example: +``` +unmark 1 +``` +Example output: +``` +Aww, not done? Okay, I'll mark this task as undone: [ ] Read a book +``` + +### Exiting the program: `bye` +Exits the program. + +Format: `bye` diff --git a/src/data/GermaBotData.txt b/src/data/GermaBotData.txt new file mode 100644 index 000000000..0739da9ee --- /dev/null +++ b/src/data/GermaBotData.txt @@ -0,0 +1,3 @@ +T | 1 | Read a book +D | 0 | Finish IP | tmr +E | 1 | Do NOT drop out (IMPOSSIBLE) | now | end of semester diff --git a/src/main/java/DataHandling/LoadData.java b/src/main/java/DataHandling/LoadData.java new file mode 100644 index 000000000..c6e7c1370 --- /dev/null +++ b/src/main/java/DataHandling/LoadData.java @@ -0,0 +1,121 @@ +package DataHandling; + +import Exceptions.FileReadException; +import Exceptions.LoadFileException; +import GermaBot.UI; +import Tasks.*; + +import java.io.FileNotFoundException; +import java.util.Scanner; +import java.util.ArrayList; +import java.io.File; + +/** + * The LoadData class handles loading tasks from a file into the program. + */ +public class LoadData { + static ArrayList toDoList = new ArrayList<>(); + static int counter = 0; + + /** + * Loads a ToDo task from a string description and adds it to the task list. + * + * @param description The description of the ToDo task. + * @throws LoadFileException If the description is empty. + */ + public static void loadToDo(String description) throws LoadFileException { + if (description.isEmpty()) { + throw new LoadFileException(); + } + toDoList.add(new ToDo(description)); + } + + /** + * Loads a Deadline task from a string description and adds it to the task list. + * + * @param description The description of the Deadline task, including the deadline date. + * @throws LoadFileException If the description or deadline date is empty or invalid. + */ + public static void loadDeadline(String description) throws LoadFileException { + String[] deadlineDescription = description.split("\\|"); + String task = deadlineDescription[0].trim(); + String by = deadlineDescription[1].trim(); + if (task.isBlank() || by.isBlank()) { + throw new LoadFileException(); + } + toDoList.add(new Deadline(task, by)); + } + + /** + * Loads an Event task from a string description and adds it to the task list. + * + * @param description The description of the Event task, including the start and end dates. + * @throws LoadFileException If the description or dates are empty or invalid. + */ + public static void loadEvent(String description) throws LoadFileException { + String[] eventDescription = description.split("\\|"); + String task = eventDescription[0].trim(); + String from = eventDescription[1].trim(); + String by = eventDescription[2].trim(); + if (task.isBlank() || from.isBlank() || by.isBlank()) { + throw new LoadFileException(); + } + toDoList.add(new Event(task, from, by)); + } + + /** + * Loads tasks from a file into the program. + * + * @return An ArrayList of tasks loaded from the file. + * @throws FileNotFoundException If the file is not found. + * @throws FileReadException If there is an error reading the file, such as if the file is in an invalid format. + */ + public static ArrayList loadFile() throws FileNotFoundException, FileReadException { + File data = new File("src/data/GermaBotData.txt"); + Scanner fileInput = new Scanner(data); + do { + String task = fileInput.nextLine(); + if (task.trim().isEmpty()) { + throw new FileReadException(); + } + counter++; + char type = task.charAt(0); + String description = task.substring(8); + boolean isCompleted = task.charAt(4) != '0'; + if (type == 'T') { + try { + loadToDo(description); + } catch (LoadFileException e) { + UI.printLoadFileException(); + } + } else if (type == 'D') { + try { + loadDeadline(description); + } catch (LoadFileException e) { + UI.printLoadFileException(); + } + } else if (type == 'E') { + try { + loadEvent(description); + } catch (LoadFileException e) { + UI.printLoadFileException(); + } + } else { + break; + } + int idxToMark = toDoList.size() - 1; + toDoList.get(idxToMark).setDone(isCompleted); + } while (fileInput.hasNext()); + fileInput.close(); + return toDoList; + } + + /** + * Returns the number of tasks loaded from the file. + * + * @return The number of tasks. + */ + public static int getCounter() { + return counter; + } +} diff --git a/src/main/java/DataHandling/SaveData.java b/src/main/java/DataHandling/SaveData.java new file mode 100644 index 000000000..f68daa705 --- /dev/null +++ b/src/main/java/DataHandling/SaveData.java @@ -0,0 +1,54 @@ +package DataHandling; + +import Tasks.*; + +import java.io.FileWriter; +import java.io.IOException; + +/** + * The SaveData class handles saving tasks to a file. + */ +public class SaveData { + private static final String filePath = "src/data/GermaBotData.txt"; + + /** + * Saves a ToDo task to the file. + * + * @param toDoTask The ToDo task to be saved. + * @param taskType The type of the task ('T' for ToDo). + * @throws IOException If there is an error writing to the file. + */ + public static void addTodoToFile(ToDo toDoTask, char taskType) throws IOException { + FileWriter writer = new FileWriter(filePath, true); + writer.write("T | " + (toDoTask.isDone() ? "1" : "0") + " | " + toDoTask.getDescription() + System.lineSeparator()); + writer.close(); + } + + /** + * Saves a Deadline task to the file. + * + * @param deadlineTask The Deadline task to be saved. + * @param taskType The type of the task ('D' for Deadline). + * @throws IOException If there is an error writing to the file. + */ + public static void addDeadlineToFile(Deadline deadlineTask, char taskType) throws IOException { + FileWriter writer = new FileWriter(filePath, true); + writer.write("D | " + (deadlineTask.isDone() ? "1" : "0") + " | " + deadlineTask.getDescription() + + " | " + deadlineTask.getBy() + System.lineSeparator()); + writer.close(); + } + + /** + * Saves an Event task to the file. + * + * @param eventTask The Event task to be saved. + * @param taskType The type of the task ('E' for Event). + * @throws IOException If there is an error writing to the file. + */ + public static void addEventToFile(Event eventTask, char taskType) throws IOException { + FileWriter writer = new FileWriter(filePath, true); + writer.write("E | " + (eventTask.isDone() ? "1" : "0") + " | " + eventTask.getDescription() + + " | " + eventTask.getFrom() + " | " + eventTask.getTo() + System.lineSeparator()); + writer.close(); + } +} 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/Exceptions/EmptyTaskException.java b/src/main/java/Exceptions/EmptyTaskException.java new file mode 100644 index 000000000..bc2cd15ab --- /dev/null +++ b/src/main/java/Exceptions/EmptyTaskException.java @@ -0,0 +1,4 @@ +package Exceptions; + +public class EmptyTaskException extends Exception{ +} diff --git a/src/main/java/Exceptions/FileReadException.java b/src/main/java/Exceptions/FileReadException.java new file mode 100644 index 000000000..8a7adda56 --- /dev/null +++ b/src/main/java/Exceptions/FileReadException.java @@ -0,0 +1,4 @@ +package Exceptions; + +public class FileReadException extends Exception{ +} diff --git a/src/main/java/Exceptions/LoadFileException.java b/src/main/java/Exceptions/LoadFileException.java new file mode 100644 index 000000000..2af6e102f --- /dev/null +++ b/src/main/java/Exceptions/LoadFileException.java @@ -0,0 +1,4 @@ +package Exceptions; + +public class LoadFileException extends Exception { +} diff --git a/src/main/java/Exceptions/MissingDeadlineException.java b/src/main/java/Exceptions/MissingDeadlineException.java new file mode 100644 index 000000000..c32f8ac8e --- /dev/null +++ b/src/main/java/Exceptions/MissingDeadlineException.java @@ -0,0 +1,4 @@ +package Exceptions; + +public class MissingDeadlineException extends Exception{ +} diff --git a/src/main/java/Exceptions/MissingStartDateException.java b/src/main/java/Exceptions/MissingStartDateException.java new file mode 100644 index 000000000..13d6b8714 --- /dev/null +++ b/src/main/java/Exceptions/MissingStartDateException.java @@ -0,0 +1,4 @@ +package Exceptions; + +public class MissingStartDateException extends Exception{ +} diff --git a/src/main/java/Exceptions/TaskNotFoundException.java b/src/main/java/Exceptions/TaskNotFoundException.java new file mode 100644 index 000000000..3002f95d9 --- /dev/null +++ b/src/main/java/Exceptions/TaskNotFoundException.java @@ -0,0 +1,4 @@ +package Exceptions; + +public class TaskNotFoundException extends Exception{ +} diff --git a/src/main/java/Exceptions/UnknownInputException.java b/src/main/java/Exceptions/UnknownInputException.java new file mode 100644 index 000000000..634325351 --- /dev/null +++ b/src/main/java/Exceptions/UnknownInputException.java @@ -0,0 +1,4 @@ +package Exceptions; + +public class UnknownInputException extends Exception{ +} diff --git a/src/main/java/GermaBot/Logic.java b/src/main/java/GermaBot/Logic.java new file mode 100644 index 000000000..0892f8e69 --- /dev/null +++ b/src/main/java/GermaBot/Logic.java @@ -0,0 +1,264 @@ +package GermaBot; + +import Exceptions.*; +import Tasks.Deadline; +import Tasks.Event; +import Tasks.Task; +import Tasks.ToDo; + +import java.io.IOException; +import java.util.ArrayList; + + +/** + * Contains the main logic for handling user commands in the GermaBot application. + */ +public class Logic { + + public static TaskManager taskManager = new TaskManager(); + + /** + * Returns the index of a task in the arraylist that is specified in the input. + * @param input The user input. + * @return The index parsed from the input. + * @throws IllegalArgumentException If the input format is invalid, such as if there is no index provided. + */ + public static int getIdx(String input) throws IllegalArgumentException { + int spaceIndex = input.indexOf(" "); + if (spaceIndex == -1 || spaceIndex == input.length() - 1) { + throw new IllegalArgumentException(); + } + return Integer.parseInt(input.substring(spaceIndex + 1)) - 1; + } + + /** + * Creates a new ToDo task based on user input and adds it to the task list. + * + * @param toDoList The list of tasks in the form of an ArrayList. + * @param input The user input containing the task description. + * @throws EmptyTaskException If the task description is empty. + * @throws IOException If there is an error saving the task to the file. + */ + public static void createTodo(ArrayList toDoList, String input) throws EmptyTaskException, IOException { + int idxBetweenTodoAndDescription = 5; + String toDoTask = input.substring(input.indexOf("todo ") + idxBetweenTodoAndDescription); + if (toDoTask.isBlank()) { + throw new EmptyTaskException(); + } + taskManager.addTodo(toDoList, toDoTask); + Task.setNoOfTask(Task.getNoOfTask() + 1); + Storage.saveTodo(new ToDo(toDoTask), 'T'); + UI.printCreateTodoMessage(toDoTask); + } + + /** + * Creates a new Deadline task based on user input and adds it to the task list. + * + * @param toDoList The list of tasks in the form of an ArrayList. + * @param input The user input containing the task description and deadline. + * @throws EmptyTaskException If the task description is empty. + * @throws MissingDeadlineException If the deadline is missing. + * @throws IOException If there is an error saving the task to the file. + */ + public static void createDeadline(ArrayList toDoList, String input) throws EmptyTaskException, MissingDeadlineException, IOException { + String description = input.replaceFirst("deadline ", ""); + if (description.equals("deadline")) { + throw new EmptyTaskException(); + } + int idxOfEndDate = description.indexOf("/"); + if (idxOfEndDate == -1) { + throw new MissingDeadlineException(); + } + int idxToDateFromEndDate = 4; + String date = description.substring(idxOfEndDate + idxToDateFromEndDate); + String toDoTask = description.substring(0, idxOfEndDate - 1); + if (toDoTask.isBlank()) { + throw new EmptyTaskException(); + } + taskManager.addDeadline(toDoList, description, idxOfEndDate, date); + Task.setNoOfTask(Task.getNoOfTask() + 1); + Storage.saveDeadline(new Deadline(description.substring(0, idxOfEndDate - 1), date), 'D'); + UI.printCreateDeadlineMessage(toDoTask, date); + } + + /** + * Creates a new Event task based on user input and adds it to the task list. + * + * @param toDoList The list of tasks in the form of an ArrayList. + * @param input The user input containing the task description, start date, and end date. + * @throws EmptyTaskException If the task description is empty. + * @throws MissingDeadlineException If the end date is missing. + * @throws MissingStartDateException If the start date is missing. + * @throws IOException If there is an error saving the task to the file. + */ + public static void createEvent(ArrayList toDoList, String input) throws EmptyTaskException, MissingDeadlineException, + MissingStartDateException, IOException { + String description = input.replaceFirst("event ", ""); + int idxOfFrom = description.indexOf("/from"); + if (idxOfFrom == -1) { + throw new EmptyTaskException(); + } + int idxOfBy = description.indexOf("/to"); + if (idxOfBy == -1) { + throw new MissingDeadlineException(); + } + int idxFromFromToStartDate = 6; + String startDate = description.substring(idxOfFrom + idxFromFromToStartDate, idxOfBy - 1); + if (startDate.isBlank()) { + throw new MissingStartDateException(); + } + int idxFromByToEndDate = 4; + String endDate = description.substring(idxOfBy + idxFromByToEndDate); + if (endDate.isBlank()) { + throw new MissingDeadlineException(); + } + String toDoTask = description.substring(0, idxOfFrom - 1); + if (toDoTask.isBlank()) { + throw new EmptyTaskException(); + } + taskManager.addEvent(toDoList, description, idxOfFrom, startDate, endDate); + Task.setNoOfTask(Task.getNoOfTask() + 1); + Storage.saveEvent(new Event(description.substring(0, idxOfFrom - 1), startDate, endDate), 'E'); + UI.printCreateEventMessage(toDoTask, startDate, endDate); + } + + /** + * Deletes a task from the task list based on the index specified in the user input. + * + * @param toDoList The list of tasks in the form of an ArrayList. + * @param input The user input containing the index of the task to be deleted. + * @throws TaskNotFoundException If the specified task index is not found. + */ + public static void deleteTask(ArrayList toDoList, String input) throws TaskNotFoundException { + try { + int idxToDelete = getIdx(input); + if (idxToDelete >= Task.getNoOfTask()) { + throw new TaskNotFoundException(); + } else { + UI.deleteTask(toDoList, idxToDelete); + Task.setNoOfTask(Task.getNoOfTask() - 1); + } + } catch (IllegalArgumentException e) { + UI.printIllegalArgumentException(); + } + } + + /** + * Processes user input to create, delete, or manage tasks. + * + * @param toDoList The list of tasks in the form of an ArrayList. + * @param input The user input command. + */ + public static void createTask(ArrayList toDoList, String input) { + if (input.startsWith("delete")) { + try { + deleteTask(toDoList, input); + } catch (TaskNotFoundException e) { + try { + int idx = getIdx(input); + UI.printTaskNotFoundException(idx); + } catch (IllegalArgumentException f) { + UI.printIllegalArgumentException(); + } + } + } else if (input.startsWith("todo")) { + try { + createTodo(toDoList, input); + } catch (EmptyTaskException e) { + UI.printEmptyTaskException(); + } catch (IOException e) { + UI.printIOException(); + } + } else if (input.startsWith("deadline")) { + try { + createDeadline(toDoList, input); + } catch (EmptyTaskException e) { + UI.printEmptyTaskException(); + } catch (MissingDeadlineException e) { + UI.printMissingDeadlineException(); + } catch (IOException e) { + UI.printIOException(); + } + } else if (input.startsWith("event")) { + try { + createEvent(toDoList, input); + } catch (EmptyTaskException e) { + UI.printEmptyTaskException(); + } catch (MissingStartDateException e) { + UI.printMissingStartDateException(); + } catch (MissingDeadlineException e) { + UI.printMissingDeadlineException(); + } catch (IOException e) { + UI.printIOException(); + } + } + } + + /** + * Searches for tasks in the task list that match the keyword specified in the user input. + * + * @param toDoList The list of tasks in the form of an ArrayList. + * @param input The user input containing the search keyword. + */ + public static void findTask(ArrayList toDoList, String input) { + int counter = 1; + int idxBetweenFindAndDescription = 5; + String taskToFind = input.substring(input.indexOf("find ") + idxBetweenFindAndDescription); + if (taskToFind.isBlank()) { + throw new IllegalArgumentException(); + } + UI.printFindingMessage(taskToFind); + for (int i = 0; i < Task.getNoOfTask(); i++) { + if (toDoList.get(i).getDescription().contains(taskToFind)) { + UI.printTask(toDoList, counter, i); + counter++; + } + } + if (counter == 1) { + UI.printTaskNotFoundMessage(taskToFind); + } + } + + /** + * Interprets and executes the command specified in the user input. + * + * @param toDoList The list of tasks in the form of an ArrayList. + * @param input The user input command. + * @throws UnknownInputException If the input command is not recognized. + */ + public static void readCommand(ArrayList toDoList, String input) throws UnknownInputException { + if (input.startsWith("delete") || input.startsWith("todo") || input.startsWith("deadline") || input.startsWith("event")) { + createTask(toDoList, input); + } else if (input.startsWith("list")) { + if (toDoList.isEmpty()) { + UI.printListEmptyMessage(); + } else { + UI.printTaskList(toDoList); + } + } else if (input.startsWith("unmark")) { + try { + int idx = getIdx(input); + taskManager.markTaskUndone(toDoList, idx); + UI.printMarkUndone(idx, toDoList); + } catch (IllegalArgumentException e) { + UI.printIllegalArgumentException(); + } + } else if (input.startsWith("mark")) { + try { + int idx = getIdx(input); + taskManager.markTaskDone(toDoList, idx); + UI.printMarkDone(idx, toDoList); + } catch (IllegalArgumentException e) { + UI.printIllegalArgumentException(); + } + } else if (input.startsWith("find")) { + try { + findTask(toDoList, input); + } catch (IllegalArgumentException e) { + UI.printIllegalArgumentException(); + } + } else { + throw new UnknownInputException(); + } + } +} diff --git a/src/main/java/GermaBot/Storage.java b/src/main/java/GermaBot/Storage.java new file mode 100644 index 000000000..be0c07df8 --- /dev/null +++ b/src/main/java/GermaBot/Storage.java @@ -0,0 +1,61 @@ +package GermaBot; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; + +import DataHandling.*; +import Exceptions.FileReadException; +import Tasks.*; + +/** + * Handles storage operations for the GermaBot application. + */ +public class Storage { + private File dataFile; + + public Storage() { + } + + /** + * Loads tasks from a file. + * @return The list of tasks loaded from the file. + * @throws FileNotFoundException If the file is not found. + * @throws FileReadException If there is an error reading the file. + */ + public ArrayList loadFile() throws FileNotFoundException, FileReadException { + return LoadData.loadFile(); + } + + /** + * Saves a todo task to the file. + * @param toDoTask The todo task to save to the file. + * @param taskType The type of task (T for todo, D for deadline, E for event). + * @throws IOException If an I/O error occurs. + */ + public static void saveTodo(ToDo toDoTask, char taskType) throws IOException { + SaveData.addTodoToFile(toDoTask, taskType); + } + + /** + * Saves a deadline task to the file. + * @param deadlineTask The deadline task to save to the file. + * @param taskType The type of task (T for todo, D for deadline, E for event). + * @throws IOException If an I/O error occurs. + */ + public static void saveDeadline(Deadline deadlineTask, char taskType) throws IOException { + SaveData.addDeadlineToFile(deadlineTask, taskType); + } + + /** + * Saves an event task to the file. + * @param eventTask The event task to save to the file. + * @param taskType The type of task (T for todo, D for deadline, E for event). + * @throws IOException If an I/O error occurs. + */ + public static void saveEvent(Event eventTask, char taskType) throws IOException { + SaveData.addEventToFile(eventTask, taskType); + } + +} diff --git a/src/main/java/GermaBot/TaskManager.java b/src/main/java/GermaBot/TaskManager.java new file mode 100644 index 000000000..520a1fbe3 --- /dev/null +++ b/src/main/java/GermaBot/TaskManager.java @@ -0,0 +1,69 @@ +package GermaBot; + +import Tasks.Deadline; +import Tasks.Event; +import Tasks.Task; +import Tasks.ToDo; + +import java.util.ArrayList; + +/** + * Manages tasks in the GermaBot application. + */ +public class TaskManager { + private final ArrayList tasks = new ArrayList<>(); + + public TaskManager() { + } + + /** + * Marks a task as done. + * @param toDoList The list of tasks in the form of an ArrayList. + * @param idx The index of the task to mark as done. + */ + public void markTaskDone(ArrayList toDoList, int idx) { + toDoList.get(idx).setDone(true); + } + + /** + * Marks a task as undone. + * @param toDoList The list of tasks in the form of an ArrayList. + * @param idx The index of the task to mark as undone. + */ + public void markTaskUndone(ArrayList toDoList, int idx) { + toDoList.get(idx).setDone(false); + } + + /** + * Adds a todo task to the list of tasks. + * @param toDoList The list of tasks in the form of an ArrayList. + * @param toDoTask The description of the todo task. + */ + public void addTodo(ArrayList toDoList, String toDoTask) { + toDoList.add(new ToDo(toDoTask)); + } + + /** + * Adds a deadline task to the list of tasks. + * @param toDoList The list of tasks in the form of an ArrayList. + * @param description The description of the deadline task. + * @param idxOfEndDate The index of the end date in the String array of the description. + * @param date The end date of the deadline task. + */ + public void addDeadline(ArrayList toDoList, String description, int idxOfEndDate, String date) { + toDoList.add(new Deadline(description.substring(0, idxOfEndDate - 1), date)); + } + + /** + * Adds an event task to the list of tasks. + * @param toDoList The list of tasks in the form of an ArrayList. + * @param description The description of the event task. + * @param idxOfFrom The index of the from date in the String array of the description. + * @param startDate The start date of the event task. + * @param endDate The end date of the event task. + */ + public void addEvent(ArrayList toDoList, String description, int idxOfFrom, String startDate, String endDate) { + toDoList.add(new Event(description.substring(0, idxOfFrom - 1), startDate, endDate)); + } + +} diff --git a/src/main/java/GermaBot/UI.java b/src/main/java/GermaBot/UI.java new file mode 100644 index 000000000..5e14d1bd9 --- /dev/null +++ b/src/main/java/GermaBot/UI.java @@ -0,0 +1,161 @@ +package GermaBot; + +import Tasks.Task; + +import java.util.ArrayList; +import java.util.Scanner; + +/** + * Represents a class object for printing to standard output, as well as reading input. + */ +public class UI { + static final String LINE= "____________________________________________"; + static final String WELCOME_MESSAGE = "Hei...! GermaBot here! \n" + + "Let me load your saved To Do List first..."; + static final String GOODBYE_MESSAGE = "Thanks you for using me!!!! See you soon~! ^^"; + static final String LOAD_COMPLETE = "Loading complete!"; + + private static final Scanner scanner = new Scanner(System.in);; + + public UI() { + } + + public String getInput() { + return scanner.nextLine(); + } + + public void printWelcomeMessage() { + System.out.println(LINE); + System.out.println(WELCOME_MESSAGE); + } + + public void printLoadComplete() { + + System.out.println(LOAD_COMPLETE); + } + + public void printFileNotFoundException() { + System.out.println("Uh oh, there is no saved file yet! Please create a GermaBotsData.txt " + + "file under './src/data/GermaBotData'!!\n" + + "Because there is no saved file found, I will start with an empty list!"); + } + + public void printFileReadException() { + System.out.println("Uh oh, there seems to be an issue with the save file...\n" + + "Because there is an error with the save file, I will start with an empty list!"); + } + + public static void printLoadFileException() { + System.out.println("Oh no, There was an error loading your save file! Please check" + + " to make sure it follows the format..."); + } + + public void printPostLoadingMessage() { + System.out.println("What may I do for you this fine day?"); + System.out.println(LINE); + } + + public void printByeMessage() { + System.out.println(LINE); + System.out.println(GOODBYE_MESSAGE); + System.out.println(LINE); + } + + public static void printListEmptyMessage() { + System.out.println("Umm... You haven't added any Tasks yet... Let's try adding " + + "some now!"); + } + + public static void printMarkUndone(int idx, ArrayList toDoList) { + System.out.println("Aww, not done? Okay, I'll mark this task as undone: " + + "[" + toDoList.get(idx).getStatusIcon() + "] " + toDoList.get(idx).getDescription()); + } + + public static void printMarkDone(int idx, ArrayList toDoList) { + System.out.println("Good job! I'll mark this task as done: " + + "[" + toDoList.get(idx).getStatusIcon() + "] " + toDoList.get(idx).getDescription()); + } + + public void printUnknownInputException(String input) { + System.out.println("Uhh.. I'm sorry but I'm not quite sure what in the world '" + input + "' means..." + + " Remember to include the Task' Type in front of the input!!"); + } + + /** + * Prints the list of tasks currently stored in the toDoList. + * @param toDoList The list of tasks in the form of an ArrayList. + */ + public static void printTaskList(ArrayList toDoList) { + System.out.println("Gotcha! Here are your tasks:"); + for (int i = 0; i < toDoList.size(); i++) { + System.out.println(i + 1 + ". " + toDoList.get(i)); + } + } + + public static void printIOException() { + System.out.println("Uh oh, I could not save that to the file..."); + } + + public static void printEmptyTaskException() { + System.out.println("Uh oh, you did not specify a task to add! Let's try again!"); + } + + public static void printMissingStartDateException() { + System.out.println("Uh oh, you did not specify a start time! Let's try again!"); + } + + public static void printMissingDeadlineException() { + System.out.println("Uh oh, you did not specify the deadline! Let's try again!"); + } + + public static void printTaskNotFoundException(int idx) { + System.out.println("Sorry but... There is no task number " + (idx + 1) + "... " + + "Let's try again!"); + } + + /** + * Deletes a task to be removed from the task list. + * @param toDoList the list of tasks in the form of an ArrayList. + * @param idxToDelete is the index of the task that is going to be deleted. + */ + public static void deleteTask(ArrayList toDoList, int idxToDelete) { + System.out.println("Okay! I've removed this task from your To Do List:"); + System.out.println(toDoList.get(idxToDelete)); + toDoList.remove(idxToDelete); + System.out.println("Now you have, let me count... " + toDoList.size() + " items left in your " + + "To Do List!"); + } + + public static void printCreateTodoMessage(String toDoTask) { + System.out.println("Gotcha! Added '" + toDoTask + "' to your To Do List!"); + } + + public static void printCreateEventMessage(String toDoTask, String startDate, String endDate) { + System.out.println("Gotcha! Added '" + toDoTask + "' to your To Do List!" + + " This will happen from " + startDate + " to " + endDate + ", so please remember to mark it" + + " on your calender! (Or ask me!)"); + } + + public static void printCreateDeadlineMessage(String toDoTask, String date) { + System.out.println("Gotcha! Added '" + toDoTask + "' to your To Do List!" + + " You have to finish this by " + date + ", so be reminded!"); + } + + public static void printTask(ArrayList toDoList, int counter, int i) { + System.out.println(counter + ". " + toDoList.get(i)); + } + + public static void printTaskNotFoundMessage(String input) { + System.out.println("Uhm... I'm sorry but, I could not find any tasks containing '" + input + "'... Maybe try again?"); + } + + public static void printIllegalArgumentException() { + System.out.println("Uh oh, you did not provide a task number! Please try again!"); + } + + public static void printFindingMessage(String input) { + System.out.println("Gotcha! Finding tasks containing '" + input + "'..."); + } +} + + diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 000000000..f6ace6ee9 --- /dev/null +++ b/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: MainRuntime.GermaBot + diff --git a/src/main/java/MainRuntime/GermaBot.java b/src/main/java/MainRuntime/GermaBot.java new file mode 100644 index 000000000..79d2fe666 --- /dev/null +++ b/src/main/java/MainRuntime/GermaBot.java @@ -0,0 +1,59 @@ +package MainRuntime; + +import Exceptions.*; +import Tasks.*; +import DataHandling.*; +import GermaBot.*; + +import java.io.FileNotFoundException; +import java.util.ArrayList; + +/** + * Main class for the GermaBot application. + */ +public class GermaBot { + static ArrayList toDoList = new ArrayList<>(); + private static UI ui; + private static Storage storage; + + /** + * Constructor for GermaBot class. Initializes the user interface and storage manager, loads tasks from storage, and prints welcome messages. + */ + public GermaBot() { + storage = new Storage(); + ui = new UI(); + ui.printWelcomeMessage(); + try { + toDoList = storage.loadFile(); + Task.setNoOfTask(LoadData.getCounter()); + ui.printLoadComplete(); + } catch (FileNotFoundException e) { + ui.printFileNotFoundException(); + } catch (FileReadException e) { + ui.printFileReadException(); + } + ui.printPostLoadingMessage(); + } + + /** + * Main method to run the GermaBot application. Continuously reads user input, processes it and prints the result until the user types "bye". + */ + public void run() { + while (true) { + String input = ui.getInput(); + if (input.equals("bye")) { + break; + } + try { + Logic.readCommand(toDoList, input); + } catch (UnknownInputException e) { + ui.printUnknownInputException(input); + } + } + ui.printByeMessage(); + } + + public static void main(String[] args) { + new GermaBot().run(); + } +} diff --git a/src/main/java/Tasks/Deadline.java b/src/main/java/Tasks/Deadline.java new file mode 100644 index 000000000..af37edcc0 --- /dev/null +++ b/src/main/java/Tasks/Deadline.java @@ -0,0 +1,27 @@ +package Tasks; + +/** + * Represents a class for deadline tasks. + */ +public class Deadline extends Task { + + protected String by; + + public Deadline(String description, String by) { + super(description); + this.by = by; + } + + public String getBy() { + return by; + } + + public void setBy(String date) { + this.by = date; + } + + @Override + public String toString() { + return "[D]" + super.toString() + " (by: " + by + ")"; + } +} diff --git a/src/main/java/Tasks/Event.java b/src/main/java/Tasks/Event.java new file mode 100644 index 000000000..d0d4c7748 --- /dev/null +++ b/src/main/java/Tasks/Event.java @@ -0,0 +1,39 @@ +package Tasks; + +import Tasks.Task; + +/** + * Represents a class for event tasks. + */ +public class Event extends Task { + + protected String from; + protected String to; + + public Event(String description, String from, String to) { + super(description); + this.from = from; + this.to = to; + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public String getTo() { + return to; + } + + public void setTo(String to) { + this.to = to; + } + + @Override + public String toString() { + return "[E]" + super.toString() + " (from: " + from + " to: " + to + ")"; + } +} diff --git a/src/main/java/Tasks/Task.java b/src/main/java/Tasks/Task.java new file mode 100644 index 000000000..b9bf82f8d --- /dev/null +++ b/src/main/java/Tasks/Task.java @@ -0,0 +1,48 @@ +package Tasks; + +/** + * Represents a Task object that can be used as a parent class for deadline, event and todo type classes. + */ +public class Task { + protected String description; + protected boolean isDone; + protected static int counter = 0; + + public Task(String description) { + this.description = description; + this.isDone = false; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public boolean isDone() { + return isDone; + } + + public void setDone(boolean done) { + isDone = done; + } + + public String getStatusIcon() { + return (isDone ? "X" : " "); // mark done task with X + } + + public static int getNoOfTask() { + return counter; + } + + public static void setNoOfTask(int numberOfTasks) { + counter = numberOfTasks; + } + + @Override + public String toString() { + return "[" + this.getStatusIcon() + "] " + this.getDescription(); + } +} diff --git a/src/main/java/Tasks/ToDo.java b/src/main/java/Tasks/ToDo.java new file mode 100644 index 000000000..b4caac87b --- /dev/null +++ b/src/main/java/Tasks/ToDo.java @@ -0,0 +1,17 @@ +package Tasks; + +import Tasks.Task; + +/** + * Represents a class for todo tasks. + */ +public class ToDo extends Task { + public ToDo(String description) { + super(description); + } + + @Override + public String toString() { + return "[T]" + super.toString(); + } +}