diff --git a/README.md b/README.md
index 8715d4d9..63d0ad6b 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
____ _
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/Duke/Duke.java b/src/main/java/Duke/Duke.java
new file mode 100644
index 00000000..3ae813b7
--- /dev/null
+++ b/src/main/java/Duke/Duke.java
@@ -0,0 +1,139 @@
+package Duke;
+
+import Duke.ExceptionList.*;
+import Duke.Storage.Storage;
+import Duke.TaskList.*;
+import Duke.Ui.Ui;
+
+import java.util.Scanner;
+import java.io.IOException; // Import the IOException class to handle errors
+import java.util.regex.Pattern;
+
+public class Duke {
+
+ private Storage storage;
+ private TaskList tl;
+ private Ui ui;
+
+ public Duke(){
+ run();
+ }
+
+ private Pattern pattern = Pattern.compile("-?\\d+(\\.\\d+)?");
+
+ public boolean isNumeric(String strNum) {
+ if (strNum == null) {
+ return false;
+ }
+ return pattern.matcher(strNum).matches();
+ }
+
+ public void run() {
+ ui = new Ui();
+ ui.showStartMessage();
+ ui.printBreak();
+ storage = new Storage();
+ try {
+ tl = new TaskList(storage.load());
+ }
+ catch (DukeException | IOException e) {
+ ui.showLoadingError();
+ tl = new TaskList();
+ }
+ String line, desc, desc2, s1, s2;
+ while (true) {
+ Scanner in = new Scanner(System.in);
+ line = in.nextLine();
+ try {
+ if (!line.isEmpty()) {
+ desc2 = "";
+ if (line.contains(" ")) {
+
+ String[] input = line.split(" ", 2);
+ desc = input[0];
+ desc2 = input[1];
+ } else {
+ desc = line;
+ }
+ if (line.equalsIgnoreCase("bye")) {
+ storage.saveTask(tl);
+ break;
+ }
+ if (line.equalsIgnoreCase("list")) {
+ ui.printBreak();
+ tl.printTaskList();
+ ui.printBreak();
+ } else if (desc.equalsIgnoreCase("done")) {
+ if (desc2.isEmpty() || !isNumeric(desc2)){
+ throw new CommandNotFoundException("Please enter a number.");
+ }else if (Integer.parseInt(desc2) > tl.getSize() || Integer.parseInt(desc2) <= 0){
+ throw new CommandNotFoundException("Sorry, Please enter a legit number.");
+ }
+ ui.printBreak();
+ int x = Integer.parseInt(desc2);
+ tl.setDoneStatus(x);
+ ui.printBreak();
+ } else if (desc.equalsIgnoreCase("delete")) {
+ if (tl.getSize()==0){
+ throw new NoListFoundException("Sorry, I am unable to delete any task because no task is found.");
+ }
+ if (desc2.isEmpty()|| !isNumeric(desc2)){
+ throw new CommandNotFoundException("Please enter a number.");
+ }else if (Integer.parseInt(desc2) > tl.getSize() || Integer.parseInt(desc2) <= 0){
+ throw new CommandNotFoundException("Sorry, Please enter a legit number.");
+ }
+ ui.printBreak();
+ int x = Integer.parseInt(desc2);
+ System.out.println("I've deleted this task entered: ");
+ tl.deleteTask(x);
+ ui.printBreak();
+ } else if (desc.equalsIgnoreCase("deadline")) {
+ if (desc2.isEmpty()){
+ throw new deadlineNotFoundException("Sorry, there cannot be any empty deadline task.");
+ }
+ ui.printBreak();
+ tl.addTask(desc,desc2,false);
+ System.out.println("Got it. I've added this task: ");
+ System.out.println(tl.getLastAddedTask());
+ ui.printTotalTask(tl.getSize());
+ ui.printBreak();
+ } else if (desc.equalsIgnoreCase("event")) {
+ if (desc2.isEmpty()){
+ throw new eventNotFoundException("Sorry, there cannot be any empty event task.");
+ }
+ ui.printBreak();
+ tl.addTask(desc,desc2,false);
+ System.out.println("Got it. I've added this task: ");
+ System.out.println(tl.getLastAddedTask());
+ ui.printTotalTask(tl.getSize());
+ ui.printBreak();
+ } else if (desc.equalsIgnoreCase("todo")) {
+ if (desc2.isEmpty()){
+ throw new toDoNotFoundException("Sorry, there cannot be any empty todo task.");
+ }
+ ui.printBreak();
+ tl.addTask(desc,desc2,false);
+ System.out.println("Got it. I've added this task: ");
+ System.out.println(tl.getLastAddedTask());
+ ui.printTotalTask(tl.getSize());
+ ui.printBreak();
+ } else {
+ throw new CommandNotFoundException("Sorry, I am unable to handle your request.");
+ }
+ }
+ } catch (toDoNotFoundException | CommandNotFoundException | NoListFoundException | deadlineNotFoundException | eventNotFoundException e ) {
+ ui.printBreak();
+ System.out.println(e.getMessage());
+ ui.printBreak();
+ continue;
+ }
+ }
+ ui.printBreak();
+ ui.printBye();
+ ui.printBreak();
+ }
+
+ public static void main(String[] args) {
+ new Duke();
+ }
+}
diff --git a/src/main/java/Duke/ExceptionList/CommandNotFoundException.java b/src/main/java/Duke/ExceptionList/CommandNotFoundException.java
new file mode 100644
index 00000000..7d4eb33a
--- /dev/null
+++ b/src/main/java/Duke/ExceptionList/CommandNotFoundException.java
@@ -0,0 +1,11 @@
+package Duke.ExceptionList;
+
+public class CommandNotFoundException extends Exception{
+ //no other code needed
+ public CommandNotFoundException(String message) {
+ super(message);
+ }
+ public CommandNotFoundException(){
+ super();
+ }
+}
diff --git a/src/main/java/Duke/ExceptionList/DukeException.java b/src/main/java/Duke/ExceptionList/DukeException.java
new file mode 100644
index 00000000..09a0d5b1
--- /dev/null
+++ b/src/main/java/Duke/ExceptionList/DukeException.java
@@ -0,0 +1,10 @@
+package Duke.ExceptionList;
+
+public class DukeException extends Exception {
+ public DukeException(String message) {
+ super(message);
+ }
+ public DukeException(){
+ super();
+ }
+}
diff --git a/src/main/java/Duke/ExceptionList/NoListFoundException.java b/src/main/java/Duke/ExceptionList/NoListFoundException.java
new file mode 100644
index 00000000..1d4be88d
--- /dev/null
+++ b/src/main/java/Duke/ExceptionList/NoListFoundException.java
@@ -0,0 +1,12 @@
+package Duke.ExceptionList;
+
+public class NoListFoundException extends Exception {
+ //no other code needed
+ public NoListFoundException(String message) {
+ super(message);
+ }
+
+ public NoListFoundException() {
+ super();
+ }
+}
diff --git a/src/main/java/Duke/ExceptionList/deadlineNotFoundException.java b/src/main/java/Duke/ExceptionList/deadlineNotFoundException.java
new file mode 100644
index 00000000..9cab566c
--- /dev/null
+++ b/src/main/java/Duke/ExceptionList/deadlineNotFoundException.java
@@ -0,0 +1,11 @@
+package Duke.ExceptionList;
+
+public class deadlineNotFoundException extends Exception{
+ //no other code needed
+ public deadlineNotFoundException(String message) {
+ super(message);
+ }
+ public deadlineNotFoundException(){
+ super();
+ }
+}
diff --git a/src/main/java/Duke/ExceptionList/eventNotFoundException.java b/src/main/java/Duke/ExceptionList/eventNotFoundException.java
new file mode 100644
index 00000000..baf9a3fe
--- /dev/null
+++ b/src/main/java/Duke/ExceptionList/eventNotFoundException.java
@@ -0,0 +1,10 @@
+package Duke.ExceptionList;
+
+public class eventNotFoundException extends Exception{
+ public eventNotFoundException(String message) {
+ super(message);
+ }
+ public eventNotFoundException(){
+ super();
+ }
+}
diff --git a/src/main/java/Duke/ExceptionList/toDoNotFoundException.java b/src/main/java/Duke/ExceptionList/toDoNotFoundException.java
new file mode 100644
index 00000000..73cc06ee
--- /dev/null
+++ b/src/main/java/Duke/ExceptionList/toDoNotFoundException.java
@@ -0,0 +1,11 @@
+package Duke.ExceptionList;
+
+public class toDoNotFoundException extends Exception{
+ //no other code needed
+ public toDoNotFoundException(String message) {
+ super(message);
+ }
+ public toDoNotFoundException(){
+ super();
+ }
+}
diff --git a/src/main/java/Duke/Storage/Storage.java b/src/main/java/Duke/Storage/Storage.java
new file mode 100644
index 00000000..5395bd7d
--- /dev/null
+++ b/src/main/java/Duke/Storage/Storage.java
@@ -0,0 +1,79 @@
+package Duke.Storage;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import Duke.TaskList.*;
+import java.util.ArrayList;
+
+public class Storage {
+ protected final String DEFAULT_STORAGE_FILEPATH = "duke.txt";
+ protected final String home = System.getProperty("user.home");
+ private String filePath = DEFAULT_STORAGE_FILEPATH;
+ protected Path path;
+
+ public Storage(){
+ filePath = DEFAULT_STORAGE_FILEPATH;
+ path = Paths.get(home, filePath);
+ }
+ public Storage(String filepath) throws IOException {
+ this.filePath = filePath;
+ path = Paths.get(home, filePath);
+ if (!isValidPath(path)) {}
+ //check if file exist
+ isPathExist();
+ }
+
+ private static boolean isValidPath(Path filePath) {
+ return filePath.toString().endsWith(".txt");
+ }
+
+ private void isPathExist() throws IOException {
+ Path path = Paths.get(home, filePath);
+ // check if the directory and file exists, else create
+ if (!Files.exists(path)) {
+ Files.createDirectory(Paths.get(home,"data"));
+ Files.createFile(path);
+ }
+ }
+ /**
+ * This method save all the tasks in the ArrayList of TaskLists.
+ *
+ * @param tasks ArrayList of Task in TaskLists.
+ * */
+ public void saveTask(TaskList tasks){
+ path = Paths.get(home, "data",DEFAULT_STORAGE_FILEPATH);
+
+ // start saving task
+ String content = "";
+ ArrayList save = tasks.getTaskList();
+ for (Task task : save)
+ content += task.saveTask() + System.lineSeparator();
+ //System.out.println(content);
+ try{
+ writeToFile(path+"",content);
+ }catch(IOException e){
+ e.printStackTrace();
+ }
+ }
+ /**
+ * This method writes all the text into the file.
+ *
+ * @param filePath Path of the file to be written.
+ * @param text String of the text to be stored in the file.
+ * */
+ private void writeToFile(String filePath, String text) throws IOException {
+ FileWriter fw = new FileWriter(filePath);
+ fw.write(text);
+ fw.close();
+ }
+
+ public String load() throws IOException {
+ String path = home+"\\data\\"+filePath;
+ //return (File) Files.readAllLines(Path.of(path));
+ return path; // create a File for the given file path
+ }
+}
diff --git a/src/main/java/Duke/TaskList/Deadline.java b/src/main/java/Duke/TaskList/Deadline.java
new file mode 100644
index 00000000..4eb36ef1
--- /dev/null
+++ b/src/main/java/Duke/TaskList/Deadline.java
@@ -0,0 +1,18 @@
+package Duke.TaskList;
+
+public class Deadline extends Task {
+ protected String by;
+
+ public Deadline(String description, String by) {
+ super(description);
+ this.by = by;
+ }
+
+ @Override
+ public String toString() {
+ return "[D]" + super.toString() + " (by: " + by + ")";
+ }
+
+ @Override
+ public String saveTask(){ return "D|" + super.saveTask() + "|" + by;}
+}
diff --git a/src/main/java/Duke/TaskList/Event.java b/src/main/java/Duke/TaskList/Event.java
new file mode 100644
index 00000000..75945739
--- /dev/null
+++ b/src/main/java/Duke/TaskList/Event.java
@@ -0,0 +1,19 @@
+package Duke.TaskList;
+
+public class Event extends Task{
+ protected String at;
+
+ public Event(String description, String at) {
+ super(description);
+ this.at = at;
+ }
+
+ @Override
+ public String toString() {
+ return "[E]" + super.toString() + " (at: " + at + ")";
+ }
+
+ @Override
+ public String saveTask(){ return "E|" + super.saveTask() + "|" + at;}
+
+}
\ No newline at end of file
diff --git a/src/main/java/Duke/TaskList/Task.java b/src/main/java/Duke/TaskList/Task.java
new file mode 100644
index 00000000..02f398cf
--- /dev/null
+++ b/src/main/java/Duke/TaskList/Task.java
@@ -0,0 +1,54 @@
+package Duke.TaskList;
+
+public class Task {
+ protected String description;
+ protected boolean isDone;
+
+ public Task(String description) {
+ this.description = description;
+ this.isDone = false;
+ }
+ public Task(String description,boolean isDone){
+ this.description = description;
+ this.isDone = isDone;
+ }
+
+ public String getStatusIcon() {
+ return (isDone ? "X" : " "); // mark done task with X
+ }
+
+ public String getStatusDone(){
+ return (isDone ? "1" : "0"); // mark done task with 1
+ }
+
+ public void setDone(boolean done){
+ this.isDone = done;
+ }
+
+ public String getDescription(){
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+ /**
+ * This method returns the object in String format.
+ *
+ * @return the object in string format
+ * */
+ public String toString(){
+ String print = "[" + getStatusIcon()+"] " + getDescription();
+ return print;
+ }
+ /**
+ * This method return the object in String format.
+ *
+ * @return the object in string format for the task to be saved.
+ * */
+ public String saveTask(){
+ String save = getStatusDone() + "|" + getDescription();
+ return save;
+ }
+
+}
diff --git a/src/main/java/Duke/TaskList/TaskList.java b/src/main/java/Duke/TaskList/TaskList.java
new file mode 100644
index 00000000..099e6cb2
--- /dev/null
+++ b/src/main/java/Duke/TaskList/TaskList.java
@@ -0,0 +1,133 @@
+package Duke.TaskList;
+
+import Duke.ExceptionList.*;
+
+import java.io.*;
+import java.util.ArrayList;
+
+
+public class TaskList {
+ ArrayList taskLists = new ArrayList();
+ public TaskList() {
+ }
+ public TaskList(String f) throws DukeException {
+ //parse the String from the text file then use it to inside into the DB
+ try (BufferedReader br = new BufferedReader(new FileReader(f))) {
+ String line;
+ while ((line = br.readLine()) != null) {
+ // process the line.
+ addFileTask(line);
+ }
+ } catch (FileNotFoundException e) {
+ throw new DukeException("File is not found. Please, make sure you entered the correct path.");
+ } catch (toDoNotFoundException | eventNotFoundException | deadlineNotFoundException |IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void addFileTask(String str) throws toDoNotFoundException, eventNotFoundException, deadlineNotFoundException {
+ String[] input = str.split("\\|", 2);
+ String s1 = input[0];
+ String s2 = input[1];
+ addTask(s1, s2, true);
+ }
+
+ /**
+ * Adds task into the ArrayList of Tasks object. The cmd has been passed through validation thus unwanted commands
+ * will not be written into the list.
+ *
+ * @param cmd the given command by the user
+ * @param description details on the task listed by user
+ * @param file checks if it is from a loaded file or an input string
+ * */
+ public void addTask(String cmd, String description, boolean file) throws toDoNotFoundException, eventNotFoundException, deadlineNotFoundException {
+ if (cmd.equalsIgnoreCase("todo") || cmd.equalsIgnoreCase("T")) {
+ if (description.isEmpty()) {
+ throw new toDoNotFoundException("Sorry, there cannot be any empty todo task.");
+ }
+ if (file) {
+ String[] input = description.split("\\|", 2);
+ String s1 = input[0];
+ String s2 = input[1];
+ taskLists.add(new ToDo(s2));
+ if (s1.equals("1")) {
+ taskLists.get(taskLists.size() - 1).setDone(true);
+ }
+ } else taskLists.add(new ToDo(description));
+
+ } else if (cmd.equalsIgnoreCase("deadline") || cmd.equalsIgnoreCase("D")) {
+ if (description.isEmpty()) {
+ throw new deadlineNotFoundException("Sorry, there cannot be any empty deadline task.");
+ }
+ if (file) {
+ String[] input = description.split("\\|", 3);
+ String s1 = input[0];
+ String s2 = input[1];
+ String s3 = input[2];
+ taskLists.add(new Deadline(s2, s3));
+ if (s1.equals("1")) {
+ taskLists.get(taskLists.size() - 1).setDone(true);
+ }
+ } else {
+ String[] input = description.split("/by ", 2);
+ String s1 = input[0];
+ String s2 = input[1];
+ taskLists.add(new Deadline(s1, s2));
+ }
+
+ } else if (cmd.equalsIgnoreCase("event") || cmd.equalsIgnoreCase("E")) {
+ if (description.isEmpty()) {
+ throw new eventNotFoundException("Sorry, there cannot be any empty event task.");
+ }
+ if (file) {
+ String[] input = description.split("\\|", 3);
+ String s1 = input[0];
+ String s2 = input[1];
+ String s3 = input[2];
+ taskLists.add(new Event(s2, s3));
+ if (s1.equals("1")) {
+ taskLists.get(taskLists.size() - 1).setDone(true);
+ }
+ } else {
+ String[] input = description.split("/at ", 2);
+ String s1 = input[0];
+ String s2 = input[1];
+ taskLists.add(new Event(s1, s2));
+ }
+ }
+ }
+
+ public String getLastAddedTask() {
+ return taskLists.get(taskLists.size() - 1).toString();
+ }
+ /**
+ * User input will perform a deleting of the specific task from the ArrayList of Tasks object.
+ *
+ * @param x the given position of the list given by the user
+ * */
+ public void deleteTask(int x) {
+ System.out.println(taskLists.get(x - 1).toString());
+ taskLists.remove(x - 1);
+ }
+
+ public void printTaskList() {
+ System.out.println("Here are the tasks in your list: ");
+ for (int i = 0; i < taskLists.size(); i++) {
+ System.out.println(taskLists.get(i).toString());
+ }
+ }
+
+ public void setDoneStatus(int x) {
+ taskLists.get(x - 1).setDone(true);
+ System.out.println("Nice! I've marked this task as done: ");
+ System.out.println(taskLists.get(x - 1).toString());
+ }
+
+ public int getSize() {
+ return taskLists.size();
+ }
+
+ public ArrayList getTaskList() {
+ return taskLists;
+ }
+}
diff --git a/src/main/java/Duke/TaskList/ToDo.java b/src/main/java/Duke/TaskList/ToDo.java
new file mode 100644
index 00000000..afdfe427
--- /dev/null
+++ b/src/main/java/Duke/TaskList/ToDo.java
@@ -0,0 +1,16 @@
+package Duke.TaskList;
+
+public class ToDo extends Task{
+
+ public ToDo(String description) {
+ super(description);
+ }
+
+ @Override
+ public String toString() {
+ return "[T]" + super.toString();
+ }
+
+ @Override
+ public String saveTask(){ return "T|" + super.saveTask();}
+}
\ No newline at end of file
diff --git a/src/main/java/Duke/TaskList/taskToDo.java b/src/main/java/Duke/TaskList/taskToDo.java
new file mode 100644
index 00000000..39b9fa82
--- /dev/null
+++ b/src/main/java/Duke/TaskList/taskToDo.java
@@ -0,0 +1,5 @@
+package Duke.TaskList;
+
+public enum taskToDo {
+ todo,deadline,list,event,done,delete
+}
diff --git a/src/main/java/Duke/Ui/Ui.java b/src/main/java/Duke/Ui/Ui.java
new file mode 100644
index 00000000..243c2a69
--- /dev/null
+++ b/src/main/java/Duke/Ui/Ui.java
@@ -0,0 +1,46 @@
+package Duke.Ui;
+
+public class Ui {
+ private final String logo = " ____ _ \n"
+ + "| _ \\ _ _| | _____ \n"
+ + "| | | | | | | |/ / _ \\\n"
+ + "| |_| | |_| | < __/\n"
+ + "|____/ \\__,_|_|\\_\\___|\n";
+
+ private final String logoMessage = logo + "\nHello! I'm Duke.Duke. \nWhat can I do for you?";
+
+ private final String breakLines = "____________________________________________________________";
+
+ private String print(){
+ return logoMessage;
+ }
+
+ //Printing divider
+ public void printBreak() {
+ System.out.println(breakLines);
+ }
+
+ //Printing goodbye message
+ public void printBye() {
+ System.out.println("Bye. Hope to see you again soon!");
+ }
+
+ /**
+ * Listing the total number of Task object inside the TaskLists.
+ *
+ * @param counter the number of task in the TaskLists
+ * */
+ public void printTotalTask(int counter) {
+ System.out.println("Now you have " + counter + " tasks in the list.");
+ }
+
+ //Printing start message
+ public void showStartMessage(){
+ System.out.println(print());
+ }
+
+ //Printing Loading Error message
+ public void showLoadingError() {
+ System.out.println("Sorry file is not found. We will save a new copy.");
+ }
+}
diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..5699c741
--- /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/text-ui-test/runtest.bat b/text-ui-test/runtest.bat
index 08737446..cecfdb11 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