diff --git a/README.md b/README.md
index 8715d4d9..de26d556 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Duke project template
+# duke.Duke project template
This is a project template for a greenfield Java project. It's named after the Java mascot _Duke_. Given below are instructions on how to use it.
@@ -13,7 +13,7 @@ Prerequisites: JDK 11, update Intellij to the most recent version.
1. If there are any further prompts, accept the defaults.
1. Configure the project to use **JDK 11** (not other versions) as explained in [here](https://www.jetbrains.com/help/idea/sdk.html#set-up-jdk).
In the same dialog, set the **Project language level** field to the `SDK default` option.
-3. After that, locate the `src/main/java/Duke.java` file, right-click it, and choose `Run Duke.main()` (if the code editor is showing compile errors, try restarting the IDE). If the setup is correct, you should see something like the below as the output:
+3. After that, locate the `src/main/java/duke.Duke.java` file, right-click it, and choose `Run duke.Duke.main()` (if the code editor is showing compile errors, try restarting the IDE). If the setup is correct, you should see something like the below as the output:
```
Hello from
____ _
@@ -22,3 +22,4 @@ Prerequisites: JDK 11, update Intellij to the most recent version.
| |_| | |_| | < __/
|____/ \__,_|_|\_\___|
```
+4. Duke is part of https://se-education.org
diff --git a/data/duke.txt b/data/duke.txt
new file mode 100644
index 00000000..766ec201
--- /dev/null
+++ b/data/duke.txt
@@ -0,0 +1,4 @@
+E | 1 | read book | 2021-10-11 - 2021-10-13
+D | 0 | return book | 2021-10-14
+T | 0 | sporting
+D | 0 | sporting | 2021-11-13
diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
deleted file mode 100644
index 5d313334..00000000
--- 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 00000000..2c9a9745
--- /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/DateFun.java b/src/main/java/duke/DateFun.java
new file mode 100644
index 00000000..be025009
--- /dev/null
+++ b/src/main/java/duke/DateFun.java
@@ -0,0 +1,25 @@
+package duke;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.Locale;
+
+public class DateFun {
+
+ public static LocalDate stringToLocalDate(String timeStr){
+ DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ LocalDate date = LocalDate.parse(timeStr, fmt);
+ return date;
+ }
+
+ /**
+ * date convert to string
+ * @param date: a LocalDate variable
+ * @return a string which shows date
+ */
+ public static String LocalDateToString(LocalDate date){
+ DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MMM dd yyyy");
+ return date.format(fmt);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java
new file mode 100644
index 00000000..fbd51af8
--- /dev/null
+++ b/src/main/java/duke/Duke.java
@@ -0,0 +1,79 @@
+package duke;
+
+import duke.command.Command;
+import duke.exception.InvalidException;
+import duke.exception.MissReqException;
+import duke.task.Deadline;
+import duke.task.Event;
+import duke.task.Task;
+import duke.task.Todo;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+public class Duke {
+
+ private TaskList tasks;
+ private Storage storage;
+ private Ui ui;
+ private boolean isExit;
+
+ public Duke(){isExit = false;}
+
+ public Duke(String path){
+ ui = new Ui();
+ storage = new Storage(path);
+ isExit = false;
+ try{
+ tasks = storage.load();
+ }catch (FileNotFoundException e){
+ tasks = new TaskList();
+ ui.showLoadException();
+ }
+
+ }
+
+
+
+ public void dukeGreet(){
+ String logo = " ____ _ \n"
+ + "| _ \\ _ _| | _____ \n"
+ + "| | | | | | | |/ / _ \\\n"
+ + "| |_| | |_| | < __/\n"
+ + "|____/ \\__,_|_|\\_\\___|\n";
+ System.out.println("Hello from\n" + logo);
+ ui.showLine();
+ System.out.println(" Hello! I'm duke.Duke");
+ System.out.println(" What can I do for you?\n");
+ ui.showLine();
+ }
+
+
+ public void dukeEcho(){
+ while(!isExit){
+ String req = ui.readReq();
+ try{
+ Command command = Parser.parse(req);
+ command.execute(tasks, ui, storage);
+ isExit = command.isExit();
+ }catch (IOException e){
+ ui.showStoreException();
+ }catch (Exception e){
+ ui.showException(e, req);
+ }
+ }
+
+ }
+
+ public void run(){
+ dukeGreet();
+ dukeEcho();
+ }
+ 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 00000000..62d2ddfd
--- /dev/null
+++ b/src/main/java/duke/Parser.java
@@ -0,0 +1,89 @@
+package duke;
+
+import duke.command.*;
+import duke.exception.InvalidException;
+import duke.exception.MissReqException;
+import duke.task.Deadline;
+import duke.task.Event;
+import duke.task.Task;
+import duke.task.Todo;
+
+public class Parser {
+ /**
+ *
+ * @param req Extract task from command
+ * @return a task object
+ * @throws MissReqException
+ * @throws InvalidException
+ */
+ public static Task getTask(String req) throws MissReqException, InvalidException {
+ String[] reqs = req.trim().split(" ");
+ String type = reqs[0];
+ String description;
+ assert reqs.length > 1 : "invalid input";
+ if(type.equals("todo")){
+ if(reqs.length == 1){
+ throw new MissReqException("todo");
+ }
+ description = req.replaceFirst("todo", "").trim();
+ return new Todo(description);
+ } else if(type.equals("deadline")){
+ if(reqs.length == 1){
+ throw new MissReqException("deadline");
+ }
+ String[] descriptions = req.replaceFirst("deadline", "").trim().split("/by ");
+ assert descriptions.length == 2: "invalid input";
+ description = descriptions[0].trim();
+ String by = descriptions[1];
+ return new Deadline(description, by);
+ } else if(type.equals("event")){
+ if(reqs.length == 1){
+ throw new MissReqException("event");
+ }
+ String[] descriptions = req.replaceFirst("event", "").trim().split("/at ");
+ assert descriptions.length == 2: "invalid input";
+ description = descriptions[0].trim();
+ String at = descriptions[1];
+ return new Event(description, at);
+ } else{
+ throw new InvalidException();
+ }
+ }
+
+ /**
+ * Extract command
+ * @param req the command input of user
+ * @return Variable of Command
+ * @throws MissReqException
+ * @throws InvalidException
+ */
+ public static Command parse(String req) throws MissReqException, InvalidException {
+ String[] reqs = req.split(" ");
+ if(req.equals("bye")){
+ return new ExitCommand(req);
+ }
+ if(reqs[0].equals("list")) {
+ assert reqs.length == 1: "invalid input";
+ return new ListCommand(req);
+ }
+ if(reqs[0].equals("done")) {
+ assert reqs.length == 2: "invalid input";
+ int idx = Integer.parseInt(req.substring(4).trim()) - 1;
+ return new DoneCommand(req, idx);
+ }
+ if(reqs[0].equals("delete")) {
+ assert reqs.length == 2: "invalid input";
+ int idx = Integer.parseInt(reqs[1]) - 1;
+ return new DeleteCommand(req, idx);
+ }
+ if(reqs[0].equals("find")){
+ assert reqs.length > 1: "invalid input";
+ String search = reqs[1];
+ return new FindCommand(req, search);
+ }
+ Task task = getTask(req);
+ return new AddCommand(req, task);
+ }
+
+
+}
diff --git a/src/main/java/duke/Storage.java b/src/main/java/duke/Storage.java
new file mode 100644
index 00000000..a8e2597d
--- /dev/null
+++ b/src/main/java/duke/Storage.java
@@ -0,0 +1,77 @@
+package duke;
+
+import duke.task.Deadline;
+import duke.task.Event;
+import duke.task.Task;
+import duke.task.Todo;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Scanner;
+
+public class Storage {
+ public String filepath;
+
+ /**
+ * storage constructor
+ * @param filepath the address of file path
+ */
+ public Storage(String filepath){
+ this.filepath = filepath;
+
+ }
+
+ /**
+ * store the task list to selected file
+ * @param tasks
+ * @throws IOException
+ */
+
+ public void store(TaskList tasks) throws IOException {
+ File file = new File(filepath);
+ File dir = file.getParentFile();
+ if(!file.exists()){
+ if(!dir.exists()){
+ dir.mkdirs();
+ }
+ file.createNewFile();
+ }
+ FileWriter fw = new FileWriter(file);
+ for(int i = 0; i < tasks.size(); i++){
+ fw.write(tasks.taskList.get(i).toStoreString());
+ }
+ fw.close();
+ }
+
+
+ /**
+ * load task list from selected file
+ * @return task List from selected file
+ * @throws FileNotFoundException
+ */
+ public TaskList load() throws FileNotFoundException {
+ TaskList tasks = new TaskList();
+ File file = new File(filepath);
+ Scanner sc = new Scanner(file);
+ while(sc.hasNext()){
+ String line = sc.nextLine();
+ String[] data = line.split(" \\| ");
+ boolean isDone = data[1].equals("1") ? true : false;
+ Task task;
+ if(data[0].equals("T")){
+ task = new Todo(isDone, data[2]);
+ }
+ else if(data[0].equals("D")){
+ task = new Deadline(isDone, data[2], data[3]);
+ }
+ else{
+ task = new Event(isDone, data[2], data[3]);
+ }
+ tasks.addTask(task);
+ }
+ return tasks;
+ }
+
+}
diff --git a/src/main/java/duke/TaskList.java b/src/main/java/duke/TaskList.java
new file mode 100644
index 00000000..b91c4305
--- /dev/null
+++ b/src/main/java/duke/TaskList.java
@@ -0,0 +1,38 @@
+package duke;
+
+import duke.task.Task;
+
+import java.util.ArrayList;
+
+public class TaskList {
+ public ArrayList taskList = new ArrayList<>();
+
+ public void addTask(Task t){
+ taskList.add(t);
+ }
+
+ public Task deleteTask(int idx){
+ Task t = taskList.get(idx);
+ taskList.remove(idx);
+ return t;
+ }
+
+ public Task doneTask(int idx){
+ taskList.get(idx).doTask();
+ return taskList.get(idx);
+ }
+
+ public int size(){
+ return taskList.size();
+ }
+
+ public TaskList find(String search){
+ TaskList tl = new TaskList();
+ for(Task task: taskList){
+ if(task.containInfo(search)){
+ tl.addTask(task);
+ }
+ }
+ return tl;
+ }
+}
diff --git a/src/main/java/duke/Ui.java b/src/main/java/duke/Ui.java
new file mode 100644
index 00000000..a6619d94
--- /dev/null
+++ b/src/main/java/duke/Ui.java
@@ -0,0 +1,90 @@
+package duke;
+
+import duke.task.Task;
+
+import java.util.Scanner;
+
+public class Ui {
+
+ public void showLine(){
+ System.out.println(" -----------------------------------------------");
+ }
+
+ public String readReq(){
+ Scanner sc = new Scanner(System.in);
+ return sc.nextLine();
+ }
+
+ public void showReq(String req){
+ System.out.println(req + "\n");
+ showLine();
+ }
+
+ public void showAdd(TaskList tasks, Task task){
+ System.out.println(" Got it. I've added this task:");
+ System.out.print(" ");
+ task.showTask();
+ System.out.println(" Now you have " + tasks.size() + " tasks in the list.");
+ System.out.println();
+ showLine();
+ }
+
+ public void showDelete(TaskList tasks, Task task){
+ System.out.println(" Noted! I've removed this task:");
+ System.out.print(" ");
+ task.showTask();
+ System.out.println(" Now you have " + tasks.size() + " tasks in the list.");
+ System.out.println();
+ showLine();
+ }
+
+ public void showDone(Task task){
+ System.out.println(" Nice! I've marked this task as done:");
+ System.out.print(" ");
+ task.showTask();
+ System.out.println();
+ showLine();
+ }
+
+ public void showList(TaskList tasks){
+ System.out.println(" Here are the tasks in your list:");
+ for(int i = 0; i < tasks.size(); i++){
+ System.out.print(" " + (i + 1) + ".");
+ tasks.taskList.get(i).showTask();
+ }
+ System.out.println();
+ showLine();
+ }
+
+ public void showExit(){
+ System.out.println(" Bye.Hope to see you again soon!\n");
+ showLine();
+ }
+
+ public void showFind(TaskList tasks){
+ System.out.println(" Here are the matching tasks in your list:");
+ for(int i = 0; i < tasks.size(); i++){
+ System.out.print(" " + (i + 1) + ".");
+ tasks.taskList.get(i).showTask();
+ }
+ System.out.println();
+ showLine();
+ }
+
+ public void showLoadException(){
+ System.out.println("No data can be loaded! ");
+ System.out.println();
+ }
+
+ public void showStoreException(){
+ System.out.println("There may be a problem with the storage! ");
+ System.out.println();
+ }
+
+ public void showException(Exception e, String req){
+ showReq(req);
+ System.out.println(" " + e.getMessage());
+ System.out.println();
+ showLine();
+ }
+}
diff --git a/src/main/java/duke/command/AddCommand.java b/src/main/java/duke/command/AddCommand.java
new file mode 100644
index 00000000..651e4868
--- /dev/null
+++ b/src/main/java/duke/command/AddCommand.java
@@ -0,0 +1,28 @@
+package duke.command;
+
+import duke.Storage;
+import duke.TaskList;
+import duke.Ui;
+import duke.task.Task;
+
+import java.io.IOException;
+
+public class AddCommand extends Command{
+ public Task task;
+
+ public AddCommand(String req, Task task){
+ this.task = task;
+ this.req = req;
+ }
+
+ public void execute(TaskList tasks, Ui ui, Storage storage) throws IOException {
+ ui.showReq(req);
+ tasks.addTask(task);
+ ui.showAdd(tasks, task);
+ storage.store(tasks);
+ }
+
+ public boolean isExit(){
+ return false;
+ }
+}
diff --git a/src/main/java/duke/command/Command.java b/src/main/java/duke/command/Command.java
new file mode 100644
index 00000000..6f8d0c12
--- /dev/null
+++ b/src/main/java/duke/command/Command.java
@@ -0,0 +1,15 @@
+package duke.command;
+
+import duke.Storage;
+import duke.TaskList;
+import duke.Ui;
+
+import java.io.IOException;
+
+public abstract class Command {
+ public String req;
+
+ public abstract void execute(TaskList tasks, Ui ui, Storage storage) throws IOException;
+
+ public abstract boolean isExit();
+}
diff --git a/src/main/java/duke/command/DeleteCommand.java b/src/main/java/duke/command/DeleteCommand.java
new file mode 100644
index 00000000..99dd7235
--- /dev/null
+++ b/src/main/java/duke/command/DeleteCommand.java
@@ -0,0 +1,28 @@
+package duke.command;
+
+import duke.Storage;
+import duke.TaskList;
+import duke.Ui;
+import duke.task.Task;
+
+import java.io.IOException;
+
+public class DeleteCommand extends Command{
+ public int idx;
+
+ public DeleteCommand(String req, int idx){
+ this.idx = idx;
+ this.req = req;
+ }
+
+ public void execute(TaskList tasks, Ui ui, Storage storage) throws IOException {
+ ui.showReq(req);
+ Task t = tasks.deleteTask(idx);
+ ui.showDelete(tasks, t);
+ storage.store(tasks);
+ }
+
+ public boolean isExit(){
+ return false;
+ }
+}
diff --git a/src/main/java/duke/command/DoneCommand.java b/src/main/java/duke/command/DoneCommand.java
new file mode 100644
index 00000000..a9d868d0
--- /dev/null
+++ b/src/main/java/duke/command/DoneCommand.java
@@ -0,0 +1,28 @@
+package duke.command;
+
+import duke.Storage;
+import duke.TaskList;
+import duke.Ui;
+import duke.task.Task;
+
+import java.io.IOException;
+
+public class DoneCommand extends Command{
+ public int idx;
+
+ public DoneCommand(String req, int idx){
+ this.idx = idx;
+ this.req = req;
+ }
+
+ public void execute(TaskList tasks, Ui ui, Storage storage) throws IOException {
+ ui.showReq(req);
+ Task t = tasks.doneTask(idx);
+ ui.showDone(t);
+ storage.store(tasks);
+ }
+
+ public boolean isExit(){
+ return false;
+ }
+}
diff --git a/src/main/java/duke/command/ExitCommand.java b/src/main/java/duke/command/ExitCommand.java
new file mode 100644
index 00000000..373704be
--- /dev/null
+++ b/src/main/java/duke/command/ExitCommand.java
@@ -0,0 +1,21 @@
+package duke.command;
+
+import duke.Storage;
+import duke.TaskList;
+import duke.Ui;
+
+public class ExitCommand extends Command{
+
+ public ExitCommand(String req){
+ this.req = req;
+ }
+
+ public void execute(TaskList tasks, Ui ui, Storage storage){
+ ui.showReq(req);
+ ui.showExit();
+ }
+
+ public boolean isExit(){
+ return true;
+ }
+}
diff --git a/src/main/java/duke/command/FindCommand.java b/src/main/java/duke/command/FindCommand.java
new file mode 100644
index 00000000..0e8257e1
--- /dev/null
+++ b/src/main/java/duke/command/FindCommand.java
@@ -0,0 +1,26 @@
+package duke.command;
+
+import duke.Storage;
+import duke.TaskList;
+import duke.Ui;
+
+import java.io.IOException;
+
+public class FindCommand extends Command{
+ public String search;
+
+ public FindCommand(String req, String search){
+ this.req = req;
+ this.search = search;
+ }
+
+ public void execute(TaskList tasks, Ui ui, Storage storage) throws IOException {
+ ui.showReq(req);
+ TaskList tl = tasks.find(search);
+ ui.showFind(tl);
+ }
+
+ public boolean isExit(){
+ return false;
+ }
+}
diff --git a/src/main/java/duke/command/ListCommand.java b/src/main/java/duke/command/ListCommand.java
new file mode 100644
index 00000000..85617415
--- /dev/null
+++ b/src/main/java/duke/command/ListCommand.java
@@ -0,0 +1,21 @@
+package duke.command;
+
+import duke.Storage;
+import duke.TaskList;
+import duke.Ui;
+
+public class ListCommand extends Command{
+
+ public ListCommand(String req){
+ this.req = req;
+ }
+
+ public void execute(TaskList tasks, Ui ui, Storage storage){
+ ui.showReq(req);
+ ui.showList(tasks);
+ }
+
+ public boolean isExit(){
+ return false;
+ }
+}
diff --git a/src/main/java/duke/exception/InvalidException.java b/src/main/java/duke/exception/InvalidException.java
new file mode 100644
index 00000000..47ea89ce
--- /dev/null
+++ b/src/main/java/duke/exception/InvalidException.java
@@ -0,0 +1,9 @@
+package duke.exception;
+
+public class InvalidException extends Exception{
+ public InvalidException(){}
+
+ public String getMessage(){
+ return "☹ OOPS!!! I'm sorry, but I don't know what that means :-(";
+ }
+}
diff --git a/src/main/java/duke/exception/MissReqException.java b/src/main/java/duke/exception/MissReqException.java
new file mode 100644
index 00000000..a1a45414
--- /dev/null
+++ b/src/main/java/duke/exception/MissReqException.java
@@ -0,0 +1,12 @@
+package duke.exception;
+
+public class MissReqException extends Exception{
+ String message;
+ public MissReqException(String req){
+ message = String.format("☹ OOPS!!! The description of a %s cannot be empty.", req);
+
+ }
+ public String getMessage(){
+ return message;
+ }
+}
diff --git a/src/main/java/duke/task/Deadline.java b/src/main/java/duke/task/Deadline.java
new file mode 100644
index 00000000..cee8c32f
--- /dev/null
+++ b/src/main/java/duke/task/Deadline.java
@@ -0,0 +1,56 @@
+package duke.task;
+
+import duke.DateFun;
+
+import java.time.LocalDate;
+
+public class Deadline extends Task{
+ String by;
+ LocalDate deadLineDate;
+
+ /**
+ * Deadline constructor
+ * @param description
+ * @param by deadline date.
+ */
+
+ public Deadline(String description, String by){
+ super(description);
+ this.by = by;
+ deadLineDate = DateFun.stringToLocalDate(by);
+ type = Types.DEADLINE;
+ }
+
+ /**
+ *
+ * @param isDone status
+ * @param description
+ * @param by
+ */
+
+ public Deadline(boolean isDone, String description, String by){
+ super(description);
+ this.by = by;
+ this.isDone = isDone;
+ deadLineDate = DateFun.stringToLocalDate(by);
+ type = Types.DEADLINE;
+ }
+
+ /**
+ * print deardline task
+ */
+ public void showTask(){
+ String mark = isDone ? "X" : " ";
+ System.out.println("[D][" + mark + "] " + description + " (by: " + DateFun.LocalDateToString(deadLineDate) + ")");
+ }
+
+ /**
+ * convert deadline to string
+ * @return a string
+ */
+ public String toStoreString(){
+ int state = isDone ? 1 : 0;
+ return 'D' + " | " + state + " | " + description + " | " + by + System.lineSeparator();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/duke/task/Event.java b/src/main/java/duke/task/Event.java
new file mode 100644
index 00000000..cfcd5738
--- /dev/null
+++ b/src/main/java/duke/task/Event.java
@@ -0,0 +1,40 @@
+package duke.task;
+
+import duke.DateFun;
+
+import java.time.LocalDate;
+
+public class Event extends Task{
+ String at;
+ LocalDate begin;
+ LocalDate end;
+
+ public Event(String description, String at){
+ super(description);
+ this.at = at;
+ String[] dateStr = at.split(" - ");
+ begin = DateFun.stringToLocalDate(dateStr[0]);
+ end = DateFun.stringToLocalDate(dateStr[1]);
+ type = Types.EVENT;
+ }
+
+ public Event(boolean isDone, String description, String at){
+ super(description);
+ this.at = at;
+ this.isDone = isDone;
+ String[] dateStr = at.split(" - ");
+ begin = DateFun.stringToLocalDate(dateStr[0]);
+ end = DateFun.stringToLocalDate(dateStr[1]);
+ type = Types.EVENT;
+ }
+
+ public void showTask(){
+ String mark = isDone ? "X" : " ";
+ System.out.println("[E][" + mark + "] " + description + " (at: " + DateFun.LocalDateToString(begin) + " - " + DateFun.LocalDateToString(end) + ")");
+ }
+
+ public String toStoreString(){
+ int state = isDone ? 1 : 0;
+ return 'E' + " | " + state + " | " + description + " | " + at + System.lineSeparator();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java
new file mode 100644
index 00000000..143db1b8
--- /dev/null
+++ b/src/main/java/duke/task/Task.java
@@ -0,0 +1,32 @@
+package duke.task;
+
+public abstract class Task {
+ String description;
+ boolean isDone;
+ Types type;
+
+ public Task(String description){
+ this.description = description;
+ isDone = false;
+ type = Types.UNKNOWN;
+ }
+
+ public abstract void showTask();
+
+ public void doTask(){
+ this.isDone = true;
+ }
+
+ public abstract String toStoreString();
+
+ public boolean containInfo(String info){
+ double match = 0.6;
+ int minSize = (int)Math.ceil(info.length() * match);
+ for(int i = 0; i < info.length() - minSize + 1; i++){
+ if(description.contains(info.substring(i, i + minSize))){
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/duke/task/Todo.java b/src/main/java/duke/task/Todo.java
new file mode 100644
index 00000000..db751349
--- /dev/null
+++ b/src/main/java/duke/task/Todo.java
@@ -0,0 +1,25 @@
+package duke.task;
+
+public class Todo extends Task{
+
+ public Todo(String description){
+ super(description);
+ type = Types.TODO;
+ }
+
+ public Todo(boolean isDone, String description){
+ super(description);
+ this.isDone = isDone;
+ type = Types.TODO;
+ }
+
+ public void showTask(){
+ String mark = isDone ? "X" : " ";
+ System.out.println("[T][" + mark + "] " + description);
+ }
+
+ public String toStoreString(){
+ int state = isDone ? 1 : 0;
+ return 'T' + " | " + state + " | " + description + System.lineSeparator();
+ }
+}
diff --git a/src/main/java/duke/task/Types.java b/src/main/java/duke/task/Types.java
new file mode 100644
index 00000000..3718114f
--- /dev/null
+++ b/src/main/java/duke/task/Types.java
@@ -0,0 +1,5 @@
+package duke.task;
+
+public enum Types {
+ TODO, EVENT, DEADLINE, UNKNOWN
+}
diff --git a/src/main/java/duke/test/DateFunTest.java b/src/main/java/duke/test/DateFunTest.java
new file mode 100644
index 00000000..72477903
--- /dev/null
+++ b/src/main/java/duke/test/DateFunTest.java
@@ -0,0 +1,19 @@
+package duke.test;
+import duke.DateFun;
+import java.time.LocalDate;
+import org.junit.Test;
+import static org.junit.Assert.*;
+public class DateFunTest {
+
+ @Test
+ public void stringToLocalDateTest(){
+ assertEquals(LocalDate.of(2021, 10, 14), DateFun.stringToLocalDate("2021-10-14"));
+ assertEquals(LocalDate.of(2021, 11, 15), DateFun.stringToLocalDate("2021-11-15"));
+ }
+
+ @Test
+ public void LocalDateToStringTest(){
+ assertEquals("Oct 11 2000", DateFun.LocalDateToString(LocalDate.of(2000, 10, 11)));
+ assertEquals("Jan 31 2021", DateFun.LocalDateToString(LocalDate.of(2021, 1, 31)));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/duke/test/ParseTest.java b/src/main/java/duke/test/ParseTest.java
new file mode 100644
index 00000000..aeb3b80a
--- /dev/null
+++ b/src/main/java/duke/test/ParseTest.java
@@ -0,0 +1,15 @@
+package duke.test;
+import duke.Parser;
+import duke.command.DeleteCommand;
+import duke.exception.InvalidException;
+import duke.exception.MissReqException;
+import org.junit.Test;
+import static org.junit.Assert.*;
+public class ParseTest {
+ @Test
+ public void parseTest() throws MissReqException, InvalidException {
+ assertEquals(0, ((DeleteCommand)Parser.parse("delete 1")).idx);
+ assertEquals("delete 1", Parser.parse("delete 1").req);
+ assertEquals("list", Parser.parse("list").req);
+ }
+}
diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat
index 08737446..62752b88 100644
--- a/text-ui-test/runtest.bat
+++ b/text-ui-test/runtest.bat
@@ -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