diff --git a/README.md b/README.md
index 84755485a7..36829d8ad5 100644
--- a/README.md
+++ b/README.md
@@ -22,11 +22,11 @@
# Tutorials
-Duke Increment | Tutorial
+Duke.Duke Increment | Tutorial
---------------|---------------
`A-Gradle` | [Gradle Tutorial](tutorials/gradleTutorial.md)
`A-TextUiTesting` | [Text UI Testing Tutorial](tutorials/textUiTestingTutorial.md)
-`Level-10` | JavaFX tutorials:
→ [Part 1: Introduction to JavaFX][fx1]
→ [Part 2: Creating a GUI for Duke][fx2]
→ [Part 3: Interacting with the user][fx3]
→ [Part 4: Introduction to FXML][fx4]
+`Level-10` | JavaFX tutorials:
→ [Part 1: Introduction to JavaFX][fx1]
→ [Part 2: Creating a GUI for Duke.Duke][fx2]
→ [Part 3: Interacting with the user][fx3]
→ [Part 4: Introduction to FXML][fx4]
[fx1]:
[fx2]:
diff --git a/data.txt b/data.txt
new file mode 100644
index 0000000000..225bdc1c1d
--- /dev/null
+++ b/data.txt
@@ -0,0 +1,3 @@
+0|Career Fair|E|26-02-2020
+0|English Essay|D|26 Feb
+0|CS2105 Assignment|D|next week
diff --git a/docs/README.md b/docs/README.md
index fd44069597..6e4a106009 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,20 +1,149 @@
-# User Guide
+# Introduction
-## Features
+Duke is a command-line interface task manager. You can use Duke to manage a list of to-do items, upcoming deadlines, and upcoming events. The list is saved upon exit and will be loaded upon the next session of Duke.
-### Feature 1
-Description of feature.
+# Features
-## Usage
+This section describes the features that Duke supports.
-### `Keyword` - Describe action
+NOTE:
+* Commands have to be the first word of the user input and in lower case
+* Words in ```UPPER_CASE``` are the parameters to be supplied by the user
-Describe action and its outcome.
-Example of usage:
+## 1. Adding New Tasks
-`keyword (optional arguments)`
+New tasks can be added by typing the command relevant to the type of task that is to be added (i.e. ```todo```,``` event``` or ```deadline```).
-Expected outcome:
+#### 1.1 Adding New To-Dos: ```todo```
+- Adds a new to-do item to the task list.
+- Format: ```todo NAME_OF_TASK```
+- Examples:
+ - ```todo Math Online Quiz```
+ - ```todo CS2113 Homework```
+- Expected Output:
+```
+todo CS2113 Homework
+____________________________________________________________
+Got it. I've added this task:
+[T][X] CS2113 Homework
+Now you have 2 tasks in the list.
+____________________________________________________________
+```
-`outcome`
+#### 1.2 Adding New Events: ```event```
+- Adds a new event to the task list.
+- Format: ```event NAME_OF_EVENT /at DATE_OF_EVENT```
+- Examples:
+ - ```event Career Fair /at 26-02-2020```
+ - ```event Family Gathering /at 26 Feb```
+ - ```event Computing Convention /at Next Month```
+- Expected Output:
+```
+event Career Fair /at 26-02-2020
+____________________________________________________________
+Got it. I've added this task:
+[E][X] Career Fair (at: 26-02-2020)
+Now you have 3 tasks in the list.
+____________________________________________________________
+```
+
+#### 1.3 Adding New Deadlines: ```deadline```
+- Adds a new deadline to the task list.
+- Format: ```deadline NAME_OF_DEADLINE /by DATE_OF_DEADLINE```
+- Examples:
+ - ```deadline Math Online Quiz /by 26-02-2020```
+ - ```deadline English Essay /by 26 Feb```
+ - ```deadline CS2113 Homework /by Tomorrow```
+- Expected Output:
+```
+deadline English Essay /by 26 Feb
+____________________________________________________________
+Got it. I've added this task:
+[D][X] English Essay (by: 26 Feb)
+Now you have 4 tasks in the list.
+____________________________________________________________
+```
+
+## 2. Listing All Tasks: ```list```
+- Lists all task in the list.
+- Format: ```list```
+- Expected Output:
+```
+list
+1.[T][O] CS2113 Homework
+2.[E][X] Career Fair (at: 26-02-2020)
+3.[D][X] English Essay (by: 26 Feb)
+```
+
+## 3. Finding Tasks by Keyword: ```find```
+- Lists all task in the list that contains the specified keyword.
+- Format: ```find KEYWORD```
+- Examples:
+ - ```find Math```
+ - ```find CS2113```
+ - ```find CS```
+
+- Expected Output:
+```
+find CS
+____________________________________________________________
+Here are the matching tasks in your list:
+
+1.[T][X] CS2113 Homework
+2.[D][X] CS2105 Assignment (by: next week)
+____________________________________________________________
+```
+
+## 4. Marking Tasks as Done: ```done```
+- Marks specified tasks as done.
+- Specified index of the task will be its index of the entire task list by default, unless the ```list``` or ```find``` command has been called. In which case, it will be the index of the item as shown in the last shown list.
+- Format: ```done INDEX```
+- Examples:
+ - ```done 1```
+ - ```done 2```
+- Expected Output:
+```
+done 1
+Nice! I've marked this task as done:
+[O] CS2113 Homework
+```
+
+## 5. Deleting Tasks: ```delete```
+- Delete specified tasks from the list.
+- Specified index of the task will be its index of the entire task list by default, unless the ```list``` or ```find``` command has been called. In which case, it will be the index of the item as shown in the last shown list.
+- Format: ```done INDEX```
+- Examples:
+ - ```delete 1```
+ - ```delete 2```
+- Expected Output:
+```
+delete 1
+____________________________________________________________
+Noted. I've removed this task:
+[T][O] CS2113 Homework
+Now you have 3 tasks in the list.
+____________________________________________________________
+
+```
+
+## 6. Loading Tasks from File
+- Loading of tasks will be done automatically upon starting the application when there is a saved file present in the same directory of the Duke application. The file has the name ```data.txt```.
+- Expected Output:
+```
+Previous tasks has been loaded successfully:
+____________________________________________________________
+1.[E][X] Career Fair (at: 26-02-2020)
+2.[D][X] English Essay (by: 26 Feb)
+3.[D][X] CS2105 Assignment (by: next week)
+```
+
+## 7. Saving Tasks: ```bye```
+- Saving the state of the task list is done automatically when the program is exited using the ```bye`` command.
+- Format: ```bye```
+- Expected Output:
+
+```
+bye
+Bye. Hope to see you again soon!
+```
diff --git a/saved/data.txt b/saved/data.txt
new file mode 100644
index 0000000000..d9496d9c8d
--- /dev/null
+++ b/saved/data.txt
@@ -0,0 +1,3 @@
+1|something|T
+0|some date|D|tmr
+0|some lame thing|E|ytd
diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
deleted file mode 100644
index 5d313334cc..0000000000
--- 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/Deadline.java b/src/main/java/Duke/Deadline.java
new file mode 100644
index 0000000000..c1b85f931e
--- /dev/null
+++ b/src/main/java/Duke/Deadline.java
@@ -0,0 +1,48 @@
+package Duke;
+
+/**
+ * Represents a deadline object which is a task with a deadline date associated with it.
+ */
+public class Deadline extends Task {
+ protected String by;
+
+ /**
+ * Constructor for a new deadline.
+ * @param description description for the deadline
+ * @param by the date for the deadline
+ */
+ public Deadline(String description, String by) {
+ super(description);
+ this.by = by;
+ }
+
+ /**
+ * Constructor for deadlines that are read from a storage file.
+ * @param description description of the deadline
+ * @param by date of the deadline
+ * @param status status of the deadline
+ */
+ public Deadline(String description, String by, String status) {
+ super(description);
+ this.by = by;
+ if (status.equals("1")) {
+ this.markAsDone();
+ }
+ }
+
+ /**
+ * @return a string containing the status, description and date of the deadline for printing
+ */
+ @Override
+ public String toString() {
+ return "[D]" + super.toString() + " (by: " + this.by + ")";
+ }
+
+ /**
+ * @return a string of information of the deadline in the format for saving to a file
+ */
+ @Override
+ public String toSaveFormat() {
+ return(super.toSaveFormat() + "D|" + this.by);
+ }
+}
\ 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 0000000000..c0454c9878
--- /dev/null
+++ b/src/main/java/Duke/Duke.java
@@ -0,0 +1,43 @@
+package Duke;
+
+import java.util.Scanner;
+import java.util.ArrayList;
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * Represents the Duke task manager.
+ */
+public class Duke {
+
+ public static final String GREETING =
+ "\n" +
+ " ___ _ \n" +
+ " | \\ _ _| |_____ \n" +
+ " | |) | || | / / -_)\n" +
+ " |___/ \\_,_|_\\_\\___|\n" +
+ " \n" +
+ "Hello! I'm Duke\n" + "What can I do for you?\n" +
+ "____________________________________________________________\n";
+ public static final String GOODBYE = "Bye. Hope to see you again soon!";
+ public static final String FILEPATH = "data.txt";
+
+ public static void main(String[] args) {
+ System.out.println(GREETING);
+
+ File f = new File(FILEPATH);
+
+ TaskList taskArray = new TaskList();
+
+ try {
+ Storage.loadFileContents(FILEPATH, taskArray);
+ Ui.printTasks(taskArray);
+ } catch (FileNotFoundException e) {
+ System.out.println("No saved file available");
+ }
+
+ Scanner scanner = new Scanner(System.in);
+
+ Parser.parseUserCommands(taskArray, scanner);
+ }
+}
diff --git a/src/main/java/Duke/DukeException.java b/src/main/java/Duke/DukeException.java
new file mode 100644
index 0000000000..c05991f530
--- /dev/null
+++ b/src/main/java/Duke/DukeException.java
@@ -0,0 +1,4 @@
+package Duke;
+
+public class DukeException extends Exception {
+}
diff --git a/src/main/java/Duke/Event.java b/src/main/java/Duke/Event.java
new file mode 100644
index 0000000000..6424ef8f4a
--- /dev/null
+++ b/src/main/java/Duke/Event.java
@@ -0,0 +1,48 @@
+package Duke;
+
+/**
+ * Represents an event-based task happening at a specific date.
+ */
+public class Event extends Task {
+ protected String at;
+
+ /**
+ * Constructor for a new event.
+ * @param description description for the event
+ * @param at date of the event
+ */
+ public Event(String description, String at) {
+ super(description);
+ this.at = at;
+ }
+
+ /**
+ * Constructor for an event that is read from a storage file.
+ * @param description description of the event
+ * @param at date of the event
+ * @param status status of the event
+ */
+ public Event(String description, String at, String status) {
+ super(description);
+ this.at = at;
+ if (status.equals("1")) {
+ this.markAsDone();
+ }
+ }
+
+ /**
+ * @return a string containing the status, description and date of the event for printing
+ */
+ @Override
+ public String toString() {
+ return "[E]" + super.toString() + " (at: " + this.at + ")";
+ }
+
+ /**
+ * @return a string of information of the event in the format for saving to a file
+ */
+ @Override
+ public String toSaveFormat() {
+ return(super.toSaveFormat() + "E|" + this.at);
+ }
+}
diff --git a/src/main/java/Duke/Parser.java b/src/main/java/Duke/Parser.java
new file mode 100644
index 0000000000..643d25afb3
--- /dev/null
+++ b/src/main/java/Duke/Parser.java
@@ -0,0 +1,157 @@
+package Duke;
+
+import java.util.ArrayList;
+import java.util.Scanner;
+
+/**
+ * Represents the object which parses user input to relevant functions for the execution of commands.
+ */
+public class Parser {
+
+ /**
+ * Parses user commands to relevant functions to complete it while checking for user input errors.
+ * @param taskArray the task list of the current session to be parsed to relevant command methods
+ * @param scanner a scanner object that takes in user input
+ */
+ public static void parseUserCommands(TaskList taskArray, Scanner scanner) {
+ ArrayList lastShownList = (ArrayList) taskArray.tasks.clone();
+ boolean exit = false;
+ while (exit == false) {
+ String userInput = scanner.nextLine();
+ String[] tokenizedInputs = userInput.split(" ", 2);
+ String instruction = tokenizedInputs[0];
+
+ switch (instruction) {
+ case "bye":
+ System.out.println(Duke.GOODBYE);
+ exit = true;
+ Storage.saveTasks(Duke.FILEPATH, taskArray);
+ break;
+ case "find":
+ if (isDescriptionEmpty(tokenizedInputs, instruction)) break;
+ String keyword = tokenizedInputs[1];
+ lastShownList.clear();
+ Ui.displayMatchingTasks(taskArray, lastShownList, keyword);
+ break;
+ case "list":
+ Ui.printTasks(taskArray);
+ lastShownList.clear();
+ lastShownList = (ArrayList) taskArray.tasks.clone();
+ break;
+ case "done":
+ if (isDescriptionEmpty(tokenizedInputs, instruction)) break;
+ int taskDone = 0;
+ try {
+ taskDone = Integer.valueOf(tokenizedInputs[1]) - 1;
+ } catch (Exception e){
+ System.out.println("Sorry, invalid index entered.\n");
+ break;
+ }
+ if (isOutOfBounds(lastShownList, taskDone)) break;
+ if (isInvalidTask(taskArray, lastShownList.get(taskDone))) break;
+ System.out.println("Nice! I've marked this task as done: ");
+ System.out.println(lastShownList.get(taskDone).markAsDone());
+ break;
+ case "delete":
+ if (isDescriptionEmpty(tokenizedInputs, instruction)) break;
+ int taskToDelete = 0;
+ try {
+ taskToDelete = Integer.valueOf(tokenizedInputs[1]) - 1;
+ } catch (Exception e){
+ System.out.println("Sorry, invalid index entered.\n");
+ break;
+ }
+ if (isOutOfBounds(lastShownList, taskToDelete)) break;
+ if (isInvalidTask(taskArray, lastShownList.get(taskToDelete))) break;
+ Ui.respondDeleteSuccess(taskArray.size-1, lastShownList.get(taskToDelete));
+ taskArray.deleteTask(lastShownList.get(taskToDelete));
+ break;
+ case "todo":
+ if (isDescriptionEmpty(tokenizedInputs, instruction)) break;
+ taskArray.addTask(new ToDo(tokenizedInputs[1]));
+ Ui.respondAddedSuccess(taskArray.size, taskArray.get(taskArray.size-1));
+ break;
+ case "deadline":
+ if (isDescriptionEmpty(tokenizedInputs, instruction)) break;
+ String[] deadlineInfo = tokenizedInputs[1].split(" /by ");
+ if (isDateEmpty(deadlineInfo)) break;
+ taskArray.addTask(new Deadline(deadlineInfo[0], deadlineInfo[1]));
+ Ui.respondAddedSuccess(taskArray.size, taskArray.get(taskArray.size-1));
+ break;
+ case "event":
+ if (isDescriptionEmpty(tokenizedInputs, instruction)) break;
+ String[] eventInfo = tokenizedInputs[1].split(" /at ");
+ if (isDateEmpty(eventInfo)) break;
+ taskArray.addTask(new Event(eventInfo[0], eventInfo[1]));
+ Ui.respondAddedSuccess(taskArray.size, taskArray.get(taskArray.size-1));
+ break;
+ default:
+ System.out.println("☹ OOPS!!! I'm sorry, but I don't know what that means :-(");
+ break;
+ }
+ }
+ }
+
+ /**
+ * Checks if index supplied is out of bounds.
+ * @param lastShownList the last shown list from 'list' or 'find' commands.
+ * @param index the index supplied by user input from 'delete' or 'done' commands
+ * @return true if out of bounds and false if it is within bounds.
+ */
+ private static boolean isOutOfBounds(ArrayList lastShownList, int index) {
+ if (index >= lastShownList.size()) {
+ System.out.println("Sorry, the task does not exist. Please use the 'list' or 'find' command for an updated list of tasks.\n");
+ return true;
+ }
+
+ if (index < 0) {
+ System.out.println("Sorry, invalid index entered.\n");
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the task to be marked as done or deleted still exists as the last shown list may not be the most updated.
+ * For example, the user may have deleted and added new tasks since the last time the list or find command was called.
+ * @param taskArray the task array to check if it contains the chosen task extracted from the last shown list.
+ * @param requestedTask the task from the last shown list chosen by referencing its index
+ * @return true if the task is no longer valid and false if it is valid
+ */
+ public static boolean isInvalidTask(TaskList taskArray, Task requestedTask) {
+ if (taskArray.taskExists(requestedTask) == false) {
+ System.out.println("Sorry the task no longer exists. Please use 'list' or 'find' for an updated list\n");
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Checks if a date has been entered for new Events and Deadlines.
+ * @param information the information portion of the user input, further split into the description and date
+ * portions.
+ * @return true if the date portion is empty and false if the date portion is valid
+ */
+ static boolean isDateEmpty(String[] information) {
+ if (information.length == 1) {
+ System.out.println("☹ OOPS!!! You did not enter a date");
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the description portion of a command is empty.
+ *
+ * @param tokens an array containing the user input tokenized into the instruction and the task information
+ * @param instruction the instruction requested
+ * @return true if the description is empty and false if it is not empty
+ */
+ static boolean isDescriptionEmpty(String[] tokens, String instruction) {
+ if (tokens.length == 1) {
+ System.out.println("☹ OOPS!!! The description of a " + instruction + " cannot be empty.");
+ return true;
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/Duke/Storage.java b/src/main/java/Duke/Storage.java
new file mode 100644
index 0000000000..6fdd1f8d67
--- /dev/null
+++ b/src/main/java/Duke/Storage.java
@@ -0,0 +1,101 @@
+package Duke;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+/**
+ * Represents the interface between the application and the storage files. Provides methods to update and retrieve tasks
+ * from storage files.
+ */
+public class Storage {
+ /**
+ * Loads the task list for the current session with tasks located in a previously saved storage file.
+ * @param filePath the location of the storage file
+ * @param taskArray the task list to populate with tasks
+ * @throws FileNotFoundException
+ */
+ public static void loadFileContents(String filePath, TaskList taskArray) throws FileNotFoundException {
+ File f = new File(filePath);
+ Scanner s = new Scanner(f);
+ int taskListSize = 0;
+ while (s.hasNext()) {
+ String newLine = s.nextLine();
+ String[] tokenizedLine = newLine.split("\\|");
+ String type = tokenizedLine[2];
+ switch (type) {
+ case ("T"):
+ taskArray.addTask(new ToDo(tokenizedLine[1], tokenizedLine[0]));
+ break;
+ case ("E"):
+ taskArray.addTask(new Event(tokenizedLine[1], tokenizedLine[3], tokenizedLine[0]));
+ break;
+ case ("D"):
+ taskArray.addTask(new Deadline(tokenizedLine[1], tokenizedLine[3], tokenizedLine[0]));
+ break;
+ }
+ }
+ System.out.print("Previous tasks has been loaded successfully:\n" +
+ "____________________________________________________________\n");
+ }
+
+ /**
+ * Creates a new save file overwriting the existing one.
+ *
+ * @param filePath destination for the new storage file
+ * @param textToAdd the pre-formatted text string to be written to the file
+ * @throws IOException
+ */
+ static void writeToFile(String filePath, String textToAdd) throws IOException {
+ FileWriter fw = new FileWriter(filePath);
+ fw.write(textToAdd);
+ fw.close();
+ }
+
+ /**
+ * Appends task to a pre-existing storage file without overwriting.
+ *
+ * @param filePath file of the existing save file to be appended to
+ * @param textToAppend the pre-formatted text string to append to the file
+ * @throws IOException
+ */
+ static void appendToFile(String filePath, String textToAppend) throws IOException {
+ FileWriter fw = new FileWriter(filePath, true); // create a FileWriter in append mode
+ fw.write(textToAppend);
+ fw.close();
+ }
+
+ /**
+ * Saves the current state of the task list to a storage file.
+ *
+ * @param filePath the destination file path where the file will be stored
+ * @param taskArray the list of tasks to be saved in the file
+ * @see Storage#writeToFile(String, String) writeToFile
+ * @see Storage#appendToFile(String, String) appendToFile
+ * @see ToDo#toSaveFormat() ToDo
+ * @see Deadline#toSaveFormat() Deadline
+ * @see Event#toSaveFormat() Event
+ */
+ public static void saveTasks(String filePath, TaskList taskArray) {
+ boolean overWrite = true;
+ for (Task currTask : taskArray.tasks) {
+ if(overWrite == true) {
+ try {
+ Storage.writeToFile(filePath, currTask.toSaveFormat() + "\n");
+ } catch (IOException e) {
+ System.out.println("Something went wrong: " + e.getMessage());
+ }
+ overWrite = false;
+ } else {
+ try {
+ Storage.appendToFile(filePath, currTask.toSaveFormat() + "\n");
+ } catch (IOException e) {
+ System.out.println("Something went wrong: " + e.getMessage() + "\n");
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/Duke/Task.java b/src/main/java/Duke/Task.java
new file mode 100644
index 0000000000..ed60786e22
--- /dev/null
+++ b/src/main/java/Duke/Task.java
@@ -0,0 +1,47 @@
+package Duke;
+
+/**
+ * Represents a task object that the user can mark as done when completed.
+ */
+public class Task {
+ protected String description;
+ protected boolean isDone;
+
+ public Task(String description) {
+ this.description = description;
+ this.isDone = false;
+ }
+
+
+ public String getStatusIcon() {
+ return (isDone ? "O" : "X"); //return tick or X symbols
+ }
+
+ /**
+ * Updates the status of a task to done.
+ * @return a response string showing the updated status icon of the task
+ */
+ public String markAsDone () {
+ this.isDone = true;
+ return ("[" + this.getStatusIcon() + "] "+ this.description);
+ }
+
+ /**
+ * @return a string containing the task status and description for printing
+ */
+ public String toString() {
+ return ("["+ this.getStatusIcon() + "] " + this.description);
+ }
+
+ /**
+ * @return a string of containing the task status and description for saving
+ */
+ public String toSaveFormat() {
+ if (this.isDone == true) {
+ return ("1|" + this.description+ "|");
+ } else {
+ return ("0|" + this.description + "|");
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/Duke/TaskList.java b/src/main/java/Duke/TaskList.java
new file mode 100644
index 0000000000..58cd165eb7
--- /dev/null
+++ b/src/main/java/Duke/TaskList.java
@@ -0,0 +1,60 @@
+package Duke;
+
+import java.util.ArrayList;
+
+/**
+ * Represents the list of tasks (todos, events and deadlines) relevant to the current user session.
+ * Provides methods to add tasks, delete tasks and retrieve tasks in the list.
+ */
+public class TaskList {
+ ArrayList tasks;
+ int size;
+
+ /**
+ * Constructor for a new task array for the session.
+ */
+ public TaskList() {
+ this.tasks = new ArrayList<>();
+ size = 0;
+ }
+
+ /**
+ * Adds a new task to the task array.
+ * @param task the task object to be added to the array
+ */
+ public void addTask (Task task) {
+ tasks.add(task);
+ size++;
+ }
+
+ /**
+ * Deletes a task from the task array.
+ * @param task the task object to be deleted from the array
+ */
+ public void deleteTask (Task task) {
+ tasks.remove(task);
+ size--;
+ }
+
+ /**
+ * Provides the task located in index index of the array.
+ * @param index the index of the task being queried
+ * @return the task located at index index
+ */
+ public Task get (int index) {
+ return tasks.get(index);
+ }
+
+ /**
+ * Checks if a task exists in the list.
+ * @param task the task to check
+ * @return true if tasks exists in the list, false if it doesn't
+ */
+ public boolean taskExists (Task task) {
+ if (tasks.contains(task) == true) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/src/main/java/Duke/ToDo.java b/src/main/java/Duke/ToDo.java
new file mode 100644
index 0000000000..ade8aa41d7
--- /dev/null
+++ b/src/main/java/Duke/ToDo.java
@@ -0,0 +1,43 @@
+package Duke;
+
+/**
+ * Represents a task object with an item that needs to be done, but does not have a specific date to be completed by.
+ */
+public class ToDo extends Task {
+
+ /**
+ * Constructor for a new todo item.
+ * @param description the description of the ToDo item
+ */
+ public ToDo(String description) {
+ super(description);
+ }
+
+ /**
+ * Constructor for a todo task when reading from a saved file.
+ * @param description description of the ToDo item
+ * @param status the status of the ToDO item
+ */
+ public ToDo(String description, String status) {
+ super(description);
+ if (status.equals("1")) {
+ this.markAsDone();
+ }
+ }
+
+ /**
+ * @return a string containing the status and the description of the todo item for printing.
+ */
+ @Override
+ public String toString() {
+ return ("[T]" + super.toString());
+ }
+
+ /**
+ * @return @return a string of information of the todo item in the format for saving to a file
+ */
+ @Override
+ public String toSaveFormat() {
+ return(super.toSaveFormat() + "T");
+ }
+}
diff --git a/src/main/java/Duke/Ui.java b/src/main/java/Duke/Ui.java
new file mode 100644
index 0000000000..9721099673
--- /dev/null
+++ b/src/main/java/Duke/Ui.java
@@ -0,0 +1,98 @@
+package Duke;
+
+import java.util.ArrayList;
+
+
+/**
+ * Represents the interface between the application and the user where messages are printed to the terminal.
+ */
+public class Ui {
+
+ /**
+ * Displays a list of tasks that have descriptions which contain the keyword searched.
+ * @param taskArray the full task array to search
+ * @param lastShownList the last shown list to be overwritten when this function is called
+ * @param keyword the search term to be matched against task descriptions
+ * @see Ui#printFindResults(ArrayList, int) printFindResults
+ */
+ public static void displayMatchingTasks(TaskList taskArray, ArrayList lastShownList, String keyword) {
+ int lastShownListSize = 0;
+ for (Task i : taskArray.tasks) {
+ if (i.description.contains(keyword)) {
+ lastShownList.add(i);
+ lastShownListSize++;
+ }
+ }
+ if (lastShownListSize > 0) {
+ System.out.println("____________________________________________________________\n" +
+ " Here are the matching tasks in your list:\n");
+ Ui.printFindResults(lastShownList, lastShownListSize);
+ System.out.println("____________________________________________________________\n");
+ } else {
+ System.out.println("There are no tasks matching that description.\n");
+ }
+
+ }
+
+ /**
+ * Prints a messages to user to show the task is going to be deleted from the task array.
+ * @param taskListSize the size of the task array after deletion
+ * @param task the task to be deleted
+ */
+ public static void respondDeleteSuccess(int taskListSize, Task task) {
+
+ System.out.println("____________________________________________________________\n" +
+ "Noted. I've removed this task:\n" + task.toString());
+ System.out.print("Now you have ");
+ System.out.print(taskListSize);
+ if (taskListSize == 1) {
+ System.out.print(" task in the list.\n" +
+ "____________________________________________________________\n");
+ } else {
+ System.out.print(" tasks in the list.\n" +
+ "____________________________________________________________\n");
+ }
+ }
+
+ /**
+ * Prints a message to the user to show that the task has been added successfully to the task array.
+ * @param taskListSize the number of tasks in the array
+ * @param task the new task that was just added
+ */
+ public static void respondAddedSuccess(int taskListSize, Task task) {
+ System.out.println("____________________________________________________________\n" +
+ "Got it. I've added this task:\n" + task.toString());
+ System.out.print("Now you have ");
+ System.out.print(taskListSize);
+ if (taskListSize <= 0) {
+ System.out.print(" task in the list.\n" +
+ "____________________________________________________________");
+ } else {
+ System.out.print(" tasks in the list.\n" +
+ "____________________________________________________________\n");
+ }
+ }
+
+ /**
+ * Prints all tasks in the task array.
+ * @param taskArray the full array of tasks
+ */
+ public static void printTasks(TaskList taskArray) {
+ for (int i = 1; i <= taskArray.size; i++) {
+ System.out.print(i);
+ System.out.println("." + taskArray.get(i - 1).toString());
+ }
+ }
+
+ /**
+ * Prints the results from the {@link Ui#displayMatchingTasks(TaskList, ArrayList, String) displayMatchingTasks} method which provides a list of matching tasks to print.
+ * @param results a list of tasks matching the keyword queried
+ * @param size size of the list of results
+ */
+ public static void printFindResults (ArrayList results, int size) {
+ for (int i = 1; i <= size; i++) {
+ System.out.print(i);
+ System.out.println("." + results.get(i - 1).toString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..5699c7418f
--- /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/tutorials/gradleTutorial.md b/tutorials/gradleTutorial.md
index 08292b118d..f3142111e2 100644
--- a/tutorials/gradleTutorial.md
+++ b/tutorials/gradleTutorial.md
@@ -30,10 +30,10 @@ As a developer, you write a _build file_ that describes the project. A build fil
git checkout master
git merge gradle
```
-1. Open the `build.gradle` file in an editor. Update the following code block to point to the main class (i.e., the one containing the `main` method) of your application. The code below assumes your main class is `seedu.duke.Duke`
+1. Open the `build.gradle` file in an editor. Update the following code block to point to the main class (i.e., the one containing the `main` method) of your application. The code below assumes your main class is `seedu.duke.Duke.Duke`
```groovy
application {
- mainClassName = "seedu.duke.Duke"
+ mainClassName = "seedu.duke.Duke.Duke"
}
```
1. To check if Gradle has been added to the project correctly, open a terminal window, navigate to the root directory of your project and run the command `gradlew run`. This should result in Gradle running the main method of your project.
@@ -146,7 +146,7 @@ By convention, java tests belong in `src/test/java` folder. Create a new `test/j
src
├─main
│ └─java
-│ └─seedu/duke/Duke.java
+│ └─seedu/duke/Duke.Duke.java
└─test
└─java
└─seedu/duke/DukeTest.java
diff --git a/tutorials/javaFxTutorialPart1.md b/tutorials/javaFxTutorialPart1.md
index 561daeca43..b90034895d 100644
--- a/tutorials/javaFxTutorialPart1.md
+++ b/tutorials/javaFxTutorialPart1.md
@@ -44,7 +44,7 @@ javafx {
## Writing your first program
-As customary, let’s start off with a simple “Hello World” program. Modify your `Duke` class to extend `javafx.application.Application`. This requires you to override the `Application#start()` method and provide a concrete implementation. Notice that the method signature for `Application#start()` has a parameter `Stage`. This is the _primary stage_ that JavaFX provides.
+As customary, let’s start off with a simple “Hello World” program. Modify your `Duke.Duke` class to extend `javafx.application.Application`. This requires you to override the `Application#start()` method and provide a concrete implementation. Notice that the method signature for `Application#start()` has a parameter `Stage`. This is the _primary stage_ that JavaFX provides.
```java
import javafx.application.Application;
@@ -52,7 +52,7 @@ import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;
-public class Duke extends Application {
+public class Duke.Duke extends Application {
// ...
@@ -73,7 +73,7 @@ Next, we create another Java class, `Launcher`, as an entry point to our applica
The `Launcher` class is reproduced below in its entirety.
```java
-import javafx.application.Application;
+import Duke.Duke;import javafx.application.Application;
/**
* A launcher class to workaround classpath issues.
diff --git a/tutorials/javaFxTutorialPart2.md b/tutorials/javaFxTutorialPart2.md
index f24a0cd6ad..5060722948 100644
--- a/tutorials/javaFxTutorialPart2.md
+++ b/tutorials/javaFxTutorialPart2.md
@@ -1,8 +1,8 @@
-# JavaFX Tutorial Part 2 - Creating a GUI for Duke
+# JavaFX Tutorial Part 2 - Creating a GUI for Duke.Duke
-In this tutorial, we will be creating a GUI for Duke from scratch based on the following mockup.
+In this tutorial, we will be creating a GUI for Duke.Duke from scratch based on the following mockup.
-![Mockup for Duke](assets/DukeMockup.png)
+![Mockup for Duke.Duke](assets/DukeMockup.png)
## JavaFX controls
@@ -34,7 +34,7 @@ But how do we get the exact layout we want in the UI? JavaFX provides that funct
One way to obtain the layout in the mockup is as follows.
-![Duke's layout](assets/DukeSceneGraph.png)
+![Duke.Duke's layout](assets/DukeSceneGraph.png)
To get that layout, we create a new `AnchorPane` and add our controls to it. Similarly, we create a new `VBox` to hold the contents of the `ScrollPane`. The code should look something like this:
@@ -49,7 +49,7 @@ import javafx.scene.layout.VBox;
import javafx.stage.Stage;
-public class Duke extends Application {
+public class Duke.Duke extends Application {
private ScrollPane scrollPane;
private VBox dialogContainer;
@@ -88,7 +88,7 @@ public class Duke extends Application {
Run the application and you should see something like this:
-![Duke's raw layout](assets/RawLayout.png)
+![Duke.Duke's raw layout](assets/RawLayout.png)
That is not what we were expecting, what did we forget to do?
@@ -106,7 +106,7 @@ Add the following code to the bottom of the `start` method. You'll have to add `
//...
//Step 2. Formatting the window to look as expected
- stage.setTitle("Duke");
+ stage.setTitle("Duke.Duke");
stage.setResizable(false);
stage.setMinHeight(600.0);
stage.setMinWidth(400.0);
@@ -141,7 +141,7 @@ Add the following code to the bottom of the `start` method. You'll have to add `
Run the application again. It should now look like this:
-![Duke's Final layout](assets/FinalLayout.png)
+![Duke.Duke's Final layout](assets/FinalLayout.png)
## Exercises
diff --git a/tutorials/javaFxTutorialPart3.md b/tutorials/javaFxTutorialPart3.md
index a9e1bdddd3..88c48326cd 100644
--- a/tutorials/javaFxTutorialPart3.md
+++ b/tutorials/javaFxTutorialPart3.md
@@ -8,7 +8,7 @@ Rather than to do everything in one try, let’s iterate and build up towards ou
JavaFX has an _event-driven architecture style_. As such, we programmatically define _handler_ methods to execute as a response to certain _events_. When an event is detected, JavaFX will call the respective handlers.
-For Duke, there are two events that we want to respond to, namely the user pressing `Enter` in the `TextField` and left-clicking the `Button`. These are the `onAction` event for the `TextField` and the `onMouseClicked` event for the `Button`.
+For Duke.Duke, there are two events that we want to respond to, namely the user pressing `Enter` in the `TextField` and left-clicking the `Button`. These are the `onAction` event for the `TextField` and the `onMouseClicked` event for the `Button`.
For now, let’s have the application add a new `Label` with the text from the `TextField`. Update the `Main` class as follows. You'll need to add an `import javafx.scene.control.Label;` too.
```java
@@ -103,7 +103,7 @@ import javafx.scene.image.ImageView;
```
Next, add two images to the `main/resources/images` folder.
-For this tutorial, we have two images `DaUser.png` and `DaDuke.png` to represent the user avatar and Duke's avatar respectively but you can use any image you want.
+For this tutorial, we have two images `DaUser.png` and `DaDuke.png` to represent the user avatar and Duke.Duke's avatar respectively but you can use any image you want.
Image|Filename
---|---
@@ -112,7 +112,7 @@ Image|Filename
```java
-public class Duke extends Application {
+public class Duke.Duke extends Application {
// ...
private Image user = new Image(this.getClass().getResourceAsStream("/images/DaUser.png"));
private Image duke = new Image(this.getClass().getResourceAsStream("/images/DaDuke.png"));
@@ -124,7 +124,7 @@ Add a new method to handle user input:
```java
/**
* Iteration 2:
- * Creates two dialog boxes, one echoing user input and the other containing Duke's reply and then appends them to
+ * Creates two dialog boxes, one echoing user input and the other containing Duke.Duke's reply and then appends them to
* the dialog container. Clears the user input after processing.
*/
private void handleUserInput() {
@@ -142,7 +142,7 @@ private void handleUserInput() {
* Replace this stub with your completed method.
*/
private String getResponse(String input) {
- return "Duke heard: " + input;
+ return "Duke.Duke heard: " + input;
}
```
@@ -170,7 +170,7 @@ Run the program and see how it works.
## Iteration 3 – Adding custom behavior to DialogBox
-One additional benefit of defining a custom control is that we can add behavior specific to our `DialogBox`. Let’s add a method to flip a dialog box such that the image on the left to differentiate between user input and Duke’s output.
+One additional benefit of defining a custom control is that we can add behavior specific to our `DialogBox`. Let’s add a method to flip a dialog box such that the image on the left to differentiate between user input and Duke.Duke’s output.
```java
/**
@@ -224,7 +224,7 @@ Run the application and play around with it.
![DialogBoxes Iteration 3](assets/DialogBoxesIteration3.png)
Congratulations!
-You have successfully implemented a fully functional GUI for Duke!
+You have successfully implemented a fully functional GUI for Duke.Duke!
## Exercises
diff --git a/tutorials/javaFxTutorialPart4.md b/tutorials/javaFxTutorialPart4.md
index 0e0ab280c4..19258e8270 100644
--- a/tutorials/javaFxTutorialPart4.md
+++ b/tutorials/javaFxTutorialPart4.md
@@ -29,7 +29,7 @@ FXML is a XML-based language that allows us to define our user interface. Proper
The FXML snippet define a TextField similar to the one that we programmatically defined previous in Tutorial 2. Notice how concise FXML is compared to the plain Java version.
-Let's return to Duke and convert it to use FXML instead.
+Let's return to Duke.Duke and convert it to use FXML instead.
# Rebuilding the Scene using FXML
@@ -101,14 +101,14 @@ We will get to that later.
## Using Controllers
-As part of the effort to separate the code handling Duke's logic and UI, let's _refactor_ the UI-related code to its own class.
+As part of the effort to separate the code handling Duke.Duke's logic and UI, let's _refactor_ the UI-related code to its own class.
We call these UI classes _controllers_.
Let's implement the `MainWindow` controller class that we specified in `MainWindow.fxml`.
**MainWindow.java**
```java
-import javafx.fxml.FXML;
+import Duke;import Duke.Duke;import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
@@ -143,7 +143,7 @@ public class MainWindow extends AnchorPane {
}
/**
- * Creates two dialog boxes, one echoing user input and the other containing Duke's reply and then appends them to
+ * Creates two dialog boxes, one echoing user input and the other containing Duke.Duke's reply and then appends them to
* the dialog container. Clears the user input after processing.
*/
@FXML
@@ -168,7 +168,7 @@ Similarly, methods like private methods like `handleUserInput` can be used in FX
## Using FXML in our application
-Let's create a new `Main` class as the bridge between the existing logic in `Duke` and the UI in `MainWindow`.
+Let's create a new `Main` class as the bridge between the existing logic in `Duke.Duke` and the UI in `MainWindow`.
**Main.java**
```java
@@ -182,7 +182,7 @@ import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
/**
- * A GUI for Duke using FXML.
+ * A GUI for Duke.Duke using FXML.
*/
public class Main extends Application {
diff --git a/tutorials/textUiTestingTutorial.md b/tutorials/textUiTestingTutorial.md
index f397d76aef..d6c9e54ade 100644
--- a/tutorials/textUiTestingTutorial.md
+++ b/tutorials/textUiTestingTutorial.md
@@ -13,7 +13,7 @@
del ACTUAL.TXT
REM compile the code into the bin folder
- javac -cp ..\src -Xlint:none -d ..\bin ..\src\main\java\Duke.java
+ javac -cp ..\src -Xlint:none -d ..\bin ..\src\main\java\Duke.Duke.java
IF ERRORLEVEL 1 (
echo ********** BUILD FAILURE **********
exit /b 1
@@ -21,7 +21,7 @@
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
@@ -44,14 +44,14 @@
fi
# compile the code into the bin folder, terminates if error occurred
- if ! javac -cp ../src -Xlint:none -d ../bin ../src/main/java/Duke.java
+ if ! javac -cp ../src -Xlint:none -d ../bin ../src/main/java/Duke.Duke.java
then
echo "********** BUILD FAILURE **********"
exit 1
fi
# 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
# compare the output to the expected output
diff ACTUAL.TXT EXPECTED.TXT