diff --git a/README.md b/README.md index 0dd8f7fb21..fcb2dbc508 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ -# Duke project template +# Duke project -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. +This is a project named after the Java mascot _Duke_. Given below are instructions on how to use the interactive Duke bot. +# User Guide ## Setting up in Intellij Prerequisites: JDK 11, update Intellij to the most recent version. @@ -12,12 +13,168 @@ 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: - ``` - Hello from - ____ _ - | _ \ _ _| | _____ - | | | | | | | |/ / _ \ - | |_| | |_| | < __/ - |____/ \__,_|_|\_\___| - ``` +1. After that, locate the `src/main/java/Launcher.java` file, right-click it, and choose `Run Launcher.main()`. +1. Refer to the Features below for details of each command. + +## Features + +***NOTE: Words in UPPER_CASE are the parameters to be supplied by the user.*** + +### Adding a task: +  +#### Adding a ToDo task: `todo` + +Adds a new ToDo task to the Duke's tasklist. + +Format: `todo CONTENT` + +- The content field must be provided. + +Examples: + +- `todo hello` +- `todo read book` + +  + +#### Adding a Deadline task: `deadline` + +Adds a new Deadline task to the Duke's tasklist. + +Format: `deadline CONTENT /by DATE_AND_TIME` + +- The date and time must be in the format DD/MM/YYYY HH:MM +- Both fields must be provided. + +Examples: +- `deadline read book /by 12/12/2020 18:30` +- `deadline return book /by 10/10/2020 10:00` + +  +#### Adding an Event task: `event` + +Adds a new Event task to the Duke's tasklist. + +Format: `event CONTENT /at DATE_AND_TIME` + +- The date and time must be in the format DD/MM/YYYY HH:MM +- Both fields must be provided. + +Examples: +- `event go for meeting /at 12/10/2020 18:00` +- `event meet groupmates /at 10/10/2020 10:30` + +  + +### Listing all tasks: `list` + +Shows a list of all tasks in the Duke's tasklist. + +Format: `list` + +  +### Marking a task as done: `done` + +Marks an existing task in the Duke's tasklist as done. + +Format: `done INDEX` + +- Updates the task status to done for the task at the specified `INDEX` +- The index refers to the index number shown in the displayed tasklist. +- The index **must be a positive integer**. + +Examples: +- `list` followed by `done 3` marks the 3rd task in the tasklist as done. + +  +### Deleting a task: `delete` + +Deletes an existing task from the Duke's tasklist. + +Format: `delete INDEX` + +- Deletes the task at the specified `INDEX` +- The index refers to the index number shown in the displayed tasklist. +- The index **must be a positive integer**. + +Examples: +- `list` followed by `delete 1` deletes the 1st task in the tasklist. + +  +### Finding a task by content: `find` + +Finds tasks with contents that contain the given keyword/s. + +Format: `find KEYWORD OR KEYWORDS` + +- The search is **case-sensitive**. +- Only the contents of the tasks are searched. +- The following tasks will be returned: + 1. content matching the keyword/s + 2. the keyword/s form a part of the content + +Examples: +- `find read` returns both task with content `read book` and task with content `read` from the tasklist. + +  + +### Editing a task: `edit` + +  + +#### Editing a task's content: `edit_content` + +Edits an existing task's content in the Duke's tasklist. + +Format: `edit INDEX content NEW_CONTENT` + +- Edits the content of the task at the specified `INDEX` +- The index refers to the index number shown in the displayed tasklist. +- The index **must be a positive integer**. +- Existing content will be updated to `NEW_CONTENT`. +- All fields must be provided. + +Examples: +- `edit 1 content read new book` edits the content of the 1st task in the tasklist to `read new book`. + +  + +#### Editing a task's date and time: `edit_datetime` + +Edits an existing task's date and time in the Duke's tasklist. + +Format: `edit INDEX datetime NEW_DATETIME` + +- Edit the date and time of the task at the specified `INDEX` +- The index refers to the index number shown in the displayed tasklist. +- The index **must be a positive integer**. +- The date and time must be in the format DD/MM/YYYY HH:MM +- Existing date and time will be updated to `NEW_DATETIME`. +- All fields must be provided. + +Examples: +- `edit 2 datetime 12/12/2020 18:30` edits the date and time of the 2nd task in the tasklist to `12/12/2020 18:30`. + +  +### Exiting the program: `bye` + +Saves the tasklist's changes to the file at relative filepath `/data/duke.txt`. + +Format: `bye` + + +  +##Command Summary + + +Action | Format, Examples +------------ | ------------- +Add | ToDo Task
`todo CONTENT`
e.g. `todo hello`

Deadline Task
`deadline CONTENT /by DATE_AND_TIME`
e.g. `deadline read book /by 12/12/2020 18:30`

Event Task
`event CONTENT /at DATE_AND_TIME`
e.g. `event go for meeting /at 12/10/2020 18:00` +List | `list` +Done | `done INDEX`
e.g. `done 3` +Delete | `delete INDEX`
e.g. `delete 1` +Find | `find KEYWORD OR KEYWORDS`
e.g. `find read` +Edit | Edit content
`edit INDEX content NEW_CONTENT`
e.g. `edit 1 content read new book`

