diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000000..bfdccfd000
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000..00a51aff5e
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,6 @@
+#
+# https://help.github.com/articles/dealing-with-line-endings/
+#
+# These are explicitly windows files and should use crlf
+*.bat text eol=crlf
+
diff --git a/.gitignore b/.gitignore
index f69985ef1f..f803960d66 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,12 @@ bin/
/text-ui-test/ACTUAL.txt
text-ui-test/EXPECTED-UNIX.TXT
+
+# Ignore Gradle project-specific cache directory
+.gradle
+
+# Ignore Gradle build output directory
+build
+
+# Data Storage File
+data/checklst.txt
\ No newline at end of file
diff --git a/.project b/.project
new file mode 100644
index 0000000000..d0aba217ed
--- /dev/null
+++ b/.project
@@ -0,0 +1,34 @@
+
+
+ ip
+ Project ip created by Buildship.
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1613581073555
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 0000000000..5e18705066
--- /dev/null
+++ b/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,13 @@
+arguments=
+auto.sync=false
+build.scans.enabled=false
+connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
+connection.project.dir=
+eclipse.preferences.version=1
+gradle.user.home=
+java.home=/Library/Java/JavaVirtualMachines/jdk-14.0.1.jdk/Contents/Home
+jvm.arguments=
+offline.mode=false
+override.workspace.settings=true
+show.console.view=true
+show.executions.view=true
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000..18ad895236
--- /dev/null
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.source=11
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000000..0aeeaea035
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,22 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "java",
+ "name": "Launch External Terminal",
+ "request": "launch",
+ "console": "externalTerminal",
+ "mainClass": "checklst.main.Loader"
+ },
+ {
+ "type": "java",
+ "name": "Launch Loader",
+ "request": "launch",
+ "mainClass": "checklst.main.Loader",
+ "projectName": "ip_11f7286"
+ },
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000000..f54101a703
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,6 @@
+{
+ "java.project.referencedLibraries": [
+ "lib/**/*.jar",
+ "/Users/glenn/.gradle/caches/modules-2/files-2.1/org.openjfx/**/*.jar"
+ ]
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 0dd8f7fb21..1ca9140013 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,84 @@
-# 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.
-
-## Setting up in Intellij
-
-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. 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).
-1. After that, locate the `src/main/java/Duke.java` file, right-click it, and choose `Run Duke.main()`. If the setup is correct, you should see something like the below:
- ```
- Hello from
- ____ _
- | _ \ _ _| | _____
- | | | | | | | |/ / _ \
- | |_| | |_| | < __/
- |____/ \__,_|_|\_\___|
- ```
+# Checklst
+
+Checklst is a basic Todo app, allowing users to store and track events, deadlines and todos. Checklst has gradually evolved from a basic CLI application to a fully ready GUI.
+
+![](docs/main_ui.png)
+
+# Command Syntax
+
+| Command | Description | Example |
+|--|--|--|
+| `list` | Lists all Tasks | `list` |
+| `todo NAME` | Creates a Todo | `todo Read Books` |
+| `event NAME /at EVENT_DATE` | Creates an Event with a specific occurrence date| `event Concert /at 2020-12-04` |
+| `deadline NAME /by DUE_DATE` | Creates a Deadline with a specific due date | `deadline Assignment /by 2020-12-03` |
+| `done INDEX` | Completes the Task | `done 1` |
+| `delete INDEX` | Deletes the Task | `delete 1` |
+| `find KEYWORD` | Finds all Tasks whose name contains the Keyword | `find CS2103` |
+| `sort` | Sorts all Tasks by Complete/Incomplete and then Task Type | `sort` |
+| `help` | Shows all Commands | `help` |
+| `bye` | Exits Checklst | `bye` |
+
+
+# Features
+
+## Creating a Task
+Tasks can be one of 3 types - Todo, Event and Deadline. Todos are basic named Tasks while Events and Deadlines both contain a date which corresponds to their event date and due date respectively.
+
+Tasks can be made using commands `todo`, `event`, `deadline` to create each type of task respectively. Tasks will be labelled according to their task type in the Checklst application as follows:
+
+| Task Command | Task Representation
+|--|--|
+| `todo Read Books` | [T][ ] Read Books |
+| `event Concert /at 2020-12-04` | [E][ ] Concert (at: Dec 4 2020) |
+| `deadline Assignment /by 2020-12-03` | [D][ ] Assignment (by: Dec 3 2020) |
+
+
+## Listing Tasks and Completing a Task
+Tasks can be listed using the `list` command.
+
+Once a Task is made, it will be by default labelled as incomplete. A task can then be completed using the `done` command to mark it as completed. The index value of the task starts from index 1 and can be referenced from the `list` command.
+
+| Task Command | Expected Output
+|--|--|
+| `list` | These are your current tasks:
1. [T][ ] Read Books |
+| `done 1` | [T][X] Read Books |
+| `list` | These are your current tasks:
1. [T][X] Read Books |
+
+## Deleting a Task
+Tasks can be removed from Checklst by using the `delete` command. Similarly, the index value starts from index 1.
+
+| Task Command | Expected Output
+|--|--|
+| `list` | These are your current tasks:
1. [T][X] Read Books |
+| `delete 1` | [T][X] Read Books |
+| `list` | Task list is currently empty! |
+
+
+## Finding Tasks
+To easily retrieve tasks when the Task List gets convoluted, the `find` command may be used with a keyword that will be matched to tasks. As long as some part of a Task's name contains the keyword, it will be returned.
+
+| Task Command | Expected Output
+|--|--|
+| `list` | These are your current tasks:
1. [T][ ] Read Books
2. [T][ ] Return Books
3. [T][ ] Eat Lunch|
+| `find books` | Here are the matching tasks in your list!
1. [T][ ] Read Books
2. [T][ ] Return Books |
+
+
+## Sorting Tasks
+Tasks are added to the bottom of the Task List via a Chronological input order. However, the tasks may be deliberately sorted on will via the `sort` command.
+
+The sorting will be done via 2 conditions. Firstly, the tasks will be split into complete and incomplete. Secondly, the tasks will be sorted by Task type.
+
+| Task Command | Expected Output
+|--|--|
+| `list` | These are your current tasks:
1. [T][ ] Read Books
2. [E][ ] Movie (at: Apr 24 2020)
3. [T][X] Return Books
4. [E][ ] Concert (at: Feb 13 2020) |
+| `sort` | These are your current tasks:
1. [T][ ] Read Books
2. [E][ ] Movie (at: Apr 24 2020)
3. [E][ ] Concert (at: Feb 13 2020)
4. [T][X] Return Books |
+
+## Errors
+Checklst is is capable of handling errors in command or keyword inputs. Whenever an error is encounted, Checklst will return the error message with a clear red indicator.
+
+![](docs/Ui.png)
+
+## Credits
+Icons in Checklst are made by and used with courtesy from Flat Icons.
+
"https://www.flaticon.com/"
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000000..9d9dd966e7
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,71 @@
+plugins {
+ id 'java'
+ id 'application'
+ id 'checkstyle'
+ id 'java-library'
+ id 'com.github.johnrengelman.shadow' version '5.1.0'
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.5.0'
+ testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.5.0'
+
+ String javaFxVersion = '11'
+
+ implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'win'
+ implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'mac'
+ implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'linux'
+ implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'win'
+ implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'mac'
+ implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'linux'
+ implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'win'
+ implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'mac'
+ implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'linux'
+ implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'win'
+ implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'mac'
+ implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'linux'
+}
+
+test {
+ useJUnitPlatform()
+
+ testLogging {
+ events "passed", "skipped", "failed"
+
+ showExceptions true
+ exceptionFormat "full"
+ showCauses true
+ showStackTraces true
+ showStandardStreams = false
+ }
+}
+
+application {
+ mainClassName = "checklst.main.Loader"
+}
+
+shadowJar {
+ archiveBaseName = "checklst"
+ archiveClassifier = null
+}
+
+checkstyle {
+ toolVersion = '8.32'
+}
+
+run {
+ enableAssertions = true
+ standardInput = System.in
+}
+
+java {
+ toolchain {
+ languageVersion = JavaLanguageVersion.of(11)
+ }
+}
+
+version = '1.2.1'
\ No newline at end of file
diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
new file mode 100644
index 0000000000..502fbd3a58
--- /dev/null
+++ b/config/checkstyle/checkstyle.xml
@@ -0,0 +1,398 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml
new file mode 100644
index 0000000000..dcaa1af3c3
--- /dev/null
+++ b/config/checkstyle/suppressions.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data/checklst.txt b/data/checklst.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/docs/README.md b/docs/README.md
index fd44069597..665c0b248f 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,20 +1,87 @@
-# User Guide
+# Checklst
-## Features
+Checklst is a basic Todo app, allowing users to store and track events, deadlines and todos. Checklst has gradually evolved from a basic CLI application to a fully ready GUI.
-### Feature 1
-Description of feature.
+#### Github Link
+https://github.com/glennljs/ip
-## Usage
+![](main_ui.png)
-### `Keyword` - Describe action
+# Command Syntax
-Describe action and its outcome.
+| Command | Description | Example |
+|--|--|--|
+| `list` | Lists all Tasks | `list` |
+| `todo NAME` | Creates a Todo | `todo Read Books` |
+| `event NAME /at EVENT_DATE` | Creates an Event with a specific occurrence date| `event Concert /at 2020-12-04` |
+| `deadline NAME /by DUE_DATE` | Creates a Deadline with a specific due date | `deadline Assignment /by 2020-12-03` |
+| `done INDEX` | Completes the Task | `done 1` |
+| `delete INDEX` | Deletes the Task | `delete 1` |
+| `find KEYWORD` | Finds all Tasks whose name contains the Keyword | `find CS2103` |
+| `sort` | Sorts all Tasks by Complete/Incomplete and then Task Type | `sort` |
+| `help` | Shows all Commands | `help` |
+| `bye` | Exits Checklst | `bye` |
-Example of usage:
-`keyword (optional arguments)`
+# Features
-Expected outcome:
+## Creating a Task
+Tasks can be one of 3 types - Todo, Event and Deadline. Todos are basic named Tasks while Events and Deadlines both contain a date which corresponds to their event date and due date respectively.
-`outcome`
+Tasks can be made using commands `todo`, `event`, `deadline` to create each type of task respectively. Tasks will be labelled according to their task type in the Checklst application as follows:
+
+| Task Command | Task Representation
+|--|--|
+| `todo Read Books` | [T][ ] Read Books |
+| `event Concert /at 2020-12-04` | [E][ ] Concert (at: Dec 4 2020) |
+| `deadline Assignment /by 2020-12-03` | [D][ ] Assignment (by: Dec 3 2020) |
+
+
+## Listing Tasks and Completing a Task
+Tasks can be listed using the `list` command.
+
+Once a Task is made, it will be by default labelled as incomplete. A task can then be completed using the `done` command to mark it as completed. The index value of the task starts from index 1 and can be referenced from the `list` command.
+
+| Task Command | Expected Output
+|--|--|
+| `list` | These are your current tasks:
1. [T][ ] Read Books |
+| `done 1` | [T][X] Read Books |
+| `list` | These are your current tasks:
1. [T][X] Read Books |
+
+## Deleting a Task
+Tasks can be removed from Checklst by using the `delete` command. Similarly, the index value starts from index 1.
+
+| Task Command | Expected Output
+|--|--|
+| `list` | These are your current tasks:
1. [T][X] Read Books |
+| `delete 1` | [T][X] Read Books |
+| `list` | Task list is currently empty! |
+
+
+## Finding Tasks
+To easily retrieve tasks when the Task List gets convoluted, the `find` command may be used with a keyword that will be matched to tasks. As long as some part of a Task's name contains the keyword, it will be returned.
+
+| Task Command | Expected Output
+|--|--|
+| `list` | These are your current tasks:
1. [T][ ] Read Books
2. [T][ ] Return Books
3. [T][ ] Eat Lunch|
+| `find books` | Here are the matching tasks in your list!
1. [T][ ] Read Books
2. [T][ ] Return Books |
+
+
+## Sorting Tasks
+Tasks are added to the bottom of the Task List via a Chronological input order. However, the tasks may be deliberately sorted on will via the `sort` command.
+
+The sorting will be done via 2 conditions. Firstly, the tasks will be split into complete and incomplete. Secondly, the tasks will be sorted by Task type.
+
+| Task Command | Expected Output
+|--|--|
+| `list` | These are your current tasks:
1. [T][ ] Read Books
2. [E][ ] Movie (at: Apr 24 2020)
3. [T][X] Return Books
4. [E][ ] Concert (at: Feb 13 2020) |
+| `sort` | These are your current tasks:
1. [T][ ] Read Books
2. [E][ ] Movie (at: Apr 24 2020)
3. [E][ ] Concert (at: Feb 13 2020)
4. [T][X] Return Books |
+
+## Errors
+Checklst is is capable of handling errors in command or keyword inputs. Whenever an error is encounted, Checklst will return the error message with a clear red indicator.
+
+![](Ui.png)
+
+## Credits
+Icons in Checklst are made by and used with courtesy from Flat Icons.
+
"https://www.flaticon.com/"
\ No newline at end of file
diff --git a/docs/Ui.png b/docs/Ui.png
new file mode 100644
index 0000000000..ace7bdc6ec
Binary files /dev/null and b/docs/Ui.png differ
diff --git a/docs/main_ui.png b/docs/main_ui.png
new file mode 100644
index 0000000000..23f8a2af9b
Binary files /dev/null and b/docs/main_ui.png differ
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000..e708b1c023
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000..28ff446a21
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000000..4f906e0c81
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000000..107acd32c4
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000000..aec1281716
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,10 @@
+/*
+ * This file was generated by the Gradle 'init' task.
+ *
+ * The settings file is used to specify which projects to include in your build.
+ *
+ * Detailed information about configuring a multi-project build in Gradle can be found
+ * in the user manual at https://docs.gradle.org/6.8.1/userguide/multi_project_builds.html
+ */
+
+rootProject.name = 'ip'
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/checklst/exception/ChecklstException.java b/src/main/java/checklst/exception/ChecklstException.java
new file mode 100644
index 0000000000..3c7ca1ff1a
--- /dev/null
+++ b/src/main/java/checklst/exception/ChecklstException.java
@@ -0,0 +1,21 @@
+package checklst.exception;
+
+/**
+ * Custom exception to represent Exceptions in the Checklst program.
+ */
+public class ChecklstException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 4447981462872622989L;
+
+ /**
+ * Creates instance for Checklst Exceptions.
+ * @param errMessage Error message to be displayed.
+ */
+ public ChecklstException(String errMessage) {
+ super(errMessage);
+ }
+
+}
diff --git a/src/main/java/checklst/gui/ChecklstDialog.java b/src/main/java/checklst/gui/ChecklstDialog.java
new file mode 100644
index 0000000000..b581cd9306
--- /dev/null
+++ b/src/main/java/checklst/gui/ChecklstDialog.java
@@ -0,0 +1,30 @@
+package checklst.gui;
+
+import javafx.geometry.Insets;
+import javafx.scene.control.Label;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.Background;
+import javafx.scene.layout.BackgroundFill;
+import javafx.scene.layout.CornerRadii;
+import javafx.scene.paint.Color;
+
+public class ChecklstDialog extends DialogBox {
+
+ private static final String NAME = "Checklst";
+
+ /**
+ * Creates a message dialog from the Checklst bot.
+ * @param l Message to be shown.
+ * @param iv Image of Checklst.
+ */
+ public ChecklstDialog(Label l, ImageView iv) {
+ super(NAME, l, iv);
+
+ Color dialogColor = new Color(0, 0.7, 1, 1);
+ this.text.setBackground(
+ new Background(new BackgroundFill(dialogColor, new CornerRadii(7.0), Insets.EMPTY)));
+
+ this.flip();
+ }
+
+}
diff --git a/src/main/java/checklst/gui/DialogBox.java b/src/main/java/checklst/gui/DialogBox.java
new file mode 100644
index 0000000000..1e78b41beb
--- /dev/null
+++ b/src/main/java/checklst/gui/DialogBox.java
@@ -0,0 +1,55 @@
+package checklst.gui;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
+import javafx.scene.control.Label;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+import javafx.scene.text.Font;
+import javafx.scene.text.FontWeight;
+
+public class DialogBox extends HBox {
+
+ protected Label name;
+ protected Label text;
+ protected ImageView displayPicture;
+
+ protected DialogBox(String name, Label l, ImageView iv) {
+ this.text = l;
+ this.text.setFont(new Font("Arial", 14));
+ this.displayPicture = iv;
+ this.name = new Label(name);
+
+ this.text.setWrapText(true);
+ this.text.setPadding(new Insets(10));
+
+ this.displayPicture.setFitWidth(50.0);
+ this.displayPicture.setFitHeight(50.0);
+ DialogBox.setMargin(this.displayPicture, new Insets(21, 5, 3, 5));
+
+ this.name.setFont(Font.font("Arial", FontWeight.BOLD, 14));
+ this.name.setPadding(new Insets(2));
+
+ VBox output = new VBox(this.name, this.text);
+
+ this.setPadding(new Insets(5));
+
+ this.setAlignment(Pos.TOP_RIGHT);
+ this.getChildren().addAll(output, displayPicture);
+ }
+
+ /**
+ * Flips the dialog box such that the ImageView is on the left and text on the right.
+ */
+ protected void flip() {
+ this.setAlignment(Pos.TOP_LEFT);
+ ObservableList tmp = FXCollections.observableArrayList(this.getChildren());
+ FXCollections.reverse(tmp);
+ this.getChildren().setAll(tmp);
+ }
+
+}
diff --git a/src/main/java/checklst/gui/ErrorDialog.java b/src/main/java/checklst/gui/ErrorDialog.java
new file mode 100644
index 0000000000..0ddb4a0a17
--- /dev/null
+++ b/src/main/java/checklst/gui/ErrorDialog.java
@@ -0,0 +1,30 @@
+package checklst.gui;
+
+import javafx.geometry.Insets;
+import javafx.scene.control.Label;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.Background;
+import javafx.scene.layout.BackgroundFill;
+import javafx.scene.layout.CornerRadii;
+import javafx.scene.paint.Color;
+
+public class ErrorDialog extends DialogBox {
+
+ private static final String NAME = "Checklst - Error";
+
+ /**
+ * Creates an error dialog from the Checklst bot.
+ * @param l Error to be shown.
+ * @param iv Image of Checklst.
+ */
+ public ErrorDialog(Label l, ImageView iv) {
+ super(NAME, l, iv);
+
+ Color dialogColor = new Color(1, 0, 0, 1);
+ this.text.setBackground(
+ new Background(new BackgroundFill(dialogColor, new CornerRadii(7.0), Insets.EMPTY)));
+
+ this.flip();
+ }
+
+}
diff --git a/src/main/java/checklst/gui/UserDialog.java b/src/main/java/checklst/gui/UserDialog.java
new file mode 100644
index 0000000000..a5bf079bd9
--- /dev/null
+++ b/src/main/java/checklst/gui/UserDialog.java
@@ -0,0 +1,28 @@
+package checklst.gui;
+
+import javafx.geometry.Insets;
+import javafx.scene.control.Label;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.Background;
+import javafx.scene.layout.BackgroundFill;
+import javafx.scene.layout.CornerRadii;
+import javafx.scene.paint.Color;
+
+public class UserDialog extends DialogBox {
+
+ private static final String NAME = "You";
+
+ /**
+ * Creates a message dialog from the user.
+ * @param l Message to be shown.
+ * @param iv Image of User.
+ */
+ public UserDialog(Label l, ImageView iv) {
+ super(NAME, l, iv);
+
+ Color dialogColor = new Color(1, 0.7, 0, 1);
+ this.text.setBackground(
+ new Background(new BackgroundFill(dialogColor, new CornerRadii(7.0), Insets.EMPTY)));
+ }
+
+}
diff --git a/src/main/java/checklst/main/Checklst.java b/src/main/java/checklst/main/Checklst.java
new file mode 100644
index 0000000000..90b11b633e
--- /dev/null
+++ b/src/main/java/checklst/main/Checklst.java
@@ -0,0 +1,173 @@
+package checklst.main;
+
+import checklst.exception.ChecklstException;
+import checklst.gui.ChecklstDialog;
+import checklst.gui.DialogBox;
+import checklst.gui.ErrorDialog;
+import checklst.gui.UserDialog;
+import checklst.parser.Parser;
+import checklst.storage.Storage;
+import checklst.task.TaskList;
+import checklst.ui.Ui;
+import javafx.application.Application;
+import javafx.application.Platform;
+import javafx.geometry.Insets;
+import javafx.scene.Scene;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.ScrollPane;
+import javafx.scene.control.TextField;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.AnchorPane;
+import javafx.scene.layout.Region;
+import javafx.scene.layout.VBox;
+import javafx.scene.text.Font;
+import javafx.stage.Stage;
+
+/**
+ * The Checklst Class represents the entry point of the Checklst Program.
+ */
+public class Checklst extends Application {
+
+ private static final Font STANDARD_FONT = new Font("Arial", 14);
+
+ private final Ui ui = new Ui();
+ private final TaskList taskList = new TaskList();
+ private final Parser parser = new Parser(this.taskList);
+ private final Storage storage = new Storage();
+
+ private ScrollPane scrollPane;
+ private VBox dialogContainer;
+ private TextField userInput;
+ private Button sendButton;
+ private Scene scene;
+ private Image userIcon = new Image(this.getClass().getResourceAsStream("/images/UserIcon.png"));
+ private Image checklstIcon = new Image(this.getClass().getResourceAsStream("/images/ChecklstIcon.png"));
+
+ @Override
+ public void start(Stage stage) {
+
+ //Step 1. Formatting the window to look as expected.
+ scrollPane = new ScrollPane();
+ dialogContainer = new VBox();
+ scrollPane.setContent(dialogContainer);
+
+ this.userInput = new TextField();
+ this.userInput.setFont(STANDARD_FONT);
+ this.sendButton = new Button("Send");
+ this.sendButton.setFont(STANDARD_FONT);
+
+ AnchorPane mainLayout = new AnchorPane();
+ mainLayout.getChildren().addAll(scrollPane, userInput, sendButton);
+
+ scene = new Scene(mainLayout);
+
+ stage.setScene(scene);
+ stage.show();
+
+ //Step 2. Formatting the window to look as expected
+ stage.setTitle("Checklst");
+ stage.setResizable(false);
+ stage.setMinHeight(600.0);
+ stage.setMinWidth(400.0);
+
+ mainLayout.setPrefSize(400.0, 600.0);
+
+ this.scrollPane.setPrefSize(385, 535);
+ this.scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
+ this.scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
+
+ this.scrollPane.setVvalue(1.0);
+ this.scrollPane.setFitToWidth(true);
+ this.scrollPane.setStyle("-fx-background-color: transparent; -fx-background: rgb(207, 232, 243);");
+
+ this.dialogContainer.setPrefHeight(Region.USE_COMPUTED_SIZE);
+
+ this.userInput.setPrefWidth(325.0);
+ this.userInput.setPrefHeight(32.0);
+ this.sendButton.setPrefWidth(70.0);
+ this.sendButton.setPrefHeight(32.0);
+
+ AnchorPane.setTopAnchor(scrollPane, 1.0);
+ AnchorPane.setBottomAnchor(sendButton, 1.0);
+ AnchorPane.setRightAnchor(sendButton, 1.0);
+
+ AnchorPane.setLeftAnchor(userInput , 1.0);
+ AnchorPane.setBottomAnchor(userInput, 1.0);
+
+ // Step 3. Add functionality to handle user input.
+ this.sendButton.setOnMouseClicked((event) -> {
+ this.handleUserInput();
+ });
+
+ this.userInput.setOnAction((event) -> {
+ this.handleUserInput();
+ });
+
+ //Scroll down to the end every time dialogContainer's height changes.
+ this.dialogContainer.heightProperty().addListener((observable) -> scrollPane.setVvalue(1.0));
+
+ // Get History
+ try {
+ this.storage.parseHistory(this.taskList);
+ this.addChecklstMessage("History successfully parsed!");
+ } catch (ChecklstException e) {
+ this.addErrorMessage(e.getMessage());
+ }
+
+ this.addChecklstMessage(this.ui.sendWelcome());
+
+ }
+
+ /**
+ * Iteration 2:
+ * Creates two dialog boxes, one echoing user input and the other containing Duke's reply and then appends them to
+ * the dialog container. Clears the user input after processing.
+ */
+ private void handleUserInput() {
+ if (userInput.getText().equals("bye")) {
+ try {
+ Platform.exit();
+ } catch (Exception e) {
+ // Do nothing
+ }
+ }
+
+ this.addUserMessage(userInput.getText());
+
+ String response = "";
+ try {
+ response = this.parser.parse(userInput.getText().split(" ", 2));
+ this.addChecklstMessage(response);
+ } catch (ChecklstException e) {
+ this.addErrorMessage(e.getMessage());
+ }
+
+ userInput.clear();
+ }
+
+ private void addChecklstMessage(String input) {
+ DialogBox newDialogBox = new ChecklstDialog(new Label(input), new ImageView(checklstIcon));
+ this.dialogContainer.getChildren().add(newDialogBox);
+ VBox.setMargin(newDialogBox, new Insets(3));
+ }
+
+ private void addUserMessage(String input) {
+ DialogBox newDialogBox = new UserDialog(new Label(input), new ImageView(userIcon));
+ this.dialogContainer.getChildren().add(newDialogBox);
+ VBox.setMargin(newDialogBox, new Insets(3));
+ }
+
+ private void addErrorMessage(String input) {
+ DialogBox newDialogBox = new ErrorDialog(new Label(input), new ImageView(checklstIcon));
+ this.dialogContainer.getChildren().add(newDialogBox);
+ VBox.setMargin(newDialogBox, new Insets(3));
+ }
+
+ @Override
+ public void stop() throws Exception {
+ this.storage.saveToFile(this.taskList);
+ }
+
+}
diff --git a/src/main/java/checklst/main/Loader.java b/src/main/java/checklst/main/Loader.java
new file mode 100644
index 0000000000..4f7a598357
--- /dev/null
+++ b/src/main/java/checklst/main/Loader.java
@@ -0,0 +1,14 @@
+package checklst.main;
+
+import javafx.application.Application;
+
+/**
+ * A launcher class to workaround classpath issues.
+ */
+public class Loader {
+
+ public static void main(String[] args) {
+ Application.launch(Checklst.class, args);
+ }
+
+}
diff --git a/src/main/java/checklst/parser/CheckedFunction.java b/src/main/java/checklst/parser/CheckedFunction.java
new file mode 100644
index 0000000000..d9325ebf57
--- /dev/null
+++ b/src/main/java/checklst/parser/CheckedFunction.java
@@ -0,0 +1,8 @@
+package checklst.parser;
+
+import checklst.exception.ChecklstException;
+
+@FunctionalInterface
+public interface CheckedFunction {
+ R apply(T t) throws ChecklstException;
+}
diff --git a/src/main/java/checklst/parser/MethodPair.java b/src/main/java/checklst/parser/MethodPair.java
new file mode 100644
index 0000000000..e8df995681
--- /dev/null
+++ b/src/main/java/checklst/parser/MethodPair.java
@@ -0,0 +1,26 @@
+package checklst.parser;
+
+public class MethodPair {
+
+ private final String description;
+ private final CheckedFunction method;
+
+ /**
+ * Creates a new Method Pair of Description and Function to be run.
+ * @param description Description of method.
+ * @param method Functional Interface method to be run on call.
+ */
+ public MethodPair(String description, CheckedFunction method) {
+ this.description = description;
+ this.method = method;
+ }
+
+ public String getDescription() {
+ return this.description;
+ }
+
+ public CheckedFunction getMethod() {
+ return this.method;
+ }
+
+}
diff --git a/src/main/java/checklst/parser/Parser.java b/src/main/java/checklst/parser/Parser.java
new file mode 100644
index 0000000000..405fe24603
--- /dev/null
+++ b/src/main/java/checklst/parser/Parser.java
@@ -0,0 +1,106 @@
+package checklst.parser;
+
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import checklst.exception.ChecklstException;
+import checklst.task.Deadline;
+import checklst.task.Event;
+import checklst.task.Task;
+import checklst.task.TaskList;
+import checklst.task.Todo;
+
+/**
+ * The Parser class makes sense of inputs and runs the respective follow up methods.
+ */
+public class Parser {
+
+ private final TaskList taskList;
+ private final Map methodMap = Map.of(
+ "list", new MethodPair("Lists all Tasks", x -> list(x)),
+ "todo", new MethodPair("Creates a Todo", x -> todo(x)),
+ "event", new MethodPair("Creates an Event", x -> event(x)),
+ "deadline", new MethodPair("Creates a Deadline", x -> deadline(x)),
+ "done", new MethodPair("Completes a Task", x -> done(x)),
+ "delete", new MethodPair("Deletes a Task", x -> delete(x)),
+ "find", new MethodPair("Finds a Task", x -> find(x)),
+ "sort", new MethodPair("Sorts Taks", x -> sort(x)),
+ "help", new MethodPair("Get all Commands", x -> help(x)),
+ "bye", new MethodPair("Exits Checklst", x -> null)
+ );
+
+ public Parser(TaskList taskList) {
+ this.taskList = taskList;
+ }
+
+ /**
+ * Parses the input string and returns the corresponding command.
+ * @param input Input string to be parsed.
+ * @return String representing the output.
+ * @throws ChecklstException Exception when command is invalid.
+ */
+ public String parse(String[] input) throws ChecklstException {
+ MethodPair method = methodMap.get(input[0]);
+
+ if (method == null) {
+ throw new ChecklstException("Sorry I didn't understand that command!");
+ }
+
+ return method.getMethod().apply(input);
+ }
+
+ private String list(String[] input) {
+ return this.taskList.toString();
+ }
+
+ private String todo(String[] input) throws ChecklstException {
+ assert input.length >= 1 : "No Todo Input";
+ Task newTodo = Todo.makeTodo(input[1]);
+ return this.taskList.add(newTodo);
+ }
+
+ private String event(String[] input) throws ChecklstException {
+ assert input.length >= 1 : "No Event Input";
+ Task newEvent = Event.makeEvent(input[1]);
+ return this.taskList.add(newEvent);
+ }
+
+ private String deadline(String[] input) throws ChecklstException {
+ assert input.length >= 1 : "No Deadline Input";
+ Task newDeadline = Deadline.makeDeadline(input[1]);
+ return this.taskList.add(newDeadline);
+ }
+
+ private String done(String[] input) throws ChecklstException {
+ assert input.length >= 1 : "No Done Input";
+ int doneIndex = Integer.parseInt(input[1]);
+ return "Nice! I've marked this task as done!\n" + this.taskList.completeTask(doneIndex);
+ }
+
+ private String delete(String[] input) throws ChecklstException {
+ assert input.length >= 1 : "No Delete Input";
+ int deleteIndex = Integer.parseInt(input[1]);
+ return "Alright! I've deleted this task!\n" + this.taskList.deleteTask(deleteIndex);
+ }
+
+ private String find(String[] input) throws ChecklstException {
+ assert input.length >= 1 : "No Find Input";
+ return "Here are the matching tasks in your list!\n" + this.taskList.findTask(input[1]);
+ }
+
+ private String sort(String[] input) {
+ return this.taskList.sort();
+ }
+
+ private String help(String[] input) {
+ return "These are the Commands Available:\n"
+ + this.methodMap.entrySet().stream()
+ .map(x -> x.getKey() + ": " + x.getValue().getDescription())
+ .collect(Collectors.toList())
+ .toString()
+ .replace("[", "")
+ .replace("]", "")
+ .replace(", ", "\n");
+ }
+
+}
diff --git a/src/main/java/checklst/storage/Storage.java b/src/main/java/checklst/storage/Storage.java
new file mode 100644
index 0000000000..92f40359bb
--- /dev/null
+++ b/src/main/java/checklst/storage/Storage.java
@@ -0,0 +1,81 @@
+package checklst.storage;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import checklst.exception.ChecklstException;
+import checklst.task.Deadline;
+import checklst.task.Event;
+import checklst.task.TaskList;
+import checklst.task.Todo;
+
+/**
+ * The Storage class stores and processes the saved commands.
+ */
+public class Storage {
+
+ private List exportList = new ArrayList<>();
+
+ /**
+ * Saves the command history to the save file.
+ * @throws ChecklstException Exception when unable to save or write to file.
+ */
+ public void saveToFile(TaskList taskList) throws ChecklstException {
+ File history = new File("./data/checklst.txt");
+ history.getParentFile().mkdirs();
+
+ assert history.canWrite() : "Can't Write to file!";
+
+ try {
+ history.createNewFile();
+ } catch (IOException | SecurityException e) {
+ throw new ChecklstException("Unable to make file!");
+ }
+
+ try (PrintStream out = new PrintStream(new FileOutputStream("./data/checklst.txt"))) {
+ exportList = taskList.getTaskList().stream().map(x -> x.export()).collect(Collectors.toList());
+ out.print(this.exportList.toString().replace("[", "").replace("]", "").replace(", ", "\n"));
+ } catch (FileNotFoundException e) {
+ throw new ChecklstException("File not found! Please create a file at path ./data/checklst.txt");
+ }
+ }
+
+ /**
+ * Processes history commands and run the relevant Task parser.
+ * @param taskList TaskList to add Tasks to.
+ * @throws ChecklstException Exception if strings are corrupted.
+ */
+ public void parseHistory(TaskList taskList) throws ChecklstException {
+ try {
+ String[] history = Files.readString(Paths.get("./data/checklst.txt")).split("\n");
+ for (String task: history) {
+ if (task.isBlank()) {
+ continue;
+ }
+
+ if (task.charAt(0) == 'T') {
+ taskList.add(Todo.parseTodo(task));
+ } else if (task.charAt(0) == 'D') {
+ taskList.add(Deadline.parseDeadline(task));
+ } else if (task.charAt(0) == 'E') {
+ taskList.add(Event.parseEvent(task));
+ } else {
+ throw new ChecklstException("History corrupted!");
+ }
+ }
+ } catch (InvalidPathException | IOException e) {
+ throw new ChecklstException("No history found... Initializing from blank state!");
+ }
+
+ }
+
+}
diff --git a/src/main/java/checklst/task/Deadline.java b/src/main/java/checklst/task/Deadline.java
new file mode 100644
index 0000000000..860f6acbeb
--- /dev/null
+++ b/src/main/java/checklst/task/Deadline.java
@@ -0,0 +1,92 @@
+package checklst.task;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+
+import checklst.exception.ChecklstException;
+
+/**
+ * The Deadline class represents a Task with a specific Deadline.
+ */
+public class Deadline extends Task {
+
+ protected final LocalDate dueDate;
+
+ protected Deadline(String name, LocalDate dueDate) {
+ super(name);
+ this.dueDate = dueDate;
+ }
+
+ protected Deadline(String name, boolean completed, LocalDate dueDate) {
+ super(name, completed);
+ this.dueDate = dueDate;
+ }
+
+ /**
+ * Creates a new Deadline object.
+ * @param input Input for the Deadline in the form "{ name } /by { date }".
+ * @return New Deadline object.
+ */
+ public static Deadline makeDeadline(String input) throws ChecklstException {
+ String[] splitInput = input.split(" /by ");
+ if (splitInput.length == 1) {
+ throw new ChecklstException("Inproper Deadline format used! Please use { name } /by { deadline }");
+ } else if (splitInput[0].equals("")) {
+ throw new ChecklstException("Deadline needs a name!");
+ } else if (splitInput[0].contains(";") || splitInput[1].contains(";")) {
+ throw new ChecklstException("Sorry, Deadline input cannot contain a \";\"!");
+ }
+
+
+ LocalDate dueDate;
+ try {
+ dueDate = LocalDate.parse(splitInput[1]);
+ } catch (DateTimeParseException e) {
+ throw new ChecklstException("Incorrect DateTime format! Please use YYYY-MM-DD");
+ }
+
+ return new Deadline(splitInput[0], dueDate);
+ }
+
+ /**
+ * Parses a saved Deadline string.
+ * @param input Deadline string.
+ * @return Deadline object.
+ */
+ public static Deadline parseDeadline(String input) {
+ String[] splitInput = input.split(" ; ");
+ String name = splitInput[2];
+ boolean completed = splitInput[1].equals("X") ? true : false;
+ LocalDate dueDate = LocalDate.parse(splitInput[3]);
+
+ return new Deadline(name, completed, dueDate);
+ }
+
+ @Override
+ public String export() {
+ String output = "D ; ";
+
+ if (this.isCompleted) {
+ output += "X ; ";
+ } else {
+ output += "O ; ";
+ }
+
+ output += this.name + " ; " + this.dueDate.toString();
+
+ return output;
+ }
+
+ @Override
+ public Task complete() {
+ return new Deadline(this.name, true, this.dueDate);
+ }
+
+ @Override
+ public String toString() {
+ return "[D]" + super.toString() + " (by: "
+ + this.dueDate.format(DateTimeFormatter.ofPattern("MMM dd yyyy")) + ")";
+ }
+
+}
diff --git a/src/main/java/checklst/task/Event.java b/src/main/java/checklst/task/Event.java
new file mode 100644
index 0000000000..41f7274473
--- /dev/null
+++ b/src/main/java/checklst/task/Event.java
@@ -0,0 +1,91 @@
+package checklst.task;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+
+import checklst.exception.ChecklstException;
+
+/**
+ * The Event class represents a Task which has a specific DateTime.
+ */
+public class Event extends Task {
+
+ protected final LocalDate eventDate;
+
+ protected Event(String name, LocalDate eventDate) {
+ super(name);
+ this.eventDate = eventDate;
+ }
+
+ protected Event(String name, boolean completed, LocalDate eventDate) {
+ super(name, completed);
+ this.eventDate = eventDate;
+ }
+
+ /**
+ * Creates a new Event object.
+ * @param input Input for the Event in the form "{ name } /at { date }".
+ * @return New Event object.
+ */
+ public static Event makeEvent(String input) throws ChecklstException {
+ String[] splitInput = input.split(" /at ");
+ if (splitInput.length == 1) {
+ throw new ChecklstException("Inproper Event format used! Please use { name } /at { event }");
+ } else if (splitInput[0].equals("")) {
+ throw new ChecklstException("Event needs a name!");
+ } else if (splitInput[0].contains(";") || splitInput[1].contains(";")) {
+ throw new ChecklstException("Sorry, Event input cannot contain a \";\"!");
+ }
+
+ LocalDate eventDate;
+ try {
+ eventDate = LocalDate.parse(splitInput[1]);
+ } catch (DateTimeParseException e) {
+ throw new ChecklstException("Incorrect Event Date format! Please use YYYY-MM-DD");
+ }
+
+ return new Event(splitInput[0], eventDate);
+ }
+
+ /**
+ * Parses a saved Event string.
+ * @param input Event string.
+ * @return Event object.
+ */
+ public static Event parseEvent(String input) {
+ String[] splitInput = input.split(" ; ");
+ String name = splitInput[2];
+ boolean completed = splitInput[1].equals("X") ? true : false;
+ LocalDate dateTime = LocalDate.parse(splitInput[3]);
+
+ return new Event(name, completed, dateTime);
+ }
+
+ @Override
+ public String export() {
+ String output = "E ; ";
+
+ if (this.isCompleted) {
+ output += "X ; ";
+ } else {
+ output += "O ; ";
+ }
+
+ output += this.name + " ; " + this.eventDate.toString();
+
+ return output;
+ }
+
+ @Override
+ public Task complete() {
+ return new Event(this.name, true, this.eventDate);
+ }
+
+ @Override
+ public String toString() {
+ return "[E]" + super.toString() + " (at: "
+ + this.eventDate.format(DateTimeFormatter.ofPattern("MMM dd yyyy")) + ")";
+ }
+
+}
diff --git a/src/main/java/checklst/task/Task.java b/src/main/java/checklst/task/Task.java
new file mode 100644
index 0000000000..25e502967c
--- /dev/null
+++ b/src/main/java/checklst/task/Task.java
@@ -0,0 +1,40 @@
+package checklst.task;
+
+/**
+ * The Task class is an abstract skeleton that all Tasks (Todo, Event, Deadline) inherit from.
+ */
+public abstract class Task {
+
+ protected final String name;
+ protected final boolean isCompleted;
+
+ protected Task(String name) {
+ this.name = name;
+ this.isCompleted = false;
+ }
+
+ protected Task(String name, boolean isCompleted) {
+ this.name = name;
+ this.isCompleted = isCompleted;
+ }
+
+ /**
+ * Returns a String representation of the Task for exporting.
+ * Format: "Type | Completed | Name | Optional: Date"
+ * @return String representation of Task.
+ */
+ public abstract String export();
+
+ /**
+ * Returns a new Task object which has been completed.
+ * @return New completed Task.
+ */
+ public abstract Task complete();
+
+ @Override
+ public String toString() {
+ String isCompleted = this.isCompleted ? "[X]" : "[ ]";
+ return isCompleted + " " + this.name;
+ }
+
+}
diff --git a/src/main/java/checklst/task/TaskList.java b/src/main/java/checklst/task/TaskList.java
new file mode 100644
index 0000000000..30813a041a
--- /dev/null
+++ b/src/main/java/checklst/task/TaskList.java
@@ -0,0 +1,144 @@
+package checklst.task;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import checklst.exception.ChecklstException;
+
+/**
+ * The TaskList class wraps a list of Tasks and has various methods to process them.
+ */
+public class TaskList {
+
+ private final List taskList;
+
+ /**
+ * Creates a new TaskList object.
+ */
+ public TaskList() {
+ this.taskList = new ArrayList<>();
+ }
+
+ private TaskList(List taskList) {
+ this.taskList = taskList;
+ }
+
+ /**
+ * Adds a Task to the TaskList.
+ * @param task The Task to be added.
+ * @return A String indicating the number of items in the TaskList.
+ * @throws CheckLstException Exception when duplicate unfinished Task.
+ */
+ public String add(Task task) throws ChecklstException {
+ List listNames = this.taskList.stream()
+ .filter(x -> !x.isCompleted)
+ .filter(x -> x.getClass().equals(task.getClass()))
+ .map(x -> x.name)
+ .collect(Collectors.toList());
+
+ if (listNames.contains(task.name)) {
+ throw new ChecklstException("You have an uncompleted Task of a similar name and type already!");
+ }
+
+ this.taskList.add(task);
+
+ return String.format("Added: %s\nYou now have %d task(s) in the list!", task, this.taskList.size());
+ }
+
+ /**
+ * Completes a Task in the TaskList.
+ * @param index The index (1-based) of the Task to be completed.
+ * @return The completed Task.
+ * @throws ChecklstException Exception thrown if index is out of bounds.
+ */
+ public Task completeTask(int index) throws ChecklstException {
+ index--;
+
+ if (index < 0 || index >= this.taskList.size()) {
+ throw new ChecklstException("The task index you have indicated does not exist!");
+ }
+
+ Task newTask = taskList.get(index).complete();
+ this.taskList.set(index, newTask);
+
+ return newTask;
+ }
+
+ /**
+ * Deletes a Task from the TaskList based on index.
+ * @param index The index (1-based) of the Task to be deleted.
+ * @return The deleted Task.
+ * @throws ChecklstException Exception thrown if index is out of bounds.
+ */
+ public Task deleteTask(int index) throws ChecklstException {
+ index--;
+
+ if (index < 0 || index >= this.taskList.size()) {
+ throw new ChecklstException("The task index you have indicated does not exist!");
+ }
+
+ Task newTask = taskList.get(index);
+ this.taskList.remove(index);
+
+ return newTask;
+ }
+
+ /**
+ * Returns a TaskList with the filtered tasks.
+ * @param input String to filter by.
+ * @return Filtered TaskList
+ * @throws ChecklstException Exception when no items are found.
+ */
+ public TaskList findTask(String input) throws ChecklstException {
+ List filteredList = this.taskList.stream()
+ .filter(x -> x.name.contains(input))
+ .collect(Collectors.toList());
+
+ if (filteredList.size() == 0) {
+ throw new ChecklstException("No results found!!");
+ }
+
+ return new TaskList(filteredList);
+ }
+
+ /**
+ * Sorts the TaskList by completed and Task Type
+ * @return String of new Sorted List
+ */
+ public String sort() {
+ Map, Integer> sortMap =
+ Map.of(Todo.class, 0, Deadline.class, 1, Event.class, 2);
+
+ this.taskList.sort((x, y) -> {
+ if (x.isCompleted && y.isCompleted) {
+ return sortMap.get(x.getClass()).compareTo(sortMap.get(y.getClass()));
+ }
+
+ return x.isCompleted ? 1 : -1;
+ });
+
+ return "Your list is now sorted!\nYour new list is:\n" + this;
+ }
+
+ @Override
+ public String toString() {
+ if (this.taskList.size() == 0) {
+ return "Task list is currently empty!";
+ }
+
+ String taskListOutput = "These are your current task";
+ taskListOutput += this.taskList.size() == 1 ? ":" : "s:";
+
+ for (int i = 0; i < this.taskList.size(); i++) {
+ taskListOutput += "\n" + String.valueOf(i + 1) + ". " + this.taskList.get(i);
+ }
+ return taskListOutput;
+ }
+
+ public List getTaskList() {
+ return this.taskList;
+ }
+
+}
diff --git a/src/main/java/checklst/task/Todo.java b/src/main/java/checklst/task/Todo.java
new file mode 100644
index 0000000000..11100343a4
--- /dev/null
+++ b/src/main/java/checklst/task/Todo.java
@@ -0,0 +1,70 @@
+package checklst.task;
+
+import checklst.exception.ChecklstException;
+
+/**
+ * The Deadline class represents a basic Task.
+ */
+public class Todo extends Task {
+
+ protected Todo(String name) {
+ super(name);
+ }
+
+ protected Todo(String name, boolean completed) {
+ super(name, completed);
+ }
+
+ /**
+ * Creates a Todo Object.
+ * @param name - Name of Todo.
+ * @return - Todo Object.
+ */
+ public static Todo makeTodo(String name) throws ChecklstException {
+ if (name.equals("")) {
+ throw new ChecklstException("Todo needs a name!");
+ } else if (name.contains(";")) {
+ throw new ChecklstException("Sorry, Todo name cannot contain a \";\"!");
+ }
+ return new Todo(name);
+ }
+
+ /**
+ * Parses a saved Todo String.
+ * @param input Todo String.
+ * @return Todo Object.
+ */
+ public static Todo parseTodo(String input) {
+ String[] splitInput = input.split(" ; ");
+ String name = splitInput[2];
+ boolean completed = splitInput[1].equals("X") ? true : false;
+
+ return new Todo(name, completed);
+ }
+
+ @Override
+ public String export() {
+ String output = "T ; ";
+
+ if (this.isCompleted) {
+ output += "X ; ";
+ } else {
+ output += "O ; ";
+ }
+
+ output += this.name;
+
+ return output;
+ }
+
+ @Override
+ public Task complete() {
+ return new Todo(this.name, true);
+ }
+
+ @Override
+ public String toString() {
+ return "[T]" + super.toString();
+ }
+
+}
diff --git a/src/main/java/checklst/ui/Ui.java b/src/main/java/checklst/ui/Ui.java
new file mode 100644
index 0000000000..8c30ac2a23
--- /dev/null
+++ b/src/main/java/checklst/ui/Ui.java
@@ -0,0 +1,19 @@
+package checklst.ui;
+
+/**
+ * The Ui class handles direct I/O from the user.
+ */
+public class Ui {
+
+ private static final String WELCOME_MESSAGE = "Hello I'm Checklst! What can I do for you?";
+
+ /**
+ * Prints Welcome output.
+ * @return Welcome output.
+ */
+ public String sendWelcome() {
+ return WELCOME_MESSAGE;
+ }
+
+
+}
diff --git a/src/main/resources/images/ChecklstIcon.png b/src/main/resources/images/ChecklstIcon.png
new file mode 100644
index 0000000000..aa34f0df60
Binary files /dev/null and b/src/main/resources/images/ChecklstIcon.png differ
diff --git a/src/main/resources/images/UserIcon.png b/src/main/resources/images/UserIcon.png
new file mode 100644
index 0000000000..9b42c9d1ec
Binary files /dev/null and b/src/main/resources/images/UserIcon.png differ
diff --git a/src/test/java/checklst/task/DeadlineTest.java b/src/test/java/checklst/task/DeadlineTest.java
new file mode 100644
index 0000000000..eadeb8eaf4
--- /dev/null
+++ b/src/test/java/checklst/task/DeadlineTest.java
@@ -0,0 +1,21 @@
+package checklst.task;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+import checklst.exception.ChecklstException;
+
+public class DeadlineTest {
+
+ @Test
+ public void createDeadlineTest() {
+ assertThrows(ChecklstException.class, () -> Deadline.makeDeadline(""));
+ assertThrows(ChecklstException.class, () -> Deadline.makeDeadline("test "));
+ assertThrows(ChecklstException.class, () -> Deadline.makeDeadline("test /by"));
+ assertThrows(ChecklstException.class, () -> Deadline.makeDeadline("test /by "));
+ assertThrows(ChecklstException.class, () -> Deadline.makeDeadline("test /by 23rd Feb"));
+ assertThrows(ChecklstException.class, () -> Deadline.makeDeadline("test/by2020-11-20"));
+ }
+
+}
diff --git a/src/test/java/checklst/task/EventTest.java b/src/test/java/checklst/task/EventTest.java
new file mode 100644
index 0000000000..3f7fa8f91e
--- /dev/null
+++ b/src/test/java/checklst/task/EventTest.java
@@ -0,0 +1,21 @@
+package checklst.task;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+import checklst.exception.ChecklstException;
+
+public class EventTest {
+
+ @Test
+ public void createEventTest() {
+ assertThrows(ChecklstException.class, () -> Event.makeEvent(""));
+ assertThrows(ChecklstException.class, () -> Event.makeEvent("test"));
+ assertThrows(ChecklstException.class, () -> Event.makeEvent("test /at"));
+ assertThrows(ChecklstException.class, () -> Event.makeEvent("test /at "));
+ assertThrows(ChecklstException.class, () -> Event.makeEvent("test /at 23rd Feb"));
+ assertThrows(ChecklstException.class, () -> Event.makeEvent("test/at2020-11-20"));
+ }
+
+}
diff --git a/src/test/java/checklst/task/TaskListTest.java b/src/test/java/checklst/task/TaskListTest.java
new file mode 100644
index 0000000000..63d7810eb5
--- /dev/null
+++ b/src/test/java/checklst/task/TaskListTest.java
@@ -0,0 +1,45 @@
+package checklst.task;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+import checklst.exception.ChecklstException;
+
+public class TaskListTest {
+
+ private final TaskList taskList = new TaskList();
+
+ @Test
+ public void addTaskTest() throws ChecklstException {
+ Task task = new Todo("Hello");
+ this.taskList.add(task);
+ assertEquals(task, this.taskList.getTaskList().get(0));
+ }
+
+ @Test
+ public void completeTaskTest() throws ChecklstException {
+ assertThrows(ChecklstException.class, () -> this.taskList.completeTask(-1));
+ assertThrows(ChecklstException.class, () -> this.taskList.completeTask(0));
+ assertThrows(ChecklstException.class, () -> this.taskList.completeTask(1));
+ }
+
+ @Test
+ public void deleteTaskTest() throws ChecklstException {
+ assertThrows(ChecklstException.class, () -> this.taskList.deleteTask(-1));
+ assertThrows(ChecklstException.class, () -> this.taskList.deleteTask(0));
+ assertThrows(ChecklstException.class, () -> this.taskList.deleteTask(1));
+ }
+
+ @Test
+ public void findTaskTest() throws ChecklstException {
+ Task task = new Todo("hello");
+ this.taskList.add(task);
+
+ assertTrue(this.taskList.findTask("hello").getTaskList().size() > 0);
+ assertThrows(ChecklstException.class, () -> this.taskList.findTask("abc"));
+ }
+
+}
diff --git a/src/test/java/checklst/task/TodoTest.java b/src/test/java/checklst/task/TodoTest.java
new file mode 100644
index 0000000000..b4709d11b1
--- /dev/null
+++ b/src/test/java/checklst/task/TodoTest.java
@@ -0,0 +1,16 @@
+package checklst.task;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+import checklst.exception.ChecklstException;
+
+public class TodoTest {
+
+ @Test
+ public void createTodoTest() {
+ assertThrows(ChecklstException.class, () -> Todo.makeTodo(""));
+ }
+
+}
diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT
index 657e74f6e7..d5ef1aa9db 100644
--- a/text-ui-test/EXPECTED.TXT
+++ b/text-ui-test/EXPECTED.TXT
@@ -1,7 +1,61 @@
-Hello from
- ____ _
-| _ \ _ _| | _____
-| | | | | | | |/ / _ \
-| |_| | |_| | < __/
-|____/ \__,_|_|\_\___|
-
+ ----------------------------------------
+ No history found... Initializing from blank state!
+ ----------------------------------------
+ ----------------------------------------
+ Hello I'm Checklst! What can I do for you?
+ ----------------------------------------
+ ----------------------------------------
+ Added: [T][] Todo1
+ You now have 1 task(s) in the list!
+ ----------------------------------------
+ ----------------------------------------
+ Added: [E][] Event1 (at: May 12 2020)
+ You now have 2 task(s) in the list!
+ ----------------------------------------
+ ----------------------------------------
+ Added: [D][] Deadline1 (by: Jul 24 2020)
+ You now have 3 task(s) in the list!
+ ----------------------------------------
+ ----------------------------------------
+ Added: [T][] Todo2
+ You now have 4 task(s) in the list!
+ ----------------------------------------
+ ----------------------------------------
+ 1. [T][] Todo1
+ 2. [E][] Event1 (at: May 12 2020)
+ 3. [D][] Deadline1 (by: Jul 24 2020)
+ 4. [T][] Todo2
+ ----------------------------------------
+ ----------------------------------------
+ Nice! I've marked this task as done!
+ [E][X] Event1 (at: May 12 2020)
+ ----------------------------------------
+ ----------------------------------------
+ Alright! I've deleted this task!
+ [E][X] Event1 (at: May 12 2020)
+ ----------------------------------------
+ ----------------------------------------
+ Nice! I've marked this task as done!
+ [T][X] Todo2
+ ----------------------------------------
+ ----------------------------------------
+ Nice! I've marked this task as done!
+ [T][X] Todo1
+ ----------------------------------------
+ ----------------------------------------
+ 1. [T][X] Todo1
+ 2. [D][] Deadline1 (by: Jul 24 2020)
+ 3. [T][X] Todo2
+ ----------------------------------------
+ ----------------------------------------
+ Inproper Event format used! Please use { name } /at { event }
+ ----------------------------------------
+ ----------------------------------------
+ Inproper Deadline format used! Please use { name } /by { deadline }
+ ----------------------------------------
+ ----------------------------------------
+ Sorry I didn't understand that command!!
+ ----------------------------------------
+ ----------------------------------------
+ Bye! Hope to see you again!
+ ----------------------------------------
diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt
index e69de29bb2..491f52e499 100644
--- a/text-ui-test/input.txt
+++ b/text-ui-test/input.txt
@@ -0,0 +1,14 @@
+todo Todo1
+event Event1 /at 2020-05-12
+deadline Deadline1 /by 2020-07-24
+todo Todo2
+list
+done 2
+delete 2
+done 3
+done 1
+list
+event ErrorEvent
+deadline ErrorDeadline
+gibberish
+bye
\ No newline at end of file
diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh
old mode 100644
new mode 100755
index c9ec870033..179c820de1
--- a/text-ui-test/runtest.sh
+++ b/text-ui-test/runtest.sh
@@ -20,7 +20,7 @@ then
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 Checklst < input.txt > ACTUAL.TXT
# convert to UNIX format
cp EXPECTED.TXT EXPECTED-UNIX.TXT