diff --git a/data/savedlist.txt b/data/savedlist.txt
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs/README.md b/docs/README.md
index 8077118eb..20c60ecc4 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,29 +1,180 @@
# User Guide
+Welcome to the HinaBot User Guide! HinaBot is a personal assistant program that helps you
+maintain a to-do list.
+
## Features
-### Feature-ABC
+### Support for multiple task types
+
+HinaBot supports 3 different types of items on a to-do list: regular tasks, deadlines (tasks which have a due-date),
+and events (which have a start and end date).
+
+### Search function
-Description of the feature.
+HinaBot allows you to search your to-do list for tasks that contain a particular substring, making it easier to keep
+track of large numbers of tasks.
-### Feature-XYZ
+### Delete and mark functions
-Description of the feature.
+HinaBot allows you to mark tasks as done or not done and also supports deletion of a task.
+
+### Save and load function
+All changes you make to your to-do list are stored locally, meaning you can pick up right where you left off.
## Usage
-### `Keyword` - Describe action
+### `todo` - Add a regular task to the to-do list
-Describe the action and its outcome.
+Adds a regular task (no due date) to the to-do list. By default, the task is set as not done.
Example of usage:
-`keyword (optional arguments)`
+`todo buy milk`
+
+Expected outcome:
+
+The task is added to your to-do list and HinaBot announces how many tasks are currently on your list
+
+```
+Noted! This task has been added:
+[T][ ] buy milk
+There are 1 items on your list.
+```
+### `deadline` - Add a deadline to the to-do list
+
+Adds a deadline (with a do-by date in dd-MMM-yyyy HH:mm format) to the to-do list. By default, the task is set as not done.
+
+Example of usage:
+
+`deadline Assignment 1 /by 04-Apr-2023 23:59`
Expected outcome:
-Description of the outcome.
+The deadline is added to your to-do list and HinaBot announces how many tasks are currently on your list
+
+```
+Noted! This task has been added:
+[D][ ] Assignment 1 (by: 04-Apr-2023 23:59)
+There are 2 items on your list
+```
+### `event` - Add an event to the to-do list
+
+Adds an event (with start and end times in dd-MMM-yyyy HH:mm format) to the to-do list. By default, the task is set as not done.
+
+Example of usage:
+
+`event Midterms /from 03-Mar-2023 13:00 /to 03-Mar-2023 17:30`
+
+Expected outcome:
+
+The deadline is added to your to-do list and HinaBot announces how many tasks are currently on your list
+
+```
+Noted! This task has been added:
+[E][ ] Midterms (from: 03-Mar-2023 13:00 to: 03-Mar-2023 17:30)
+There are 2 items on your list
+```
+### `list` - Lists all tasks in the to-do list
+
+Prints a list of all tasks in the to-do list including the task type and done status.
+
+Example of usage:
+
+`list`
+
+Expected outcome:
+
+The deadline is added to your to-do list and HinaBot announces how many tasks are currently on your list
+
+```
+1. [T][ ] buy milk
+2. [D][ ] Assignment 1 (by: 04-Apr-2023 23:59)
+3. [E][ ] Midterms (from: 03-Mar-2023 13:00 to: 03-Mar-2023 17:30)
+```
+### `mark` - Marks a task as done
+
+Marks an item by its index on the to-do list as done. This is indicated by an 'X' in the checkbox next to
+its description.
+
+Example of usage:
+
+`mark 1`
+
+Expected outcome:
+An acknowledgement message and an 'X' is printed in the checkbox next to item 1 on the to-do list.
```
-expected output
+Roger that! This task is marked as done:
+[T][X] buy milk
```
+
+### `unmark` - Marks a task as not done
+
+Marks an item by its index on the to-do list as not done. This is indicated by a blank checkbox next to
+its description.
+
+Example of usage:
+
+`unmark 1`
+
+Expected outcome:
+
+An acknowledgement message and a blank checkbox is printed next to item 1 on the to-do list.
+```
+Roger that! This task is marked as not done:
+[T][ ] buy milk
+```
+
+### `delete` - Remove a task from the to-do list
+
+Removes the item at the specified index from the to-do list.
+
+Example of usage:
+
+`delete 3`
+
+Expected outcome:
+
+An acknowledgement message and the description of the task being removed is shown, followed by an announcement
+of the size of the remaining list.
+```
+Got it! This task will be removed:
+[E][ ] Midterms (from: 03-Mar-2023 13:00 to: 03-Mar-2023 17:30)
+There are 2 items on your list.
+```
+
+### `find` - Search for a task
+
+Searches the to-do list for all tasks with a description containing the substring provided by the user.
+
+Example of usage:
+
+`find buy`
+
+Expected outcome:
+
+Any matching tasks, along with their index on the list, are printed.
+
+```
+Found a match! Here are the results master!
+1. [T][ ] buy milk
+```
+
+### `bye` - Exits the program
+
+Terminates the program and prints a goodbye message.
+
+Example of usage:
+
+`bye`
+
+Expected outcome:
+
+The program exits with code 0 and a goodbye message is shown.
+
+```
+Goodbye master, let's meet again soon...
+
+Process finished with exit code 0
+```
\ 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..d83708e47
--- /dev/null
+++ b/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: hina.HinaBot
+
diff --git a/src/main/java/hina/HinaBot.java b/src/main/java/hina/HinaBot.java
new file mode 100644
index 000000000..7d794f1c8
--- /dev/null
+++ b/src/main/java/hina/HinaBot.java
@@ -0,0 +1,47 @@
+package hina;
+
+import hina.exceptions.HinaException;
+import hina.helper.Parser;
+import hina.helper.Storage;
+import hina.helper.TaskList;
+import hina.helper.Ui;
+
+import java.io.FileNotFoundException;
+
+public class HinaBot {
+ private static Ui ui;
+ private static Storage storage;
+ private static TaskList tasks;
+
+ /**
+ * Class constructor specifying the path to a file containing save data. Tries to
+ * access the save file and attempts to create a new one if it does not exist.
+ *
+ * @param savePath path to the save file.
+ * @param dataDir directory the save file is stored in.
+ */
+ public HinaBot(String savePath, String dataDir) {
+ ui = new Ui();
+ storage = new Storage();
+ Ui.showGreeting();
+ try {
+ tasks = new TaskList(Storage.readSaveFile(savePath));
+ } catch (FileNotFoundException exception) {
+ Storage.createSaveFile(savePath, dataDir);
+ }
+ }
+
+ public static void main(String[] args) {
+ new HinaBot("data/savedlist.txt", "data");
+
+ while (true) {
+ try {
+ Parser.readCommand();
+ } catch (HinaException cmdException) {
+ Ui.invalidCommandMessage();
+ } catch (StringIndexOutOfBoundsException argException) {
+ Ui.notEnoughDetails();
+ }
+ }
+ }
+}
diff --git a/src/main/java/hina/exceptions/HinaException.java b/src/main/java/hina/exceptions/HinaException.java
new file mode 100644
index 000000000..f0c448cb4
--- /dev/null
+++ b/src/main/java/hina/exceptions/HinaException.java
@@ -0,0 +1,4 @@
+package hina.exceptions;
+
+public class HinaException extends Throwable {
+}
diff --git a/src/main/java/hina/helper/Parser.java b/src/main/java/hina/helper/Parser.java
new file mode 100644
index 000000000..4f7c52dc7
--- /dev/null
+++ b/src/main/java/hina/helper/Parser.java
@@ -0,0 +1,87 @@
+package hina.helper;
+
+import hina.exceptions.HinaException;
+
+import java.io.IOException;
+import java.util.Scanner;
+
+/**
+ * Contains methods to process user input.
+ */
+public class Parser {
+ /**
+ * Reads a user input from the command line and determines if it was a command.
+ * If the input was a recognised command, handle it respectively, else throws
+ * a HinaException.
+ *
+ * @throws HinaException If the input is not recognised as a valid command.
+ */
+ public static void readCommand() throws HinaException {
+ String line;
+ Scanner in = new Scanner(System.in);
+ line = in.nextLine().trim();
+ if (line.equalsIgnoreCase("bye")) {
+ Ui.showExitMessage();
+ System.exit(0);
+ } else if (line.equalsIgnoreCase("list")) {
+ TaskList.listTasks();
+ } else if (line.split(" ")[0].equalsIgnoreCase("mark")) {
+ try {
+ int taskIndex = Integer.parseInt(line.split(" ")[1]);
+ TaskList.markTask(taskIndex);
+ } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
+ Ui.invalidNumberMessage();
+ }
+ try {
+ Storage.writeToFile();
+ } catch (IOException ioexception) {
+ Ui.couldNotSaveMessage();
+ }
+ } else if (line.split(" ")[0].equalsIgnoreCase("unmark")) {
+ int taskIndex = Integer.parseInt(line.split(" ")[1]);
+ TaskList.unmarkTask(taskIndex);
+ try {
+ Storage.writeToFile();
+ } catch (IOException ioexception) {
+ Ui.couldNotSaveMessage();
+ }
+ } else if (line.split(" ")[0].equalsIgnoreCase("todo")) {
+ TaskList.addTask(line.substring(5));
+ try {
+ Storage.writeToFile();
+ } catch (IOException ioexception) {
+ Ui.couldNotSaveMessage();
+ }
+ } else if (line.split(" ")[0].equalsIgnoreCase("deadline")) {
+ TaskList.addDeadline(line.substring(9));
+ try {
+ Storage.writeToFile();
+ } catch (IOException ioexception) {
+ Ui.couldNotSaveMessage();
+ }
+ } else if (line.split(" ")[0].equalsIgnoreCase("event")) {
+ TaskList.addEvent(line.substring(6));
+ try {
+ Storage.writeToFile();
+ } catch (IOException ioexception) {
+ Ui.couldNotSaveMessage();
+ }
+ } else if (line.split(" ")[0].equalsIgnoreCase("delete")) {
+ try {
+ int taskIndex = Integer.parseInt(line.split(" ")[1]);
+ TaskList.deleteTask(taskIndex);
+ } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
+ Ui.invalidNumberMessage();
+ }
+ try {
+ Storage.writeToFile();
+ } catch (IOException ioexception) {
+ Ui.couldNotSaveMessage();
+ }
+ } else if (line.split(" ")[0].equalsIgnoreCase("find")) {
+ TaskList.findTask(line);
+ } else {
+ throw new HinaException();
+ }
+ }
+}
diff --git a/src/main/java/hina/helper/Storage.java b/src/main/java/hina/helper/Storage.java
new file mode 100644
index 000000000..ff1868b4c
--- /dev/null
+++ b/src/main/java/hina/helper/Storage.java
@@ -0,0 +1,103 @@
+package hina.helper;
+
+import hina.task.Deadline;
+import hina.task.Event;
+import hina.task.Task;
+
+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.time.LocalDateTime;
+import java.time.format.DateTimeParseException;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+public class Storage {
+ /**
+ * Class constructor.
+ */
+ public Storage() {
+ }
+
+ /**
+ * Returns an ArrayList containing Task objects from a .txt save file
+ * at a specified path on the hard disk.
+ *
+ * @param savePath relative path to the save file.
+ * @return the ArrayList of saved Task elements.
+ * @throws FileNotFoundException If the file could not be found at the specified path.
+ */
+ public static ArrayList readSaveFile(String savePath) throws FileNotFoundException {
+ ArrayList savedList = new ArrayList<>();
+ File saveFile = new File(savePath);
+ Scanner save = new Scanner(saveFile);
+ Ui.saveFound();
+ while (save.hasNext()) {
+ String line = save.nextLine();
+ String[] taskDetails = line.split(" / ");
+ switch (taskDetails[0]) {
+ case "T":
+ Task savedTask = new Task(taskDetails[2]);
+ savedTask.setDone(!taskDetails[1].contains("0"));
+ savedList.add(savedTask);
+ break;
+ case "D":
+ try {
+ Deadline savedDeadline = new Deadline(taskDetails[2],
+ LocalDateTime.parse(taskDetails[3], TaskList.formatter));
+ savedDeadline.setDone(!taskDetails[1].contains("0"));
+ savedList.add(savedDeadline);
+ } catch (DateTimeParseException e) {
+ System.out.println(e.getMessage());
+ }
+ break;
+ case "E":
+ Event savedEvent = new Event(taskDetails[2], LocalDateTime.parse(taskDetails[3], TaskList.formatter),
+ LocalDateTime.parse(taskDetails[4], TaskList.formatter));
+ savedEvent.setDone(!taskDetails[1].contains("0"));
+ savedList.add(savedEvent);
+ break;
+ }
+ }
+ return savedList;
+ }
+
+ /**
+ * Creates a new .txt file at the specified path. If the directory does not exist,
+ * creates a new one.
+ *
+ * @param savePath relative path to the new file.
+ * @param dataDir relative path to the new file's directory.
+ */
+ public static void createSaveFile(String savePath, String dataDir) {
+ Ui.saveNotFound();
+ File newFile = new File(savePath);
+ try {
+ Path dataPath = Paths.get(dataDir);
+ Files.createDirectory(dataPath);
+ newFile.createNewFile();
+ Ui.saveCreated();
+ } catch (IOException ioException) {
+ Ui.fileCreateError();
+ }
+ }
+
+ /**
+ * Prints all the formatted Task objects in the TaskList on separate lines
+ * into a .txt file on the hard disk.
+ *
+ * @throws IOException If the file could not be written to.
+ */
+ public static void writeToFile() throws IOException {
+ FileWriter saveFile = new FileWriter("data/savedlist.txt");
+ for (Task taskToSave : TaskList.getTaskList()) {
+ saveFile.write(taskToSave.toSave());
+ saveFile.write("\n");
+ }
+ saveFile.close();
+ }
+}
diff --git a/src/main/java/hina/helper/TaskList.java b/src/main/java/hina/helper/TaskList.java
new file mode 100644
index 000000000..e6ff96180
--- /dev/null
+++ b/src/main/java/hina/helper/TaskList.java
@@ -0,0 +1,186 @@
+package hina.helper;
+
+import hina.task.Deadline;
+import hina.task.Event;
+import hina.task.Task;
+
+import java.time.DateTimeException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+
+public class TaskList {
+ private static ArrayList taskList;
+
+ /**
+ * Specifies the date-time format to be used.
+ */
+ public static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm");
+
+ /**
+ * Class constructor with a taskList initialised with the Task elements of
+ * another ArrayList.
+ *
+ * @param savedList the list from which elements are initialised.
+ */
+ public TaskList(ArrayList savedList) {
+ taskList = savedList;
+ }
+
+ /**
+ * Returns an ArrayList containing the Task elements currently stored in
+ * the taskList.
+ *
+ * @return the ArrayList of Task objects.
+ */
+ public static ArrayList getTaskList() {
+ return taskList;
+ }
+
+ /**
+ * Prints line-by-line the data of the Task objects stored in the taskList.
+ */
+ public static void listTasks() {
+ if (taskList.size() == 0) {
+ Ui.emptyListMessage();
+ }
+ for (Task task : taskList) {
+ int i = taskList.indexOf(task);
+ System.out.print(i + 1);
+ System.out.print(". ");
+ System.out.println(task.toString());
+ }
+ }
+
+ /**
+ * Prints the number of elements in the taskList.
+ */
+ public static void getTaskCount() {
+ System.out.printf("There are %d items on your list.\n", taskList.size());
+ }
+
+ /**
+ * Adds a Task object to the taskList.
+ *
+ * @param description the description of the Task.
+ */
+ public static void addTask(String description) {
+ Task newTask = new Task(description);
+ taskList.add(newTask);
+ Ui.taskAdded(newTask);
+ getTaskCount();
+ }
+
+ /**
+ * Adds a Deadline object to the taskList.
+ *
+ * @param deadline a String specifying the description of the Deadline and
+ * the do-by date and time.
+ */
+ public static void addDeadline(String deadline) {
+ String[] details = deadline.split("/by");
+ if (details.length < 2) {
+ System.out.println("Hina needs to know the deadline for this task!");
+ } else {
+ try {
+ LocalDateTime by = LocalDateTime.parse(details[1].trim(), formatter);
+ Deadline newDeadline = new Deadline(details[0], by);
+ taskList.add(newDeadline);
+ Ui.taskAdded(newDeadline);
+ getTaskCount();
+
+ } catch (DateTimeException exception) {
+ Ui.showDateTimeError();
+ }
+ }
+ }
+
+ /**
+ * Adds an Event object to the taskList.
+ *
+ * @param event a String specifying the description of the Event and
+ * the start and end time.
+ */
+ public static void addEvent(String event) {
+ String[] details = event.split("/from");
+ if (details.length < 2) {
+ System.out.println("Please tell Hina when this event starts!");
+ } else {
+ if (details[1].split("/to").length < 2) {
+ System.out.println("Please tell Hina when this event ends!");
+ } else {
+ try {
+ LocalDateTime from = LocalDateTime.parse(details[1].split("/to")[0].trim(), formatter);
+ LocalDateTime to = LocalDateTime.parse(details[1].split("/to")[1].trim(), formatter);
+ Event newEvent = new Event(details[0], from, to);
+ taskList.add(newEvent);
+ Ui.taskAdded(newEvent);
+ getTaskCount();
+
+ } catch (DateTimeException exception) {
+ Ui.showDateTimeError();
+ }
+
+ }
+ }
+ }
+ public static void deleteTask(int taskIndex) {
+ try {
+ Task toDelete = taskList.get(taskIndex - 1);
+ System.out.println("Got it! This task will be removed:");
+ System.out.println(toDelete);
+ taskList.remove(taskIndex - 1);
+ getTaskCount();
+ } catch (IndexOutOfBoundsException e) {
+ Ui.invalidNumberMessage();
+ }
+ }
+ public static void markTask(int taskIndex) {
+ try {
+ taskList.get(taskIndex - 1).setDone(true);
+ System.out.println("Roger that! This task is marked as done: ");
+ System.out.println(taskList.get(taskIndex - 1).toString());
+ } catch (IndexOutOfBoundsException e) {
+ Ui.invalidNumberMessage();
+ }
+ }
+ public static void unmarkTask(int taskIndex) {
+ try {
+ taskList.get(taskIndex - 1).setDone(false);
+ System.out.println("Roger that! This task is marked as not done: ");
+ System.out.println(taskList.get(taskIndex - 1).toString());
+ } catch (IndexOutOfBoundsException e) {
+ Ui.invalidNumberMessage();
+ }
+ }
+
+ /**
+ * Determines, ignoring and trailing and leading whitespaces, if any of the
+ * Task descriptions contain the exact query substring. Prints
+ * the Task data of those that do and prints a message if none are
+ * found.
+ *
+ * @param line the query substring.
+ */
+ public static void findTask(String line) {
+ String query = line.substring(4).trim();
+ boolean matchFound = false;
+ ArrayList matchList = new ArrayList<>();
+ for (Task task : taskList) {
+ if (task.getDescription().contains(query)) {
+ int i = taskList.indexOf(task);
+ String match = String.format("%d. %s", i + 1, task);
+ matchList.add(match);
+ matchFound = true;
+ }
+ }
+ if (matchFound) {
+ Ui.taskFoundMessage();
+ for (String task : matchList) {
+ System.out.println(task);
+ }
+ } else {
+ Ui.taskNotFoundMessage();
+ }
+ }
+}
diff --git a/src/main/java/hina/helper/Ui.java b/src/main/java/hina/helper/Ui.java
new file mode 100644
index 000000000..d6264a961
--- /dev/null
+++ b/src/main/java/hina/helper/Ui.java
@@ -0,0 +1,62 @@
+package hina.helper;
+
+import hina.task.Task;
+
+/**
+ * Contains methods to print messages to the user.
+ */
+public class Ui {
+ /**
+ * Class constructor.
+ */
+ public Ui() {
+ }
+
+ public static void showGreeting() {
+ System.out.println("Hello master!");
+ System.out.println("What are your orders?");
+ }
+ public static void showExitMessage() {
+ System.out.println("Goodbye master, let's meet again soon...");
+ }
+ public static void invalidCommandMessage() {
+ System.out.println(">.< Hina does not recognise this command!");
+ }
+ public static void notEnoughDetails() {
+ System.out.println("@_@ Please give Hina more details!");
+ }
+ public static void couldNotSaveMessage() {
+ System.out.println("Something went wrong, could not save!");
+ }
+ public static void taskFoundMessage() {
+ System.out.println("Found a match! Here are the results master!");
+ }
+ public static void taskNotFoundMessage() {
+ System.out.println("Hina could not find anything about that in master's list...");
+ }
+ public static void showDateTimeError() {
+ System.out.println("Please use dd-MMM-yyyy HH:mm format!");
+ }
+ public static void emptyListMessage() {
+ System.out.println("There are no items on the list :o");
+ }
+ public static void taskAdded(Task task) {
+ System.out.println("Noted! This task has been added:");
+ System.out.println(task);
+ }
+ public static void saveFound() {
+ System.out.println("Saved list found, loading saved list...");
+ }
+ public static void saveNotFound() {
+ System.out.println("Save file not found! Creating new file...");
+ }
+ public static void saveCreated() {
+ System.out.println("Save file created!");
+ }
+ public static void fileCreateError() {
+ System.out.println("T.T Ahh! Something went wrong, could not create file!");
+ }
+ public static void invalidNumberMessage() {
+ System.out.println("That's not a valid number!");
+ }
+}
diff --git a/src/main/java/hina/task/Deadline.java b/src/main/java/hina/task/Deadline.java
new file mode 100644
index 000000000..0a347be81
--- /dev/null
+++ b/src/main/java/hina/task/Deadline.java
@@ -0,0 +1,41 @@
+package hina.task;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Represents a Task on a to-do list with a deadline.
+ */
+public class Deadline extends Task {
+ private LocalDateTime by;
+ String byString;
+
+ /**
+ * Class constructor specifying this Deadline's description and
+ * due date.
+ *
+ * @param description description of this Deadline.
+ * @param by LocalDateTime object specifying the due date.
+ */
+ public Deadline(String description, LocalDateTime by) {
+ super(description);
+ this.by = by;
+ this.byString = this.by.format(DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm"));
+ }
+
+ @Override
+ public String toString() {
+ String mark;
+ if (super.isDone()) {
+ mark = "X";
+ } else {
+ mark = " ";
+ }
+ return String.format("[D][%s] %s (by: %s)", mark, super.getDescription(), byString);
+ }
+
+ @Override
+ public String toSave() {
+ return String.format("D / %s / %s / %s", isDone? "1" : "0", description, byString);
+ }
+}
diff --git a/src/main/java/hina/task/Event.java b/src/main/java/hina/task/Event.java
new file mode 100644
index 000000000..ba8fca8ec
--- /dev/null
+++ b/src/main/java/hina/task/Event.java
@@ -0,0 +1,54 @@
+package hina.task;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Represents an event on a to-do list that has start and end dates and times.
+ */
+public class Event extends Task {
+ private LocalDateTime from;
+ private String fromStr;
+ private LocalDateTime to;
+ private String toStr;
+
+ /**
+ * Class constructor specifying this Event's description, start and end
+ * time.
+ *
+ * @param description description of this Event.
+ * @param from LocalDateTime object specifying the start time.
+ * @param to LocalDateTime object specifying the end time.
+ */
+ public Event(String description, LocalDateTime from, LocalDateTime to) {
+ super(description);
+ this.from = from;
+ this.to = to;
+ this.fromStr = this.from.format(DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm"));
+ this.toStr = this.to.format(DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm"));
+ }
+
+ @Override
+ public String toString() {
+ String mark;
+ if (super.isDone()) {
+ mark = "X";
+ } else {
+ mark = " ";
+ }
+ return String.format("[E][%s] %s(from: %s to: %s)", mark, super.getDescription(), fromStr, toStr);
+ }
+
+ public String getFromStr() {
+ return fromStr;
+ }
+
+ public String getToStr() {
+ return toStr;
+ }
+
+ @Override
+ public String toSave() {
+ return String.format("E / %s / %s / %s / %s", isDone? "1" : "0", description, fromStr, toStr);
+ }
+}
diff --git a/src/main/java/hina/task/Task.java b/src/main/java/hina/task/Task.java
new file mode 100644
index 000000000..479603fcb
--- /dev/null
+++ b/src/main/java/hina/task/Task.java
@@ -0,0 +1,83 @@
+package hina.task;
+
+/**
+ * Represents a task on a to-do list that can be set as done or undone.
+ *
+ */
+public class Task {
+ protected String description;
+ protected boolean isDone;
+
+ /**
+ * Returns done status of the Task.
+ *
+ * @return done status.
+ */
+ public boolean isDone() {
+ return isDone;
+ }
+
+ /**
+ * Sets the done status of the Task.
+ *
+ * @param done status to set the done status to.
+ */
+ public void setDone(boolean done) {
+ isDone = done;
+ }
+
+ /**
+ * Class constructor specifying this Task's description.
+ *
+ * @param description name of this Task.
+ */
+ public Task(String description) {
+ this.description = description;
+ isDone = false;
+ }
+
+ /**
+ * Returns the description of this Task.
+ *
+ * @return description of this Task.
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Sets the description of this Task.
+ *
+ * @param description new description of this task.
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * Returns a formatted string with the type, isDone status
+ * and description of this Task.
+ *
+ * @return the formatted string.
+ */
+ public String toString() {
+ String mark;
+ if (isDone) {
+ mark = "X";
+ } else {
+ mark = " ";
+ }
+ return String.format("[T][%s] %s", mark, description);
+ }
+
+ /**
+ * Returns a formatted string with the type, a number representing the isDone
+ * status ('0' for false, '1' for true), and description of the Task
+ * for saving to the hard disk.
+ *
+ * @return the formatted string.
+ */
+ public String toSave() {
+ return String.format("T / %s / %s", isDone? "1" : "0", description);
+ }
+}