diff --git a/README.md b/README.md
index 0dd8f7fb21..c233814022 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Duke project template
+# 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.
@@ -12,7 +12,7 @@ Prerequisites: JDK 11, update Intellij to the most recent version.
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:
+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
____ _
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000000..a860071c53
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,53 @@
+plugins {
+ id 'java'
+ id 'checkstyle'
+ id 'application'
+ id 'com.github.johnrengelman.shadow' version '5.1.0'
+}
+
+group 'org.example'
+version ''
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+
+ implementation 'org.junit.jupiter:junit-jupiter:5.4.2'
+ implementation 'org.junit.jupiter:junit-jupiter:5.4.2'
+ testCompile group: 'junit', name: 'junit', version: '4.12'
+
+
+ //JavaFx
+ 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()
+}
+
+application {
+ mainClassName = "duke.Duke"
+}
+
+shadowJar {
+ archiveBaseName = "Duke"
+ archiveClassifier = null
+}
+
+checkstyle {
+ toolVersion = '8.29'
+}
\ No newline at end of file
diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
new file mode 100644
index 0000000000..4c001417ae
--- /dev/null
+++ b/config/checkstyle/checkstyle.xml
@@ -0,0 +1,403 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml
new file mode 100644
index 0000000000..39efb6e4ac
--- /dev/null
+++ b/config/checkstyle/suppressions.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/data/Duke.txt b/data/Duke.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/data/Statistics.txt b/data/Statistics.txt
new file mode 100644
index 0000000000..2c3e21c9ca
--- /dev/null
+++ b/data/Statistics.txt
@@ -0,0 +1,7 @@
+Task history:
+1
+[T][ ] project
+2
+[T][ ] project
+1
+[T][ ] project
diff --git a/docs/README.md b/docs/README.md
index fd44069597..5a19b7525a 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,20 +1,189 @@
-# User Guide
+# Duke User Guide
+
+
+
+
## Features
-### Feature 1
-Description of feature.
+Duke is a task tracking applications that helps you to keep track of task/events with or without deadline.
## Usage
-### `Keyword` - Describe action
+### Build and Run
+
+To use Duke, you have to compile and run Duke.java at `src/main/java/duke`.
+
+An alternatives will be using gradle to build and run the application.
+
+A packaged jar file has been attached in the latest release. Feel free to download it.
+To run the jar file, simply type in the command `java -jar Duke.jar`
+
+
+### 1. `todo` - Add a todo task
+
+Add a todo task with your given task content to Duke.
+
+Format: `todo CONTENT`
+
+Example:
+```$xslt
+todo a 2103 individual project
+```
+
+Expected Outcome:
+```$xslt
+Added liao: [T][ ] 1. a 2103 individual project
+You have 1 task in the list!
+```
+### 2. `deadline` - Add a deadline task
+
+Add a deadline task with your given task content and deadline(YYYY-MM-DD) to Duke.
+
+Format: `deadline CONTENT/DEADLINE`
+
+Example:
+```$xslt
+deadline team meeting/2021-01-22
+```
+
+Expected Outcome:
+```$xslt
+Added liao: [D][ ] 2. team meeting (Jan 22 2021)
+You have 2 tasks in the list!
+```
+
+### 3. `event` - Add an event
+
+Add an event with the event content and deadline(YYYY-MM-DD) to Duke.
+
+Format: `event CONTENT/DEADLINE`
+
+Example:
+```$xslt
+event Chinese New Year/2021-02-11
+```
+
+Expected Outcome:
+```$xslt
+Added liao: [E][ ] 3. Chinese New Year (Feb 11 2021)
+You have 3 tasks in the list!
+```
+
+### 4. `list` - List all the current tasks
+
+List all the tasks that you have added to Duke.
+
+Format: `list`
+
+Example:
+```$xslt
+list
+```
+
+Expected Outcome:
+```$xslt
+[T][ ] 1. a 2103 individual project
+[D][ ] 2. team meeting (Jan 22 2021)
+[E][ ] 3. Chinese New Year (Feb 11 2021)
+```
+
+### 5. `done` - Mark a current task as done.
+
+Mark a current task with the given index as done in Duke.
+
+Format: `done INDEX`
+
+Example:
+```$xslt
+done 1
+
+list
+```
+
+Expected Outcome:
+```$xslt
+Wah~ You done the task: [T][X] 1. a 2103 indivual project
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+[T][X] 1. a 2103 individual project
+[D][ ] 2. team meeting (Jan 22 2021)
+[E][ ] 3. Chinese New Year (Feb 11 2021)
+```
+
+### 6. `delete` - Delete a current task from Duke.
+
+Delete a task with the given index in Duke.
+
+Format: `delete INDEX`
+
+Example:
+```$xslt
+delete 1
+kust
+```
+
+Expected Outcome:
+```$xslt
+Awww~ You've deleted the task: [T][X] 1. a 2103 indiviual project
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+[D][ ] 1. team meeting (Jan 22 2021)
+[E][ ] 2. Chinese New Year (Feb 11 2021)
+```
+
+### 7. `find` - Find all relevant tasks.
+
+Find all relevent tasks with your given keyword in Duke.
+
+Format: `find KEYWORD`
+
+Example:
+```$xslt
+find meeting
+```
+
+Expected Outcome:
+```$xslt
+Here are the matches for your search:
+[D][ ] 1. team meeting (Jan 22 2021)
+```
+
+### 8. `clear` - Clear statistics and history.
+
+Delete user history file.
+
+Format: `clear`
+
+Example:
+```$xslt
+clear
+```
+
+Expected Outcome:
+```$xslt
+Successfully clear statistics
+(Statistics.txt removed)
+```
+
+### 9. `bye` - exit Duke
+
+Exit Duke and save your task history.
+
+Format: `bye`
+
+Example:
+```$xslt
+bye
+```
+
+Expected Outcome: Application Exits
+
+
+## Author
+Huang Zhenxin
+
+
-Describe action and its outcome.
-Example of usage:
-`keyword (optional arguments)`
-Expected outcome:
-`outcome`
diff --git a/docs/Ui.png b/docs/Ui.png
new file mode 100644
index 0000000000..41b9d1441b
Binary files /dev/null and b/docs/Ui.png differ
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000..62d4c05355
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..a4b4429748
--- /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.3-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000000..fbd7c51583
--- /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..5093609d51
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,104 @@
+@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 init
+
+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 init
+
+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
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+: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 %CMD_LINE_ARGS%
+
+: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..972cd8b6b1
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = 'ip'
+
diff --git a/src/.idea/misc.xml b/src/.idea/misc.xml
new file mode 100644
index 0000000000..7d862fbd38
--- /dev/null
+++ b/src/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/.idea/modules.xml b/src/.idea/modules.xml
new file mode 100644
index 0000000000..f669a0e594
--- /dev/null
+++ b/src/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/.idea/vcs.xml b/src/.idea/vcs.xml
new file mode 100644
index 0000000000..6c0b863585
--- /dev/null
+++ b/src/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/.idea/workspace.xml b/src/.idea/workspace.xml
new file mode 100644
index 0000000000..aa3c8d9c61
--- /dev/null
+++ b/src/.idea/workspace.xml
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1611771282430
+
+
+ 1611771282430
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/.idea/misc.xml b/src/main/.idea/misc.xml
new file mode 100644
index 0000000000..9f24f5833d
--- /dev/null
+++ b/src/main/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/main/.idea/modules.xml b/src/main/.idea/modules.xml
new file mode 100644
index 0000000000..aaf7df43bd
--- /dev/null
+++ b/src/main/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/.idea/vcs.xml b/src/main/.idea/vcs.xml
new file mode 100644
index 0000000000..b2bdec2d71
--- /dev/null
+++ b/src/main/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/.idea/workspace.xml b/src/main/.idea/workspace.xml
new file mode 100644
index 0000000000..600c78ca65
--- /dev/null
+++ b/src/main/.idea/workspace.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1611767634287
+
+
+ 1611767634287
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/.idea/misc.xml b/src/main/java/.idea/misc.xml
new file mode 100644
index 0000000000..dda71418a5
--- /dev/null
+++ b/src/main/java/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/.idea/workspace.xml b/src/main/java/.idea/workspace.xml
new file mode 100644
index 0000000000..9b8aa8fdd9
--- /dev/null
+++ b/src/main/java/.idea/workspace.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1611772006855
+
+
+ 1611772006855
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
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/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..6e864153e8
--- /dev/null
+++ b/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: duke.Duke
+
diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java
new file mode 100644
index 0000000000..8e95387ee5
--- /dev/null
+++ b/src/main/java/duke/Duke.java
@@ -0,0 +1,21 @@
+package duke;
+
+
+import duke.utils.Statistics;
+import javafx.application.Application;
+
+/**
+ * Encapsulates the main class of the Object.
+ */
+public class Duke {
+ /**
+ * Executes the programs.
+ *
+ * @param args command line arguments key in by user.
+ */
+ public static void main(String[] args) {
+ Statistics.initialize();
+ Application.launch(Main.class, args);
+ }
+
+}
diff --git a/src/main/java/duke/Main.java b/src/main/java/duke/Main.java
new file mode 100644
index 0000000000..86a7240018
--- /dev/null
+++ b/src/main/java/duke/Main.java
@@ -0,0 +1,30 @@
+package duke;
+
+import java.io.IOException;
+
+import javafx.application.Application;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Scene;
+import javafx.scene.layout.AnchorPane;
+import javafx.stage.Stage;
+
+/**
+ * A GUI for Duke using FXML.
+ */
+public class Main extends Application {
+
+
+
+ @Override
+ public void start(Stage stage) {
+ try {
+ FXMLLoader fxmlLoader = new FXMLLoader(Main.class.getResource("/view/MainMenu.fxml"));
+ AnchorPane ap = fxmlLoader.load();
+ Scene scene = new Scene(ap);
+ stage.setScene(scene);
+ stage.show();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/duke/command/AddCommand.java b/src/main/java/duke/command/AddCommand.java
new file mode 100644
index 0000000000..e4cf845e89
--- /dev/null
+++ b/src/main/java/duke/command/AddCommand.java
@@ -0,0 +1,76 @@
+package duke.command;
+
+import duke.task.Deadline;
+import duke.task.Event;
+import duke.task.TaskList;
+import duke.task.Todo;
+import duke.ui.Ui;
+import duke.utils.Statistics;
+
+
+/**
+ * Sub-class of Command that represents and execute the todo, deadline and event instructions of user.
+ */
+public class AddCommand extends Command {
+
+ /**
+ * Creates a AddCommand object for execution.
+ *
+ * @param instruction user instruction.
+ * @param task content of the user task.
+ * @param date date of the user task to be done.
+ */
+ public AddCommand(String instruction, String task, String date) {
+ super(instruction, task, date, false, command -> {
+ if (instruction.equals("todo")) {
+ return handleToDo(task);
+ } else if (instruction.equals("deadline")) {
+ return handleDeadline(task, date);
+ } else {
+ return handleEvent(task, date);
+ }
+ });
+ }
+
+ /**
+ * This method handles todo instruction and creates a Todo task.
+ *
+ * @param task content of the user task.
+ */
+ private static String handleToDo(String task) {
+ Todo todo = new Todo(task);
+
+ // Update the task list and statistics with the new task.
+ TaskList.addTask(todo);
+ Statistics.updateStatistics(todo);
+ return Ui.createAddResponse(todo);
+ }
+
+ /**
+ * This method handles deadline instruction and creates a Deadline task.
+ *
+ * @param task content of the user task.
+ */
+ private static String handleDeadline(String task, String date) {
+ Deadline deadlines = new Deadline(task, date);
+
+ // Update the task list and statistics with the new task.
+ TaskList.addTask(deadlines);
+ Statistics.updateStatistics(deadlines);
+ return Ui.createAddResponse(deadlines);
+ }
+
+ /**
+ * This method handles event instruction and creates a Event task.
+ *
+ * @param task content of the user task.
+ */
+ private static String handleEvent(String task, String date) {
+ Event event = new Event(task, date);
+
+ // Update the task list and statistics with the new task.
+ TaskList.addTask(event);
+ Statistics.updateStatistics(event);
+ return Ui.createAddResponse(event);
+ }
+}
diff --git a/src/main/java/duke/command/ClearCommand.java b/src/main/java/duke/command/ClearCommand.java
new file mode 100644
index 0000000000..a6b4f32c72
--- /dev/null
+++ b/src/main/java/duke/command/ClearCommand.java
@@ -0,0 +1,23 @@
+package duke.command;
+
+import duke.utils.Statistics;
+
+/**
+ * ClearCommand that when executes clear the Past history of tasks.
+ */
+public class ClearCommand extends Command{
+ private static final String NO_TASK = "";
+ private static final String NO_DATE = "";
+
+ /**
+ * Creates a ClearCommand object that return a response when executed.
+ */
+ public ClearCommand() {
+ super("clear", NO_TASK, NO_DATE, false, command -> handleClearCommand());
+ }
+
+ private static String handleClearCommand() {
+ Statistics.clear();
+ return "Successfully Clear Statistics";
+ }
+}
diff --git a/src/main/java/duke/command/Command.java b/src/main/java/duke/command/Command.java
new file mode 100644
index 0000000000..cc1017d4ea
--- /dev/null
+++ b/src/main/java/duke/command/Command.java
@@ -0,0 +1,49 @@
+package duke.command;
+
+import java.util.function.Function;
+
+/**
+ * This class encapsulates the user instruction,task and date and execute the instruction.
+ */
+public abstract class Command {
+ private final String instruction;
+ private final String task;
+ private final String date;
+ private boolean isExit;
+ private final Function func;
+
+ /**
+ * Creates a command with user instruction, task, date and a function to execute the instruction.
+ *
+ * @param instruction user instruction.
+ * @param task content of user task.
+ * @param date date of the task.
+ * @param func the function takes a command to execute and returns a response String.
+ */
+ public Command(String instruction, String task, String date, boolean isExit, Function func) {
+ this.instruction = instruction;
+ this.task = task;
+ this.date = date;
+ this.isExit = isExit;
+ this.func = func;
+ }
+
+ /**
+ * Executes a command and returns response String.
+ *
+ * @return a response String.
+ */
+ public String execute() {
+ return func.apply(this);
+ }
+
+ public boolean getIsExitStatus() {
+ return isExit;
+ }
+ public String getTask() {
+ return task;
+ }
+ public String getDate() {
+ return date;
+ }
+}
diff --git a/src/main/java/duke/command/DeleteCommand.java b/src/main/java/duke/command/DeleteCommand.java
new file mode 100644
index 0000000000..cf1fb6291e
--- /dev/null
+++ b/src/main/java/duke/command/DeleteCommand.java
@@ -0,0 +1,37 @@
+package duke.command;
+
+import duke.task.TaskList;
+import duke.ui.ErrorBox;
+import duke.ui.Ui;
+
+/**
+ * Sub-class of command that only represents and executes a delete instruction of a user.
+ */
+public class DeleteCommand extends Command {
+ private static final String NO_DATE = "";
+
+ /**
+ * Creates a DeleteCommand object with given task and date.
+ * @param task index of the task to be deleted.
+ */
+ public DeleteCommand(String task) {
+ super("delete", task, NO_DATE, false,
+ command -> handleDelete(task));
+ }
+
+ /**
+ * This method handles delete instruction.
+ *
+ * @param task user task in String.
+ */
+ private static String handleDelete(String task) {
+ String response = "";
+ try {
+ int num = Integer.parseInt(task);
+ response = TaskList.deleteTask(num);
+ } catch (NumberFormatException e) {
+ ErrorBox.display(Ui.KEY_IN_NUMBER);
+ }
+ return response;
+ }
+}
diff --git a/src/main/java/duke/command/DoneCommand.java b/src/main/java/duke/command/DoneCommand.java
new file mode 100644
index 0000000000..1a216b5719
--- /dev/null
+++ b/src/main/java/duke/command/DoneCommand.java
@@ -0,0 +1,39 @@
+package duke.command;
+
+import duke.task.TaskList;
+import duke.ui.ErrorBox;
+import duke.ui.Ui;
+
+/**
+ * Sub-class of Command that represents and executes the done instruction of user.
+ */
+public class DoneCommand extends Command {
+ private static final String NO_DATE = "";
+
+ /**
+ * Creates a DoneCommand object with the given task.
+ * @param task content of user task.
+ */
+ public DoneCommand(String task) {
+ super("done", task, NO_DATE, false, command -> handleDone(task));
+ }
+
+ /**
+ * This method handles done instruction by marking the task as done.
+ *
+ * @param task name of the user task.
+ */
+ private static String handleDone(String task) {
+ String response = "";
+ try {
+ int num = Integer.parseInt(task);
+ response = TaskList.markDone(num);
+ } catch (NumberFormatException e) {
+ ErrorBox.display(Ui.KEY_IN_NUMBER);
+ }
+
+ return response;
+ }
+
+
+}
diff --git a/src/main/java/duke/command/ErrorCommand.java b/src/main/java/duke/command/ErrorCommand.java
new file mode 100644
index 0000000000..2fddb21c21
--- /dev/null
+++ b/src/main/java/duke/command/ErrorCommand.java
@@ -0,0 +1,16 @@
+package duke.command;
+
+import duke.ui.Ui;
+
+/**
+ * Sub-class of Command to represents any error in the instruction of user.
+ */
+public class ErrorCommand extends Command {
+ /**
+ * Creates an ErrorCommand object that return error message when executed.
+ *
+ */
+ public ErrorCommand() {
+ super("", "", "", false, command -> Ui.COMMAND_ERROR);
+ }
+}
diff --git a/src/main/java/duke/command/ExitCommand.java b/src/main/java/duke/command/ExitCommand.java
new file mode 100644
index 0000000000..01224ae3d4
--- /dev/null
+++ b/src/main/java/duke/command/ExitCommand.java
@@ -0,0 +1,23 @@
+package duke.command;
+
+import duke.ui.Ui;
+
+/**
+ * Sub-class of command that represents and executes the "bye" instruction of user.
+ */
+public class ExitCommand extends Command {
+ private static final String NO_TASK = "";
+ private static final String NO_DATE = "";
+ /**
+ * Creates an ExitCommand object that exits the program when executed.
+ */
+ public ExitCommand() {
+ super("bye", NO_TASK, NO_DATE, true, command -> handleBye());
+ }
+
+
+ private static String handleBye() {
+ return Ui.FAREWELL;
+ }
+
+}
diff --git a/src/main/java/duke/command/FindCommand.java b/src/main/java/duke/command/FindCommand.java
new file mode 100644
index 0000000000..2ded990ebf
--- /dev/null
+++ b/src/main/java/duke/command/FindCommand.java
@@ -0,0 +1,24 @@
+package duke.command;
+
+import duke.task.TaskList;
+
+/**
+ * Sub-class of Command to represents and executes the find instruction.
+ */
+public class FindCommand extends Command {
+ private static final String NO_DATE = "";
+
+ /**
+ * Constructs a find command object that finds all relevant tasks with the given task.
+ * @param task task user want to search for.
+ */
+ public FindCommand(String task) {
+ super("find", task, NO_DATE, false, command -> {
+ String searchResult = TaskList.findTasks(task);
+ System.out.println(searchResult);
+ return searchResult;
+ });
+ }
+
+
+}
diff --git a/src/main/java/duke/command/ListCommand.java b/src/main/java/duke/command/ListCommand.java
new file mode 100644
index 0000000000..2fdf693c0c
--- /dev/null
+++ b/src/main/java/duke/command/ListCommand.java
@@ -0,0 +1,16 @@
+package duke.command;
+
+import duke.task.TaskList;
+
+/**
+ * Sub-class of Command that represents and executes the "list" instruction of user.
+ */
+public class ListCommand extends Command {
+
+ /**
+ * Creates a ListCommand object that lists tasks upon execution.
+ */
+ public ListCommand() {
+ super("", "", "", false, command -> TaskList.listTasks());
+ }
+}
diff --git a/src/main/java/duke/exceptions/DukeException.java b/src/main/java/duke/exceptions/DukeException.java
new file mode 100644
index 0000000000..976b5eb50c
--- /dev/null
+++ b/src/main/java/duke/exceptions/DukeException.java
@@ -0,0 +1,11 @@
+package duke.exceptions;
+
+/**
+ * A class that stores all the possible display of errorsException in Duke.
+ */
+public class DukeException extends Exception {
+ public DukeException(String errorMessage) {
+ super(errorMessage);
+ }
+
+}
diff --git a/src/main/java/duke/task/Deadline.java b/src/main/java/duke/task/Deadline.java
new file mode 100644
index 0000000000..9ba966f312
--- /dev/null
+++ b/src/main/java/duke/task/Deadline.java
@@ -0,0 +1,33 @@
+package duke.task;
+
+/**
+ * sub-class of Task to represents a task with deadline.
+ */
+public class Deadline extends Task {
+
+
+ /**
+ * creates a deadline task object with given task name and given dates/comments.
+ *
+ * @param taskContent String representation of the content of the task.
+ * @param date String representation of the comments/dates.
+ */
+ public Deadline(String taskContent, String date) {
+ super(taskContent, date);
+ }
+
+ public Deadline(String taskContent, String date, String done) {
+ super(taskContent, date, done);
+ }
+
+ @Override
+ public int getType() {
+ return 2;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("[D][%s] %d. %s ( %s )", super.getDoneStatus(), super.getIndex(),
+ super.getTaskName(), super.getDate());
+ }
+}
diff --git a/src/main/java/duke/task/Event.java b/src/main/java/duke/task/Event.java
new file mode 100644
index 0000000000..7ffa44630a
--- /dev/null
+++ b/src/main/java/duke/task/Event.java
@@ -0,0 +1,33 @@
+package duke.task;
+
+/**
+ * A subclass of Task that represent an event key in by user.
+ */
+public class Event extends Task {
+
+
+ /**
+ * Creates a event Task with given task name and given comments/dates.
+ *
+ * @param taskContent content of the user task in String.
+ * @param date dates or comments of the user regarding the task.
+ */
+ public Event(String taskContent, String date) {
+ super(taskContent, date);
+ }
+
+ public Event(String taskContent, String date, String done) {
+ super(taskContent, date, done);
+ }
+
+ @Override
+ public int getType() {
+ return 3;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("[E][%s] %d. %s ( %s )", super.getDoneStatus(), super.getIndex(),
+ super.getTaskName(), super.getDate());
+ }
+}
diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java
new file mode 100644
index 0000000000..362e661f40
--- /dev/null
+++ b/src/main/java/duke/task/Task.java
@@ -0,0 +1,101 @@
+package duke.task;
+
+
+/**
+ * A class that stores the task that user key in.
+ */
+public class Task {
+ private final String taskName;
+ private int index;
+ private String isDone;
+ private final String date;
+
+ /**
+ * Constructs a task object with taskName attached and its index label in the taskList.
+ *
+ * @param taskName name of the task.
+ */
+ Task(String taskName) {
+ this.taskName = taskName;
+ this.index = TaskList.getTasksSize() + 1;
+ this.isDone = " ";
+ this.date = "";
+ }
+
+ Task(String taskName, String isDone, boolean check) {
+ this.taskName = taskName;
+ this.index = TaskList.getTasksSize() + 1;
+ this.isDone = isDone;
+ this.date = "";
+ }
+
+ Task(String taskName, String date) {
+ this.taskName = taskName;
+ this.index = TaskList.getTasksSize() + 1;
+ this.isDone = " ";
+ this.date = date;
+ }
+
+ Task(String taskName, String date, String done) {
+ this.taskName = taskName;
+ this.index = TaskList.getTasksSize() + 1;
+ this.isDone = done;
+ this.date = date;
+ }
+
+
+ public void changeIndex(int i) {
+ this.index = i;
+ }
+
+ /**
+ * Marks the task status as done with the notation X.
+ */
+ public void markDone() {
+ this.isDone = "X";
+ }
+
+
+ /**
+ * Gets the name of the task.
+ *
+ * @return a String representation of the task name.
+ */
+ public String getTaskName() {
+ return taskName;
+ }
+
+
+ /**
+ * Gets the isDone status of the task.
+ *
+ * @return a String representation of the isDone status (X for done).
+ */
+ public String getDoneStatus() {
+ return isDone;
+ }
+
+ /**
+ * Gets the index label of the task.
+ *
+ * @return the int representation of the index label.
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ public int getType() {
+ return 0;
+ }
+
+ public String getDate() {
+ return date;
+ }
+
+
+
+ @Override
+ public String toString() {
+ return String.format("[%s] %d. %s", isDone, index, taskName);
+ }
+}
diff --git a/src/main/java/duke/task/TaskList.java b/src/main/java/duke/task/TaskList.java
new file mode 100644
index 0000000000..5cd63ba57c
--- /dev/null
+++ b/src/main/java/duke/task/TaskList.java
@@ -0,0 +1,144 @@
+package duke.task;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import duke.ui.ErrorBox;
+import duke.ui.Ui;
+
+/**
+ * This class encapsulate a list of Task.
+ */
+public class TaskList {
+ private static List tasks = new ArrayList<>();
+
+ /**
+ * Add a user task to the list.
+ * @param task user task keyed in.
+ */
+ public static void addTask(Task task) {
+ tasks.add(task);
+ assert tasks.size() >= 1 : "Task is not added successfully";
+ }
+
+
+ /**
+ * This method marks a task in the list as done.
+ *
+ * @param i index labelling of the task in list.
+ */
+ public static String markDone(int i) {
+ String response = "";
+
+ if (tasks.size() == 0) {
+ response = (Ui.EMPTY_LIST);
+ }
+
+ try {
+ Task t = tasks.get(i - 1);
+ tasks.get(i - 1).markDone();
+ assert t.getDoneStatus().equals("X") : "Task is not marked as done successfully";
+ response = Ui.doneTask(t);
+ } catch (IndexOutOfBoundsException e) {
+ ErrorBox.display(Ui.TASK_ERROR);
+ }
+ return response;
+ }
+
+ /**
+ * This method finds all relevant tasks according to the keyword.
+ *
+ * @param keyword keyword that the user want to search.
+ * @return the matched tasks according to the keyword in String.
+ */
+ public static String findTasks(String keyword) {
+ int index = 1;
+ StringBuilder response = new StringBuilder();
+
+ //Finds matching tasks in task list and appends to the response.
+ for (Task task : tasks) {
+ String taskName = task.getTaskName();
+ if (taskName.contains(keyword)) {
+ String prefix = task.toString().substring(0, 6);
+ response.append(prefix + " " + index + ". " + task.getTaskName() + task.getDate() + "\n");
+ index++;
+ }
+ }
+
+ boolean hasMatchTask = response.capacity() > 0;
+ if (!hasMatchTask) {
+ response.append("~~~~~Sorry ah, no match.~~~~~");
+ } else {
+ response.insert(0, "Here are the matches for your search: \n");
+ }
+
+ return response.toString();
+ }
+
+ /**
+ * This method displays all the tasks in the list.
+ */
+ public static String listTasks() {
+ StringBuilder response = new StringBuilder();
+
+ if (tasks.size() == 0) {
+ response.append(Ui.EMPTY_LIST);
+ }
+
+ //Lists all tasks in the task list and appends them to the response.
+ for (Task task : tasks) {
+ if (task == null) {
+ break;
+ }
+ System.out.println(task);
+ response.append(task.toString() + "\n");
+ }
+
+ return response.toString();
+ }
+
+ /**
+ * This method delete a task in the task list with the given index.
+ *
+ * @param i the index labelling of the task.
+ */
+ public static String deleteTask(int i) {
+ String response = "";
+
+ if (tasks.size() == 0) {
+ response = (Ui.EMPTY_LIST);
+ }
+ try {
+ Task t = tasks.get(i - 1);
+ tasks.remove(i - 1);
+ response = Ui.deleteTask(t);
+ for (Task task : tasks) {
+ if (task.getIndex() > i) {
+ task.changeIndex(task.getIndex() - 1);
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ ErrorBox.display(Ui.TASK_ERROR);
+ }
+ return response;
+ }
+
+
+ public static void clearAllTasks() {
+ tasks.clear();
+ }
+
+ public static List getTaskList() {
+ return tasks;
+ }
+
+
+ /**
+ * Obtain the total number of tasks in the list.
+ * @return the number of tasks in the list.
+ */
+ public static int getTasksSize() {
+ return tasks.size();
+ }
+
+}
diff --git a/src/main/java/duke/task/Todo.java b/src/main/java/duke/task/Todo.java
new file mode 100644
index 0000000000..12e007600c
--- /dev/null
+++ b/src/main/java/duke/task/Todo.java
@@ -0,0 +1,39 @@
+package duke.task;
+
+
+/**
+ * A sub-class of Task to represents a toDo task key in by user.
+ */
+public class Todo extends Task {
+
+ /**
+ * Creates a Todo object with given taskName.
+ *
+ * @param taskName name of the task in String.
+ */
+ public Todo(String taskName) {
+ super(taskName);
+
+ }
+
+ /**
+ * Creates a Todo object with given taskName and isDone status.
+ * @param taskName name of the task.
+ * @param done String representation of the done status.
+ */
+ public Todo(String taskName, String done) {
+ super(taskName, done, true);
+
+ }
+
+ @Override
+ public int getType() {
+ return 1;
+ }
+
+
+ @Override
+ public String toString() {
+ return String.format("[T][%s] %d. %s", super.getDoneStatus(), super.getIndex(), super.getTaskName());
+ }
+}
diff --git a/src/main/java/duke/type/CommandType.java b/src/main/java/duke/type/CommandType.java
new file mode 100644
index 0000000000..046536aaa3
--- /dev/null
+++ b/src/main/java/duke/type/CommandType.java
@@ -0,0 +1,45 @@
+package duke.type;
+
+/**
+ * Encapsulates a CommandType enum class that represents the type of command.
+ * The class includes seven types: todo, clear, deadline, event, bye, list, delete, done and find.
+ */
+public enum CommandType {
+ BYE("bye"),
+ CLEAR("clear"),
+ DEADLINE("deadline"),
+ DELETE("delete"),
+ DONE("done"),
+ EVENT("event"),
+ FIND("find"),
+ LIST("list"),
+ TODO("todo");
+
+ private final String type;
+
+
+ /**
+ * Constructs a CommandType object with a String representation of the type.
+ *
+ * @param type String representation of the type.
+ */
+ CommandType(String type) {
+ this.type = type;
+ }
+
+ /**
+ * Gets the CommandType object from a string representation of the type.
+ * Returns null if no such object exists.
+ *
+ * @param type a string representing the type.
+ * @return an CommandType object of the specified type and null if no such object exists.
+ */
+ public static CommandType valueOfType(String type) {
+ for (CommandType t : values()) {
+ if (t.type.equals(type)) {
+ return t;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/duke/ui/DialogBox.java b/src/main/java/duke/ui/DialogBox.java
new file mode 100644
index 0000000000..55bf0151e9
--- /dev/null
+++ b/src/main/java/duke/ui/DialogBox.java
@@ -0,0 +1,81 @@
+package duke.ui;
+
+import java.io.IOException;
+import java.util.Collections;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.fxml.FXML;
+import javafx.fxml.FXMLLoader;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
+import javafx.scene.control.Label;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.HBox;
+
+/**
+ * An example of a custom control using FXML.
+ * This control represents a dialog box consisting of an ImageView to represent the speaker's face and a label
+ * containing text from the speaker.
+ */
+public class DialogBox extends HBox {
+ @FXML
+ private HBox hbox;
+ @FXML
+ private HBox dialogContainer;
+ @FXML
+ private Label dialog;
+ @FXML
+ private ImageView displayPicture;
+
+ private DialogBox(String text, Image img) {
+ try {
+ FXMLLoader fxmlLoader = new FXMLLoader(MainWindow.class.getResource("/view/DialogBox.fxml"));
+ fxmlLoader.setController(this);
+ fxmlLoader.setRoot(this);
+ fxmlLoader.load();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ dialog.setText(text);
+ displayPicture.setImage(img);
+ }
+
+ /**
+ * Flips the dialog box such that the ImageView is on the left and text on the right.
+ */
+ private void flip() {
+ ObservableList tmp = FXCollections.observableArrayList(this.getChildren());
+ Collections.reverse(tmp);
+ getChildren().setAll(tmp);
+ setAlignment(Pos.TOP_LEFT);
+ }
+
+ /**
+ * Sets the alignment of the Dialog container.
+ *
+ * @param isUser a boolean representing if the dialog box if of the user.
+ */
+ private void setDialogContainerDirection(boolean isUser) {
+ if (isUser) {
+ dialogContainer.setAlignment(Pos.CENTER_RIGHT);
+ } else {
+ dialogContainer.setAlignment(Pos.CENTER_LEFT);
+ }
+ }
+
+ public static DialogBox getUserDialog(String text, Image img) {
+ DialogBox userBox = new DialogBox(text, img);
+ userBox.setDialogContainerDirection(true);
+ return userBox;
+ }
+
+ public static DialogBox getDukeDialog(String text, Image img) {
+ DialogBox dukeBox = new DialogBox(text, img);
+ dukeBox.flip();
+ dukeBox.setDialogContainerDirection(false);
+ return dukeBox;
+ }
+}
diff --git a/src/main/java/duke/ui/ErrorBox.java b/src/main/java/duke/ui/ErrorBox.java
new file mode 100644
index 0000000000..5cf42b4303
--- /dev/null
+++ b/src/main/java/duke/ui/ErrorBox.java
@@ -0,0 +1,44 @@
+package duke.ui;
+
+
+import javafx.geometry.Pos;
+import javafx.scene.Scene;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.layout.VBox;
+import javafx.stage.Modality;
+import javafx.stage.Stage;
+
+/**
+ * Encapsulates an ErrorBox class that deals with and displays exceptions.
+ */
+public class ErrorBox {
+ /**
+ * Displays an Error box with the given title and the alert message.
+ *
+ * @param message the main message of the Error.
+ */
+ public static void display(String message) {
+ Stage window = new Stage();
+
+ // disable actions in other windows
+ window.initModality(Modality.APPLICATION_MODAL);
+ window.setTitle("");
+ window.setMinWidth(250);
+
+ Label errorContent = new Label();
+ errorContent.setText(message);
+ errorContent.setWrapText(true);
+ Button closeButton = new Button("Close");
+ closeButton.setOnAction(e -> window.close());
+ closeButton.setDefaultButton(true);
+
+ VBox layout = new VBox(20);
+ layout.getChildren().addAll(errorContent, closeButton);
+ layout.setAlignment(Pos.CENTER);
+
+ Scene scene = new Scene(layout, 300, 300);
+ window.setScene(scene);
+ window.showAndWait();
+ }
+}
diff --git a/src/main/java/duke/ui/MainMenu.java b/src/main/java/duke/ui/MainMenu.java
new file mode 100644
index 0000000000..44104b66cb
--- /dev/null
+++ b/src/main/java/duke/ui/MainMenu.java
@@ -0,0 +1,52 @@
+package duke.ui;
+
+import java.io.IOException;
+
+import javafx.fxml.FXML;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Parent;
+import javafx.scene.Scene;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.layout.VBox;
+import javafx.stage.Stage;
+
+
+
+/**
+ * Encapsulates an MainMenu class that deals with displaying an alert UI.
+ */
+public class MainMenu {
+
+ @FXML
+ private VBox logoBox;
+
+ @FXML
+ private Label dukeLogo;
+
+ @FXML
+ private Button startButton;
+
+
+ @FXML
+ private void initialize() {
+ dukeLogo.setText(Ui.LOGO);
+ }
+
+
+ /**
+ * This method transits from current window to the MainWindow.
+ */
+ @FXML
+ private void switchWindow() {
+ try {
+ Stage stage = (Stage) startButton.getScene().getWindow();
+ Parent root = FXMLLoader.load(duke.Main.class.getResource("/view/MainWindow.fxml"));
+ Scene scene = new Scene(root);
+ stage.setScene(scene);
+ stage.show();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/duke/ui/MainWindow.java b/src/main/java/duke/ui/MainWindow.java
new file mode 100644
index 0000000000..3ab735a185
--- /dev/null
+++ b/src/main/java/duke/ui/MainWindow.java
@@ -0,0 +1,91 @@
+package duke.ui;
+
+
+import duke.command.Command;
+import duke.utils.Parser;
+import duke.utils.Statistics;
+import duke.utils.TaskStorage;
+import javafx.application.Platform;
+import javafx.fxml.FXML;
+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.layout.AnchorPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+/**
+ * Controller for MainWindow. Provides the layout for the other controls.
+ */
+public class MainWindow extends AnchorPane {
+ @FXML
+ private HBox TitleBox;
+ @FXML
+ private Label AppName;
+ @FXML
+ private ScrollPane scrollPane;
+ @FXML
+ private VBox dialogContainer;
+ @FXML
+ private TextField userInput;
+ @FXML
+ private Button sendButton;
+
+
+ private String response;
+
+ private Image dukeImage = new Image(this.getClass().getResourceAsStream("/images/cat1.jpg"));
+ private Image userImage = new Image(this.getClass().getResourceAsStream("/images/cat2.jpg"));
+
+ @FXML
+ private void initialize() {
+ scrollPane.vvalueProperty().bind(dialogContainer.heightProperty());
+ dialogContainer.getChildren().addAll(
+ DialogBox.getDukeDialog(Ui.GREETING, dukeImage),
+ DialogBox.getDukeDialog(TaskStorage.loadFiles(), dukeImage),
+ DialogBox.getDukeDialog(Statistics.getStatistics().toString(), dukeImage)
+ );
+
+ }
+
+
+ /**
+ * 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.
+ */
+ @FXML
+ private void handleUserInput() {
+ String userText = userInput.getText();
+ Parser parser = new Parser(userText);
+ Command command = parser.parse();
+ boolean isExit = command.getIsExitStatus();
+ response = command.execute();
+
+
+ if (isExit) {
+ dialogContainer.getChildren().addAll(
+ DialogBox.getDukeDialog(response, dukeImage)
+ );
+ Platform.exit();
+ }
+
+ if (!response.equals("")) {
+ dialogContainer.getChildren().addAll(
+ DialogBox.getUserDialog(userText, userImage),
+ DialogBox.getDukeDialog(response, dukeImage)
+ );
+ } else {
+ dialogContainer.getChildren().addAll(
+ DialogBox.getDukeDialog(Ui.COMMAND_ERROR, dukeImage)
+ );
+ }
+
+
+
+ userInput.clear();
+ }
+
+
+
+}
diff --git a/src/main/java/duke/ui/Ui.java b/src/main/java/duke/ui/Ui.java
new file mode 100644
index 0000000000..1e09107180
--- /dev/null
+++ b/src/main/java/duke/ui/Ui.java
@@ -0,0 +1,61 @@
+package duke.ui;
+
+import duke.task.Task;
+import duke.task.TaskList;
+
+/**
+ * A class that store all the possible String format for Duke for code simplicity.
+ */
+public class Ui {
+
+ public static final String LINEBREAK = "\n";
+ public static final String LOGO = "D U K E";
+ public static final String WRONG_DATE_FORMAT = "!!!Err, wrong date format.. (yyyy-mm-dd)!!!";
+ public static final String KEY_IN_NUMBER = "!!!!!PLease Lah! Key in number!!!!!!";
+ public static final String EMPTY_TASK = "!!!Walao!NO TASK!!!";
+ public static final String MISSING_DATE = "Fill ur date lah (add date with / in yyyy-mm-dd format)!";
+ public static final String COMMAND_ERROR = "!!I DON'T KNOW WHAT U SAYING BRO!!";
+ public static final String TASK_ERROR = "!!!!!!!!!!Walao, no such task!!!!!!!!!";
+ public static final String SAVE_TO_FILE_ERROR = "Huh? Where your file?";
+ public static final String EMPTY_COMMAND = "!!!Walao, command cannot be empty!!!";
+ public static final String SUCCESSFUL_SAVE = "~File Saved Successfully!~";
+ public static final String FAREWELL = " I Zao Liao. Don't Miss Meeeeeee.";
+ public static final String GREETING = "** Awww, need help ah? **";
+ public static final String EMPTY_FILE = "*Awwww~ You don't have any history of tasks *";
+ public static final String SUCESSFUL_LOAD = "*Sir, here is your past history: *\n";
+ public static final String EMPTY_LIST = "Awwww, there is nothing in the list yet";
+
+ /**
+ * Display a message to indicate the given task as done.
+ * @param t the task to be displayed as done.
+ */
+ public static String doneTask(Task t) {
+
+ return "Wah~ You done the task: "
+ + " " + t.toString();
+ }
+
+ /**
+ * Display a message to indicate the given task as deleted.
+ * @param t the task to be displayed as deleted.
+ */
+ public static String deleteTask(Task t) {
+
+ return "Awww~ You've deleted the task: "
+ + " " + t.toString();
+ }
+
+ /**
+ * make a Bigger ChatBox that wrap the name of a given Task.
+ *
+ * @param t task to be wrapped.
+ * @return the String representation of the task name wrapped in a chatBox.
+ */
+ public static String createAddResponse(Task t) {
+ return "Added liao: "
+ + t.toString() + Ui.LINEBREAK
+ + "You have " + TaskList.getTasksSize() + " tasks in the list!";
+ }
+
+}
+
diff --git a/src/main/java/duke/utils/DateAndTime.java b/src/main/java/duke/utils/DateAndTime.java
new file mode 100644
index 0000000000..a9aa7fa86a
--- /dev/null
+++ b/src/main/java/duke/utils/DateAndTime.java
@@ -0,0 +1,53 @@
+package duke.utils;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+
+import duke.ui.Ui;
+
+/**
+ * This class processes the date key in by user and converts it to the right format.
+ */
+public class DateAndTime {
+
+ /**
+ * This method converts a yyyy-mm-dd format of date to MMM d yyyy format.
+ *
+ * @param date the String representation of date.
+ * @return MMM d yyyy format of date and return error message if the given date is in wrong format.
+ */
+ public static String convertDateFormat(String date) {
+ if (isDashFormat(date)) {
+ try {
+ LocalDate d1 = LocalDate.parse(date.trim());
+ return d1.format(DateTimeFormatter.ofPattern("MMM d yyyy"));
+ } catch (DateTimeParseException e) {
+ return Ui.WRONG_DATE_FORMAT;
+ }
+ } else {
+ return Ui.WRONG_DATE_FORMAT;
+ }
+ }
+
+
+ private static boolean isDashFormat(String date) {
+ String[] dashFormat = date.toLowerCase().split("-", 3);
+ for (String s : dashFormat) {
+ if (!isNumeric(s.trim())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean isNumeric(String strNum) {
+ try {
+ Double.parseDouble(strNum);
+ } catch (NumberFormatException nfe) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/src/main/java/duke/utils/Parser.java b/src/main/java/duke/utils/Parser.java
new file mode 100644
index 0000000000..d9a5bb2c91
--- /dev/null
+++ b/src/main/java/duke/utils/Parser.java
@@ -0,0 +1,190 @@
+package duke.utils;
+
+import duke.command.AddCommand;
+import duke.command.Command;
+import duke.command.DeleteCommand;
+import duke.command.DoneCommand;
+import duke.command.ErrorCommand;
+import duke.command.ExitCommand;
+import duke.command.FindCommand;
+import duke.command.ListCommand;
+import duke.command.ClearCommand;
+import duke.exceptions.DukeException;
+import duke.type.CommandType;
+import duke.ui.ErrorBox;
+import duke.ui.Ui;
+
+
+/**
+ * This class extracts and processes the user input and produce command to be executed after parsing.
+ */
+public class Parser {
+ private final String input;
+
+ public Parser(String input) {
+ this.input = input;
+ }
+
+ /**
+ * This method processes all the user input and create respective command to be executed.
+ *
+ * @return the respective command to be executed.
+ */
+ public final Command parse() {
+ String[] validInputs = extractValidInput();
+ if (validInputs[0] == null) {
+ return new ErrorCommand();
+ }
+
+ String instruction = validInputs[0];
+ String taskName = validInputs[1];
+ String date = validInputs[2];
+ Command command;
+ switch (instruction) {
+ case "bye":
+ command = new ExitCommand();
+ TaskStorage.writeToFiles();
+ break;
+ case "list":
+ command = new ListCommand();
+ break;
+ case "done":
+ command = new DoneCommand(taskName);
+ break;
+ case "todo": case "deadline": case "event":
+ command = new AddCommand(instruction, taskName, date);
+ break;
+ case "delete":
+ command = new DeleteCommand(taskName);
+ break;
+ case "find":
+ command = new FindCommand(taskName);
+ break;
+ case "clear":
+ command = new ClearCommand();
+ break;
+ default:
+ command = new ErrorCommand();
+ break;
+ }
+ return command;
+ }
+
+
+ /**
+ * extracts the command key in by user.
+ *
+ * @param input the input key in by user.
+ * @return String representation of the command word of the user input.
+ */
+ static String extractInstruction(String input) throws DukeException {
+ // Split by the first space encountered.
+ String[] splits = input.trim().toLowerCase().split(" ", 2);
+ assert splits.length >= 1 : "Command cannot be empty!";
+ String instruction = splits[0];
+ //If the instruction is empty then throw exception.
+ if (input.replaceAll(" ", "").equals("")) {
+ throw new DukeException(Ui.EMPTY_COMMAND);
+ }
+
+ // If the instruction is not any of the known instructions then throw exception.
+ if (CommandType.valueOfType(instruction) == null) {
+ throw new DukeException(Ui.COMMAND_ERROR);
+ }
+
+ return instruction;
+
+ }
+
+ /**
+ * extracts task name from user input.
+ *
+ * @param input user input.
+ * @param command user command.
+ * @return the task name if there is one and return empty string if task name empty.
+ */
+ static String extractTask(String input, String command) throws DukeException {
+
+ // Remove instruction from the user Input.
+ String taskInput = input.replaceAll(command, "").trim();
+ String noTask = "";
+ boolean isEmptyTask = taskInput.equals(noTask);
+ switch (command) {
+ case "todo": case "find": case "done": case "delete":
+ if (isEmptyTask) {
+ throw new DukeException(Ui.EMPTY_TASK);
+ }
+ return taskInput;
+ case "deadline": case "event":
+ if (isEmptyTask) {
+ throw new DukeException(Ui.EMPTY_TASK);
+ }
+ return taskInput.split("/")[0];
+ case "bye": case "list": case "clear":
+ if (taskInput.length() > 0) {
+ throw new DukeException(Ui.COMMAND_ERROR);
+ }
+ return noTask;
+ default:
+ return noTask;
+ }
+ }
+
+ /**
+ * This method extracts the date of the task to be done.
+ *
+ * @param input user input.
+ * @param instruction user instruction.
+ * @return the task date in String and return empty if there is no date.
+ */
+ static String extractDate(String input, String instruction) throws DukeException {
+
+ // Remove instruction from the user input to get taskInput.
+ String taskInput = input.replaceAll(instruction, "").trim();
+
+ // Split task input by the first / encountered.
+ String[] splitParts = taskInput.split("/", 2);
+
+ boolean hasDate = splitParts.length == 2;
+ String noDate = "";
+ if (!hasDate) {
+ if (instruction.equals("deadline")
+ || instruction.equals("event")) {
+ throw new DukeException(Ui.MISSING_DATE);
+ }
+ // if the instruction does not require date return no date.
+ return noDate;
+ }
+
+ // Convert the date format.
+ String date = DateAndTime.convertDateFormat(splitParts[1]);
+ if (date.equals(Ui.WRONG_DATE_FORMAT)) {
+ throw new DukeException(Ui.WRONG_DATE_FORMAT);
+ }
+ return date;
+ }
+
+ /**
+ * This method extracts valid input from the user input.
+ * @return a String array that store instruction, taskName and date.
+ */
+ private String[] extractValidInput() {
+ String instruction;
+ String taskName;
+ String date;
+ String[] validInputs = new String[3];
+ try {
+ instruction = extractInstruction(input);
+ taskName = extractTask(input, instruction);
+ date = extractDate(input, instruction);
+ validInputs[0] = instruction;
+ validInputs[1] = taskName;
+ validInputs[2] = date;
+ } catch (DukeException e) {
+ ErrorBox.display(e.getMessage());
+ }
+
+ return validInputs;
+ }
+
+}
diff --git a/src/main/java/duke/utils/Statistics.java b/src/main/java/duke/utils/Statistics.java
new file mode 100644
index 0000000000..d064761cc1
--- /dev/null
+++ b/src/main/java/duke/utils/Statistics.java
@@ -0,0 +1,123 @@
+package duke.utils;
+
+import duke.task.Task;
+import duke.task.TaskList;
+import duke.ui.ErrorBox;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Statistics class that keep track of the number of done tasks;
+ */
+public class Statistics {
+ private static final String DIRECTORY = "data";
+ private static final String FILEPATH = "data/Statistics.txt";
+
+ private static int totalTaskHistory = 0;
+
+ private int numberOfDoneTasks;
+ private int numberOfIncompleteTask;
+
+ public Statistics (int numberOfDoneTasks, int numberOfIncompleteTask) {
+ this.numberOfDoneTasks = numberOfDoneTasks;
+ this.numberOfIncompleteTask = numberOfIncompleteTask;
+ }
+
+ /**
+ * Generate the statistics of the current taskList.
+ * @return the current statistics of the current taskList.
+ */
+ public static Statistics getStatistics() {
+ int numberOfDoneTasks = 0;
+ int numberOfIncompleteTasks = 0;
+ List tasks = TaskList.getTaskList();
+
+ for (Task task : tasks) {
+ if (task.getDoneStatus().equals("X")) {
+ numberOfDoneTasks++;
+ } else {
+ numberOfIncompleteTasks++;
+ }
+ }
+
+ return new Statistics(numberOfDoneTasks, numberOfIncompleteTasks);
+ }
+
+ /**
+ * This method write the Statistics of Duke in Statistics.txt.
+ *
+ */
+ public static void updateStatistics(Task task) {
+ File statsFile = new File(FILEPATH);
+ if (!statsFile.exists()) {
+ initialize();
+ }
+
+ totalTaskHistory++;
+ try {
+ FileWriter fw = new FileWriter(FILEPATH, true);
+ fw.write(reformatTask(task));
+ fw.close();
+ } catch (IOException err) {
+ ErrorBox.display(err.getMessage());
+ }
+
+ }
+
+ /**
+ * Reformats the task to be written in file.
+ * @param task user task.
+ * @return a different string format of the task.
+ */
+ private static String reformatTask(Task task) {
+ String taskDisplay = task.toString();
+ String taskType = taskDisplay.substring(0, 3);
+ String taskStatus = taskDisplay.substring(3, 6);
+ String taskContent = taskDisplay.substring(9);
+
+ return totalTaskHistory + "\n" + taskType + taskStatus + taskContent + "\n";
+ }
+
+ /**
+ * Initializes the statistic file.
+ */
+ public static void initialize() {
+ File directory = new File(DIRECTORY);
+ if (!directory.exists()) {
+ directory.mkdir();
+ }
+ File statisticsFile = new File(FILEPATH);
+ if (!statisticsFile.exists()) {
+ try {
+ File pastRecord = new File("data/Duke.txt");
+ pastRecord.delete();
+ pastRecord.createNewFile();
+ statisticsFile.createNewFile();
+ FileWriter fw = new FileWriter(FILEPATH);
+ fw.write("Task history: \n");
+ fw.close();
+ } catch (IOException err) {
+ err.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Clear all history in the statistics file.
+ */
+ public static void clear() {
+ totalTaskHistory = 0;
+ File file = new File(FILEPATH);
+ file.delete();
+ }
+
+
+ @Override
+ public String toString() {
+ return String.format("You have %d doneTasks and %d incomplete tasks\n",
+ numberOfDoneTasks, numberOfIncompleteTask);
+ }
+}
diff --git a/src/main/java/duke/utils/TaskStorage.java b/src/main/java/duke/utils/TaskStorage.java
new file mode 100644
index 0000000000..4177ddb96c
--- /dev/null
+++ b/src/main/java/duke/utils/TaskStorage.java
@@ -0,0 +1,121 @@
+package duke.utils;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.List;
+import java.util.Scanner;
+
+import duke.task.Deadline;
+import duke.task.Event;
+import duke.task.Task;
+import duke.task.TaskList;
+import duke.task.Todo;
+import duke.ui.ErrorBox;
+import duke.ui.Ui;
+
+/**
+ * This class handles the saving and loading of the taskList to/from a specific FilePath.
+ */
+public class TaskStorage {
+
+ private static final String FILEPATH = "data/Duke.txt";
+ private static final String DIRECTORY = "data";
+
+ /**
+ * This method writes the content of a taskList to data/Duke.txt.
+ *
+ * @return A string display of a successful save.
+ */
+ public static String writeToFiles() {
+ List taskList = TaskList.getTaskList();
+ try {
+ FileWriter fw = new FileWriter(FILEPATH);
+ for (Task t : taskList) {
+ String temp = t.getType() + "@@" + t.getDoneStatus()
+ + "@@" + t.getTaskName() + (t.getDate().equals("")
+ ? "" : ("@@" + t.getDate())) + System.lineSeparator();
+ fw.write(temp);
+ }
+ fw.close();
+ taskList.clear();
+ assert taskList.size() == 0 : "TaskList not clear";
+ } catch (IOException err) {
+ ErrorBox.display(err.getMessage());
+ }
+ return Ui.SUCCESSFUL_SAVE;
+ }
+
+
+ /**
+ * This method loads the file from data/Duke.txt and display in a list format when the program starts.
+ *
+ * @return the String display of a successful load.
+ */
+ public static String loadFiles() {
+ StringBuilder loadContent = new StringBuilder();
+
+ try {
+ File directory = new File(DIRECTORY);
+ File file = new File(FILEPATH);
+
+ if (!directory.exists()) {
+ directory.mkdir();
+ }
+
+ assert directory.exists() : "Directory does not exist";
+
+ if (!file.exists()) {
+ file.createNewFile();
+ }
+
+ assert file.exists() : "File does not exist";
+
+ if (file.length() == 0) {
+ return Ui.EMPTY_FILE;
+ }
+
+ loadContent.append(restoreTask(file));
+ } catch (IOException e) {
+ ErrorBox.display("IO error!: " + e.getMessage());
+ }
+ if (loadContent.length() == 0) {
+ loadContent.append(Ui.EMPTY_FILE);
+ } else {
+ loadContent.insert(0, Ui.SUCESSFUL_LOAD);
+ }
+
+ return loadContent.toString();
+ }
+
+ /**
+ * This method restore the task List from Duke.txt.
+ * @param file Duke.txt that store the user past history of task list.
+ * @return the file content in String.
+ * @throws IOException thrown when file is not found.
+ */
+ private static String restoreTask(File file) throws IOException {
+ Scanner sc = new Scanner(file);
+ StringBuilder fileContent = new StringBuilder("");
+
+ //Interpret the file content and add tasks to task list.
+ while (sc.hasNext()) {
+ String[] line = sc.nextLine().split("@@");
+ if (line.length == 3) {
+ Todo t = new Todo(line[2], line[1]);
+ TaskList.addTask(t);
+ fileContent.append(t.toString() + "\n");
+ } else {
+ int type = Integer.parseInt(line[0]);
+ String done = line[1];
+ String taskName = line[2];
+ String date = line[3];
+ Task t = type == 2 ? new Deadline(taskName, date, done) : new Event(taskName, date, done);
+ TaskList.addTask(t);
+ fileContent.append(t.toString() + "\n");
+ }
+ }
+ sc.close();
+ return fileContent.toString();
+ }
+}
diff --git a/src/main/java/out/production/main/.idea/.gitignore b/src/main/java/out/production/main/.idea/.gitignore
new file mode 100644
index 0000000000..26d33521af
--- /dev/null
+++ b/src/main/java/out/production/main/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/src/main/java/out/production/main/.idea/misc.xml b/src/main/java/out/production/main/.idea/misc.xml
new file mode 100644
index 0000000000..40674af8d6
--- /dev/null
+++ b/src/main/java/out/production/main/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/out/production/main/.idea/modules.xml b/src/main/java/out/production/main/.idea/modules.xml
new file mode 100644
index 0000000000..122a9054e1
--- /dev/null
+++ b/src/main/java/out/production/main/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/out/production/main/.idea/vcs.xml b/src/main/java/out/production/main/.idea/vcs.xml
new file mode 100644
index 0000000000..c2365ab11f
--- /dev/null
+++ b/src/main/java/out/production/main/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/out/production/main/duke/Duke.class b/src/main/java/out/production/main/duke/Duke.class
new file mode 100644
index 0000000000..fed1d60d52
Binary files /dev/null and b/src/main/java/out/production/main/duke/Duke.class differ
diff --git a/src/main/java/out/production/main/duke/command/AddCommand.class b/src/main/java/out/production/main/duke/command/AddCommand.class
new file mode 100644
index 0000000000..14fae697db
Binary files /dev/null and b/src/main/java/out/production/main/duke/command/AddCommand.class differ
diff --git a/src/main/java/out/production/main/duke/command/Command.class b/src/main/java/out/production/main/duke/command/Command.class
new file mode 100644
index 0000000000..9af484fe99
Binary files /dev/null and b/src/main/java/out/production/main/duke/command/Command.class differ
diff --git a/src/main/java/out/production/main/duke/command/DeleteCommand.class b/src/main/java/out/production/main/duke/command/DeleteCommand.class
new file mode 100644
index 0000000000..344677d16c
Binary files /dev/null and b/src/main/java/out/production/main/duke/command/DeleteCommand.class differ
diff --git a/src/main/java/out/production/main/duke/command/DoneCommand.class b/src/main/java/out/production/main/duke/command/DoneCommand.class
new file mode 100644
index 0000000000..97b25ce781
Binary files /dev/null and b/src/main/java/out/production/main/duke/command/DoneCommand.class differ
diff --git a/src/main/java/out/production/main/duke/command/ErrorCommand.class b/src/main/java/out/production/main/duke/command/ErrorCommand.class
new file mode 100644
index 0000000000..6b3749fc7f
Binary files /dev/null and b/src/main/java/out/production/main/duke/command/ErrorCommand.class differ
diff --git a/src/main/java/out/production/main/duke/command/ExitCommand.class b/src/main/java/out/production/main/duke/command/ExitCommand.class
new file mode 100644
index 0000000000..02f1b9c649
Binary files /dev/null and b/src/main/java/out/production/main/duke/command/ExitCommand.class differ
diff --git a/src/main/java/out/production/main/duke/command/ListCommand.class b/src/main/java/out/production/main/duke/command/ListCommand.class
new file mode 100644
index 0000000000..dee2b86c03
Binary files /dev/null and b/src/main/java/out/production/main/duke/command/ListCommand.class differ
diff --git a/src/main/java/out/production/main/duke/driver/DukeDriver.class b/src/main/java/out/production/main/duke/driver/DukeDriver.class
new file mode 100644
index 0000000000..38bad14a36
Binary files /dev/null and b/src/main/java/out/production/main/duke/driver/DukeDriver.class differ
diff --git a/src/main/java/out/production/main/duke/exceptions/DukeException.class b/src/main/java/out/production/main/duke/exceptions/DukeException.class
new file mode 100644
index 0000000000..1b3780b2ba
Binary files /dev/null and b/src/main/java/out/production/main/duke/exceptions/DukeException.class differ
diff --git a/src/main/java/out/production/main/duke/task/Deadlines.class b/src/main/java/out/production/main/duke/task/Deadlines.class
new file mode 100644
index 0000000000..55d04686c1
Binary files /dev/null and b/src/main/java/out/production/main/duke/task/Deadlines.class differ
diff --git a/src/main/java/out/production/main/duke/task/Event.class b/src/main/java/out/production/main/duke/task/Event.class
new file mode 100644
index 0000000000..fc0669944a
Binary files /dev/null and b/src/main/java/out/production/main/duke/task/Event.class differ
diff --git a/src/main/java/out/production/main/duke/task/Task.class b/src/main/java/out/production/main/duke/task/Task.class
new file mode 100644
index 0000000000..702e6424eb
Binary files /dev/null and b/src/main/java/out/production/main/duke/task/Task.class differ
diff --git a/src/main/java/out/production/main/duke/task/Todo.class b/src/main/java/out/production/main/duke/task/Todo.class
new file mode 100644
index 0000000000..cae2a4c7a3
Binary files /dev/null and b/src/main/java/out/production/main/duke/task/Todo.class differ
diff --git a/src/main/java/out/production/main/duke/ui/Ui.class b/src/main/java/out/production/main/duke/ui/Ui.class
new file mode 100644
index 0000000000..250e669b5b
Binary files /dev/null and b/src/main/java/out/production/main/duke/ui/Ui.class differ
diff --git a/src/main/java/out/production/main/duke/utils/DateAndTime.class b/src/main/java/out/production/main/duke/utils/DateAndTime.class
new file mode 100644
index 0000000000..b5dfb0babc
Binary files /dev/null and b/src/main/java/out/production/main/duke/utils/DateAndTime.class differ
diff --git a/src/main/java/out/production/main/duke/utils/Parser.class b/src/main/java/out/production/main/duke/utils/Parser.class
new file mode 100644
index 0000000000..f0d6f99db6
Binary files /dev/null and b/src/main/java/out/production/main/duke/utils/Parser.class differ
diff --git a/src/main/java/out/production/main/duke/utils/TaskStorage.class b/src/main/java/out/production/main/duke/utils/TaskStorage.class
new file mode 100644
index 0000000000..71cf523ad1
Binary files /dev/null and b/src/main/java/out/production/main/duke/utils/TaskStorage.class differ
diff --git a/src/main/out/production/main/duke/Duke.class b/src/main/out/production/main/duke/Duke.class
new file mode 100644
index 0000000000..d457857c61
Binary files /dev/null and b/src/main/out/production/main/duke/Duke.class differ
diff --git a/src/main/out/production/main/duke/command/AddCommand.class b/src/main/out/production/main/duke/command/AddCommand.class
new file mode 100644
index 0000000000..b0937d2b9f
Binary files /dev/null and b/src/main/out/production/main/duke/command/AddCommand.class differ
diff --git a/src/main/out/production/main/duke/command/Command.class b/src/main/out/production/main/duke/command/Command.class
new file mode 100644
index 0000000000..37b7face77
Binary files /dev/null and b/src/main/out/production/main/duke/command/Command.class differ
diff --git a/src/main/out/production/main/duke/command/DeleteCommand.class b/src/main/out/production/main/duke/command/DeleteCommand.class
new file mode 100644
index 0000000000..737a4a7da2
Binary files /dev/null and b/src/main/out/production/main/duke/command/DeleteCommand.class differ
diff --git a/src/main/out/production/main/duke/command/DoneCommand.class b/src/main/out/production/main/duke/command/DoneCommand.class
new file mode 100644
index 0000000000..0c21f54828
Binary files /dev/null and b/src/main/out/production/main/duke/command/DoneCommand.class differ
diff --git a/src/main/out/production/main/duke/command/ErrorCommand.class b/src/main/out/production/main/duke/command/ErrorCommand.class
new file mode 100644
index 0000000000..d3e4107041
Binary files /dev/null and b/src/main/out/production/main/duke/command/ErrorCommand.class differ
diff --git a/src/main/out/production/main/duke/command/ExitCommand.class b/src/main/out/production/main/duke/command/ExitCommand.class
new file mode 100644
index 0000000000..d21f2073d8
Binary files /dev/null and b/src/main/out/production/main/duke/command/ExitCommand.class differ
diff --git a/src/main/out/production/main/duke/command/ListCommand.class b/src/main/out/production/main/duke/command/ListCommand.class
new file mode 100644
index 0000000000..d7e285b20b
Binary files /dev/null and b/src/main/out/production/main/duke/command/ListCommand.class differ
diff --git a/src/main/out/production/main/duke/driver/DukeDriver.class b/src/main/out/production/main/duke/driver/DukeDriver.class
new file mode 100644
index 0000000000..d66aafa8a9
Binary files /dev/null and b/src/main/out/production/main/duke/driver/DukeDriver.class differ
diff --git a/src/main/out/production/main/duke/exceptions/DukeException.class b/src/main/out/production/main/duke/exceptions/DukeException.class
new file mode 100644
index 0000000000..e50ef862da
Binary files /dev/null and b/src/main/out/production/main/duke/exceptions/DukeException.class differ
diff --git a/src/main/out/production/main/duke/task/Deadlines.class b/src/main/out/production/main/duke/task/Deadlines.class
new file mode 100644
index 0000000000..d4db583e81
Binary files /dev/null and b/src/main/out/production/main/duke/task/Deadlines.class differ
diff --git a/src/main/out/production/main/duke/task/Event.class b/src/main/out/production/main/duke/task/Event.class
new file mode 100644
index 0000000000..8500d29021
Binary files /dev/null and b/src/main/out/production/main/duke/task/Event.class differ
diff --git a/src/main/out/production/main/duke/task/Task.class b/src/main/out/production/main/duke/task/Task.class
new file mode 100644
index 0000000000..b6cfab2721
Binary files /dev/null and b/src/main/out/production/main/duke/task/Task.class differ
diff --git a/src/main/out/production/main/duke/task/Todo.class b/src/main/out/production/main/duke/task/Todo.class
new file mode 100644
index 0000000000..ef05e0d7f1
Binary files /dev/null and b/src/main/out/production/main/duke/task/Todo.class differ
diff --git a/src/main/out/production/main/duke/ui/Ui.class b/src/main/out/production/main/duke/ui/Ui.class
new file mode 100644
index 0000000000..12f62aaee1
Binary files /dev/null and b/src/main/out/production/main/duke/ui/Ui.class differ
diff --git a/src/main/out/production/main/duke/utils/DateAndTime.class b/src/main/out/production/main/duke/utils/DateAndTime.class
new file mode 100644
index 0000000000..099415175a
Binary files /dev/null and b/src/main/out/production/main/duke/utils/DateAndTime.class differ
diff --git a/src/main/out/production/main/duke/utils/Parser.class b/src/main/out/production/main/duke/utils/Parser.class
new file mode 100644
index 0000000000..a23b88d425
Binary files /dev/null and b/src/main/out/production/main/duke/utils/Parser.class differ
diff --git a/src/main/out/production/main/duke/utils/TaskStorage.class b/src/main/out/production/main/duke/utils/TaskStorage.class
new file mode 100644
index 0000000000..9042402f68
Binary files /dev/null and b/src/main/out/production/main/duke/utils/TaskStorage.class differ
diff --git a/src/main/resources/images/background.jpg b/src/main/resources/images/background.jpg
new file mode 100644
index 0000000000..08bce42d1b
Binary files /dev/null and b/src/main/resources/images/background.jpg differ
diff --git a/src/main/resources/images/cat1.jpg b/src/main/resources/images/cat1.jpg
new file mode 100644
index 0000000000..ed415cd4f5
Binary files /dev/null and b/src/main/resources/images/cat1.jpg differ
diff --git a/src/main/resources/images/cat2.jpg b/src/main/resources/images/cat2.jpg
new file mode 100644
index 0000000000..a89846d684
Binary files /dev/null and b/src/main/resources/images/cat2.jpg differ
diff --git a/src/main/resources/view/DialogBox.fxml b/src/main/resources/view/DialogBox.fxml
new file mode 100644
index 0000000000..ab63def6c2
--- /dev/null
+++ b/src/main/resources/view/DialogBox.fxml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/view/MainMenu.fxml b/src/main/resources/view/MainMenu.fxml
new file mode 100644
index 0000000000..4796e4fb8c
--- /dev/null
+++ b/src/main/resources/view/MainMenu.fxml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml
new file mode 100644
index 0000000000..a374cef0a3
--- /dev/null
+++ b/src/main/resources/view/MainWindow.fxml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/out/test/test/duke/DukeTest.class b/src/out/test/test/duke/DukeTest.class
new file mode 100644
index 0000000000..e629858837
Binary files /dev/null and b/src/out/test/test/duke/DukeTest.class differ
diff --git a/src/test/data/Duke.txt b/src/test/data/Duke.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/test/java/duke/task/TaskListTest.java b/src/test/java/duke/task/TaskListTest.java
new file mode 100644
index 0000000000..4d1d7d7e14
--- /dev/null
+++ b/src/test/java/duke/task/TaskListTest.java
@@ -0,0 +1,39 @@
+package duke.task;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+
+class TaskListTest {
+
+ @Test
+ void doneTask() {
+ TaskList.clearAllTasks();
+ Todo task = new Todo("Scratch back", " ");
+ TaskList.addTask(task);
+ TaskList.markDone(1);
+ assertEquals("X", task.getDoneStatus());
+ }
+
+ @Test
+ void deleteTask() {
+ TaskList.clearAllTasks();
+ Todo task = new Todo("Scratch back", " ");
+ TaskList.addTask(task);
+ TaskList.deleteTask(1);
+ assertEquals(0, TaskList.getTaskList().size());
+ }
+
+ @Test
+ void listTasks() {
+ TaskList.clearAllTasks();
+ Todo todo = new Todo("nothing", " ");
+ Deadline deadline = new Deadline("Swimming", "2019-10-22", " ");
+ TaskList.addTask(todo);
+ TaskList.addTask(deadline);
+
+ assertEquals("[T][ ] 1. nothing\n" +
+ "[D][ ] 1. Swimming ( 2019-10-22 )\n", TaskList.listTasks());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/duke/utils/DateAndTimeTest.java b/src/test/java/duke/utils/DateAndTimeTest.java
new file mode 100644
index 0000000000..7c9fcf8487
--- /dev/null
+++ b/src/test/java/duke/utils/DateAndTimeTest.java
@@ -0,0 +1,26 @@
+package duke.utils;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+
+public class DateAndTimeTest {
+
+ @Test
+ void converterTest() {
+ String date = "2019-10-22";
+ String actualOutput = DateAndTime.convertDateFormat(date);
+ String expectedOutput = "Oct 22 2019";
+ assertEquals(expectedOutput, actualOutput);
+ }
+
+ @Test
+ void converterTest_wrongDateFormat() {
+ String date = "2019";
+ String actualOutput = DateAndTime.convertDateFormat(date);
+ String expectedOutput = "!!!Err, wrong date format.. (yyyy-mm-dd)!!!";
+ assertEquals(expectedOutput, actualOutput);
+ }
+
+}
diff --git a/src/test/java/duke/utils/ParserTest.java b/src/test/java/duke/utils/ParserTest.java
new file mode 100644
index 0000000000..0b2aa1d05b
--- /dev/null
+++ b/src/test/java/duke/utils/ParserTest.java
@@ -0,0 +1,90 @@
+package duke.utils;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.junit.jupiter.api.Test;
+
+import duke.exceptions.DukeException;
+
+
+public class ParserTest {
+
+
+ @Test
+ void extractInstructionTest() throws DukeException {
+ String testInput = "todo swimming";
+ String actualInstruction = Parser.extractInstruction(testInput);
+ assertEquals("todo", actualInstruction);
+ }
+
+ @Test
+ void extractInstruction_emptyInstruction_exception() {
+ try {
+ String testInput = "";
+ Parser.extractInstruction(testInput);
+ fail();
+ } catch (DukeException e) {
+ assertEquals("!!!Walao, command cannot be empty!!!", e.getMessage());
+ }
+ }
+
+ @Test
+ void extractInstruction_wrongInstruction_exception() {
+ try {
+ String testInput = "ANYHOW";
+ Parser.extractInstruction(testInput);
+ fail();
+ } catch (DukeException e) {
+ assertEquals("!!!!!!!I DON'T KNOW WHAT U SAYING BRO!!!!!!!", e.getMessage());
+ }
+ }
+
+
+ @Test
+ void extractTaskTest() throws DukeException {
+ String testInput = "deadline project/2019-10-22";
+ String actualTask = Parser.extractTask(testInput, "deadline");
+ assertEquals("project", actualTask);
+ }
+
+ @Test
+ void extractTask_emptyTask_exception() {
+ try {
+ String testInput = "deadline ";
+ Parser.extractTask(testInput, "deadline");
+ fail();
+ } catch (DukeException e) {
+ assertEquals("!!!!!!!!!Walao!NO TASK!!!!!!!!!!", e.getMessage());
+ }
+ }
+
+ @Test
+ void extractDateTest() throws DukeException {
+ String testInput = "deadline project /2019-10-22";
+ String actualDate = Parser.extractDate(testInput, "deadline");
+ assertEquals("Oct 22 2019", actualDate);
+ }
+
+ @Test
+ void extractDate_withoutSlash_exception() {
+ try {
+ String testInput = "deadline project";
+ Parser.extractDate(testInput, "deadline");
+ fail();
+ } catch (DukeException e) {
+ assertEquals("!!!Fill ur date lah (add date with / in yyyy-mm-dd format)!!!", e.getMessage());
+ }
+
+ }
+ @Test
+ void extractDate_wrongDateFormat_exception() {
+ try {
+ String testInput = "event project/2019";
+ Parser.extractDate(testInput, "event");
+ fail();
+ } catch (DukeException e) {
+ assertEquals("!!!Err, wrong date format.. (yyyy-mm-dd)!!!", e.getMessage());
+ }
+ }
+}
diff --git a/src/test/java/duke/utils/TaskStorageTest.java b/src/test/java/duke/utils/TaskStorageTest.java
new file mode 100644
index 0000000000..f9b1d6edb8
--- /dev/null
+++ b/src/test/java/duke/utils/TaskStorageTest.java
@@ -0,0 +1,24 @@
+package duke.utils;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+
+public class TaskStorageTest {
+
+ @Test
+ void writeToFilesTest() {
+ String actualOutput = TaskStorage.writeToFiles();
+ String expectedOutput = "~~~~~~~~~~~File Saved Successfully!~~~~~~~~~~~~";
+ assertEquals(actualOutput, expectedOutput);
+ }
+
+ @Test
+ void loadFilesTest() {
+ String actualOutput = TaskStorage.loadFiles();
+ String expectedOutput = "********** Awwww~ You don't have any history of tasks **********\n";
+ assertEquals(actualOutput, expectedOutput);
+ }
+
+}
diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT
new file mode 100644
index 0000000000..6f4b66597d
--- /dev/null
+++ b/text-ui-test/ACTUAL.TXT
@@ -0,0 +1,116 @@
+ ____ _
+| _ \ _ _| | _____
+| | | | | | | |/ / _ \
+| |_| | |_| | < __/
+|____/ \__,_|_|\_\___|
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+*************** Awww, need help ah? ***************
+__________________________________________________________________________________________
+
+******* Wait ah~ Loading file for you *******
+******* Cannot find your directory eh, first time ah? Create one for you *******
+******* File also don't have ah, nvm I make one for you *******
+******* Awwww~ You don't have any history of tasks *******
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Added liao: [T][ ] 1. read book
+You have 1 tasks in the list!
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Wah~ You done the task: [T][X] 1. read book
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Added liao: [T][ ] 2. swimming
+You have 2 tasks in the list!
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Added liao: [D][ ] 3. project ( Oct 22 2020 )
+You have 3 tasks in the list!
+__________________________________________________________________________________________
+
+Err, wrong date format..
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Added liao: [D][ ] 4. meeting ( 2021-1-2 )
+You have 4 tasks in the list!
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Wah~ You done the task: [D][X] 3. project ( Oct 22 2020 )
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+[T][X] 1. read book
+[T][ ] 2. swimming
+[D][X] 3. project ( Oct 22 2020 )
+[D][ ] 4. meeting ( 2021-1-2 )
+
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Added liao: [E][ ] 5. project ( Oct 22 2020 )
+You have 5 tasks in the list!
+__________________________________________________________________________________________
+
+Err, wrong date format..
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Added liao: [E][ ] 6. project2 ( 2021-1-2 )
+You have 6 tasks in the list!
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Wah~ You done the task: [E][X] 6. project2 ( 2021-1-2 )
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+[T][X] 1. read book
+[T][ ] 2. swimming
+[D][X] 3. project ( Oct 22 2020 )
+[D][ ] 4. meeting ( 2021-1-2 )
+[E][ ] 5. project ( Oct 22 2020 )
+[E][X] 6. project2 ( 2021-1-2 )
+
+__________________________________________________________________________________________
+
+Walao, no such task
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Awww~ You've deleted the task: [E][ ] 5. project ( Oct 22 2020 )
+__________________________________________________________________________________________
+
+Walao, no such task
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+~~~~~~~~ I Zao Liao. Don't Miss Meeeeeee ~~~~~~~~.
+__________________________________________________________________________________________
+
diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT
index 657e74f6e7..6f4b66597d 100644
--- a/text-ui-test/EXPECTED.TXT
+++ b/text-ui-test/EXPECTED.TXT
@@ -1,7 +1,116 @@
-Hello from
____ _
| _ \ _ _| | _____
| | | | | | | |/ / _ \
| |_| | |_| | < __/
|____/ \__,_|_|\_\___|
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+*************** Awww, need help ah? ***************
+__________________________________________________________________________________________
+
+******* Wait ah~ Loading file for you *******
+******* Cannot find your directory eh, first time ah? Create one for you *******
+******* File also don't have ah, nvm I make one for you *******
+******* Awwww~ You don't have any history of tasks *******
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Added liao: [T][ ] 1. read book
+You have 1 tasks in the list!
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Wah~ You done the task: [T][X] 1. read book
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Added liao: [T][ ] 2. swimming
+You have 2 tasks in the list!
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Added liao: [D][ ] 3. project ( Oct 22 2020 )
+You have 3 tasks in the list!
+__________________________________________________________________________________________
+
+Err, wrong date format..
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Added liao: [D][ ] 4. meeting ( 2021-1-2 )
+You have 4 tasks in the list!
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Wah~ You done the task: [D][X] 3. project ( Oct 22 2020 )
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+[T][X] 1. read book
+[T][ ] 2. swimming
+[D][X] 3. project ( Oct 22 2020 )
+[D][ ] 4. meeting ( 2021-1-2 )
+
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Added liao: [E][ ] 5. project ( Oct 22 2020 )
+You have 5 tasks in the list!
+__________________________________________________________________________________________
+
+Err, wrong date format..
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Added liao: [E][ ] 6. project2 ( 2021-1-2 )
+You have 6 tasks in the list!
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Wah~ You done the task: [E][X] 6. project2 ( 2021-1-2 )
+__________________________________________________________________________________________
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+[T][X] 1. read book
+[T][ ] 2. swimming
+[D][X] 3. project ( Oct 22 2020 )
+[D][ ] 4. meeting ( 2021-1-2 )
+[E][ ] 5. project ( Oct 22 2020 )
+[E][X] 6. project2 ( 2021-1-2 )
+
+__________________________________________________________________________________________
+
+Walao, no such task
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Awww~ You've deleted the task: [E][ ] 5. project ( Oct 22 2020 )
+__________________________________________________________________________________________
+
+Walao, no such task
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+~~~~~~~~ I Zao Liao. Don't Miss Meeeeeee ~~~~~~~~.
+__________________________________________________________________________________________
+
diff --git a/text-ui-test/data/Duke.txt b/text-ui-test/data/Duke.txt
new file mode 100644
index 0000000000..cd5fa6ad45
--- /dev/null
+++ b/text-ui-test/data/Duke.txt
@@ -0,0 +1,5 @@
+1@@X@@read book
+1@@ @@swimming
+2@@X@@project @@Oct 22 2020
+2@@ @@meeting @@2021-1-2
+3@@X@@project2 @@2021-1-2
diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt
index e69de29bb2..eb04cf45fe 100644
--- a/text-ui-test/input.txt
+++ b/text-ui-test/input.txt
@@ -0,0 +1,15 @@
+todo read book
+done 1
+todo swimming
+deadline project /2020-10-22
+deadline meeting /2021-1-2
+done 3
+list
+event project /2020-10-22
+event project2 /2021-1-2
+done 6
+list
+done 10
+delete 5
+delete 9
+bye
diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat
index 0873744649..b024e711d1 100644
--- a/text-ui-test/runtest.bat
+++ b/text-ui-test/runtest.bat
@@ -15,7 +15,7 @@ IF ERRORLEVEL 1 (
REM no error here, errorlevel == 0
REM run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT
-java -classpath ..\bin Duke < input.txt > ACTUAL.TXT
+java -classpath ..\bin duke < input.txt > ACTUAL.TXT
REM compare the output to the expected output
FC ACTUAL.TXT EXPECTED.TXT