From 556af3f47a96b32898ab4cdbd65b16486a4871e8 Mon Sep 17 00:00:00 2001 From: damithc Date: Mon, 25 May 2020 00:58:18 +0800 Subject: [PATCH 01/73] Add Gradle support --- build.gradle | 41 +++++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 58695 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 183 +++++++++++++++++++++++ gradlew.bat | 103 +++++++++++++ text-ui-test/runtest.sh | 0 6 files changed, 332 insertions(+) create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat mode change 100644 => 100755 text-ui-test/runtest.sh diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000..885198fcfa --- /dev/null +++ b/build.gradle @@ -0,0 +1,41 @@ +plugins { + id 'java' + id 'application' + 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' +} + +test { + useJUnitPlatform() + + testLogging { + events "passed", "skipped", "failed" + + showExceptions true + exceptionFormat "full" + showCauses true + showStackTraces true + showStandardStreams = false + } +} + +application { + mainClassName = "seedu.duke.Duke" +} + +shadowJar { + archiveBaseName = "duke" + archiveClassifier = null +} + +run{ + standardInput = System.in +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..f3d88b1c2faf2fc91d853cd5d4242b5547257070 GIT binary patch literal 58695 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 literal 0 HcmV?d00001 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/text-ui-test/runtest.sh b/text-ui-test/runtest.sh old mode 100644 new mode 100755 From cbdb45399bde50056d53a8f9d0bf6accbf5119cf Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Tue, 16 Aug 2022 22:32:30 +0800 Subject: [PATCH 02/73] Set up skeletal version of Duke --- src/main/java/Duke.java | 46 ++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 5d313334cc..e039c1a74b 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,10 +1,36 @@ -public class Duke { - public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - } -} +import java.util.Scanner; + +public class Duke { + private static String formatLine(String input) { + return "\t " + input + "\n"; + } + + private static String formatParagraph(String paragraph) { + String divider = "\t____________________________________________________________\n"; + return divider + paragraph + divider; + } + + public static void main(String[] args) { + String introParagraph = formatLine("Hello! I'm Duke") + formatLine("What can I do for you?"); + String formattedIntro = formatParagraph(introParagraph); + + System.out.println(formattedIntro); + + Scanner sc = new Scanner(System.in); + boolean terminate = false; + + while(!terminate) { + String nextLine = sc.nextLine(); + switch (nextLine) { + case "bye": + System.out.println(formatParagraph(formatLine("Bye. Hope to see you again soon!"))); + terminate = true; + break; + default: + System.out.println(formatParagraph(formatLine(nextLine))); + sc.close(); + } + } + } +} + From e4406e0fa7dd9f81ab32618a901d4474360aaead Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Tue, 16 Aug 2022 22:49:44 +0800 Subject: [PATCH 03/73] Revert "Set up skeletal version of Duke" This reverts commit cbdb45399bde50056d53a8f9d0bf6accbf5119cf. --- src/main/java/Duke.java | 46 +++++++++-------------------------------- 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index e039c1a74b..5d313334cc 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,36 +1,10 @@ -import java.util.Scanner; - -public class Duke { - private static String formatLine(String input) { - return "\t " + input + "\n"; - } - - private static String formatParagraph(String paragraph) { - String divider = "\t____________________________________________________________\n"; - return divider + paragraph + divider; - } - - public static void main(String[] args) { - String introParagraph = formatLine("Hello! I'm Duke") + formatLine("What can I do for you?"); - String formattedIntro = formatParagraph(introParagraph); - - System.out.println(formattedIntro); - - Scanner sc = new Scanner(System.in); - boolean terminate = false; - - while(!terminate) { - String nextLine = sc.nextLine(); - switch (nextLine) { - case "bye": - System.out.println(formatParagraph(formatLine("Bye. Hope to see you again soon!"))); - terminate = true; - break; - default: - System.out.println(formatParagraph(formatLine(nextLine))); - sc.close(); - } - } - } -} - +public class Duke { + public static void main(String[] args) { + String logo = " ____ _ \n" + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; + System.out.println("Hello from\n" + logo); + } +} From 295c10ab4886ea522fdcfd58995285b93d2c5303 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Tue, 16 Aug 2022 22:51:52 +0800 Subject: [PATCH 04/73] Set up skeletal version of Duke --- src/main/java/Duke.java | 44 ++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 5d313334cc..bb65beb72a 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,10 +1,40 @@ +import java.util.Scanner; + public class Duke { - public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); + + private static String formatLine(String input) { + return "\t " + input + "\n"; + } + + private static String formatParagraph(String paragraph) { + String divider = + "\t____________________________________________________________\n"; + return divider + paragraph + divider; + } + + public static void main(String[] args) { + String introParagraph = + formatLine("Hello! I'm Duke") + formatLine("What can I do for you?"); + String formattedIntro = formatParagraph(introParagraph); + + System.out.println(formattedIntro); + + Scanner sc = new Scanner(System.in); + boolean terminate = false; + + while (!terminate) { + String nextLine = sc.nextLine(); + switch (nextLine) { + case "bye": + System.out.println( + formatParagraph(formatLine("Bye. Hope to see you again soon!")) + ); + terminate = true; + sc.close(); + break; + default: + System.out.println(formatParagraph(formatLine(nextLine))); + } } + } } From e904640d4d9e63cb83b8a6ed49050d124c902b8f Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Tue, 16 Aug 2022 22:52:59 +0800 Subject: [PATCH 05/73] Revert "Set up skeletal version of Duke" This reverts commit 295c10ab4886ea522fdcfd58995285b93d2c5303. --- src/main/java/Duke.java | 44 +++++++---------------------------------- 1 file changed, 7 insertions(+), 37 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index bb65beb72a..5d313334cc 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,40 +1,10 @@ -import java.util.Scanner; - public class Duke { - - private static String formatLine(String input) { - return "\t " + input + "\n"; - } - - private static String formatParagraph(String paragraph) { - String divider = - "\t____________________________________________________________\n"; - return divider + paragraph + divider; - } - - public static void main(String[] args) { - String introParagraph = - formatLine("Hello! I'm Duke") + formatLine("What can I do for you?"); - String formattedIntro = formatParagraph(introParagraph); - - System.out.println(formattedIntro); - - Scanner sc = new Scanner(System.in); - boolean terminate = false; - - while (!terminate) { - String nextLine = sc.nextLine(); - switch (nextLine) { - case "bye": - System.out.println( - formatParagraph(formatLine("Bye. Hope to see you again soon!")) - ); - terminate = true; - sc.close(); - break; - default: - System.out.println(formatParagraph(formatLine(nextLine))); - } + public static void main(String[] args) { + String logo = " ____ _ \n" + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; + System.out.println("Hello from\n" + logo); } - } } From 48e4d08ca4735a96e15590435b9c8289c7aa70bb Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Tue, 16 Aug 2022 22:53:40 +0800 Subject: [PATCH 06/73] Set up skeletal version of Duke --- src/main/java/Duke.java | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 5d313334cc..744912d2a3 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,10 +1,35 @@ +import java.util.Scanner; + public class Duke { + private static String formatLine(String input) { + return "\t " + input + "\n"; + } + + private static String formatParagraph(String paragraph) { + String divider = "\t____________________________________________________________\n"; + return divider + paragraph + divider; + } + public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); + String introParagraph = formatLine("Hello! I'm Duke") + formatLine("What can I do for you?"); + String formattedIntro = formatParagraph(introParagraph); + + System.out.println(formattedIntro); + + Scanner sc = new Scanner(System.in); + boolean terminate = false; + + while(!terminate) { + String nextLine = sc.nextLine(); + switch (nextLine) { + case "bye": + System.out.println(formatParagraph(formatLine("Bye. Hope to see you again soon!"))); + terminate = true; + sc.close(); + break; + default: + System.out.println(formatParagraph(formatLine(nextLine))); + } + } } } From b0343fe5f022a678e89b0d1b841c9a75feec268d Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Tue, 16 Aug 2022 22:57:07 +0800 Subject: [PATCH 07/73] Refactor text formatting to separate class --- src/main/java/TextFormatter.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/main/java/TextFormatter.java diff --git a/src/main/java/TextFormatter.java b/src/main/java/TextFormatter.java new file mode 100644 index 0000000000..995b9d6091 --- /dev/null +++ b/src/main/java/TextFormatter.java @@ -0,0 +1,10 @@ +public class TextFormatter { + public static String formatLine(String input) { + return "\t " + input + "\n"; + } + + public static String formatParagraph(String paragraph) { + String divider = "\t____________________________________________________________\n"; + return divider + paragraph + divider; + } +} From 747d7eff95b06b88958e9a8d39723e1a5f0e5764 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Tue, 16 Aug 2022 22:58:09 +0800 Subject: [PATCH 08/73] Add list that stores/display text entered by user --- src/main/java/Duke.java | 30 +++++++++++++++++------------- src/main/java/DukeList.java | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 src/main/java/DukeList.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 744912d2a3..1e6fac0dc4 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,34 +1,38 @@ import java.util.Scanner; public class Duke { - private static String formatLine(String input) { - return "\t " + input + "\n"; - } - - private static String formatParagraph(String paragraph) { - String divider = "\t____________________________________________________________\n"; - return divider + paragraph + divider; - } - public static void main(String[] args) { - String introParagraph = formatLine("Hello! I'm Duke") + formatLine("What can I do for you?"); - String formattedIntro = formatParagraph(introParagraph); + String introParagraph = TextFormatter.formatLine("Hello! I'm Duke") + + TextFormatter.formatLine("What can I do for you?"); + String formattedIntro = TextFormatter.formatParagraph(introParagraph); System.out.println(formattedIntro); Scanner sc = new Scanner(System.in); boolean terminate = false; + DukeList dukelist = new DukeList(); while(!terminate) { String nextLine = sc.nextLine(); switch (nextLine) { case "bye": - System.out.println(formatParagraph(formatLine("Bye. Hope to see you again soon!"))); + System.out.println(TextFormatter.formatParagraph( + TextFormatter.formatLine("Bye. Hope to see you again soon!") + )); terminate = true; sc.close(); break; + case "list": + System.out.println(TextFormatter.formatParagraph( + dukelist.toString() + )); + break; default: - System.out.println(formatParagraph(formatLine(nextLine))); + dukelist.add(nextLine); + String outputString = "added: " + nextLine; + System.out.println(TextFormatter.formatParagraph( + TextFormatter.formatLine(outputString) + )); } } } diff --git a/src/main/java/DukeList.java b/src/main/java/DukeList.java new file mode 100644 index 0000000000..7e7369001b --- /dev/null +++ b/src/main/java/DukeList.java @@ -0,0 +1,20 @@ +import java.util.ArrayList; + +public class DukeList { + private final ArrayList list = new ArrayList<>(); + + public void add(String str) { + this.list.add(str); + } + + @Override + public String toString() { + String res = ""; + for (int i = 0; i < this.list.size(); i++) { + String nextListItem = String.format("%d. %s", i + 1, this.list.get(i)); + res += TextFormatter.formatLine(nextListItem); + } + return res; + } +} + From 2a968a6fe23c765d71eec81240f3cbcd7d37d161 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Tue, 16 Aug 2022 23:17:20 +0800 Subject: [PATCH 09/73] Add Task that can be marked/unmarked --- src/main/java/Duke.java | 26 +++++++++++++++++++++++--- src/main/java/DukeList.java | 20 -------------------- src/main/java/Task.java | 22 ++++++++++++++++++++++ src/main/java/TaskList.java | 28 ++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 23 deletions(-) delete mode 100644 src/main/java/DukeList.java create mode 100644 src/main/java/Task.java create mode 100644 src/main/java/TaskList.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 1e6fac0dc4..3f1ab5d955 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -10,11 +10,13 @@ public static void main(String[] args) { Scanner sc = new Scanner(System.in); boolean terminate = false; - DukeList dukelist = new DukeList(); + TaskList dukelist = new TaskList(); while(!terminate) { String nextLine = sc.nextLine(); - switch (nextLine) { + String[] splitted = nextLine.split("\\s+"); + String command = splitted[0]; + switch (command) { case "bye": System.out.println(TextFormatter.formatParagraph( TextFormatter.formatLine("Bye. Hope to see you again soon!") @@ -27,9 +29,27 @@ public static void main(String[] args) { dukelist.toString() )); break; + case "mark": + int index = Integer.parseInt(splitted[1]); + String markedItem = " " + dukelist.markItem(index); + String markedText = "Nice! I've marked this task as done:"; + System.out.println(TextFormatter.formatParagraph( + TextFormatter.formatLine(markedText) + + TextFormatter.formatLine(markedItem) + )); + break; + case "unmark": + index = Integer.parseInt(splitted[1]); + String unmarkedItem = " " + dukelist.unmarkItem(index); + String unmarkedText = "OK, I've marked this task as not done yet:"; + System.out.println(TextFormatter.formatParagraph( + TextFormatter.formatLine(unmarkedText) + + TextFormatter.formatLine(unmarkedItem) + )); + break; default: dukelist.add(nextLine); - String outputString = "added: " + nextLine; + String outputString = "added: " + command; System.out.println(TextFormatter.formatParagraph( TextFormatter.formatLine(outputString) )); diff --git a/src/main/java/DukeList.java b/src/main/java/DukeList.java deleted file mode 100644 index 7e7369001b..0000000000 --- a/src/main/java/DukeList.java +++ /dev/null @@ -1,20 +0,0 @@ -import java.util.ArrayList; - -public class DukeList { - private final ArrayList list = new ArrayList<>(); - - public void add(String str) { - this.list.add(str); - } - - @Override - public String toString() { - String res = ""; - for (int i = 0; i < this.list.size(); i++) { - String nextListItem = String.format("%d. %s", i + 1, this.list.get(i)); - res += TextFormatter.formatLine(nextListItem); - } - return res; - } -} - diff --git a/src/main/java/Task.java b/src/main/java/Task.java new file mode 100644 index 0000000000..3a6778d587 --- /dev/null +++ b/src/main/java/Task.java @@ -0,0 +1,22 @@ +public class Task { + private String TaskItem; + private boolean isMarked; + + public Task(String TaskItem) { + this.TaskItem = TaskItem; + this.isMarked = false; + } + + @Override + public String toString() { + String checkbox = isMarked + ? "[X] " + : "[ ] "; + return checkbox + this.TaskItem; + } + + public String setIsMarked(boolean status) { + isMarked = status; + return this.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java new file mode 100644 index 0000000000..ea0fb7c4ef --- /dev/null +++ b/src/main/java/TaskList.java @@ -0,0 +1,28 @@ +import java.util.ArrayList; + +public class TaskList { + private final ArrayList list = new ArrayList<>(); + + public void add(String str) { + this.list.add(new Task(str)); + } + + @Override + public String toString() { + String res = TextFormatter.formatLine("Here are the tasks in your list:"); + for (int i = 0; i < this.list.size(); i++) { + String nextListItem = String.format("%d.%s", i + 1, this.list.get(i)); + res += TextFormatter.formatLine(nextListItem); + } + return res; + } + + public String markItem(int index) { + return this.list.get(index - 1).setIsMarked(true); + } + + public String unmarkItem(int index) { + return this.list.get(index - 1).setIsMarked(false); + } +} + From ef2e2c2e8bfb96be6aa99c8024909228e5ad9b5d Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Tue, 16 Aug 2022 23:19:27 +0800 Subject: [PATCH 10/73] Refactor formatting of multiple lines to new function --- src/main/java/Duke.java | 22 ++++++++++------------ src/main/java/TextFormatter.java | 9 +++++++++ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 3f1ab5d955..9ab024510b 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -18,9 +18,9 @@ public static void main(String[] args) { String command = splitted[0]; switch (command) { case "bye": - System.out.println(TextFormatter.formatParagraph( - TextFormatter.formatLine("Bye. Hope to see you again soon!") - )); + System.out.println( + TextFormatter.formatLinesIntoParagraph("Bye. Hope to see you again soon!") + ); terminate = true; sc.close(); break; @@ -33,26 +33,24 @@ public static void main(String[] args) { int index = Integer.parseInt(splitted[1]); String markedItem = " " + dukelist.markItem(index); String markedText = "Nice! I've marked this task as done:"; - System.out.println(TextFormatter.formatParagraph( - TextFormatter.formatLine(markedText) + - TextFormatter.formatLine(markedItem) + System.out.println(TextFormatter.formatLinesIntoParagraph( + markedText, + markedItem )); break; case "unmark": index = Integer.parseInt(splitted[1]); String unmarkedItem = " " + dukelist.unmarkItem(index); String unmarkedText = "OK, I've marked this task as not done yet:"; - System.out.println(TextFormatter.formatParagraph( - TextFormatter.formatLine(unmarkedText) + - TextFormatter.formatLine(unmarkedItem) + System.out.println(TextFormatter.formatLinesIntoParagraph( + unmarkedText, + unmarkedItem )); break; default: dukelist.add(nextLine); String outputString = "added: " + command; - System.out.println(TextFormatter.formatParagraph( - TextFormatter.formatLine(outputString) - )); + System.out.println(TextFormatter.formatLinesIntoParagraph(outputString)); } } } diff --git a/src/main/java/TextFormatter.java b/src/main/java/TextFormatter.java index 995b9d6091..991d6131bd 100644 --- a/src/main/java/TextFormatter.java +++ b/src/main/java/TextFormatter.java @@ -7,4 +7,13 @@ public static String formatParagraph(String paragraph) { String divider = "\t____________________________________________________________\n"; return divider + paragraph + divider; } + + public static String formatLinesIntoParagraph(String... lines) { + String res = ""; + for (String line : lines) { + res += formatLine(line); + } + + return formatParagraph(res); + } } From 1af53d84f38f5501ec3c3a1a865ab3234e84e8ee Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 17 Aug 2022 20:33:55 +0800 Subject: [PATCH 11/73] Tidy variables and return types in Task --- src/main/java/Task.java | 5 ++--- src/main/java/TaskList.java | 8 ++++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 3a6778d587..4d033446dc 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -1,5 +1,5 @@ public class Task { - private String TaskItem; + private final String TaskItem; private boolean isMarked; public Task(String TaskItem) { @@ -15,8 +15,7 @@ public String toString() { return checkbox + this.TaskItem; } - public String setIsMarked(boolean status) { + public void setIsMarked(boolean status) { isMarked = status; - return this.toString(); } } \ No newline at end of file diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index ea0fb7c4ef..5a97f89adb 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -18,11 +18,15 @@ public String toString() { } public String markItem(int index) { - return this.list.get(index - 1).setIsMarked(true); + Task taskItem = this.list.get(index - 1); + taskItem.setIsMarked(true); + return taskItem.toString(); } public String unmarkItem(int index) { - return this.list.get(index - 1).setIsMarked(false); + Task taskItem = this.list.get(index - 1); + taskItem.setIsMarked(false); + return taskItem.toString(); } } From 92f60330b483e97057dba595797bfb5b14b24aa1 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 17 Aug 2022 20:48:31 +0800 Subject: [PATCH 12/73] Revert "Tidy variables and return types in Task" This reverts commit 1af53d84f38f5501ec3c3a1a865ab3234e84e8ee. --- src/main/java/Task.java | 5 +++-- src/main/java/TaskList.java | 8 ++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 4d033446dc..3a6778d587 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -1,5 +1,5 @@ public class Task { - private final String TaskItem; + private String TaskItem; private boolean isMarked; public Task(String TaskItem) { @@ -15,7 +15,8 @@ public String toString() { return checkbox + this.TaskItem; } - public void setIsMarked(boolean status) { + public String setIsMarked(boolean status) { isMarked = status; + return this.toString(); } } \ No newline at end of file diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index 5a97f89adb..ea0fb7c4ef 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -18,15 +18,11 @@ public String toString() { } public String markItem(int index) { - Task taskItem = this.list.get(index - 1); - taskItem.setIsMarked(true); - return taskItem.toString(); + return this.list.get(index - 1).setIsMarked(true); } public String unmarkItem(int index) { - Task taskItem = this.list.get(index - 1); - taskItem.setIsMarked(false); - return taskItem.toString(); + return this.list.get(index - 1).setIsMarked(false); } } From 8d0ffd12c55a5e92887506fbd557a3c102723292 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 17 Aug 2022 21:05:26 +0800 Subject: [PATCH 13/73] Add Task subclasses for todo, event, deadline --- src/main/java/Deadline.java | 14 ++++++++++++++ src/main/java/Event.java | 13 +++++++++++++ src/main/java/Task.java | 13 +++++-------- src/main/java/Todo.java | 10 ++++++++++ 4 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 src/main/java/Deadline.java create mode 100644 src/main/java/Event.java create mode 100644 src/main/java/Todo.java diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java new file mode 100644 index 0000000000..ed6847d2f0 --- /dev/null +++ b/src/main/java/Deadline.java @@ -0,0 +1,14 @@ +public class Deadline extends Task { + private final String deadline; + + public Deadline(String taskItem, String deadline) { + super(taskItem); + this.deadline = deadline; + } + + @Override + public String toString() { + String deadlineDisplay = String.format(" (by: %s)", this.deadline); + return "[D]" + super.toString() + deadlineDisplay; + } +} diff --git a/src/main/java/Event.java b/src/main/java/Event.java new file mode 100644 index 0000000000..439b06ad75 --- /dev/null +++ b/src/main/java/Event.java @@ -0,0 +1,13 @@ +public class Event extends Task{ + private final String eventTiming; + public Event(String taskItem, String eventTiming) { + super(taskItem); + this.eventTiming = eventTiming; + } + + @Override + public String toString() { + String eventTimingDisplay = String.format(" (at: %s)", this.eventTiming); + return "[D]" + super.toString() + eventTimingDisplay; + } +} diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 3a6778d587..b722ac1ee9 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -1,5 +1,5 @@ -public class Task { - private String TaskItem; +public abstract class Task { + private final String TaskItem; private boolean isMarked; public Task(String TaskItem) { @@ -9,14 +9,11 @@ public Task(String TaskItem) { @Override public String toString() { - String checkbox = isMarked - ? "[X] " - : "[ ] "; + String checkbox = isMarked ? "[X] " : "[ ] "; return checkbox + this.TaskItem; } - public String setIsMarked(boolean status) { + public void setIsMarked(boolean status) { isMarked = status; - return this.toString(); } -} \ No newline at end of file +} diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java new file mode 100644 index 0000000000..c2944705b7 --- /dev/null +++ b/src/main/java/Todo.java @@ -0,0 +1,10 @@ +public class Todo extends Task { + public Todo(String taskItem) { + super(taskItem); + } + + @Override + public String toString() { + return "[T]" + super.toString(); + } +} From c71124f23a6f2e0d2a2dc34fcb834c527a76abf6 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 17 Aug 2022 21:05:54 +0800 Subject: [PATCH 14/73] Update TaskList to match changes to Task --- src/main/java/TaskList.java | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index ea0fb7c4ef..2a498bbc99 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -3,8 +3,22 @@ public class TaskList { private final ArrayList list = new ArrayList<>(); - public void add(String str) { - this.list.add(new Task(str)); + public Task addTodo(String taskItem) { + Task task = new Todo(taskItem); + this.list.add(task); + return task; + } + + public Task addDeadline(String taskItem, String deadline) { + Task task = new Deadline(taskItem, deadline); + this.list.add(task); + return task; + } + + public Task addEvent(String taskItem, String eventTiming) { + Task task = new Event(taskItem, eventTiming); + this.list.add(task); + return task; } @Override @@ -17,12 +31,19 @@ public String toString() { return res; } - public String markItem(int index) { - return this.list.get(index - 1).setIsMarked(true); + public Task markItem(int index) { + Task taskItem = this.list.get(index - 1); + taskItem.setIsMarked(true); + return taskItem; } - public String unmarkItem(int index) { - return this.list.get(index - 1).setIsMarked(false); + public Task unmarkItem(int index) { + Task taskItem = this.list.get(index - 1); + taskItem.setIsMarked(false); + return taskItem; } -} + public int getTaskCount() { + return this.list.size(); + } +} \ No newline at end of file From 4d6e203ee7dc1b7b533f677c2cf5ef7556f13b43 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 17 Aug 2022 21:06:18 +0800 Subject: [PATCH 15/73] Update duke to handle todo, event, deadline --- src/main/java/Duke.java | 47 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 9ab024510b..941f4ff404 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -14,7 +14,8 @@ public static void main(String[] args) { while(!terminate) { String nextLine = sc.nextLine(); - String[] splitted = nextLine.split("\\s+"); + // Regex "//s+" matches one or more spaces + String[] splitted = nextLine.split("\\s+", 2); String command = splitted[0]; switch (command) { case "bye": @@ -47,9 +48,49 @@ public static void main(String[] args) { unmarkedItem )); break; + case "todo": + String todo = splitted[1]; + String taskItem = " " + dukelist.addTodo(todo); + String startLine = "Got it. I've added this task:"; + String endLine = String.format( + "Now you have %d tasks in the list.", + dukelist.getTaskCount()); + System.out.println(TextFormatter.formatLinesIntoParagraph( + startLine, + taskItem, + endLine + )); + break; + case "deadline": + // Regex "\\s+\\\\" matches one or more space followed by a \ + String[] taskArgs = splitted[1].split("\\s+\\\\",2); + taskItem = " " + dukelist.addDeadline(taskArgs[0], taskArgs[1]); + startLine = "Got it. I've added this task:"; + endLine = String.format( + "Now you have %d tasks in the list.", + dukelist.getTaskCount()); + System.out.println(TextFormatter.formatLinesIntoParagraph( + startLine, + taskItem, + endLine + )); + break; + case "event": + // Regex "\\s+\\\\" matches one or more space followed by a \ + taskArgs = splitted[1].split("\\s+\\\\",2); + taskItem = " " + dukelist.addEvent(taskArgs[0], taskArgs[1]); + startLine = "Got it. I've added this task:"; + endLine = String.format( + "Now you have %d tasks in the list.", + dukelist.getTaskCount()); + System.out.println(TextFormatter.formatLinesIntoParagraph( + startLine, + taskItem, + endLine + )); + break; default: - dukelist.add(nextLine); - String outputString = "added: " + command; + String outputString = "No such command"; System.out.println(TextFormatter.formatLinesIntoParagraph(outputString)); } } From 5aa7417ce18755af41f3ed8398b8ba61b1a6bbb6 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 17 Aug 2022 21:21:14 +0800 Subject: [PATCH 16/73] Fix regex to match / instead of " --- src/main/java/Duke.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 941f4ff404..5d52df20aa 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -62,8 +62,8 @@ public static void main(String[] args) { )); break; case "deadline": - // Regex "\\s+\\\\" matches one or more space followed by a \ - String[] taskArgs = splitted[1].split("\\s+\\\\",2); + // Regex "\\s+\\\\" matches one or more space followed by a / + String[] taskArgs = splitted[1].split("\\s+/",2); taskItem = " " + dukelist.addDeadline(taskArgs[0], taskArgs[1]); startLine = "Got it. I've added this task:"; endLine = String.format( @@ -76,8 +76,8 @@ public static void main(String[] args) { )); break; case "event": - // Regex "\\s+\\\\" matches one or more space followed by a \ - taskArgs = splitted[1].split("\\s+\\\\",2); + // Regex "\\s+\\\\" matches one or more space followed by a / + taskArgs = splitted[1].split("\\s+/",2); taskItem = " " + dukelist.addEvent(taskArgs[0], taskArgs[1]); startLine = "Got it. I've added this task:"; endLine = String.format( From f06be8e6a8a4f7a2cdb19612efc8af5709fe62e2 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 17 Aug 2022 21:21:49 +0800 Subject: [PATCH 17/73] Update comments to match regex change --- src/main/java/Duke.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 5d52df20aa..b4f362764a 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -62,7 +62,7 @@ public static void main(String[] args) { )); break; case "deadline": - // Regex "\\s+\\\\" matches one or more space followed by a / + // Regex "\\s+/" matches one or more space followed by a / String[] taskArgs = splitted[1].split("\\s+/",2); taskItem = " " + dukelist.addDeadline(taskArgs[0], taskArgs[1]); startLine = "Got it. I've added this task:"; @@ -76,7 +76,7 @@ public static void main(String[] args) { )); break; case "event": - // Regex "\\s+\\\\" matches one or more space followed by a / + // Regex "\\s+/" matches one or more space followed by a / taskArgs = splitted[1].split("\\s+/",2); taskItem = " " + dukelist.addEvent(taskArgs[0], taskArgs[1]); startLine = "Got it. I've added this task:"; From 5ce35d8ce60d3d30d99fdb4bc88c3968ca93f608 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 17 Aug 2022 21:35:39 +0800 Subject: [PATCH 18/73] Update test script and files to automate testing --- text-ui-test/EXPECTED.TXT | 54 ++++++++++++++++++++++++++++++++++----- text-ui-test/input.txt | 8 ++++++ text-ui-test/runtest.bat | 2 ++ 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 657e74f6e7..0b90c575b3 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,7 +1,49 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| + ____________________________________________________________ + Hello! I'm Duke + What can I do for you? + ____________________________________________________________ + + ____________________________________________________________ + Got it. I've added this task: + [T][ ] borrow book + Now you have 1 tasks in the list. + ____________________________________________________________ + + ____________________________________________________________ + Got it. I've added this task: + [D][ ] return book (by: by Sunday) + Now you have 2 tasks in the list. + ____________________________________________________________ + + ____________________________________________________________ + Got it. I've added this task: + [D][ ] project meeting (at: at Mon 2-4pm) + Now you have 3 tasks in the list. + ____________________________________________________________ + + ____________________________________________________________ + Nice! I've marked this task as done: + [T][X] borrow book + ____________________________________________________________ + + ____________________________________________________________ + Nice! I've marked this task as done: + [D][X] return book (by: by Sunday) + ____________________________________________________________ + + ____________________________________________________________ + OK, I've marked this task as not done yet: + [T][ ] borrow book + ____________________________________________________________ + + ____________________________________________________________ + Here are the tasks in your list: + 1.[T][ ] borrow book + 2.[D][X] return book (by: by Sunday) + 3.[D][ ] project meeting (at: at Mon 2-4pm) + ____________________________________________________________ + + ____________________________________________________________ + Bye. Hope to see you again soon! + ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e69de29bb2..7ca60fcd68 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -0,0 +1,8 @@ +todo borrow book +deadline return book /by Sunday +event project meeting /at Mon 2-4pm +mark 1 +mark 2 +unmark 1 +list +bye diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index 0873744649..0c79b0b7c6 100644 --- a/text-ui-test/runtest.bat +++ b/text-ui-test/runtest.bat @@ -19,3 +19,5 @@ java -classpath ..\bin Duke < input.txt > ACTUAL.TXT REM compare the output to the expected output FC ACTUAL.TXT EXPECTED.TXT + +pause \ No newline at end of file From 0f14bf5196b06457fc3154195b7ffb5c4b40c0c7 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 17 Aug 2022 22:12:33 +0800 Subject: [PATCH 19/73] Add error handling --- src/main/java/Duke.java | 152 ++++++++++++++++--------------- src/main/java/DukeException.java | 27 ++++++ src/main/java/Todo.java | 6 ++ 3 files changed, 111 insertions(+), 74 deletions(-) create mode 100644 src/main/java/DukeException.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index b4f362764a..c371caa02c 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -13,85 +13,89 @@ public static void main(String[] args) { TaskList dukelist = new TaskList(); while(!terminate) { - String nextLine = sc.nextLine(); - // Regex "//s+" matches one or more spaces - String[] splitted = nextLine.split("\\s+", 2); - String command = splitted[0]; - switch (command) { - case "bye": - System.out.println( - TextFormatter.formatLinesIntoParagraph("Bye. Hope to see you again soon!") - ); - terminate = true; - sc.close(); - break; - case "list": - System.out.println(TextFormatter.formatParagraph( - dukelist.toString() - )); - break; - case "mark": - int index = Integer.parseInt(splitted[1]); - String markedItem = " " + dukelist.markItem(index); - String markedText = "Nice! I've marked this task as done:"; - System.out.println(TextFormatter.formatLinesIntoParagraph( - markedText, - markedItem - )); - break; - case "unmark": - index = Integer.parseInt(splitted[1]); - String unmarkedItem = " " + dukelist.unmarkItem(index); - String unmarkedText = "OK, I've marked this task as not done yet:"; - System.out.println(TextFormatter.formatLinesIntoParagraph( - unmarkedText, - unmarkedItem - )); - break; - case "todo": - String todo = splitted[1]; - String taskItem = " " + dukelist.addTodo(todo); - String startLine = "Got it. I've added this task:"; - String endLine = String.format( - "Now you have %d tasks in the list.", - dukelist.getTaskCount()); - System.out.println(TextFormatter.formatLinesIntoParagraph( - startLine, - taskItem, - endLine - )); - break; - case "deadline": - // Regex "\\s+/" matches one or more space followed by a / - String[] taskArgs = splitted[1].split("\\s+/",2); - taskItem = " " + dukelist.addDeadline(taskArgs[0], taskArgs[1]); - startLine = "Got it. I've added this task:"; - endLine = String.format( + try { + String nextLine = sc.nextLine(); + // Regex "//s+" matches one or more spaces + String[] splitted = nextLine.split("\\s+", 2); + String command = splitted[0]; + switch (command) { + case "bye": + System.out.println( + TextFormatter.formatLinesIntoParagraph("Bye. Hope to see you again soon!") + ); + terminate = true; + sc.close(); + break; + case "list": + System.out.println(TextFormatter.formatParagraph( + dukelist.toString() + )); + break; + case "mark": + int index = Integer.parseInt(splitted[1]); + String markedItem = " " + dukelist.markItem(index); + String markedText = "Nice! I've marked this task as done:"; + System.out.println(TextFormatter.formatLinesIntoParagraph( + markedText, + markedItem + )); + break; + case "unmark": + index = Integer.parseInt(splitted[1]); + String unmarkedItem = " " + dukelist.unmarkItem(index); + String unmarkedText = "OK, I've marked this task as not done yet:"; + System.out.println(TextFormatter.formatLinesIntoParagraph( + unmarkedText, + unmarkedItem + )); + break; + case "todo": + Todo.validateInput(splitted); + String todo = splitted[1]; + String taskItem = " " + dukelist.addTodo(todo); + String startLine = "Got it. I've added this task:"; + String endLine = String.format( "Now you have %d tasks in the list.", dukelist.getTaskCount()); - System.out.println(TextFormatter.formatLinesIntoParagraph( + System.out.println(TextFormatter.formatLinesIntoParagraph( startLine, taskItem, endLine - )); - break; - case "event": - // Regex "\\s+/" matches one or more space followed by a / - taskArgs = splitted[1].split("\\s+/",2); - taskItem = " " + dukelist.addEvent(taskArgs[0], taskArgs[1]); - startLine = "Got it. I've added this task:"; - endLine = String.format( - "Now you have %d tasks in the list.", - dukelist.getTaskCount()); - System.out.println(TextFormatter.formatLinesIntoParagraph( - startLine, - taskItem, - endLine - )); - break; - default: - String outputString = "No such command"; - System.out.println(TextFormatter.formatLinesIntoParagraph(outputString)); + )); + break; + case "deadline": + // Regex "\\s+/" matches one or more space followed by a / + String[] taskArgs = splitted[1].split("\\s+/",2); + taskItem = " " + dukelist.addDeadline(taskArgs[0], taskArgs[1]); + startLine = "Got it. I've added this task:"; + endLine = String.format( + "Now you have %d tasks in the list.", + dukelist.getTaskCount()); + System.out.println(TextFormatter.formatLinesIntoParagraph( + startLine, + taskItem, + endLine + )); + break; + case "event": + // Regex "\\s+/" matches one or more space followed by a / + taskArgs = splitted[1].split("\\s+/",2); + taskItem = " " + dukelist.addEvent(taskArgs[0], taskArgs[1]); + startLine = "Got it. I've added this task:"; + endLine = String.format( + "Now you have %d tasks in the list.", + dukelist.getTaskCount()); + System.out.println(TextFormatter.formatLinesIntoParagraph( + startLine, + taskItem, + endLine + )); + break; + default: + throw new DukeException(DukeException.ErrorCode.UNKNOWN_CMD); + } + } catch (DukeException e) { + System.out.println(TextFormatter.formatLinesIntoParagraph(e.errorMessage())); } } } diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java new file mode 100644 index 0000000000..3150956481 --- /dev/null +++ b/src/main/java/DukeException.java @@ -0,0 +1,27 @@ +public class DukeException extends Exception { + private final ErrorCode errorCode; + + public DukeException(ErrorCode errorCode) { + this.errorCode = errorCode; + } + + public String errorMessage() { + String errorMsg; + switch(errorCode) { + case UNKNOWN_CMD: + errorMsg = "☹ OOPS!!! I'm sorry, but I don't know what that means :-("; + break; + case MISSING_TODO_ITEM: + errorMsg = "☹ OOPS!!! The description of a todo cannot be empty."; + break; + default: + errorMsg = "☹ OOPS!!! Unknown duke error occurred. :-("; + } + return errorMsg; + } + + public enum ErrorCode { + UNKNOWN_CMD, + MISSING_TODO_ITEM + } +} diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java index c2944705b7..4d378cdee5 100644 --- a/src/main/java/Todo.java +++ b/src/main/java/Todo.java @@ -7,4 +7,10 @@ public Todo(String taskItem) { public String toString() { return "[T]" + super.toString(); } + + public static void validateInput(String[] input) throws DukeException { + if (input.length < 2 || input[1].strip().equals("")) { + throw new DukeException(DukeException.ErrorCode.MISSING_TODO_ITEM); + } + } } From 41a199b5245ef5a9a8d2c920a7b8ad0b2d279680 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 17 Aug 2022 22:20:48 +0800 Subject: [PATCH 20/73] Add delete functionality to TaskList --- src/main/java/Duke.java | 15 ++++++++++++++- src/main/java/TaskList.java | 6 ++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index c371caa02c..4804c466fb 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -49,12 +49,25 @@ public static void main(String[] args) { unmarkedItem )); break; + case "delete": + index = Integer.parseInt(splitted[1]); + String deletedItem = " " + dukelist.deleteItem(index); + String deleteText = "Noted. I've removed this task:"; + String endLine = String.format( + "Now you have %d tasks in the list.", + dukelist.getTaskCount()); + System.out.println(TextFormatter.formatLinesIntoParagraph( + deleteText, + deletedItem, + endLine + )); + break; case "todo": Todo.validateInput(splitted); String todo = splitted[1]; String taskItem = " " + dukelist.addTodo(todo); String startLine = "Got it. I've added this task:"; - String endLine = String.format( + endLine = String.format( "Now you have %d tasks in the list.", dukelist.getTaskCount()); System.out.println(TextFormatter.formatLinesIntoParagraph( diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index 2a498bbc99..ab96278e54 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -43,6 +43,12 @@ public Task unmarkItem(int index) { return taskItem; } + public Task deleteItem(int index) { + Task taskItem = this.list.get(index - 1); + this.list.remove(index - 1); + return taskItem; + } + public int getTaskCount() { return this.list.size(); } From 8a5ae3118edce3de849db847362ec4683467c386 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 15:00:03 +0800 Subject: [PATCH 21/73] Add encoding to Tasks classes and group them into task package --- src/main/java/{ => task}/Deadline.java | 8 ++++++++ src/main/java/{ => task}/Event.java | 10 +++++++++- src/main/java/{ => task}/Task.java | 12 ++++++++++++ src/main/java/{ => task}/Todo.java | 10 ++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) rename src/main/java/{ => task}/Deadline.java (65%) rename src/main/java/{ => task}/Event.java (60%) rename src/main/java/{ => task}/Task.java (69%) rename src/main/java/{ => task}/Todo.java (66%) diff --git a/src/main/java/Deadline.java b/src/main/java/task/Deadline.java similarity index 65% rename from src/main/java/Deadline.java rename to src/main/java/task/Deadline.java index ed6847d2f0..bf71702f6f 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/task/Deadline.java @@ -1,3 +1,5 @@ +package task; + public class Deadline extends Task { private final String deadline; @@ -11,4 +13,10 @@ public String toString() { String deadlineDisplay = String.format(" (by: %s)", this.deadline); return "[D]" + super.toString() + deadlineDisplay; } + + @Override + public String encode() { + int markedStatus = getIsMarked() ? 1 : 0; + return String.format("D,%d,%s,%s\n", markedStatus, getTaskItem(), deadline); + } } diff --git a/src/main/java/Event.java b/src/main/java/task/Event.java similarity index 60% rename from src/main/java/Event.java rename to src/main/java/task/Event.java index 439b06ad75..e9003e5941 100644 --- a/src/main/java/Event.java +++ b/src/main/java/task/Event.java @@ -1,4 +1,6 @@ -public class Event extends Task{ +package task; + +public class Event extends Task { private final String eventTiming; public Event(String taskItem, String eventTiming) { super(taskItem); @@ -10,4 +12,10 @@ public String toString() { String eventTimingDisplay = String.format(" (at: %s)", this.eventTiming); return "[D]" + super.toString() + eventTimingDisplay; } + + @Override + public String encode() { + int markedStatus = getIsMarked() ? 1 : 0; + return String.format("E,%d,%s,%s\n", markedStatus, getTaskItem(), eventTiming); + } } diff --git a/src/main/java/Task.java b/src/main/java/task/Task.java similarity index 69% rename from src/main/java/Task.java rename to src/main/java/task/Task.java index b722ac1ee9..a75012d9a4 100644 --- a/src/main/java/Task.java +++ b/src/main/java/task/Task.java @@ -1,3 +1,5 @@ +package task; + public abstract class Task { private final String TaskItem; private boolean isMarked; @@ -16,4 +18,14 @@ public String toString() { public void setIsMarked(boolean status) { isMarked = status; } + + protected boolean getIsMarked() { + return isMarked; + } + + protected String getTaskItem() { + return TaskItem; + } + + public abstract String encode(); } diff --git a/src/main/java/Todo.java b/src/main/java/task/Todo.java similarity index 66% rename from src/main/java/Todo.java rename to src/main/java/task/Todo.java index 4d378cdee5..04801945ef 100644 --- a/src/main/java/Todo.java +++ b/src/main/java/task/Todo.java @@ -1,3 +1,7 @@ +package task; + +import exception.DukeException; + public class Todo extends Task { public Todo(String taskItem) { super(taskItem); @@ -13,4 +17,10 @@ public static void validateInput(String[] input) throws DukeException { throw new DukeException(DukeException.ErrorCode.MISSING_TODO_ITEM); } } + + @Override + public String encode() { + int markedStatus = getIsMarked() ? 1 : 0; + return String.format("T,%d,%s\n", markedStatus, getTaskItem()); + } } From 87f307f3c136e1ee0c447efef8c3c101f7d8f1fa Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 15:03:23 +0800 Subject: [PATCH 22/73] Refactor TextFormatter to Ui class placed in util package --- src/main/java/{TextFormatter.java => util/Ui.java} | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) rename src/main/java/{TextFormatter.java => util/Ui.java} (61%) diff --git a/src/main/java/TextFormatter.java b/src/main/java/util/Ui.java similarity index 61% rename from src/main/java/TextFormatter.java rename to src/main/java/util/Ui.java index 991d6131bd..3330f510ad 100644 --- a/src/main/java/TextFormatter.java +++ b/src/main/java/util/Ui.java @@ -1,4 +1,6 @@ -public class TextFormatter { +package util; + +public class Ui { public static String formatLine(String input) { return "\t " + input + "\n"; } @@ -16,4 +18,12 @@ public static String formatLinesIntoParagraph(String... lines) { return formatParagraph(res); } + + public static void printIntroMessage() { + String introParagraph = Ui.formatLine("Hello! I'm duke.") + + Ui.formatLine("What can I do for you?"); + String formattedIntro = Ui.formatParagraph(introParagraph); + + System.out.println(formattedIntro); + } } From 52cc63213b6959ac31c255c9780ae6f0cc9a75c8 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 15:04:21 +0800 Subject: [PATCH 23/73] Refactor and move TaskList to tasklist package --- src/main/java/{ => tasklist}/TaskList.java | 31 +++++++++------------- 1 file changed, 13 insertions(+), 18 deletions(-) rename src/main/java/{ => tasklist}/TaskList.java (59%) diff --git a/src/main/java/TaskList.java b/src/main/java/tasklist/TaskList.java similarity index 59% rename from src/main/java/TaskList.java rename to src/main/java/tasklist/TaskList.java index ab96278e54..8fff9bbf52 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/tasklist/TaskList.java @@ -1,32 +1,23 @@ +package tasklist; + +import task.Task; +import util.Ui; import java.util.ArrayList; public class TaskList { private final ArrayList list = new ArrayList<>(); - public Task addTodo(String taskItem) { - Task task = new Todo(taskItem); - this.list.add(task); - return task; - } - - public Task addDeadline(String taskItem, String deadline) { - Task task = new Deadline(taskItem, deadline); - this.list.add(task); - return task; - } - - public Task addEvent(String taskItem, String eventTiming) { - Task task = new Event(taskItem, eventTiming); - this.list.add(task); - return task; + public Task addTask(Task taskItem) { + this.list.add(taskItem); + return taskItem; } @Override public String toString() { - String res = TextFormatter.formatLine("Here are the tasks in your list:"); + String res = Ui.formatLine("Here are the tasks in your list:"); for (int i = 0; i < this.list.size(); i++) { String nextListItem = String.format("%d.%s", i + 1, this.list.get(i)); - res += TextFormatter.formatLine(nextListItem); + res += Ui.formatLine(nextListItem); } return res; } @@ -49,6 +40,10 @@ public Task deleteItem(int index) { return taskItem; } + public Task getItem(int index) { + return this.list.get(index - 1); + } + public int getTaskCount() { return this.list.size(); } From 1695b301444bf8d94428e8b37da1b0b020ccf1e0 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 15:06:49 +0800 Subject: [PATCH 24/73] Refactor DukeException and add unknown task encoding exception --- src/main/java/{ => exception}/DukeException.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) rename src/main/java/{ => exception}/DukeException.java (75%) diff --git a/src/main/java/DukeException.java b/src/main/java/exception/DukeException.java similarity index 75% rename from src/main/java/DukeException.java rename to src/main/java/exception/DukeException.java index 3150956481..17e0d83de9 100644 --- a/src/main/java/DukeException.java +++ b/src/main/java/exception/DukeException.java @@ -1,3 +1,5 @@ +package exception; + public class DukeException extends Exception { private final ErrorCode errorCode; @@ -14,6 +16,9 @@ public String errorMessage() { case MISSING_TODO_ITEM: errorMsg = "☹ OOPS!!! The description of a todo cannot be empty."; break; + case UNKNOWN_TASK_ENCODING: + errorMsg = "☹ OOPS!!! Unable to parse one of the saved tasks. This task will be skipped."; + break; default: errorMsg = "☹ OOPS!!! Unknown duke error occurred. :-("; } @@ -22,6 +27,7 @@ public String errorMessage() { public enum ErrorCode { UNKNOWN_CMD, - MISSING_TODO_ITEM + MISSING_TODO_ITEM, + UNKNOWN_TASK_ENCODING } } From ed33f846a79134ef7b3a8c597f6a717239bfd396 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 15:08:08 +0800 Subject: [PATCH 25/73] Add storage class --- src/main/java/util/Storage.java | 62 +++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/main/java/util/Storage.java diff --git a/src/main/java/util/Storage.java b/src/main/java/util/Storage.java new file mode 100644 index 0000000000..fd8ef38d2b --- /dev/null +++ b/src/main/java/util/Storage.java @@ -0,0 +1,62 @@ +package util; + +import command.Command; +import exception.DukeException; +import task.Task; +import tasklist.TaskList; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Scanner; + +public class Storage { + private final File saveFile; + private Storage(File saveFile) { + this.saveFile = saveFile; + } + + public static Storage initialize(String storagePathName) { + File saveFile = new File(storagePathName); + try { + if (saveFile.getParentFile().mkdirs() && saveFile.createNewFile()) { + Ui.formatLinesIntoParagraph("Successfully created save file for storage!"); + } + } catch (IOException e) { + String errorMsg = "☹ OOPS!!! Error opening/creating saved storage."; + System.out.println(Ui.formatLinesIntoParagraph(errorMsg)); + } + + return new Storage(saveFile); + } + + public void load(TaskList list) { + try (Scanner sc = new Scanner(this.saveFile)) { + while (sc.hasNext()) { + try { + Command cmd = Parser.parseEncodedTask(sc.nextLine()); + cmd.execute(list, this); + } catch (DukeException e) { + System.out.println(Ui.formatLinesIntoParagraph(e.errorMessage())); + } + } + String successMsg = "Successfully loaded tasks from saved storage!"; + System.out.println(Ui.formatLinesIntoParagraph(successMsg)); + } catch (FileNotFoundException e) { + System.out.println(Ui.formatLinesIntoParagraph(e.getMessage())); + } + } + + public void saveAllTasks(TaskList list) { + try (FileWriter fileWriter = new FileWriter(this.saveFile, false)) { + for (int i = 1; i <= list.getTaskCount(); i++) { + Task task = list.getItem(i); + String encodedTask = task.encode(); + fileWriter.write(encodedTask); + } + } catch (IOException e) { + System.out.println(Ui.formatLinesIntoParagraph(e.getMessage())); + } + } +} From 308e10598e3addf9a7f4dccaf50729cb4a0c76a9 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 15:08:48 +0800 Subject: [PATCH 26/73] Add Parser class to util pkg --- src/main/java/util/Parser.java | 78 ++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/main/java/util/Parser.java diff --git a/src/main/java/util/Parser.java b/src/main/java/util/Parser.java new file mode 100644 index 0000000000..7026d03c95 --- /dev/null +++ b/src/main/java/util/Parser.java @@ -0,0 +1,78 @@ +package util; + +import command.*; +import exception.DukeException; +import task.Deadline; +import task.Event; +import task.Task; +import task.Todo; + +public class Parser { + public static Command parseInputLine(String inputLine) throws DukeException { + String[] splitted = inputLine.split("\\s+", 2); + String command = splitted[0]; + Command cmd; + switch (command) { + case "bye": + cmd = new TerminateCommand(); + break; + case "list": + cmd = new ListAllTasksCommand(); + break; + case "mark": + int index = Integer.parseInt(splitted[1]); + cmd = new MarkTaskCommand(index); + break; + case "unmark": + index = Integer.parseInt(splitted[1]); + cmd = new UnmarkTaskCommand(index); + break; + case "delete": + index = Integer.parseInt(splitted[1]); + cmd = new DeleteTaskCommand(index); + break; + case "todo": + Todo.validateInput(splitted); + Task todo = new Todo(splitted[1]); + cmd = new AddTaskCommand(todo); + break; + case "deadline": + // Regex "\\s+/" matches one or more space followed by a / + String[] taskArgs = splitted[1].split("\\s+/", 2); + Task deadline = new Deadline(taskArgs[0], taskArgs[1]); + cmd = new AddTaskCommand(deadline); + break; + case "event": + // Regex "\\s+/" matches one or more space followed by a / + taskArgs = splitted[1].split("\\s+/", 2); + Task event = new Event(taskArgs[0], taskArgs[1]); + cmd = new AddTaskCommand(event); + break; + default: + throw new DukeException(DukeException.ErrorCode.UNKNOWN_CMD); + } + return cmd; + } + + public static Command parseEncodedTask(String encodedTask) throws DukeException { + String[] splitted = encodedTask.split(",", 4); + String taskType = splitted[0]; + Task taskItem; + + switch (taskType) { + case "T": + taskItem = new Todo(splitted[2]); + break; + case "E": + taskItem = new Event(splitted[2], splitted[3]); + break; + case "D": + taskItem = new Deadline(splitted[2], splitted[3]); + break; + default: + throw new DukeException(DukeException.ErrorCode.UNKNOWN_TASK_ENCODING); + } + taskItem.setIsMarked(splitted[1].equals("1")); + return new AddTaskFromStorageCommand(taskItem); + } +} From 794e7d0929cbd95ed68b3eec6ba2b1301319724f Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 15:10:32 +0800 Subject: [PATCH 27/73] Add Command abstract class --- src/main/java/command/Command.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/main/java/command/Command.java diff --git a/src/main/java/command/Command.java b/src/main/java/command/Command.java new file mode 100644 index 0000000000..9f1e0f92ac --- /dev/null +++ b/src/main/java/command/Command.java @@ -0,0 +1,9 @@ +package command; + +import tasklist.TaskList; +import util.Storage; + +public abstract class Command { + public boolean isTerminated = false; + public abstract void execute(TaskList list, Storage storage); +} From 2929330b5c480e5e014c78e9c2513a4bf2b9c984 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 15:11:31 +0800 Subject: [PATCH 28/73] Move execution logic to relevant Command subclasses --- src/main/java/command/AddTaskCommand.java | 27 +++++++++++++++++++ .../command/AddTaskFromStorageCommand.java | 17 ++++++++++++ src/main/java/command/DeleteTaskCommand.java | 27 +++++++++++++++++++ .../java/command/ListAllTasksCommand.java | 14 ++++++++++ src/main/java/command/MarkTaskCommand.java | 22 +++++++++++++++ src/main/java/command/TerminateCommand.java | 12 +++++++++ src/main/java/command/UnmarkTaskCommand.java | 23 ++++++++++++++++ 7 files changed, 142 insertions(+) create mode 100644 src/main/java/command/AddTaskCommand.java create mode 100644 src/main/java/command/AddTaskFromStorageCommand.java create mode 100644 src/main/java/command/DeleteTaskCommand.java create mode 100644 src/main/java/command/ListAllTasksCommand.java create mode 100644 src/main/java/command/MarkTaskCommand.java create mode 100644 src/main/java/command/TerminateCommand.java create mode 100644 src/main/java/command/UnmarkTaskCommand.java diff --git a/src/main/java/command/AddTaskCommand.java b/src/main/java/command/AddTaskCommand.java new file mode 100644 index 0000000000..08a7e9bd22 --- /dev/null +++ b/src/main/java/command/AddTaskCommand.java @@ -0,0 +1,27 @@ +package command; + +import task.Task; +import tasklist.TaskList; +import util.Storage; +import util.Ui; + +public class AddTaskCommand extends Command { + private final Task taskItem; + public AddTaskCommand(Task taskItem) { + this.taskItem = taskItem; + } + + @Override + public void execute(TaskList list, Storage storage) { + String task = " " + list.addTask(this.taskItem); + String startLine = "Got it. I've added this task:"; + String endLine = String.format( + "Now you have %d tasks in the list.", + list.getTaskCount()); + System.out.println(Ui.formatLinesIntoParagraph( + startLine, + task, + endLine + )); + } +} diff --git a/src/main/java/command/AddTaskFromStorageCommand.java b/src/main/java/command/AddTaskFromStorageCommand.java new file mode 100644 index 0000000000..fadc8637d9 --- /dev/null +++ b/src/main/java/command/AddTaskFromStorageCommand.java @@ -0,0 +1,17 @@ +package command; + +import task.Task; +import tasklist.TaskList; +import util.Storage; + +public class AddTaskFromStorageCommand extends Command { + private final Task taskItem; + public AddTaskFromStorageCommand(Task taskItem) { + this.taskItem = taskItem; + } + + @Override + public void execute(TaskList list, Storage storage) { + list.addTask(this.taskItem); + } +} diff --git a/src/main/java/command/DeleteTaskCommand.java b/src/main/java/command/DeleteTaskCommand.java new file mode 100644 index 0000000000..4e7eb752b9 --- /dev/null +++ b/src/main/java/command/DeleteTaskCommand.java @@ -0,0 +1,27 @@ +package command; + +import tasklist.TaskList; +import util.Storage; +import util.Ui; + +public class DeleteTaskCommand extends Command { + private final int index; + + public DeleteTaskCommand(int index) { + this.index = index; + } + + @Override + public void execute(TaskList list, Storage storage) { + String deletedItem = " " + list.deleteItem(index); + String deleteText = "Noted. I've removed this task:"; + String endLine = String.format( + "Now you have %d tasks in the list.", + list.getTaskCount()); + System.out.println(Ui.formatLinesIntoParagraph( + deleteText, + deletedItem, + endLine + )); + } +} diff --git a/src/main/java/command/ListAllTasksCommand.java b/src/main/java/command/ListAllTasksCommand.java new file mode 100644 index 0000000000..699ec40cfc --- /dev/null +++ b/src/main/java/command/ListAllTasksCommand.java @@ -0,0 +1,14 @@ +package command; + +import tasklist.TaskList; +import util.Storage; +import util.Ui; + +public class ListAllTasksCommand extends Command { + @Override + public void execute(TaskList list, Storage storage) { + System.out.println(Ui.formatParagraph( + list.toString() + )); + } +} diff --git a/src/main/java/command/MarkTaskCommand.java b/src/main/java/command/MarkTaskCommand.java new file mode 100644 index 0000000000..07efb8d5b1 --- /dev/null +++ b/src/main/java/command/MarkTaskCommand.java @@ -0,0 +1,22 @@ +package command; + +import tasklist.TaskList; +import util.Storage; +import util.Ui; + +public class MarkTaskCommand extends Command { + private final int index; + public MarkTaskCommand(int index) { + this.index = index; + } + + @Override + public void execute(TaskList list, Storage storage) { + String markedItem = " " + list.markItem(index); + String markedText = "Nice! I've marked this task as done:"; + System.out.println(Ui.formatLinesIntoParagraph( + markedText, + markedItem + )); + } +} diff --git a/src/main/java/command/TerminateCommand.java b/src/main/java/command/TerminateCommand.java new file mode 100644 index 0000000000..7dc69eb29e --- /dev/null +++ b/src/main/java/command/TerminateCommand.java @@ -0,0 +1,12 @@ +package command; + +import tasklist.TaskList; +import util.Storage; + +public class TerminateCommand extends Command{ + @Override + public void execute(TaskList list, Storage storage) { + isTerminated = true; + storage.saveAllTasks(list); + } +} diff --git a/src/main/java/command/UnmarkTaskCommand.java b/src/main/java/command/UnmarkTaskCommand.java new file mode 100644 index 0000000000..0f326c824a --- /dev/null +++ b/src/main/java/command/UnmarkTaskCommand.java @@ -0,0 +1,23 @@ +package command; + +import tasklist.TaskList; +import util.Storage; +import util.Ui; + +public class UnmarkTaskCommand extends Command{ + private final int index; + + public UnmarkTaskCommand(int index) { + this.index = index; + } + + @Override + public void execute(TaskList list, Storage storage) { + String unmarkedItem = " " + list.unmarkItem(index); + String unmarkedText = "OK, I've marked this task as not done yet:"; + System.out.println(Ui.formatLinesIntoParagraph( + unmarkedText, + unmarkedItem + )); + } +} From 9301f1ff4b639e47c469329418f2468c7b732686 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 15:12:18 +0800 Subject: [PATCH 29/73] Update Duke to match previous changes --- src/main/java/Duke.java | 115 ----------------------------------- src/main/java/duke/Duke.java | 40 ++++++++++++ 2 files changed, 40 insertions(+), 115 deletions(-) delete mode 100644 src/main/java/Duke.java create mode 100644 src/main/java/duke/Duke.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java deleted file mode 100644 index 4804c466fb..0000000000 --- a/src/main/java/Duke.java +++ /dev/null @@ -1,115 +0,0 @@ -import java.util.Scanner; - -public class Duke { - public static void main(String[] args) { - String introParagraph = TextFormatter.formatLine("Hello! I'm Duke") + - TextFormatter.formatLine("What can I do for you?"); - String formattedIntro = TextFormatter.formatParagraph(introParagraph); - - System.out.println(formattedIntro); - - Scanner sc = new Scanner(System.in); - boolean terminate = false; - TaskList dukelist = new TaskList(); - - while(!terminate) { - try { - String nextLine = sc.nextLine(); - // Regex "//s+" matches one or more spaces - String[] splitted = nextLine.split("\\s+", 2); - String command = splitted[0]; - switch (command) { - case "bye": - System.out.println( - TextFormatter.formatLinesIntoParagraph("Bye. Hope to see you again soon!") - ); - terminate = true; - sc.close(); - break; - case "list": - System.out.println(TextFormatter.formatParagraph( - dukelist.toString() - )); - break; - case "mark": - int index = Integer.parseInt(splitted[1]); - String markedItem = " " + dukelist.markItem(index); - String markedText = "Nice! I've marked this task as done:"; - System.out.println(TextFormatter.formatLinesIntoParagraph( - markedText, - markedItem - )); - break; - case "unmark": - index = Integer.parseInt(splitted[1]); - String unmarkedItem = " " + dukelist.unmarkItem(index); - String unmarkedText = "OK, I've marked this task as not done yet:"; - System.out.println(TextFormatter.formatLinesIntoParagraph( - unmarkedText, - unmarkedItem - )); - break; - case "delete": - index = Integer.parseInt(splitted[1]); - String deletedItem = " " + dukelist.deleteItem(index); - String deleteText = "Noted. I've removed this task:"; - String endLine = String.format( - "Now you have %d tasks in the list.", - dukelist.getTaskCount()); - System.out.println(TextFormatter.formatLinesIntoParagraph( - deleteText, - deletedItem, - endLine - )); - break; - case "todo": - Todo.validateInput(splitted); - String todo = splitted[1]; - String taskItem = " " + dukelist.addTodo(todo); - String startLine = "Got it. I've added this task:"; - endLine = String.format( - "Now you have %d tasks in the list.", - dukelist.getTaskCount()); - System.out.println(TextFormatter.formatLinesIntoParagraph( - startLine, - taskItem, - endLine - )); - break; - case "deadline": - // Regex "\\s+/" matches one or more space followed by a / - String[] taskArgs = splitted[1].split("\\s+/",2); - taskItem = " " + dukelist.addDeadline(taskArgs[0], taskArgs[1]); - startLine = "Got it. I've added this task:"; - endLine = String.format( - "Now you have %d tasks in the list.", - dukelist.getTaskCount()); - System.out.println(TextFormatter.formatLinesIntoParagraph( - startLine, - taskItem, - endLine - )); - break; - case "event": - // Regex "\\s+/" matches one or more space followed by a / - taskArgs = splitted[1].split("\\s+/",2); - taskItem = " " + dukelist.addEvent(taskArgs[0], taskArgs[1]); - startLine = "Got it. I've added this task:"; - endLine = String.format( - "Now you have %d tasks in the list.", - dukelist.getTaskCount()); - System.out.println(TextFormatter.formatLinesIntoParagraph( - startLine, - taskItem, - endLine - )); - break; - default: - throw new DukeException(DukeException.ErrorCode.UNKNOWN_CMD); - } - } catch (DukeException e) { - System.out.println(TextFormatter.formatLinesIntoParagraph(e.errorMessage())); - } - } - } -} diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java new file mode 100644 index 0000000000..6c4e07a513 --- /dev/null +++ b/src/main/java/duke/Duke.java @@ -0,0 +1,40 @@ +package duke; + +import command.Command; +import exception.DukeException; +import tasklist.TaskList; +import util.Parser; +import util.Storage; +import util.Ui; + +import java.util.Scanner; + +public class Duke { + private TaskList dukelist = new TaskList(); + private Storage storage; + + public Duke(String filePath) { + storage = Storage.initialize(filePath); + storage.load(dukelist); + } + + public void run() { + Ui.printIntroMessage(); + boolean isTerminated = false; + Scanner sc = new Scanner(System.in); + + while(!isTerminated) { + try { + String nextLine = sc.nextLine(); + Command cmd = Parser.parseInputLine(nextLine); + cmd.execute(dukelist, storage); + isTerminated = cmd.isTerminated; + } catch (DukeException e) { + System.out.println(Ui.formatLinesIntoParagraph(e.errorMessage())); + } + } + } + public static void main(String[] args) { + new Duke("data/saveFile.txt").run(); + } +} From 5af5b3503ea9ab540abb4788fcbbe64c2a9bb4bb Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 15:12:37 +0800 Subject: [PATCH 30/73] Add data/saveFile.txt to gitIgnore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f69985ef1f..d7ced6fa9f 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ bin/ /text-ui-test/ACTUAL.txt text-ui-test/EXPECTED-UNIX.TXT +/data/saveFile.txt \ No newline at end of file From c9c36a4abab7a1b17f34da8b0c87992ac5e31e78 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 15:21:14 +0800 Subject: [PATCH 31/73] Edit Duke to only parse /by or /at for Deadline and Event respectively --- src/main/java/Duke.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 4804c466fb..07dbc032e4 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -77,8 +77,9 @@ public static void main(String[] args) { )); break; case "deadline": - // Regex "\\s+/" matches one or more space followed by a / - String[] taskArgs = splitted[1].split("\\s+/",2); + // Regex "\\s+/" matches one or more space followed by a /by, + // followed by one or more space + String[] taskArgs = splitted[1].split("\\s+/by\\s+",2); taskItem = " " + dukelist.addDeadline(taskArgs[0], taskArgs[1]); startLine = "Got it. I've added this task:"; endLine = String.format( @@ -91,8 +92,9 @@ public static void main(String[] args) { )); break; case "event": - // Regex "\\s+/" matches one or more space followed by a / - taskArgs = splitted[1].split("\\s+/",2); + // Regex "\s+/at\s+" matches one or more space followed by a /at, + // followed by one or more space + taskArgs = splitted[1].split("\\s+/at\\s+",2); taskItem = " " + dukelist.addEvent(taskArgs[0], taskArgs[1]); startLine = "Got it. I've added this task:"; endLine = String.format( From c4e868dac5f4519d21ed8227f997aafd45e76962 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 20:30:44 +0800 Subject: [PATCH 32/73] Add invalid datetime format exceptions --- src/main/java/DukeException.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java index 3150956481..8142d0d75f 100644 --- a/src/main/java/DukeException.java +++ b/src/main/java/DukeException.java @@ -14,6 +14,16 @@ public String errorMessage() { case MISSING_TODO_ITEM: errorMsg = "☹ OOPS!!! The description of a todo cannot be empty."; break; + case INVALID_DEADLINE_DATETIME_FORMAT: + String dateFormat = "\t Please ensure date time is of the " + + "following format: yyyy-mm-dd hh:mm:ss"; + errorMsg = "☹ OOPS!!! Unknown to parse date time.\n" + dateFormat; + break; + case INVALID_EVENT_DATETIME_FORMAT: + dateFormat = "\t Please ensure date time is of the " + + "following format: yyyy-mm-dd hh:mm:ss hh:mm:ss hh:mm:ss"; + errorMsg = "☹ OOPS!!! Unknown to parse date time.\n" + dateFormat; + break; default: errorMsg = "☹ OOPS!!! Unknown duke error occurred. :-("; } @@ -22,6 +32,8 @@ public String errorMessage() { public enum ErrorCode { UNKNOWN_CMD, - MISSING_TODO_ITEM + MISSING_TODO_ITEM, + INVALID_DEADLINE_DATETIME_FORMAT, + INVALID_EVENT_DATETIME_FORMAT } } From f874ae40b329cfcf1c5512f14551b4b0733665b2 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 20:31:54 +0800 Subject: [PATCH 33/73] Add Date classes --- src/main/java/Date.java | 16 ++++++++++++ src/main/java/DeadlineDateTime.java | 31 +++++++++++++++++++++++ src/main/java/EventDateTime.java | 38 +++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 src/main/java/Date.java create mode 100644 src/main/java/DeadlineDateTime.java create mode 100644 src/main/java/EventDateTime.java diff --git a/src/main/java/Date.java b/src/main/java/Date.java new file mode 100644 index 0000000000..5b2857f43c --- /dev/null +++ b/src/main/java/Date.java @@ -0,0 +1,16 @@ +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +public abstract class Date { + private LocalDate date; + + public Date(String date) throws DateTimeParseException { + this.date = LocalDate.parse(date); + } + + @Override + public String toString() { + return date.format(DateTimeFormatter.ofPattern("MMM d yyyy")); + } +} diff --git a/src/main/java/DeadlineDateTime.java b/src/main/java/DeadlineDateTime.java new file mode 100644 index 0000000000..b581192263 --- /dev/null +++ b/src/main/java/DeadlineDateTime.java @@ -0,0 +1,31 @@ +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +public class DeadlineDateTime extends Date { + private LocalTime time; + + private DeadlineDateTime(String date, String time) throws DateTimeParseException { + super(date); + this.time = LocalTime.parse(time); + } + + public static DeadlineDateTime parseDate(String dateTime) throws DukeException { + String[] splitted = dateTime.split("\\s+", 2); + if (splitted.length < 2 || splitted[0].strip().equals("") || splitted[1].strip().equals("")) { + throw new DukeException(DukeException.ErrorCode.INVALID_DEADLINE_DATETIME_FORMAT); + } + try { + return new DeadlineDateTime(splitted[0], splitted[1]); + } catch (DateTimeParseException e) { + throw new DukeException(DukeException.ErrorCode.INVALID_DEADLINE_DATETIME_FORMAT); + } + } + + @Override + public String toString() { + String timeColonPattern = "HH:mm:ss"; + String formattedTime = time.format(DateTimeFormatter.ofPattern(timeColonPattern)); + return super.toString() + ' ' + formattedTime; + } +} diff --git a/src/main/java/EventDateTime.java b/src/main/java/EventDateTime.java new file mode 100644 index 0000000000..de15aac708 --- /dev/null +++ b/src/main/java/EventDateTime.java @@ -0,0 +1,38 @@ +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +public class EventDateTime extends Date { + private LocalTime startTime; + private LocalTime endTime; + + private EventDateTime(String date, String startTime, String endTime) throws DateTimeParseException { + super(date); + this.startTime = LocalTime.parse(startTime); + this.endTime = LocalTime.parse(endTime); + } + + public static EventDateTime parseDate(String dateTime) throws DukeException { + String[] splitted = dateTime.split("\\s+", 3); + if (splitted.length < 3 || + splitted[0].strip().equals("") || + splitted[1].strip().equals("") || + splitted[2].strip().equals("")) { + System.out.println("length error"); + throw new DukeException(DukeException.ErrorCode.INVALID_EVENT_DATETIME_FORMAT); + } + try { + return new EventDateTime(splitted[0], splitted[1], splitted[2]); + } catch (DateTimeParseException e) { + throw new DukeException(DukeException.ErrorCode.INVALID_EVENT_DATETIME_FORMAT); + } + } + + @Override + public String toString() { + String timeColonPattern = "HH:mm:ss"; + String formattedStartTime = startTime.format(DateTimeFormatter.ofPattern(timeColonPattern)); + String formattedEndTime = endTime.format(DateTimeFormatter.ofPattern(timeColonPattern)); + return super.toString() + ' ' + formattedStartTime + " - " + formattedEndTime; + } +} From 8d840af53356914bca065007134b1d6ee6d8a116 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 20:32:28 +0800 Subject: [PATCH 34/73] Update tasklist and tasks to use date classes --- src/main/java/Deadline.java | 4 ++-- src/main/java/Event.java | 6 +++--- src/main/java/TaskList.java | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index ed6847d2f0..78ef463ff3 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -1,7 +1,7 @@ public class Deadline extends Task { - private final String deadline; + private final DeadlineDateTime deadline; - public Deadline(String taskItem, String deadline) { + public Deadline(String taskItem, DeadlineDateTime deadline) { super(taskItem); this.deadline = deadline; } diff --git a/src/main/java/Event.java b/src/main/java/Event.java index 439b06ad75..6c6afcd7a9 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -1,6 +1,6 @@ public class Event extends Task{ - private final String eventTiming; - public Event(String taskItem, String eventTiming) { + private final EventDateTime eventTiming; + public Event(String taskItem, EventDateTime eventTiming) { super(taskItem); this.eventTiming = eventTiming; } @@ -8,6 +8,6 @@ public Event(String taskItem, String eventTiming) { @Override public String toString() { String eventTimingDisplay = String.format(" (at: %s)", this.eventTiming); - return "[D]" + super.toString() + eventTimingDisplay; + return "[E]" + super.toString() + eventTimingDisplay; } } diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index ab96278e54..3dd8039a82 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -9,13 +9,13 @@ public Task addTodo(String taskItem) { return task; } - public Task addDeadline(String taskItem, String deadline) { + public Task addDeadline(String taskItem, DeadlineDateTime deadline) { Task task = new Deadline(taskItem, deadline); this.list.add(task); return task; } - public Task addEvent(String taskItem, String eventTiming) { + public Task addEvent(String taskItem, EventDateTime eventTiming) { Task task = new Event(taskItem, eventTiming); this.list.add(task); return task; From e752e41b093c8a4b431d328b7c35cad9e2cfaee4 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 20:33:19 +0800 Subject: [PATCH 35/73] Update Duke to match date changes --- src/main/java/Duke.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 07dbc032e4..d9ae3c5964 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -80,7 +80,8 @@ public static void main(String[] args) { // Regex "\\s+/" matches one or more space followed by a /by, // followed by one or more space String[] taskArgs = splitted[1].split("\\s+/by\\s+",2); - taskItem = " " + dukelist.addDeadline(taskArgs[0], taskArgs[1]); + DeadlineDateTime deadlineDateTime = DeadlineDateTime.parseDate(taskArgs[1]); + taskItem = " " + dukelist.addDeadline(taskArgs[0], deadlineDateTime); startLine = "Got it. I've added this task:"; endLine = String.format( "Now you have %d tasks in the list.", @@ -95,7 +96,8 @@ public static void main(String[] args) { // Regex "\s+/at\s+" matches one or more space followed by a /at, // followed by one or more space taskArgs = splitted[1].split("\\s+/at\\s+",2); - taskItem = " " + dukelist.addEvent(taskArgs[0], taskArgs[1]); + EventDateTime eventDateTime = EventDateTime.parseDate(taskArgs[1]); + taskItem = " " + dukelist.addEvent(taskArgs[0], eventDateTime); startLine = "Got it. I've added this task:"; endLine = String.format( "Now you have %d tasks in the list.", From df1bf3cf9d6fb5ac93f1f46aa51e01204f89ef4e Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 22:48:42 +0800 Subject: [PATCH 36/73] Move date classes to date pkg --- src/main/java/Date.java | 16 -------------- src/main/java/date/Date.java | 22 +++++++++++++++++++ .../java/{ => date}/DeadlineDateTime.java | 21 ++++++++++++++++++ src/main/java/{ => date}/EventDateTime.java | 21 ++++++++++++++++++ 4 files changed, 64 insertions(+), 16 deletions(-) delete mode 100644 src/main/java/Date.java create mode 100644 src/main/java/date/Date.java rename src/main/java/{ => date}/DeadlineDateTime.java (62%) rename src/main/java/{ => date}/EventDateTime.java (65%) diff --git a/src/main/java/Date.java b/src/main/java/Date.java deleted file mode 100644 index 5b2857f43c..0000000000 --- a/src/main/java/Date.java +++ /dev/null @@ -1,16 +0,0 @@ -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; - -public abstract class Date { - private LocalDate date; - - public Date(String date) throws DateTimeParseException { - this.date = LocalDate.parse(date); - } - - @Override - public String toString() { - return date.format(DateTimeFormatter.ofPattern("MMM d yyyy")); - } -} diff --git a/src/main/java/date/Date.java b/src/main/java/date/Date.java new file mode 100644 index 0000000000..510d64a0dc --- /dev/null +++ b/src/main/java/date/Date.java @@ -0,0 +1,22 @@ +package date; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +public abstract class Date { + private LocalDate date; + + public Date(String date) throws DateTimeParseException { + this.date = LocalDate.parse(date); + } + + @Override + public String toString() { + return date.format(DateTimeFormatter.ofPattern("MMM d yyyy")); + } + + public String encode() { + return date.toString(); + } +} diff --git a/src/main/java/DeadlineDateTime.java b/src/main/java/date/DeadlineDateTime.java similarity index 62% rename from src/main/java/DeadlineDateTime.java rename to src/main/java/date/DeadlineDateTime.java index b581192263..42090b885c 100644 --- a/src/main/java/DeadlineDateTime.java +++ b/src/main/java/date/DeadlineDateTime.java @@ -1,3 +1,8 @@ +package date; + +import exception.DukeException; +import util.Ui; + import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; @@ -22,10 +27,26 @@ public static DeadlineDateTime parseDate(String dateTime) throws DukeException { } } + public static DeadlineDateTime parseDateFromStorage(String storedDateTime) throws DukeException { + String[] dateTime = storedDateTime.split("\\|", 2); + try { + return new DeadlineDateTime(dateTime[0], dateTime[1]); + } catch (DateTimeParseException e) { + throw new DukeException(DukeException.ErrorCode.INVALID_DEADLINE_DATETIME_FORMAT); + } + } + @Override public String toString() { String timeColonPattern = "HH:mm:ss"; String formattedTime = time.format(DateTimeFormatter.ofPattern(timeColonPattern)); return super.toString() + ' ' + formattedTime; } + + @Override + public String encode() { + String timeColonPattern = "HH:mm:ss"; + String formattedTime = time.format(DateTimeFormatter.ofPattern(timeColonPattern)); + return super.encode() + '|' + formattedTime; + } } diff --git a/src/main/java/EventDateTime.java b/src/main/java/date/EventDateTime.java similarity index 65% rename from src/main/java/EventDateTime.java rename to src/main/java/date/EventDateTime.java index de15aac708..fb7f0f5a61 100644 --- a/src/main/java/EventDateTime.java +++ b/src/main/java/date/EventDateTime.java @@ -1,3 +1,7 @@ +package date; + +import exception.DukeException; + import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; @@ -28,6 +32,15 @@ public static EventDateTime parseDate(String dateTime) throws DukeException { } } + public static EventDateTime parseDateFromStorage(String storedDateTime) throws DukeException { + String[] dateTime = storedDateTime.split("\\|", 3); + try { + return new EventDateTime(dateTime[0], dateTime[1], dateTime[2]); + } catch (DateTimeParseException e) { + throw new DukeException(DukeException.ErrorCode.INVALID_EVENT_DATETIME_FORMAT); + } + } + @Override public String toString() { String timeColonPattern = "HH:mm:ss"; @@ -35,4 +48,12 @@ public String toString() { String formattedEndTime = endTime.format(DateTimeFormatter.ofPattern(timeColonPattern)); return super.toString() + ' ' + formattedStartTime + " - " + formattedEndTime; } + + @Override + public String encode() { + String timeColonPattern = "HH:mm:ss"; + String formattedStartTime = startTime.format(DateTimeFormatter.ofPattern(timeColonPattern)); + String formattedEndTime = endTime.format(DateTimeFormatter.ofPattern(timeColonPattern)); + return super.encode() + '|' + formattedStartTime + '|' + formattedEndTime; + } } From b934421b5c93e056191d7aa73a879d468e475b75 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 22:49:48 +0800 Subject: [PATCH 37/73] Add encoding for Deadline/Event --- src/main/java/task/Deadline.java | 4 +++- src/main/java/task/Event.java | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/task/Deadline.java b/src/main/java/task/Deadline.java index f5931ef31c..1fde84108c 100644 --- a/src/main/java/task/Deadline.java +++ b/src/main/java/task/Deadline.java @@ -1,5 +1,7 @@ package task; +import date.DeadlineDateTime; + public class Deadline extends Task { private final DeadlineDateTime deadline; @@ -17,6 +19,6 @@ public String toString() { @Override public String encode() { int markedStatus = getIsMarked() ? 1 : 0; - return String.format("D,%d,%s,%s\n", markedStatus, getTaskItem(), deadline); + return String.format("D,%d,%s,%s\n", markedStatus, getTaskItem(), deadline.encode()); } } diff --git a/src/main/java/task/Event.java b/src/main/java/task/Event.java index e62dbbbf7f..732b4dbefd 100644 --- a/src/main/java/task/Event.java +++ b/src/main/java/task/Event.java @@ -1,5 +1,7 @@ package task; +import date.EventDateTime; + public class Event extends Task{ private final EventDateTime eventTiming; @@ -17,6 +19,6 @@ public String toString() { @Override public String encode() { int markedStatus = getIsMarked() ? 1 : 0; - return String.format("E,%d,%s,%s\n", markedStatus, getTaskItem(), eventTiming); + return String.format("E,%d,%s,%s\n", markedStatus, getTaskItem(), eventTiming.encode()); } } From 480e5b7d0a39471becb8662cff259ae1cb28bf34 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 22:50:36 +0800 Subject: [PATCH 38/73] Fix regression in exception when resolving merge conflict --- src/main/java/exception/DukeException.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/exception/DukeException.java b/src/main/java/exception/DukeException.java index 203645281b..7fe866cf3c 100644 --- a/src/main/java/exception/DukeException.java +++ b/src/main/java/exception/DukeException.java @@ -21,12 +21,12 @@ public String errorMessage() { case INVALID_DEADLINE_DATETIME_FORMAT: String dateFormat = "\t Please ensure date time is of the " + "following format: yyyy-mm-dd hh:mm:ss"; - errorMsg = "☹ OOPS!!! Unknown to parse date time.\n" + dateFormat; + errorMsg = "☹ OOPS!!! Unable to parse date time for deadline.\n" + dateFormat; break; case INVALID_EVENT_DATETIME_FORMAT: dateFormat = "\t Please ensure date time is of the " + "following format: yyyy-mm-dd hh:mm:ss hh:mm:ss hh:mm:ss"; - errorMsg = "☹ OOPS!!! Unknown to parse date time.\n" + dateFormat; + errorMsg = "☹ OOPS!!! Unable to parse date time for event.\n" + dateFormat; break; default: errorMsg = "☹ OOPS!!! Unknown duke error occurred. :-("; @@ -37,7 +37,7 @@ public String errorMessage() { public enum ErrorCode { UNKNOWN_CMD, MISSING_TODO_ITEM, - UNKNOWN_TASK_ENCODING + UNKNOWN_TASK_ENCODING, INVALID_DEADLINE_DATETIME_FORMAT, INVALID_EVENT_DATETIME_FORMAT } From ea5a64bffd32d0be150fac73953b3c71e3cbf23a Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 22:51:03 +0800 Subject: [PATCH 39/73] Update Parser to proper parse Deadline/Event --- src/main/java/util/Parser.java | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/main/java/util/Parser.java b/src/main/java/util/Parser.java index 7026d03c95..2d31e649e1 100644 --- a/src/main/java/util/Parser.java +++ b/src/main/java/util/Parser.java @@ -1,6 +1,8 @@ package util; import command.*; +import date.DeadlineDateTime; +import date.EventDateTime; import exception.DukeException; import task.Deadline; import task.Event; @@ -37,15 +39,19 @@ public static Command parseInputLine(String inputLine) throws DukeException { cmd = new AddTaskCommand(todo); break; case "deadline": - // Regex "\\s+/" matches one or more space followed by a / - String[] taskArgs = splitted[1].split("\\s+/", 2); - Task deadline = new Deadline(taskArgs[0], taskArgs[1]); + // Regex "\\s+/" matches one or more space followed by a /by, + // followed by one or more space + String[] taskArgs = splitted[1].split("\\s+/by\\s+",2); + DeadlineDateTime deadlineDateTime = DeadlineDateTime.parseDate(taskArgs[1]); + Task deadline = new Deadline(taskArgs[0], deadlineDateTime); cmd = new AddTaskCommand(deadline); break; case "event": - // Regex "\\s+/" matches one or more space followed by a / - taskArgs = splitted[1].split("\\s+/", 2); - Task event = new Event(taskArgs[0], taskArgs[1]); + // Regex "\s+/at\s+" matches one or more space followed by a /at, + // followed by one or more space + taskArgs = splitted[1].split("\\s+/at\\s+",2); + EventDateTime eventDateTime = EventDateTime.parseDate(taskArgs[1]); + Task event = new Event(taskArgs[0], eventDateTime); cmd = new AddTaskCommand(event); break; default: @@ -64,10 +70,12 @@ public static Command parseEncodedTask(String encodedTask) throws DukeException taskItem = new Todo(splitted[2]); break; case "E": - taskItem = new Event(splitted[2], splitted[3]); + EventDateTime eventDateTime = EventDateTime.parseDateFromStorage(splitted[3]); + taskItem = new Event(splitted[2], eventDateTime); break; case "D": - taskItem = new Deadline(splitted[2], splitted[3]); + DeadlineDateTime deadlineDateTime = DeadlineDateTime.parseDateFromStorage(splitted[3]); + taskItem = new Deadline(splitted[2], deadlineDateTime); break; default: throw new DukeException(DukeException.ErrorCode.UNKNOWN_TASK_ENCODING); From caba951f31e3b4c0bc9fef1e2988d98539b721e6 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 25 Aug 2022 22:51:41 +0800 Subject: [PATCH 40/73] Fix Storage not creating new save file if dir exists --- src/main/java/util/Storage.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/util/Storage.java b/src/main/java/util/Storage.java index fd8ef38d2b..a65108ed10 100644 --- a/src/main/java/util/Storage.java +++ b/src/main/java/util/Storage.java @@ -20,7 +20,8 @@ private Storage(File saveFile) { public static Storage initialize(String storagePathName) { File saveFile = new File(storagePathName); try { - if (saveFile.getParentFile().mkdirs() && saveFile.createNewFile()) { + saveFile.getParentFile().mkdirs(); + if (saveFile.createNewFile()) { Ui.formatLinesIntoParagraph("Successfully created save file for storage!"); } } catch (IOException e) { From b3a1a2fe2492f2aaede193267c1ff1b6074ccb39 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Fri, 26 Aug 2022 23:44:34 +0800 Subject: [PATCH 41/73] Add stubs for Task class --- src/test/java/task/stub/MarkedTaskStub.java | 13 ++++++++ src/test/java/task/stub/TaskStub.java | 32 +++++++++++++++++++ src/test/java/task/stub/UnmarkedTaskStub.java | 15 +++++++++ 3 files changed, 60 insertions(+) create mode 100644 src/test/java/task/stub/MarkedTaskStub.java create mode 100644 src/test/java/task/stub/TaskStub.java create mode 100644 src/test/java/task/stub/UnmarkedTaskStub.java diff --git a/src/test/java/task/stub/MarkedTaskStub.java b/src/test/java/task/stub/MarkedTaskStub.java new file mode 100644 index 0000000000..9ec49d9768 --- /dev/null +++ b/src/test/java/task/stub/MarkedTaskStub.java @@ -0,0 +1,13 @@ +package task.stub; + +public class MarkedTaskStub extends TaskStub { + @Override + protected boolean getIsMarked() { + return true; + } + + @Override + public String encode() { + return "[X] " + this.getTaskItem(); + } +} diff --git a/src/test/java/task/stub/TaskStub.java b/src/test/java/task/stub/TaskStub.java new file mode 100644 index 0000000000..9f7d406b0f --- /dev/null +++ b/src/test/java/task/stub/TaskStub.java @@ -0,0 +1,32 @@ +package task.stub; + +import task.Task; + +public class TaskStub extends Task { + public TaskStub() { + super("Testing!"); + } + + @Override + public String encode() { + return this.toString(); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + + if (o instanceof TaskStub) { + return this.getIsMarked() == ((TaskStub) o).getIsMarked(); + } + + return false; + } + + @Override + public String toString() { + return "Testing!"; + } +} diff --git a/src/test/java/task/stub/UnmarkedTaskStub.java b/src/test/java/task/stub/UnmarkedTaskStub.java new file mode 100644 index 0000000000..015a913ae3 --- /dev/null +++ b/src/test/java/task/stub/UnmarkedTaskStub.java @@ -0,0 +1,15 @@ +package task.stub; + +import task.stub.TaskStub; + +public class UnmarkedTaskStub extends TaskStub { + @Override + protected boolean getIsMarked() { + return false; + } + + @Override + public String encode() { + return "[ ] " + this.getTaskItem(); + } +} From 183db00b16734ee8918fe2761f91c782f55d42f0 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Fri, 26 Aug 2022 23:44:55 +0800 Subject: [PATCH 42/73] Add unit tests for TaskList --- src/test/java/tasklist/TaskListTest.java | 91 ++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/test/java/tasklist/TaskListTest.java diff --git a/src/test/java/tasklist/TaskListTest.java b/src/test/java/tasklist/TaskListTest.java new file mode 100644 index 0000000000..2e75967200 --- /dev/null +++ b/src/test/java/tasklist/TaskListTest.java @@ -0,0 +1,91 @@ +package tasklist; + +import org.junit.jupiter.api.Test; +import task.stub.MarkedTaskStub; +import task.Task; +import task.stub.TaskStub; +import task.stub.UnmarkedTaskStub; + +import static org.junit.jupiter.api.Assertions.*; + +class TaskListTest { + + @Test + void addTask() { + TaskList test = new TaskList(); + Task stub = new TaskStub(); + Task returnedStub = test.addTask(stub); + assertAll( + () -> assertSame(returnedStub, stub), + () -> assertSame(stub, test.getItem(1)) + ); + } + + @Test + void testToString_when_list_is_empty() { + TaskList test = new TaskList(); + String expected = "\t " + "Here are the tasks in your list:" + "\n"; + assertEquals(expected, test.toString()); + } + + @Test + void testToString_when_list_is_not_empty() { + TaskList test = new TaskList(); + Task stub = new TaskStub(); + test.addTask(stub); + + String taskItemString = String.format("\t 1.%s\n", stub.toString()); + String expected = "\t " + "Here are the tasks in your list:" + "\n" + + taskItemString; + assertEquals(expected, test.toString()); + } + + @Test + void markItem() { + TaskList test = new TaskList(); + Task stub = new TaskStub(); + test.addTask(stub); + Task markedStub = test.markItem(1); + + Task expectedStub = new MarkedTaskStub(); + expectedStub.setIsMarked(true); + + assertEquals(expectedStub, markedStub); + } + + @Test + void unmarkItem() { + TaskList test = new TaskList(); + Task stub = new TaskStub(); + test.addTask(stub); + test.markItem(1); + Task actualStub = test.unmarkItem(1); + Task expectedStub = new UnmarkedTaskStub(); + assertEquals(actualStub, expectedStub); + } + + @Test + void deleteItem_giving_empty_list() { + TaskList test = new TaskList(); + Task stub = new TaskStub(); + test.addTask(stub); + test.deleteItem(1); + + String expected = "\t " + "Here are the tasks in your list:" + "\n"; + assertEquals(expected, test.toString()); + } + + @Test + void getTaskCount_when_list_is_empty() { + TaskList test = new TaskList(); + assertEquals(test.getTaskCount(), 0); + } + + @Test + void getTaskCount_when_list_has_one_task() { + TaskList test = new TaskList(); + Task stub = new TaskStub(); + test.addTask(stub); + assertEquals(test.getTaskCount(), 1); + } +} \ No newline at end of file From 090246c32877cf12223efa8cd419674a519ac7f2 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Fri, 26 Aug 2022 23:45:27 +0800 Subject: [PATCH 43/73] Add unit tests for Task subclasses --- src/test/java/task/DeadlineTest.java | 36 +++++++++++++++++++ src/test/java/task/EventTest.java | 35 +++++++++++++++++++ src/test/java/task/TodoTest.java | 52 ++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 src/test/java/task/DeadlineTest.java create mode 100644 src/test/java/task/EventTest.java create mode 100644 src/test/java/task/TodoTest.java diff --git a/src/test/java/task/DeadlineTest.java b/src/test/java/task/DeadlineTest.java new file mode 100644 index 0000000000..dd3d0c7488 --- /dev/null +++ b/src/test/java/task/DeadlineTest.java @@ -0,0 +1,36 @@ +package task; + +import date.DeadlineDateTime; +import date.EventDateTime; +import exception.DukeException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class DeadlineTest { + + @Test + void testToString_for_unmarked_deadline() throws DukeException { + DeadlineDateTime date = DeadlineDateTime.parseDate("2022-01-01 00:00:00"); + Deadline test = new Deadline("Testing!", date); + String expected = "[D][ ] Testing! (by: Jan 1 2022 00:00:00)"; + assertEquals(expected, test.toString()); + } + + @Test + void testToString_for_marked_deadline() throws DukeException { + DeadlineDateTime date = DeadlineDateTime.parseDate("2022-01-01 00:00:00"); + Deadline test = new Deadline("Testing!", date); + test.setIsMarked(true); + String expected = "[D][X] Testing! (by: Jan 1 2022 00:00:00)"; + assertEquals(expected, test.toString()); + } + + @Test + void encode() throws DukeException { + DeadlineDateTime date = DeadlineDateTime.parseDate("2022-01-01 00:00:00"); + Deadline test = new Deadline("Testing!", date); + String expected = "D,0,Testing!,2022-01-01|00:00:00\n"; + assertEquals(expected, test.encode()); + } +} \ No newline at end of file diff --git a/src/test/java/task/EventTest.java b/src/test/java/task/EventTest.java new file mode 100644 index 0000000000..e27deed5cb --- /dev/null +++ b/src/test/java/task/EventTest.java @@ -0,0 +1,35 @@ +package task; + +import date.EventDateTime; +import exception.DukeException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class EventTest { + + @Test + void testToString_for_unmarked_event() throws DukeException { + EventDateTime date = EventDateTime.parseDate("2022-01-01 00:00:00 12:00:00"); + Event test = new Event("Testing!", date); + String expected = "[E][ ] Testing! (at: Jan 1 2022 00:00:00 - 12:00:00)"; + assertEquals(expected, test.toString()); + } + + @Test + void testToString_for_marked_event() throws DukeException { + EventDateTime date = EventDateTime.parseDate("2022-01-01 00:00:00 12:00:00"); + Event test = new Event("Testing!", date); + test.setIsMarked(true); + String expected = "[E][X] Testing! (at: Jan 1 2022 00:00:00 - 12:00:00)"; + assertEquals(expected, test.toString()); + } + + @Test + void encode() throws DukeException { + EventDateTime date = EventDateTime.parseDate("2022-01-01 00:00:00 12:00:00"); + Event test = new Event("Testing!", date); + String expected = "E,0,Testing!,2022-01-01|00:00:00|12:00:00\n"; + assertEquals(expected, test.encode()); + } +} \ No newline at end of file diff --git a/src/test/java/task/TodoTest.java b/src/test/java/task/TodoTest.java new file mode 100644 index 0000000000..05ccf2de16 --- /dev/null +++ b/src/test/java/task/TodoTest.java @@ -0,0 +1,52 @@ +package task; + +import exception.DukeException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class TodoTest { + + @Test + void testToString_for_unmarked_todo() { + Todo test = new Todo("Testing!"); + String expected = "[T][ ] Testing!"; + assertEquals(expected, test.toString()); + } + + @Test + void validateInput_throws_exception_when_input_length_less_than_two() { + String[] inputLengthLessThanOne = new String[] { + "Testing!" + }; + assertThrows( + DukeException.class, + () -> Todo.validateInput(inputLengthLessThanOne)); + } + + @Test + void validateInput_throws_exception_when_second_string_is_whitespace() { + String[] secondStringIsWhitespace = new String[] { + "Testing!", + " ", + }; + assertThrows( + DukeException.class, + () -> Todo.validateInput(secondStringIsWhitespace)); + } + + @Test + void encode_unmarked_todo() { + Todo test = new Todo("Testing!"); + String expected = "T,0,Testing!\n"; + assertEquals(expected, test.encode()); + } + + @Test + void encode_marked_todo() { + Todo test = new Todo("Testing!"); + test.setIsMarked(true); + String expected = "T,1,Testing!\n"; + assertEquals(expected, test.encode()); + } +} \ No newline at end of file From ad95c7642542d849a43b1d875ccd8dd7c1615fa5 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Sat, 27 Aug 2022 00:31:05 +0800 Subject: [PATCH 44/73] Update build.gradle on main class classname --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 885198fcfa..0bdc254568 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ test { } application { - mainClassName = "seedu.duke.Duke" + mainClassName = "duke.Duke" } shadowJar { From 5c28d8e59810e254516ce88f58738d61962640cc Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Sat, 27 Aug 2022 00:31:30 +0800 Subject: [PATCH 45/73] Remove unnecessary println statement --- src/main/java/date/EventDateTime.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/date/EventDateTime.java b/src/main/java/date/EventDateTime.java index fb7f0f5a61..bb468fdb80 100644 --- a/src/main/java/date/EventDateTime.java +++ b/src/main/java/date/EventDateTime.java @@ -22,7 +22,6 @@ public static EventDateTime parseDate(String dateTime) throws DukeException { splitted[0].strip().equals("") || splitted[1].strip().equals("") || splitted[2].strip().equals("")) { - System.out.println("length error"); throw new DukeException(DukeException.ErrorCode.INVALID_EVENT_DATETIME_FORMAT); } try { From 42eaf497b0475e0a59627ceb09673f4329013427 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Sat, 27 Aug 2022 00:32:04 +0800 Subject: [PATCH 46/73] Remove symbol from error messages --- src/main/java/exception/DukeException.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/exception/DukeException.java b/src/main/java/exception/DukeException.java index 7fe866cf3c..8b115c7dd6 100644 --- a/src/main/java/exception/DukeException.java +++ b/src/main/java/exception/DukeException.java @@ -11,25 +11,25 @@ public String errorMessage() { String errorMsg; switch(errorCode) { case UNKNOWN_CMD: - errorMsg = "☹ OOPS!!! I'm sorry, but I don't know what that means :-("; + errorMsg = "OOPS!!! I'm sorry, but I don't know what that means :-("; break; case MISSING_TODO_ITEM: - errorMsg = "☹ OOPS!!! The description of a todo cannot be empty."; + errorMsg = "OOPS!!! The description of a todo cannot be empty."; break; case UNKNOWN_TASK_ENCODING: - errorMsg = "☹ OOPS!!! Unable to parse one of the saved tasks. This task will be skipped."; + errorMsg = "OOPS!!! Unable to parse one of the saved tasks. This task will be skipped."; case INVALID_DEADLINE_DATETIME_FORMAT: String dateFormat = "\t Please ensure date time is of the " + "following format: yyyy-mm-dd hh:mm:ss"; - errorMsg = "☹ OOPS!!! Unable to parse date time for deadline.\n" + dateFormat; + errorMsg = "OOPS!!! Unable to parse date time for deadline.\n" + dateFormat; break; case INVALID_EVENT_DATETIME_FORMAT: dateFormat = "\t Please ensure date time is of the " + "following format: yyyy-mm-dd hh:mm:ss hh:mm:ss hh:mm:ss"; - errorMsg = "☹ OOPS!!! Unable to parse date time for event.\n" + dateFormat; + errorMsg = "OOPS!!! Unable to parse date time for event.\n" + dateFormat; break; default: - errorMsg = "☹ OOPS!!! Unknown duke error occurred. :-("; + errorMsg = "OOPS!!! Unknown duke error occurred. :-("; } return errorMsg; } From 4274021a0dd54b0612c02d91101d5fb122b1cd78 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Sat, 27 Aug 2022 00:50:52 +0800 Subject: [PATCH 47/73] Add find functionality to TaskList --- src/main/java/tasklist/TaskList.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/tasklist/TaskList.java b/src/main/java/tasklist/TaskList.java index 8fff9bbf52..2e0f941354 100644 --- a/src/main/java/tasklist/TaskList.java +++ b/src/main/java/tasklist/TaskList.java @@ -47,4 +47,21 @@ public Task getItem(int index) { public int getTaskCount() { return this.list.size(); } + + public ArrayList find(String searchText) { + ArrayList res = new ArrayList<>(); + + if (searchText.strip().equals("")) { + return res; + } + + for (int i = 0; i < list.size(); i++) { + Task t = list.get(i); + if (t.toString().contains(searchText)) { + String searchedResult = String.format("%d.%s", i + 1, t.toString()); + res.add(searchedResult); + } + } + return res; + } } \ No newline at end of file From 5c0c0f405bfb27cf21de5688c4818d3ba3cf934b Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Sat, 27 Aug 2022 00:51:22 +0800 Subject: [PATCH 48/73] Add find command --- .../java/command/FindSearchTextCommand.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/main/java/command/FindSearchTextCommand.java diff --git a/src/main/java/command/FindSearchTextCommand.java b/src/main/java/command/FindSearchTextCommand.java new file mode 100644 index 0000000000..a09e564b76 --- /dev/null +++ b/src/main/java/command/FindSearchTextCommand.java @@ -0,0 +1,33 @@ +package command; + +import tasklist.TaskList; +import util.Storage; +import util.Ui; + +import java.util.ArrayList; + +public class FindSearchTextCommand extends Command { + private final String searchText; + + public FindSearchTextCommand(String searchText) { + this.searchText = searchText; + } + + @Override + public void execute(TaskList list, Storage storage) { + ArrayList matchedTasks = list.find(searchText); + + if (matchedTasks.size() == 0) { + System.out.println(Ui.formatLinesIntoParagraph( + "Sorry but there is no matching task in the list!" + )); + return; + } + + String res = ""; + for (String match : matchedTasks) { + res += Ui.formatLine(match); + } + System.out.println(Ui.formatParagraph(res)); + } +} From 28568987b991dfb976e1bc70194250e72db259d4 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Sat, 27 Aug 2022 00:51:37 +0800 Subject: [PATCH 49/73] Update Parse to parse find command --- src/main/java/util/Parser.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/util/Parser.java b/src/main/java/util/Parser.java index 2d31e649e1..e1e789fe3b 100644 --- a/src/main/java/util/Parser.java +++ b/src/main/java/util/Parser.java @@ -54,6 +54,10 @@ public static Command parseInputLine(String inputLine) throws DukeException { Task event = new Event(taskArgs[0], eventDateTime); cmd = new AddTaskCommand(event); break; + case "find": + String searchText = splitted[1]; + cmd = new FindSearchTextCommand(searchText); + break; default: throw new DukeException(DukeException.ErrorCode.UNKNOWN_CMD); } From dad6c94785aadcfc3e06fd0578b1fb87e382f0ec Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Sat, 27 Aug 2022 14:56:59 +0800 Subject: [PATCH 50/73] Set up checkstyle with Gradle --- build.gradle | 5 + config/checkstyle/checkstyle.xml | 434 +++++++++++++++++++++++++++++ config/checkstyle/suppressions.xml | 10 + 3 files changed, 449 insertions(+) create mode 100644 config/checkstyle/checkstyle.xml create mode 100644 config/checkstyle/suppressions.xml diff --git a/build.gradle b/build.gradle index 0bdc254568..19f97fd7b6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ plugins { id 'java' id 'application' + id 'checkstyle' id 'com.github.johnrengelman.shadow' version '5.1.0' } @@ -39,3 +40,7 @@ shadowJar { run{ standardInput = System.in } + +checkstyle { + toolVersion = '10.2' +} diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml new file mode 100644 index 0000000000..fb88cedfc2 --- /dev/null +++ b/config/checkstyle/checkstyle.xml @@ -0,0 +1,434 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 From c5739eab403ac63b2491fcad2ccb3bad6df2078c Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Sat, 27 Aug 2022 15:21:13 +0800 Subject: [PATCH 51/73] Fix coding style violations --- src/main/java/command/AddTaskCommand.java | 1 + .../command/AddTaskFromStorageCommand.java | 1 + src/main/java/command/Command.java | 11 +- src/main/java/command/MarkTaskCommand.java | 1 + src/main/java/command/TerminateCommand.java | 4 +- src/main/java/command/UnmarkTaskCommand.java | 2 +- src/main/java/date/DeadlineDateTime.java | 5 +- src/main/java/date/EventDateTime.java | 12 +- src/main/java/duke/Duke.java | 9 +- src/main/java/exception/DukeException.java | 43 +++---- src/main/java/task/Event.java | 4 +- src/main/java/task/Task.java | 10 +- src/main/java/tasklist/TaskList.java | 6 +- src/main/java/util/Parser.java | 117 ++++++++++-------- src/main/java/util/Storage.java | 11 +- src/main/java/util/Ui.java | 4 +- src/test/java/task/DeadlineTest.java | 8 +- src/test/java/task/EventTest.java | 7 +- src/test/java/task/TodoTest.java | 6 +- src/test/java/task/stub/UnmarkedTaskStub.java | 2 - src/test/java/tasklist/TaskListTest.java | 9 +- 21 files changed, 150 insertions(+), 123 deletions(-) diff --git a/src/main/java/command/AddTaskCommand.java b/src/main/java/command/AddTaskCommand.java index 08a7e9bd22..4e818a5443 100644 --- a/src/main/java/command/AddTaskCommand.java +++ b/src/main/java/command/AddTaskCommand.java @@ -7,6 +7,7 @@ public class AddTaskCommand extends Command { private final Task taskItem; + public AddTaskCommand(Task taskItem) { this.taskItem = taskItem; } diff --git a/src/main/java/command/AddTaskFromStorageCommand.java b/src/main/java/command/AddTaskFromStorageCommand.java index fadc8637d9..abc12479ec 100644 --- a/src/main/java/command/AddTaskFromStorageCommand.java +++ b/src/main/java/command/AddTaskFromStorageCommand.java @@ -6,6 +6,7 @@ public class AddTaskFromStorageCommand extends Command { private final Task taskItem; + public AddTaskFromStorageCommand(Task taskItem) { this.taskItem = taskItem; } diff --git a/src/main/java/command/Command.java b/src/main/java/command/Command.java index 9f1e0f92ac..d6a19fc541 100644 --- a/src/main/java/command/Command.java +++ b/src/main/java/command/Command.java @@ -4,6 +4,15 @@ import util.Storage; public abstract class Command { - public boolean isTerminated = false; + private boolean isTerminated = false; + public abstract void execute(TaskList list, Storage storage); + + public boolean getIsTerminated() { + return isTerminated; + } + + public void setIsTerminated(boolean isTerminated) { + this.isTerminated = isTerminated; + } } diff --git a/src/main/java/command/MarkTaskCommand.java b/src/main/java/command/MarkTaskCommand.java index 07efb8d5b1..1fd6f0f5db 100644 --- a/src/main/java/command/MarkTaskCommand.java +++ b/src/main/java/command/MarkTaskCommand.java @@ -6,6 +6,7 @@ public class MarkTaskCommand extends Command { private final int index; + public MarkTaskCommand(int index) { this.index = index; } diff --git a/src/main/java/command/TerminateCommand.java b/src/main/java/command/TerminateCommand.java index 7dc69eb29e..da537cf1e9 100644 --- a/src/main/java/command/TerminateCommand.java +++ b/src/main/java/command/TerminateCommand.java @@ -3,10 +3,10 @@ import tasklist.TaskList; import util.Storage; -public class TerminateCommand extends Command{ +public class TerminateCommand extends Command { @Override public void execute(TaskList list, Storage storage) { - isTerminated = true; + setIsTerminated(true); storage.saveAllTasks(list); } } diff --git a/src/main/java/command/UnmarkTaskCommand.java b/src/main/java/command/UnmarkTaskCommand.java index 0f326c824a..02789004e0 100644 --- a/src/main/java/command/UnmarkTaskCommand.java +++ b/src/main/java/command/UnmarkTaskCommand.java @@ -4,7 +4,7 @@ import util.Storage; import util.Ui; -public class UnmarkTaskCommand extends Command{ +public class UnmarkTaskCommand extends Command { private final int index; public UnmarkTaskCommand(int index) { diff --git a/src/main/java/date/DeadlineDateTime.java b/src/main/java/date/DeadlineDateTime.java index 42090b885c..7b4bf272a1 100644 --- a/src/main/java/date/DeadlineDateTime.java +++ b/src/main/java/date/DeadlineDateTime.java @@ -1,12 +1,11 @@ package date; -import exception.DukeException; -import util.Ui; - import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import exception.DukeException; + public class DeadlineDateTime extends Date { private LocalTime time; diff --git a/src/main/java/date/EventDateTime.java b/src/main/java/date/EventDateTime.java index bb468fdb80..87dcefd615 100644 --- a/src/main/java/date/EventDateTime.java +++ b/src/main/java/date/EventDateTime.java @@ -1,11 +1,11 @@ package date; -import exception.DukeException; - import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import exception.DukeException; + public class EventDateTime extends Date { private LocalTime startTime; private LocalTime endTime; @@ -18,10 +18,10 @@ private EventDateTime(String date, String startTime, String endTime) throws Date public static EventDateTime parseDate(String dateTime) throws DukeException { String[] splitted = dateTime.split("\\s+", 3); - if (splitted.length < 3 || - splitted[0].strip().equals("") || - splitted[1].strip().equals("") || - splitted[2].strip().equals("")) { + if (splitted.length < 3 + || splitted[0].strip().equals("") + || splitted[1].strip().equals("") + || splitted[2].strip().equals("")) { throw new DukeException(DukeException.ErrorCode.INVALID_EVENT_DATETIME_FORMAT); } try { diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java index 6c4e07a513..46537f862d 100644 --- a/src/main/java/duke/Duke.java +++ b/src/main/java/duke/Duke.java @@ -1,5 +1,7 @@ package duke; +import java.util.Scanner; + import command.Command; import exception.DukeException; import tasklist.TaskList; @@ -7,8 +9,6 @@ import util.Storage; import util.Ui; -import java.util.Scanner; - public class Duke { private TaskList dukelist = new TaskList(); private Storage storage; @@ -23,17 +23,18 @@ public void run() { boolean isTerminated = false; Scanner sc = new Scanner(System.in); - while(!isTerminated) { + while (!isTerminated) { try { String nextLine = sc.nextLine(); Command cmd = Parser.parseInputLine(nextLine); cmd.execute(dukelist, storage); - isTerminated = cmd.isTerminated; + isTerminated = cmd.getIsTerminated(); } catch (DukeException e) { System.out.println(Ui.formatLinesIntoParagraph(e.errorMessage())); } } } + public static void main(String[] args) { new Duke("data/saveFile.txt").run(); } diff --git a/src/main/java/exception/DukeException.java b/src/main/java/exception/DukeException.java index 8b115c7dd6..db905dca0e 100644 --- a/src/main/java/exception/DukeException.java +++ b/src/main/java/exception/DukeException.java @@ -9,27 +9,28 @@ public DukeException(ErrorCode errorCode) { public String errorMessage() { String errorMsg; - switch(errorCode) { - case UNKNOWN_CMD: - errorMsg = "OOPS!!! I'm sorry, but I don't know what that means :-("; - break; - case MISSING_TODO_ITEM: - errorMsg = "OOPS!!! The description of a todo cannot be empty."; - break; - case UNKNOWN_TASK_ENCODING: - errorMsg = "OOPS!!! Unable to parse one of the saved tasks. This task will be skipped."; - case INVALID_DEADLINE_DATETIME_FORMAT: - String dateFormat = "\t Please ensure date time is of the " + - "following format: yyyy-mm-dd hh:mm:ss"; - errorMsg = "OOPS!!! Unable to parse date time for deadline.\n" + dateFormat; - break; - case INVALID_EVENT_DATETIME_FORMAT: - dateFormat = "\t Please ensure date time is of the " + - "following format: yyyy-mm-dd hh:mm:ss hh:mm:ss hh:mm:ss"; - errorMsg = "OOPS!!! Unable to parse date time for event.\n" + dateFormat; - break; - default: - errorMsg = "OOPS!!! Unknown duke error occurred. :-("; + switch (errorCode) { + case UNKNOWN_CMD: + errorMsg = "OOPS!!! I'm sorry, but I don't know what that means :-("; + break; + case MISSING_TODO_ITEM: + errorMsg = "OOPS!!! The description of a todo cannot be empty."; + break; + case UNKNOWN_TASK_ENCODING: + errorMsg = "OOPS!!! Unable to parse one of the saved tasks. This task will be skipped."; + break; + case INVALID_DEADLINE_DATETIME_FORMAT: + String dateFormat = "\t Please ensure date time is of the " + + "following format: yyyy-mm-dd hh:mm:ss"; + errorMsg = "OOPS!!! Unable to parse date time for deadline.\n" + dateFormat; + break; + case INVALID_EVENT_DATETIME_FORMAT: + dateFormat = "\t Please ensure date time is of the " + + "following format: yyyy-mm-dd hh:mm:ss hh:mm:ss hh:mm:ss"; + errorMsg = "OOPS!!! Unable to parse date time for event.\n" + dateFormat; + break; + default: + errorMsg = "OOPS!!! Unknown duke error occurred. :-("; } return errorMsg; } diff --git a/src/main/java/task/Event.java b/src/main/java/task/Event.java index 732b4dbefd..c165b1eb9a 100644 --- a/src/main/java/task/Event.java +++ b/src/main/java/task/Event.java @@ -2,9 +2,9 @@ import date.EventDateTime; -public class Event extends Task{ +public class Event extends Task { private final EventDateTime eventTiming; - + public Event(String taskItem, EventDateTime eventTiming) { super(taskItem); this.eventTiming = eventTiming; diff --git a/src/main/java/task/Task.java b/src/main/java/task/Task.java index a75012d9a4..96c4614e5a 100644 --- a/src/main/java/task/Task.java +++ b/src/main/java/task/Task.java @@ -1,18 +1,18 @@ package task; public abstract class Task { - private final String TaskItem; + private final String taskItem; private boolean isMarked; - public Task(String TaskItem) { - this.TaskItem = TaskItem; + public Task(String taskItem) { + this.taskItem = taskItem; this.isMarked = false; } @Override public String toString() { String checkbox = isMarked ? "[X] " : "[ ] "; - return checkbox + this.TaskItem; + return checkbox + this.taskItem; } public void setIsMarked(boolean status) { @@ -24,7 +24,7 @@ protected boolean getIsMarked() { } protected String getTaskItem() { - return TaskItem; + return taskItem; } public abstract String encode(); diff --git a/src/main/java/tasklist/TaskList.java b/src/main/java/tasklist/TaskList.java index 8fff9bbf52..b54b85a1cb 100644 --- a/src/main/java/tasklist/TaskList.java +++ b/src/main/java/tasklist/TaskList.java @@ -1,8 +1,10 @@ package tasklist; +import java.util.ArrayList; + import task.Task; import util.Ui; -import java.util.ArrayList; + public class TaskList { private final ArrayList list = new ArrayList<>(); @@ -47,4 +49,4 @@ public Task getItem(int index) { public int getTaskCount() { return this.list.size(); } -} \ No newline at end of file +} diff --git a/src/main/java/util/Parser.java b/src/main/java/util/Parser.java index 2d31e649e1..9d5576d6bf 100644 --- a/src/main/java/util/Parser.java +++ b/src/main/java/util/Parser.java @@ -1,6 +1,13 @@ package util; -import command.*; +import command.AddTaskCommand; +import command.AddTaskFromStorageCommand; +import command.Command; +import command.DeleteTaskCommand; +import command.ListAllTasksCommand; +import command.MarkTaskCommand; +import command.TerminateCommand; +import command.UnmarkTaskCommand; import date.DeadlineDateTime; import date.EventDateTime; import exception.DukeException; @@ -15,47 +22,47 @@ public static Command parseInputLine(String inputLine) throws DukeException { String command = splitted[0]; Command cmd; switch (command) { - case "bye": - cmd = new TerminateCommand(); - break; - case "list": - cmd = new ListAllTasksCommand(); - break; - case "mark": - int index = Integer.parseInt(splitted[1]); - cmd = new MarkTaskCommand(index); - break; - case "unmark": - index = Integer.parseInt(splitted[1]); - cmd = new UnmarkTaskCommand(index); - break; - case "delete": - index = Integer.parseInt(splitted[1]); - cmd = new DeleteTaskCommand(index); - break; - case "todo": - Todo.validateInput(splitted); - Task todo = new Todo(splitted[1]); - cmd = new AddTaskCommand(todo); - break; - case "deadline": - // Regex "\\s+/" matches one or more space followed by a /by, - // followed by one or more space - String[] taskArgs = splitted[1].split("\\s+/by\\s+",2); - DeadlineDateTime deadlineDateTime = DeadlineDateTime.parseDate(taskArgs[1]); - Task deadline = new Deadline(taskArgs[0], deadlineDateTime); - cmd = new AddTaskCommand(deadline); - break; - case "event": - // Regex "\s+/at\s+" matches one or more space followed by a /at, - // followed by one or more space - taskArgs = splitted[1].split("\\s+/at\\s+",2); - EventDateTime eventDateTime = EventDateTime.parseDate(taskArgs[1]); - Task event = new Event(taskArgs[0], eventDateTime); - cmd = new AddTaskCommand(event); - break; - default: - throw new DukeException(DukeException.ErrorCode.UNKNOWN_CMD); + case "bye": + cmd = new TerminateCommand(); + break; + case "list": + cmd = new ListAllTasksCommand(); + break; + case "mark": + int index = Integer.parseInt(splitted[1]); + cmd = new MarkTaskCommand(index); + break; + case "unmark": + index = Integer.parseInt(splitted[1]); + cmd = new UnmarkTaskCommand(index); + break; + case "delete": + index = Integer.parseInt(splitted[1]); + cmd = new DeleteTaskCommand(index); + break; + case "todo": + Todo.validateInput(splitted); + Task todo = new Todo(splitted[1]); + cmd = new AddTaskCommand(todo); + break; + case "deadline": + // Regex "\\s+/" matches one or more space followed by a /by, + // followed by one or more space + String[] taskArgs = splitted[1].split("\\s+/by\\s+", 2); + DeadlineDateTime deadlineDateTime = DeadlineDateTime.parseDate(taskArgs[1]); + Task deadline = new Deadline(taskArgs[0], deadlineDateTime); + cmd = new AddTaskCommand(deadline); + break; + case "event": + // Regex "\s+/at\s+" matches one or more space followed by a /at, + // followed by one or more space + taskArgs = splitted[1].split("\\s+/at\\s+", 2); + EventDateTime eventDateTime = EventDateTime.parseDate(taskArgs[1]); + Task event = new Event(taskArgs[0], eventDateTime); + cmd = new AddTaskCommand(event); + break; + default: + throw new DukeException(DukeException.ErrorCode.UNKNOWN_CMD); } return cmd; } @@ -66,19 +73,19 @@ public static Command parseEncodedTask(String encodedTask) throws DukeException Task taskItem; switch (taskType) { - case "T": - taskItem = new Todo(splitted[2]); - break; - case "E": - EventDateTime eventDateTime = EventDateTime.parseDateFromStorage(splitted[3]); - taskItem = new Event(splitted[2], eventDateTime); - break; - case "D": - DeadlineDateTime deadlineDateTime = DeadlineDateTime.parseDateFromStorage(splitted[3]); - taskItem = new Deadline(splitted[2], deadlineDateTime); - break; - default: - throw new DukeException(DukeException.ErrorCode.UNKNOWN_TASK_ENCODING); + case "T": + taskItem = new Todo(splitted[2]); + break; + case "E": + EventDateTime eventDateTime = EventDateTime.parseDateFromStorage(splitted[3]); + taskItem = new Event(splitted[2], eventDateTime); + break; + case "D": + DeadlineDateTime deadlineDateTime = DeadlineDateTime.parseDateFromStorage(splitted[3]); + taskItem = new Deadline(splitted[2], deadlineDateTime); + break; + default: + throw new DukeException(DukeException.ErrorCode.UNKNOWN_TASK_ENCODING); } taskItem.setIsMarked(splitted[1].equals("1")); return new AddTaskFromStorageCommand(taskItem); diff --git a/src/main/java/util/Storage.java b/src/main/java/util/Storage.java index a65108ed10..905f896c81 100644 --- a/src/main/java/util/Storage.java +++ b/src/main/java/util/Storage.java @@ -1,18 +1,19 @@ package util; -import command.Command; -import exception.DukeException; -import task.Task; -import tasklist.TaskList; - import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.util.Scanner; +import command.Command; +import exception.DukeException; +import task.Task; +import tasklist.TaskList; + public class Storage { private final File saveFile; + private Storage(File saveFile) { this.saveFile = saveFile; } diff --git a/src/main/java/util/Ui.java b/src/main/java/util/Ui.java index 3330f510ad..0bfea57f27 100644 --- a/src/main/java/util/Ui.java +++ b/src/main/java/util/Ui.java @@ -20,8 +20,8 @@ public static String formatLinesIntoParagraph(String... lines) { } public static void printIntroMessage() { - String introParagraph = Ui.formatLine("Hello! I'm duke.") + - Ui.formatLine("What can I do for you?"); + String introParagraph = Ui.formatLine("Hello! I'm duke.") + + Ui.formatLine("What can I do for you?"); String formattedIntro = Ui.formatParagraph(introParagraph); System.out.println(formattedIntro); diff --git a/src/test/java/task/DeadlineTest.java b/src/test/java/task/DeadlineTest.java index dd3d0c7488..cec9328acb 100644 --- a/src/test/java/task/DeadlineTest.java +++ b/src/test/java/task/DeadlineTest.java @@ -1,11 +1,11 @@ package task; -import date.DeadlineDateTime; -import date.EventDateTime; -import exception.DukeException; +import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import date.DeadlineDateTime; +import exception.DukeException; class DeadlineTest { diff --git a/src/test/java/task/EventTest.java b/src/test/java/task/EventTest.java index e27deed5cb..5991eccc93 100644 --- a/src/test/java/task/EventTest.java +++ b/src/test/java/task/EventTest.java @@ -1,10 +1,11 @@ package task; -import date.EventDateTime; -import exception.DukeException; +import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import date.EventDateTime; +import exception.DukeException; class EventTest { diff --git a/src/test/java/task/TodoTest.java b/src/test/java/task/TodoTest.java index 05ccf2de16..7440de2a35 100644 --- a/src/test/java/task/TodoTest.java +++ b/src/test/java/task/TodoTest.java @@ -1,9 +1,11 @@ package task; -import exception.DukeException; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import exception.DukeException; class TodoTest { diff --git a/src/test/java/task/stub/UnmarkedTaskStub.java b/src/test/java/task/stub/UnmarkedTaskStub.java index 015a913ae3..506ebef7ef 100644 --- a/src/test/java/task/stub/UnmarkedTaskStub.java +++ b/src/test/java/task/stub/UnmarkedTaskStub.java @@ -1,7 +1,5 @@ package task.stub; -import task.stub.TaskStub; - public class UnmarkedTaskStub extends TaskStub { @Override protected boolean getIsMarked() { diff --git a/src/test/java/tasklist/TaskListTest.java b/src/test/java/tasklist/TaskListTest.java index 2e75967200..a29fbcf87a 100644 --- a/src/test/java/tasklist/TaskListTest.java +++ b/src/test/java/tasklist/TaskListTest.java @@ -1,13 +1,16 @@ package tasklist; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; + import org.junit.jupiter.api.Test; -import task.stub.MarkedTaskStub; + import task.Task; +import task.stub.MarkedTaskStub; import task.stub.TaskStub; import task.stub.UnmarkedTaskStub; -import static org.junit.jupiter.api.Assertions.*; - class TaskListTest { @Test From 7e0f0c2ede2fc18a7335c9f6698553568f6e4d98 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Sat, 27 Aug 2022 16:18:06 +0800 Subject: [PATCH 52/73] Add javadocs Note that this branch is done after the A-CodingStandards when auto format on save in intelliJ was set up so there might be some files that were formatted as well. --- src/main/java/command/AddTaskCommand.java | 12 ++ .../command/AddTaskFromStorageCommand.java | 12 ++ src/main/java/command/Command.java | 13 ++ src/main/java/command/DeleteTaskCommand.java | 13 ++ .../java/command/ListAllTasksCommand.java | 9 ++ src/main/java/command/MarkTaskCommand.java | 12 ++ src/main/java/command/TerminateCommand.java | 10 +- src/main/java/command/UnmarkTaskCommand.java | 15 +- src/main/java/date/Date.java | 13 ++ src/main/java/date/DeadlineDateTime.java | 26 ++++ src/main/java/date/EventDateTime.java | 26 ++++ src/main/java/duke/Duke.java | 14 +- src/main/java/exception/DukeException.java | 57 +++++--- src/main/java/task/Deadline.java | 16 +++ src/main/java/task/Event.java | 20 ++- src/main/java/task/Task.java | 17 +++ src/main/java/task/Todo.java | 21 +++ src/main/java/tasklist/TaskList.java | 37 +++++ src/main/java/util/Parser.java | 129 ++++++++++-------- src/main/java/util/Storage.java | 22 +++ src/main/java/util/Ui.java | 26 ++++ src/test/java/task/DeadlineTest.java | 5 +- src/test/java/task/EventTest.java | 4 + src/test/java/task/TodoTest.java | 6 + src/test/java/task/stub/MarkedTaskStub.java | 10 ++ src/test/java/task/stub/TaskStub.java | 15 ++ src/test/java/task/stub/UnmarkedTaskStub.java | 12 +- src/test/java/tasklist/TaskListTest.java | 9 ++ 28 files changed, 498 insertions(+), 83 deletions(-) diff --git a/src/main/java/command/AddTaskCommand.java b/src/main/java/command/AddTaskCommand.java index 08a7e9bd22..9f86839530 100644 --- a/src/main/java/command/AddTaskCommand.java +++ b/src/main/java/command/AddTaskCommand.java @@ -5,12 +5,24 @@ import util.Storage; import util.Ui; +/** + * Represents a command to be executed that adds a task to the internal duke list. + * + * @author Bryan Lim Jing Xiang + */ public class AddTaskCommand extends Command { private final Task taskItem; + + /** + * @param taskItem Task to be added to duke list + */ public AddTaskCommand(Task taskItem) { this.taskItem = taskItem; } + /** + * {@inheritDoc} + */ @Override public void execute(TaskList list, Storage storage) { String task = " " + list.addTask(this.taskItem); diff --git a/src/main/java/command/AddTaskFromStorageCommand.java b/src/main/java/command/AddTaskFromStorageCommand.java index fadc8637d9..5987ab4264 100644 --- a/src/main/java/command/AddTaskFromStorageCommand.java +++ b/src/main/java/command/AddTaskFromStorageCommand.java @@ -4,12 +4,24 @@ import tasklist.TaskList; import util.Storage; +/** + * Represents a command to be executed that adds a task based on input from save file. + * + * @author Bryan Lim Jing Xiang + */ public class AddTaskFromStorageCommand extends Command { private final Task taskItem; + + /** + * @param taskItem Task to be added to internal duke list + */ public AddTaskFromStorageCommand(Task taskItem) { this.taskItem = taskItem; } + /** + * {@inheritDoc} + */ @Override public void execute(TaskList list, Storage storage) { list.addTask(this.taskItem); diff --git a/src/main/java/command/Command.java b/src/main/java/command/Command.java index 9f1e0f92ac..a4c69c2de1 100644 --- a/src/main/java/command/Command.java +++ b/src/main/java/command/Command.java @@ -3,7 +3,20 @@ import tasklist.TaskList; import util.Storage; +/** + * Represents a command generated from the internal save file or input from the + * command line. + * + * @author Bryan Lim Jing Xiang + */ public abstract class Command { public boolean isTerminated = false; + + /** + * Executes a specific command + * + * @param list Duke list that stores all current tasks + * @param storage Storage that handles all storage related functionalities + */ public abstract void execute(TaskList list, Storage storage); } diff --git a/src/main/java/command/DeleteTaskCommand.java b/src/main/java/command/DeleteTaskCommand.java index 4e7eb752b9..13ddf6177b 100644 --- a/src/main/java/command/DeleteTaskCommand.java +++ b/src/main/java/command/DeleteTaskCommand.java @@ -4,13 +4,26 @@ import util.Storage; import util.Ui; +/** + * Represents a task to be executed that deletes a specific task from internal + * duke list based on given index. + * + * @author Bryan Lim Jing Xiang + */ public class DeleteTaskCommand extends Command { private final int index; + /** + * @param index Index of the element to be deleted within the + * internal duke list + */ public DeleteTaskCommand(int index) { this.index = index; } + /** + * {@inheritDoc} + */ @Override public void execute(TaskList list, Storage storage) { String deletedItem = " " + list.deleteItem(index); diff --git a/src/main/java/command/ListAllTasksCommand.java b/src/main/java/command/ListAllTasksCommand.java index 699ec40cfc..7aa88b6e38 100644 --- a/src/main/java/command/ListAllTasksCommand.java +++ b/src/main/java/command/ListAllTasksCommand.java @@ -4,7 +4,16 @@ import util.Storage; import util.Ui; +/** + * Represents a command to be executed that lists all current tasks in the + * internal duke list. + * + * @author Bryan Lim Jing Xiang + */ public class ListAllTasksCommand extends Command { + /** + * {@inheritDoc} + */ @Override public void execute(TaskList list, Storage storage) { System.out.println(Ui.formatParagraph( diff --git a/src/main/java/command/MarkTaskCommand.java b/src/main/java/command/MarkTaskCommand.java index 07efb8d5b1..8dbf8ab9f4 100644 --- a/src/main/java/command/MarkTaskCommand.java +++ b/src/main/java/command/MarkTaskCommand.java @@ -4,12 +4,24 @@ import util.Storage; import util.Ui; +/** + * Represents a task to be executed that marks a specific task in the + * internal duke list based on given index + */ public class MarkTaskCommand extends Command { private final int index; + + /** + * @param index Index of the element to be marked within the + * internal duke list + */ public MarkTaskCommand(int index) { this.index = index; } + /** + * {@inheritDoc} + */ @Override public void execute(TaskList list, Storage storage) { String markedItem = " " + list.markItem(index); diff --git a/src/main/java/command/TerminateCommand.java b/src/main/java/command/TerminateCommand.java index 7dc69eb29e..d2bb925c07 100644 --- a/src/main/java/command/TerminateCommand.java +++ b/src/main/java/command/TerminateCommand.java @@ -3,7 +3,15 @@ import tasklist.TaskList; import util.Storage; -public class TerminateCommand extends Command{ +/** + * Represents a command that to be executed that terminates the program + * + * @author Bryan Lim Jing Xiang + */ +public class TerminateCommand extends Command { + /** + * {@inheritDoc} + */ @Override public void execute(TaskList list, Storage storage) { isTerminated = true; diff --git a/src/main/java/command/UnmarkTaskCommand.java b/src/main/java/command/UnmarkTaskCommand.java index 0f326c824a..58e36c8386 100644 --- a/src/main/java/command/UnmarkTaskCommand.java +++ b/src/main/java/command/UnmarkTaskCommand.java @@ -4,13 +4,26 @@ import util.Storage; import util.Ui; -public class UnmarkTaskCommand extends Command{ +/** + * Represents a task to be executed that unmarks a specific task within the + * internal duke list based on given index + * + * @author Bryan Lim Jing Xiang + */ +public class UnmarkTaskCommand extends Command { private final int index; + /** + * @param index Index of the element to be unmarked within the + * internal duke list + */ public UnmarkTaskCommand(int index) { this.index = index; } + /** + * {@inheritDoc} + */ @Override public void execute(TaskList list, Storage storage) { String unmarkedItem = " " + list.unmarkItem(index); diff --git a/src/main/java/date/Date.java b/src/main/java/date/Date.java index 510d64a0dc..2b33a05dda 100644 --- a/src/main/java/date/Date.java +++ b/src/main/java/date/Date.java @@ -4,6 +4,11 @@ import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +/** + * Stores a representation of Date based on ISO-8601 + * + * @author Bryan Lim Jing Xiang + */ public abstract class Date { private LocalDate date; @@ -11,11 +16,19 @@ public Date(String date) throws DateTimeParseException { this.date = LocalDate.parse(date); } + /** + * {@inheritDoc} + * + * @return Date formatted in terms of "month day year", e.g Jan 1 2000 + */ @Override public String toString() { return date.format(DateTimeFormatter.ofPattern("MMM d yyyy")); } + /** + * @return A string encoding of the stored date + */ public String encode() { return date.toString(); } diff --git a/src/main/java/date/DeadlineDateTime.java b/src/main/java/date/DeadlineDateTime.java index 42090b885c..7a4a4e6a24 100644 --- a/src/main/java/date/DeadlineDateTime.java +++ b/src/main/java/date/DeadlineDateTime.java @@ -7,6 +7,11 @@ import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +/** + * Stores a representation of a data and a time based on ISO-8601 + * + * @author Bryan Lim Jing Xiang + */ public class DeadlineDateTime extends Date { private LocalTime time; @@ -15,6 +20,14 @@ private DeadlineDateTime(String date, String time) throws DateTimeParseException this.time = LocalTime.parse(time); } + /** + * Parses a given string and returns an object storing the Date and Time given + * + * @param dateTime A string with a date and time as per ISO-8601 format, + * delimited by a space + * @return DeadlineDateTime object that stores the Date and Time passed in + * @throws DukeException If the dateTime passed in cannot be parsed + */ public static DeadlineDateTime parseDate(String dateTime) throws DukeException { String[] splitted = dateTime.split("\\s+", 2); if (splitted.length < 2 || splitted[0].strip().equals("") || splitted[1].strip().equals("")) { @@ -27,6 +40,13 @@ public static DeadlineDateTime parseDate(String dateTime) throws DukeException { } } + /** + * Parses date from encoded data in save file + * + * @param storedDateTime An encoding of DeadlineDateTime stored in the save file + * @return DeadlineDateTime object that stores the Date and Time + * @throws DukeException If the storedDateTime cannot be parsed + */ public static DeadlineDateTime parseDateFromStorage(String storedDateTime) throws DukeException { String[] dateTime = storedDateTime.split("\\|", 2); try { @@ -36,6 +56,9 @@ public static DeadlineDateTime parseDateFromStorage(String storedDateTime) throw } } + /** + * {@inheritDoc} + */ @Override public String toString() { String timeColonPattern = "HH:mm:ss"; @@ -43,6 +66,9 @@ public String toString() { return super.toString() + ' ' + formattedTime; } + /** + * {@inheritDoc} + */ @Override public String encode() { String timeColonPattern = "HH:mm:ss"; diff --git a/src/main/java/date/EventDateTime.java b/src/main/java/date/EventDateTime.java index bb468fdb80..546d8a62da 100644 --- a/src/main/java/date/EventDateTime.java +++ b/src/main/java/date/EventDateTime.java @@ -6,6 +6,11 @@ import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +/** + * Stores a representation of a data, start time and end time based on ISO-8601 + * + * @author Bryan Lim Jing Xiang + */ public class EventDateTime extends Date { private LocalTime startTime; private LocalTime endTime; @@ -16,6 +21,14 @@ private EventDateTime(String date, String startTime, String endTime) throws Date this.endTime = LocalTime.parse(endTime); } + /** + * Parses a given string and returns an object storing the Date and Time given + * + * @param dateTime A string with a date, start time and end time as per + * ISO-8601 format, delimited by a space + * @return EventDateTime object that stores the Date and Time passed in + * @throws DukeException If the dateTime passed in cannot be parsed + */ public static EventDateTime parseDate(String dateTime) throws DukeException { String[] splitted = dateTime.split("\\s+", 3); if (splitted.length < 3 || @@ -31,6 +44,13 @@ public static EventDateTime parseDate(String dateTime) throws DukeException { } } + /** + * Parses date from encoded data in save file + * + * @param storedDateTime An encoding of EventDateTime stored in the save file + * @return EventDateTime object that stores the Date and Time + * @throws DukeException If the storedDateTime cannot be parsed + */ public static EventDateTime parseDateFromStorage(String storedDateTime) throws DukeException { String[] dateTime = storedDateTime.split("\\|", 3); try { @@ -40,6 +60,9 @@ public static EventDateTime parseDateFromStorage(String storedDateTime) throws D } } + /** + * {@inheritDoc} + */ @Override public String toString() { String timeColonPattern = "HH:mm:ss"; @@ -48,6 +71,9 @@ public String toString() { return super.toString() + ' ' + formattedStartTime + " - " + formattedEndTime; } + /** + * {@inheritDoc} + */ @Override public String encode() { String timeColonPattern = "HH:mm:ss"; diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java index 6c4e07a513..0a8cc63939 100644 --- a/src/main/java/duke/Duke.java +++ b/src/main/java/duke/Duke.java @@ -9,21 +9,32 @@ import java.util.Scanner; +/** + * Entry point of the application that initialises and run the app. + * + * @author Bryan Lim Jing Xiang + */ public class Duke { private TaskList dukelist = new TaskList(); private Storage storage; + /** + * @param filePath File path of the internal save file + */ public Duke(String filePath) { storage = Storage.initialize(filePath); storage.load(dukelist); } + /** + * Initialises and runs the Duke application + */ public void run() { Ui.printIntroMessage(); boolean isTerminated = false; Scanner sc = new Scanner(System.in); - while(!isTerminated) { + while (!isTerminated) { try { String nextLine = sc.nextLine(); Command cmd = Parser.parseInputLine(nextLine); @@ -34,6 +45,7 @@ public void run() { } } } + public static void main(String[] args) { new Duke("data/saveFile.txt").run(); } diff --git a/src/main/java/exception/DukeException.java b/src/main/java/exception/DukeException.java index 8b115c7dd6..8ac23ac820 100644 --- a/src/main/java/exception/DukeException.java +++ b/src/main/java/exception/DukeException.java @@ -1,39 +1,54 @@ package exception; +/** + * Represents exceptions that occur from Duke operations. Uses an error code + * to represent and differentiate between different types of exception. + * + * @author Bryan Lim Jing Xiang + */ public class DukeException extends Exception { private final ErrorCode errorCode; + /** + * @param errorCode Represents the type of exception that occurred + */ public DukeException(ErrorCode errorCode) { this.errorCode = errorCode; } + /** + * @return Error message pertaining to the exception + */ public String errorMessage() { String errorMsg; - switch(errorCode) { - case UNKNOWN_CMD: - errorMsg = "OOPS!!! I'm sorry, but I don't know what that means :-("; - break; - case MISSING_TODO_ITEM: - errorMsg = "OOPS!!! The description of a todo cannot be empty."; - break; - case UNKNOWN_TASK_ENCODING: - errorMsg = "OOPS!!! Unable to parse one of the saved tasks. This task will be skipped."; - case INVALID_DEADLINE_DATETIME_FORMAT: - String dateFormat = "\t Please ensure date time is of the " + - "following format: yyyy-mm-dd hh:mm:ss"; - errorMsg = "OOPS!!! Unable to parse date time for deadline.\n" + dateFormat; - break; - case INVALID_EVENT_DATETIME_FORMAT: - dateFormat = "\t Please ensure date time is of the " + - "following format: yyyy-mm-dd hh:mm:ss hh:mm:ss hh:mm:ss"; - errorMsg = "OOPS!!! Unable to parse date time for event.\n" + dateFormat; - break; - default: - errorMsg = "OOPS!!! Unknown duke error occurred. :-("; + switch (errorCode) { + case UNKNOWN_CMD: + errorMsg = "OOPS!!! I'm sorry, but I don't know what that means :-("; + break; + case MISSING_TODO_ITEM: + errorMsg = "OOPS!!! The description of a todo cannot be empty."; + break; + case UNKNOWN_TASK_ENCODING: + errorMsg = "OOPS!!! Unable to parse one of the saved tasks. This task will be skipped."; + case INVALID_DEADLINE_DATETIME_FORMAT: + String dateFormat = "\t Please ensure date time is of the " + + "following format: yyyy-mm-dd hh:mm:ss"; + errorMsg = "OOPS!!! Unable to parse date time for deadline.\n" + dateFormat; + break; + case INVALID_EVENT_DATETIME_FORMAT: + dateFormat = "\t Please ensure date time is of the " + + "following format: yyyy-mm-dd hh:mm:ss hh:mm:ss hh:mm:ss"; + errorMsg = "OOPS!!! Unable to parse date time for event.\n" + dateFormat; + break; + default: + errorMsg = "OOPS!!! Unknown duke error occurred. :-("; } return errorMsg; } + /** + * A representation of possible exceptions that occur from Duke operations + */ public enum ErrorCode { UNKNOWN_CMD, MISSING_TODO_ITEM, diff --git a/src/main/java/task/Deadline.java b/src/main/java/task/Deadline.java index 1fde84108c..a62cede683 100644 --- a/src/main/java/task/Deadline.java +++ b/src/main/java/task/Deadline.java @@ -2,20 +2,36 @@ import date.DeadlineDateTime; +/** + * Represents a task with a deadline + * + * @author Bryan Lim Jing Xiang + */ public class Deadline extends Task { private final DeadlineDateTime deadline; + /** + * {@inheritDoc} + * + * @param deadline Deadline of the task + */ public Deadline(String taskItem, DeadlineDateTime deadline) { super(taskItem); this.deadline = deadline; } + /** + * {@inheritDoc} + */ @Override public String toString() { String deadlineDisplay = String.format(" (by: %s)", this.deadline); return "[D]" + super.toString() + deadlineDisplay; } + /** + * {@inheritDoc} + */ @Override public String encode() { int markedStatus = getIsMarked() ? 1 : 0; diff --git a/src/main/java/task/Event.java b/src/main/java/task/Event.java index 732b4dbefd..8aafaf76df 100644 --- a/src/main/java/task/Event.java +++ b/src/main/java/task/Event.java @@ -2,20 +2,36 @@ import date.EventDateTime; -public class Event extends Task{ +/** + * Represents an event task + * + * @author Bryan Lim Jing Xiang + */ +public class Event extends Task { private final EventDateTime eventTiming; - + + /** + * {@inheritDoc} + * + * @param eventTiming Date and time of the event + */ public Event(String taskItem, EventDateTime eventTiming) { super(taskItem); this.eventTiming = eventTiming; } + /** + * {@inheritDoc} + */ @Override public String toString() { String eventTimingDisplay = String.format(" (at: %s)", this.eventTiming); return "[E]" + super.toString() + eventTimingDisplay; } + /** + * {@inheritDoc} + */ @Override public String encode() { int markedStatus = getIsMarked() ? 1 : 0; diff --git a/src/main/java/task/Task.java b/src/main/java/task/Task.java index a75012d9a4..8273ea540f 100644 --- a/src/main/java/task/Task.java +++ b/src/main/java/task/Task.java @@ -1,14 +1,28 @@ package task; +/** + * Represents the tasks that are stored within the internal duke list + * + * @author Bryan Lim Jing Xiang + */ public abstract class Task { private final String TaskItem; private boolean isMarked; + /** + * @param TaskItem Task to be stored + */ public Task(String TaskItem) { this.TaskItem = TaskItem; this.isMarked = false; } + /** + * {@inheritDoc} + * + * @return String representation of the task + * including its marked status and type + */ @Override public String toString() { String checkbox = isMarked ? "[X] " : "[ ] "; @@ -27,5 +41,8 @@ protected String getTaskItem() { return TaskItem; } + /** + * @return A string encoding of the task to be stored in the save file + */ public abstract String encode(); } diff --git a/src/main/java/task/Todo.java b/src/main/java/task/Todo.java index 04801945ef..8849d942e7 100644 --- a/src/main/java/task/Todo.java +++ b/src/main/java/task/Todo.java @@ -2,22 +2,43 @@ import exception.DukeException; +/** + * Represents a task to be done + * + * @author Bryan Lim Jing Xiang + */ public class Todo extends Task { + /** + * {@inheritDoc} + */ public Todo(String taskItem) { super(taskItem); } + /** + * {@inheritDoc} + */ @Override public String toString() { return "[T]" + super.toString(); } + /** + * Validates the input line that represents a command + * to create a Todo object. + * + * @param input Input command to create a Todo + * @throws DukeException If input is invalid + */ public static void validateInput(String[] input) throws DukeException { if (input.length < 2 || input[1].strip().equals("")) { throw new DukeException(DukeException.ErrorCode.MISSING_TODO_ITEM); } } + /** + * {@inheritDoc} + */ @Override public String encode() { int markedStatus = getIsMarked() ? 1 : 0; diff --git a/src/main/java/tasklist/TaskList.java b/src/main/java/tasklist/TaskList.java index 8fff9bbf52..aa3104c4a9 100644 --- a/src/main/java/tasklist/TaskList.java +++ b/src/main/java/tasklist/TaskList.java @@ -2,16 +2,34 @@ import task.Task; import util.Ui; + import java.util.ArrayList; +/** + * A list that that handles the storing of tasks + * + * @author Bryan Lim Jing Xiang + */ public class TaskList { private final ArrayList list = new ArrayList<>(); + /** + * Adds a given task item to the list + * + * @param taskItem Task to be added + * @return The same task that is passed in + */ public Task addTask(Task taskItem) { this.list.add(taskItem); return taskItem; } + /** + * {@inheritDoc} + * + * @return A string representation of all tasks within the list + * formatted properly to be printed out as output + */ @Override public String toString() { String res = Ui.formatLine("Here are the tasks in your list:"); @@ -22,28 +40,47 @@ public String toString() { return res; } + /** + * @param index Index of the task to be marked, based on 1-index + * @return Task that is marked + */ public Task markItem(int index) { Task taskItem = this.list.get(index - 1); taskItem.setIsMarked(true); return taskItem; } + /** + * @param index Index of the task to be unmarked, based on 1-index + * @return Task that is unmarked + */ public Task unmarkItem(int index) { Task taskItem = this.list.get(index - 1); taskItem.setIsMarked(false); return taskItem; } + /** + * @param index Index of the task to be removed from list, based on 1-index + * @return Task that is deleted + */ public Task deleteItem(int index) { Task taskItem = this.list.get(index - 1); this.list.remove(index - 1); return taskItem; } + /** + * @param index Index of the task to be retrieved, based on 1-index + * @return Task that is retrieved + */ public Task getItem(int index) { return this.list.get(index - 1); } + /** + * @return Number of tasks within the list currently + */ public int getTaskCount() { return this.list.size(); } diff --git a/src/main/java/util/Parser.java b/src/main/java/util/Parser.java index 2d31e649e1..516c7527ec 100644 --- a/src/main/java/util/Parser.java +++ b/src/main/java/util/Parser.java @@ -9,76 +9,97 @@ import task.Task; import task.Todo; +/** + * Parses all input lines from command line or save file and generates commands + * to be executed + * + * @author Bryan Lim Jing Xiang + */ public class Parser { + /** + * Parses a single line of input from the command line + * + * @param inputLine Input from the command line containing a command + * and its arguments + * @return A command to be executed + * @throws DukeException If inputLine cannot be parsed successfully + */ public static Command parseInputLine(String inputLine) throws DukeException { String[] splitted = inputLine.split("\\s+", 2); String command = splitted[0]; Command cmd; switch (command) { - case "bye": - cmd = new TerminateCommand(); - break; - case "list": - cmd = new ListAllTasksCommand(); - break; - case "mark": - int index = Integer.parseInt(splitted[1]); - cmd = new MarkTaskCommand(index); - break; - case "unmark": - index = Integer.parseInt(splitted[1]); - cmd = new UnmarkTaskCommand(index); - break; - case "delete": - index = Integer.parseInt(splitted[1]); - cmd = new DeleteTaskCommand(index); - break; - case "todo": - Todo.validateInput(splitted); - Task todo = new Todo(splitted[1]); - cmd = new AddTaskCommand(todo); - break; - case "deadline": - // Regex "\\s+/" matches one or more space followed by a /by, - // followed by one or more space - String[] taskArgs = splitted[1].split("\\s+/by\\s+",2); - DeadlineDateTime deadlineDateTime = DeadlineDateTime.parseDate(taskArgs[1]); - Task deadline = new Deadline(taskArgs[0], deadlineDateTime); - cmd = new AddTaskCommand(deadline); - break; - case "event": - // Regex "\s+/at\s+" matches one or more space followed by a /at, - // followed by one or more space - taskArgs = splitted[1].split("\\s+/at\\s+",2); - EventDateTime eventDateTime = EventDateTime.parseDate(taskArgs[1]); - Task event = new Event(taskArgs[0], eventDateTime); - cmd = new AddTaskCommand(event); - break; - default: - throw new DukeException(DukeException.ErrorCode.UNKNOWN_CMD); + case "bye": + cmd = new TerminateCommand(); + break; + case "list": + cmd = new ListAllTasksCommand(); + break; + case "mark": + int index = Integer.parseInt(splitted[1]); + cmd = new MarkTaskCommand(index); + break; + case "unmark": + index = Integer.parseInt(splitted[1]); + cmd = new UnmarkTaskCommand(index); + break; + case "delete": + index = Integer.parseInt(splitted[1]); + cmd = new DeleteTaskCommand(index); + break; + case "todo": + Todo.validateInput(splitted); + Task todo = new Todo(splitted[1]); + cmd = new AddTaskCommand(todo); + break; + case "deadline": + // Regex "\\s+/" matches one or more space followed by a /by, + // followed by one or more space + String[] taskArgs = splitted[1].split("\\s+/by\\s+", 2); + DeadlineDateTime deadlineDateTime = DeadlineDateTime.parseDate(taskArgs[1]); + Task deadline = new Deadline(taskArgs[0], deadlineDateTime); + cmd = new AddTaskCommand(deadline); + break; + case "event": + // Regex "\s+/at\s+" matches one or more space followed by a /at, + // followed by one or more space + taskArgs = splitted[1].split("\\s+/at\\s+", 2); + EventDateTime eventDateTime = EventDateTime.parseDate(taskArgs[1]); + Task event = new Event(taskArgs[0], eventDateTime); + cmd = new AddTaskCommand(event); + break; + default: + throw new DukeException(DukeException.ErrorCode.UNKNOWN_CMD); } return cmd; } + /** + * Parses a single line of input from the save file + * + * @param encodedTask Encoding from a task saved in the save file + * @return A command to be executed + * @throws DukeException If encoded task cannot be parsed successfully + */ public static Command parseEncodedTask(String encodedTask) throws DukeException { String[] splitted = encodedTask.split(",", 4); String taskType = splitted[0]; Task taskItem; switch (taskType) { - case "T": - taskItem = new Todo(splitted[2]); - break; - case "E": - EventDateTime eventDateTime = EventDateTime.parseDateFromStorage(splitted[3]); - taskItem = new Event(splitted[2], eventDateTime); - break; - case "D": - DeadlineDateTime deadlineDateTime = DeadlineDateTime.parseDateFromStorage(splitted[3]); - taskItem = new Deadline(splitted[2], deadlineDateTime); - break; - default: - throw new DukeException(DukeException.ErrorCode.UNKNOWN_TASK_ENCODING); + case "T": + taskItem = new Todo(splitted[2]); + break; + case "E": + EventDateTime eventDateTime = EventDateTime.parseDateFromStorage(splitted[3]); + taskItem = new Event(splitted[2], eventDateTime); + break; + case "D": + DeadlineDateTime deadlineDateTime = DeadlineDateTime.parseDateFromStorage(splitted[3]); + taskItem = new Deadline(splitted[2], deadlineDateTime); + break; + default: + throw new DukeException(DukeException.ErrorCode.UNKNOWN_TASK_ENCODING); } taskItem.setIsMarked(splitted[1].equals("1")); return new AddTaskFromStorageCommand(taskItem); diff --git a/src/main/java/util/Storage.java b/src/main/java/util/Storage.java index a65108ed10..9464be9d0c 100644 --- a/src/main/java/util/Storage.java +++ b/src/main/java/util/Storage.java @@ -11,12 +11,24 @@ import java.io.IOException; import java.util.Scanner; +/** + * Handles the any storage related functionality related to the save file + * + * @author Bryan Lim Jing Xiang + */ public class Storage { private final File saveFile; + private Storage(File saveFile) { this.saveFile = saveFile; } + /** + * Initialises the save file, creates one if needed + * + * @param storagePathName Relative path of the save file + * @return Storage object that handles operations to the save file + */ public static Storage initialize(String storagePathName) { File saveFile = new File(storagePathName); try { @@ -32,6 +44,11 @@ public static Storage initialize(String storagePathName) { return new Storage(saveFile); } + /** + * Loads and stores all saved tasks into the current duke list + * + * @param list Duke list of the current running instance of the app + */ public void load(TaskList list) { try (Scanner sc = new Scanner(this.saveFile)) { while (sc.hasNext()) { @@ -49,6 +66,11 @@ public void load(TaskList list) { } } + /** + * Saves all tasks from the current duke list into the save file + * + * @param list Duke list of the current running instance of the app + */ public void saveAllTasks(TaskList list) { try (FileWriter fileWriter = new FileWriter(this.saveFile, false)) { for (int i = 1; i <= list.getTaskCount(); i++) { diff --git a/src/main/java/util/Ui.java b/src/main/java/util/Ui.java index 3330f510ad..6df655dadc 100644 --- a/src/main/java/util/Ui.java +++ b/src/main/java/util/Ui.java @@ -1,15 +1,38 @@ package util; +/** + * A collection of all Ui related utilities + * + * @author Bryan Lim Jing Xiang + */ public class Ui { + /** + * Formats a single line of text + * + * @param input String to be formatted + * @return Formatted string to be printed + */ public static String formatLine(String input) { return "\t " + input + "\n"; } + /** + * Adds Ui elements to prettify a block or paragraph of text + * + * @param paragraph Paragraph of formatted text to be prettified + * @return Prettified block of text to be printed + */ public static String formatParagraph(String paragraph) { String divider = "\t____________________________________________________________\n"; return divider + paragraph + divider; } + /** + * Formats and prettifies lines of text to be printed + * + * @param lines Lines of text to be formatted and prettified + * @return Prettified block of text to be printed + */ public static String formatLinesIntoParagraph(String... lines) { String res = ""; for (String line : lines) { @@ -19,6 +42,9 @@ public static String formatLinesIntoParagraph(String... lines) { return formatParagraph(res); } + /** + * Prints the introduction message when starting the app + */ public static void printIntroMessage() { String introParagraph = Ui.formatLine("Hello! I'm duke.") + Ui.formatLine("What can I do for you?"); diff --git a/src/test/java/task/DeadlineTest.java b/src/test/java/task/DeadlineTest.java index dd3d0c7488..e6c019a531 100644 --- a/src/test/java/task/DeadlineTest.java +++ b/src/test/java/task/DeadlineTest.java @@ -1,8 +1,8 @@ package task; import date.DeadlineDateTime; -import date.EventDateTime; import exception.DukeException; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -10,6 +10,7 @@ class DeadlineTest { @Test + @DisplayName("Test for toString() method of unmarked deadline") void testToString_for_unmarked_deadline() throws DukeException { DeadlineDateTime date = DeadlineDateTime.parseDate("2022-01-01 00:00:00"); Deadline test = new Deadline("Testing!", date); @@ -18,6 +19,7 @@ void testToString_for_unmarked_deadline() throws DukeException { } @Test + @DisplayName("Test for toString() method of marked deadline") void testToString_for_marked_deadline() throws DukeException { DeadlineDateTime date = DeadlineDateTime.parseDate("2022-01-01 00:00:00"); Deadline test = new Deadline("Testing!", date); @@ -27,6 +29,7 @@ void testToString_for_marked_deadline() throws DukeException { } @Test + @DisplayName("Test for encode() method of deadline") void encode() throws DukeException { DeadlineDateTime date = DeadlineDateTime.parseDate("2022-01-01 00:00:00"); Deadline test = new Deadline("Testing!", date); diff --git a/src/test/java/task/EventTest.java b/src/test/java/task/EventTest.java index e27deed5cb..71543bd209 100644 --- a/src/test/java/task/EventTest.java +++ b/src/test/java/task/EventTest.java @@ -2,6 +2,7 @@ import date.EventDateTime; import exception.DukeException; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -9,6 +10,7 @@ class EventTest { @Test + @DisplayName("Test for toString() method of unmarked event") void testToString_for_unmarked_event() throws DukeException { EventDateTime date = EventDateTime.parseDate("2022-01-01 00:00:00 12:00:00"); Event test = new Event("Testing!", date); @@ -17,6 +19,7 @@ void testToString_for_unmarked_event() throws DukeException { } @Test + @DisplayName("Test for toString() method of marked event") void testToString_for_marked_event() throws DukeException { EventDateTime date = EventDateTime.parseDate("2022-01-01 00:00:00 12:00:00"); Event test = new Event("Testing!", date); @@ -26,6 +29,7 @@ void testToString_for_marked_event() throws DukeException { } @Test + @DisplayName("Test for encode() method of event") void encode() throws DukeException { EventDateTime date = EventDateTime.parseDate("2022-01-01 00:00:00 12:00:00"); Event test = new Event("Testing!", date); diff --git a/src/test/java/task/TodoTest.java b/src/test/java/task/TodoTest.java index 05ccf2de16..e3b0ea0c00 100644 --- a/src/test/java/task/TodoTest.java +++ b/src/test/java/task/TodoTest.java @@ -1,6 +1,7 @@ package task; import exception.DukeException; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -8,6 +9,7 @@ class TodoTest { @Test + @DisplayName("Test for toString() method of unmarked todo") void testToString_for_unmarked_todo() { Todo test = new Todo("Testing!"); String expected = "[T][ ] Testing!"; @@ -15,6 +17,7 @@ void testToString_for_unmarked_todo() { } @Test + @DisplayName("Test validateInput throws exception when task item is not given") void validateInput_throws_exception_when_input_length_less_than_two() { String[] inputLengthLessThanOne = new String[] { "Testing!" @@ -25,6 +28,7 @@ void validateInput_throws_exception_when_input_length_less_than_two() { } @Test + @DisplayName("Test validateInput throws exception when task item is whitespace") void validateInput_throws_exception_when_second_string_is_whitespace() { String[] secondStringIsWhitespace = new String[] { "Testing!", @@ -36,6 +40,7 @@ void validateInput_throws_exception_when_second_string_is_whitespace() { } @Test + @DisplayName("Test for encode() method of unmarked todo") void encode_unmarked_todo() { Todo test = new Todo("Testing!"); String expected = "T,0,Testing!\n"; @@ -43,6 +48,7 @@ void encode_unmarked_todo() { } @Test + @DisplayName("Test for encode() method of marked todo") void encode_marked_todo() { Todo test = new Todo("Testing!"); test.setIsMarked(true); diff --git a/src/test/java/task/stub/MarkedTaskStub.java b/src/test/java/task/stub/MarkedTaskStub.java index 9ec49d9768..18d33adc25 100644 --- a/src/test/java/task/stub/MarkedTaskStub.java +++ b/src/test/java/task/stub/MarkedTaskStub.java @@ -1,11 +1,21 @@ package task.stub; +/** + * A task stub that is marked + * + * @author Bryan Lim Jing Xiang + */ public class MarkedTaskStub extends TaskStub { @Override protected boolean getIsMarked() { return true; } + /** + * Overrides the Task encoding to always return a marked task's encoding + * + * @return Encoding of a marked Task stub + */ @Override public String encode() { return "[X] " + this.getTaskItem(); diff --git a/src/test/java/task/stub/TaskStub.java b/src/test/java/task/stub/TaskStub.java index 9f7d406b0f..1b3fa690e5 100644 --- a/src/test/java/task/stub/TaskStub.java +++ b/src/test/java/task/stub/TaskStub.java @@ -2,16 +2,28 @@ import task.Task; +/** + * A stub for the Task class + * + * @author Bryan Lim Jing Xiang + */ public class TaskStub extends Task { public TaskStub() { super("Testing!"); } + /** + * {@inheritDoc} + */ @Override public String encode() { return this.toString(); } + /** + * {@inheritDoc} + * Compares two stubs for equality for testing convenience + */ @Override public boolean equals(Object o) { if (o == this) { @@ -25,6 +37,9 @@ public boolean equals(Object o) { return false; } + /** + * {@inheritDoc} + */ @Override public String toString() { return "Testing!"; diff --git a/src/test/java/task/stub/UnmarkedTaskStub.java b/src/test/java/task/stub/UnmarkedTaskStub.java index 015a913ae3..867766dba1 100644 --- a/src/test/java/task/stub/UnmarkedTaskStub.java +++ b/src/test/java/task/stub/UnmarkedTaskStub.java @@ -1,13 +1,21 @@ package task.stub; -import task.stub.TaskStub; - +/** + * A task stub that is unmarked + * + * @author Bryan Lim Jing Xiang + */ public class UnmarkedTaskStub extends TaskStub { @Override protected boolean getIsMarked() { return false; } + /** + * Overrides the Task encoding to always return a unmarked task's encoding + * + * @return Encoding of an unmarked Task stub + */ @Override public String encode() { return "[ ] " + this.getTaskItem(); diff --git a/src/test/java/tasklist/TaskListTest.java b/src/test/java/tasklist/TaskListTest.java index 2e75967200..ffe325da7d 100644 --- a/src/test/java/tasklist/TaskListTest.java +++ b/src/test/java/tasklist/TaskListTest.java @@ -1,5 +1,6 @@ package tasklist; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import task.stub.MarkedTaskStub; import task.Task; @@ -11,6 +12,7 @@ class TaskListTest { @Test + @DisplayName("Testing addTask()") void addTask() { TaskList test = new TaskList(); Task stub = new TaskStub(); @@ -22,6 +24,7 @@ void addTask() { } @Test + @DisplayName("Testing toString() when list is empty") void testToString_when_list_is_empty() { TaskList test = new TaskList(); String expected = "\t " + "Here are the tasks in your list:" + "\n"; @@ -29,6 +32,7 @@ void testToString_when_list_is_empty() { } @Test + @DisplayName("Testing toString() when list is not empty") void testToString_when_list_is_not_empty() { TaskList test = new TaskList(); Task stub = new TaskStub(); @@ -41,6 +45,7 @@ void testToString_when_list_is_not_empty() { } @Test + @DisplayName("Testing markItem()") void markItem() { TaskList test = new TaskList(); Task stub = new TaskStub(); @@ -54,6 +59,7 @@ void markItem() { } @Test + @DisplayName("Testing unmarkItem()") void unmarkItem() { TaskList test = new TaskList(); Task stub = new TaskStub(); @@ -65,6 +71,7 @@ void unmarkItem() { } @Test + @DisplayName("Testing deleteItem()") void deleteItem_giving_empty_list() { TaskList test = new TaskList(); Task stub = new TaskStub(); @@ -76,12 +83,14 @@ void deleteItem_giving_empty_list() { } @Test + @DisplayName("Testing getTaskCount() when list is empty") void getTaskCount_when_list_is_empty() { TaskList test = new TaskList(); assertEquals(test.getTaskCount(), 0); } @Test + @DisplayName("Testing getTaskCount() when list has one task") void getTaskCount_when_list_has_one_task() { TaskList test = new TaskList(); Task stub = new TaskStub(); From d3659f7495bd7c4dc89bb907a4e534d3247e3289 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Sat, 27 Aug 2022 16:27:58 +0800 Subject: [PATCH 53/73] Add javadocs for FindSearchTextCommand --- src/main/java/command/FindSearchTextCommand.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/command/FindSearchTextCommand.java b/src/main/java/command/FindSearchTextCommand.java index a09e564b76..09a70f6bd3 100644 --- a/src/main/java/command/FindSearchTextCommand.java +++ b/src/main/java/command/FindSearchTextCommand.java @@ -6,13 +6,26 @@ import java.util.ArrayList; +/** + * Represents a task to be executed that searches and returns a task in the internal + * duke list based on search text + * + * @author Bryan Lim Jing Xiang + */ public class FindSearchTextCommand extends Command { private final String searchText; + /** + * @param searchText Searches duke list for any tasks that contains the + * search text + */ public FindSearchTextCommand(String searchText) { this.searchText = searchText; } + /** + * {@inheritDoc} + */ @Override public void execute(TaskList list, Storage storage) { ArrayList matchedTasks = list.find(searchText); From 1d817e141ef18f11709228381ef520f90c849a11 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Mon, 29 Aug 2022 14:52:57 +0800 Subject: [PATCH 54/73] Add javadocs for Find functions --- src/main/java/command/FindSearchTextCommand.java | 4 ++-- src/main/java/tasklist/TaskList.java | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/command/FindSearchTextCommand.java b/src/main/java/command/FindSearchTextCommand.java index 09a70f6bd3..f181f14311 100644 --- a/src/main/java/command/FindSearchTextCommand.java +++ b/src/main/java/command/FindSearchTextCommand.java @@ -1,11 +1,11 @@ package command; +import java.util.ArrayList; + import tasklist.TaskList; import util.Storage; import util.Ui; -import java.util.ArrayList; - /** * Represents a task to be executed that searches and returns a task in the internal * duke list based on search text diff --git a/src/main/java/tasklist/TaskList.java b/src/main/java/tasklist/TaskList.java index 08fe3510ed..22cb485f54 100644 --- a/src/main/java/tasklist/TaskList.java +++ b/src/main/java/tasklist/TaskList.java @@ -28,7 +28,7 @@ public Task addTask(Task taskItem) { * {@inheritDoc} * * @return A string representation of all tasks within the list - * formatted properly to be printed out as output + * formatted properly to be printed out as output */ @Override public String toString() { @@ -85,6 +85,10 @@ public int getTaskCount() { return this.list.size(); } + /** + * @param searchText Text to be searched + * @return A list of tasks that matches the searchText + */ public ArrayList find(String searchText) { ArrayList res = new ArrayList<>(); From ec31e4cb0caf3b0975dcb5e312b2e629ba446d3e Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Mon, 29 Aug 2022 14:54:49 +0800 Subject: [PATCH 55/73] Add import for @DisplayName annotation --- src/test/java/task/DeadlineTest.java | 1 + src/test/java/task/EventTest.java | 1 + src/test/java/task/TodoTest.java | 1 + 3 files changed, 3 insertions(+) diff --git a/src/test/java/task/DeadlineTest.java b/src/test/java/task/DeadlineTest.java index aff80a20e7..398d523c86 100644 --- a/src/test/java/task/DeadlineTest.java +++ b/src/test/java/task/DeadlineTest.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import date.DeadlineDateTime; diff --git a/src/test/java/task/EventTest.java b/src/test/java/task/EventTest.java index 5a87419110..ef651907a8 100644 --- a/src/test/java/task/EventTest.java +++ b/src/test/java/task/EventTest.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import date.EventDateTime; diff --git a/src/test/java/task/TodoTest.java b/src/test/java/task/TodoTest.java index dc8c4dd809..5a947fd1ec 100644 --- a/src/test/java/task/TodoTest.java +++ b/src/test/java/task/TodoTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import exception.DukeException; From 1f4342355c062b58c16671235a2714b2b2ade452 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 1 Sep 2022 16:40:16 +0800 Subject: [PATCH 56/73] Add javaFX to application --- build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.gradle b/build.gradle index 19f97fd7b6..aaba8ad40a 100644 --- a/build.gradle +++ b/build.gradle @@ -3,12 +3,18 @@ plugins { id 'application' id 'checkstyle' id 'com.github.johnrengelman.shadow' version '5.1.0' + id 'org.openjfx.javafxplugin' version '0.0.10' } repositories { mavenCentral() } +javafx { + version = "18.0.2" + modules = [ 'javafx.controls' ] +} + 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' From 6791a4f6f88eec6098d071bef0a7106f6da58ed5 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 1 Sep 2022 16:41:23 +0800 Subject: [PATCH 57/73] Modify Command classes to store/return output message --- src/main/java/command/AddTaskCommand.java | 2 +- src/main/java/command/Command.java | 10 ++++++++++ src/main/java/command/DeleteTaskCommand.java | 2 +- src/main/java/command/FindSearchTextCommand.java | 2 +- src/main/java/command/ListAllTasksCommand.java | 5 ++--- src/main/java/command/MarkTaskCommand.java | 2 +- src/main/java/command/UnmarkTaskCommand.java | 2 +- 7 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/main/java/command/AddTaskCommand.java b/src/main/java/command/AddTaskCommand.java index c70aa319c0..80f30780c1 100644 --- a/src/main/java/command/AddTaskCommand.java +++ b/src/main/java/command/AddTaskCommand.java @@ -27,7 +27,7 @@ public void execute(TaskList list, Storage storage) { String endLine = String.format( "Now you have %d tasks in the list.", list.getTaskCount()); - System.out.println(Ui.formatLinesIntoParagraph( + setOutputMessage(Ui.formatLinesIntoParagraph( startLine, task, endLine diff --git a/src/main/java/command/Command.java b/src/main/java/command/Command.java index 014e80fec8..354ef244c1 100644 --- a/src/main/java/command/Command.java +++ b/src/main/java/command/Command.java @@ -12,6 +12,8 @@ public abstract class Command { private boolean isTerminated = false; + private String outputMessage = ""; + /** * Executes a specific command * @@ -20,6 +22,14 @@ public abstract class Command { */ public abstract void execute(TaskList list, Storage storage); + public String getOutputMessage() { + return this.outputMessage; + } + + protected void setOutputMessage(String outputMessage) { + this.outputMessage = outputMessage; + } + public boolean getIsTerminated() { return isTerminated; } diff --git a/src/main/java/command/DeleteTaskCommand.java b/src/main/java/command/DeleteTaskCommand.java index 13ddf6177b..b125b012d0 100644 --- a/src/main/java/command/DeleteTaskCommand.java +++ b/src/main/java/command/DeleteTaskCommand.java @@ -31,7 +31,7 @@ public void execute(TaskList list, Storage storage) { String endLine = String.format( "Now you have %d tasks in the list.", list.getTaskCount()); - System.out.println(Ui.formatLinesIntoParagraph( + setOutputMessage(Ui.formatLinesIntoParagraph( deleteText, deletedItem, endLine diff --git a/src/main/java/command/FindSearchTextCommand.java b/src/main/java/command/FindSearchTextCommand.java index f181f14311..37fc3c6073 100644 --- a/src/main/java/command/FindSearchTextCommand.java +++ b/src/main/java/command/FindSearchTextCommand.java @@ -41,6 +41,6 @@ public void execute(TaskList list, Storage storage) { for (String match : matchedTasks) { res += Ui.formatLine(match); } - System.out.println(Ui.formatParagraph(res)); + setOutputMessage(res); } } diff --git a/src/main/java/command/ListAllTasksCommand.java b/src/main/java/command/ListAllTasksCommand.java index 7aa88b6e38..9714332a34 100644 --- a/src/main/java/command/ListAllTasksCommand.java +++ b/src/main/java/command/ListAllTasksCommand.java @@ -2,7 +2,6 @@ import tasklist.TaskList; import util.Storage; -import util.Ui; /** * Represents a command to be executed that lists all current tasks in the @@ -16,8 +15,8 @@ public class ListAllTasksCommand extends Command { */ @Override public void execute(TaskList list, Storage storage) { - System.out.println(Ui.formatParagraph( + setOutputMessage( list.toString() - )); + ); } } diff --git a/src/main/java/command/MarkTaskCommand.java b/src/main/java/command/MarkTaskCommand.java index 8dbf8ab9f4..cb55584298 100644 --- a/src/main/java/command/MarkTaskCommand.java +++ b/src/main/java/command/MarkTaskCommand.java @@ -26,7 +26,7 @@ public MarkTaskCommand(int index) { public void execute(TaskList list, Storage storage) { String markedItem = " " + list.markItem(index); String markedText = "Nice! I've marked this task as done:"; - System.out.println(Ui.formatLinesIntoParagraph( + setOutputMessage(Ui.formatLinesIntoParagraph( markedText, markedItem )); diff --git a/src/main/java/command/UnmarkTaskCommand.java b/src/main/java/command/UnmarkTaskCommand.java index 58e36c8386..20caef255d 100644 --- a/src/main/java/command/UnmarkTaskCommand.java +++ b/src/main/java/command/UnmarkTaskCommand.java @@ -28,7 +28,7 @@ public UnmarkTaskCommand(int index) { public void execute(TaskList list, Storage storage) { String unmarkedItem = " " + list.unmarkItem(index); String unmarkedText = "OK, I've marked this task as not done yet:"; - System.out.println(Ui.formatLinesIntoParagraph( + setOutputMessage(Ui.formatLinesIntoParagraph( unmarkedText, unmarkedItem )); From e960b7d19bc4024ef3a0cb811159a9870ac94c82 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 1 Sep 2022 16:42:17 +0800 Subject: [PATCH 58/73] Add gui elements --- src/main/java/gui/DialogBox.java | 68 +++++++++++++++++ src/main/java/gui/DukeGui.java | 109 +++++++++++++++++++++++++++ src/main/resources/images/DaDuke.png | Bin 0 -> 32657 bytes src/main/resources/images/DaUser.png | Bin 0 -> 37794 bytes 4 files changed, 177 insertions(+) create mode 100644 src/main/java/gui/DialogBox.java create mode 100644 src/main/java/gui/DukeGui.java create mode 100644 src/main/resources/images/DaDuke.png create mode 100644 src/main/resources/images/DaUser.png diff --git a/src/main/java/gui/DialogBox.java b/src/main/java/gui/DialogBox.java new file mode 100644 index 0000000000..bb6ab3f310 --- /dev/null +++ b/src/main/java/gui/DialogBox.java @@ -0,0 +1,68 @@ +package gui; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.image.ImageView; +import javafx.scene.layout.HBox; + +/** + * DialogBox serves as the layout where the user interacts with the Duke + * + * @author Bryan Lim Jing Xiang + */ +public class DialogBox extends HBox { + + private Label text; + private ImageView displayPicture; + + /** + * @param l Label or text to be displayed + * @param iv Avatar of the current speaker + */ + public DialogBox(Label l, ImageView iv) { + text = l; + displayPicture = iv; + + text.setWrapText(true); + displayPicture.setFitWidth(100.0); + displayPicture.setFitHeight(100.0); + + l.setAlignment(Pos.BASELINE_LEFT); + + this.setAlignment(Pos.TOP_RIGHT); + this.getChildren().addAll(text, displayPicture); + } + + /** + * Flips the dialog box such that the ImageView is on the left and text on the right. + */ + private void flip() { + this.setAlignment(Pos.TOP_LEFT); + ObservableList tmp = FXCollections.observableArrayList(this.getChildren()); + FXCollections.reverse(tmp); + this.getChildren().setAll(tmp); + } + + /** + * @param l Command or text entered by user + * @param iv Avatar of the user + * @return A dialog box for the user + */ + public static DialogBox getUserDialog(Label l, ImageView iv) { + return new DialogBox(l, iv); + } + + /** + * @param l Response returned by Duke + * @param iv Avatar of Duke + * @return A dialog box for Duke + */ + public static DialogBox getDukeDialog(Label l, ImageView iv) { + var db = new DialogBox(l, iv); + db.flip(); + return db; + } +} diff --git a/src/main/java/gui/DukeGui.java b/src/main/java/gui/DukeGui.java new file mode 100644 index 0000000000..4d40ca38ad --- /dev/null +++ b/src/main/java/gui/DukeGui.java @@ -0,0 +1,109 @@ +package gui; + +import duke.Duke; +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TextField; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.Region; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import util.Ui; + +/** + * Handles the main logic for the graphical user interface for Duke + * + * @author Bryan Lim Jing Xiang + */ +public class DukeGui extends Application { + private final Duke dukeApp = new Duke("data/saveFile.txt"); + + private Image user = new Image(this.getClass().getResourceAsStream("/images/DaUser.png")); + private Image duke = new Image(this.getClass().getResourceAsStream("/images/DaDuke.png")); + + private ScrollPane scrollPane; + private VBox dialogContainer; + private TextField userInput; + private Button sendButton; + private Scene scene; + + /** + * {@inheritDoc} + */ + @Override + public void start(Stage stage) { + scrollPane = new ScrollPane(); + dialogContainer = new VBox(); + scrollPane.setContent(dialogContainer); + + displayIntroMessage(); + + userInput = new TextField(); + sendButton = new Button("Send"); + + AnchorPane mainLayout = new AnchorPane(); + mainLayout.getChildren().addAll(scrollPane, userInput, sendButton); + + scene = new Scene(mainLayout); + + stage.setScene(scene); + stage.show(); + + stage.setTitle("Duke"); + stage.setResizable(false); + stage.setMinHeight(600.0); + stage.setMinWidth(400.0); + + mainLayout.setPrefSize(400.0, 600.0); + + scrollPane.setPrefSize(385, 535); + scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); + scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS); + + scrollPane.setVvalue(1.0); + scrollPane.setFitToWidth(true); + + dialogContainer.setPrefHeight(Region.USE_COMPUTED_SIZE); + + userInput.setPrefWidth(325.0); + + sendButton.setPrefWidth(55.0); + + AnchorPane.setTopAnchor(scrollPane, 1.0); + + AnchorPane.setBottomAnchor(sendButton, 1.0); + AnchorPane.setRightAnchor(sendButton, 1.0); + + AnchorPane.setLeftAnchor(userInput , 1.0); + AnchorPane.setBottomAnchor(userInput, 1.0); + + sendButton.setOnMouseClicked((event) -> { + handleUserInput(); + }); + + userInput.setOnAction((event) -> { + handleUserInput(); + }); + } + + private void handleUserInput() { + String dukeResponse = dukeApp.getResponse(userInput.getText()); + Label userText = new Label(userInput.getText()); + Label dukeText = new Label(dukeResponse); + dialogContainer.getChildren().addAll( + DialogBox.getUserDialog(userText, new ImageView(user)), + DialogBox.getDukeDialog(dukeText, new ImageView(duke)) + ); + userInput.clear(); + } + + private void displayIntroMessage() { + Label introText = new Label(Ui.getIntroMessage()); + dialogContainer.getChildren().add(DialogBox.getDukeDialog(introText, new ImageView(duke))); + } +} diff --git a/src/main/resources/images/DaDuke.png b/src/main/resources/images/DaDuke.png new file mode 100644 index 0000000000000000000000000000000000000000..d893658717e29b50b4ceedada235d9f75835a118 GIT binary patch literal 32657 zcmV)5K*_&}P)Zf>Tg`t%N;{PE9Y2%-o7`CdniQG#9szpJX+ zcrVK`zK7pG^!n{1T{qo3os(XNkTqW0IXIfGihv^wpO4cHg6YjrzS7VYZJZVWev% z!fK9RcD(ntf zCxMCmC7oRZecuOe6J~p&f5@?I;U2zE;O2T?Vy_8UZ1S4i=b>l%q0jeYAI+i(>K zsIun-!&|SPodfa+5u7Z5yhtd`XRjxuF+Ww~1H4xg)(?GXYLo{q2VPiixh(3*`0iyFHj`V{p-_+Q4jWKC=o6ohr zW)q;Nb7IxtY}qD4RyBpAMv`rR!YytU)sgEIa8F)wX(O<=RwjYY+sLdy0`5o0>=a zd(GePvuhIc}2|`2Y7OgN%4u~XV>q*3e$65qJ;}bK0Li-Wh%~iQn_FhV_*O6|& z$E%S!>BN;~l+|jbw5B2<783HDuPYE-T1Z)&EZTFhZGIj)nseO*|7}7`Vz4%vMl&l& z!c*D(>n3|ulhD`D1FzG)Tik79GgrpJ#HE0O)y{gM#c%L1=xtu`A<9oj(;}Q6cpHb= zIjOSNTO3vD|G|N_tH+^nj?I`D4+@;j;9`s4!*lY>X2_|khHWO LGkWs%c&z?S( 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 z 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 KMNUMnLSTa5`eeEQ literal 0 HcmV?d00001 From 02ea18b497a44826facdff6e318c0a56809b184d Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Thu, 1 Sep 2022 16:43:00 +0800 Subject: [PATCH 59/73] Update Duke and Ui according to gui changes --- src/main/java/duke/Duke.java | 35 +++++++++++++++-------------------- src/main/java/util/Ui.java | 9 ++++----- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java index c6cdad7066..8cff787d56 100644 --- a/src/main/java/duke/Duke.java +++ b/src/main/java/duke/Duke.java @@ -1,13 +1,13 @@ package duke; -import java.util.Scanner; - import command.Command; import exception.DukeException; +import gui.DukeGui; +import javafx.application.Application; +import javafx.application.Platform; import tasklist.TaskList; import util.Parser; import util.Storage; -import util.Ui; /** * Entry point of the application that initialises and run the app. @@ -26,27 +26,22 @@ public Duke(String filePath) { storage.load(dukelist); } - /** - * Initialises and runs the Duke application - */ - public void run() { - Ui.printIntroMessage(); - boolean isTerminated = false; - Scanner sc = new Scanner(System.in); - - while (!isTerminated) { - try { - String nextLine = sc.nextLine(); - Command cmd = Parser.parseInputLine(nextLine); - cmd.execute(dukelist, storage); - isTerminated = cmd.getIsTerminated(); - } catch (DukeException e) { - System.out.println(Ui.formatLinesIntoParagraph(e.errorMessage())); + public String getResponse(String input) { + try { + Command cmd = Parser.parseInputLine(input); + cmd.execute(dukelist, storage); + if (cmd.getIsTerminated()) { + Platform.exit(); } + return cmd.getOutputMessage(); + } catch (DukeException e) { + return e.errorMessage(); + } catch (Exception e) { + return e.getMessage(); } } public static void main(String[] args) { - new Duke("data/saveFile.txt").run(); + Application.launch(DukeGui.class, args); } } diff --git a/src/main/java/util/Ui.java b/src/main/java/util/Ui.java index 9410a53441..93f7d90d83 100644 --- a/src/main/java/util/Ui.java +++ b/src/main/java/util/Ui.java @@ -13,7 +13,7 @@ public class Ui { * @return Formatted string to be printed */ public static String formatLine(String input) { - return "\t " + input + "\n"; + return input + "\n"; } /** @@ -39,17 +39,16 @@ public static String formatLinesIntoParagraph(String... lines) { res += formatLine(line); } - return formatParagraph(res); + return res; } /** * Prints the introduction message when starting the app */ - public static void printIntroMessage() { + public static String getIntroMessage() { String introParagraph = Ui.formatLine("Hello! I'm duke.") + Ui.formatLine("What can I do for you?"); - String formattedIntro = Ui.formatParagraph(introParagraph); - System.out.println(formattedIntro); + return introParagraph; } } From 61e5dec3eb0c27de525e97cb778122c4fc96d39d Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 7 Sep 2022 15:35:06 +0800 Subject: [PATCH 60/73] Add equals method for Date Time classes --- src/main/java/date/Date.java | 15 +++++++++++++++ src/main/java/date/DeadlineDateTime.java | 15 +++++++++++++++ src/main/java/date/EventDateTime.java | 17 +++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/src/main/java/date/Date.java b/src/main/java/date/Date.java index 2b33a05dda..79daa3ae18 100644 --- a/src/main/java/date/Date.java +++ b/src/main/java/date/Date.java @@ -32,4 +32,19 @@ public String toString() { public String encode() { return date.toString(); } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof Date) { + Date other = (Date) o; + return other.date.equals(this.date); + } + return false; + } } diff --git a/src/main/java/date/DeadlineDateTime.java b/src/main/java/date/DeadlineDateTime.java index 5cfe51ae5d..ab53bf15e6 100644 --- a/src/main/java/date/DeadlineDateTime.java +++ b/src/main/java/date/DeadlineDateTime.java @@ -74,4 +74,19 @@ public String encode() { String formattedTime = time.format(DateTimeFormatter.ofPattern(timeColonPattern)); return super.encode() + '|' + formattedTime; } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof DeadlineDateTime) { + DeadlineDateTime other = (DeadlineDateTime) o; + return super.equals(o) && other.time.equals(this.time); + } + return false; + } } diff --git a/src/main/java/date/EventDateTime.java b/src/main/java/date/EventDateTime.java index 5c941993ca..32086c301b 100644 --- a/src/main/java/date/EventDateTime.java +++ b/src/main/java/date/EventDateTime.java @@ -81,4 +81,21 @@ public String encode() { String formattedEndTime = endTime.format(DateTimeFormatter.ofPattern(timeColonPattern)); return super.encode() + '|' + formattedStartTime + '|' + formattedEndTime; } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof EventDateTime) { + EventDateTime other = (EventDateTime) o; + return super.equals(o) + && other.startTime.equals(this.startTime) + && other.endTime.equals(this.endTime); + } + return false; + } } From 726da86087b624fb0bef4339da38e003956f5c6d Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 7 Sep 2022 15:35:38 +0800 Subject: [PATCH 61/73] Add equals method for Task classes --- src/main/java/task/Deadline.java | 15 +++++++++++++++ src/main/java/task/Event.java | 15 +++++++++++++++ src/main/java/task/Task.java | 15 +++++++++++++++ src/main/java/task/Todo.java | 14 ++++++++++++++ 4 files changed, 59 insertions(+) diff --git a/src/main/java/task/Deadline.java b/src/main/java/task/Deadline.java index a62cede683..616bc7406a 100644 --- a/src/main/java/task/Deadline.java +++ b/src/main/java/task/Deadline.java @@ -37,4 +37,19 @@ public String encode() { int markedStatus = getIsMarked() ? 1 : 0; return String.format("D,%d,%s,%s\n", markedStatus, getTaskItem(), deadline.encode()); } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof Deadline) { + Deadline other = (Deadline) o; + return super.equals(o) && other.deadline.equals(this.deadline); + } + return false; + } } diff --git a/src/main/java/task/Event.java b/src/main/java/task/Event.java index 8aafaf76df..31abe8884e 100644 --- a/src/main/java/task/Event.java +++ b/src/main/java/task/Event.java @@ -37,4 +37,19 @@ public String encode() { int markedStatus = getIsMarked() ? 1 : 0; return String.format("E,%d,%s,%s\n", markedStatus, getTaskItem(), eventTiming.encode()); } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof Event) { + Event other = (Event) o; + return super.equals(o) && other.eventTiming.equals(this.eventTiming); + } + return false; + } } diff --git a/src/main/java/task/Task.java b/src/main/java/task/Task.java index 5e2c0e7dae..5ac79b03d1 100644 --- a/src/main/java/task/Task.java +++ b/src/main/java/task/Task.java @@ -44,4 +44,19 @@ protected String getTaskItem() { * @return A string encoding of the task to be stored in the save file */ public abstract String encode(); + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof Task) { + Task other = (Task) o; + return other.taskItem.strip().equals(this.taskItem.strip()); + } + return false; + } } diff --git a/src/main/java/task/Todo.java b/src/main/java/task/Todo.java index 8849d942e7..048f4f5ae2 100644 --- a/src/main/java/task/Todo.java +++ b/src/main/java/task/Todo.java @@ -44,4 +44,18 @@ public String encode() { int markedStatus = getIsMarked() ? 1 : 0; return String.format("T,%d,%s\n", markedStatus, getTaskItem()); } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof Todo) { + return super.equals(o); + } + return false; + } } From fdce8bbbe71734c4f5c0061787dd3e202302a278 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 7 Sep 2022 15:36:13 +0800 Subject: [PATCH 62/73] Implement check for duplicated tasks in TaskList --- src/main/java/tasklist/TaskList.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/tasklist/TaskList.java b/src/main/java/tasklist/TaskList.java index 22cb485f54..148dbff03c 100644 --- a/src/main/java/tasklist/TaskList.java +++ b/src/main/java/tasklist/TaskList.java @@ -20,6 +20,9 @@ public class TaskList { * @return The same task that is passed in */ public Task addTask(Task taskItem) { + if (this.list.contains(taskItem)) { + return null; + } this.list.add(taskItem); return taskItem; } From 49f846a9d542c646a4f4eb9b0af66f44d37ce9a4 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 7 Sep 2022 15:37:13 +0800 Subject: [PATCH 63/73] Update AddTaskCommand to account for duplicated tasks --- src/main/java/command/AddTaskCommand.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/command/AddTaskCommand.java b/src/main/java/command/AddTaskCommand.java index 80f30780c1..56a27df7bc 100644 --- a/src/main/java/command/AddTaskCommand.java +++ b/src/main/java/command/AddTaskCommand.java @@ -22,14 +22,22 @@ public AddTaskCommand(Task taskItem) { */ @Override public void execute(TaskList list, Storage storage) { - String task = " " + list.addTask(this.taskItem); + Task task = list.addTask(this.taskItem); + if (task == null) { + setOutputMessage(Ui.formatLinesIntoParagraph( + "This task has already been added to the list previously." + )); + return; + } + assert task != null; + String taskDescription = " " + task.toString(); String startLine = "Got it. I've added this task:"; String endLine = String.format( "Now you have %d tasks in the list.", list.getTaskCount()); setOutputMessage(Ui.formatLinesIntoParagraph( startLine, - task, + taskDescription, endLine )); } From e92068881437ee5ff950353611c2de54574de326 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 7 Sep 2022 15:38:08 +0800 Subject: [PATCH 64/73] Rectify error in date format for INVALID_EVENT_DATETIME_FORMAT Date format for event datetime is `yyyy-mm-dd hh:mm:ss hh:mm:ss`, not `yyyy-mm hh:mm:ss hh:mm:ss hh:mm:ss`. This has been rectified in this commit. --- src/main/java/exception/DukeException.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/exception/DukeException.java b/src/main/java/exception/DukeException.java index 3113bd7699..53c686adc5 100644 --- a/src/main/java/exception/DukeException.java +++ b/src/main/java/exception/DukeException.java @@ -38,7 +38,7 @@ public String errorMessage() { break; case INVALID_EVENT_DATETIME_FORMAT: dateFormat = "\t Please ensure date time is of the " - + "following format: yyyy-mm-dd hh:mm:ss hh:mm:ss hh:mm:ss"; + + "following format: yyyy-mm-dd hh:mm:ss hh:mm:ss"; errorMsg = "OOPS!!! Unable to parse date time for event.\n" + dateFormat; break; default: From a704a9da7951bfb45c4a9fb7762a10cb92a7f73a Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 7 Sep 2022 14:52:32 +0800 Subject: [PATCH 65/73] Add assertions after validating args where appropriate Added validations after validating arguments/format for Todo arguments, EventDateTime, and DeadlineDateTime. --- src/main/java/date/DeadlineDateTime.java | 1 + src/main/java/date/EventDateTime.java | 1 + src/main/java/util/Parser.java | 1 + 3 files changed, 3 insertions(+) diff --git a/src/main/java/date/DeadlineDateTime.java b/src/main/java/date/DeadlineDateTime.java index 5cfe51ae5d..b72e83df45 100644 --- a/src/main/java/date/DeadlineDateTime.java +++ b/src/main/java/date/DeadlineDateTime.java @@ -32,6 +32,7 @@ public static DeadlineDateTime parseDate(String dateTime) throws DukeException { if (splitted.length < 2 || splitted[0].strip().equals("") || splitted[1].strip().equals("")) { throw new DukeException(DukeException.ErrorCode.INVALID_DEADLINE_DATETIME_FORMAT); } + assert splitted.length >= 2 : "Date time not formatted properly"; try { return new DeadlineDateTime(splitted[0], splitted[1]); } catch (DateTimeParseException e) { diff --git a/src/main/java/date/EventDateTime.java b/src/main/java/date/EventDateTime.java index 5c941993ca..0d8088a45e 100644 --- a/src/main/java/date/EventDateTime.java +++ b/src/main/java/date/EventDateTime.java @@ -37,6 +37,7 @@ public static EventDateTime parseDate(String dateTime) throws DukeException { || splitted[2].strip().equals("")) { throw new DukeException(DukeException.ErrorCode.INVALID_EVENT_DATETIME_FORMAT); } + assert splitted.length >= 3 : "Date time not properly formatted"; try { return new EventDateTime(splitted[0], splitted[1], splitted[2]); } catch (DateTimeParseException e) { diff --git a/src/main/java/util/Parser.java b/src/main/java/util/Parser.java index ebced720b0..e308f7bf27 100644 --- a/src/main/java/util/Parser.java +++ b/src/main/java/util/Parser.java @@ -57,6 +57,7 @@ public static Command parseInputLine(String inputLine) throws DukeException { break; case "todo": Todo.validateInput(splitted); + assert splitted.length >= 2 : "No of arguments should be more than 1."; Task todo = new Todo(splitted[1]); cmd = new AddTaskCommand(todo); break; From 88006fa7c9f3bb1e611edb9836718862f4276180 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 7 Sep 2022 15:04:34 +0800 Subject: [PATCH 66/73] Refactor string concatenation to use StringBuilder instead There were a few cases where String concatenation was used within a loop instead of StringBuilder, which is not ideal due to performance reasons. This was fixed in this commit. --- src/main/java/command/FindSearchTextCommand.java | 6 +++--- src/main/java/tasklist/TaskList.java | 6 +++--- src/main/java/util/Ui.java | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/command/FindSearchTextCommand.java b/src/main/java/command/FindSearchTextCommand.java index 37fc3c6073..37d098c71e 100644 --- a/src/main/java/command/FindSearchTextCommand.java +++ b/src/main/java/command/FindSearchTextCommand.java @@ -37,10 +37,10 @@ public void execute(TaskList list, Storage storage) { return; } - String res = ""; + StringBuilder res = new StringBuilder(); for (String match : matchedTasks) { - res += Ui.formatLine(match); + res.append(Ui.formatLine(match)); } - setOutputMessage(res); + setOutputMessage(res.toString()); } } diff --git a/src/main/java/tasklist/TaskList.java b/src/main/java/tasklist/TaskList.java index 22cb485f54..cf0e223e90 100644 --- a/src/main/java/tasklist/TaskList.java +++ b/src/main/java/tasklist/TaskList.java @@ -32,12 +32,12 @@ public Task addTask(Task taskItem) { */ @Override public String toString() { - String res = Ui.formatLine("Here are the tasks in your list:"); + StringBuilder res = new StringBuilder(Ui.formatLine("Here are the tasks in your list:")); for (int i = 0; i < this.list.size(); i++) { String nextListItem = String.format("%d.%s", i + 1, this.list.get(i)); - res += Ui.formatLine(nextListItem); + res.append(Ui.formatLine(nextListItem)); } - return res; + return res.toString(); } /** diff --git a/src/main/java/util/Ui.java b/src/main/java/util/Ui.java index 93f7d90d83..062d063950 100644 --- a/src/main/java/util/Ui.java +++ b/src/main/java/util/Ui.java @@ -34,12 +34,12 @@ public static String formatParagraph(String paragraph) { * @return Prettified block of text to be printed */ public static String formatLinesIntoParagraph(String... lines) { - String res = ""; + StringBuilder res = new StringBuilder(); for (String line : lines) { - res += formatLine(line); + res.append(formatLine(line)); } - return res; + return res.toString(); } /** From 6f82246223423946f91c94fd718b1c5c12663c8f Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 7 Sep 2022 16:49:06 +0800 Subject: [PATCH 67/73] Enable assertions in gradle file --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index aaba8ad40a..8cb5d38375 100644 --- a/build.gradle +++ b/build.gradle @@ -45,6 +45,7 @@ shadowJar { run{ standardInput = System.in + enableAssertions = true } checkstyle { From 45d6b5367c590e993fbc7faf138dc63abca581da Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Sun, 18 Sep 2022 01:18:00 +0800 Subject: [PATCH 68/73] Add screenshot of app --- docs/Ui.png | Bin 0 -> 169434 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/Ui.png diff --git a/docs/Ui.png b/docs/Ui.png new file mode 100644 index 0000000000000000000000000000000000000000..227faca266a7a8303afdee371c196ac2797d1a72 GIT binary patch literal 169434 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 ECB2m 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 QuQC9Er>mdKI;Vst0Na%B!vFvP literal 0 HcmV?d00001 From ce3cfa90f3cf03f1a13e1491ec2ae7fdbdd5113c Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Sun, 18 Sep 2022 01:18:23 +0800 Subject: [PATCH 69/73] Update User Guide --- docs/README.md | 184 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 172 insertions(+), 12 deletions(-) diff --git a/docs/README.md b/docs/README.md index 8077118ebe..64a765c3f7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,29 +1,189 @@ # User Guide +## About +Duke is a desktop app designed for task management, optimized for use via +a Command-Line interface (CLI) while still having the benefits of a +Graphical-User Interface (GUI). If you can type fast, Duke is an efficient +program to manage all your tasks. + ## Features +- todo +- deadline +- event +- list +- mark +- unmark +- delete +- find +- bye -### Feature-ABC +## Adding Tasks -Description of the feature. +There are 3 types of tasks that can be added to Duke -### Feature-XYZ +1. Todo +2. Deadline +3. Event -Description of the feature. +### `todo` - Adds a Todo task to Duke list +Command format: `todo TODO_ITEM` -## Usage +This adds a todo task to Duke list, along with a short note corresponding to `TODO_ITEM`. -### `Keyword` - Describe action +#### Example of Usage: -Describe the action and its outcome. +Input: +``` +todo sweep the floor +``` -Example of usage: +Output: +``` +Got it. I've added this task: +[T][ ] sweep the floor +Now you have 2 tasks in the list. +``` +### `deadline` - Adds a Deadline task to Duke list +Command format: `deadline DEADLINE_ITEM /by DATE TIME` -`keyword (optional arguments)` +This adds a deadline task to Duke list, that is to be done by `DATE` and at time `TIME`. +Note that `DATE` is of the format `YYYY-MM-DD` and `TIME` is of the format `hh:mm:ss`. -Expected outcome: +#### Example of Usage: -Description of the outcome. +Input: +``` +deadline finish ip /by 2022-09-19 23:59:59 +``` + +Output: +``` +Got it. I've added this task: +[D][ ] finish ip (by: Sep 19 2022 23:59:59) +Now you have 2 tasks in the list. +``` + +### `event` - Adds an Event task to Duke list +Command format: `event EVENT_ITEM /at DATE START_TIME END_TIME` + +This adds an event task to Duke list, that occurs on `DATE` from `START_TIME` to `END_TIME`. + +Note that `DATE` is of the format `YYYY-MM-DD` and both `START_TIME` and `END_TIME` are of the format `hh:mm:ss`. + +#### Example of Usage: + +Input: +``` +event cs2100 midterm /at 2022-10-08 09:00:00 10:30:00 +``` +Output: ``` -expected output +Got it. I've added this task: +[E][ ] finish ip (at: Oct 8 2022 09:00:00 - 10:30:00) +Now you have 2 tasks in the list. +``` + +## Managing Tasks +### `list` - List all tasks in Duke list +Command format: `list` + +Returns a list of all tasks currently in Duke list. + +#### Example of Usage: + +Input: +``` +list +``` + +Output: +``` +Here are the tasks in your list: +1. [T][ ] sweep the floor +2. [D][ ] finish ip (by: Sep 19 2022 23:59:59) +3. [E][ ] finish ip (at: Oct 8 2022 09:00:00 - 10:30:00) +``` +### `mark` - Marks a specified task as completed +Command format: `mark INDEX` + +Marks the task stored at `INDEX` in Duke list as completed. + +#### Example of Usage: + +Input: +``` +mark 1 +``` + +Output: ``` +Nice! I've marked this task as done: + [T][X] sweep the floor +``` +### `unmark` - Unmarks a specified task as incomeplete +Command format: `unmark INDEX` + +Unmarks the task stored at `INDEX` in Duke list as incomplete. + +#### Example of Usage: + +Input: +``` +unmark 1 +``` + +Output: +``` +OK, I've marked this task as not done yet: + [T][ ] sweep the floor +``` +### `delete` - Deletes a specified task from Duke list +Command format: `delete INDEX` + +Deletes the task stored at `INDEX` in Duke list. + +#### Example of Usage: + +Input: +``` +delete 3 +``` + +Output: +``` +Noted, I've removed this task: + [E][ ] finish ip (at: Oct 8 2022 09:00:00 - 10:30:00) +Now you have 2 tasks in the list. +``` +### `find` - Searches for tasks that match a given string +Command format: `find SEARCH_STRING` + +Searches for all tasks that match `SEARCH_STRING` + +#### Example of Usage: + +Input: +``` +find sweep +``` + +Output: +``` +1. [T][ ] sweep the floor +``` +### `bye` - Exits the application and saves all tasks in Duke list +Command format: `bye` + +Exits the application and saves all tasks currently within Duke list. + +#### Example of Usage: + +Input: +``` +bye +``` + +Output: + +The application terminates and the window closes. \ No newline at end of file From 54e1d55520a8b01ecc04e134489624c3ddd3a95e Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Tue, 20 Sep 2022 23:39:18 +0800 Subject: [PATCH 70/73] Update tests --- src/test/java/task/DeadlineTest.java | 6 +++--- src/test/java/task/EventTest.java | 6 +++--- src/test/java/task/TodoTest.java | 22 +++++++++------------- src/test/java/tasklist/TaskListTest.java | 24 +++++++++++------------- 4 files changed, 26 insertions(+), 32 deletions(-) diff --git a/src/test/java/task/DeadlineTest.java b/src/test/java/task/DeadlineTest.java index 398d523c86..b5ca882876 100644 --- a/src/test/java/task/DeadlineTest.java +++ b/src/test/java/task/DeadlineTest.java @@ -12,7 +12,7 @@ class DeadlineTest { @Test @DisplayName("Test for toString() method of unmarked deadline") - void testToString_for_unmarked_deadline() throws DukeException { + void test_unmarked_deadline() throws DukeException { DeadlineDateTime date = DeadlineDateTime.parseDate("2022-01-01 00:00:00"); Deadline test = new Deadline("Testing!", date); String expected = "[D][ ] Testing! (by: Jan 1 2022 00:00:00)"; @@ -21,7 +21,7 @@ void testToString_for_unmarked_deadline() throws DukeException { @Test @DisplayName("Test for toString() method of marked deadline") - void testToString_for_marked_deadline() throws DukeException { + void test_marked_deadline() throws DukeException { DeadlineDateTime date = DeadlineDateTime.parseDate("2022-01-01 00:00:00"); Deadline test = new Deadline("Testing!", date); test.setIsMarked(true); @@ -37,4 +37,4 @@ void encode() throws DukeException { String expected = "D,0,Testing!,2022-01-01|00:00:00\n"; assertEquals(expected, test.encode()); } -} \ No newline at end of file +} diff --git a/src/test/java/task/EventTest.java b/src/test/java/task/EventTest.java index ef651907a8..9f13aa8023 100644 --- a/src/test/java/task/EventTest.java +++ b/src/test/java/task/EventTest.java @@ -12,7 +12,7 @@ class EventTest { @Test @DisplayName("Test for toString() method of unmarked event") - void testToString_for_unmarked_event() throws DukeException { + void test_unmarked_event() throws DukeException { EventDateTime date = EventDateTime.parseDate("2022-01-01 00:00:00 12:00:00"); Event test = new Event("Testing!", date); String expected = "[E][ ] Testing! (at: Jan 1 2022 00:00:00 - 12:00:00)"; @@ -21,7 +21,7 @@ void testToString_for_unmarked_event() throws DukeException { @Test @DisplayName("Test for toString() method of marked event") - void testToString_for_marked_event() throws DukeException { + void test_marked_event() throws DukeException { EventDateTime date = EventDateTime.parseDate("2022-01-01 00:00:00 12:00:00"); Event test = new Event("Testing!", date); test.setIsMarked(true); @@ -37,4 +37,4 @@ void encode() throws DukeException { String expected = "E,0,Testing!,2022-01-01|00:00:00|12:00:00\n"; assertEquals(expected, test.encode()); } -} \ No newline at end of file +} diff --git a/src/test/java/task/TodoTest.java b/src/test/java/task/TodoTest.java index 5a947fd1ec..0dfc3aa013 100644 --- a/src/test/java/task/TodoTest.java +++ b/src/test/java/task/TodoTest.java @@ -12,7 +12,7 @@ class TodoTest { @Test @DisplayName("Test for toString() method of unmarked todo") - void testToString_for_unmarked_todo() { + void test_unmarked_todo() { Todo test = new Todo("Testing!"); String expected = "[T][ ] Testing!"; assertEquals(expected, test.toString()); @@ -20,25 +20,21 @@ void testToString_for_unmarked_todo() { @Test @DisplayName("Test validateInput throws exception when task item is not given") - void validateInput_throws_exception_when_input_length_less_than_two() { - String[] inputLengthLessThanOne = new String[] { - "Testing!" - }; + void validateInput_throws_exception() { + String[] inputLengthLessThanOne = new String[] {"Testing!"}; assertThrows( - DukeException.class, - () -> Todo.validateInput(inputLengthLessThanOne)); + DukeException.class, () -> Todo.validateInput(inputLengthLessThanOne)); } @Test @DisplayName("Test validateInput throws exception when task item is whitespace") - void validateInput_throws_exception_when_second_string_is_whitespace() { + void validateInput_throws_exception2() { String[] secondStringIsWhitespace = new String[] { - "Testing!", - " ", + "Testing!", + " ", }; assertThrows( - DukeException.class, - () -> Todo.validateInput(secondStringIsWhitespace)); + DukeException.class, () -> Todo.validateInput(secondStringIsWhitespace)); } @Test @@ -57,4 +53,4 @@ void encode_marked_todo() { String expected = "T,1,Testing!\n"; assertEquals(expected, test.encode()); } -} \ No newline at end of file +} diff --git a/src/test/java/tasklist/TaskListTest.java b/src/test/java/tasklist/TaskListTest.java index 9ad3d3ef82..9a49292388 100644 --- a/src/test/java/tasklist/TaskListTest.java +++ b/src/test/java/tasklist/TaskListTest.java @@ -20,29 +20,27 @@ void addTask() { TaskList test = new TaskList(); Task stub = new TaskStub(); Task returnedStub = test.addTask(stub); - assertAll( - () -> assertSame(returnedStub, stub), - () -> assertSame(stub, test.getItem(1)) + assertAll(() -> assertSame(returnedStub, stub), () -> assertSame(stub, test.getItem(1)) ); } @Test @DisplayName("Testing toString() when list is empty") - void testToString_when_list_is_empty() { + void test_empty_list() { TaskList test = new TaskList(); - String expected = "\t " + "Here are the tasks in your list:" + "\n"; + String expected = "Here are the tasks in your list:" + "\n"; assertEquals(expected, test.toString()); } @Test @DisplayName("Testing toString() when list is not empty") - void testToString_when_list_is_not_empty() { + void test_nonempty_list() { TaskList test = new TaskList(); Task stub = new TaskStub(); test.addTask(stub); - String taskItemString = String.format("\t 1.%s\n", stub.toString()); - String expected = "\t " + "Here are the tasks in your list:" + "\n" + String taskItemString = String.format("1.%s\n", stub.toString()); + String expected = "Here are the tasks in your list:" + "\n" + taskItemString; assertEquals(expected, test.toString()); } @@ -75,29 +73,29 @@ void unmarkItem() { @Test @DisplayName("Testing deleteItem()") - void deleteItem_giving_empty_list() { + void deleteItem_resulting_emptyList() { TaskList test = new TaskList(); Task stub = new TaskStub(); test.addTask(stub); test.deleteItem(1); - String expected = "\t " + "Here are the tasks in your list:" + "\n"; + String expected = "Here are the tasks in your list:" + "\n"; assertEquals(expected, test.toString()); } @Test @DisplayName("Testing getTaskCount() when list is empty") - void getTaskCount_when_list_is_empty() { + void getTaskCount_empty_list() { TaskList test = new TaskList(); assertEquals(test.getTaskCount(), 0); } @Test @DisplayName("Testing getTaskCount() when list has one task") - void getTaskCount_when_list_has_one_task() { + void getTaskCount_nonempty_list() { TaskList test = new TaskList(); Task stub = new TaskStub(); test.addTask(stub); assertEquals(test.getTaskCount(), 1); } -} \ No newline at end of file +} From ff6fdad2dc2604675773b87b1b2d74348344b0f6 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Tue, 20 Sep 2022 23:39:46 +0800 Subject: [PATCH 71/73] Update build.gradle --- build.gradle | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8cb5d38375..132df75e32 100644 --- a/build.gradle +++ b/build.gradle @@ -11,13 +11,16 @@ repositories { } javafx { - version = "18.0.2" + version = "11" modules = [ 'javafx.controls' ] } 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' + runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:win" + runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:linux" + runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:mac" } test { From cec587b251cd92de6fc26a220a1fc7117675388e Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Tue, 20 Sep 2022 23:42:00 +0800 Subject: [PATCH 72/73] Update user guide --- docs/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/README.md b/docs/README.md index 64a765c3f7..5ff74a9d16 100644 --- a/docs/README.md +++ b/docs/README.md @@ -25,6 +25,12 @@ There are 3 types of tasks that can be added to Duke 2. Deadline 3. Event +A task is formatted as follows: + +`[T][ ] TASK_ITEM` + +The first box `[T]` indicates the type of task, while the second `[ ]` indicates whether the task has been marked as completed. + ### `todo` - Adds a Todo task to Duke list Command format: `todo TODO_ITEM` From af1cd6e714ebf256a2e35facaedb3811b5a03a81 Mon Sep 17 00:00:00 2001 From: bryanljx1 Date: Wed, 21 Sep 2022 00:11:11 +0800 Subject: [PATCH 73/73] Update gradle.build --- build.gradle | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index 132df75e32..d03b2948d6 100644 --- a/build.gradle +++ b/build.gradle @@ -10,17 +10,24 @@ repositories { mavenCentral() } -javafx { - version = "11" - modules = [ 'javafx.controls' ] -} - 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' - runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:win" - runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:linux" - runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:mac" + + String javaFxVersion = '12' + + 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 {