diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml
new file mode 100644
index 00000000..1d38e9d8
--- /dev/null
+++ b/.github/workflows/gradle.yml
@@ -0,0 +1,39 @@
+# This workflow will build a Java project with Gradle
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
+
+name: Java CI with Gradle
+
+on: [push, pull_request]
+
+jobs:
+ build:
+ strategy:
+ matrix:
+ platform: [ubuntu-latest, macos-latest, windows-latest]
+ runs-on: ${{ matrix.platform }}
+
+ steps:
+ - name: Set up repository
+ uses: actions/checkout@master
+
+ - name: Set up repository
+ uses: actions/checkout@master
+ with:
+ ref: master
+
+ - name: Merge to master
+ run: git checkout --progress --force ${{ github.sha }}
+
+ - name: Validate Gradle Wrapper
+ uses: gradle/wrapper-validation-action@v1
+
+ - name: Setup JDK 11
+ uses: actions/setup-java@v1
+ with:
+ java-version: '11'
+ java-package: jdk+fx
+
+ - name: Build and check with Gradle
+ run: ./gradlew check
+
+
diff --git a/README.md b/README.md
index 9d95025b..8f725dca 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,6 @@
-# Duke project template
+[![CI Status](https://github.com/tototto/ip/actions/workflows/gradle.yml/badge.svg)](https://github.com/tototto/ip/actions)
+
+# duke.Duke project template
This is a project template for a greenfield Java project. It's named after the Java mascot _Duke_. Given below are instructions on how to use it.
@@ -15,7 +17,7 @@ Prerequisites: JDK 11, update Intellij to the most recent version.
1. Click `Open or Import`.
1. Select the project directory, and click `OK`
1. If there are any further prompts, accept the defaults.
-1. After the importing is complete, 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 the importing is complete, locate the `src/main/java/duke.Duke.java` file, right-click it, and choose `Run duke.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 00000000..53e3bb78
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,62 @@
+plugins {
+ id 'java'
+ id 'application'
+ id 'checkstyle'
+ id 'com.github.johnrengelman.shadow' version '5.1.0'
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0'
+ testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
+
+ String javaFxVersion = '11'
+
+ implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'win'
+ implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'mac'
+ implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'linux'
+ implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'win'
+ implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'mac'
+ implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'linux'
+ implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'win'
+ implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'mac'
+ implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'linux'
+ implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'win'
+ implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'mac'
+ implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'linux'
+}
+
+test {
+ useJUnitPlatform()
+
+ testLogging {
+ events "passed", "skipped", "failed"
+
+ showExceptions true
+ exceptionFormat "full"
+ showCauses true
+ showStackTraces true
+ showStandardStreams = false
+ }
+}
+
+application {
+ mainClassName = "duke.Launcher"
+}
+
+shadowJar {
+ archiveBaseName = "duke"
+ archiveClassifier = null
+}
+
+checkstyle {
+ toolVersion = '8.29'
+}
+
+run{
+ standardInput = System.in
+}
+
diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
new file mode 100644
index 00000000..36d469c8
--- /dev/null
+++ b/config/checkstyle/checkstyle.xml
@@ -0,0 +1,398 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml
new file mode 100644
index 00000000..135ea49e
--- /dev/null
+++ b/config/checkstyle/suppressions.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data.txt b/data.txt
new file mode 100644
index 00000000..4a385cc9
--- /dev/null
+++ b/data.txt
@@ -0,0 +1,21 @@
+[D] [✘] read book (by: 2/2/20 12pm)
+[T] [✘] return book
+[T] [✓] buy iphone 12
+[D] [✘] sell ipad (by: 30/10/2020 12pm)
+[E] [✘] join webinar (at: 12/06/2020 4am)
+[D] [✘] sample ded task (by: 20/2/2222 3pm)
+[D] [✓] thanks giving dinner (by: 12/12/12 4pm)
+[D] [✘] fskdg (by: 12/12/21 7pm)
+[E] [✓] tgsdfsdf (at: 12/12/12 5pm-6pm)
+[T] [✘] just checking
+[D] [✘] birthday party today (by: 12/12/12 5pm)
+[E] [✓] eating competition (at: 12/12/21 5pm-6pm)
+[T] [✓] sample
+[D] [✘] task desc (by: 12/12/99 4pm)
+[E] [✓] wwdc at night (at: 12/4/21 5pm-6pm)
+[T] [✓] ttt
+[E] [✓] uuu iii (at: 5/5/21 9pm)
+[D] [✓] iii ffsf sdfd (by: 4/3/12 9pm)
+[T] [✓] gggggg
+[T] [✓] iiiiiiii
+[D] [✘] dfsfgg (by: 5/5/5 12pm)
diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md
new file mode 100644
index 00000000..32a88ef0
--- /dev/null
+++ b/docs/DeveloperGuide.md
@@ -0,0 +1,138 @@
+# Developer Guide
+
+## Design
+
+### Architecture
+
+![Image of SoftwareArchitecture](https://github.com/tototto/ip/blob/master/docs/images/architecture.jpg?raw=true)
+
+The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.
+
+The App consist of 9 components.
+
+* UI: The UI of the App.
+* Duke: The main logic handler of the App.
+* Command: The control variable of the App.
+* FileManager: Reads data from, and writes data to, the hard disk.
+* Storage: Contains the in-memory data of the app.
+* Search: Searches the data
+* Task: Define the structure of each task.
+* Input: Define how input is recieved.
+* Output: Define how output is displayed.
+
+### How the architecture components interact with each other
+
+The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command todo xxx.
+
+![Image of SequenceDiagram](https://github.com/tototto/ip/blob/master/docs/images/Interaction.jpg?raw=true)
+
+The sections below give more details of some of each component.
+
+### Duke component
+
+![Image of DukeComponent](https://github.com/tototto/ip/blob/master/docs/images/Duke.jpg?raw=true)
+
+The Duke componenet is the main handler of the App logic. It is associated with and contains all other classes as they are needed and necessary for the sucessful implementation of the logic in Duke. Duke uses the other classes in the order that is required to work the logic.
+
+The Duke componenet is called by the UI componenet which is implemented using JavaFX.
+
+### Command component
+
+![Image of CommandComponent](https://github.com/tototto/ip/blob/master/docs/images/CmdComponent.jpg?raw=true)
+
+User provide input to the App and they are pared by the InputParser class to produce a Keyword String object.
+Command and input entered by the user with the keyword are passed into the Command componenet by Duke.
+Command Components handles the different input of user entered into Duke based on the keyword extracted.
+Based on the keywords that was parsed, different actions are taken by the Command componenet.
+
+Such as:
+ * Adding a todo
+ * Adding a deadline
+ * Marking a task as done
+ * Deleting a task
+
+Based on the different keywords, the user remaning input are further parsed using the API of other componenet such as the InputParser.
+Task can then be created or updated or action can be taken, such as deleting or displaying help.
+The storage can be updated based on the result of the command executed.
+The result of the command execution is encapsulated as a output string object and is passed back to the Ui.
+In addition, the Command Component can also instruct the Ui to perform certain actions, such as displaying help to the user.
+The result is stored in the Storage componenet and then written to the file by the FileManager Component.
+
+## Implementation
+
+Add todo task Implementation
+
+The add todo feature add items in Duke. It is facillated by the Command Class which comprises of the following implementation for the add functionality:
+
+* ```InputParser``` - Parses the remaining input after keyword and prepares them to be added to the App
+* ```ListHandler``` - Add the input to the in-memory storage list
+* ```Task``` - Define how the task is structured in the App
+* ```DisplayHandler``` - Controls the result of the command execution
+
+The following sequence diagram shows how the Add todo operation works.
+
+![Image of CommandComponent](https://github.com/tototto/ip/blob/master/docs/images/AddTodoImplementation.jpg?raw=true)
+
+##### Design consideration:
+Aspect: Add Todo can otherwise be implemented
+
+###### Alternative 1: Allow user to store all task including Events & Deadline using the Todo command instead of having seperate command such as Deadline & Event for each of them.
+Pros: Improve usability. User now only needs to remember one command.
+Cons: difficult to implement.
+
+
+## Product scope
+### Target user profile
+* Is a manager, student or individual who needs to manage tasks.
+* prefer desktop apps over other types.
+* can type fast.
+* prefers typing to mouse interactions.
+* is reasonably comfortable using CLI apps.
+
+### Value proposition
+manage defects faster than a typical mouse/GUI driven app. Allows the user to better manage the personal or work issues.
+
+## Non-Functional Requirements
+
+* Should work on any mainstream OS as long as it has Java 11 or above installed.
+* Should be able to hold up to 1000 task without a noticeable sluggishness in performance for typical usage.
+* A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse
+* Should load from and save to from a text files
+
+
+## Glossary
+
+* *Mainstream OS:* Windows, Linux, Unix, OS-X.
+
+## Instructions for manual testing
+
+### Launch and Shutdown
+
+1. Initial launch
+ 1. Download the jar file and copy into an empty folder
+ 2. Use Command Prompt to run jar file with `java -jar` command.
+ 3. type exit command to exit from the program.
+
+2. Re-launch the app by running `java -jar` command with Command Prompt.
+
+### Adding a todo task
+1. Add the Todo task through following command:
+ 1. Todo {task description here}
+
+### Listing all task in the system
+1. Enter the command
+ 1. List
+2. List of all task in the system will be listed in the order they were created.
+
+### Delete a particular task in the system
+1. Enter the command
+ 1. Delete {index}. Eg: Delete 1
+2. The first Defect will be deleted.
+
+### Load a list of Defects into the progam upon lauch
+1. Program looks for and loads data.txt
+2. If file is not found, no task will be preloaded. Program starts as per normal operation.
+
+### Save a list of task into itlogger.txt upon exit
+1. Saves all task into the data.txt file when user issues any command.
+2. If file does not exist, data.txt will be created.
diff --git a/docs/README.md b/docs/README.md
index fd440695..b889b8e8 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,20 +1,9 @@
-# User Guide
+Duke is an education project.
+This application has a GUI that can allow user to manage task.
-## Features
+NUS TIC4002 iP submission
-### Feature 1
-Description of feature.
+Useful links:
+* [User Guide](UserGuide.md)
+* [Developer Guide](DeveloperGuide.md)
-## Usage
-
-### `Keyword` - Describe action
-
-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 00000000..6c576cb4
Binary files /dev/null and b/docs/Ui.png differ
diff --git a/docs/UserGuide.md b/docs/UserGuide.md
new file mode 100644
index 00000000..854d2eed
--- /dev/null
+++ b/docs/UserGuide.md
@@ -0,0 +1,106 @@
+# User Guide
+
+## Quick Start
+
+1. Ensure you have Java 11 or above installed in your Computer.
+
+1. Download the latest Duke.jar from the release page.
+
+1. Copy the file to the folder you want to use as the home folder for Duke.
+
+1. Double-click the file to start the app.
+
+## Features
+Allows user to add task to Duke and manage a list of pending items.
+
+### Features
+* Adding task to Duke
+ * Adding a simple task
+ * Adding a task with a deadline (date & time)
+ * Adding an event with a deadline (date & time range)
+* Allowing user to mark a task as completed
+* Viewing a list of task
+
+### `Keyword` - Describe action
+
+Keyword |
+------------ |
+```todo``` |
+```deadline``` |
+```event``` |
+```list``` |
+```done``` |
+```delete``` |
+```bye``` |
+```help```|
+
+## Usage
+
+##### ```todo```
+Adds a task to Duke with task description given in ``````.
+##### Usage: ```todo ```
+
+##### Examples:
+* ```todo Buy an iPhone 12 at launch date```
+
+##### ```deadline```
+Adds a task with deadline to Duke with task description given in ``````.
+State completion deadline of the date & the time in ``` ```.
+##### Usage: ```deadline /by ```
+
+##### Examples:
+* ```todo Buy an iPhone 12 at launch date /by 30/10/2020 12pm```
+
+##### ```event```
+Adds an event to Duke with task description given in ``````.
+State event period listing the date & the time period in ``` ```.
+Usage: ```event /at ```
+
+##### Examples:
+* ```event Attend Apple's WWDC /at 12/06/2020 4am```
+
+##### ```list```
+List down all task that are logged in Duke.
+##### Usage: ```list```
+
+##### Examples:
+* ```list```
+
+##### ```done```
+Mark tasks in Duke as completed.
+Usage: ```done ```
+
+##### Examples:
+* ```done 4```
+
+##### ```delete```
+Mark tasks in Duke as completed.
+Usage: ```delete ```
+
+##### Examples:
+* ```delete 4```
+
+##### ```find```
+Loop up all task with a given a word.
+Usage: ```find ```
+
+##### Examples:
+* ```find book```
+
+##### ```help```
+Display the usage guide for Duke command.
+
+##### Examples:
+* ```help```
+
+##### ```bye```
+Exit Duke program.
+##### Usage: ```bye```
+
+##### Examples:
+* ```bye```
+
+## Saving the data
+Data is saved in the hard disk automatically after any command that changes the data. There is no need to save manually.
+
+
diff --git a/docs/_config.yml b/docs/_config.yml
new file mode 100644
index 00000000..c50ff38d
--- /dev/null
+++ b/docs/_config.yml
@@ -0,0 +1 @@
+theme: jekyll-theme-merlot
\ No newline at end of file
diff --git a/docs/images/AddTodoImplementation.jpg b/docs/images/AddTodoImplementation.jpg
new file mode 100644
index 00000000..0ac8b35c
Binary files /dev/null and b/docs/images/AddTodoImplementation.jpg differ
diff --git a/docs/images/CmdComponent.jpg b/docs/images/CmdComponent.jpg
new file mode 100644
index 00000000..98b2c945
Binary files /dev/null and b/docs/images/CmdComponent.jpg differ
diff --git a/docs/images/Duke.jpg b/docs/images/Duke.jpg
new file mode 100644
index 00000000..6513d5d7
Binary files /dev/null and b/docs/images/Duke.jpg differ
diff --git a/docs/images/Interaction.jpg b/docs/images/Interaction.jpg
new file mode 100644
index 00000000..fe048b4b
Binary files /dev/null and b/docs/images/Interaction.jpg differ
diff --git a/docs/images/architecture.jpg b/docs/images/architecture.jpg
new file mode 100644
index 00000000..62a3e98b
Binary files /dev/null and b/docs/images/architecture.jpg differ
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..f3d88b1c
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 00000000..b7c8c5db
--- /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.2-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 00000000..2fe81a7d
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,183 @@
+#!/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 00000000..62bd9b9c
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,103 @@
+@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/src/main/java/Duke.java b/src/main/java/Duke.java
deleted file mode 100644
index 5d313334..00000000
--- a/src/main/java/Duke.java
+++ /dev/null
@@ -1,10 +0,0 @@
-public class Duke {
- public static void main(String[] args) {
- String logo = " ____ _ \n"
- + "| _ \\ _ _| | _____ \n"
- + "| | | | | | | |/ / _ \\\n"
- + "| |_| | |_| | < __/\n"
- + "|____/ \\__,_|_|\\_\\___|\n";
- System.out.println("Hello from\n" + logo);
- }
-}
diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..6e864153
--- /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 00000000..d15059d3
--- /dev/null
+++ b/src/main/java/duke/Duke.java
@@ -0,0 +1,62 @@
+package duke;
+
+import duke.command.CommandHandler;
+import duke.fileManager.FileManager;
+import duke.input.InputHandler;
+import duke.input.InputParser;
+import duke.output.DisplayHandler;
+import duke.storage.ListHandler;
+
+public class Duke {
+ //Instantiate Duke program components
+ private DisplayHandler displayHandler = new DisplayHandler();
+ private InputHandler inputHandler = new InputHandler();
+ private InputParser parser = new InputParser();
+ private ListHandler list = new ListHandler();
+ private CommandHandler command = new CommandHandler();
+ private FileManager fileManager = new FileManager("data.txt");
+
+ /**
+ * Display the opening statement of DUKE
+ */
+ public String displayProgramOpening() {
+ return displayHandler.programOpening();
+ }
+
+ public String readDataFile() {
+ return fileManager.readFile(list);
+ }
+
+ /**
+ * Contains the main logic to run Duke
+ */
+ public String runLogic(String input) {
+
+ String result = "";
+
+ // Parse User input
+ String keyWord = parser.extractKeyWord(input);
+ String body = parser.extractKeyWordBody(input, keyWord);
+
+ // If input is not recognised Keyword
+ if (parser.checkIfKeyWord(keyWord) == false) {
+ result = displayHandler.displayInvalidInput();
+ }
+ // Else if input is a recognised Keyword
+ else {
+ result = command.checkCommandType(keyWord, body, list);
+ }
+
+ fileManager.saveFile(list.getList());
+
+ return result;
+ }
+
+ /**
+ * You should have your own function to generate a response to user input.
+ * Replace this stub with your completed method.
+ */
+ public String getResponse(String input) {
+ return "Duke: " + input;
+ }
+}
diff --git a/src/main/java/duke/Launcher.java b/src/main/java/duke/Launcher.java
new file mode 100644
index 00000000..e4ef6b46
--- /dev/null
+++ b/src/main/java/duke/Launcher.java
@@ -0,0 +1,12 @@
+package duke;
+
+import javafx.application.Application;
+
+/**
+ * A launcher class to workaround classpath issues.
+ */
+public class Launcher {
+ public static void main(String[] args) {
+ 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 00000000..cdb87855
--- /dev/null
+++ b/src/main/java/duke/Main.java
@@ -0,0 +1,33 @@
+package duke;
+
+import java.io.IOException;
+
+import duke.userInterface.MainWindow;
+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 {
+
+ private Duke duke = new Duke();
+
+ @Override
+ public void start(Stage stage) {
+ try {
+ FXMLLoader fxmlLoader = new FXMLLoader(Main.class.getResource("/view/MainWindow.fxml"));
+ AnchorPane ap = fxmlLoader.load();
+ Scene scene = new Scene(ap);
+ stage.setScene(scene);
+ fxmlLoader.getController().setDuke(duke);
+ stage.show();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/duke/command/CommandHandler.java b/src/main/java/duke/command/CommandHandler.java
new file mode 100644
index 00000000..71213eb0
--- /dev/null
+++ b/src/main/java/duke/command/CommandHandler.java
@@ -0,0 +1,98 @@
+package duke.command;
+
+import duke.exception.IncorrectInputException;
+import duke.input.InputParser;
+import duke.output.DisplayHandler;
+import duke.search.TaskFinder;
+import duke.storage.ListHandler;
+import duke.task.Task;
+
+/**
+ * Handles all commands that user will input
+ * Commands are listed in the switch-case statement
+ */
+public class CommandHandler {
+
+ private DisplayHandler displayHandler = new DisplayHandler();
+ private InputParser inputParser = new InputParser();
+
+ /**
+ * Used to handles the different behaviors of the respective commands
+ * @param KeyWord Command for duke
+ * @param Body User task input
+ * @param List contains the list of user Tasks
+ */
+ public String checkCommandType(String KeyWord, String Body, ListHandler List) {
+
+ keyword keyword = duke.command.keyword.valueOf(KeyWord.toUpperCase());
+ String output = "";
+
+ try {
+ switch(keyword) {
+ case TODO:
+ String todoBody = inputParser.extractTodoBody(Body);
+ List.addToDo(todoBody);
+ Task todoTaskAdded = (Task) List.getList().lastElement();
+ output = displayHandler.showTaskAdded(List.getList().size(), todoTaskAdded);
+ break;
+
+ case DEADLINE:
+ String deadlineBody = inputParser.extractDeadlineBody(Body);
+ String deadlineByDate = inputParser.extractDeadlineByDay(Body);
+ String deadlineByTime = inputParser.extractDeadlineByTime(Body);
+ List.addDeadline(deadlineBody, deadlineByDate, deadlineByTime);
+ Task deadlineTaskAdded = (Task) List.getList().lastElement();
+ output = displayHandler.showTaskAdded(List.getList().size(), deadlineTaskAdded);
+ break;
+
+ case EVENT:
+ String eventBody = inputParser.extractEventBody(Body);
+ String eventDay = inputParser.extractEventAtDay(Body);;
+ String eventTime = inputParser.extractEventAtTime(Body);
+ List.addEvent(eventBody, eventDay, eventTime);
+ Task EventTaskAdded = (Task) List.getList().lastElement();
+ output = displayHandler.showTaskAdded(List.getList().size(), EventTaskAdded);
+ break;
+
+ case LIST:
+ output = displayHandler.displayList(List.getList());
+ break;
+
+ case DONE:
+ Task taskDone = List.updateListItem(Body);
+ output = displayHandler.displayChanges(taskDone);
+ break;
+
+ case DELETE:
+ Task taskDeleted = List.deleteListItem(Body);
+ output = displayHandler.displayDeleteResult(List.getList().size(), taskDeleted);
+ break;
+
+ case FIND:
+ output = TaskFinder.findTask(Body, List.getList());
+ break;
+
+ case HELP:
+ output = displayHandler.displayHelp();
+ break;
+ case BYE:
+ output = displayHandler.programEnding();
+ System.exit(0);
+ break;
+
+ default:
+ break;
+ }
+
+ } catch (Exception e) {
+ if (e instanceof IncorrectInputException) {
+ output = displayHandler.displayCustomException(e);
+ }
+ else {
+ output = displayHandler.displayInvalidInput();
+ }
+ }
+
+ return output;
+ }
+}
diff --git a/src/main/java/duke/command/keyword.java b/src/main/java/duke/command/keyword.java
new file mode 100644
index 00000000..5e2bd52b
--- /dev/null
+++ b/src/main/java/duke/command/keyword.java
@@ -0,0 +1,18 @@
+package duke.command;
+
+/**
+ * Stores all KeyWords
+ * Used by Duke to perform differing actions
+ */
+public enum keyword {
+ TODO,
+ DEADLINE,
+ EVENT,
+ LIST,
+ DONE,
+ DELETE,
+ FIND,
+ BYE,
+ HELP
+}
+
diff --git a/src/main/java/duke/exception/IncorrectInputException.java b/src/main/java/duke/exception/IncorrectInputException.java
new file mode 100644
index 00000000..47efcbb4
--- /dev/null
+++ b/src/main/java/duke/exception/IncorrectInputException.java
@@ -0,0 +1,12 @@
+package duke.exception;
+
+/**
+ * Custom error message
+ * Handles user input issues
+ * Used when performing String manipulation
+ */
+public class IncorrectInputException extends Exception {
+ public IncorrectInputException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/duke/fileManager/FileManager.java b/src/main/java/duke/fileManager/FileManager.java
new file mode 100644
index 00000000..4a910fae
--- /dev/null
+++ b/src/main/java/duke/fileManager/FileManager.java
@@ -0,0 +1,200 @@
+package duke.fileManager;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.Vector;
+
+import duke.output.DisplayHandler;
+import duke.storage.ListHandler;
+import duke.task.Task;
+
+public class FileManager {
+
+ protected String fileName;
+ protected File dataFile;
+ protected String filePath;
+
+ public FileManager(String fileName) {
+ this.fileName = fileName;
+ }
+
+ /**
+ * Read the file and load data into duke
+ * @param list the list to be populated
+ * @return the result of the file loading
+ */
+ public String readFile(ListHandler list) {
+ // Check if file exists
+ dataFile = new File(fileName);
+
+ // Read file format and load it in Duke
+ try {
+ BufferedReader br = new BufferedReader(new FileReader(dataFile));
+ String eachLineOfFile;
+ while ((eachLineOfFile = br.readLine()) != null) {
+ // Parse File Data & Insert to Duke
+ insertFileContent(list, eachLineOfFile);
+ }
+
+ } catch (FileNotFoundException e) {
+ DisplayHandler.fileNotFound(e.getMessage());
+ } catch (IOException e) {
+ DisplayHandler.cannotReadFile(e.getMessage());
+ }
+
+ return "Reading data from: " + dataFile.getAbsolutePath(); // debug statement
+ }
+
+ private void insertFileContent(ListHandler list, String eachLineOfFile) {
+ String[] eachLineContent = eachLineOfFile.split(" ");
+
+ checkTaskType(list, eachLineContent);
+ }
+
+ private void checkTaskType(ListHandler list, String[] eachLineContent) {
+ String taskType = eachLineContent[0];
+ taskType = taskType.trim();
+
+ switch(taskType) {
+ case "[T]":
+ insertTodo(list, eachLineContent);
+ break;
+
+ case "[D]":
+ insertDeadline(list, eachLineContent);
+ break;
+
+ case "[E]":
+ insertEvent(list, eachLineContent);
+ break;
+
+ default:
+ DisplayHandler.encounterWrongFormat();
+ }
+ }
+
+ private void insertTodo(ListHandler list, String[] eachLineContent) {
+ String doneStatus = eachLineContent[1];
+ int begin = 2;
+ int end = eachLineContent.length - 1;
+ String[] todoBody = new String[ (end + 1) - begin];
+ System.arraycopy(eachLineContent, begin, todoBody, 0, todoBody.length);
+ list.addToDo(convertArrayToString(todoBody));
+
+ if (doneStatus.equals("[✓]")) {
+ Vector List = list.getList();
+ Task justInserted = (Task) List.lastElement();
+ justInserted.markAsDone();
+ }
+ }
+
+ private void insertDeadline(ListHandler list, String[] eachLineContent) {
+ String doneStatus = eachLineContent[1];
+ int begin = 2;
+ int end = eachLineContent.length - 4;
+ String[] deadlineBody = new String[ (end + 1) - begin];
+ System.arraycopy(eachLineContent, begin, deadlineBody, 0, deadlineBody.length);
+ String deadlineDate = getDateContent(eachLineContent);
+ String deadlineTime = getTimeContent(eachLineContent);
+ list.addDeadline(convertArrayToString(deadlineBody), deadlineDate, deadlineTime);
+
+ if (doneStatus.equals("[✓]")) {
+ Vector List = list.getList();
+ Task justInserted = (Task) List.lastElement();
+ justInserted.markAsDone();
+ }
+ }
+
+ private void insertEvent(ListHandler list, String[] eachLineContent) {
+ String doneStatus = eachLineContent[1];
+ int begin = 2;
+ int end = eachLineContent.length - 4;
+ String[] eventBody = new String[ (end + 1) - begin];
+ System.arraycopy(eachLineContent, begin, eventBody, 0, eventBody.length);
+ String eventDate = getDateContent(eachLineContent);
+ String eventTime = getTimeContent(eachLineContent);
+ list.addEvent(convertArrayToString(eventBody), eventDate, eventTime);
+
+ if (doneStatus.equals("[✓]")) {
+ Vector List = list.getList();
+ Task justInserted = (Task) List.lastElement();
+ justInserted.markAsDone();
+ }
+ }
+
+ private String getDateContent(String[] eachLineContent) {
+ String date = eachLineContent[eachLineContent.length - 2];
+ return date;
+ }
+
+ private String getTimeContent(String[] eachLineContent) {
+ String time = eachLineContent[eachLineContent.length - 1];
+ time = charRemoveAt(time, time.length() - 1);
+ return time;
+ }
+
+ public static String charRemoveAt(String str, int p) {
+ return str.substring(0, p) + str.substring(p + 1);
+ }
+
+ private String convertArrayToString(String[] array) {
+ StringBuilder builder = new StringBuilder();
+ for (String value : array) {
+ builder.append(" " + value);
+ }
+ builder.append(" ");
+ return builder.toString();
+ }
+
+ /**
+ * Store all task in duke as a data file
+ * @param ListStorage data to be stored in file
+ */
+ public void saveFile(Vector ListStorage) {
+
+ dataFile = createFile();
+ Iterator dukeTask = ListStorage.iterator();
+ clearFileContent();
+
+ while (dukeTask.hasNext()) {
+ try {
+ Task toBeStored = (Task) dukeTask.next(); // Read the Tasks from Duke
+ writeToFile(toBeStored.toString()); // Write Tasks to File
+
+ } catch (IOException e) {
+ DisplayHandler.writeFileError(e.getMessage());
+ }
+ }
+ }
+
+ private File createFile() {
+ File createdFile = new File(fileName);
+ filePath = createdFile.getAbsolutePath();
+ DisplayHandler.createdFile(createdFile.getAbsolutePath()); // debug statement
+
+ return createdFile;
+ }
+
+ private void writeToFile(String textToAppend) throws IOException {
+ FileWriter fw = new FileWriter(fileName, true);
+ fw.write(textToAppend + "\n");
+ fw.close();
+ }
+
+ private void clearFileContent() {
+ try {
+ PrintWriter writer = new PrintWriter(dataFile);
+ writer.print("");
+ writer.close();
+
+ } catch (FileNotFoundException e) {
+ DisplayHandler.clearFileFailure(e.getMessage());
+ }
+ }
+}
diff --git a/src/main/java/duke/input/InputHandler.java b/src/main/java/duke/input/InputHandler.java
new file mode 100644
index 00000000..c0e44e55
--- /dev/null
+++ b/src/main/java/duke/input/InputHandler.java
@@ -0,0 +1,20 @@
+package duke.input;
+
+import java.util.Scanner;
+
+/**
+ * Used to obtain user input from Input Stream
+ */
+public class InputHandler {
+
+ private static Scanner fromInputStream = new Scanner(System.in);
+
+ /**
+ * Used to get user input
+ * @return a line of user input e.g. todo Birthday Celebration
+ */
+ public String getUserInput() {
+ String command = fromInputStream.nextLine();
+ return command;
+ }
+}
diff --git a/src/main/java/duke/input/InputParser.java b/src/main/java/duke/input/InputParser.java
new file mode 100644
index 00000000..09a2dd3a
--- /dev/null
+++ b/src/main/java/duke/input/InputParser.java
@@ -0,0 +1,200 @@
+package duke.input;
+import duke.command.keyword;
+import duke.exception.IncorrectInputException;
+import duke.output.DisplayHandler;
+
+/**
+ * Handles and transform user input
+ * Turns input into format accepted by DUKE
+ */
+public class InputParser {
+
+ /**
+ * Determine if user entered a Task
+ * @param input value to be checked
+ * @return returns true if keyword, false otherwise
+ */
+ public boolean checkIfKeyWord(String input) {
+
+ try {
+ keyword.valueOf(input.toUpperCase());
+ return true;
+
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Get Task keyWord from user input line
+ * @param input value to be parsed
+ * @return return keyword from @param input
+ */
+ public String extractKeyWord(String input) {
+ String[] Array = input.split(" ");
+ return Array[0];
+ }
+
+ /**
+ * Get Task body from user's input
+ * @param input full line of user input
+ * @param keyword keyword of user
+ * @return return extracted body
+ */
+ public String extractKeyWordBody(String input, String keyword) {
+ try {
+ return input.replaceFirst(keyword, "");
+
+ } catch (ArrayIndexOutOfBoundsException e) { // May not be used anymore
+ return null;
+ }
+ }
+
+ /**
+ * Extract body from Todo
+ * @param todoInput take input line from a todo
+ * @return extracted body
+ * @throws IncorrectInputException for wrong input format
+ */
+ public String extractTodoBody(String todoInput) throws IncorrectInputException {
+ if (todoInput.isEmpty()) {
+ throw new IncorrectInputException(DisplayHandler.EMPTY_TODO);
+ }
+ return todoInput;
+ }
+
+ /**
+ * Get the body of the deadline from user input
+ * @param deadlineInput the full user input for deadline
+ * @return the deadline task
+ * @throws IncorrectInputException if input does not follow duke format
+ */
+ public String extractDeadlineBody(String deadlineInput) throws IncorrectInputException {
+ String result = "";
+ try {
+ int indx = deadlineInput.indexOf("/by");
+ result = deadlineInput.substring(0, indx);
+
+ } catch (Exception e) {
+ if (result.length() < 1) {
+ throw new IncorrectInputException(DisplayHandler.EMPTY_DEADLINE_DESC);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Get deadline input "day" field
+ * @param deadlineInput full user input for deadline
+ * @return the day
+ * @throws IncorrectInputException if input does not follow duke format
+ */
+ public String extractDeadlineByDay(String deadlineInput) throws IncorrectInputException {
+ String day = "";
+ try {
+ int indx = deadlineInput.indexOf("/by");
+ String by = deadlineInput.substring(indx, deadlineInput.length());
+ String[] array = by.split(" ");
+ day = array[1];
+ return day;
+
+ } catch (Exception e) {
+ if (day.length() < 1) {
+ throw new IncorrectInputException(DisplayHandler.EMPTY_DEADLINE_DAY);
+ }
+ }
+
+ return day;
+ }
+
+ /**
+ * Get the deadline input time field
+ * @param deadlineInput full user input for deadline
+ * @return the time field
+ * @throws IncorrectInputException if it does not follow duke format
+ */
+ public String extractDeadlineByTime(String deadlineInput) throws IncorrectInputException {
+ String time = "";
+ try {
+ int indx = deadlineInput.indexOf("/by");
+ String by = deadlineInput.substring(indx);
+ String[] array = by.split(" ");
+ time = array[2];
+
+ } catch (Exception e) {
+ if (time.length() < 1) {
+ throw new IncorrectInputException(DisplayHandler.EMPTY_DEADLINE_TIME);
+ }
+ }
+
+ return time;
+ }
+
+ /**
+ * Get the body of the Event from user input
+ * @param eventInput the full input of the event
+ * @return the event body field
+ * @throws IncorrectInputException if it does not follow duke format
+ */
+ public String extractEventBody(String eventInput) throws IncorrectInputException {
+ String result = "";
+
+ try {
+ int indx = eventInput.indexOf("/at");
+ result = eventInput.substring(0, indx);
+
+ } catch (Exception e) {
+ if (result.length() < 1) {
+ throw new IncorrectInputException(DisplayHandler.EMPTY_EVENT_DESC);
+ }
+ }
+
+ return result;
+ }
+ /**
+ * Get the day of the Event from user input
+ * @param eventInput the full input of the event
+ * @return the event day field
+ * @throws IncorrectInputException if it does not follow duke format
+ */
+ public String extractEventAtDay(String eventInput) throws IncorrectInputException {
+ String day = "";
+
+ try {
+ int indx = eventInput.indexOf("/at");
+ String by = eventInput.substring(indx, eventInput.length());
+ String[] array = by.split(" ");
+ day = array[1];
+
+ } catch (Exception e) {
+ if (day.length() < 1) {
+ throw new IncorrectInputException(DisplayHandler.EMPTY_EVENT_DAY);
+ }
+ }
+ return day;
+ }
+
+ /**
+ * Get the time of the Event from user input
+ * @param eventInput the full input of the event
+ * @return the event time field
+ * @throws IncorrectInputException if it does not follow duke format
+ */
+ public String extractEventAtTime(String eventInput) throws IncorrectInputException {
+ String time = "";
+
+ try {
+ int indx = eventInput.indexOf("/at");
+ String by = eventInput.substring(indx);
+ String[] array = by.split(" ");
+ time = array[2];
+
+ } catch (Exception e) {
+ if (time.length() < 1) {
+ throw new IncorrectInputException(DisplayHandler.EMPTY_EVENT_TIME);
+ }
+ }
+
+ return time;
+ }
+}
diff --git a/src/main/java/duke/output/DisplayHandler.java b/src/main/java/duke/output/DisplayHandler.java
new file mode 100644
index 00000000..890dc3a6
--- /dev/null
+++ b/src/main/java/duke/output/DisplayHandler.java
@@ -0,0 +1,212 @@
+package duke.output;
+
+import java.util.Iterator;
+import java.util.Vector;
+
+import duke.task.Task;
+
+public class DisplayHandler {
+
+ public static final String EMPTY_TODO = " OOPS!!! The description of a todo cannot be empty";
+ public static final String EMPTY_DEADLINE_DESC = " OOPS!!! The description of a duke Deadline "
+ + "cannot be empty & must be accompanied by Date and Time";
+ public static final String EMPTY_DEADLINE_DAY = " OOPS!!! The description of duke's Deadline Day cannot be empty";
+ public static final String EMPTY_DEADLINE_TIME = " OOPS!!! The description of duke's Deadline Time cannot be empty";
+ public static final String EMPTY_EVENT_DESC = " OOPS!!! The description of a duke Event "
+ + "cannot be empty & must be accompanied by Date and Time Range";
+ public static final String EMPTY_EVENT_DAY = " OOPS!!! The description of a duke's Event Day cannot be empty";
+ public static final String EMPTY_EVENT_TIME = " OOPS!!! The description of a duke's Event Time cannot be empty";
+ public static final String FILE_NOT_EXISTS = "File does not exists yet : ";
+ public static final String FILE_CANNOT_BE_READ = "File cannot be read : ";
+ public static final String UNRECOGNISED_TEXT_FORMAT = "There is a unrecognised text format in DUKE data file";
+ public static final String WRITE_FILE_ERROR = "Error writing to file: ";
+ public static final String CREATED_FILE_SUCCESS = "Created/Updated data file at: ";
+ public static final String CLEAR_FILE_ERROR = "Unable to clear file content: ";
+ public static final String WRONG_COMMAND = "OOPS!!! No such command exists";
+
+ private final String logoIcon = " ____ _ \n"
+ + "| _ \\ _ _| | _____ \n"
+ + "| | | | | | | |/ / _ \\\n"
+ + "| |_| | |_| | < __/\n"
+ + "|____/ \\__,_|_|\\_\\___|\n";
+
+ private final String greetingMsg = " Hello! I'm duke.Duke\n What can I do for you?";
+ private final String successMsg = " Got it. I've added this task: ";
+ private final String listMsg = " Here are the tasks in your list:";
+ private final String doneMsg = " Nice! I've marked this task as done: ";
+ private final String invalidInputMsg = " OOPS!!! I'm sorry, but I don't know what that means :-(";
+ private final String deleteTask = " Noted. I've removed this task:";
+ private final String goodbyeMsg = " Bye. Hope to see you again soon!";
+ private final String lineDivider = "----------------------------------------";
+
+ public static void clearFileFailure(String errorMsg) {
+ System.out.println(CLEAR_FILE_ERROR + errorMsg);
+ }
+
+ public static void createdFile(String fileAbsolutePath) {
+ System.out.println(CREATED_FILE_SUCCESS + fileAbsolutePath);
+ }
+
+ public static void writeFileError(String errorMsg) {
+ System.out.println(WRITE_FILE_ERROR + errorMsg);
+ }
+
+ public static void encounterWrongFormat() {
+ System.out.println(UNRECOGNISED_TEXT_FORMAT);
+ }
+
+ public static void cannotReadFile(String errorMsg) {
+ System.out.println(FILE_CANNOT_BE_READ + errorMsg);
+ }
+
+ public static void fileNotFound(String errorMsg) {
+ System.out.println(FILE_NOT_EXISTS + errorMsg);
+ }
+
+ private void greeter() {
+ System.out.println(greetingMsg);
+ }
+
+ private String goodbye() {
+ return goodbyeMsg;
+ }
+
+ private String divider() {
+ return (lineDivider);
+ }
+
+ private void logo() {
+ System.out.println(logoIcon);
+ }
+
+ private void success() {
+ System.out.println(successMsg);
+ }
+
+ private String invalidInput() {
+ return invalidInputMsg;
+ }
+
+ private String showListMsg() {
+ return listMsg;
+ }
+
+ public String displayNumAddedTask(int listNum) {
+ return "Now you have " + listNum + " task in the list";
+ }
+
+ public String done() {
+ return doneMsg;
+ }
+
+ public String printDeleteMsg() {
+ return deleteTask;
+ }
+
+ public String displayIndividualTask(Task task) {
+ return " " + task;
+ }
+
+ private String listResult(Vector result) {
+
+ String output = "";
+ output = output + showListMsg() + '\n';
+ Iterator iter = result.iterator();
+
+ for (int i = 0; iter.hasNext(); i++) {
+ int currIndex = i + 1;
+ Task element = (Task) iter.next();
+ output = output + " " + currIndex + "." + element + '\n';
+ }
+
+ return output;
+ }
+
+ public String displayInvalidInput() {
+ return invalidInputMsg;
+ }
+
+ /**
+ * Output the new state of the task that was updated
+ * @param task to be updated
+ * @return result of the update
+ */
+ public String displayChanges(Task task) {
+
+ try {
+ task.getStatusIcon(); // check if exception will be thrown, this line has no functional usage
+ return lineDivider + '\n' + done() + task + '\n' + lineDivider;
+
+ } catch (NullPointerException e) {
+ return invalidInput();
+ }
+
+ }
+
+ /**
+ * Output the result of the deletion
+ * @param ListNum ID of the deletion
+ * @param task the task to be deleted
+ * @return result of the deletion
+ */
+ public String displayDeleteResult(int ListNum, Task task) {
+ try {
+ task.getStatusIcon(); // check if exception will be thrown, this line has no functional usage
+ return lineDivider + '\n'
+ + printDeleteMsg()
+ + task + '\n'
+ + displayNumAddedTask(ListNum)
+ + '\n' + lineDivider;
+ } catch (NullPointerException e) {
+ return invalidInput();
+ }
+ }
+
+ public String displayList(Vector result) {
+ return '\n' + lineDivider + '\n' + listResult(result) + '\n' + lineDivider;
+ }
+
+ /**
+ * Display the task that was added to duke
+ * @param ListNum ID of new task
+ * @param task task data
+ * @return the result of the added task
+ */
+ public String showTaskAdded(int ListNum, Task task) {
+ return '\n'
+ + lineDivider
+ + '\n'
+ + successMsg
+ + displayIndividualTask(task)
+ + '\n'
+ + displayNumAddedTask(ListNum)
+ + '\n' + lineDivider;
+ }
+
+ public String programOpening() {
+ return '\n' + lineDivider + '\n' + logoIcon + '\n' + greetingMsg + '\n' + lineDivider;
+ }
+
+ public String programEnding() {
+ return '\n' + lineDivider + '\n' + goodbye() + '\n' + lineDivider;
+ }
+
+ public String displayCustomException(Exception e) {
+ return e.getMessage();
+ }
+
+ /**
+ * Display Help guide to user
+ * @return list of command usage details
+ */
+ public String displayHelp() {
+ return "TODO : todo "
+ + " \n DEADLINE: deadline /by "
+ + " \n EVENT: event /at "
+ + " \n LIST: list"
+ + " \n DONE: done "
+ + " \n DELETE: delete "
+ + " \n FIND: find "
+ + " \n BYE: bye";
+ }
+}
diff --git a/src/main/java/duke/search/TaskFinder.java b/src/main/java/duke/search/TaskFinder.java
new file mode 100644
index 00000000..09e0644c
--- /dev/null
+++ b/src/main/java/duke/search/TaskFinder.java
@@ -0,0 +1,38 @@
+package duke.search;
+
+import java.util.Iterator;
+import java.util.Vector;
+
+import duke.task.Task;
+
+public class TaskFinder {
+ /**
+ * Find task in Duke list
+ * @param searchTerm string to search for
+ * @param taskList the task List to be searched
+ * @return the task found
+ */
+ @SuppressWarnings("checkstyle:Regexp")
+ public static String findTask(String searchTerm , Vector taskList) {
+ Iterator taskIter = taskList.iterator();
+ String output;
+
+ output = "----------------------------------------" + '\n';
+ output = output + "Here are the matching tasks in your list:" + '\n';
+
+ for (int i = 0; taskIter.hasNext(); i++) {
+ Task currTask = (Task) taskIter.next();
+ String currTaskDesc = currTask.getTaskDescription();
+
+ if (currTaskDesc.contains(searchTerm)) {
+ //System.out.println(i+1 + "." + currTask);
+ int indx = i + 1;
+ output = output + indx + "." + currTask + '\n';
+ }
+ }
+
+ output = output + "----------------------------------------" + '\n';
+
+ return output;
+ }
+}
diff --git a/src/main/java/duke/storage/ListHandler.java b/src/main/java/duke/storage/ListHandler.java
new file mode 100644
index 00000000..07eb1cc2
--- /dev/null
+++ b/src/main/java/duke/storage/ListHandler.java
@@ -0,0 +1,67 @@
+package duke.storage;
+
+import java.util.Vector;
+
+import duke.task.Deadline;
+import duke.task.Event;
+import duke.task.Task;
+import duke.task.Todo;
+
+public class ListHandler {
+
+ private Vector ListStorage = new Vector();
+
+ public void addToDo(String body) {
+ ListStorage.add(new Todo(body));
+ }
+
+ public void addDeadline(String body, String by, String time) {
+ ListStorage.add(new Deadline(body, by, time));
+ }
+
+ public void addEvent(String body, String at, String timePeriod) {
+ ListStorage.add(new Event(body, at, timePeriod));
+ }
+
+ public Vector getList() {
+ return ListStorage;
+ }
+
+ /**
+ * Update the task in list by index
+ * @param index the identifier for the task
+ * @return return updated task if sucessful NULL otherwise
+ */
+ public Task updateListItem(String index) {
+ try {
+ int idx = Integer.parseInt(index.trim());
+ Task task = (Task) ListStorage.get(idx - 1);
+ task.markAsDone();
+ return task;
+ } catch (NumberFormatException e) {
+ // Do nothing
+ } catch (ArrayIndexOutOfBoundsException e) {
+ // Do nothing
+ }
+
+ return null;
+ }
+
+ /**
+ * Delete a task based on index from task list
+ * @param index the identifier for the task
+ * @return
+ */
+ public Task deleteListItem(String index) {
+ try {
+ int idx = Integer.parseInt(index.trim());
+ Task task = (Task) ListStorage.remove(idx - 1);
+ return task;
+
+ } catch (Exception e) {
+ // Do nothing
+ }
+
+ return null;
+ }
+}
diff --git a/src/main/java/duke/task/Deadline.java b/src/main/java/duke/task/Deadline.java
new file mode 100644
index 00000000..1195723a
--- /dev/null
+++ b/src/main/java/duke/task/Deadline.java
@@ -0,0 +1,23 @@
+package duke.task;
+
+public class Deadline extends Task {
+ protected String by;
+ protected String time;
+
+ /**
+ * constructor for the deadline
+ * @param description describe the deadline task
+ * @param by when it must be completed
+ * @param time time it must be completed
+ */
+ public Deadline(String description, String by, String time) {
+ super(description);
+ this.by = by;
+ this.time = time;
+ }
+
+ @Override
+ public String toString() {
+ return "[D] " + super.toString() + "(by: " + by + " " + time + ")";
+ }
+}
diff --git a/src/main/java/duke/task/Event.java b/src/main/java/duke/task/Event.java
new file mode 100644
index 00000000..90eb6f94
--- /dev/null
+++ b/src/main/java/duke/task/Event.java
@@ -0,0 +1,22 @@
+package duke.task;
+
+public class Event extends Task {
+ protected String at;
+ protected String timePeriod;
+ /**
+ * Constructor for the Event task
+ * @param description describe the event task
+ * @param at which date the event takes place
+ * @param timePeriod the start till end time of the event
+ */
+ public Event(String description, String at, String timePeriod) {
+ super(description);
+ this.at = at;
+ this.timePeriod = timePeriod;
+ }
+ @Override
+ public String toString() {
+ return "[E] " + super.toString() + "(at: " + at + " " + timePeriod + ")";
+ }
+}
+
diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java
new file mode 100644
index 00000000..8cf37132
--- /dev/null
+++ b/src/main/java/duke/task/Task.java
@@ -0,0 +1,32 @@
+package duke.task;
+
+public abstract class Task {
+ protected String description;
+ protected boolean isDone;
+
+ /**
+ * Constructor for the Task
+ * @param description describe the task to be done
+ */
+ public Task(String description) {
+ this.description = description;
+ this.isDone = false;
+ }
+
+ public String getStatusIcon() {
+ return (isDone ? "\u2713" : "\u2718"); //return tick or X symbols
+ }
+
+ public String getTaskDescription() {
+ return description;
+ }
+
+ public void markAsDone() {
+ isDone = !isDone;
+ }
+
+ @Override
+ public String toString() {
+ return "[" + getStatusIcon() + "]" + "" + getTaskDescription();
+ }
+}
diff --git a/src/main/java/duke/task/Todo.java b/src/main/java/duke/task/Todo.java
new file mode 100644
index 00000000..b439aa4b
--- /dev/null
+++ b/src/main/java/duke/task/Todo.java
@@ -0,0 +1,13 @@
+package duke.task;
+
+public class Todo extends Task {
+
+ public Todo(String description) {
+ super(description);
+ }
+
+ @Override
+ public String toString() {
+ return "[T] " + super.toString();
+ }
+}
diff --git a/src/main/java/duke/userInterface/DialogBox.java b/src/main/java/duke/userInterface/DialogBox.java
new file mode 100644
index 00000000..4bbc35dd
--- /dev/null
+++ b/src/main/java/duke/userInterface/DialogBox.java
@@ -0,0 +1,61 @@
+package duke.userInterface;
+
+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 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);
+ }
+
+ public static DialogBox getUserDialog(String text, Image img) {
+ return new DialogBox(text, img);
+ }
+
+ public static DialogBox getDukeDialog(String text, Image img) {
+ var db = new DialogBox(text, img);
+ db.flip();
+ return db;
+ }
+}
diff --git a/src/main/java/duke/userInterface/MainWindow.java b/src/main/java/duke/userInterface/MainWindow.java
new file mode 100644
index 00000000..82c630a0
--- /dev/null
+++ b/src/main/java/duke/userInterface/MainWindow.java
@@ -0,0 +1,87 @@
+package duke.userInterface;
+
+import duke.Duke;
+import javafx.fxml.FXML;
+import javafx.scene.control.Button;
+import javafx.scene.control.ScrollPane;
+import javafx.scene.control.TextField;
+import javafx.scene.image.Image;
+import javafx.scene.layout.AnchorPane;
+import javafx.scene.layout.VBox;
+/**
+ * Controller for MainWindow. Provides the layout for the other controls.
+ */
+public class MainWindow extends AnchorPane {
+ @FXML
+ private ScrollPane scrollPane;
+ @FXML
+ private VBox dialogContainer;
+ @FXML
+ private TextField userInput;
+ @FXML
+ private Button sendButton;
+
+ private Duke duke;
+
+ private Image userImage = new Image(this.getClass().getResourceAsStream("/images/DaUser.png"));
+ private Image dukeImage = new Image(this.getClass().getResourceAsStream("/images/DaDuke.png"));
+
+ @FXML
+ public void initialize() {
+ scrollPane.vvalueProperty().bind(dialogContainer.heightProperty());
+ }
+
+ public void setDuke(Duke d) {
+ duke = d;
+ startDuke();
+ }
+
+ private void startDuke() {
+ displayDukeResponse(duke.displayProgramOpening());
+ displayDukeResponse(duke.readDataFile());
+ }
+
+ /**
+ * 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() {
+
+ // Get and display user input
+ String input = getInput();
+ displayUserInput(input);
+
+ String dukeResponse = duke.runLogic(input);
+ //System.out.println(dukeResponse);
+ displayDukeResponse(dukeResponse);
+
+ userInput.clear();
+ }
+
+ private String getInput() {
+ return userInput.getText();
+ }
+
+ /**
+ * Creates dialog boxes containing Duke's reply and then appends them to
+ * the dialog container.
+ */
+ private void displayDukeResponse(String response) {
+ String dukeText = duke.getResponse(response);
+ dialogContainer.getChildren().addAll(
+ DialogBox.getDukeDialog(dukeText, dukeImage)
+ );
+ }
+
+ /**
+ * Creates dialog boxes containing User's Input and then appends them to
+ * the dialog container.
+ */
+ private void displayUserInput(String input) {
+ String userText = input;
+ dialogContainer.getChildren().addAll(
+ DialogBox.getUserDialog(userText, userImage)
+ );
+ }
+}
diff --git a/src/main/resources/images/DaDuke.png b/src/main/resources/images/DaDuke.png
new file mode 100644
index 00000000..d8936587
Binary files /dev/null and b/src/main/resources/images/DaDuke.png differ
diff --git a/src/main/resources/images/DaUser.png b/src/main/resources/images/DaUser.png
new file mode 100644
index 00000000..3c82f454
Binary files /dev/null and b/src/main/resources/images/DaUser.png differ
diff --git a/src/main/resources/view/DialogBox.fxml b/src/main/resources/view/DialogBox.fxml
new file mode 100644
index 00000000..3048b5a2
--- /dev/null
+++ b/src/main/resources/view/DialogBox.fxml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml
new file mode 100644
index 00000000..cb20ea1a
--- /dev/null
+++ b/src/main/resources/view/MainWindow.fxml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/java/inputParser/InputParserTest.java b/src/test/java/inputParser/InputParserTest.java
new file mode 100644
index 00000000..836b8b77
--- /dev/null
+++ b/src/test/java/inputParser/InputParserTest.java
@@ -0,0 +1,48 @@
+package inputParser;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.junit.jupiter.api.Test;
+
+import duke.exception.IncorrectInputException;
+import duke.input.InputParser;
+
+public class InputParserTest {
+
+ @Test
+ public void testKeywordChecker() {
+ String keywordStub = "Hello There";
+
+ InputParser inputParser = new InputParser();
+ boolean result = inputParser.checkIfKeyWord(keywordStub);
+
+ assertEquals(result, false);
+ }
+
+ @Test
+ public void testKeywordExtraction() {
+ String inputStub = "todo Buy groceries from NTUC";
+
+ InputParser inputParser = new InputParser();
+ String result = inputParser.extractKeyWord(inputStub);
+
+ assertEquals(result, "todo");
+ }
+
+ @Test
+ public void testDeadlineBodyExtraction() {
+ String inputStub = "Read book /by 20/12/20 6pm";
+
+ InputParser inputParser = new InputParser();
+ String result = "";
+
+ try {
+ result = inputParser.extractDeadlineBody(inputStub);
+ } catch (IncorrectInputException e) {
+ fail();
+ }
+
+ assertEquals(result, "Read book ");
+ }
+}
diff --git a/src/test/java/listHandler/ListHandlerTest.java b/src/test/java/listHandler/ListHandlerTest.java
new file mode 100644
index 00000000..9f32c63c
--- /dev/null
+++ b/src/test/java/listHandler/ListHandlerTest.java
@@ -0,0 +1,41 @@
+package listHandler;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Vector;
+
+import org.junit.jupiter.api.Test;
+
+import duke.storage.ListHandler;
+
+public class ListHandlerTest {
+
+ @Test
+ public void testAddTodo() {
+ ListHandler listHandler = new ListHandler();
+ listHandler.addToDo("Read Book");
+
+ Vector result = listHandler.getList();
+ assertEquals(result.size(), 1);
+ }
+
+ @Test
+ public void testAddDeadline() {
+ ListHandler listHandler = new ListHandler();
+ listHandler.addDeadline("Read book", "21/12/20", "1800");
+
+ Vector result = listHandler.getList();
+ assertEquals(result.size(), 1);
+ }
+
+ @Test
+ public void testDeleteTask() {
+ ListHandler listHandler = new ListHandler();
+ listHandler.addToDo("Read Book");
+
+ String indexToDelete = "1";
+ listHandler.deleteListItem(indexToDelete);
+
+ Vector result = listHandler.getList();
+ assertEquals(result.size(), 0);
+ }
+}
diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT
index 657e74f6..292c782d 100644
--- a/text-ui-test/EXPECTED.TXT
+++ b/text-ui-test/EXPECTED.TXT
@@ -1,7 +1,10 @@
-Hello from
+----------------------------------------
____ _
| _ \ _ _| | _____
| | | | | | | |/ / _ \
| |_| | |_| | < __/
|____/ \__,_|_|\_\___|
+ Hello! I'm Duke
+ What can I do for you?
+----------------------------------------
diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt
index e69de29b..638e570e 100644
--- a/text-ui-test/input.txt
+++ b/text-ui-test/input.txt
@@ -0,0 +1,3 @@
+todo read book
+deadline return book /by 12/12/12 6pm
+bye
diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh
old mode 100644
new mode 100755
index e169618a..3111ffda
--- a/text-ui-test/runtest.sh
+++ b/text-ui-test/runtest.sh
@@ -13,7 +13,7 @@ then
fi
# compile the code into the bin folder, terminates if error occurred
-if ! javac -cp ../src -Xlint:none -d ../bin ../src/main/java/Duke.java
+if ! javac -cp ../src -Xlint:none -d ../bin ../src/main/java/duke/**/*.java
then
echo "********** BUILD FAILURE **********"
exit 1
@@ -22,12 +22,8 @@ fi
# run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT
java -classpath ../bin Duke < input.txt > ACTUAL.TXT
-# convert to UNIX format
-cp EXPECTED.TXT EXPECTED-UNIX.TXT
-dos2unix ACTUAL.TXT EXPECTED-UNIX.TXT
-
# compare the output to the expected output
-diff ACTUAL.TXT EXPECTED-UNIX.TXT
+diff ACTUAL.TXT EXPECTED.TXT
if [ $? -eq 0 ]
then
echo "Test result: PASSED"