Edit date and time
`edit INDEX datetime NEW_DATETIME`
e.g. `edit 2 datetime 12/12/2020 18:30`
+Exit | `bye` + + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000..10b23a9eec --- /dev/null +++ b/build.gradle @@ -0,0 +1,61 @@ +plugins { + id 'java' + id 'application' + id 'checkstyle' + id 'com.github.johnrengelman.shadow' version '5.1.0' +} + +repositories { + mavenCentral() +} + +dependencies { + testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.5.0' + testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.5.0' + + String javaFxVersion = '11' + + implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'linux' + implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'linux' + implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'linux' + implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'linux' +} + +test { + useJUnitPlatform() + + testLogging { + events "passed", "skipped", "failed" + + showExceptions true + exceptionFormat "full" + showCauses true + showStackTraces true + showStandardStreams = false + } +} + +application { + mainClassName = "ip.src.main.java.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 0000000000..502fbd3a58 --- /dev/null +++ b/config/checkstyle/checkstyle.xml @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml new file mode 100644 index 0000000000..dcaa1af3c3 --- /dev/null +++ b/config/checkstyle/suppressions.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/data/duke.txt b/data/duke.txt new file mode 100644 index 0000000000..1b23f50bc0 --- /dev/null +++ b/data/duke.txt @@ -0,0 +1,3 @@ +E | 1 | bye | 12/02/2019 18:00 +E | 0 | read | 12/12/2020 18:40 +D | 0 | read book | 12/12/2020 18:20 diff --git a/docs/README.md b/docs/README.md index fd44069597..83f3829b2d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,20 +1,180 @@ +# Duke project + +This is a project named after the Java mascot Duke. Given below are instructions on how to use the interactive Duke bot. + # User Guide +## Setting up in Intellij + +Prerequisites: JDK 11, update Intellij to the most recent version. + +1. Open Intellij (if you are not in the welcome screen, click `File` > `Close Project` to close the existing project first) +1. Open the project into Intellij as follows: + 1. Click `Open`. + 1. Select the project directory, and click `OK`. + 1. If there are any further prompts, accept the defaults. +1. Configure the project to use **JDK 11** (not other versions) as explained in [here](https://www.jetbrains.com/help/idea/sdk.html#set-up-jdk). +1. After that, locate the `src/main/java/Launcher.java` file, right-click it, and choose `Run Launcher.main()`. +1. Refer to the Features below for details of each command. + +## Features + +***NOTE: Words in UPPER_CASE are the parameters to be supplied by the user.*** + +### Adding a task: +  +#### Adding a ToDo task: `todo` + +Adds a new ToDo task to the Duke's tasklist. + +Format: `todo CONTENT` + +- The content field must be provided. + +Examples: + +- `todo hello` +- `todo read book` + +  + +#### Adding a Deadline task: `deadline` + +Adds a new Deadline task to the Duke's tasklist. + +Format: `deadline CONTENT /by DATE_AND_TIME` + +- The date and time must be in the format DD/MM/YYYY HH:MM +- Both fields must be provided. + +Examples: +- `deadline read book /by 12/12/2020 18:30` +- `deadline return book /by 10/10/2020 10:00` + +  +#### Adding an Event task: `event` + +Adds a new Event task to the Duke's tasklist. + +Format: `event CONTENT /at DATE_AND_TIME` + +- The date and time must be in the format DD/MM/YYYY HH:MM +- Both fields must be provided. + +Examples: +- `event go for meeting /at 12/10/2020 18:00` +- `event meet groupmates /at 10/10/2020 10:30` + +  + +### Listing all tasks: `list` + +Shows a list of all tasks in the Duke's tasklist. + +Format: `list` + +  +### Marking a task as done: `done` + +Marks an existing task in the Duke's tasklist as done. + +Format: `done INDEX` + +- Updates the task status to done for the task at the specified `INDEX` +- The index refers to the index number shown in the displayed tasklist. +- The index **must be a positive integer**. + +Examples: +- `list` followed by `done 3` marks the 3rd task in the tasklist as done. + +  +### Deleting a task: `delete` + +Deletes an existing task from the Duke's tasklist. + +Format: `delete INDEX` + +- Deletes the task at the specified `INDEX` +- The index refers to the index number shown in the displayed tasklist. +- The index **must be a positive integer**. + +Examples: +- `list` followed by `delete 1` deletes the 1st task in the tasklist. + +  +### Finding a task by content: `find` + +Finds tasks with contents that contain the given keyword/s. + +Format: `find KEYWORD OR KEYWORDS` + +- The search is **case-sensitive**. +- Only the contents of the tasks are searched. +- The following tasks will be returned: + 1. content matching the keyword/s + 2. the keyword/s form a part of the content + +Examples: +- `find read` returns both task with content `read book` and task with content `read` from the tasklist. + +  + +### Editing a task: `edit` + +  + +#### Editing a task's content: `edit_content` + +Edits an existing task's content in the Duke's tasklist. + +Format: `edit INDEX content NEW_CONTENT` + +- Edits the content of the task at the specified `INDEX` +- The index refers to the index number shown in the displayed tasklist. +- The index **must be a positive integer**. +- Existing content will be updated to `NEW_CONTENT`. +- All fields must be provided. + +Examples: +- `edit 1 content read new book` edits the content of the 1st task in the tasklist to `read new book`. + +  + +#### Editing a task's date and time: `edit_datetime` + +Edits an existing task's date and time in the Duke's tasklist. + +Format: `edit INDEX datetime NEW_DATETIME` + +- Edit the date and time of the task at the specified `INDEX` +- The index refers to the index number shown in the displayed tasklist. +- The index **must be a positive integer**. +- The date and time must be in the format DD/MM/YYYY HH:MM +- Existing date and time will be updated to `NEW_DATETIME`. +- All fields must be provided. + +Examples: +- `edit 2 datetime 12/12/2020 18:30` edits the date and time of the 2nd task in the tasklist to `12/12/2020 18:30`. -## Features +  +### Exiting the program: `bye` -### Feature 1 -Description of feature. +Saves the tasklist's changes to the file at relative filepath `/data/duke.txt`. -## Usage +Format: `bye` -### `Keyword` - Describe action -Describe action and its outcome. +  +##Command Summary -Example of usage: -`keyword (optional arguments)` +Action | Format, Examples +------------ | ------------- +Add | ToDo Task
`todo CONTENT`
e.g. `todo hello`

Deadline Task
`deadline CONTENT /by DATE_AND_TIME`
e.g. `deadline read book /by 12/12/2020 18:30`

Event Task
`event CONTENT /at DATE_AND_TIME`
e.g. `event go for meeting /at 12/10/2020 18:00` +List | `list` +Done | `done INDEX`
e.g. `done 3` +Delete | `delete INDEX`
e.g. `delete 1` +Find | `find KEYWORD OR KEYWORDS`
e.g. `find read` +Edit | Edit content
`edit INDEX content NEW_CONTENT`
e.g. `edit 1 content read new book`

Edit date and time
`edit INDEX datetime NEW_DATETIME`
e.g. `edit 2 datetime 12/12/2020 18:30`
+Exit | `bye` -Expected outcome: -`outcome` diff --git a/docs/Ui.png b/docs/Ui.png new file mode 100644 index 0000000000..a0aa456a48 Binary files /dev/null and b/docs/Ui.png differ diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000000..c4192631f2 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..f3d88b1c2f 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..b7c8c5dbf5 --- /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 0000000000..2fe81a7d95 --- /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 0000000000..62bd9b9cce --- /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/A_MoreOop.java b/src/main/A_MoreOop.java new file mode 100644 index 0000000000..bcde1396cd --- /dev/null +++ b/src/main/A_MoreOop.java @@ -0,0 +1,131 @@ +package ip.src.main; + +import ip.src.main.java.*; + +import java.io.IOException; +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Scanner; + +/** A-More OOP class that demonstrates OOP by having classes such as Task, Event etc. + * + */ + +public class A_MoreOop { + + /** Returns a Duke bot that has loaded the tasks from the file given. + * + * @param filePath Location of the file with the tasks information. + * @param bot The Duke bot to be updated with the tasks from the file. + * @throws FileNotFoundException + */ + + private static void createBot(String filePath, Duke bot) throws FileNotFoundException { + File f = new File(filePath); // create a File for the given file path + Scanner s = new Scanner(f); // create a Scanner using the File as the source + Storage storage = new Storage(filePath, bot); + Task newTask = new Task(""); + + while (s.hasNext()) { + storage.loadTask(s.nextLine()); + } + + } + + /** + * Overwrites the file with the updated tasks everytime a user gives a command/input. + * + * @param filePath The location of the file to be updated. + * @param bot The bot with the new tasks to be written to the file. + * @throws IOException + */ + private static void updateFile(String filePath, Duke bot) throws IOException { + Storage storage = new Storage(filePath, bot); + storage.updateFile(); + } + + /** + * Main method that greets users and interacts with users. + */ + public static void main(String[] args) throws DukeException { + System.out.println("Hello! I'm Duke"); + System.out.println("What can I do for you?"); + Duke bot = new Duke(); + + try { + File f = new File("data/duke.txt"); + f.getParentFile().mkdirs(); + if (f.createNewFile()) { + System.out.println("File created"); + } else { + createBot("data/duke.txt", bot); + } + } catch (IOException e) { + System.out.println("Error in creating file"); + + } + + Scanner sc = new Scanner(System.in); + String input = sc.nextLine(); + Parser parser = new Parser(); + Ui ui = new Ui(bot); + + while (!(input.equals("bye"))) { + if (input.equals("list")) { + bot.printList(); + } else { + String command = parser.getCommand(input); + try { + if (command.equals("done")) { + int id = parser.getId(input); + ui.doneCommand(id); + + } else if (command.equals("todo")) { + try { + input = parser.toDoTask(input); + ui.toDoCommand(input); + + } catch (Exception e) { + throw new DukeException(("OOPS!!! The description cannot be empty.")); + } + } else if (command.equals("event")) { + String content = parser.eventTaskContent(input); + String at = parser.eventTaskAt(input); + ui.eventCommand(content, at); + + } else if (command.equals("deadline")) { + String content = parser.deadlineTaskContent(input); + String by = parser.deadlineTaskBy(input); + ui.deadlineCommand(content, by); + + } else if(command.equals("delete")) { + int id = parser.getId(input); + ui.deleteCommand(id); + + } else { + throw new DukeException("OOPS!!! I'm sorry, but I don't know what that means :-{"); + } + } catch (DukeException e1) { + System.out.println(e1); + + } + } + try { + updateFile("data/duke.txt", bot); + } catch (IOException e) { + System.out.println("Unable to update file"); + } + input = sc.nextLine(); + } + + + System.out.println("Bye. Hope to see you again soon!"); + } +} + + + + + + + diff --git a/src/main/Level1_9/Level_1.java b/src/main/Level1_9/Level_1.java new file mode 100644 index 0000000000..e4c3b76b05 --- /dev/null +++ b/src/main/Level1_9/Level_1.java @@ -0,0 +1,21 @@ +package Level1_9; +import ip.src.main.java.Duke; + +import java.util.Scanner; + +public class Level_1 { + public static void main(String[] args) { + System.out.println("Hello! I'm Duke"); + System.out.println("What can I do for you?"); + Scanner sc = new Scanner(System.in); + String input = sc.next(); + Duke bot = new Duke(); + + while(!(input.equals("bye"))){ + bot.echo(input); + input = sc.next(); + } + + System.out.println("Bye. Hope to see you again soon!"); + } +} diff --git a/src/main/Level1_9/Level_2.java b/src/main/Level1_9/Level_2.java new file mode 100644 index 0000000000..13783cbe85 --- /dev/null +++ b/src/main/Level1_9/Level_2.java @@ -0,0 +1,29 @@ +package Level1_9; +import ip.src.main.java.Duke; +import ip.src.main.java.Task; + +import java.util.Scanner; + +public class Level_2 { + public static void main(String[] args) { + System.out.println("Hello! I'm Duke"); + System.out.println("What can I do for you?"); + Scanner sc = new Scanner(System.in); + String input = sc.nextLine(); + Duke bot = new Duke(); + //int counter = 1; + + while(!(input.equals("bye"))) { + if (input.equals("list")) { + bot.printList(); + }else{ + Task newTask = new Task(input); + bot.addToList(newTask); + //counter++; + } + input = sc.nextLine(); + } + + System.out.println("Bye. Hope to see you again soon!"); + } +} diff --git a/src/main/Level1_9/Level_3.java b/src/main/Level1_9/Level_3.java new file mode 100644 index 0000000000..b0d3f29c8a --- /dev/null +++ b/src/main/Level1_9/Level_3.java @@ -0,0 +1,36 @@ +package Level1_9; +import ip.src.main.java.Duke; +import ip.src.main.java.Task; + +import java.util.Scanner; + +public class Level_3 { + public static void main(String[] args) { + System.out.println("Hello! I'm Duke"); + System.out.println("What can I do for you?"); + Scanner sc = new Scanner(System.in); + String input = sc.nextLine(); + Duke bot = new Duke(); + //int counter = 1; + + while(!(input.equals("bye"))) { + if (input.equals("list")) { + bot.printList(); + }else{ + String command = input.split(" ")[0]; + if(command.equals("done")){ + int id = Integer.valueOf(input.split(" ")[1]); + bot.markTaskAsDone(id); + + }else { + Task newTask = new Task(input); + bot.addToList(newTask); + //counter++; + } + } + input = sc.nextLine(); + } + + System.out.println("Bye. Hope to see you again soon!"); + } +} diff --git a/src/main/Level1_9/Level_4.java b/src/main/Level1_9/Level_4.java new file mode 100644 index 0000000000..6cd11a5b58 --- /dev/null +++ b/src/main/Level1_9/Level_4.java @@ -0,0 +1,52 @@ +package Level1_9; +import ip.src.main.java.Deadline; +import ip.src.main.java.Duke; +import ip.src.main.java.Event; +import ip.src.main.java.ToDo; + +import java.util.Scanner; + +public class Level_4 { + public static void main(String[] args) { + System.out.println("Hello! I'm Duke"); + System.out.println("What can I do for you?"); + Scanner sc = new Scanner(System.in); + String input = sc.nextLine(); + Duke bot = new Duke(); + //int counter = 1; + + while(!(input.equals("bye"))) { + if (input.equals("list")) { + bot.printList(); + }else{ + String command = input.split(" ")[0]; + if(command.equals("done")){ + int id = Integer.valueOf(input.split(" ")[1]); + bot.markTaskAsDone(id); + + }else if(command.equals("todo")) { + input = input.split(" ",2)[1]; + ToDo newTask = new ToDo(input); + bot.addToList(newTask); + //counter++; + }else if(command.equals("event")){ + input = input.split(" ",2)[1]; + String content = input.split("/at")[0]; + String at = input.split("/at")[1]; + Event newTask = new Event(content,at); + bot.addToList(newTask); + }else{ + input = input.split(" ",2)[1]; + String content = input.split("/by")[0]; + String by= input.split("/by")[1]; + Deadline newTask = new Deadline(content,by); + bot.addToList(newTask); + } + + } + input = sc.nextLine(); + } + + System.out.println("Bye. Hope to see you again soon!"); + } +} diff --git a/src/main/Level1_9/Level_5.java b/src/main/Level1_9/Level_5.java new file mode 100644 index 0000000000..26b08458dc --- /dev/null +++ b/src/main/Level1_9/Level_5.java @@ -0,0 +1,62 @@ +package Level1_9; +import ip.src.main.java.*; + +import java.util.Scanner; + +public class Level_5 { + public static void main(String[] args) throws DukeException { + System.out.println("Hello! I'm Duke"); + System.out.println("What can I do for you?"); + Scanner sc = new Scanner(System.in); + String input = sc.nextLine(); + Duke bot = new Duke(); + //int counter = 1; + + while (!(input.equals("bye"))) { + if (input.equals("list")) { + bot.printList(); + } else { + String command = input.split(" ")[0]; + try { + if (command.equals("done")) { + int id = Integer.valueOf(input.split(" ")[1]); + bot.markTaskAsDone(id); + + } else if (command.equals("todo")) { + try { + input = input.split(" ", 2)[1]; + ToDo newTask = new ToDo(input); + bot.addToList(newTask); + //counter++; + } catch (Exception e) { + throw new DukeException(("OOPS!!! The description cannot be empty.")); + } + } else if (command.equals("event")) { + input = input.split(" ", 2)[1]; + String content = input.split("/at")[0]; + String at = input.split("/at")[1]; + Event newTask = new Event(content, at); + bot.addToList(newTask); + } else if (command.equals("deadline")) { + input = input.split(" ", 2)[1]; + String content = input.split("/by")[0]; + String by = input.split("/by")[1]; + Deadline newTask = new Deadline(content, by); + bot.addToList(newTask); + } else { + throw new DukeException("OOPS!!! I'm sorry, but I don't know what that means :-{"); + } + } catch (DukeException e1) { + System.out.println(e1); + + } + } + + input = sc.nextLine(); + } + + + System.out.println("Bye. Hope to see you again soon!"); + } +} + diff --git a/src/main/Level1_9/Level_6.java b/src/main/Level1_9/Level_6.java new file mode 100644 index 0000000000..326a361d75 --- /dev/null +++ b/src/main/Level1_9/Level_6.java @@ -0,0 +1,68 @@ +package Level1_9; +import ip.src.main.java.*; + +import java.util.Scanner; + +public class Level_6 { + public static void main(String[] args) throws DukeException { + System.out.println("Hello! I'm Duke"); + System.out.println("What can I do for you?"); + Scanner sc = new Scanner(System.in); + String input = sc.nextLine(); + Duke bot = new Duke(); + //int counter = 1; + + while (!(input.equals("bye"))) { + if (input.equals("list")) { + bot.printList(); + } else { + String command = input.split(" ")[0]; + try { + if (command.equals("done")) { + int id = Integer.valueOf(input.split(" ")[1]); + bot.markTaskAsDone(id); + + } else if (command.equals("todo")) { + try { + input = input.split(" ", 2)[1]; + ToDo newTask = new ToDo(input); + bot.addToList(newTask); + //counter++; + } catch (Exception e) { + throw new DukeException(("OOPS!!! The description cannot be empty.")); + } + } else if (command.equals("event")) { + input = input.split(" ", 2)[1]; + String content = input.split("/at")[0]; + String at = input.split("/at")[1]; + Event newTask = new Event(content, at); + bot.addToList(newTask); + } else if (command.equals("deadline")) { + input = input.split(" ", 2)[1]; + String content = input.split("/by")[0]; + String by = input.split("/by")[1]; + Deadline newTask = new Deadline(content, by); + bot.addToList(newTask); + }else if(command.equals("delete")){ + int id = Integer.valueOf(input.split(" ")[1]); + bot.deleteTask(id); + + } else { + throw new DukeException("OOPS!!! I'm sorry, but I don't know what that means :-{"); + } + } catch (DukeException e1) { + System.out.println(e1); + + } + } + + input = sc.nextLine(); + } + + + System.out.println("Bye. Hope to see you again soon!"); + } +} + + + diff --git a/src/main/Level1_9/Level_7.java b/src/main/Level1_9/Level_7.java new file mode 100644 index 0000000000..29ece14bc8 --- /dev/null +++ b/src/main/Level1_9/Level_7.java @@ -0,0 +1,135 @@ +package Level1_9; +import ip.src.main.java.*; + +import java.io.IOException; +import java.util.Scanner; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; + +public class Level_7 { + + private static void createBot(String filePath, Duke bot) throws FileNotFoundException { + File f = new File(filePath); // create a File for the given file path + Scanner s = new Scanner(f); // create a Scanner using the File as the source + Task newTask = new Task(""); + while (s.hasNext()) { + String[] taskData = s.nextLine().split(" \\| "); + String type = taskData[0]; + String doneStatus = taskData[1]; + if (type.equals("T")) { + String details = taskData[2]; + newTask = new ToDo(details); + bot.addToBot(newTask); + + } else if (type.equals("E")) { + String content = taskData[2]; + String at = taskData[3]; + newTask = new Event(content, at); + bot.addToBot(newTask); + + } else { + String content = taskData[2]; + String by = taskData[3]; + newTask = new Deadline(content, by); + bot.addToBot(newTask); + } + + if (doneStatus == " 1 ") { + newTask.markDone(); + } + + } + } + + + private static void updateFile(String filePath, Duke bot) throws IOException { + FileWriter fw = new FileWriter(filePath); + for(Task element:bot.list.list) { + fw.write(element.toString() + "\n"); + + } + fw.close(); + } + public static void main(String[] args) throws DukeException { + System.out.println("Hello! I'm Duke"); + System.out.println("What can I do for you?"); + Duke bot = new Duke(); + try{ + File f = new File("data/duke.txt"); + f.getParentFile().mkdirs(); + if(f.createNewFile()){ + System.out.println("File created"); + }else { + createBot("data/duke.txt", bot); + } + }catch (IOException e){ + System.out.println("Error in creating file"); + + + } + Scanner sc = new Scanner(System.in); + String input = sc.nextLine(); + + while (!(input.equals("bye"))) { + if (input.equals("list")) { + bot.printList(); + } else { + String command = input.split(" ")[0]; + try { + if (command.equals("done")) { + int id = Integer.valueOf(input.split(" ")[1]); + bot.markTaskAsDone(id); + + } else if (command.equals("todo")) { + try { + input = input.split(" ", 2)[1]; + ToDo newTask = new ToDo(input); + bot.addToList(newTask); + //counter++; + } catch (Exception e) { + throw new DukeException(("OOPS!!! The description cannot be empty.")); + } + } else if (command.equals("event")) { + input = input.split(" ", 2)[1]; + String content = input.split("/at")[0]; + String at = input.split("/at")[1]; + Event newTask = new Event(content, at); + bot.addToList(newTask); + } else if (command.equals("deadline")) { + input = input.split(" ", 2)[1]; + String content = input.split("/by")[0]; + String by = input.split("/by")[1]; + Deadline newTask = new Deadline(content, by); + bot.addToList(newTask); + }else if(command.equals("delete")){ + int id = Integer.valueOf(input.split(" ")[1]); + bot.deleteTask(id); + + } else { + throw new DukeException("OOPS!!! I'm sorry, but I don't know what that means :-{"); + } + } catch (DukeException e1) { + System.out.println(e1); + + } + } + try { + updateFile("data/duke.txt", bot); + }catch (IOException e) { + System.out.println("Unable to update file"); + } + input = sc.nextLine(); + } + + + System.out.println("Bye. Hope to see you again soon!"); + } +} + + + + + + + diff --git a/src/main/Level1_9/Level_8.java b/src/main/Level1_9/Level_8.java new file mode 100644 index 0000000000..f9f23f89cc --- /dev/null +++ b/src/main/Level1_9/Level_8.java @@ -0,0 +1,137 @@ +package Level1_9; +import ip.src.main.java.*; + +import java.io.IOException; +import java.util.Scanner; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.time.LocalDate; + +public class Level_8 { + + private static void createBot(String filePath, Duke bot) throws FileNotFoundException { + File f = new File(filePath); // create a File for the given file path + Scanner s = new Scanner(f); // create a Scanner using the File as the source + Task newTask = new Task(""); + while (s.hasNext()) { + String[] taskData = s.nextLine().split(" \\| "); + String type = taskData[0]; + String doneStatus = taskData[1]; + if (type.equals("T")) { + String details = taskData[2]; + newTask = new ToDo(details); + bot.addToBot(newTask); + + } else if (type.equals("E")) { + String content = taskData[2]; + String at = taskData[3]; + newTask = new Event(content, at); + bot.addToBot(newTask); + + } else { + String content = taskData[2]; + String by = taskData[3]; + newTask = new Deadline(content, by); + bot.addToBot(newTask); + } + + if (doneStatus == " 1 ") { + newTask.markDone(); + } + + } + } + + + private static void updateFile(String filePath, Duke bot) throws IOException { + FileWriter fw = new FileWriter(filePath); + for(Task element:bot.list.list) { + fw.write(element.toString() + "\n"); + + } + fw.close(); + } + public static void main(String[] args) throws DukeException { + System.out.println("Hello! I'm Duke"); + System.out.println("What can I do for you?"); + Duke bot = new Duke(); + try{ + File f = new File("data/duke.txt"); + f.getParentFile().mkdirs(); + if(f.createNewFile()){ + System.out.println("File created"); + }else { + createBot("data/duke.txt", bot); + } + }catch (IOException e){ + System.out.println("Error in creating file"); + + + } + Scanner sc = new Scanner(System.in); + String input = sc.nextLine(); + + while (!(input.equals("bye"))) { + if (input.equals("list")) { + bot.printList(); + } else { + String command = input.split(" ")[0]; + try { + if (command.equals("done")) { + int id = Integer.valueOf(input.split(" ")[1]); + bot.markTaskAsDone(id); + + } else if (command.equals("todo")) { + try { + input = input.split(" ", 2)[1]; + ToDo newTask = new ToDo(input); + bot.addToList(newTask); + //counter++; + } catch (Exception e) { + throw new DukeException(("OOPS!!! The description cannot be empty.")); + } + } else if (command.equals("event")) { + input = input.split(" ", 2)[1]; + String content = input.split("/at")[0]; + String at = input.split(" /at ")[1]; + Event newTask = new Event(content, at); + bot.addToList(newTask); + } else if (command.equals("deadline")) { + input = input.split(" ", 2)[1]; + String content = input.split("/by")[0]; + String by = input.split(" /by ")[1]; + System.out.println(by); + Deadline newTask = new Deadline(content, by); + bot.addToList(newTask); + }else if(command.equals("delete")){ + int id = Integer.valueOf(input.split(" ")[1]); + bot.deleteTask(id); + + } else { + throw new DukeException("OOPS!!! I'm sorry, but I don't know what that means :-{"); + } + } catch (DukeException e1) { + System.out.println(e1); + + } + } + try { + updateFile("data/duke.txt", bot); + }catch (IOException e) { + System.out.println("Unable to update file"); + } + input = sc.nextLine(); + } + + + System.out.println("Bye. Hope to see you again soon!"); + } +} + + + + + + + diff --git a/src/main/Level1_9/Level_9.java b/src/main/Level1_9/Level_9.java new file mode 100644 index 0000000000..c827ab2114 --- /dev/null +++ b/src/main/Level1_9/Level_9.java @@ -0,0 +1,130 @@ +package Level1_9; + +import ip.src.main.java.*; + +import java.io.IOException; +import java.util.Scanner; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; + +/** A-More OOP class that demonstrates OOP by having classes such as Task, Event etc. + * + */ + +public class Level_9 { + + /** Returns a Duke bot that has loaded the tasks from the file given. + * + * @param filePath Location of the file with the tasks information. + * @param bot The Duke bot to be updated with the tasks from the file. + * @throws FileNotFoundException + */ + + private static void createBot(String filePath, Duke bot) throws FileNotFoundException { + File f = new File(filePath); // create a File for the given file path + Scanner s = new Scanner(f); // create a Scanner using the File as the source + Storage storage = new Storage(filePath, bot); + Task newTask = new Task(""); + + while (s.hasNext()) { + storage.loadTask(s.nextLine()); + } + + } + + /** + * Overwrites the file with the updated tasks everytime a user gives a command/input. + * + * @param filePath The location of the file to be updated. + * @param bot The bot with the new tasks to be written to the file. + * @throws IOException + */ + private static void updateFile(String filePath, Duke bot) throws IOException { + Storage storage = new Storage(filePath, bot); + storage.updateFile(); + } + + public static void main(String[] args) throws DukeException { + System.out.println("Hello! I'm Duke"); + System.out.println("What can I do for you?"); + Duke bot = new Duke(); + + try{ + File f = new File("data/duke.txt"); + f.getParentFile().mkdirs(); + if(f.createNewFile()){ + System.out.println("File created"); + }else { + createBot("data/duke.txt", bot); + } + }catch (IOException e){ + System.out.println("Error in creating file"); + + } + + Scanner sc = new Scanner(System.in); + String input = sc.nextLine(); + Parser parser = new Parser(); + Ui ui = new Ui(bot); + + while (!(input.equals("bye"))) { + if (input.equals("list")) { + bot.printList(); + } else { + String command = parser.getCommand(input); + try { + if (command.equals("done")) { + int id = parser.getId(input); + ui.doneCommand(id); + + } else if (command.equals("find")) { + String keyword = parser.getKeyword(input); + bot.findMatchingTasks(keyword); + + } else if (command.equals("todo")) { + try { + input = parser.toDoTask(input); + ui.toDoCommand(input); + + } catch (Exception e) { + throw new DukeException(("OOPS!!! The description cannot be empty.")); + } + } else if (command.equals("event")) { + String content = parser.eventTaskContent(input); + String at = parser.eventTaskAt(input); + ui.eventCommand(content, at); + + } else if (command.equals("deadline")) { + String content = parser.deadlineTaskContent(input); + String by = parser.deadlineTaskBy(input); + ui.deadlineCommand(content, by); + + }else if(command.equals("delete")){ + int id = parser.getId(input); + ui.deleteCommand(id); + + } else { + throw new DukeException("OOPS!!! I'm sorry, but I don't know what that means :-{"); + } + } catch (DukeException e1) { + System.out.println(e1); + + } + } + try { + updateFile("data/duke.txt", bot); + }catch (IOException e) { + System.out.println("Unable to update file"); + } + input = sc.nextLine(); + } + + + System.out.println("Bye. Hope to see you again soon!"); + } +} + + + + 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..ad933595bc --- /dev/null +++ b/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: ip.src.main.java.A_MoreOOP + diff --git a/src/main/java/ip/src/main/java/Command.java b/src/main/java/ip/src/main/java/Command.java new file mode 100644 index 0000000000..fb5889c37f --- /dev/null +++ b/src/main/java/ip/src/main/java/Command.java @@ -0,0 +1,16 @@ +package ip.src.main.java; + +/** + * Command enum class for the different types of commands available for the Duke bot. + */ +public enum Command { + BYE, + DEADLINE, + DELETE, + DONE, + EDIT, + EVENT, + FIND, + LIST, + TODO; +} diff --git a/src/main/java/ip/src/main/java/Deadline.java b/src/main/java/ip/src/main/java/Deadline.java new file mode 100644 index 0000000000..45481d481e --- /dev/null +++ b/src/main/java/ip/src/main/java/Deadline.java @@ -0,0 +1,80 @@ +package ip.src.main.java; + +import java.text.ParseException; +import java.util.Date; +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +/** + * Deadline is a type of Task with attributes String content and a Date stored as a Date object. + * + */ + +public class Deadline extends Task{ + protected Date by; + + /** + * Constructor for Deadline Class. + * + * @param content String content given by user. + * @param by_str Deadline date given by user, parsed into a Date object with the format dd/MM/yyyy HH:mm. + */ + + public Deadline(String content , String by_str) { + super(content); + DateFormat sourceFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm"); + try { + Date by = sourceFormat.parse(by_str); + this.by = by; + } catch (ParseException e) { + System.out.println("Date and Time is not in correct format DD/MM/YYYY HH:MM"); + e.printStackTrace(); + } + + } + + /** + *Edits the date and time of the Deadline task by cloning the old Deadline task. + * + * @param newDate New date given by user. + * @return A clone of the old Deadline task with the new date and time change. + */ + protected Deadline editDate (String newDate) { + String content = this.content; + boolean doneStatus = this.done; + Deadline newDeadlineTask = new Deadline(content , newDate); + newDeadlineTask.done = doneStatus; + return newDeadlineTask; + } + + /** + *Edits the content of the Deadline task by cloning the old Deadline task. + * + * @param newContent New content given by user. + * @return A clone of the old Deadline task with the new content change. + */ + public Deadline editContent (String newContent) { + Deadline newTask = new Deadline(newContent , "0/0/0 00:00"); + newTask.by = this.by; + newTask.done = this.done; + return newTask; + } + + /** + * toString() of Deadline Class. + * + * @return toString() representation of a Deadline object with its done status, content and date. + */ + + @Override + public String toString() { + DateFormat sourceFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm"); + String strDate = sourceFormat.format(this.by); + if (!this.done) { + return "D | 0 | " + super.toString() + " | " + strDate; + } else { + return "D | 1 | " + super.toString() + " | " + strDate; + + } + } +} diff --git a/src/main/java/ip/src/main/java/DialogBox.java b/src/main/java/ip/src/main/java/DialogBox.java new file mode 100644 index 0000000000..8be2edb316 --- /dev/null +++ b/src/main/java/ip/src/main/java/DialogBox.java @@ -0,0 +1,61 @@ +package ip.src.main.java; + +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; + } +} \ No newline at end of file diff --git a/src/main/java/ip/src/main/java/Duke.java b/src/main/java/ip/src/main/java/Duke.java new file mode 100644 index 0000000000..55869fb2ea --- /dev/null +++ b/src/main/java/ip/src/main/java/Duke.java @@ -0,0 +1,170 @@ +package ip.src.main.java; + +import java.io.IOException; + +/** + * Returns a Duke bot that stores the tasks given by the user. + */ +public class Duke { + /** Tasks stored in this task list object */ + TaskList list; + + public Duke() { + this.list = new TaskList(); + } + + /** + *Sends a greeting to the user. + * + * @return A string representation of the greeting. + */ + public String greet() { + String output = ""; + output += "Hello! I'm Duke! :) " + "\n"; + output += "What can I do for you?"; + return output; + } + + /** + * Exits the conversion with the bot. + * Initiates the saving of the new tasklist to the file at the relative filepath (attribute of storage). + * + * @param storage Storage object used to save final data to the data file. + * @return A string saying bye to the user. + * @throws DukeException + */ + public String bye(Storage storage) throws DukeException { + try { + storage.updateFile(); + return "Bye! See you again"; + } catch (IOException e) { + throw new DukeException("Can't save to file!"); + } + } + + /** + * Echos the user input. + * + * @param input User input given. + */ + + public void echo(String input) { + System.out.println(input); + + } + + /** + * Adds the given task to the Duke bot list, informs the user and prints the number of tasks in the bot list. + * + * @param task Task object created from user input. + * @return A string representation that informs the user of the task added and the number of tasks in the tasklist. + */ + public String addToList(Task task) { + this.list.addTask(task); + String output = ""; + output += "Got it. I've added this task: " + "\n"; + output += " " + task + "\n"; + output += "Now you have " + String.valueOf(this.list.size()) + " tasks in the list."; + return output; + } + + /** + * Adds the given task to the Duke bot list quietly. + * + * @param task Task object created from user input. + */ + public void addToBot(Task task) { + this.list.addTask(task); + } + + /** + *Prints the bot's tasklist. + * + * @return A string representation of the bot's current tasklist. + */ + public String printList() { + String output = ""; + + if (this.list.isEmpty()) { + output += "There are no tasks!"; + } else { + output += this.list.printTasks(); + } + return output; + } + + /** + * Marks a task specified in the bot list as done. + * + * @param id The position ,1-th based, of the task to be marked done in the bot list. + * @return A string representation to inform the user of the task marked done. + */ + public String markTaskAsDone(int id) { + Task task = this.list.getTask(id-1); + task.markDone(); + String output = ""; + output += "Nice! I've marked this task as done: \n"; + output += " [X] "+ task.content; + return output; + } + + /** + * Deletes a task specified in the bot list. + * + * @param id The position ,1-th based, of the task to be marked done in the bot list. + * @return A string representation to inform the user of the deletion of the specified task. + */ + public String deleteTask(int id) { + Task task = this.list.getTask(id-1); + this.list.remove(id-1); + String output = ""; + output += "Noted. I've removed this task: \n"; + output += " " + task + "\n"; + output += "Now you have " + String.valueOf(this.list.size()) + " tasks in the list."; + return output; + } + + /** + * Prints all the tasks with content that contain the keyword. + * + * @param keyword The keyword given by the user. + * @return A string representation of all the matching tasks. + */ + public String findMatchingTasks(String keyword) { + TaskList matchingTasks = this.list.findTasks(keyword); + return matchingTasks.printMatchingTasks(); + } + + /** + * Retrieves a task from the bot's TaskList at the specified index. + * + * @param id The specified index of the task in the tasklist to be retrieved. + * @return The task at the specified index. + */ + public Task getTask (int id) { + return this.list.getTask(id); + } + + /** + *Updates the old task with the new task with the edited task details. + * + * @param newTask The new task with the new edited task details. + * @param id The index of the old task to be updated with the new task. + * @return A string representation of the new edited tasklist. + */ + public String editTask(Task newTask , int id) { + this.list.editTask(newTask , id-1); + String output = "Task has been edited. \n"; + output += this.list.printEditedTasks(); + return output; + } + + 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/ip/src/main/java/DukeException.java b/src/main/java/ip/src/main/java/DukeException.java new file mode 100644 index 0000000000..4de69bffab --- /dev/null +++ b/src/main/java/ip/src/main/java/DukeException.java @@ -0,0 +1,16 @@ +package ip.src.main.java; + +/** + * Customized Exception Class for Duke. + */ + +public class DukeException extends Exception { + public DukeException(String message) { + super(message); + } + + @Override + public String toString() { + return this.getMessage(); + } +} diff --git a/src/main/java/ip/src/main/java/EditType.java b/src/main/java/ip/src/main/java/EditType.java new file mode 100644 index 0000000000..79a80474e6 --- /dev/null +++ b/src/main/java/ip/src/main/java/EditType.java @@ -0,0 +1,9 @@ +package ip.src.main.java; + +/** + * Edit enum class shows the different types of edit commands available for the bot. + */ +public enum EditType { + EDIT_CONTENT, + EDIT_DATETIME +} diff --git a/src/main/java/ip/src/main/java/Event.java b/src/main/java/ip/src/main/java/Event.java new file mode 100644 index 0000000000..e738426ac3 --- /dev/null +++ b/src/main/java/ip/src/main/java/Event.java @@ -0,0 +1,75 @@ +package ip.src.main.java; +import java.text.ParseException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Event is a type of Task with attributes String content and a Date stored as a Date object. + * + */ +public class Event extends Task { + protected Date at; + + /** + * Constructor for Event Class. + * + * @param content String content given by user. + * @param atStr Event date given by user, parsed into a Date object with the format dd/MM/yyyy HH:mm. + */ + public Event(String content , String atStr) { + super(content); + DateFormat sourceFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm"); + try { + Date at = sourceFormat.parse(atStr); + this.at = at; + } catch (ParseException e) { + System.out.println("Date and Time is not in correct format DD/MM/YYYY HH:MM"); + e.printStackTrace(); + } + + } + + /** + *Edits the date and time of the Event task by cloning the old Event task. + * + * @param newDate New date given by user. + * @return A clone of the old Event task with the new date and time change. + */ + public Event editDate (String newDate) { + String content = this.content; + boolean doneStatus = this.done; + Event newEventTask = new Event (content , newDate); + newEventTask.done = doneStatus; + return newEventTask; + } + + /** + *Edits the content of the Event task by cloning the old Event task. + * + * @param newContent New content given by user. + * @return A clone of the old Event task with the new content change. + */ + public Event editContent (String newContent) { + Event newTask = new Event(newContent , "0/0/0 00:00"); + newTask.at = this.at; + newTask.done = this.done; + return newTask; + } + + /** + * toString() of Event Class. + * + * @return toString() representation of a Event object with its done status, content and date. + */ + @Override + public String toString() { + DateFormat sourceFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm"); + String strDate = sourceFormat.format(this.at); + if (!this.done) { + return "E | 0 | " + super.toString() + " | " + strDate; + } else { + return "E | 1 | " + super.toString() + " | " + strDate; + } + } +} diff --git a/src/main/java/ip/src/main/java/Launcher.java b/src/main/java/ip/src/main/java/Launcher.java new file mode 100644 index 0000000000..8c03f37cb9 --- /dev/null +++ b/src/main/java/ip/src/main/java/Launcher.java @@ -0,0 +1,12 @@ +package ip.src.main.java; + +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); + } +} \ No newline at end of file diff --git a/src/main/java/ip/src/main/java/Main.java b/src/main/java/ip/src/main/java/Main.java new file mode 100644 index 0000000000..72f9276f3a --- /dev/null +++ b/src/main/java/ip/src/main/java/Main.java @@ -0,0 +1,50 @@ +package ip.src.main.java; + +import java.io.File; +import java.io.IOException; + +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.control.Label; +import javafx.scene.layout.AnchorPane; +import javafx.scene.text.TextAlignment; +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) { + Storage storage = new Storage("data/duke.txt" , duke); + + try { + File f = new File("data/duke.txt"); + f.getParentFile().mkdirs(); + if (!f.createNewFile()) { + storage.createBot("data/duke.txt" , duke); + } + } catch (IOException e) { + e.printStackTrace(); + } + + 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(); + String greet = duke.greet(); + Label label = new Label(greet); + stage.setTitle(greet); + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/ip/src/main/java/MainWindow.java b/src/main/java/ip/src/main/java/MainWindow.java new file mode 100644 index 0000000000..9fbd418c10 --- /dev/null +++ b/src/main/java/ip/src/main/java/MainWindow.java @@ -0,0 +1,55 @@ +package ip.src.main.java; + +import ip.src.main.java.DialogBox; +import ip.src.main.java.Duke; +import ip.src.main.java.Ui; +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/MaskedPikachu.png")); + private Image dukeImage = new Image(this.getClass().getResourceAsStream("/images/MaskedSquirtle.png")); + + @FXML + public void initialize() { + scrollPane.vvalueProperty().bind(dialogContainer.heightProperty()); + } + + public void setDuke(Duke d) { + duke = d; + } + + /** + * 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 input = userInput.getText(); + Ui ui = new Ui(duke); + String response = ui.handleUserInput(input); + dialogContainer.getChildren().addAll( + DialogBox.getUserDialog(input, userImage), + DialogBox.getDukeDialog(response, dukeImage) + ); + userInput.clear(); + } +} \ No newline at end of file diff --git a/src/main/java/ip/src/main/java/Parser.java b/src/main/java/ip/src/main/java/Parser.java new file mode 100644 index 0000000000..11cb508e24 --- /dev/null +++ b/src/main/java/ip/src/main/java/Parser.java @@ -0,0 +1,168 @@ +package ip.src.main.java; + +import java.util.Locale; + +/** + * Parser is a class that parsers user input to retrieve user commands, information to create Task objects etc. + * + */ + +public class Parser { + + //static field to standardize the parsing for Edit commands. + private static final String EDIT_HEADER = "EDIT_"; + + Parser() { + } + + /** + * Retrieves the command entered by the user. + * + * @param input Input entered by user. + * @return Returns the first word that represents the command given by the user. + */ + public Command getCommand(String input) throws DukeException { + String commandType = ""; + if (input.equals("bye")) { + commandType = "bye"; + } else if (input.equals("list")) { + commandType = "list"; + } else { + assert input.length() > 1; + commandType = input.split(" ")[0]; + } + try { + Command command = Command.valueOf(commandType.toUpperCase(Locale.ENGLISH)); + return command; + } catch (IllegalArgumentException e) { + throw new DukeException("OOPS! I don't know what this means! :("); + } + } + + /** + * Gets the specific edit type from the edit command given. + * + * @param input The type of edit stated by the user. + * @return EditType command. + * @throws DukeException + */ + protected EditType getEditType (String input) throws DukeException { + try { + String editType = input.split(" ")[2]; + editType = EDIT_HEADER + editType; + EditType edit = EditType.valueOf(editType.toUpperCase(Locale.ENGLISH)); + return edit; + } catch (Exception e) { + throw new DukeException("OOPS! Invalid edit type! :( \n Edit format should be: edit {index} {type of edit} {edit details}"); + } + } + + /** + * Gets the edit details from the edit command given. + * + * @param input The edit details provided by the users. + * @return Edit details, either new content or new date and time. + * @throws DukeException + */ + protected String getEditDetails (String input) throws DukeException { + try { + input = input.split(" ", 4)[3]; + return input; + } catch (IndexOutOfBoundsException e) { + throw new DukeException(("OOPS!!! The edit details cannot be empty. \n Edit format should be: edit {index} {type of edit} {edit details}")); + } + + } + + + /** + * Retrieves the information needed from the user input for a ToDo object. + * + * @param input User input. + * @return String content needed to create a ToDo Object. + */ + public String toDoTask(String input) throws DukeException { + try { + input = input.split(" ", 2)[1]; + return input; + } catch (IndexOutOfBoundsException e) { + throw new DukeException(("OOPS!!! The description cannot be empty.")); + } + } + + + /** + * Retrieves the information needed from the user input for a Event object. + * + * @param input User input. + * @return String content needed to create a Event Object. + */ + public String eventTaskContent(String input) { + input = input.split(" ", 2)[1]; + String content = input.split("/at")[0]; + return content; + } + + /** + * Retrieves the information needed from the user input for a Event object. + * + * @param input User input. + * @return String date needed to create a Event Object. + */ + public String eventTaskAt(String input) { + input = input.split(" ", 2)[1]; + String at = input.split("/at")[1]; + return at; + } + + /** + * Retrieves the information needed from the user input for a Deadline object. + * + * @param input User input. + * @return String content needed to create a Deadline Object. + */ + public String deadlineTaskContent(String input) { + input = input.split(" ", 2)[1]; + String content = input.split("/by")[0]; + return content; + } + + /** + * Retrieves the information needed from the user input for a Deadline object. + * + * @param input User input. + * @return String date needed to create a Deadline Object. + */ + public String deadlineTaskBy(String input) { + input = input.split(" ", 2)[1]; + String by = input.split("/by")[1]; + return by; + } + + /** + * Gives the ID (position) of the task to be manipulated in the TaskList. + * + * @param input User input. + * @return Integer ID that represents the position (1-th based) of the task in the TaskList. + */ + public int getId(String input) throws DukeException { + try { + int id = Integer.valueOf(input.split(" ")[1]); + return id; + } catch (IndexOutOfBoundsException e) { + throw new DukeException("Invalid input! Please enter in the correct format with the task index!"); + } + + } + + /** + * Retrieves the keyword from the user input to for the find task method. + * + * @param input User input. + * @return The keyword used to find the matching tasks in the Task list. + */ + public String getKeyword(String input) { + String keyword = input.split(" ", 2)[1]; + return keyword; + } +} diff --git a/src/main/java/ip/src/main/java/Storage.java b/src/main/java/ip/src/main/java/Storage.java new file mode 100644 index 0000000000..a8a4bbe180 --- /dev/null +++ b/src/main/java/ip/src/main/java/Storage.java @@ -0,0 +1,107 @@ +package ip.src.main.java; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Scanner; + +/** + * Storage class that deals with loading and updating the tasks in the given file. + * + */ +public class Storage { + protected String filePath; + protected Duke bot; + + Storage (String filePath, Duke bot) { + this.filePath = filePath; + this.bot = bot; + } + + private Task loadToDoTask (String[] taskDataArr) { + String details = taskDataArr[2]; + Task newTask = new ToDo(details); + bot.addToBot(newTask); + return newTask; + } + + private Task loadEventTask (String[] taskDataArr) { + String content = taskDataArr[2]; + String at = taskDataArr[3]; + Task newTask = new Event(content, at); + bot.addToBot(newTask); + return newTask; + } + + private Task loadDeadlineTask (String[] taskDataArr) { + String content = taskDataArr[2]; + String by = taskDataArr[3]; + Task newTask = new Deadline(content, by); + bot.addToBot(newTask); + return newTask; + } + + /** + * Updates the Duke bot with the tasks by loading the tasks in the file. + * Task is in the format {type} | {doneStatus} | {details}. + * + * @param taskData The task from the file. + * @throws FileNotFoundException + */ + public void loadTasks(String taskData) throws FileNotFoundException { + // create a File for the given file path + File f = new File(this.filePath); + // create a Scanner using the File as the source + Scanner s = new Scanner(f); + + String[] taskDataArr = taskData.split(" \\| "); + String type = taskDataArr[0]; + String doneStatus = taskDataArr[1]; + Task newTask = new Task(""); + + if (newTask.isToDoTask(type)) { + newTask = loadToDoTask(taskDataArr); + } else if (newTask.isEventTask(type)) { + newTask = loadEventTask(taskDataArr); + } else { + assert type.equals("D"); + newTask = loadDeadlineTask(taskDataArr); + } + + if (newTask.isDone(doneStatus)) { + newTask.markDone(); + } + } + + /** + * Updates the Duke bot with the tasks stored in the file by calling the loadTask method. + * + * @param filePath The file with the tasks. + * @param bot The duke bot. + * @throws FileNotFoundException + */ + public void createBot(String filePath, Duke bot) throws FileNotFoundException { + // create a File for the given file path + File f = new File(filePath); + // create a Scanner using the File as the source + Scanner s = new Scanner(f); + Storage storage = new Storage(filePath, bot); + + while (s.hasNext()) { + storage.loadTasks(s.nextLine()); + } + } + + /** + * Updates the file at the specific relative filepath with the bot's final tasklist. + * + * @throws IOException + */ + public void updateFile() throws IOException { + FileWriter fw = new FileWriter(this.filePath); + for (Task element:this.bot.list.list) { + fw.write(element.toString() + "\n"); + } + fw.close(); + } +} diff --git a/src/main/java/ip/src/main/java/Task.java b/src/main/java/ip/src/main/java/Task.java new file mode 100644 index 0000000000..af0236b22d --- /dev/null +++ b/src/main/java/ip/src/main/java/Task.java @@ -0,0 +1,78 @@ +package ip.src.main.java; + +/** + * Task class that stores Task details and Task status. + * + */ + +public class Task { + //int id; + protected String content; + protected boolean done = false; + + public Task(String content) { + //this.id = id; + this.content = content; + + } + + /** + * Updates the Task Status to completed. + */ + public void markDone() { + this.done = true; + } + + public boolean isDone(String doneStatus) { + return doneStatus.equals(" 1 "); + } + + /** + * Checks if Task content has matching keyword. + * + * @return Returns True if task content has keyword. + */ + public boolean isMatch(String keyword) { + return this.content.contains(keyword); + } + + protected boolean isToDoTask(String inputType) { + return inputType.equals("T"); + } + + protected boolean isEventTask(String inputType) { + return inputType.equals("E"); + } + + /** + *Dummy method for editing the content of the old task. + * Exact implementations in each child class, utilizing Polymorphism when editContent is called. + * + * @param newContent New content given by user. + * @return A clone of the old task with the new content change. + */ + protected Task editContent (String newContent) { + Task newTask = new Task(newContent); + newTask.done = this.done; + return newTask; + } + + /** + * Dummy method for editDate in Task. + * Exact implementations in each child class, utilizing Polymorphism when editDate is called. + * + * @param newDate New date given by user. + */ + protected Task editDate (String newDate) { + return this; + } + + + public String toString() { + return this.content; + } + + +} + + diff --git a/src/main/java/ip/src/main/java/TaskList.java b/src/main/java/ip/src/main/java/TaskList.java new file mode 100644 index 0000000000..f3e5552f73 --- /dev/null +++ b/src/main/java/ip/src/main/java/TaskList.java @@ -0,0 +1,129 @@ +package ip.src.main.java; +import java.util.ArrayList; +import java.util.List; + +/** + * TaskList stores and manipulate the tasks in a List. + * + */ +public class TaskList { + protected List list; + + TaskList() { + this.list = new ArrayList<>(); + } + + /** + * Adds a Task to the list. + * + * @param task New Task to be added to list. + */ + public void addTask(Task task) { + this.list.add(task); + } + + /** + * Checks if list is empty. + * + * @return Boolean to indicate if list is empty. + */ + public boolean isEmpty() { + return this.list.isEmpty(); + } + + /** + * Prints the tasks in the bot's tasklist. + * + * @return A string representation of the list of the tasks in the tasklist. + */ + public String printTasks() { + int counter = 1; + String output = ""; + for (Task element : this.list) { + output += String.valueOf(counter) + ". " + element + "\n"; + counter++; + } + output += "Now you have " + String.valueOf(this.list.size()) + " tasks in the list."; + return output; + } + + /** + * Prints the tasks that contain the keyword/s from the bot's tasklist. + * + * @return A string representation of the list of matching tasks. + */ + public String printMatchingTasks() { + int counter = 1; + String output = ""; + for (Task element : this.list) { + output += String.valueOf(counter) + ". " + element + "\n"; + counter++; + } + output += "You have " + String.valueOf(this.list.size()) + " matching tasks from the list!"; + return output; + } + + /** + * Prints the edited bot's tasklist. + * + * @return A string representation of the newly edited tasks in the tasklist. + */ + public String printEditedTasks() { + int counter = 1; + String output = ""; + for (Task element : this.list) { + output += String.valueOf(counter) + ". " + element + "\n"; + counter++; + } + return output; + } + + /** + * Gets the task at a specified position in the list. + * + * @param id The position of the task to be retrieved in the list. + * @return A task in the list. + */ + public Task getTask(int id) { + return this.list.get(id); + } + + /** + * Removes a task at a specified position in the list. + * + * @param id The position of the task to be removed from the list. + */ + public void remove(int id) { + this.list.remove(id); + } + + /** + * Returns size of the Task list. + * + * @return The number of tasks in the list. + */ + public int size() { + return this.list.size(); + } + + /** + * Gets the matching tasks that contain the keyword/s. + * + * @param keyword Keyword/s given by user. + * @return A tasklist of tasks that contain the keyword/s. + */ + public TaskList findTasks(String keyword) { + TaskList taskListWithMatches = new TaskList(); + + for (Task task: this.list) { + if (task.isMatch(keyword)) { + taskListWithMatches.addTask(task); + } + } + return taskListWithMatches; + } + + protected void editTask(Task newTask , int id) { + this.list.set(id , newTask); + } +} diff --git a/src/main/java/ip/src/main/java/ToDo.java b/src/main/java/ip/src/main/java/ToDo.java new file mode 100644 index 0000000000..bdf4f5892d --- /dev/null +++ b/src/main/java/ip/src/main/java/ToDo.java @@ -0,0 +1,39 @@ +package ip.src.main.java; + +/** + * ToDo class is a type of Task that has attribute String content. + * + */ + +public class ToDo extends Task { + + public ToDo(String content) { + super(content); + } + + /** + *Edits the content of the ToDo task by cloning the old ToDo task. + * + * @param newContent New content given by user. + * @return A clone of the old ToDo task with the new content change. + */ + public ToDo editContent (String newContent) { + ToDo newTask = new ToDo(newContent); + newTask.done = this.done; + return newTask; + } + + /** + * toString() of ToDo Class. + * + * @return toString() representation of a ToDo object with its done status and content. + */ + @Override + public String toString() { + if (!this.done) { + return "T | 0 | " + super.toString(); + } else { + return "T | 1 | " + super.toString(); + } + } +} diff --git a/src/main/java/ip/src/main/java/Ui.java b/src/main/java/ip/src/main/java/Ui.java new file mode 100644 index 0000000000..42c42f6033 --- /dev/null +++ b/src/main/java/ip/src/main/java/Ui.java @@ -0,0 +1,171 @@ +package ip.src.main.java; + +import java.io.IOException; + +/** + * Ui class deals with user interactions. + * + */ + +public class Ui { + protected Duke bot; + + public Ui(Duke bot) { + this.bot = bot; + } + + /** + * Deals with the done command by the user by telling the bot to mark a specified task as done. + * + * @param id The specified position of the task which status is to be updated as done in the Task List. + */ + public String doneCommand(int id) { + return this.bot.markTaskAsDone(id); + } + + /** + * Deals with the ToDo command. Creates a ToDo task from the input + * and tells the bot to add the new task to its Task list. + * + * @param content Content of the ToDo object. + */ + private String toDoCommand(String content) { + ToDo newTask = new ToDo(content); + return this.bot.addToList(newTask); + } + + /** + * Deals with the Event command. + * Creates a Event task from the input and tells the bot to add the new task to its Task list. + * + * @param content Content of the Event object. + * @param at Date of the Event object. + */ + private String eventCommand(String content, String at) { + Event newTask = new Event(content, at); + return this.bot.addToList(newTask); + + } + + /** + * Deals with the Deadline command. + * Creates a Deadline task from the input and tells the bot to add the new task to its Task list. + * + * @param content Content of the Event object. + * @param by Date of the Event object. + */ + private String deadlineCommand(String content, String by) { + Deadline newTask = new Deadline(content, by); + return this.bot.addToList(newTask); + } + + private String editCommand(String editDetails , int id , EditType editType) throws DukeException { + try { + Task oldTask = this.bot.getTask(id-1); + Task newTask = new Task(""); + + switch (editType) { + case EDIT_DATETIME: + newTask = oldTask.editDate(editDetails); + break; + + case EDIT_CONTENT: + newTask = oldTask.editContent(editDetails); + break; + + default: + assert false : editType; + } + return this.bot.editTask(newTask , id); + } catch (IndexOutOfBoundsException e) { + throw new DukeException("Index is out of bounds! \n Please enter a valid task number!"); + } + } + + /** + * Deals with the Delete command. Tells the bot to remove a task from its Task list. + * + * @param id The specified position of the task to be removed from the bot Task List. + */ + public String deleteCommand(int id) throws DukeException { + try { + return this.bot.deleteTask(id-1); + } catch (IndexOutOfBoundsException e) { + throw new DukeException("Index is out of bounds! \n Please enter a valid task number!"); + } + } + + /** + * Handles user input for the different commands given by the user. + * Gets the result string to respond to the user. + * + * @param input User input. + * @return Result string. + */ + public String handleUserInput(String input) { + Parser parser = new Parser(); + String output = ""; + try { + Command command = parser.getCommand(input); + switch (command) { + + case BYE: + Storage storage = new Storage("data/duke.txt" , this.bot); + output = this.bot.bye(storage); + break; + + case LIST: + output = this.bot.printList(); + break; + + case DONE: + int id = parser.getId(input); + output = doneCommand(id); + break; + + case FIND: + String keyword = parser.getKeyword(input); + output = this.bot.findMatchingTasks(keyword); + break; + + case TODO: + input = parser.toDoTask(input); + output = toDoCommand(input); + break; + + case EVENT: + String content = parser.eventTaskContent(input); + String at = parser.eventTaskAt(input); + output = eventCommand(content, at); + break; + + case DEADLINE: + content = parser.deadlineTaskContent(input); + String by = parser.deadlineTaskBy(input); + output = deadlineCommand(content, by); + break; + + case EDIT: + id = parser.getId(input); + EditType editType = parser.getEditType(input); + String editDetails = parser.getEditDetails(input); + output = editCommand(editDetails , id , editType); + break; + + case DELETE: + id = parser.getId(input); + output = deleteCommand(id); + break; + + default: + assert false : command; + } + + } catch (DukeException e1) { + output = e1.getMessage(); + } + return output; + } + +} + diff --git a/src/main/resources/images/MaskedPikachu.png b/src/main/resources/images/MaskedPikachu.png new file mode 100644 index 0000000000..009c0e5b13 Binary files /dev/null and b/src/main/resources/images/MaskedPikachu.png differ diff --git a/src/main/resources/images/MaskedSquirtle.png b/src/main/resources/images/MaskedSquirtle.png new file mode 100644 index 0000000000..1ef91c0718 Binary files /dev/null and b/src/main/resources/images/MaskedSquirtle.png differ diff --git a/src/main/resources/view/DialogBox.fxml b/src/main/resources/view/DialogBox.fxml new file mode 100644 index 0000000000..c9521bd5af --- /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 0000000000..e35f459ae4 --- /dev/null +++ b/src/main/resources/view/MainWindow.fxml @@ -0,0 +1,19 @@ + + + + + + + + + + + +