diff --git a/.gitignore b/.gitignore
index f69985ef1..d186d26b0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,5 @@ bin/
/text-ui-test/ACTUAL.txt
text-ui-test/EXPECTED-UNIX.TXT
+
+checkstyle.xml
\ No newline at end of file
diff --git a/Duke.txt b/Duke.txt
new file mode 100644
index 000000000..adf781cdd
--- /dev/null
+++ b/Duke.txt
@@ -0,0 +1,2 @@
+1. [T][ ] `
+2. [D][ ] ` (by: 99)
\ No newline at end of file
diff --git a/README.md b/README.md
index 8715d4d91..05af20f06 100644
--- a/README.md
+++ b/README.md
@@ -8,9 +8,9 @@ Prerequisites: JDK 11, update Intellij to the most recent version.
1. Open Intellij (if you are not in the welcome screen, click `File` > `Close Project` to close the existing project first)
1. Open the project into Intellij as follows:
- 1. Click `Open`.
- 1. Select the project directory, and click `OK`.
- 1. If there are any further prompts, accept the defaults.
+ 1. Click `Open`.
+ 1. Select the project directory, and click `OK`.
+ 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:
@@ -21,4 +21,4 @@ Prerequisites: JDK 11, update Intellij to the most recent version.
| | | | | | | |/ / _ \
| |_| | |_| | < __/
|____/ \__,_|_|\_\___|
- ```
+ ```
\ No newline at end of file
diff --git a/docs/README.md b/docs/README.md
index 8077118eb..5a1de4f53 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,29 +1,141 @@
-# User Guide
-## Features
-### Feature-ABC
+# Welcome to Duke!
+Duke is a CLI-based todo application.
+# Getting started
+After running the JAR file, an output file named "Duke.txt" will be created in the same directory of the JAR. Output will be saved into the file before the program exits, and the file will be reread the next time Duke runs.
-Description of the feature.
+To run the file, from the terminal, go to the same directory as your Duke.jar file, and run the command `java -jar Duke.jar`
-### Feature-XYZ
-Description of the feature.
+# Features and usage
+| Notation | Meaning |
+|--|--|
+| [T] | todo |
+| [D] | deadline|
+| [E] | event |
+| [ ] | incomplete task
+| [X] | completed task
-## Usage
-### `Keyword` - Describe action
-Describe the action and its outcome.
-Example of usage:
+## Add
+There are three types of tasks to be added. Namely, todo, deadline and event.
+### Todo
-`keyword (optional arguments)`
+To add a todo, command should be typed in the format
+`todo (taskname)`
+Example of a valid input:
+`todo get groceries`
-Expected outcome:
+Sample usage:
-Description of the outcome.
+ todo buy groceries
+ ____________________________________________________________
+ Got it. I've added this task:
+ [T][ ] buy groceries
+ Now you have 1 task in the list.
+ ____________________________________________________________
+
+
+
+### Event / Deadline
+
+To add an event or a deadline, command should be typed in the format `event (taskname) /(dd-MM-yyyy HH:mm)` or
+`event (taskname) /(additional info)`
+
+:white_check_mark: Sample usage with valid input:
+
+
+ deadline cs2113t project /tomorrow
+ ____________________________________________________________
+ Got it. I've added this task:
+ [D][ ] cs2113t project (by: tomorrow)
+ Now you have 2 tasks in the list.
+ ____________________________________________________________
+ event Mark's birthday party /07-03-2022 22:00
+ ____________________________________________________________
+ Got it. I've added this task:
+ [E][ ] Mark's birthday party (on: Mar 07 2022 22:00)
+ Now you have 3 tasks in the list.
+ ____________________________________________________________
+
+
+
+:x: Example of a invalid input:
+
+ deadline hello /
+ event /
+
+
+
+
+## List
+To list all the tasks, simply type
+`list`
+
+
+Sample usage:
+
+ list
+ ____________________________________________________________
+ 1. [T][ ] buy groceries
+ 2. [D][ ] cs2113t project (by: tomorrow)
+ 3. [E][ ] Mark's birthday party (on: Mar 07 2022 22:00)
+ ____________________________________________________________
+
+## Delete
+To delete a task, type in the command `delete (task number)`
+
+Sample usage:
+
+ delete 2
+ ____________________________________________________________
+ Noted. I've removed this task:
+ [D][ ] cs2113t project (by: tomorrow)
+ Now you have 2 tasks in the list.
+ ____________________________________________________________
+
+
+
+
+## Mark/Unmark
+To mark the task as completed, type in `mark (task number)`.
+Similarly, type in `unmark (task number)` to mark the task as incomplete.
+
+Sample usage:
+
+ mark 1
+ ____________________________________________________________
+ [T][X] buy groceries
+ ____________________________________________________________
+ unmark 1
+ ____________________________________________________________
+ [T][ ] buy groceries
+ ____________________________________________________________
+
+## Find
+To find task(s) containing a specific keyword, type in `find (keyword)`
+
+Sample usage:
+
+ find groceries
+ ____________________________________________________________
+ Here are the matching tasks in your list:
+ 1. [T][ ] buy groceries
+ ____________________________________________________________
+
+## Bye
+To exit the program, simply type "bye". The program terminates and the current state of the tasks is saved into "Duke.txt".
+
+Sample usage:
+
+ bye
+ ____________________________________________________________
+ Bye. Hope to see you again soon!
+ ____________________________________________________________
+
+
+
-```
-expected output
-```
diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
index 5d313334c..979a9df61 100644
--- a/src/main/java/Duke.java
+++ b/src/main/java/Duke.java
@@ -1,10 +1,60 @@
+import java.io.IOException;
+
+import duke.command.Command;
+import duke.exception.DukeException;
+import duke.parser.Parser;
+import duke.storage.Storage;
+import duke.task.TaskManager;
+import duke.ui.Ui;
+
public class Duke {
- public static void main(String[] args) {
- String logo = " ____ _ \n"
- + "| _ \\ _ _| | _____ \n"
- + "| | | | | | | |/ / _ \\\n"
- + "| |_| | |_| | < __/\n"
- + "|____/ \\__,_|_|\\_\\___|\n";
- System.out.println("Hello from\n" + logo);
+
+ //fields
+ private TaskManager taskManager;
+ private Ui ui;
+ private Storage storage;
+
+ //methods
+
+ /**
+ * Creates a Duke Object
+ * @param filePath filePath of the input/output file
+ */
+ public Duke(String filePath) {
+ ui = new Ui();
+ storage = new Storage(filePath);
+ try {
+ taskManager = new TaskManager();
+ taskManager.setTasks(storage.readFile());
+ } catch (DukeException e) {
+ ui.showError(e);
+ }
+ }
+
+ /**
+ * Runs the main function
+ */
+ public void run() {
+ ui.hello();
+ boolean isExit = false;
+ while (!isExit) {
+ try {
+ String fullCommand = ui.readCommand();
+ Command c = Parser.parse(fullCommand);
+ if (c != null) {
+ c.execute(taskManager, ui, storage);
+ isExit = c.isExit();
+ }
+ } catch (DukeException e) {
+ ui.showError(e);
+ }
+ }
+
+ Ui.printWithDivider("Bye. Hope to see you again soon!");
+
+ }
+
+ public static void main(String[] args) throws IOException {
+ new Duke ("./Duke.txt").run();
}
}
diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..d2ffd5b4d
--- /dev/null
+++ b/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: Duke
+
diff --git a/src/main/java/duke/command/AddCommand.java b/src/main/java/duke/command/AddCommand.java
new file mode 100644
index 000000000..fda2f76ab
--- /dev/null
+++ b/src/main/java/duke/command/AddCommand.java
@@ -0,0 +1,31 @@
+package duke.command;
+
+import duke.exception.DukeException;
+import duke.storage.Storage;
+import duke.task.TaskManager;
+import duke.ui.Ui;
+
+public class AddCommand extends Command {
+
+ private String commandType;
+ private String taskName;
+ private String addInfo;
+
+ /**
+ * Command for "add" operations (add todo, event or deadline)
+ * @param commandType todo, event or deadline
+ * @param taskName name of task
+ * @param addInfo additional information
+ */
+ public AddCommand(String commandType, String taskName, String addInfo) {
+ this.taskName = taskName;
+ this.commandType = commandType;
+ this.addInfo = addInfo;
+ }
+
+ @Override
+ public void execute(TaskManager taskManager, Ui ui, Storage storage) throws DukeException {
+ taskManager.addTask(this.commandType, this.taskName, this.addInfo);
+ storage.writeFile(taskManager.toString());
+ }
+}
diff --git a/src/main/java/duke/command/ByeCommand.java b/src/main/java/duke/command/ByeCommand.java
new file mode 100644
index 000000000..8f9ad69cc
--- /dev/null
+++ b/src/main/java/duke/command/ByeCommand.java
@@ -0,0 +1,9 @@
+package duke.command;
+
+public class ByeCommand extends Command {
+
+ @Override
+ public boolean isExit() {
+ return true;
+ }
+}
diff --git a/src/main/java/duke/command/Command.java b/src/main/java/duke/command/Command.java
new file mode 100644
index 000000000..526dc7073
--- /dev/null
+++ b/src/main/java/duke/command/Command.java
@@ -0,0 +1,24 @@
+package duke.command;
+import duke.exception.DukeException;
+import duke.storage.Storage;
+import duke.task.TaskManager;
+import duke.ui.Ui;
+
+public abstract class Command {
+
+ /**
+ * Executes the command
+ *
+ * @param taskManager TaskManager instance in charge of calling the correct method
+ * @param ui Ui instance in charge to print
+ * @param storage Storage instance for writing files
+ * @throws DukeException
+ */
+ public void execute(TaskManager taskManager, Ui ui, Storage storage) throws DukeException {
+
+ }
+
+ public boolean isExit(){
+ return false;
+ }
+}
diff --git a/src/main/java/duke/command/DeleteCommand.java b/src/main/java/duke/command/DeleteCommand.java
new file mode 100644
index 000000000..3b49870d3
--- /dev/null
+++ b/src/main/java/duke/command/DeleteCommand.java
@@ -0,0 +1,21 @@
+package duke.command;
+
+import duke.exception.DukeException;
+import duke.storage.Storage;
+import duke.task.TaskManager;
+import duke.ui.Ui;
+
+public class DeleteCommand extends Command {
+
+ private int taskNumber;
+ public DeleteCommand(int taskNumber) {
+ this.taskNumber = taskNumber;
+ }
+
+ @Override
+ public void execute(TaskManager taskManager, Ui ui, Storage storage) throws DukeException {
+ taskManager.deleteTask(this.taskNumber);
+ storage.writeFile(taskManager.toString());
+
+ }
+}
diff --git a/src/main/java/duke/command/FindCommand.java b/src/main/java/duke/command/FindCommand.java
new file mode 100644
index 000000000..391dfc7b5
--- /dev/null
+++ b/src/main/java/duke/command/FindCommand.java
@@ -0,0 +1,28 @@
+package duke.command;
+
+import duke.storage.Storage;
+import duke.task.TaskManager;
+import duke.ui.Ui;
+
+public class FindCommand extends Command {
+
+ private String keyword;
+
+
+ public FindCommand(String keyword) {
+ this.keyword = keyword;
+ }
+
+ @Override
+ public void execute(TaskManager taskManager, Ui ui, Storage storage) {
+ TaskManager relatedTaskManager = taskManager.findTask(this.keyword);
+ if (relatedTaskManager.getNumOfTasks() == 0) {
+ Ui.printWithDivider("Sorry, task(s) containing the word " + this.keyword +" not found.");
+ }
+ else {
+ Ui.printWithDivider( "Here are the matching tasks in your list: \n"
+ + relatedTaskManager);
+ }
+
+ }
+}
diff --git a/src/main/java/duke/command/ListCommand.java b/src/main/java/duke/command/ListCommand.java
new file mode 100644
index 000000000..9da655b5a
--- /dev/null
+++ b/src/main/java/duke/command/ListCommand.java
@@ -0,0 +1,13 @@
+package duke.command;
+
+import duke.storage.Storage;
+import duke.task.TaskManager;
+import duke.ui.Ui;
+
+public class ListCommand extends Command {
+
+ @Override
+ public void execute(TaskManager taskManager, Ui ui, Storage storage) {
+ Ui.printWithDivider(taskManager.toString());
+ }
+}
diff --git a/src/main/java/duke/command/MarkCommand.java b/src/main/java/duke/command/MarkCommand.java
new file mode 100644
index 000000000..791916bfd
--- /dev/null
+++ b/src/main/java/duke/command/MarkCommand.java
@@ -0,0 +1,20 @@
+package duke.command;
+import duke.exception.DukeException;
+import duke.storage.Storage;
+import duke.task.TaskManager;
+import duke.ui.Ui;
+
+public class MarkCommand extends Command {
+
+ private int taskNumber;
+
+ public MarkCommand(int taskNumber) {
+ this.taskNumber = taskNumber;
+ }
+
+ @Override
+ public void execute(TaskManager taskManager, Ui ui, Storage storage) throws DukeException {
+ taskManager.markCompleted(this.taskNumber);
+ storage.writeFile(taskManager.toString());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/duke/command/UnmarkCommand.java b/src/main/java/duke/command/UnmarkCommand.java
new file mode 100644
index 000000000..103645d21
--- /dev/null
+++ b/src/main/java/duke/command/UnmarkCommand.java
@@ -0,0 +1,20 @@
+package duke.command;
+import duke.exception.DukeException;
+import duke.storage.Storage;
+import duke.task.TaskManager;
+import duke.ui.Ui;
+
+public class UnmarkCommand extends Command {
+
+ private int taskNumber;
+
+ public UnmarkCommand(int taskNumber) {
+ this.taskNumber = taskNumber;
+ }
+
+ @Override
+ public void execute(TaskManager taskManager, Ui ui, Storage storage) throws DukeException {
+ taskManager.unmarkCompleted(this.taskNumber);
+ storage.writeFile(taskManager.toString());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/duke/exception/DukeException.java b/src/main/java/duke/exception/DukeException.java
new file mode 100644
index 000000000..722724230
--- /dev/null
+++ b/src/main/java/duke/exception/DukeException.java
@@ -0,0 +1,10 @@
+package duke.exception;
+
+/**
+ * Exception for anything related to Duke
+ */
+public class DukeException extends Exception {
+ public DukeException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/duke/parser/Parser.java b/src/main/java/duke/parser/Parser.java
new file mode 100644
index 000000000..ae48243d9
--- /dev/null
+++ b/src/main/java/duke/parser/Parser.java
@@ -0,0 +1,180 @@
+package duke.parser;
+import java.util.ArrayList;
+
+import duke.command.*;
+import duke.exception.DukeException;
+import duke.task.Deadline;
+import duke.task.Event;
+import duke.task.Task;
+import duke.task.ToDo;
+
+
+
+
+public class Parser {
+ private static ArrayList splitToTwo(String line, String delimiter) {
+ ArrayList words = new ArrayList<>();
+ int divider = line.indexOf(delimiter);
+
+ words.add(line);
+
+ if (divider != -1) {
+ words.set(0, line.substring(0, divider));
+ words.add(line.substring(divider + 1));
+ }
+ return words;
+ }
+
+ private static String getNextWord(String line, String word) {
+ String nextWord = "";
+ try {
+ int indexOfWord = line.indexOf(word);
+ String nextPart = line.substring(indexOfWord + word.length() + 1);
+ int indexOfSpace = nextPart.indexOf(" ");
+ if (indexOfSpace == -1) {
+ nextWord = nextPart;
+ } else {
+ nextWord = nextPart.substring(0, indexOfSpace);
+ }
+ } catch (IndexOutOfBoundsException e) {
+ nextWord = "";
+ }
+ return nextWord;
+ }
+
+ /**
+ * Checks input command for any error
+ * @param input input command to be checked
+ * @throws DukeException if there is an error
+ */
+ private static void errorCheck(String input) throws DukeException {
+ String[] words = input.split(" ");
+ String command = words[0];
+
+ switch (command) {
+ case "todo":
+ case "event":
+ case "deadline":
+ String taskName = getNextWord(input, command);
+ // taskName cannot have "/" and must be at least size of 1
+ if (taskName.contains("/") || taskName == "") {
+ String errorMsg = String.format("%s requires valid name (no `/` allowed) \n", command);
+ throw new DukeException(errorMsg);
+ }
+ if (command.equals("event") || command.equals("deadline")) {
+ int indexOfSlash = input.indexOf("/");
+ String date = indexOfSlash == -1 ? "" : input.substring(indexOfSlash);
+ if (date.length() <= 1) {
+ String errorMsg = String.format("%s requires a valid date in the format taskName /date"
+ + "date could be a string or in /dd-MM-yyyy hh:mm format\n", command);
+ throw new DukeException(errorMsg);
+ }
+ }
+ break;
+
+ case "bye":
+ case "list":
+ if (!getNextWord(input, command).equals("")) {
+ String errorMsg = "Command not understood";
+ throw new DukeException(errorMsg);
+ }
+ break;
+ case "find":
+ String keyword = getNextWord(input, command);
+ if (keyword.equals("")) {
+ String errorMsg = String.format("%s requires a word\n", command);
+ throw new DukeException(errorMsg);
+ }
+ break;
+ case "mark":
+ case "unmark":
+ case "delete":
+ try {
+ Integer.parseInt(getNextWord(input, command));
+ } catch (NumberFormatException e) {
+ String errorMsg = "Please enter a valid index for mark/unmark";
+ throw new DukeException(errorMsg);
+ }
+ break;
+ default:
+ String errorMsg = "Command not understood";
+ throw new DukeException(errorMsg);
+ }
+ }
+
+ /**
+ * Parses the input command and return the corresponding command.
+ * @param fullCommand input command
+ * @return Command object corresponding to the input command
+ * @throws DukeException if there is an error
+ */
+
+ public static Command parse(String fullCommand) throws DukeException {
+ //checks for error before continuing, if there's error, an exception is thrown
+ errorCheck(fullCommand);
+ ArrayList words = splitToTwo(fullCommand, " ");
+ String command = words.get(0);
+ String description = words.size() >= 2 ? words.get(1) : "";
+
+ switch (command) {
+ case "mark":
+ return new MarkCommand(Integer.parseInt(description));
+ case "unmark":
+ return new UnmarkCommand(Integer.parseInt(description));
+ case "list":
+ return new ListCommand();
+ case "todo":
+ return new AddCommand(command, description, "");
+ case "deadline":
+ case "event":
+ ArrayList descriptionSplit = Parser.splitToTwo(description, "/");
+ String taskName = descriptionSplit.get(0);
+ String addInfo = descriptionSplit.size() >= 2 ? descriptionSplit.get(1) : "";
+ return new AddCommand(command, taskName, addInfo);
+ case "delete":
+ return new DeleteCommand(Integer.parseInt(description));
+ case "find":
+ return new FindCommand(description);
+ case "bye":
+ return new ByeCommand();
+ default: //fine to return null, as error check makes sure the commands are valid.
+ return null;
+ }
+ }
+
+ /**
+ * Parses string into task. Used by Storage to parse input file into task list.
+ * @param input String to be parsed
+ * @return task object correspond to the String
+ */
+ public static Task parseToTask(String input) {
+ int indexOfSpace = input.indexOf(" ");
+ String taskType = input.substring(indexOfSpace + 2, indexOfSpace+3);
+ String status = input.substring(indexOfSpace + 5, indexOfSpace + 6);
+ String nameAndDate = input.substring(indexOfSpace + 7);
+ String name = "";
+ String date = "";
+ if (!taskType.equals("T")) {
+ name = nameAndDate.substring(0, nameAndDate.indexOf("("));
+ date = nameAndDate.substring(nameAndDate.indexOf("(") + 1, nameAndDate.indexOf(")"));
+ }
+ Task task = new Task("");
+ switch (taskType) {
+ case "T":
+ task = new ToDo(nameAndDate);
+ break;
+ case "D":
+ task = new Deadline(name, date);
+ break;
+ case "E":
+ task = new Event(name, date);
+ break;
+ default:
+ break;
+ }
+ if (status.equals("X")) {
+ task.setCompleted(true);
+ }
+ return task;
+ }
+ }
diff --git a/src/main/java/duke/storage/Storage.java b/src/main/java/duke/storage/Storage.java
new file mode 100644
index 000000000..88ce6cba0
--- /dev/null
+++ b/src/main/java/duke/storage/Storage.java
@@ -0,0 +1,64 @@
+package duke.storage;
+
+import duke.exception.DukeException;
+import duke.parser.Parser;
+import duke.task.Task;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+public class Storage {
+ private String filePath;
+
+ /**
+ * Creates a storage to read and write file from filepath
+ *
+ * @param filePath path of input/output file
+ */
+ public Storage(String filePath) {
+ this.filePath = filePath;
+ }
+
+ /**
+ * Reads input and returns it as a task list
+ * @return TaskList from input file
+ * @throws DukeException If no input file is found
+ */
+ public ArrayList readFile() throws DukeException {
+ ArrayList tasks = new ArrayList<>();
+ File input = new File(filePath);
+ try {
+ //unused boolean
+ boolean hasCreatedFile = input.createNewFile();
+ Scanner s = new Scanner(input);
+ while (s.hasNext()) {
+ tasks.add(Parser.parseToTask(s.nextLine()));
+ }
+ return tasks;
+ } catch (IOException e) {
+ String message = "Issue at file creation!";
+ throw new DukeException(message);
+ }
+
+ }
+
+ /**
+ * Saves task list into a ile
+ * @param textToAdd text to be written
+ * @throws DukeException if file not found
+ */
+ public void writeFile(String textToAdd) throws DukeException {
+ try {
+ FileWriter output = new FileWriter(this.filePath);
+ output.write(textToAdd);
+ output.close();
+ } catch (IOException e) {
+ String message = "File writing issue";
+ throw new DukeException(message);
+ }
+
+ }
+}
diff --git a/src/main/java/duke/task/DatedTask.java b/src/main/java/duke/task/DatedTask.java
new file mode 100644
index 000000000..835f171bd
--- /dev/null
+++ b/src/main/java/duke/task/DatedTask.java
@@ -0,0 +1,43 @@
+package duke.task;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+
+public class DatedTask extends Task {
+
+ private String DateTimeString;
+ private LocalDateTime RealDateTime;
+
+ /**
+ * Task that has date/time attribute
+ * @param taskName name of task
+ * @param DateTimeString optional date/time in string format "dd-MM-yyyy HH:mm, "" if none
+ */
+ public DatedTask(String taskName, String DateTimeString) {
+ super(taskName);
+ this.DateTimeString = DateTimeString;
+ try {
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm");
+ this.RealDateTime = LocalDateTime.parse(DateTimeString, formatter);
+ } catch (Exception e) {
+ this.RealDateTime = null;
+ }
+
+ }
+
+ /**
+ * Get date and time in string
+ * @return date and time
+ */
+ public String getDateTimeString() {
+ String dateTimeString = this.DateTimeString;
+
+ if (this.RealDateTime != null) {
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm");
+ dateTimeString = this.RealDateTime.format(formatter);
+ }
+ return dateTimeString;
+ }
+
+}
diff --git a/src/main/java/duke/task/Deadline.java b/src/main/java/duke/task/Deadline.java
new file mode 100644
index 000000000..eac94b756
--- /dev/null
+++ b/src/main/java/duke/task/Deadline.java
@@ -0,0 +1,14 @@
+package duke.task;
+
+public class Deadline extends DatedTask {
+
+
+ public Deadline(String name, String by) {
+ super(name, by);
+ }
+
+ @Override
+ public String toString() {
+ return "[D]" + super.toString() + String.format("(by: %s)", this.getDateTimeString());
+ }
+}
diff --git a/src/main/java/duke/task/Event.java b/src/main/java/duke/task/Event.java
new file mode 100644
index 000000000..cad879fb9
--- /dev/null
+++ b/src/main/java/duke/task/Event.java
@@ -0,0 +1,13 @@
+package duke.task;
+
+public class Event extends DatedTask {
+
+ public Event(String name, String on) {
+ super(name, on);
+ }
+
+ @Override
+ public String toString() {
+ return "[E]" + super.toString() + String.format("(on: %s)", this.getDateTimeString());
+ }
+}
diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java
new file mode 100644
index 000000000..f1a85b7f9
--- /dev/null
+++ b/src/main/java/duke/task/Task.java
@@ -0,0 +1,41 @@
+package duke.task;
+
+public class Task {
+ private String name;
+ private boolean isCompleted;
+
+ /**
+ * Creates a task
+ * @param name name of task
+ */
+ public Task(String name) {
+ this.name = name;
+ this.isCompleted = false;
+ }
+
+ /**
+ * Returns name of task
+ * @return task name
+ */
+ public String getName() {
+ return this.name;
+ }
+
+
+ /**
+ * Mark task as complete/incomplete
+ * @param completion completion status of task, true as completed, false as not completed
+ */
+ public void setCompleted(boolean completion) {
+ this.isCompleted = completion;
+ }
+
+ /**
+ * Returns a string representation of the task
+ * @return task in the format "[x] task name" (x for completed, " " for incomplete)
+ */
+ public String toString() {
+ return String.format("[%s] %s", (this.isCompleted ? "X" : " "), this.name);
+ }
+
+}
diff --git a/src/main/java/duke/task/TaskManager.java b/src/main/java/duke/task/TaskManager.java
new file mode 100644
index 000000000..838c1d019
--- /dev/null
+++ b/src/main/java/duke/task/TaskManager.java
@@ -0,0 +1,161 @@
+package duke.task;
+
+import java.util.ArrayList;
+
+import duke.exception.DukeException;
+import duke.ui.Ui;
+
+
+
+public class TaskManager {
+ private ArrayList tasks = new ArrayList<>();
+ private int numOfTasks = 0;
+
+ /**
+ * Class to manage the tasks
+ */
+ public TaskManager(){
+ }
+
+ /**
+ * Returns number of tasks
+ * @return Number of tasks
+ */
+ public int getNumOfTasks() {
+ return this.numOfTasks;
+ }
+
+ /**
+ * Adds a task into the task list.
+ *
+ * @param type Type of command (todo, event or deadline)
+ * @param taskName Task name
+ * @param addInfo Any additional info (date or time)
+ */
+ public void addTask(String type, String taskName, String addInfo) {
+ Task toBeAdded;
+
+ switch (type) {
+ case "todo":
+ toBeAdded = new ToDo(taskName);
+ break;
+ case "deadline":
+ toBeAdded = new Deadline(taskName, addInfo);
+ break;
+ case "event":
+ toBeAdded = new Event(taskName, addInfo);
+ break;
+ default:
+ toBeAdded = new Task(taskName);
+ break;
+ }
+
+ this.numOfTasks++;
+ this.tasks.add(toBeAdded);
+
+ Ui.printWithDivider("Got it. I've added this task:\n\t" + toBeAdded.toString()
+ + String.format("\nNow you have %d task%s in the list.", this.numOfTasks,
+ this.numOfTasks > 1 ? "s" : ""));
+
+ }
+
+
+ /**
+ * * Deletes a task from the task list.
+ *
+ * @param taskNumber Task number of the task to be deleted (as seen from list)
+ * @throws DukeException Throws exception if task number invalid
+ */
+ public void deleteTask(int taskNumber) throws DukeException {
+ try {
+ Task task = tasks.get(taskNumber - 1);
+ tasks.remove(task);
+ this.numOfTasks--;
+
+ Ui.printWithDivider("Noted. I've removed this task:\n\t " + task.toString()
+ + String.format("\nNow you have %d task%s in the list.", this.numOfTasks,
+ this.numOfTasks > 1 ? "s" : ""));
+ } catch (IndexOutOfBoundsException e) {
+ throw new DukeException("Index out of bounds!");
+ }
+ }
+
+ /**
+ * Replaces existing task list with a new task list.
+ *
+ * @param tasks Replacing task list.
+ */
+ public void setTasks(ArrayList tasks) {
+ this.tasks = tasks;
+ this.numOfTasks = tasks.size();
+ }
+
+ /**
+ * Marks task as complete.
+ *
+ * @param taskNumber Task number of the task to be deleted (as seen from list)
+ * @throws DukeException Throws exception if task number invalid
+ */
+ public void markCompleted (int taskNumber) throws DukeException {
+ try {
+ Task task = tasks.get(taskNumber - 1);
+ task.setCompleted(true);
+ Ui.printWithDivider(task.toString());
+ }
+ catch (IndexOutOfBoundsException e) {
+ throw new DukeException("Index out of bounds!");
+ }
+ }
+
+ /**
+ * Marks task as incomplete.
+ *
+ * @param taskNumber Task number of the task to be deleted (as seen from list)
+ * @throws DukeException Throws exception if task number invalid
+ */
+ public void unmarkCompleted (int taskNumber) throws DukeException {
+ try {
+ Task task = tasks.get(taskNumber - 1);
+ task.setCompleted(false);
+ Ui.printWithDivider(task.toString());
+ }
+ catch (IndexOutOfBoundsException e) {
+ throw new DukeException("Index out of bounds!");
+ }
+ }
+
+ /**
+ * Find tasks containing keyword in its name
+ * @param keyword Keyword in task name
+ * @return TaskManager containing all the related tasks
+ */
+ public TaskManager findTask (String keyword) {
+ TaskManager relatedTaskManager = new TaskManager();
+ ArrayList relatedTasks = new ArrayList<>();
+ for (Task task : tasks) {
+ if (task.getName().contains(keyword)) {
+ relatedTasks.add(task);
+ }
+ }
+ relatedTaskManager.setTasks(relatedTasks);
+ return relatedTaskManager;
+ }
+
+ /**
+ * Return the task list (number listed)
+ * @return Task list
+ */
+ @Override
+ public String toString() {
+ String output = "";
+ int number = 1;
+ for (Task item : this.tasks) {
+ output += String.format("%d. %s", number, item.toString());
+ if (number != numOfTasks) {
+ output += "\n";
+ }
+ number++;
+ }
+ return output;
+ }
+}
diff --git a/src/main/java/duke/task/ToDo.java b/src/main/java/duke/task/ToDo.java
new file mode 100644
index 000000000..9924e4749
--- /dev/null
+++ b/src/main/java/duke/task/ToDo.java
@@ -0,0 +1,12 @@
+package duke.task;
+
+public class ToDo extends Task {
+ public ToDo(String name) {
+ super(name);
+ }
+
+ @Override
+ public String toString() {
+ return "[T]" + super.toString();
+ }
+}
diff --git a/src/main/java/duke/ui/Ui.java b/src/main/java/duke/ui/Ui.java
new file mode 100644
index 000000000..50e828d7e
--- /dev/null
+++ b/src/main/java/duke/ui/Ui.java
@@ -0,0 +1,59 @@
+package duke.ui;
+
+import duke.exception.DukeException;
+
+import java.util.ArrayList;
+import java.util.Scanner;
+
+public class Ui {
+ private Scanner sc;
+
+ public Ui () {
+ this.sc = new Scanner(System.in);
+ }
+
+ /**
+ * Prints String wrapped inside two divider lines.
+ *
+ * @param stringWithinDivider String to be wrapped
+ */
+ public static void printWithDivider(String stringWithinDivider) {
+ String breakLine = "\t____________________________________________________________";
+ System.out.println(breakLine);
+ stringWithinDivider = stringWithinDivider.replace("\n", "\n\t");
+ System.out.println("\t" + stringWithinDivider);
+ System.out.println(breakLine);
+ }
+
+ /**
+ * Greets the user
+ */
+ public void hello() {
+ String logo = " ____ _ \n"
+ + "| _ \\ _ _| | _____ \n"
+ + "| | | | | | | |/ / _ \\\n"
+ + "| |_| | |_| | < __/\n"
+ + "|____/ \\__,_|_|\\_\\___|\n";
+ System.out.println("Hello from\n" + logo);
+ Ui.printWithDivider("Hello! I'm Duke\nWhat can I do for you?");
+ }
+
+ /**
+ * Reads input typed in by user
+ *
+ * @return input command as string
+ */
+ public String readCommand() {
+ String line = sc.nextLine();
+ return line;
+ }
+
+ /**
+ * Prints the error message
+ *
+ * @param e error
+ */
+ public void showError(DukeException e) {
+ System.out.println(e.toString());
+ }
+}
diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT
index 657e74f6e..381ca976a 100644
--- a/text-ui-test/EXPECTED.TXT
+++ b/text-ui-test/EXPECTED.TXT
@@ -5,3 +5,45 @@ Hello from
| |_| | |_| | < __/
|____/ \__,_|_|\_\___|
+ ____________________________________________________________
+ Hello! I'm Duke
+ What can I do for you?
+ ____________________________________________________________
+ ____________________________________________________________
+ Got it. I've added this task:
+ [ ] read book
+ Now you have 1 task in the list.
+ ____________________________________________________________
+ ____________________________________________________________
+ [X] read book
+ ____________________________________________________________
+ ____________________________________________________________
+ [ ] read book
+ ____________________________________________________________
+ ____________________________________________________________
+ Got it. I've added this task:
+ [T][ ] go to gym
+ Now you have 2 tasks in the list.
+ ____________________________________________________________
+ ____________________________________________________________
+ Got it. I've added this task:
+ [D][ ] assignment 3 (by: Sunday)
+ Now you have 3 tasks in the list.
+ ____________________________________________________________
+ ____________________________________________________________
+ Got it. I've added this task:
+ [E][ ] spiderman's birthday (15th December)
+ Now you have 4 tasks in the list.
+ ____________________________________________________________
+ ____________________________________________________________
+ [D][X] assignment 3 (by: Sunday)
+ ____________________________________________________________
+ ____________________________________________________________
+ 1. [ ] read book
+ 2. [T][ ] go to gym
+ 3. [D][X] assignment 3 (by: Sunday)
+ 4. [E][ ] spiderman's birthday (15th December)
+ ____________________________________________________________
+ ____________________________________________________________
+ Bye. Hope to see you again soon!
+ ____________________________________________________________
diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt
index e69de29bb..ef52c4f21 100644
--- a/text-ui-test/input.txt
+++ b/text-ui-test/input.txt
@@ -0,0 +1,9 @@
+read book
+mark 1
+unmark 1
+todo go to gym
+deadline assignment 3 /by: Sunday
+event spiderman's birthday /15th December
+mark 3
+list
+bye
\ No newline at end of file