diff --git a/README.md b/README.md index 8715d4d915..bb36c63031 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,27 @@ -# Duke project template - -This is a project template for a greenfield Java project. It's named after the Java mascot _Duke_. Given below are instructions on how to use it. - -## Setting up in Intellij - -Prerequisites: JDK 11, update Intellij to the most recent version. - -1. Open Intellij (if you are not in the welcome screen, click `File` > `Close Project` to close the existing project first) -1. Open the project into Intellij as follows: - 1. Click `Open`. - 1. Select the project directory, and click `OK`. - 1. If there are any further prompts, accept the defaults. -1. Configure the project to use **JDK 11** (not other versions) as explained in [here](https://www.jetbrains.com/help/idea/sdk.html#set-up-jdk).
- In the same dialog, set the **Project language level** field to the `SDK default` option. -3. After that, locate the `src/main/java/Duke.java` file, right-click it, and choose `Run Duke.main()` (if the code editor is showing compile errors, try restarting the IDE). If the setup is correct, you should see something like the below as the output: - ``` - Hello from - ____ _ - | _ \ _ _| | _____ - | | | | | | | |/ / _ \ - | |_| | |_| | < __/ - |____/ \__,_|_|\_\___| - ``` +### DUKE + +> “Your mind is for having ideas, not holding them.” – David Allen (source) + +Hi this is my Duke program! It's + +- _Fun_ 👍 +- Easy to use +- text-based + +Steps to use: + +1. Download from [here](https://github.com/nus-cs2103-AY2122S1/ip/pull/461) +2. Run +3. **Use!** + +Features: + +- [x] Managing tasks +- [ ] GUI + +Sample code `main` : +```java +public static void main(String[] args) { + new Duke().run(); + } +``` diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000..b8fa30093a --- /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 = "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 0000000000..7951f3a6c4 --- /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..135ea49ee0 --- /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..def35aca62 --- /dev/null +++ b/data/duke.txt @@ -0,0 +1,8 @@ +todo | 0 | Do +event | 0 | Dinner with Friends | 2021-10-10 +todo | 0 | test +todo | 0 | test +todo | 0 | ts +todo | 0 | test3 +todo | 0 | test44 +todo | 0 | sdfaafd diff --git a/docs/README.md b/docs/README.md index 8077118ebe..58c8ae65ac 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,29 +1,87 @@ # User Guide +Magnolia is a desktop app for managing your tasks. It is simple and lightweight. +Tasks can be added to the list through simple commands. + ## Features -### Feature-ABC +### Add Task + +Adds a task to the list. There are 4 tasks. Todos, Events, Deadlines, and Withins. +* Todos are the most simple task with just a description +* Events also have a date in which it occurs +* Deadlines have the deadline of the task +* Within tasks have 2 dates for the timeframe to complete the task + +### Delete Task + +Delete task from list. + +### Find Task + +Find tasks in list using keywords. + +### List Tasks -Description of the feature. +Show a list of all tasks -### Feature-XYZ +### Mark Task -Description of the feature. +Mark task as complete ## Usage -### `Keyword` - Describe action +### `Add Task` -Describe the action and its outcome. +Add task to list. + +Format: +* `todo DESCRIPTION` +* `event DESCRIPTION at DATE` +* `deadline DESCRIPTION by DATE` +* `within DESCRIPTION between DATE and DATE` + +Date in YYYY-MM-DD format Example of usage: +* `todo Clean Room` +* `within Cancel Subscription between 2021-09-10 and 2021-10-05` +* `event Dinner with Family at 2021-09-17` + +### `delete` + +Deletes task from list. + +Format: `delete NUMBER` + + +Number is index of task to be deleted + +Example of usage: `delete 3` + +### `find` + +Finds tasks that matches keywords. + +Format: `find KEYWORDS` + +Example of usage: `find homework` + +### `list` + +Lists all tasks. + +Format: `list` + +### `done` + +Marks task as done. + +Format: `done NUMBER` + -`keyword (optional arguments)` +Number is index of task to be marked -Expected outcome: +Example of usage: `done 4` -Description of the outcome. -``` -expected output -``` diff --git a/docs/Ui.png b/docs/Ui.png new file mode 100644 index 0000000000..6cc5e8a1d7 Binary files /dev/null and b/docs/Ui.png differ diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..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/java/Duke.java b/src/main/java/Duke.java deleted file mode 100644 index 5d313334cc..0000000000 --- a/src/main/java/Duke.java +++ /dev/null @@ -1,10 +0,0 @@ -public class Duke { - public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - } -} diff --git a/src/main/java/duke/Command/AddCommand.java b/src/main/java/duke/Command/AddCommand.java new file mode 100644 index 0000000000..8ae7f35f61 --- /dev/null +++ b/src/main/java/duke/Command/AddCommand.java @@ -0,0 +1,90 @@ +package duke.Command; + +import duke.DukeException; +import duke.Parser.Type; +import duke.Storage; +import duke.Task; +import duke.TaskList; +import duke.Ui; + +/** + * Command to add task to list + */ +public class AddCommand extends Command { + private Type type; + private String description; + + + /** + * Constructor for AddCommand + * + * @param type Type of task + * @param description Description of task + */ + public AddCommand(Type type, String description) throws DukeException { + this.type = type; + this.description = description; + } + + /** + * Adds task to list + * + * @param tasks Current TaskList + * @param ui Ui object of bot + * @param storage Storage object of bot + * @return Confirmation message + * @throws DukeException when incorrect input + */ + @Override + public String execute(TaskList tasks, Ui ui, Storage storage) throws DukeException { + Task task = null; + switch (type) { + case todo: + task = new Task.Todo(description, false); + break; + case deadline: + String[] temp1 = description.split("by "); + try { + task = new Task.Deadline(temp1[0], false, temp1[1]); + } catch (ArrayIndexOutOfBoundsException e) { + throw new DukeException("Format of deadline command is: 'deadline DESCRIPTION by DATE'"); + } + break; + case event: + String[] temp2 = description.split("at "); + try { + task = new Task.Event(temp2[0], false, temp2[1]); + } catch (ArrayIndexOutOfBoundsException e) { + throw new DukeException("Format of event command is: 'event DESCRIPTION at DATE'"); + } + break; + case within: + String[] temp3 = description.split("between | and "); + try { + task = new Task.Within(temp3[0], false, temp3[1], temp3[2]); + } catch (ArrayIndexOutOfBoundsException e) { + throw new DukeException("Format of within command is: 'within DESCRIPTION between DATE and DATE'"); + } + break; + default: + } + + assert task != null; + tasks.addTask(task); + String result = ""; + result += ("Added: " + task.getTaskType() + task.getStatusIcon() + " " + task.getDescription() + "\n"); + result += ("There are " + tasks.size() + " tasks in the list"); + storage.save(tasks); + return result; + } + + /** + * Checks if Command is ExitCommand + * + * @return false + */ + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/duke/Command/Command.java b/src/main/java/duke/Command/Command.java new file mode 100644 index 0000000000..65e615e0b9 --- /dev/null +++ b/src/main/java/duke/Command/Command.java @@ -0,0 +1,26 @@ +package duke.Command; + +import duke.DukeException; +import duke.Storage; +import duke.TaskList; +import duke.Ui; + +public abstract class Command { + /** + * Executes command based on which command it is + * + * @param tasks Current TaskList + * @param ui Ui object of bot + * @param storage Storage object of bot + * @return Confirmation message + * @throws DukeException + */ + public abstract String execute(TaskList tasks, Ui ui, Storage storage) throws DukeException; + + /** + * Checks if Command is ExitCommand + * + * @return true if ExitCommand + */ + public abstract boolean isExit(); +} diff --git a/src/main/java/duke/Command/DeleteCommand.java b/src/main/java/duke/Command/DeleteCommand.java new file mode 100644 index 0000000000..84b037e55f --- /dev/null +++ b/src/main/java/duke/Command/DeleteCommand.java @@ -0,0 +1,47 @@ +package duke.Command; + +import duke.DukeException; +import duke.Storage; +import duke.Task; +import duke.TaskList; +import duke.Ui; + +/** + * Command to delete task from list + */ +public class DeleteCommand extends Command { + private int index; + + /** + * Constructs delete command + * @param index Index of task to be deleted + */ + public DeleteCommand(int index) { + this.index = index; + } + + /** + * Delete task from list + * @param tasks Current TaskList + * @param ui Ui object of bot + * @param storage Storage object of bot + * @return Confirmation message + * @throws DukeException when problem deleting task + */ + @Override + public String execute(TaskList tasks, Ui ui, Storage storage) throws DukeException { + int size = tasks.size(); + Task task = tasks.deleteTask(index); + assert tasks.size() == size - 1; + String result = ""; + result += ("Deleted:\n" + task.getDescription() + "\n"); + result += ("There are " + tasks.size() + " tasks remaining in the list"); + storage.save(tasks); + return result; + } + + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/duke/Command/DoneCommand.java b/src/main/java/duke/Command/DoneCommand.java new file mode 100644 index 0000000000..0c0a88508c --- /dev/null +++ b/src/main/java/duke/Command/DoneCommand.java @@ -0,0 +1,43 @@ +package duke.Command; + +import duke.DukeException; +import duke.Storage; +import duke.Task; +import duke.TaskList; +import duke.Ui; + +/** + * Command to mark task as done + */ +public class DoneCommand extends Command { + + private int index; + + /** + * Constructs done command + * @param index Index of task to be marked as done + */ + public DoneCommand(int index) { + this.index = index; + } + + /** + * Marks task as done + * @param tasks Current TaskList + * @param ui Ui object of bot + * @param storage Storage object of bot + * @return Confirmation message + * @throws DukeException when problem saving tasks + */ + @Override + public String execute(TaskList tasks, Ui ui, Storage storage) throws DukeException { + Task task = tasks.doneTask(this.index); + storage.save(tasks); + return ("Marked as done:\n" + task.getDescription()); + } + + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/duke/Command/ExitCommand.java b/src/main/java/duke/Command/ExitCommand.java new file mode 100644 index 0000000000..5af159fe53 --- /dev/null +++ b/src/main/java/duke/Command/ExitCommand.java @@ -0,0 +1,28 @@ +package duke.Command; + +import duke.Storage; +import duke.TaskList; +import duke.Ui; + +/** + * Command to exit program + */ +public class ExitCommand extends Command { + + /** + * Exits program + * @param tasks Current TaskList + * @param ui Ui object of bot + * @param storage Storage object of bot + * @return Confirmation message + */ + @Override + public String execute(TaskList tasks, Ui ui, Storage storage) { + return ("Bye. Hope to see you again soon!"); + } + + @Override + public boolean isExit() { + return true; + } +} diff --git a/src/main/java/duke/Command/FindCommand.java b/src/main/java/duke/Command/FindCommand.java new file mode 100644 index 0000000000..3b7438c09a --- /dev/null +++ b/src/main/java/duke/Command/FindCommand.java @@ -0,0 +1,49 @@ +package duke.Command; + +import java.util.ArrayList; + +import duke.Storage; +import duke.Task; +import duke.TaskList; +import duke.Ui; + +/** + * Command to find tasks + */ +public class FindCommand extends Command { + private String keyword; + + /** + * Constructs find command + * @param keyword keyword used to search tasks + */ + public FindCommand(String keyword) { + this.keyword = keyword; + } + + /** + * Finds tasks that matches keyword + * @param tasks Current TaskList + * @param ui Ui object of bot + * @param storage Storage object of bot + * @return List of tasks found + */ + @Override + public String execute(TaskList tasks, Ui ui, Storage storage) { + ArrayList list = tasks.getList(); + list.removeIf(task -> !task.getDescription().contains(this.keyword)); + String result = ""; + if (list.size() == 0) { + result += ("No matching tasks found."); + } else { + result += (list.size() + " matching task(s):" + "\n"); + result += (new TaskList(list).allTasks()); + } + return result; + } + + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/duke/Command/ListCommand.java b/src/main/java/duke/Command/ListCommand.java new file mode 100644 index 0000000000..261aba8c44 --- /dev/null +++ b/src/main/java/duke/Command/ListCommand.java @@ -0,0 +1,31 @@ +package duke.Command; + +import duke.Storage; +import duke.TaskList; +import duke.Ui; + +/** + * Command to list all tasks + */ +public class ListCommand extends Command { + + /** + * List all tasks + * @param tasks Current TaskList + * @param ui Ui object of bot + * @param storage Storage object of bot + * @return List of all tasks + */ + @Override + public String execute(TaskList tasks, Ui ui, Storage storage) { + String result = ""; + result += ("All tasks:" + "\n"); + result += (tasks.allTasks()); + return result; + } + + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/duke/DialogBox.java b/src/main/java/duke/DialogBox.java new file mode 100644 index 0000000000..cbdbd0b7e5 --- /dev/null +++ b/src/main/java/duke/DialogBox.java @@ -0,0 +1,74 @@ +package duke; + +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; +import javafx.scene.shape.Circle; + +/** + * Dialog box of chat box. From JavaFX tutorial. + */ +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); + displayPicture.setClip(new Circle(displayPicture.getFitWidth() / 2, + displayPicture.getFitHeight() / 2.1, 37)); + } + + /** + * 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); + } + + /** + * Get user dialog + * @param text User text + * @param img User image + * @return User dialog box + */ + public static DialogBox getUserDialog(String text, Image img) { + return new DialogBox(text, img); + } + + /** + * Get bot dialog + * @param text Bot text + * @param img Bot image + * @return Bot dialog box + */ + 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/Duke.java b/src/main/java/duke/Duke.java new file mode 100644 index 0000000000..c0baca4a76 --- /dev/null +++ b/src/main/java/duke/Duke.java @@ -0,0 +1,45 @@ +package duke; + +import duke.Command.Command; + +/** + * Main class of the bot + */ +public class Duke { + + private Storage storage; + private TaskList tasks; + private Ui ui; + + + /** + * Constructs Duke object with Ui, Storage and Tasklist. + */ + public Duke() { + ui = new Ui(); + storage = new Storage("data/duke.txt"); + try { + tasks = new TaskList(storage.load()); + } catch (DukeException e) { + tasks = new TaskList(); + } + } + + /** + * Executes command and returns the reply + * @param input User input entered + * @return The reply by bot + */ + public String getResponse(String input) { + try { + Command c = Parser.parse(input); + String output = c.execute(tasks, ui, storage); + return output; + } catch (DukeException e) { + return e.getMessage(); + } + + + } + +} diff --git a/src/main/java/duke/DukeException.java b/src/main/java/duke/DukeException.java new file mode 100644 index 0000000000..663862fead --- /dev/null +++ b/src/main/java/duke/DukeException.java @@ -0,0 +1,11 @@ +package duke; + +/** + * DukeException when any error in task bot + */ +public class DukeException extends Exception { + public DukeException(String errorMessage) { + super(errorMessage); + } + +} diff --git a/src/main/java/duke/Launcher.java b/src/main/java/duke/Launcher.java new file mode 100644 index 0000000000..44e5009f53 --- /dev/null +++ b/src/main/java/duke/Launcher.java @@ -0,0 +1,12 @@ +package duke; + +import javafx.application.Application; + +/** + * Launches application + */ +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 0000000000..22c20620aa --- /dev/null +++ b/src/main/java/duke/Main.java @@ -0,0 +1,35 @@ +package duke; + +import java.io.IOException; + +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.layout.AnchorPane; +import javafx.stage.Stage; + +/** + * A GUI for Duke using FXML. + */ +public class Main extends Application { + + private Duke duke = new Duke(); + + /** + * Starts window. From JavaFX tutorial. + * @param stage Stage used + */ + @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/MainWindow.java b/src/main/java/duke/MainWindow.java new file mode 100644 index 0000000000..9b107cd12b --- /dev/null +++ b/src/main/java/duke/MainWindow.java @@ -0,0 +1,57 @@ +package duke; + +import javafx.application.Platform; +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 duke.MainWindow. Provides the layout for the other controls. From JavaFX tutorial. + */ +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/default_user.png")); + private Image dukeImage = new Image(this.getClass().getResourceAsStream("/images/magnolia.jpg")); + + @FXML + public void initialize() { + scrollPane.vvalueProperty().bind(dialogContainer.heightProperty()); + } + + public void setDuke(Duke d) { + duke = d; + dialogContainer.getChildren().add(DialogBox.getDukeDialog(Ui.greet(), dukeImage)); + } + + /** + * Creates two dialog boxes, one echoing user input and the other containing Duke's reply and then appends them to + * the dialog container. Clears the user input after processing. From JavaFX tutorial. + */ + @FXML + private void handleUserInput() { + String input = userInput.getText(); + String response = duke.getResponse(input); + dialogContainer.getChildren().addAll( + DialogBox.getUserDialog(input, userImage), + DialogBox.getDukeDialog(response, dukeImage) + ); + if (input.equals("bye")) { + Platform.exit(); + } + userInput.clear(); + } +} diff --git a/src/main/java/duke/Parser.java b/src/main/java/duke/Parser.java new file mode 100644 index 0000000000..2e99e9e16d --- /dev/null +++ b/src/main/java/duke/Parser.java @@ -0,0 +1,82 @@ +package duke; + +import duke.Command.AddCommand; +import duke.Command.Command; +import duke.Command.DeleteCommand; +import duke.Command.DoneCommand; +import duke.Command.ExitCommand; +import duke.Command.FindCommand; +import duke.Command.ListCommand; + +/** + * Class with methods to parse user input + */ +public class Parser { + /** + * List of valid commands + */ + public enum Type { + bye, + list, + done, + delete, + find, + todo, + deadline, + event, + within + } + /** + * Parses the input provided into relevant Commands + * + * @param input String of next line of user input + * @return Relevant Command corresponding to input + * @throws DukeException when invalid input + */ + public static Command parse(String input) throws DukeException { + Type firstWord = null; + try { + firstWord = Type.valueOf(input.split(" ")[0]); + } catch (IllegalArgumentException e) { + throw new DukeException("Sorry, I don't understand what that means. :("); + } + assert firstWord != null; + String errorMsg; + switch (firstWord) { + case bye: + return new ExitCommand(); + case list: + return new ListCommand(); + case done: + errorMsg = "Sorry, please enter an integer after 'done'. (e.g. done 2)"; + int index = Integer.parseInt(secondParameter(input, errorMsg)) - 1; + return new DoneCommand(index); + case delete: + errorMsg = "Sorry, please enter an integer after 'delete'. (e.g. delete 2)"; + int index2 = Integer.parseInt(secondParameter(input, errorMsg)) - 1; + return new DeleteCommand(index2); + case find: + errorMsg = "Sorry, please enter a keyword after 'find'."; + String remaining = secondParameter(input, errorMsg); + return new FindCommand(remaining); + default: + errorMsg = "Sorry, tasks must include descriptions."; + String remaining2 = secondParameter(input, errorMsg); + return new AddCommand(firstWord, remaining2); + } + } + /** + * Gets the parameter after the command. + * @param input Input to be parsed + * @param error Error Message if nothing after command + * @return String of second parameter + * @throws DukeException when nothing after command + */ + private static String secondParameter(String input, String error) throws DukeException { + try { + return input.split(" ", 2)[1]; + } catch (ArrayIndexOutOfBoundsException e) { + throw new DukeException(error); + } + } +} diff --git a/src/main/java/duke/Storage.java b/src/main/java/duke/Storage.java new file mode 100644 index 0000000000..bed31f3247 --- /dev/null +++ b/src/main/java/duke/Storage.java @@ -0,0 +1,83 @@ +package duke; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Scanner; + +/** + * Class that handles storing and loading data + */ +public class Storage { + private String filepath; + + /** + * Constructs new storage object + * @param filepath filepath to store data + */ + public Storage(String filepath) { + this.filepath = filepath; + } + + /** + * Loads task data from storage + * + * @return ArrayList of tasks + * @throws DukeException when file not found + */ + public ArrayList load() throws DukeException { + ArrayList list = new ArrayList<>(); + File listData = new File(filepath); + Scanner reader; + try { + reader = new Scanner(listData); + } catch (FileNotFoundException e) { + throw new DukeException("File not found"); + } + + while (reader.hasNextLine()) { + String line = reader.nextLine(); + String[] data = line.split(" \\| "); + switch (data[0]) { + case "todo": + list.add(new Task.Todo(data[2], data[1].equals("0") ? false : true)); + break; + case "deadline": + list.add(new Task.Deadline(data[2], data[1].equals("0") ? false : true, data[3])); + break; + case "event": + list.add(new Task.Event(data[2], data[1].equals("0") ? false : true, data[3])); + break; + case "within": + list.add(new Task.Within(data[2], data[1].equals("0") ? false : true, data[3], data[4])); + break; + default: + throw new DukeException("Invalid input"); + } + } + reader.close(); + return list; + } + + /** + * Saves all tasks in TaskList to filepath of storage + * + * @param list TaskList to be saved + */ + public void save(TaskList list) { + try { + File listData = new File(filepath); + Files.createDirectories(Paths.get("data/")); + FileWriter myWriter = new FileWriter(listData); + myWriter.write(list.toString()); + myWriter.close(); + } catch (IOException e) { + System.out.println("File not found"); + } + } + +} diff --git a/src/main/java/duke/Task.java b/src/main/java/duke/Task.java new file mode 100644 index 0000000000..0d5b528d5c --- /dev/null +++ b/src/main/java/duke/Task.java @@ -0,0 +1,224 @@ +package duke; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.time.format.FormatStyle; + +/** + * Task class that includes Todos, Events, Deadline and Within. + */ +public class Task { + protected String description; + protected boolean isComplete; + + /** + * Constructs generic Task object + * + * @param description Description of task + * @param isComplete Completion status of Task + */ + private Task(String description, boolean isComplete) { + this.description = description; + this.isComplete = isComplete; + } + + /** + * Returns the corresponding status icon + * + * @return Corresponding status icon + */ + public String getStatusIcon() { + return (isComplete ? "[X]" : "[ ]"); + } + + public String getTaskType() { + return "[ ]"; + } + + public String getDescription() { + return this.description; + } + + public void setComplete(boolean complete) { + this.isComplete = complete; + } + + public static class Todo extends Task { + /** + * Constructs Todo task + * + * @param description Description for the task + * @param status Completion status of task + */ + public Todo(String description, boolean status) { + super(description, status); + } + + @Override + public String getTaskType() { + return "[T]"; + } + + /** + * Formats task information into String format to be saved onto storage + * + * @return String containing task info + */ + @Override + public String toString() { + return "todo" + " | " + (this.isComplete ? "1" : "0") + " | " + this.description; + } + + } + + public static class Deadline extends Task { + private LocalDate by; + + + /** + * Constructs Deadline task + * + * @param description Description for the task + * @param status Completion status of task + * @param by Deadline of task in YYYY-MM-DD format + */ + public Deadline(String description, boolean status, String by) throws DukeException { + super(description, status); + try { + this.by = LocalDate.parse(by, DateTimeFormatter.ISO_LOCAL_DATE); + } catch (DateTimeParseException e) { + throw new DukeException("Please enter date in format YYYY-MM-DD"); + } + + } + + @Override + public String getTaskType() { + return "[D]"; + } + + /** + * Returns description of task including deadline + * + * @return Description of task including deadline + */ + @Override + public String getDescription() { + return super.getDescription() + "(by: " + + this.by.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)) + ")"; + } + + /** + * Formats task information into String format to be saved onto storage + * + * @return String containing task info + */ + @Override + public String toString() { + return "deadline" + " | " + (this.isComplete ? "1" : "0") + " | " + this.description + " | " + this.by; + } + + } + + public static class Event extends Task { + private LocalDate at; + + /** + * Constructs Event task + * + * @param description Description for the task + * @param status Completion status of task + * @param at Deadline of task in YYYY-MM-DD format + */ + public Event(String description, boolean status, String at) throws DukeException { + super(description, status); + try { + this.at = LocalDate.parse(at, DateTimeFormatter.ISO_LOCAL_DATE); + } catch (DateTimeParseException e) { + throw new DukeException("Please enter date in format YYYY-MM-DD"); + } + } + + @Override + public String getTaskType() { + return "[E]"; + } + + /** + * Returns description of task including date + * + * @return Description of task including date + */ + @Override + public String getDescription() { + return super.getDescription() + "(at: " + + this.at.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)) + ")"; + } + + /** + * Formats task information into String format to be saved onto storage + * + * @return String containing task info + */ + @Override + public String toString() { + return "event" + " | " + (this.isComplete ? "1" : "0") + " | " + this.description + " | " + this.at; + } + + } + + public static class Within extends Task { + private LocalDate firstDate; + private LocalDate secondDate; + + /** + * Constructs Within task + * + * @param description Description for the task + * @param status Completion status of task + * @param firstDate Starting timeframe of task in YYYY-MM-DD format + * @param secondDate Ending timeframe of task in YYYY-MM-DD format + * @throws DukeException When date format is incorrect + */ + public Within(String description, boolean status, String firstDate, String secondDate) throws DukeException { + super(description, status); + try { + this.firstDate = LocalDate.parse(firstDate, DateTimeFormatter.ISO_LOCAL_DATE); + this.secondDate = LocalDate.parse(secondDate, DateTimeFormatter.ISO_LOCAL_DATE); + } catch (DateTimeParseException e) { + throw new DukeException("Please enter date in format YYYY-MM-DD"); + } + } + + @Override + public String getTaskType() { + return "[W]"; + } + + /** + * Returns description of task including date + * + * @return Description of task including date + */ + @Override + public String getDescription() { + return super.getDescription() + "(between " + + this.firstDate.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)) + + " and " + + this.secondDate.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)) + ")"; + } + + /** + * Formats task information into String format to be saved onto storage + * + * @return String containing task info + */ + @Override + public String toString() { + return "within" + " | " + (this.isComplete ? "1" : "0") + " | " + this.description + " | " + + this.firstDate + " | " + this.secondDate; + } + + } +} diff --git a/src/main/java/duke/TaskList.java b/src/main/java/duke/TaskList.java new file mode 100644 index 0000000000..8accad4916 --- /dev/null +++ b/src/main/java/duke/TaskList.java @@ -0,0 +1,127 @@ +package duke; + +import java.util.ArrayList; + +/** + * Handles any interaction with task list + */ +public class TaskList { + private ArrayList list; + + /** + * Constructs an empty TaskList + */ + public TaskList() { + this.list = new ArrayList<>(); + } + + /** + * Constructs a TaskList using an ArrayList of Tasks + * + * @param list ArrayList of Tasks to be used + */ + public TaskList(ArrayList list) { + this.list = list; + } + + /** + * Adds Task to TaskList + * + * @param task + */ + public void addTask(Task task) { + list.add(task); + } + + + /** + * Returns a copy of the list + * + * @return ArrayList copy containing all of the tasks + */ + public ArrayList getList() { + ArrayList list = (ArrayList) this.list.clone(); + return list; + } + + /** + * Obtains Task from TaskList + * + * @param index Index of task to be retrieved + * @return Task corresponding to index + * @throws DukeException + */ + public Task getTask(int index) throws DukeException { + Task task; + try { + task = list.get(index); + } catch (IndexOutOfBoundsException e) { + throw new DukeException("Sorry, there are only " + list.size() + " tasks."); + } + return task; + } + + /** + * Deletes Task from TaskList + * + * @param index Index of task to be deleted + * @return Task that was deleted from list + * @throws DukeException + */ + public Task deleteTask(int index) throws DukeException { + Task task = getTask(index); + list.remove(index); + return task; + } + + /** + * Sets Task from TaskList to completed + * + * @param index Index of task to be completed + * @return Task that was completed + * @throws DukeException + */ + public Task doneTask(int index) throws DukeException { + Task task = getTask(index); + task.setComplete(true); + return task; + } + + /** + * Outputs list of all Tasks with descriptions + * + * @return List of all Tasks with descriptions + */ + public String allTasks() { + int i = 1; + String result = ""; + for (Task item : list) { + result += i + ". " + item.getTaskType() + item.getStatusIcon() + " " + item.getDescription() + "\n"; + i++; + } + return result; + } + + /** + * Returns size of list + * + * @return Current size of task list + */ + public int size() { + return list.size(); + } + + /** + * Gets toString() of all tasks in list + * + * @return String containing all tasks in list + */ + @Override + public String toString() { + String data = ""; + for (Task task : list) { + data += task.toString() + "\n"; + } + return data; + } +} diff --git a/src/main/java/duke/Ui.java b/src/main/java/duke/Ui.java new file mode 100644 index 0000000000..deaed9e25e --- /dev/null +++ b/src/main/java/duke/Ui.java @@ -0,0 +1,23 @@ +package duke; + +/** + * UI related methods + */ +public class Ui { + + + /** + * Greets user with a simple message + */ + public static String greet() { + return ("Hello! I'm Magnolia\n" + "What can I do for you?"); + } + /** + * Shows user an error message + * + * @param message Error message to be shown + */ + public void showError(String message) { + System.out.println(message); + } +} diff --git a/src/main/resources/images/default_user.png b/src/main/resources/images/default_user.png new file mode 100644 index 0000000000..5911d30481 Binary files /dev/null and b/src/main/resources/images/default_user.png differ diff --git a/src/main/resources/images/magnolia.jpg b/src/main/resources/images/magnolia.jpg new file mode 100644 index 0000000000..1fb7f63f03 Binary files /dev/null and b/src/main/resources/images/magnolia.jpg differ diff --git a/src/main/resources/view/DialogBox.fxml b/src/main/resources/view/DialogBox.fxml new file mode 100644 index 0000000000..c57441a92f --- /dev/null +++ b/src/main/resources/view/DialogBox.fxml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml new file mode 100644 index 0000000000..2f3a0e49c1 --- /dev/null +++ b/src/main/resources/view/MainWindow.fxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/dukeTest/TaskListTest.java b/src/test/java/dukeTest/TaskListTest.java new file mode 100644 index 0000000000..ef22232c3c --- /dev/null +++ b/src/test/java/dukeTest/TaskListTest.java @@ -0,0 +1,36 @@ +package dukeTest; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.ArrayList; + +import org.junit.jupiter.api.Test; + +import duke.DukeException; +import duke.Task; +import duke.TaskList; + + +/** + * Test class for TaskList class + */ +public class TaskListTest { + @Test + public void addTaskTest() throws DukeException { + TaskList test = new TaskList(); + Task task = new Task.Deadline("test", false, "2021-12-12"); + test.addTask(task); + assertEquals(task, + test.getTask(0)); + } + + @Test + public void removeTaskTest() throws DukeException { + Task task = new Task.Deadline("test", false, "2021-12-12"); + ArrayList temp = new ArrayList<>(); + temp.add(task); + TaskList test = new TaskList(temp); + test.deleteTask(0); + assertEquals(new TaskList().size(), test.size()); + } +} diff --git a/src/test/java/dukeTest/TaskTest.java b/src/test/java/dukeTest/TaskTest.java new file mode 100644 index 0000000000..42b09f9b8b --- /dev/null +++ b/src/test/java/dukeTest/TaskTest.java @@ -0,0 +1,19 @@ +package dukeTest; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +import duke.DukeException; +import duke.Task; + + + + +public class TaskTest { + @Test + public void toStringTest() throws DukeException { + Task task = new Task.Deadline("Clean room", false, "2021-12-12"); + assertEquals("deadline | 0 | Clean room | 2021-12-12", task.toString()); + } +} diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT deleted file mode 100644 index 657e74f6e7..0000000000 --- a/text-ui-test/EXPECTED.TXT +++ /dev/null @@ -1,7 +0,0 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| - diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat deleted file mode 100644 index 0873744649..0000000000 --- a/text-ui-test/runtest.bat +++ /dev/null @@ -1,21 +0,0 @@ -@ECHO OFF - -REM create bin directory if it doesn't exist -if not exist ..\bin mkdir ..\bin - -REM delete output from previous run -if exist ACTUAL.TXT del ACTUAL.TXT - -REM compile the code into the bin folder -javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\*.java -IF ERRORLEVEL 1 ( - echo ********** BUILD FAILURE ********** - exit /b 1 -) -REM no error here, errorlevel == 0 - -REM run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT -java -classpath ..\bin Duke < input.txt > ACTUAL.TXT - -REM compare the output to the expected output -FC ACTUAL.TXT EXPECTED.TXT diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh deleted file mode 100644 index c9ec870033..0000000000 --- a/text-ui-test/runtest.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -# create bin directory if it doesn't exist -if [ ! -d "../bin" ] -then - mkdir ../bin -fi - -# delete output from previous run -if [ -e "./ACTUAL.TXT" ] -then - rm ACTUAL.TXT -fi - -# compile the code into the bin folder, terminates if error occurred -if ! javac -cp ../src/main/java -Xlint:none -d ../bin ../src/main/java/*.java -then - echo "********** BUILD FAILURE **********" - exit 1 -fi - -# run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT -java -classpath ../bin Duke < input.txt > ACTUAL.TXT - -# 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 -if [ $? -eq 0 ] -then - echo "Test result: PASSED" - exit 0 -else - echo "Test result: FAILED" - exit 1 -fi \ No newline at end of file