diff --git a/docs/README.md b/docs/README.md index 8077118eb..bb32003a0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,29 +1,158 @@ # User Guide -## Features +## Command list -### Feature-ABC +### `todo` - adds todo task +### `deadline` - adds deadline task +### `event` - adds event task +### `list` - lists all task +### `find` - find matching tasks +### `done` - completes task +### `delete` - deletes task +### `bye` - exits program -Description of the feature. +## Usage -### Feature-XYZ +### `todo` - adds todo task -Description of the feature. +Adds todo task to the list -## Usage +Example of usage: -### `Keyword` - Describe action +`todo Complete CS2113 lecture quiz` -Describe the action and its outcome. +Expected outcome: -Example of usage: +Displays successfully addition of todo task to the list and the total number of tasks in the list. + +``` +Kao got it! ( 。•̀ᴗ-)✧ Kao has added this task: +Complete CS2113 lecture quiz +Now you have 1 tasks in the list. +``` + +### `deadline` - adds deadline task + +Adds deadline task to the list + +Example of usage: + +`deadline Complete iP increment /by Thursday 2359` + +Expected outcome: + +Displays successfully addition of deadline task to the list and the total number of tasks in the list. + +``` +Kao got it! ( 。•̀ᴗ-)✧ Kao has added this task: +Complete iP increment +Now you have 2 tasks in the list. +``` + +### `event` - adds event task + +Adds event task to the list + +Example of usage: + +`event Attend CS2113 lecture /at Friday 1400` + +Expected outcome: + +Displays successfully addition of event task to the list and the total number of tasks in the list. + +``` +Kao got it! ( 。•̀ᴗ-)✧ Kao has added this task: +Attend CS2113 lecture +Now you have 3 tasks in the list. +``` + +### `list` - lists all task + +Lists the entire task list + +Example of usage: + +`list` + +Expected outcome: + +Displays the entire task list -`keyword (optional arguments)` +``` +Right away! ε=ε=┌( >_<)┘ +Kao retrieved the tasks in your list: +1. [T][ ] Complete CS2113 lecture quiz +2. [D][ ] Complete iP increment (by: Thursday 2359) +3. [E][ ] Attend CS2113 lecture (at: Friday 1400) +``` + +### `find` - find matching tasks + +Finds matching tasks in the list + +Example of usage: + +`find CS2113` + +Expected outcome: + +Display tasks in the task list with the matching keyword + +``` +Kao got it! ε=ε=┌( `ー´)┘ +Kao retrieved the matching tasks in your list: +1. [T][ ] Complete CS2113 lecture quiz +3. [E][ ] Attend CS2113 lecture (at: Friday 1400) +``` + +### `done` - completes task + +Marks task as complete + +Example of usage: + +`done 1` Expected outcome: -Description of the outcome. +Displays successful completion of the corresponding task ``` -expected output +Nice job! ( >ω<)☆ Kao marked this task as done: +Complete CS2113 lecture quiz +``` + +### `delete` - deletes task + +Deletes task from the list + +Example of usage: + +`delete 1` + +Expected outcome: + +Displays successful deletion of the corresponding task + +``` +Alright! ( ・∀・ )ノ Kao removed this task: +Complete CS2113 lecture quiz +Now you have 2 tasks in the list. +``` + +### `bye` - exits program + +Exits and closes the program + +Example of usage: + +`bye` + +Expected outcome: + +Shows successful termination of the program + ``` +Bye bye! Kao will be waiting for you 。:゚( ´°ω°` )゚:。 +``` \ No newline at end of file diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java deleted file mode 100644 index 5d313334c..000000000 --- a/src/main/java/Duke.java +++ /dev/null @@ -1,10 +0,0 @@ -public class Duke { - public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - } -} diff --git a/src/main/java/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/Duke.java b/src/main/java/duke/Duke.java new file mode 100644 index 000000000..e0704183c --- /dev/null +++ b/src/main/java/duke/Duke.java @@ -0,0 +1,59 @@ +package duke; + +import duke.commands.Command; +import duke.commands.CommandOutput; +import duke.tasks.*; + +import java.util.Scanner; + +public class Duke { + + private Storage storage; + private TaskList tasks; + private Ui ui; + private Parser parser; + + public Duke(String filePath) { + ui = new Ui(); + storage = new Storage(filePath); + parser = new Parser(); + TaskListResponse response = storage.initialiseTasks(); + tasks = response.taskList; + Ui.printMessage(response.response); + } + + //attempts to execute the user command + public CommandOutput executeCommand(Command command) { + try { + return command.execute(); + } catch (Exception e){ + return new CommandOutput(e.getMessage(), false, null); + } + } + + //runs the program + public void run() { + ui.printGreeting(); + String line; + Scanner in = new Scanner(System.in); + ui.printPrompt(); + line = in.nextLine(); + while(!line.equals(parser.BYE)) { + Command command = parser.parseCommand(tasks, line); + CommandOutput commandOutput = executeCommand(command); + if (commandOutput.isUpdated()) { + tasks = commandOutput.getTaskList(); + String errorMessage = storage.write(tasks); + ui.printMessage(errorMessage); + } + ui.printMessage(commandOutput.getResponse()); + ui.printPrompt(); + line = in.nextLine(); + } + ui.printExit(); + } + + public static void main(String[] args) { + new Duke("data/duke.txt").run(); + } +} diff --git a/src/main/java/duke/Parser.java b/src/main/java/duke/Parser.java new file mode 100644 index 000000000..166d3874d --- /dev/null +++ b/src/main/java/duke/Parser.java @@ -0,0 +1,46 @@ +package duke; + +import duke.commands.Command; +import duke.commands.ListCommand; +import duke.commands.AddCommand; +import duke.commands.FindCommand; +import duke.commands.NoCommand; +import duke.commands.DoneCommand; +import duke.commands.DeleteCommand; +import duke.tasks.TaskList; +import duke.tasks.TaskType; + +public class Parser { + + public final String LIST = "list"; + public final String TODO = "todo"; + public final String DEADLINE = "deadline"; + public final String EVENT = "event"; + public final String FIND = "find"; + public final String DONE = "done"; + public final String DELETE = "delete"; + public final String BYE = "bye"; + + //executes program and updates task list according to user command + public Command parseCommand(TaskList taskList, String line) { + final String[] splitLine = line.split(" ", 2); + final String command = splitLine[0]; + final String userCommand = line.replaceAll("^" + command + " ", ""); + if (command.equals(LIST)) { + return new ListCommand(taskList); + } else if (command.equals(TODO)) { + return new AddCommand(taskList, userCommand, TaskType.TODO); + } else if (command.equals(DEADLINE)) { + return new AddCommand(taskList, userCommand, TaskType.DEADLINE); + } else if (command.equals(EVENT)) { + return new AddCommand(taskList, userCommand, TaskType.EVENT); + } else if (command.equals(FIND)) { + return new FindCommand(taskList, userCommand); + } else if (command.equals(DONE)) { + return new DoneCommand(taskList, userCommand); + } else if (command.equals(DELETE)) { + return new DeleteCommand(taskList, userCommand); + } + return new NoCommand(taskList); + } +} diff --git a/src/main/java/duke/Storage.java b/src/main/java/duke/Storage.java new file mode 100644 index 000000000..c526b6427 --- /dev/null +++ b/src/main/java/duke/Storage.java @@ -0,0 +1,100 @@ +package duke; + +import duke.exceptions.FileFormatException; +import duke.tasks.Deadline; +import duke.tasks.Event; +import duke.tasks.Task; +import duke.tasks.Todo; +import duke.tasks.TaskList; +import duke.tasks.TaskListResponse; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Scanner; + +public class Storage { + + private final String filePath; + private final File f; + + public Storage(String filePath) { + this.filePath = filePath; + this.f = new File(filePath); + } + + //load tasks from save file if save file exists + public void loadTasks(TaskList taskList) throws FileNotFoundException, FileFormatException { + Scanner s = new Scanner(f); // create a Scanner using the File as the source + while (s.hasNext()) { + String task = s.nextLine(); + if (!task.matches("T\\s\\|\\s[01]\\s\\|.+") + && !task.matches("[ED]\\\\s\\\\|\\\\s[01]\\\\s\\\\|.+\\\\|.+")) { + throw new FileFormatException(); + } + String[] taskSplit= task.split(" \\| "); + String taskType = taskSplit[0]; + boolean isDone = taskSplit[1].equals("1"); + String description = taskSplit[2]; + String preposition = taskSplit.length >= 4 ? taskSplit[3] : ""; + if (taskType.equals("E")){ + taskList.tasks.add(new Event(description, isDone, preposition)); + } else if (taskType.equals("D")){ + taskList.tasks.add(new Deadline(description, isDone, preposition)); + } else { + taskList.tasks.add(new Todo(description, isDone)); + } + } + } + + //creates a save file + public void createFile() throws IOException { + Path pathToFile = Paths.get("data/duke.txt"); + Files.createDirectories(pathToFile.getParent()); + f.createNewFile(); + } + + //program output for save file + public TaskListResponse initialiseTasks() { + TaskList taskList = new TaskList(); + String response = ""; + try { + loadTasks(taskList); + } catch (FileNotFoundException e0){ + response = response + "Kao cannot find the file data/duke.txt ( ;ŏ﹏ŏ ) "; + try { + createFile(); + } catch (IOException e1) { + response = response + "Kao has encountered an error creating a new file ( °ㅂ°╬ )"; + } + response = response + "Kao will create a new file data/duke.txt for you!"; + } catch (FileFormatException e2) { + response = response + "Kao is facing a formatting error with the save file ヽ( `д´ )ノ"; + taskList.clearList(); + } + return new TaskListResponse(taskList, response); + } + + //writing to save file + private void writeToFile(TaskList taskList) throws IOException { + FileWriter fw = new FileWriter("data/duke.txt"); + for (Task list : taskList.tasks) { + fw.write(list.saveTask() + "\n"); + } + fw.close(); + } + + //program output for writing to save file + public String write(TaskList taskList) { + try { + writeToFile(taskList); + } catch (IOException e) { + return "Kao has faced an error writing to file ( ; ω ; )"; + } + return ""; + } +} diff --git a/src/main/java/duke/Ui.java b/src/main/java/duke/Ui.java new file mode 100644 index 000000000..40a5f5795 --- /dev/null +++ b/src/main/java/duke/Ui.java @@ -0,0 +1,24 @@ +package duke; + +public class Ui { + + //prints program output + public static void printMessage(String line) { + if (line.isEmpty()) { + return; + } + System.out.println(line); + } + + public static void printGreeting() { + printMessage("Hello there! Kao here! ⸜(˃ ᵕ ˂ )⸝"); + } + + public static void printPrompt() { + printMessage( "How can Kao be of assistance? ( •̀ ᗜ •́ )"); + } + + public static void printExit() { + printMessage("Bye bye! Kao will be waiting for you 。:゚( ´°ω°` )゚:。"); + } +} diff --git a/src/main/java/duke/commands/AddCommand.java b/src/main/java/duke/commands/AddCommand.java new file mode 100644 index 000000000..d413e805b --- /dev/null +++ b/src/main/java/duke/commands/AddCommand.java @@ -0,0 +1,29 @@ +package duke.commands; + +import duke.tasks.TaskList; +import duke.tasks.TaskType; + +public class AddCommand extends Command { + + public TaskType type; + + public AddCommand(TaskList taskList, String userCommand, TaskType type) { + super(taskList, userCommand); + this.type = type; + } + + @Override + public CommandOutput execute() throws Exception { + String response = ""; + + if (type == TaskType.TODO) { + response = taskList.addTodo(userCommand); + } else if (type == TaskType.DEADLINE) { + response = taskList.addDeadline(userCommand); + } else if (type == TaskType.EVENT){ + response = taskList.addEvent(userCommand); + } + + return new CommandOutput(response, true, taskList); + } +} diff --git a/src/main/java/duke/commands/Command.java b/src/main/java/duke/commands/Command.java new file mode 100644 index 000000000..f9b109ab2 --- /dev/null +++ b/src/main/java/duke/commands/Command.java @@ -0,0 +1,17 @@ +package duke.commands; + +import duke.tasks.TaskList; + +public abstract class Command { + + protected TaskList taskList; + protected String userCommand; + + protected Command(TaskList taskList, String userCommand) { + this.taskList = taskList; + this.userCommand = userCommand; + } + + //attempts to execute program according to user command + public abstract CommandOutput execute() throws Exception; +} diff --git a/src/main/java/duke/commands/CommandOutput.java b/src/main/java/duke/commands/CommandOutput.java new file mode 100644 index 000000000..fa2463fb9 --- /dev/null +++ b/src/main/java/duke/commands/CommandOutput.java @@ -0,0 +1,34 @@ +package duke.commands; + +import duke.tasks.TaskList; + +public class CommandOutput { + + private String response; + private boolean updated; + private TaskList taskList; + + public CommandOutput(String response, boolean updated) { + this.response = response; + this.updated = updated; + taskList = null; + } + + public CommandOutput(String response, boolean updated, TaskList taskList) { + this.response = response; + this.updated = updated; + this.taskList = taskList; + } + + public String getResponse() { + return response; + } + + public boolean isUpdated() { + return updated; + } + + public TaskList getTaskList() { + return taskList; + } +} diff --git a/src/main/java/duke/commands/DeleteCommand.java b/src/main/java/duke/commands/DeleteCommand.java new file mode 100644 index 000000000..c6ddb5a7b --- /dev/null +++ b/src/main/java/duke/commands/DeleteCommand.java @@ -0,0 +1,16 @@ +package duke.commands; + +import duke.tasks.TaskList; + +public class DeleteCommand extends Command { + + public DeleteCommand(TaskList taskList, String userCommand) { + super(taskList, userCommand); + } + + @Override + public CommandOutput execute() throws Exception { + String response = taskList.deleteTask(userCommand); + return new CommandOutput(response, true, taskList); + } +} diff --git a/src/main/java/duke/commands/DoneCommand.java b/src/main/java/duke/commands/DoneCommand.java new file mode 100644 index 000000000..838112870 --- /dev/null +++ b/src/main/java/duke/commands/DoneCommand.java @@ -0,0 +1,16 @@ +package duke.commands; + +import duke.tasks.TaskList; + +public class DoneCommand extends Command { + + public DoneCommand(TaskList taskList, String userCommand) { + super(taskList, userCommand); + } + + @Override + public CommandOutput execute() throws Exception { + String response = taskList.taskDone(userCommand); + return new CommandOutput(response, true, taskList); + } +} diff --git a/src/main/java/duke/commands/FindCommand.java b/src/main/java/duke/commands/FindCommand.java new file mode 100644 index 000000000..1a3219345 --- /dev/null +++ b/src/main/java/duke/commands/FindCommand.java @@ -0,0 +1,17 @@ +package duke.commands; + +import duke.tasks.TaskList; + +public class FindCommand extends Command { + + public FindCommand(TaskList taskList, String userCommand){ + super(taskList, userCommand); + } + + @Override + public CommandOutput execute() throws Exception{ + String response = taskList.findTask(userCommand); + + return new CommandOutput(response, false); + } +} diff --git a/src/main/java/duke/commands/ListCommand.java b/src/main/java/duke/commands/ListCommand.java new file mode 100644 index 000000000..b361140f6 --- /dev/null +++ b/src/main/java/duke/commands/ListCommand.java @@ -0,0 +1,16 @@ +package duke.commands; + +import duke.tasks.TaskList; + +public class ListCommand extends Command { + + public ListCommand(TaskList taskList) { + super(taskList, ""); + } + + @Override + public CommandOutput execute() throws Exception { + String response = taskList.printList(); + return new CommandOutput(response, false); + } +} diff --git a/src/main/java/duke/commands/NoCommand.java b/src/main/java/duke/commands/NoCommand.java new file mode 100644 index 000000000..a18a38831 --- /dev/null +++ b/src/main/java/duke/commands/NoCommand.java @@ -0,0 +1,16 @@ +package duke.commands; + +import duke.tasks.TaskList; + +public class NoCommand extends Command { + + public NoCommand(TaskList taskList) { + super(taskList, ""); + } + + @Override + public CommandOutput execute() throws Exception { + taskList.noResponse(); + return new CommandOutput("", false, taskList); + } +} diff --git a/src/main/java/duke/exceptions/AlreadyDoneException.java b/src/main/java/duke/exceptions/AlreadyDoneException.java new file mode 100644 index 000000000..df7eef2ec --- /dev/null +++ b/src/main/java/duke/exceptions/AlreadyDoneException.java @@ -0,0 +1,12 @@ +package duke.exceptions; + +//used when user tries to complete an already completed task +public class AlreadyDoneException extends Exception { + + public final String DONE_RESPONSE = "Hmm? You already completed that task (/  ̄O ̄)/"; + + @Override + public String getMessage(){ + return DONE_RESPONSE; + } +} diff --git a/src/main/java/duke/exceptions/DeadlineException.java b/src/main/java/duke/exceptions/DeadlineException.java new file mode 100644 index 000000000..767876d12 --- /dev/null +++ b/src/main/java/duke/exceptions/DeadlineException.java @@ -0,0 +1,13 @@ +package duke.exceptions; + +//used when deadline description is in the wrong format +public class DeadlineException extends Exception { + + public final String DEADLINE_RESPONSE = "Kao needs you to repeat that (。_ 。 )?" + + "\nThe following format must be used: deadline [description] /by [date and time]"; + + @Override + public String getMessage() { + return DEADLINE_RESPONSE; + } +} diff --git a/src/main/java/duke/exceptions/DeleteFormatException.java b/src/main/java/duke/exceptions/DeleteFormatException.java new file mode 100644 index 000000000..e2160851d --- /dev/null +++ b/src/main/java/duke/exceptions/DeleteFormatException.java @@ -0,0 +1,13 @@ +package duke.exceptions; + +//used when delete description is in the wrong format +public class DeleteFormatException extends Exception { + + public final String DELETE_FORMAT_RESPONSE = "Could you rephrase that for Kao ( ̄▽ ̄*)?" + + "\nThe following format must be used: delete [index]"; + + @Override + public String getMessage(){ + return DELETE_FORMAT_RESPONSE; + } +} diff --git a/src/main/java/duke/exceptions/DeleteRangeException.java b/src/main/java/duke/exceptions/DeleteRangeException.java new file mode 100644 index 000000000..63f4f49b3 --- /dev/null +++ b/src/main/java/duke/exceptions/DeleteRangeException.java @@ -0,0 +1,12 @@ +package duke.exceptions; + +//used when task user wants to delete does not exist +public class DeleteRangeException extends Exception { + + public final String DELETE_RANGE_RESPONSE = "Kao doesn't see that task anywhere ┐( ・∀・ )┌"; + + @Override + public String getMessage(){ + return DELETE_RANGE_RESPONSE; + } +} diff --git a/src/main/java/duke/exceptions/DoneFormatException.java b/src/main/java/duke/exceptions/DoneFormatException.java new file mode 100644 index 000000000..eaf9f45fa --- /dev/null +++ b/src/main/java/duke/exceptions/DoneFormatException.java @@ -0,0 +1,13 @@ +package duke.exceptions; + +//used when done description is in the wrong format +public class DoneFormatException extends Exception { + + public final String DONE_FORMAT_RESPONSE = "Kao doesn't get what you said ( ・ω・)?" + + "\nThe following format must be used: done [index]"; + + @Override + public String getMessage(){ + return DONE_FORMAT_RESPONSE; + } +} diff --git a/src/main/java/duke/exceptions/DoneRangeException.java b/src/main/java/duke/exceptions/DoneRangeException.java new file mode 100644 index 000000000..a8b0414c9 --- /dev/null +++ b/src/main/java/duke/exceptions/DoneRangeException.java @@ -0,0 +1,12 @@ +package duke.exceptions; + +//used when task user wants to complete does not exist +public class DoneRangeException extends Exception { + + public final String DONE_RANGE_RESPONSE = "Kao doesn't see that task ( ・д・)?"; + + @Override + public String getMessage(){ + return DONE_RANGE_RESPONSE; + } +} diff --git a/src/main/java/duke/exceptions/EmptyException.java b/src/main/java/duke/exceptions/EmptyException.java new file mode 100644 index 000000000..d3ca7c4eb --- /dev/null +++ b/src/main/java/duke/exceptions/EmptyException.java @@ -0,0 +1,12 @@ +package duke.exceptions; + +//used when user did not input a command +public class EmptyException extends Exception { + + public final String EMPTY_RESPONSE = "Did you call Kao? (・_・ )"; + + @Override + public String getMessage(){ + return EMPTY_RESPONSE; + } +} diff --git a/src/main/java/duke/exceptions/EmptyListException.java b/src/main/java/duke/exceptions/EmptyListException.java new file mode 100644 index 000000000..a5dfaed2e --- /dev/null +++ b/src/main/java/duke/exceptions/EmptyListException.java @@ -0,0 +1,12 @@ +package duke.exceptions; + +//used when user tries the list command even though list is empty +public class EmptyListException extends Exception { + + public final String EMPTY_LIST_RESPONSE = "The list is empty ( ̄ω ̄;)"; + + @Override + public String getMessage(){ + return EMPTY_LIST_RESPONSE; + } +} diff --git a/src/main/java/duke/exceptions/EventException.java b/src/main/java/duke/exceptions/EventException.java new file mode 100644 index 000000000..36ea829ee --- /dev/null +++ b/src/main/java/duke/exceptions/EventException.java @@ -0,0 +1,13 @@ +package duke.exceptions; + +//used when event description is in the wrong format +public class EventException extends Exception { + + public final String EVENT_RESPONSE = "Kao doesn't understand you ( ⊙_⊙)?" + + "\nThe following format must be used: event [description] /at [date and time]"; + + @Override + public String getMessage(){ + return EVENT_RESPONSE; + } +} diff --git a/src/main/java/duke/exceptions/FileFormatException.java b/src/main/java/duke/exceptions/FileFormatException.java new file mode 100644 index 000000000..6396dc754 --- /dev/null +++ b/src/main/java/duke/exceptions/FileFormatException.java @@ -0,0 +1,5 @@ +package duke.exceptions; + +//used when save file is in the wrong format +public class FileFormatException extends Exception { +} diff --git a/src/main/java/duke/exceptions/NotFoundException.java b/src/main/java/duke/exceptions/NotFoundException.java new file mode 100644 index 000000000..675f79a73 --- /dev/null +++ b/src/main/java/duke/exceptions/NotFoundException.java @@ -0,0 +1,12 @@ +package duke.exceptions; + +//used when no matching tasks are found from the find command +public class NotFoundException extends Exception { + + public final String NOT_FOUND_RESPONSE = "Kao couldn't find any matching tasks ╮(・ω・;)╭"; + + @Override + public String getMessage(){ + return NOT_FOUND_RESPONSE; + } +} diff --git a/src/main/java/duke/exceptions/TodoException.java b/src/main/java/duke/exceptions/TodoException.java new file mode 100644 index 000000000..ee69226b7 --- /dev/null +++ b/src/main/java/duke/exceptions/TodoException.java @@ -0,0 +1,13 @@ +package duke.exceptions; + +//used when todo description is in the wrong format +public class TodoException extends Exception { + + public final String TODO_RESPONSE = "Kao is confused (・~・ )?" + + "\nThe following format must be used: todo [description]"; + + @Override + public String getMessage(){ + return TODO_RESPONSE; + } +} diff --git a/src/main/java/duke/tasks/Deadline.java b/src/main/java/duke/tasks/Deadline.java new file mode 100644 index 000000000..678c8b03a --- /dev/null +++ b/src/main/java/duke/tasks/Deadline.java @@ -0,0 +1,34 @@ +package duke.tasks; + +public class Deadline extends Task { + + private TaskType type = TaskType.DEADLINE; + protected String by; + + public Deadline(String description, String by) { + super(description); + this.by = by; + } + public Deadline(String description, boolean isDone, String by) { + super(description, isDone); + this.by = by; + } + + public String getBy() { + return by; + } + + public void setBy(String by) { + this.by = by; + } + + @Override + public String printTask() { + return "[D][" + getStatusIcon() + "] " + getDescription() + " (by:" + by + ")"; + } + + @Override + public String saveTask() { + return "D | " + (isDone ? 1 : 0) + " | " + description + " | " + by; + } +} diff --git a/src/main/java/duke/tasks/Event.java b/src/main/java/duke/tasks/Event.java new file mode 100644 index 000000000..f85cf61bb --- /dev/null +++ b/src/main/java/duke/tasks/Event.java @@ -0,0 +1,33 @@ +package duke.tasks; + +public class Event extends Task { + + private TaskType type = TaskType.EVENT; + protected String at; + + public Event(String description, String at) { + super(description); + this.at = at; + } + + public Event(String description, boolean isDone, String at) { + super(description, isDone); + this.at = at; + } + public String getAt() { + return at; + } + public void setAt(String at) { + this.at = at; + } + + @Override + public String printTask() { + return "[E][" + getStatusIcon() + "] " + getDescription() + "(at:" + at + ")"; + } + + @Override + public String saveTask() { + return "E | " + (isDone ? 1 : 0) + " | " + description + " | " + at; + } +} diff --git a/src/main/java/duke/tasks/Task.java b/src/main/java/duke/tasks/Task.java new file mode 100644 index 000000000..84458bb4a --- /dev/null +++ b/src/main/java/duke/tasks/Task.java @@ -0,0 +1,42 @@ +package duke.tasks; + +public class Task { + + protected String description; + protected boolean isDone; + + public Task(String description) { + this.description = description; + isDone = false; + } + + public Task(String description, boolean isDone) { + this.description = description; + this.isDone = isDone; + } + + public String getStatusIcon() { + // mark done task with X + return (isDone ? "X" : " "); + } + + public String getDescription() { + return description; + } + + public boolean isDone() { + return isDone; + } + + public void setDone() { + isDone = true; + } + + public String printTask() { + return ""; + } + + public String saveTask() { + return null; + } +} diff --git a/src/main/java/duke/tasks/TaskList.java b/src/main/java/duke/tasks/TaskList.java new file mode 100644 index 000000000..9a863c4a6 --- /dev/null +++ b/src/main/java/duke/tasks/TaskList.java @@ -0,0 +1,133 @@ +package duke.tasks; + +import duke.exceptions.*; + +import java.util.ArrayList; + +public class TaskList { + + public ArrayList tasks = new ArrayList<>(); + + public String ADDED = "Kao got it! ( 。•̀ᴗ-)✧ Kao has added this task:"; + public String REMOVED = "Alright! ( ・∀・ )ノ Kao removed this task:"; + public String ACKNOWLEDGED = "Nice job! ( >ω<)☆ Kao marked this task as done:"; + public String LIST_START = "Right away! ε=ε=┌( >_<)┘ \nKao retrieved the tasks in your list:"; + public String FIND_START = "Kao got it! ε=ε=┌( `ー´)┘ \nKao retrieved the matching tasks in your list:"; + + public String TaskListResponse(String line, int index){ + return line + "\n" + tasks.get(index).getDescription(); + } + + public void noResponse () throws EmptyException { + throw new EmptyException(); + } + + public String printTaskCount() { + return "Now you have " + tasks.size() + " tasks in the list."; + } + + //displays the list to the user + public String printList() throws EmptyListException { + if (tasks.size() == 0) { + throw new EmptyListException(); + } + String listResponse = LIST_START; + for (int i = 1; i <= tasks.size(); i += 1) { + listResponse = listResponse + "\n" + i + ". " + tasks.get(i - 1).printTask(); + } + return listResponse; + } + + public TaskList() { + } + + //executes program to mark a task as done + public String taskDone(String line) + throws DoneFormatException, AlreadyDoneException, DoneRangeException { + if (!line.matches("\\d+")) { + throw new DoneFormatException(); + } + int index = Integer.parseInt(line) - 1; + if (index >= tasks.size()) { + throw new DoneRangeException(); + } else if (tasks.get(index).isDone()) { + throw new AlreadyDoneException(); + } else { + tasks.get(index).setDone(); + return TaskListResponse(ACKNOWLEDGED, index); + } + } + + //adds a todo task to the list + public String addTodo(String line) throws TodoException { + if (line.equals("") || line.equals("todo")) { + throw new TodoException(); + } else { + tasks.add(new Todo(line)); + return TaskListResponse(ADDED, tasks.size()-1) +"\n" + printTaskCount(); + } + } + + //adds a deadline task to the list + public String addDeadline(String line) throws DeadlineException { + if (!line.matches("(.*)/by(.*)")) { + throw new DeadlineException(); + } else { + //extracting the description and date + String description = line.replaceAll("/.+", ""); + String by = line.replaceAll(".+/by", ""); + tasks.add(new Deadline(description, by)); + return TaskListResponse(ADDED, tasks.size()-1) +"\n" + printTaskCount(); + } + } + + //adds an event task to the list + public String addEvent(String line) throws EventException { + if (!line.matches("(.*)/at(.*)")) { + throw new EventException(); + } else { + //extracting the description and date + String description = line.replaceAll("/.+", ""); + String at = line.replaceAll(".+/at", ""); + tasks.add(new Event(description, at)); + return TaskListResponse(ADDED, tasks.size()-1) +"\n" + printTaskCount(); + } + } + + //deletes task from the list + public String deleteTask(String line) throws DeleteFormatException, DeleteRangeException { + if (!line.matches("\\d+")) { + throw new DeleteFormatException(); + } + int index = Integer.parseInt(line) - 1; + if (index >= tasks.size()) { + throw new DeleteRangeException(); + } else { + String response = TaskListResponse(REMOVED, index); + tasks.remove(index); + return response +"\n" + printTaskCount(); + } + } + + //finds matching tasks in the list + public String findTask(String line) throws NotFoundException { + String foundList = FIND_START; + int tasksFound = 0; + for (int i = 1; i <= tasks.size(); ++i) { + if (tasks.get(i - 1).getDescription().toLowerCase().contains(line.toLowerCase())) { + tasksFound += 1; + foundList = foundList + "\n" + i + ". " + tasks.get(i - 1).printTask(); + } + } + + if (tasksFound == 0){ + throw new NotFoundException(); + } + return foundList; + } + + //clears existing list + public void clearList(){ + tasks.clear(); + } +} diff --git a/src/main/java/duke/tasks/TaskListResponse.java b/src/main/java/duke/tasks/TaskListResponse.java new file mode 100644 index 000000000..14a7a3634 --- /dev/null +++ b/src/main/java/duke/tasks/TaskListResponse.java @@ -0,0 +1,12 @@ +package duke.tasks; + +public class TaskListResponse { + + public TaskList taskList; + public String response; + + public TaskListResponse(TaskList taskList, String response) { + this.taskList = taskList; + this.response = response; + } +} diff --git a/src/main/java/duke/tasks/TaskType.java b/src/main/java/duke/tasks/TaskType.java new file mode 100644 index 000000000..e641c880a --- /dev/null +++ b/src/main/java/duke/tasks/TaskType.java @@ -0,0 +1,5 @@ +package duke.tasks; + +public enum TaskType { + TODO, EVENT, DEADLINE +} diff --git a/src/main/java/duke/tasks/Todo.java b/src/main/java/duke/tasks/Todo.java new file mode 100644 index 000000000..15e0c8da8 --- /dev/null +++ b/src/main/java/duke/tasks/Todo.java @@ -0,0 +1,23 @@ +package duke.tasks; + +public class Todo extends Task{ + + private TaskType type = TaskType.TODO; + + public Todo(String description) { + super(description); + } + public Todo(String description, boolean isDone) { + super(description, isDone); + } + + @Override + public String printTask() { + return "[T][" + getStatusIcon() + "] " + getDescription(); + } + + @Override + public String saveTask() { + return "T | " + (isDone ? 1 : 0) + " | " + description; + } +} diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 657e74f6e..d09585156 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,7 +1,37 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| - +Kao cannot find the file data/duke.txt ( ;ŏ﹏ŏ ) Kao will create a new file data/duke.txt for you! +Hello there! Kao here! ⸜(˃ ᵕ ˂ )⸝ +How can Kao be of assistance? ( •̀ ᗜ •́ ) +todo Eat cake +Kao got it! ( 。•̀ᴗ-)✧ Kao has added this task: +Eat cake +Now you have 1 tasks in the list. +How can Kao be of assistance? ( •̀ ᗜ •́ ) +deadline Eat chocolate cake /by Friday 2pm +Kao got it! ( 。•̀ᴗ-)✧ Kao has added this task: +Eat chocolate cake +Now you have 2 tasks in the list. +How can Kao be of assistance? ( •̀ ᗜ •́ ) +event Attend cake buffet /at Saturday 5pm +Kao got it! ( 。•̀ᴗ-)✧ Kao has added this task: +Attend cake buffet +Now you have 3 tasks in the list. +How can Kao be of assistance? ( •̀ ᗜ •́ ) +done 1 +Nice job! ( >ω<)☆ Kao marked this task as done: +Eat cake +How can Kao be of assistance? ( •̀ ᗜ •́ ) +find eat +Kao got it! ε=ε=┌( `ー´)┘ +Kao retrieved the matching tasks in your list: +1. [T][X] Eat cake +2. [D][ ] Eat chocolate cake (by: Friday 2pm) +How can Kao be of assistance? ( •̀ ᗜ •́ ) +list +Right away! ε=ε=┌( >_<)┘ +Kao retrieved the tasks in your list: +1. [T][X] Eat cake +2. [D][ ] Eat chocolate cake (by: Friday 2pm) +3. [E][ ] Attend cake buffet (at: Saturday 5pm) +How can Kao be of assistance? ( •̀ ᗜ •́ ) +bye +Bye bye! Kao will be waiting for you 。:゚( ´°ω°` )゚:。 diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e69de29bb..567a1aa4e 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -0,0 +1,7 @@ +todo Eat cake +deadline Eat chocolate cake /by Friday 2pm +event Attend cake buffet /at Saturday 5pm +done 1 +find eat +list +bye \ No newline at end of file diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index 087374464..9dec60887 100644 --- a/text-ui-test/runtest.bat +++ b/text-ui-test/runtest.bat @@ -4,10 +4,10 @@ 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 +javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\duke\*.java IF ERRORLEVEL 1 ( echo ********** BUILD FAILURE ********** exit /b 1 @@ -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.Duke < input.txt > ACTUAL.TXT REM compare the output to the expected output FC ACTUAL.TXT EXPECTED.TXT