diff --git a/docs/README.md b/docs/README.md
index 8077118eb..28a158314 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,29 +1,104 @@
# User Guide
-## Features
+## Features
-### Feature-ABC
+Users can add, mark, unmark, list tasks as needed.
-Description of the feature.
+### Add task
-### Feature-XYZ
+Users can add new tasks to the list. Tasks have 3 available types, Event, Todo and Deadline
-Description of the feature.
+Format: `type of task` `name of task` date-attribute of task
+Example: deadline do tutorial /by Sunday
-## Usage
+Expected outcome:
+New tasks of correct type and description is added to task list
+
+### Add Todo (task subclass)
+
+Users can add todo tasks to the list.
+
+Format: todo `name of task`
+Example: todo eat
+
+Expected: task of type T is added to task list
+
+### Add Event (task subclass)
+
+Users can add Events to the list.
+
+Format: event `name of event` /from `start time` /to `end time`
+Example: event eat /from morning /to night
+
+Expected: task of type E is added to task list
+
+### Add Deadline (task subclass)
+
+Users can add Deadline to the list.
+
+Format: deadline `name of deadline` /by `due date`
+Example (correct LocalDate format): deadline return books /by 2022-03-05
+Example (incorrect LocalDate format): deadline return books /by next week
+
+Expected: task of type D is added to task list, user is alerted if date was not stored as LocalDate format
+
+### Mark task
+
+Users can mark tasks as done.
+
+Format: mark `task index`
+Example: mark 3
+
+Expected outcome:
+[ ] state of task(s) changes to [x] when marked as done.
+
+### Unmark task
+
+Users can mark tasks as undone.
-### `Keyword` - Describe action
+Format: unmark `task index`
+Example: mark 3
+
+Expected outcome:
+[x] state of task(s) changes to [ ] when marked as done.
-Describe the action and its outcome.
+### List task(s)
-Example of usage:
+Users can list and view all tasks currently in the task list
-`keyword (optional arguments)`
+Format: list
Expected outcome:
+If task list is empty, "Tasklist is empty."
+Indexed list of `index`, `done state`, `description`
-Description of the outcome.
+### List overdue task(s)
+
+Users can list and view all tasks that are currently overdue in the task list
+
+Format: list overdue
+
+Expected outcome:
+If task list is empty, "Tasklist is empty."
+Indexed list of overdue tasks `index`, `done state`, `description`
-```
-expected output
-```
+### Find
+
+Users can find and list all tasks by inputting keyword to be searched
+
+Format: find `string to be searched`
+Example: find food
+
+Expected outcome:
+If task lsit is empty, "Tasklist is empty."
+Indexed list of tasks with description containing searched string
+
+### Delete
+
+Users can remove tasks from task list
+Format: delete `index`
+Example: delete 3
+
+Expected outcome:
+If index out of bounds, "Please input valid task number!"
+"Noted. I've removed this task:" `index`
diff --git a/duke.txt b/duke.txt
new file mode 100644
index 000000000..e2aae9be5
--- /dev/null
+++ b/duke.txt
@@ -0,0 +1 @@
+D|false|eat /by tmr
diff --git a/ip.jar b/ip.jar
new file mode 100644
index 000000000..0f2f09b55
Binary files /dev/null and b/ip.jar differ
diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java
new file mode 100644
index 000000000..6efbb53fd
--- /dev/null
+++ b/src/main/java/Deadline.java
@@ -0,0 +1,61 @@
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+//import java.time.temporal.ChronoUnit;
+
+/*
+ * Sub-class of super-class Task, represents a task that has a deadline,
+ * Contains attributes due, info, deadline name and evaluates attribute whether Deadline task is overdue
+ */
+public class Deadline extends Task {
+ public LocalDate due;
+ public String dueText;
+ public String[] info;
+ public String deadlineName;
+ public boolean isOverdue;
+
+ public Deadline(String description) {
+ super(description);
+ this.info = this.description.split("/by", 2);
+ this.deadlineName = info[0];
+ this.due = isValid((info[1]).trim());
+ if (this.due == null) {
+ this.dueText = (info[1]).trim();
+ System.out.println("Due date is not in yyyy-MM-dd format, will be saved as text");
+ } else if (this.due.isBefore(LocalDate.now())) {
+ this.isOverdue = true;
+ }
+
+ }
+
+ private LocalDate isValid(String date) {
+ try {
+ return LocalDate.parse(date);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ @Override
+ public String fileFormat() {
+ DateTimeFormatter yyyyMMdd = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ if (this.due != null) {
+ return (String.format("D|%b|%s /by %s\n", super.isDone, this.deadlineName,
+ due.format(yyyyMMdd)));
+ } else {
+ return (String.format("D|%b|%s /by %s\n", super.isDone, this.deadlineName, this.dueText));
+ }
+ }
+
+ @Override
+ public String toString() {
+ DateTimeFormatter yyyyMMdd = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ if (this.due != null) {
+ return ("[D][" + super.getStatusIcon() + "] " + this.deadlineName) +
+ " (by: " + this.due.format(yyyyMMdd) + ")";
+ } else {
+ return ("[D][" + super.getStatusIcon() + "] " + this.deadlineName) +
+ " (by: " + this.dueText + ")";
+ }
+ }
+}
diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index 5d313334c..78852b3d1 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -1,10 +1,30 @@
+/*
+ * Duke is an instance of the bot which has several subclasses,
+ * storage for file management, ui for communicating with user for input/output, tasklist for managing tasks and task-related commands
+ */
public class Duke {
- public static void main(String[] args) {
- String logo = " ____ _ \n"
- + "| _ \\ _ _| | _____ \n"
- + "| | | | | | | |/ / _ \\\n"
- + "| |_| | |_| | < __/\n"
- + "|____/ \\__,_|_|\\_\\___|\n";
- System.out.println("Hello from\n" + logo);
+
+ private String fileName = "duke.txt";
+ public Storage storage;
+ private UI ui;
+ public TaskList tasks;
+
+ public Duke() {
+ ui = new UI();
+ storage = new Storage(fileName);
+ this.tasks = new TaskList();
+ storage.load(tasks);
+ ui.greet(tasks);
}
+
+ // public void addTask(String taskName){
+ // Task t = new Task(taskName);
+ // taskList.add(t);
+ // System.out.printf(
+ // "Got it. I've added this task:\n" +
+ // String.format("added: %s\n", taskName)
+
+ // );
+ // }
+
}
diff --git a/src/main/java/Event.java b/src/main/java/Event.java
new file mode 100644
index 000000000..8da2927df
--- /dev/null
+++ b/src/main/java/Event.java
@@ -0,0 +1,27 @@
+/*
+ * Sub-class of super-class Task, represents a task that is an event,
+ * Contains attributes event name, start and end time
+ */
+public class Event extends Task {
+ public String startTime, endTime, eventName;
+ public String[] info;
+
+ public Event(String description) {
+ super(description);
+ this.info = this.description.split("/from", 2);
+ this.eventName = info[0];
+ this.startTime = info[1].split("/to", 2)[0];
+ this.endTime = info[1].split("/to", 2)[1];
+ }
+
+ @Override
+ public String fileFormat() {
+ return (String.format("E|%b|%s /from %s /to %s\n", super.isDone, this.eventName, this.startTime, this.endTime));
+ }
+
+ @Override
+ public String toString() {
+ return ("[E][" + super.getStatusIcon() + "] " + this.eventName) +
+ " (from: " + this.startTime + " to: " + this.endTime + ")";
+ }
+}
diff --git a/src/main/java/Main.java b/src/main/java/Main.java
new file mode 100644
index 000000000..fe0329cbb
--- /dev/null
+++ b/src/main/java/Main.java
@@ -0,0 +1,58 @@
+import java.util.Scanner;
+
+/*
+ * Initialises Duke class
+ * If earlier written file exists, displays files
+ * Continuously promtps user for input until specified terminating input is received
+ * List of inputs include bye, list, mark, unmark, event, todo, deadline, delete, find
+ */
+public class Main {
+ public static void main(String[] args) {
+ Duke Duke = new Duke();
+ Scanner userInput = new Scanner(System.in); // create Scanner object
+ String inputCommand; // read user input
+ String[] commandPhrase;
+ String command, phrase;
+ while (true) {
+ inputCommand = userInput.nextLine();
+ commandPhrase = inputCommand.split(" ", 2);
+ command = commandPhrase[0];
+ if (commandPhrase.length < 2) {
+ if (command.equals("bye")) {
+ break;
+ } else if (command.equals("clear")) {
+ Duke.tasks.clearTaskList();
+ } else if (command.equals("list")) {
+ Duke.tasks.list();
+ } else if (command.equals("overdue")) {
+ Duke.tasks.listOverdue();
+ } else {
+ System.out.println("Invalid command");
+ }
+ } else {
+ phrase = commandPhrase[1];
+ if (command.equals("mark")) {
+ Duke.tasks.changeTaskState(true, Integer.parseInt(phrase));
+ } else if (command.equals("unmark")) {
+ Duke.tasks.changeTaskState(false, Integer.parseInt(phrase));
+ } else if (command.equals("event")) {
+ Duke.tasks.addEvent(phrase);
+ } else if (command.equals("todo")) {
+ Duke.tasks.addTodo(phrase);
+ } else if (command.equals("deadline")) {
+ Duke.tasks.addDeadline(phrase);
+ } else if (command.equals("delete")) {
+ Duke.tasks.delete(Integer.parseInt(phrase));
+ } else if (command.equals("find")) {
+ Duke.tasks.find(phrase);
+ } else {
+ System.out.println("Invalid command");
+ }
+ }
+ Duke.storage.saveToFile(Duke.tasks);
+ UI.horizontalLine();
+ }
+ userInput.close();
+ System.out.println("Bye. Hope to see you again soon!");
+ }
+}
diff --git a/src/main/java/Storage.java b/src/main/java/Storage.java
new file mode 100644
index 000000000..bd59f55e4
--- /dev/null
+++ b/src/main/java/Storage.java
@@ -0,0 +1,82 @@
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Scanner;
+import java.util.ArrayList;
+
+/*
+ * Storage class handles all file methods of Duke, it only has the attribute fileName
+ */
+public class Storage {
+ private String fileName;
+
+ public Storage(String inputFileName) {
+ this.fileName = inputFileName;
+ }
+
+ /*
+ * Loads file from location specified by fileName
+ *
+ * @param none
+ *
+ * @return File object file from the location
+ */
+ public void load(TaskList taskList) {
+ File file = new File(fileName);
+ String data;
+ try {
+ if (!file.createNewFile()) {
+ Scanner fileData = new Scanner(file);
+ while (fileData.hasNext()) {
+ data = fileData.nextLine();
+ String[] inputArgs = data.split("\\|");
+ addFileData(inputArgs, taskList);
+ for (String arg : inputArgs) {
+ System.out.print(arg + " ");
+ }
+ }
+ }
+ } catch (IOException e) {
+ System.out.print("\nError getting file data");
+ }
+ }
+
+ public void addFileData(String[] inputArgs, TaskList taskList) {
+ Task newTask;
+ String command = inputArgs[0];
+ boolean taskStatus = Boolean.parseBoolean(inputArgs[1]);
+ switch (command) {
+ case "T":
+ newTask = new Todo(inputArgs[2]);
+ break;
+ case "D":
+ newTask = new Deadline(inputArgs[2]);
+ break;
+ case "E":
+ newTask = new Event(inputArgs[2]);
+ break;
+ default:
+ throw new IllegalStateException("File contents are invalid");
+ }
+ if (taskStatus) {
+ newTask.markAsDone();
+ }
+ taskList.returnTaskList().add(newTask);
+ }
+
+ /*
+ * Saves file to destination specified by fileName, the same
+ * location where file is retrieved from
+ */
+ public void saveToFile(TaskList taskList) {
+ try {
+ FileWriter fWriter = new FileWriter(fileName);
+ for (Task task : taskList.returnTaskList()) {
+ fWriter.write(task.fileFormat());
+ }
+ fWriter.close();
+ } catch (IOException e) {
+ System.out.print("IOException Error: data not saved to file\n");
+ }
+ }
+}
diff --git a/src/main/java/Task.java b/src/main/java/Task.java
new file mode 100644
index 000000000..d51c2b50e
--- /dev/null
+++ b/src/main/java/Task.java
@@ -0,0 +1,40 @@
+/*
+ * Superclass Task extends to subtasks Deadline, Event and Todo
+ * Task has 2 attributes, description and isDone, which toggles whether the task is done or not done
+ */
+public class Task {
+ protected String description;
+ protected boolean isDone;
+
+ public Task(String description) {
+ this.description = description;
+ this.isDone = false;
+ }
+
+ public String getStatusIcon() {
+ return (isDone ? "X" : " "); // mark done task with X
+ }
+
+ public void markAsDone() {
+ this.isDone = true;
+ System.out.println("Nice! I've marked this task as done:");
+ System.out.println(this.toString());
+ }
+
+ public void markAsUndone() {
+ this.isDone = false;
+ System.out.println("OK, I've marked this task as not done yet:");
+ System.out.println(this.toString());
+ }
+
+ public String fileFormat() {
+ return (String.format(" |%b|%s", this.isDone, this.description));
+ }
+
+ @Override
+ public String toString() {
+ return String.format("[%s] %s", this.getStatusIcon(), this.description);
+ }
+
+ // ...
+}
\ No newline at end of file
diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java
new file mode 100644
index 000000000..6f1a59492
--- /dev/null
+++ b/src/main/java/TaskList.java
@@ -0,0 +1,146 @@
+import java.util.ArrayList;
+import java.util.List;
+import java.io.File;
+import java.util.Scanner;
+import java.io.IOException;
+
+/*
+ * TaskList is the class of Duke which contains the list of tasks and methods to makes changes to the list
+ * It contains only the ArrayList tasks
+ */
+public class TaskList {
+ private List tasks = new ArrayList();
+
+ /*
+ * Writes file data from file scanned from file to tasks object
+ * Uses Scanner to read contents from file, splits content into
+ * String[]
+ *
+ * @param File file with contents of previously created tasklist
+ *
+ * @throws IOException if file data is not formatted as specified
+ */
+ public void Tasklist() {
+ this.tasks = new ArrayList();
+ }
+
+ /*
+ * Formats file data retrieved by Tasklist, parses String[] and adds them to
+ * tasks as Todo, Event or Deadline subclasses
+ */
+
+ public List returnTaskList() {
+ return tasks;
+ }
+
+ public void clearTaskList() {
+ tasks.clear();
+ System.out.println("Task list cleared!");
+ }
+
+ public void addEvent(String taskName) {
+ Event t = new Event(taskName);
+ tasks.add(t);
+ System.out.printf(
+ "Got it. I've added this task:\n" +
+ t.toString() +
+ String.format("\nNow you have %d tasks in the list.\n", tasks.size()));
+ }
+
+ public void addTodo(String taskName) {
+ Todo t = new Todo(taskName);
+ tasks.add(t);
+ System.out.printf(
+ "Got it. I've added this task:\n" +
+ t.toString() +
+ String.format("\nNow you have %d tasks in the list.\n", tasks.size()));
+ }
+
+ public void addDeadline(String taskName) {
+ Deadline t = new Deadline(taskName);
+ tasks.add(t);
+ System.out.printf(
+ "Got it. I've added this task:\n" +
+ t.toString() +
+ String.format("\nNow you have %d tasks in the list.\n", tasks.size()));
+ }
+
+ public void changeTaskState(boolean doneState, Integer index) {
+ if (index > tasks.size() || index < 1) {
+ System.out.println("Please input valid task number!");
+ } else {
+ index--;
+ if (doneState) {
+ tasks.get(index).markAsDone();
+ } else {
+ tasks.get(index).markAsUndone();
+ }
+ }
+ }
+
+ public void delete(int index) {
+ if (index > tasks.size() || index < 1) {
+ System.out.println("Please input valid task number!");
+ } else {
+ index--;
+ System.out.printf("Noted. I've removed this task:" +
+ tasks.get(index).toString());
+ tasks.remove(index);
+ System.out.println(String.format("\nNow you have %d tasks in the list.\n", tasks.size()));
+ }
+ }
+
+ /*
+ * Main list method, lists all contents of tasklist
+ */
+ public void list() {
+ if (tasks.size() == 0) {
+ System.out.println("Task list is empty.");
+ } else {
+ System.out.println("Here are the tasks in your list:");
+ Integer i = 0;
+ for (Task task : tasks) {
+ System.out.printf(String.format("%d.%s\n", i + 1, task.toString()));
+ i++;
+ }
+ }
+ }
+
+ /*
+ * Lists overdue deadline subclass objects in tasklist
+ */
+ public void listOverdue() {
+ if (tasks.size() == 0) {
+ System.out.println("Task list is empty.");
+ } else {
+ System.out.println("Here are the overdue deadlines in your list:");
+ Integer i = 0;
+ for (Task task : tasks) {
+ if (task instanceof Deadline && ((Deadline) task).isOverdue) {
+ System.out.printf(String.format("%d.%s\n", i + 1, task.toString()));
+ i++;
+ }
+ }
+ }
+ }
+
+ /*
+ * lists all tasks in task list containing keyword
+ *
+ * @param keyword to be searched for
+ */
+ public void find(String keyword) {
+ if (tasks.size() == 0) {
+ System.out.println("Task list is empty.");
+ } else {
+ System.out.println("Here are the matching tasks in your list:");
+ Integer i = 0;
+ for (Task task : tasks) {
+ if (task.description.contains(keyword)) {
+ System.out.printf(String.format("%d.%s\n", i + 1, task.toString()));
+ i++;
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java
new file mode 100644
index 000000000..c236f72a3
--- /dev/null
+++ b/src/main/java/Todo.java
@@ -0,0 +1,19 @@
+/*
+ * Sub-class of super-class Task, represents a todo task,
+ * only inherits task description attribute from parent Task class
+ */
+public class Todo extends Task {
+ public Todo(String description) {
+ super(description);
+ }
+
+ @Override
+ public String toString() {
+ return ("[T][" + super.getStatusIcon() + "] " + super.description);
+ }
+
+ @Override
+ public String fileFormat() {
+ return (String.format("T|%b|%s\n", super.isDone, this.description));
+ }
+}
diff --git a/src/main/java/UI.java b/src/main/java/UI.java
new file mode 100644
index 000000000..17134312f
--- /dev/null
+++ b/src/main/java/UI.java
@@ -0,0 +1,23 @@
+/*
+ * UI class contains methods that interact with user through text
+ */
+public class UI {
+ /*
+ * Prints greeting statement and logo to terminal
+ */
+ public void greet(TaskList taskList) {
+ String logo = " ____ _ \n"
+ + "| _ \\ _ _| | _____ \n"
+ + "| | | | | | | |/ / _ \\\n"
+ + "| |_| | |_| | < __/\n"
+ + "|____/ \\__,_|_|\\_\\___|\n";
+ System.out.println("Hello from\n" + logo);
+ System.out.println("Hello! I'm Duke");
+ taskList.list();
+ System.out.println("What can I do for you?");
+ }
+
+ public static void horizontalLine() {
+ System.out.println("------------------------------------");
+ }
+}