From 556af3f47a96b32898ab4cdbd65b16486a4871e8 Mon Sep 17 00:00:00 2001 From: damithc Date: Mon, 25 May 2020 00:58:18 +0800 Subject: [PATCH 01/42] 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 2abf484d66868a310b8801e51252015e725ca9d8 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Mon, 30 Jan 2023 20:01:01 +0800 Subject: [PATCH 02/42] Add Increment Level-1 --- src/main/java/Duke.java | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 5d313334cc..6fd0ed9ab8 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,10 +1,27 @@ +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); + String logo = "\t ____ _ \n" + + "\t | _ \\ _ _| | _____ \n" + + "\t | | | | | | | |/ / _ \\\n" + + "\t | |_| | |_| | < __/\n" + + "\t |____/ \\__,_|_|\\_\\___|\n"; + System.out.println(logo); + System.out.println("\t Hello! I'm Duke"); + System.out.println("\t What can I do for you?"); + + Scanner input = new Scanner(System.in); + + while (true) { + String command = input.nextLine(); + + if (command.equals("bye")) { + System.out.println("\t Bye. Hope to see you again soon!"); + break; + } else { + System.out.println("\t " + command); + } + } } } From 6e6c66ff8ba9638a710263490134605b3405e72a Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Mon, 30 Jan 2023 20:12:52 +0800 Subject: [PATCH 03/42] Add Increment Level-2 --- src/main/java/Duke.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 6fd0ed9ab8..1664295fec 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -11,6 +11,9 @@ public static void main(String[] args) { System.out.println("\t Hello! I'm Duke"); System.out.println("\t What can I do for you?"); + String[] tasks = new String[100]; + int taskIndex = 0; + Scanner input = new Scanner(System.in); while (true) { @@ -19,9 +22,16 @@ public static void main(String[] args) { if (command.equals("bye")) { System.out.println("\t Bye. Hope to see you again soon!"); break; + } else if (command.equals("list")) { + for (int i = 0; i < taskIndex; i++) { + System.out.println("\t " + (i + 1) + ". " + tasks[i]); + } } else { - System.out.println("\t " + command); + tasks[taskIndex] = command; + taskIndex++; + System.out.println("\t added: " + command); } } } } + From 8e390d2519c3fc475249b162d1460ce74aa67935 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Mon, 30 Jan 2023 20:18:22 +0800 Subject: [PATCH 04/42] Add Increment Level-3 with a new class Task --- src/main/java/Duke.java | 47 ++++++++++++++++++++++++++++++++--------- src/main/java/Task.java | 29 +++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 src/main/java/Task.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 1664295fec..8537ec6aa5 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,7 +1,12 @@ import java.util.Scanner; public class Duke { - public static void main(String[] args) { + + private Scanner input = new Scanner(System.in); + private Task tasks[] = new Task[100]; + private int size = 0; + + public void start() { String logo = "\t ____ _ \n" + "\t | _ \\ _ _| | _____ \n" + "\t | | | | | | | |/ / _ \\\n" @@ -10,28 +15,50 @@ public static void main(String[] args) { System.out.println(logo); System.out.println("\t Hello! I'm Duke"); System.out.println("\t What can I do for you?"); + } - String[] tasks = new String[100]; - int taskIndex = 0; + public void mark(String command) { + int taskindex = Integer.parseInt(command.split(" ")[1]) - 1; + tasks[taskindex].mark(); + } + + public void unmark(String command) { + int taskindex = Integer.parseInt(command.split(" ")[1]) - 1; + tasks[taskindex].unmark(); + } - Scanner input = new Scanner(System.in); + public void list() { + for (int i = 0; i < size; i++) { + System.out.print("\t " + (i + 1) + "."); + tasks[i].showTask(); + } + } + public void run() { + start(); while (true) { String command = input.nextLine(); - if (command.equals("bye")) { System.out.println("\t Bye. Hope to see you again soon!"); break; } else if (command.equals("list")) { - for (int i = 0; i < taskIndex; i++) { - System.out.println("\t " + (i + 1) + ". " + tasks[i]); - } + list(); + } else if (command.startsWith("mark")) { + mark(command); + } else if (command.startsWith("unmark")) { + unmark(command); } else { - tasks[taskIndex] = command; - taskIndex++; + tasks[size] = new Task(command); + size++; System.out.println("\t added: " + command); } } } + + public static void main(String[] args) { + Duke duke = new Duke(); + duke.run(); + } } + diff --git a/src/main/java/Task.java b/src/main/java/Task.java new file mode 100644 index 0000000000..dd9f1bf2a6 --- /dev/null +++ b/src/main/java/Task.java @@ -0,0 +1,29 @@ +public class Task { + protected String description; + protected boolean isDone; + + public Task(String description) { + this.description = description; + this.isDone = false; + } + + public String getStatusIcon() { + return (isDone ? "X" : " "); + } + + public void mark() { + this.isDone = true; + System.out.println("\t Nice! I've marked this task as done:\n" + + "\t\t [X] " + this.description); + } + + public void unmark() { + this.isDone = false; + System.out.println("\t OK, I've marked this task as not done yet:\n" + + "\t\t [ ] " + this.description); + } + + public void showTask() { + System.out.println(" [" + getStatusIcon() + "] " + this.description); + } +} From 63deb9fa967fdaab493a2a93721469490441416f Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Tue, 31 Jan 2023 23:32:36 +0800 Subject: [PATCH 05/42] Add Increments Level-4 --- src/main/java/Deadline.java | 13 +++++++ src/main/java/Duke.java | 73 +++++++++++++++++++++++++++++-------- src/main/java/Event.java | 14 +++++++ src/main/java/Task.java | 9 +++-- src/main/java/Todo.java | 10 +++++ 5 files changed, 100 insertions(+), 19 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..573b7b8793 --- /dev/null +++ b/src/main/java/Deadline.java @@ -0,0 +1,13 @@ +public class Deadline extends Task { + protected String by; + + public Deadline(String description, String by) { + super(description); + this.by = by; + } + + @Override + public String toString() { + return "[D]" + super.toString() + " (by: " + by + ")"; + } +} diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 8537ec6aa5..642513c1b6 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -4,7 +4,7 @@ public class Duke { private Scanner input = new Scanner(System.in); private Task tasks[] = new Task[100]; - private int size = 0; + private int taskIndex = 0; public void start() { String logo = "\t ____ _ \n" @@ -14,24 +14,60 @@ public void start() { + "\t |____/ \\__,_|_|\\_\\___|\n"; System.out.println(logo); System.out.println("\t Hello! I'm Duke"); - System.out.println("\t What can I do for you?"); + System.out.println("\t What can I do for you?\n"); + } + + public void display() { + System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); } public void mark(String command) { - int taskindex = Integer.parseInt(command.split(" ")[1]) - 1; - tasks[taskindex].mark(); + int index = Integer.parseInt(command.split(" ")[1]) - 1; + tasks[index].mark(); } public void unmark(String command) { - int taskindex = Integer.parseInt(command.split(" ")[1]) - 1; - tasks[taskindex].unmark(); + int index = Integer.parseInt(command.split(" ")[1]) - 1; + tasks[index].unmark(); } public void list() { - for (int i = 0; i < size; i++) { - System.out.print("\t " + (i + 1) + "."); - tasks[i].showTask(); + for (int i = 0; i < taskIndex; i++) { + System.out.print("\t " + (i + 1) + "." + tasks[i].toString() + "\n"); } + System.out.print("\n"); + } + + public void addTask(Task task) { + tasks[taskIndex] = task; + taskIndex++; + System.out.println("\t Got it. I've added this task:\n" + + "\t\t "+ tasks[taskIndex - 1].toString() + + "\n\t Now you have " + taskIndex + " tasks in the list.\n"); + } + public void todo(String command) { + String description = command.split(" ", 2)[1]; + Todo todo = new Todo(description); + addTask(todo); + } + + public void deadline(String command) { + String info[] = command.split(" ", 2)[1].split(" /by "); + String description = info[0]; + String by = info[1]; + Deadline deadline = new Deadline(description, by); + addTask(deadline); + } + + public void event(String command) { + String info[] = command.split(" ", 2)[1].split(" /from "); + String description = info[0]; + String dates[] = info[1].split(" /to "); + String from = dates[0]; + String to = dates[1]; + + Event event = new Event(description, from, to); + addTask(event); } public void run() { @@ -39,18 +75,27 @@ public void run() { while (true) { String command = input.nextLine(); if (command.equals("bye")) { + display(); System.out.println("\t Bye. Hope to see you again soon!"); break; } else if (command.equals("list")) { + display(); list(); } else if (command.startsWith("mark")) { + display(); mark(command); } else if (command.startsWith("unmark")) { + display(); unmark(command); - } else { - tasks[size] = new Task(command); - size++; - System.out.println("\t added: " + command); + } else if (command.startsWith("todo")) { + display(); + todo(command); + } else if (command.startsWith("deadline")) { + display(); + deadline(command); + } else if(command.startsWith("event")) { + display(); + event(command); } } } @@ -60,5 +105,3 @@ public static void main(String[] args) { duke.run(); } } - - diff --git a/src/main/java/Event.java b/src/main/java/Event.java new file mode 100644 index 0000000000..f4d12b14ca --- /dev/null +++ b/src/main/java/Event.java @@ -0,0 +1,14 @@ +public class Event extends Task{ + protected String from; + protected String to; + + public Event(String description, String from, String to) { + super(description); + this.from = from; + this.to = to; + } + @Override + public String toString() { + return "[E]" + super.toString() + " (from: " + from + " to: " + to + ")"; + } +} diff --git a/src/main/java/Task.java b/src/main/java/Task.java index dd9f1bf2a6..47704689a4 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -14,16 +14,17 @@ public String getStatusIcon() { public void mark() { this.isDone = true; System.out.println("\t Nice! I've marked this task as done:\n" - + "\t\t [X] " + this.description); + + "\t\t [X] " + this.description + "\n"); } public void unmark() { this.isDone = false; System.out.println("\t OK, I've marked this task as not done yet:\n" - + "\t\t [ ] " + this.description); + + "\t\t [ ] " + this.description + "\n"); } - public void showTask() { - System.out.println(" [" + getStatusIcon() + "] " + this.description); + @Override + public String toString() { + return " [" + getStatusIcon() + "] " + this.description; } } diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java new file mode 100644 index 0000000000..2a6fe09db2 --- /dev/null +++ b/src/main/java/Todo.java @@ -0,0 +1,10 @@ +public class Todo extends Task{ + public Todo(String description) { + super(description); + } + + @Override + public String toString() { + return "[T]" + super.toString(); + } +} From 638fe5e5bb68069984b99ea7b88e282bddcd0e30 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Tue, 31 Jan 2023 23:34:56 +0800 Subject: [PATCH 06/42] Add Increments for Automated Text UI Testing --- text-ui-test/EXPECTED.TXT | 61 +++++++++++++++++++++++++++++++++++---- text-ui-test/input.txt | 9 ++++++ text-ui-test/runtest.bat | 2 ++ 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 657e74f6e7..444e8ed366 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,7 +1,56 @@ -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: Sunday) + Now you have 2 tasks in the list. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + 1.[T] [ ] borrow book + 2.[D] [ ] return book (by: Sunday) + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Nice! I've marked this task as done: + [X] return book + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Got it. I've added this task: + [E] [ ] project meeting (from: Mon 2pm to: 4pm) + Now you have 3 tasks in the list. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Nice! I've marked this task as done: + [X] project meeting + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + OK, I've marked this task as not done yet: + [ ] return book + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + 1.[T] [ ] borrow book + 2.[D] [ ] return book (by: Sunday) + 3.[E] [X] project meeting (from: Mon 2pm to: 4pm) + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Bye. Hope to see you again soon! \ No newline at end of file diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e69de29bb2..c0eba47e75 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -0,0 +1,9 @@ +todo borrow book +deadline return book /by Sunday +list +mark 2 +event project meeting /from Mon 2pm /to 4pm +mark 3 +unmark 2 +list +bye diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index 0873744649..1873b3db23 100644 --- a/text-ui-test/runtest.bat +++ b/text-ui-test/runtest.bat @@ -8,6 +8,8 @@ if exist ACTUAL.TXT del ACTUAL.TXT REM compile the code into the bin folder javac -cp ..\src\main\java -Xlint:none -d ..\bin ..\src\main\java\*.java + + IF ERRORLEVEL 1 ( echo ********** BUILD FAILURE ********** exit /b 1 From fea77b039b6cb81237eac9ad5a46578129a2ee8a Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Wed, 1 Feb 2023 01:32:20 +0800 Subject: [PATCH 07/42] Add Increment Level-5 --- src/main/java/Duke.java | 125 +++++++++++++++++++++++-------- src/main/java/DukeException.java | 6 ++ 2 files changed, 98 insertions(+), 33 deletions(-) create mode 100644 src/main/java/DukeException.java diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 642513c1b6..068ec7cbd1 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -21,14 +21,36 @@ public void display() { System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); } - public void mark(String command) { - int index = Integer.parseInt(command.split(" ")[1]) - 1; - tasks[index].mark(); + public void mark(String command) throws DukeException{ + if (command.trim().equals("mark")) { + throw new DukeException("\t ☹ OOPS!!! The description of a mark cannot be empty.\n"); + } + try { + int index = Integer.parseInt(command.split(" ")[1]) - 1; + if (index + 1 > taskIndex || index < 0) { + throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); + } + tasks[index].mark(); + } catch (NumberFormatException ex) { + System.out.println("\t ☹ OOPS!!! Please input a valid number.\n"); + } } - public void unmark(String command) { - int index = Integer.parseInt(command.split(" ")[1]) - 1; - tasks[index].unmark(); + public void unmark(String command) throws DukeException{ + if (command.trim().equals("mark")) { + throw new DukeException("\t ☹ OOPS!!! The description of a unmark cannot be empty.\n"); + } + try { + int index = Integer.parseInt(command.split(" ")[1]) - 1; + if (index + 1 > taskIndex || index < 0) { + throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); + } else if (tasks[index].getStatusIcon().equals(" ")) { + throw new DukeException("\t ☹ OOPS!!! This task has not been marked yet.\n"); + } + tasks[index].unmark(); + } catch (NumberFormatException ex) { + System.out.println("\t ☹ OOPS!!! Please input a valid number.\n"); + } } public void list() { @@ -45,22 +67,51 @@ public void addTask(Task task) { + "\t\t "+ tasks[taskIndex - 1].toString() + "\n\t Now you have " + taskIndex + " tasks in the list.\n"); } - public void todo(String command) { + public void todo(String command) throws DukeException { + if (command.trim().equals("todo")) { + throw new DukeException("\t ☹ OOPS!!! The description of a todo cannot be empty.\n"); + } String description = command.split(" ", 2)[1]; Todo todo = new Todo(description); addTask(todo); } - public void deadline(String command) { - String info[] = command.split(" ", 2)[1].split(" /by "); + public void deadline(String command) throws DukeException { + if (command.trim().equals("deadline")) { + throw new DukeException("\t ☹ OOPS!!! The description of a deadline cannot be empty.\n"); + } else if (command.trim().contains(" /by ") == false) { + throw new DukeException("\t ☹ OOPS!!! There is no deadline date or the wrong format\n"); + } + + command = command.split(" ", 2)[1]; + if (command.startsWith("/by")) { + throw new DukeException("☹ OOPS!!! The description of a deadline cannot be empty.\n"); + } else if (command.endsWith("/by")) { + throw new DukeException(("☹ OOPS!!! The due date of a deadline cannot be empty.\n")); + } + + String info[] = command.split(" /by "); String description = info[0]; String by = info[1]; Deadline deadline = new Deadline(description, by); addTask(deadline); } - public void event(String command) { - String info[] = command.split(" ", 2)[1].split(" /from "); + public void event(String command) throws DukeException{ + command = command.trim(); + if (command.equals("event")) { + throw new DukeException("\t ☹ OOPS!!! The description of a event cannot be empty.\n"); + } else if (command.contains(" /from ") == false || command.contains(" /to ") == false) { + throw new DukeException("\t ☹ OOPS!!! The from date or due date of a deadline cannot be empty.\n" + + "\t Or the format is wrong.\n"); + } + + command = command.split(" ", 2)[1]; + if (command.startsWith("/from") || command.endsWith("/to") || command.contains("/from /to")) { + throw new DukeException("\t ☹ OOPS!!! The description, from date or due date of a event cannot be empty.\n"); + } + + String info[] = command.split(" /from "); String description = info[0]; String dates[] = info[1].split(" /to "); String from = dates[0]; @@ -74,32 +125,40 @@ public void run() { start(); while (true) { String command = input.nextLine(); - if (command.equals("bye")) { - display(); - System.out.println("\t Bye. Hope to see you again soon!"); - break; - } else if (command.equals("list")) { - display(); - list(); - } else if (command.startsWith("mark")) { - display(); - mark(command); - } else if (command.startsWith("unmark")) { - display(); - unmark(command); - } else if (command.startsWith("todo")) { - display(); - todo(command); - } else if (command.startsWith("deadline")) { - display(); - deadline(command); - } else if(command.startsWith("event")) { - display(); - event(command); + try { + if (command.equals("bye")) { + display(); + System.out.println("\t Bye. Hope to see you again soon!"); + break; + } else if (command.equals("list")) { + display(); + list(); + } else if (command.startsWith("mark")) { + display(); + mark(command); + } else if (command.startsWith("unmark")) { + display(); + unmark(command); + } else if (command.startsWith("todo")) { + display(); + todo(command); + } else if (command.startsWith("deadline")) { + display(); + deadline(command); + } else if(command.startsWith("event")) { + display(); + event(command); + } else { + display(); + System.out.println("\t ☹ OOPS!!! I'm sorry, but I don't know what that means.\n"); + } + } catch (DukeException e) { + System.out.println(e.getMessage()); } } } + public static void main(String[] args) { Duke duke = new Duke(); duke.run(); diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java new file mode 100644 index 0000000000..d2a5b3057e --- /dev/null +++ b/src/main/java/DukeException.java @@ -0,0 +1,6 @@ +public class DukeException extends Exception{ + + public DukeException(String message) { + super(message); + } +} From a6d87e4c4c403a658b6a1aa2ba90f2000473eb28 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Wed, 1 Feb 2023 02:10:40 +0800 Subject: [PATCH 08/42] Add Increment Level-6 --- src/main/java/Duke.java | 52 ++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 068ec7cbd1..9d9327c8b8 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,10 +1,10 @@ +import java.util.ArrayList; import java.util.Scanner; public class Duke { private Scanner input = new Scanner(System.in); - private Task tasks[] = new Task[100]; - private int taskIndex = 0; + private ArrayList tasks = new ArrayList<>(); public void start() { String logo = "\t ____ _ \n" @@ -27,10 +27,10 @@ public void mark(String command) throws DukeException{ } try { int index = Integer.parseInt(command.split(" ")[1]) - 1; - if (index + 1 > taskIndex || index < 0) { + if (index + 1 > tasks.size() || index < 0) { throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); } - tasks[index].mark(); + tasks.get(index).mark(); } catch (NumberFormatException ex) { System.out.println("\t ☹ OOPS!!! Please input a valid number.\n"); } @@ -42,30 +42,29 @@ public void unmark(String command) throws DukeException{ } try { int index = Integer.parseInt(command.split(" ")[1]) - 1; - if (index + 1 > taskIndex || index < 0) { + if (index + 1 > tasks.size() || index < 0) { throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); - } else if (tasks[index].getStatusIcon().equals(" ")) { + } else if (tasks.get(index).getStatusIcon().equals(" ")) { throw new DukeException("\t ☹ OOPS!!! This task has not been marked yet.\n"); } - tasks[index].unmark(); + tasks.get(index).unmark(); } catch (NumberFormatException ex) { System.out.println("\t ☹ OOPS!!! Please input a valid number.\n"); } } public void list() { - for (int i = 0; i < taskIndex; i++) { - System.out.print("\t " + (i + 1) + "." + tasks[i].toString() + "\n"); + for (int i = 0; i < tasks.size(); i++) { + System.out.print("\t " + (i + 1) + "." + tasks.get(i).toString() + "\n"); } System.out.print("\n"); } public void addTask(Task task) { - tasks[taskIndex] = task; - taskIndex++; + tasks.add(task); System.out.println("\t Got it. I've added this task:\n" - + "\t\t "+ tasks[taskIndex - 1].toString() - + "\n\t Now you have " + taskIndex + " tasks in the list.\n"); + + "\t\t "+ tasks.get(tasks.size() - 1).toString() + + "\n\t Now you have " + tasks.size() + " tasks in the list.\n"); } public void todo(String command) throws DukeException { if (command.trim().equals("todo")) { @@ -121,6 +120,26 @@ public void event(String command) throws DukeException{ addTask(event); } + public void delete(String command) throws DukeException { + command = command.trim(); + if (command.equals("delete")) { + throw new DukeException("\t ☹ OOPS!!! The description of a delete cannot be empty.\n"); + } + int index; + try { + index = Integer.parseInt(command.split(" ")[1]); + } catch (NumberFormatException ex) { + throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); + } + if (index < 1 || index > tasks.size()) { + throw new DukeException("\t ☹ OOPS!!! The input is out of range.\n"); + } + System.out.println("\t Noted. I've removed this task:\n" + + "\t\t " + tasks.get(index - 1).toString()); + tasks.remove(index - 1); + System.out.println("\t Now you have " + tasks.size() + " tasks in the list.\n"); + } + public void run() { start(); while (true) { @@ -145,9 +164,12 @@ public void run() { } else if (command.startsWith("deadline")) { display(); deadline(command); - } else if(command.startsWith("event")) { + } else if (command.startsWith("event")) { display(); event(command); + } else if (command.startsWith("delete")) { + display(); + delete(command); } else { display(); System.out.println("\t ☹ OOPS!!! I'm sorry, but I don't know what that means.\n"); @@ -157,8 +179,6 @@ public void run() { } } } - - public static void main(String[] args) { Duke duke = new Duke(); duke.run(); From a57249e807cf7169ba0a0ee0eb4d269c0bfaea71 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Tue, 7 Feb 2023 10:18:26 +0800 Subject: [PATCH 09/42] Add Increment Level -7 as parallel branche with Save method --- src/main/java/Deadline.java | 4 ++ src/main/java/Duke.java | 122 ++++++++++++++++++++++++++++++++++-- src/main/java/Event.java | 7 +++ src/main/java/Task.java | 11 ++++ 4 files changed, 140 insertions(+), 4 deletions(-) diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index 573b7b8793..d14b5255fd 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -6,6 +6,10 @@ public Deadline(String description, String by) { this.by = by; } + public String getBy() { + return this.by; + } + @Override public String toString() { return "[D]" + super.toString() + " (by: " + by + ")"; diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 9d9327c8b8..1d905ac9a0 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,5 +1,11 @@ +import java.nio.file.StandardOpenOption; import java.util.ArrayList; +import java.util.List; import java.util.Scanner; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; public class Duke { @@ -31,7 +37,8 @@ public void mark(String command) throws DukeException{ throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); } tasks.get(index).mark(); - } catch (NumberFormatException ex) { + editData(index, "1"); + } catch (NumberFormatException | IOException ex) { System.out.println("\t ☹ OOPS!!! Please input a valid number.\n"); } } @@ -48,7 +55,8 @@ public void unmark(String command) throws DukeException{ throw new DukeException("\t ☹ OOPS!!! This task has not been marked yet.\n"); } tasks.get(index).unmark(); - } catch (NumberFormatException ex) { + editData(index, "0"); + } catch (NumberFormatException | IOException ex) { System.out.println("\t ☹ OOPS!!! Please input a valid number.\n"); } } @@ -62,6 +70,7 @@ public void list() { public void addTask(Task task) { tasks.add(task); + save(task); System.out.println("\t Got it. I've added this task:\n" + "\t\t "+ tasks.get(tasks.size() - 1).toString() + "\n\t Now you have " + tasks.size() + " tasks in the list.\n"); @@ -120,7 +129,7 @@ public void event(String command) throws DukeException{ addTask(event); } - public void delete(String command) throws DukeException { + public void delete(String command) throws DukeException, IOException { command = command.trim(); if (command.equals("delete")) { throw new DukeException("\t ☹ OOPS!!! The description of a delete cannot be empty.\n"); @@ -138,10 +147,113 @@ public void delete(String command) throws DukeException { + "\t\t " + tasks.get(index - 1).toString()); tasks.remove(index - 1); System.out.println("\t Now you have " + tasks.size() + " tasks in the list.\n"); + deleteData(index); + } + + public void editData(int taskIndex, String data) throws IOException { + Path file = Paths.get(".", ".\\data\\duke.txt"); + List records = Files.readAllLines(file); + String[] str = records.get(taskIndex).split(" \\| "); + str[1] = data; + String record = String.join(" | ", str); + records.set(taskIndex, record); + Files.write(file, records); + } + + public void deleteData(int taskIndex) throws IOException { + Path file = Paths.get(".", ".\\data\\duke.txt"); + + try { + List datas = Files.readAllLines(file); + datas.remove(taskIndex - 1); + Files.write(file, datas); + } catch (IOException e) { + System.out.println("\t Invalid Path."); + } + } + + public void save(Task task) { + Path file = Paths.get(".", ".\\data\\duke.txt"); + String data = ""; + if (task instanceof Todo) { + data = ("T | "); + } else if (task instanceof Deadline) { + data = "D | "; + } else { + data = "E | "; + } + if (task.getStatusIcon().equals("X")) { + data += "1 | "; + } else { + data += "0 | "; + } + data += task.getDescription(); + if (task instanceof Deadline) { + data += " | " + ((Deadline) task).getBy(); + } else if (task instanceof Event) { + data += " | " + ((Event) task).getFrom() + "-" + ((Event) task).getTo(); + } + data += "\n"; + + try { + Files.writeString(file, data, StandardOpenOption.APPEND); + } catch (IOException e) { + System.out.println("\t Invalid Path"); + } + } + + public void loadData() { + Path file = Paths.get(".", ".\\data\\duke.txt"); + try { + List datas = Files.readAllLines(file); + for (int i = 0; i < datas.size(); i++) { + String[] content = datas.get(i).split(" \\| "); + String isDone = content[1]; + String description = content[2]; + if (content[0].equals("T")) { + Todo task = new Todo(description); + tasks.add(task); + } else if (content[0].equals("D")) { + String endDate = content[3]; + Deadline task = new Deadline(description, endDate); + tasks.add(task); + } else { + String times = content[3]; + String date[] = times.split("-", 2); + String startTime = date[0]; + String endTime = date[1]; + Event task = new Event(description, startTime, endTime); + tasks.add(task); + } + if (isDone.equals("1")) { + tasks.get(i).setDone(true); + } + } + } catch (IOException e) { + System.out.println("\t Invalid Path."); + } + } + + public void checkFileExit() { + try { + Path file = Paths.get(".", ".\\data\\duke.txt"); + + if (Files.exists(file)) { + loadData(); + } else { + Files.createDirectories(file.getParent()); + Files.createFile(file); + } + } catch (IOException e) { + System.out.println("Invalid Path"); + e.printStackTrace(); + } } public void run() { start(); + display(); + checkFileExit(); while (true) { String command = input.nextLine(); try { @@ -174,13 +286,15 @@ public void run() { display(); System.out.println("\t ☹ OOPS!!! I'm sorry, but I don't know what that means.\n"); } - } catch (DukeException e) { + } catch (DukeException | IOException e) { System.out.println(e.getMessage()); } } } + public static void main(String[] args) { Duke duke = new Duke(); duke.run(); } } + diff --git a/src/main/java/Event.java b/src/main/java/Event.java index f4d12b14ca..bab8c81092 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -7,6 +7,13 @@ public Event(String description, String from, String to) { this.from = from; this.to = to; } + public String getFrom() { + return this.from; + } + + public String getTo() { + return this.to; + } @Override public String toString() { return "[E]" + super.toString() + " (from: " + from + " to: " + to + ")"; diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 47704689a4..fee3d411b3 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -7,7 +7,17 @@ public Task(String description) { this.isDone = false; } + public String getDescription() { + return this.description; + } + + public void setDone(boolean isDone) { + + this.isDone = isDone; + } + public String getStatusIcon() { + return (isDone ? "X" : " "); } @@ -25,6 +35,7 @@ public void unmark() { @Override public String toString() { + return " [" + getStatusIcon() + "] " + this.description; } } From 3d7c8f3ae92d828d196921eaaa1b0b539da9cfde Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Tue, 7 Feb 2023 10:39:29 +0800 Subject: [PATCH 10/42] Merge branch 'branch-Level-8' # Conflicts: # src/main/java/Event.java # src/main/java/Deadline.java --- src/main/java/Deadline.java | 22 ++++++++++++++++--- src/main/java/Event.java | 42 +++++++++++++++++++++++++++++++------ 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index d14b5255fd..84e8f02056 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -1,9 +1,25 @@ +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + public class Deadline extends Task { - protected String by; + protected LocalDateTime by; public Deadline(String description, String by) { super(description); - this.by = by; + this.by = transferTOLocalDateTime(by); + } + + public LocalDateTime transferTOLocalDateTime(String by) { + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); + LocalDateTime dateTime = LocalDateTime.parse(by, dateTimeFormatter); + return dateTime; + } + + public String deadlineDateTime() { + DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm"); + String deadline = this.by.format(format); + String dayOfWeek = this.by.getDayOfWeek().toString(); + return dayOfWeek + ", " + deadline; } public String getBy() { @@ -12,6 +28,6 @@ public String getBy() { @Override public String toString() { - return "[D]" + super.toString() + " (by: " + by + ")"; + return "[D]" + super.toString() + " (by: " + deadlineDateTime() + ")"; } } diff --git a/src/main/java/Event.java b/src/main/java/Event.java index bab8c81092..644dd1877e 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -1,12 +1,28 @@ -public class Event extends Task{ - protected String from; - protected String to; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class Event extends Task { + protected LocalDateTime from; + protected LocalDateTime to; public Event(String description, String from, String to) { super(description); - this.from = from; - this.to = to; + this.from = getStartDateTime(from); + this.to = getEndDateTime(to); + } + + public LocalDateTime getStartDateTime(String from) { + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); + LocalDateTime startDateTime = LocalDateTime.parse(from, dateTimeFormatter); + return startDateTime; + } + + public LocalDateTime getEndDateTime(String from) { + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); + LocalDateTime endDateTime = LocalDateTime.parse(from, dateTimeFormatter); + return endDateTime; } +<<<<<<< HEAD public String getFrom() { return this.from; } @@ -14,8 +30,22 @@ public String getFrom() { public String getTo() { return this.to; } +======= + + public String deadlineDateTime() { + DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm"); + String startDateTime = this.from.format(format); + String startDayOfWeek = this.from.getDayOfWeek().toString(); + String endDateTime = this.to.format(format); + String endDayOfWeek = this.to.getDayOfWeek().toString(); + return " (from: " + startDayOfWeek + ", " + startDateTime + + " to: " + endDayOfWeek + ", " + endDateTime + ")"; + } + +>>>>>>> branch-Level-8 @Override public String toString() { - return "[E]" + super.toString() + " (from: " + from + " to: " + to + ")"; + + return "[E]" + super.toString() + deadlineDateTime(); } } From f308ef42fb1e2a4e966d84a9bae179ef93c1dffe Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Tue, 7 Feb 2023 13:16:50 +0800 Subject: [PATCH 11/42] Add Increments as parallel branche-Level-8 with Dates and Times --- src/main/java/Deadline.java | 22 +++++++++++++++++++--- src/main/java/Event.java | 36 +++++++++++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index 573b7b8793..0fe6249145 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -1,13 +1,29 @@ +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + public class Deadline extends Task { - protected String by; + protected LocalDateTime by; public Deadline(String description, String by) { super(description); - this.by = by; + this.by = transferTOLocalDateTime(by); + } + + public LocalDateTime transferTOLocalDateTime(String by) { + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); + LocalDateTime dateTime = LocalDateTime.parse(by, dateTimeFormatter); + return dateTime; + } + + public String deadlineDateTime() { + DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm"); + String deadline = this.by.format(format); + String dayOfWeek = this.by.getDayOfWeek().toString(); + return dayOfWeek + ", " + deadline; } @Override public String toString() { - return "[D]" + super.toString() + " (by: " + by + ")"; + return "[D]" + super.toString() + " (by: " + deadlineDateTime() + ")"; } } diff --git a/src/main/java/Event.java b/src/main/java/Event.java index f4d12b14ca..66554dddf6 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -1,14 +1,40 @@ +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + public class Event extends Task{ - protected String from; - protected String to; + protected LocalDateTime from; + protected LocalDateTime to; public Event(String description, String from, String to) { super(description); - this.from = from; - this.to = to; + this.from = getStartDateTime(from); + this.to = getEndDateTime(to); + } + + public LocalDateTime getStartDateTime(String from) { + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); + LocalDateTime startDateTime = LocalDateTime.parse(from, dateTimeFormatter); + return startDateTime; + } + + public LocalDateTime getEndDateTime(String from) { + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); + LocalDateTime endDateTime = LocalDateTime.parse(from, dateTimeFormatter); + return endDateTime; + } + + public String deadlineDateTime() { + DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm"); + String startDateTime = this.from.format(format); + String startDayOfWeek = this.from.getDayOfWeek().toString(); + String endDateTime = this.to.format(format); + String endDayOfWeek = this.to.getDayOfWeek().toString(); + return " (from: " + startDayOfWeek + ", " + startDateTime + + " to: " + endDayOfWeek + ", " + endDateTime + ")"; } @Override public String toString() { - return "[E]" + super.toString() + " (from: " + from + " to: " + to + ")"; + + return "[E]" + super.toString() + deadlineDateTime(); } } From eaeedb99b4c770195d53854b000ed2fee87b4be4 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Tue, 7 Feb 2023 13:24:34 +0800 Subject: [PATCH 12/42] Add Increments as parallel branch-Level-7 with Save method --- src/main/java/Deadline.java | 3 + src/main/java/Duke.java | 120 ++++++++++++++++++++++++++++++++++-- src/main/java/Event.java | 9 +++ src/main/java/Task.java | 8 +++ 4 files changed, 136 insertions(+), 4 deletions(-) diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index 573b7b8793..850bf199be 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -6,6 +6,9 @@ public Deadline(String description, String by) { this.by = by; } + public String getBy() { + return this.by; + } @Override public String toString() { return "[D]" + super.toString() + " (by: " + by + ")"; diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 9d9327c8b8..effcfbcbaf 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,5 +1,11 @@ +import java.nio.file.StandardOpenOption; import java.util.ArrayList; +import java.util.List; import java.util.Scanner; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; public class Duke { @@ -31,7 +37,8 @@ public void mark(String command) throws DukeException{ throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); } tasks.get(index).mark(); - } catch (NumberFormatException ex) { + editData(index, "1"); + } catch (NumberFormatException | IOException ex) { System.out.println("\t ☹ OOPS!!! Please input a valid number.\n"); } } @@ -48,7 +55,8 @@ public void unmark(String command) throws DukeException{ throw new DukeException("\t ☹ OOPS!!! This task has not been marked yet.\n"); } tasks.get(index).unmark(); - } catch (NumberFormatException ex) { + editData(index, "0"); + } catch (NumberFormatException | IOException ex) { System.out.println("\t ☹ OOPS!!! Please input a valid number.\n"); } } @@ -62,6 +70,7 @@ public void list() { public void addTask(Task task) { tasks.add(task); + save(task); System.out.println("\t Got it. I've added this task:\n" + "\t\t "+ tasks.get(tasks.size() - 1).toString() + "\n\t Now you have " + tasks.size() + " tasks in the list.\n"); @@ -120,7 +129,7 @@ public void event(String command) throws DukeException{ addTask(event); } - public void delete(String command) throws DukeException { + public void delete(String command) throws DukeException, IOException { command = command.trim(); if (command.equals("delete")) { throw new DukeException("\t ☹ OOPS!!! The description of a delete cannot be empty.\n"); @@ -138,10 +147,113 @@ public void delete(String command) throws DukeException { + "\t\t " + tasks.get(index - 1).toString()); tasks.remove(index - 1); System.out.println("\t Now you have " + tasks.size() + " tasks in the list.\n"); + deleteData(index); + } + + public void editData(int taskIndex, String data) throws IOException { + Path file = Paths.get(".", ".\\data\\duke.txt"); + List records = Files.readAllLines(file); + String[] str = records.get(taskIndex).split(" \\| "); + str[1] = data; + String record = String.join(" | ", str); + records.set(taskIndex, record); + Files.write(file, records); + } + + public void deleteData(int taskIndex) throws IOException { + Path file = Paths.get(".", ".\\data\\duke.txt"); + + try { + List datas = Files.readAllLines(file); + datas.remove(taskIndex - 1); + Files.write(file, datas); + } catch (IOException e) { + System.out.println("\t Invalid Path."); + } + } + + public void save(Task task) { + Path file = Paths.get(".", ".\\data\\duke.txt"); + String data = ""; + if (task instanceof Todo) { + data = ("T | "); + } else if (task instanceof Deadline) { + data = "D | "; + } else { + data = "E | "; + } + if (task.getStatusIcon().equals("X")) { + data += "1 | "; + } else { + data += "0 | "; + } + data += task.getDescription(); + if (task instanceof Deadline) { + data += " | " + ((Deadline) task).getBy(); + } else if (task instanceof Event) { + data += " | " + ((Event) task).getFrom() + "-" + ((Event) task).getTo(); + } + data += "\n"; + + try { + Files.writeString(file, data, StandardOpenOption.APPEND); + } catch (IOException e) { + System.out.println("\t Invalid Path"); + } + } + + public void loadData() { + Path file = Paths.get(".", ".\\data\\duke.txt"); + try { + List datas = Files.readAllLines(file); + for (int i = 0; i < datas.size(); i++) { + String[] content = datas.get(i).split(" \\| "); + String isDone = content[1]; + String description = content[2]; + if (content[0].equals("T")) { + Todo task = new Todo(description); + tasks.add(task); + } else if (content[0].equals("D")) { + String endDate = content[3]; + Deadline task = new Deadline(description, endDate); + tasks.add(task); + } else { + String times = content[3]; + String date[] = times.split("-", 2); + String startTime = date[0]; + String endTime = date[1]; + Event task = new Event(description, startTime, endTime); + tasks.add(task); + } + if (isDone.equals("1")) { + tasks.get(i).setDone(true); + } + } + } catch (IOException e) { + System.out.println("\t Invalid Path."); + } + } + + public void checkFileExit() { + try { + Path file = Paths.get(".", ".\\data\\duke.txt"); + + if (Files.exists(file)) { + loadData(); + } else { + Files.createDirectories(file.getParent()); + Files.createFile(file); + } + } catch (IOException e) { + System.out.println("Invalid Path"); + e.printStackTrace(); + } } public void run() { start(); + display(); + checkFileExit(); while (true) { String command = input.nextLine(); try { @@ -174,7 +286,7 @@ public void run() { display(); System.out.println("\t ☹ OOPS!!! I'm sorry, but I don't know what that means.\n"); } - } catch (DukeException e) { + } catch (DukeException | IOException e) { System.out.println(e.getMessage()); } } diff --git a/src/main/java/Event.java b/src/main/java/Event.java index f4d12b14ca..8649aa9cf6 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -7,6 +7,15 @@ public Event(String description, String from, String to) { this.from = from; this.to = to; } + + public String getFrom() { + return this.from; + } + + public String getTo() { + return this.to; + } + @Override public String toString() { return "[E]" + super.toString() + " (from: " + from + " to: " + to + ")"; diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 47704689a4..04d32dead6 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -7,6 +7,14 @@ public Task(String description) { this.isDone = false; } + public String getDescription() { + return this.description; + } + + public void setDone(boolean isDone) { + this.isDone = isDone; + } + public String getStatusIcon() { return (isDone ? "X" : " "); } From e1c0c5ef74b63f9530e9c502edf6138cefa5f3fb Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Tue, 7 Feb 2023 14:14:30 +0800 Subject: [PATCH 13/42] Solve merge conflict branch-Level-8 --- src/main/java/Deadline.java | 23 +++++++++++++--- src/main/java/Event.java | 55 ++++++++++++++++++++++++++++++------- 2 files changed, 64 insertions(+), 14 deletions(-) diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index ee2e470c5b..37c83cc5fe 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -1,5 +1,6 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; public class Deadline extends Task { protected LocalDateTime by; @@ -10,20 +11,34 @@ public Deadline(String description, String by) { } public LocalDateTime transferTOLocalDateTime(String by) { + LocalDateTime dateTime = null; DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); - LocalDateTime dateTime = LocalDateTime.parse(by, dateTimeFormatter); + try { + dateTime = LocalDateTime.parse(by, dateTimeFormatter); + return dateTime; + } catch (DateTimeParseException | NullPointerException e) { + System.out.println("\t Wrong Wrong Date Format!\n"); + } return dateTime; } public String deadlineDateTime() { + String deadline = ""; + String dayOfWeek = ""; DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm"); - String deadline = this.by.format(format); - String dayOfWeek = this.by.getDayOfWeek().toString(); + try { + deadline = this.by.format(format); + dayOfWeek = this.by.getDayOfWeek().toString(); + return dayOfWeek + ", " + deadline; + } catch (DateTimeParseException | NullPointerException e) { + System.out.println("\t Wrong Wrong Date Format!\n"); + } return dayOfWeek + ", " + deadline; } public String getBy() { - return this.by; + String deadline = deadlineDateTime(); + return deadline; } @Override public String toString() { diff --git a/src/main/java/Event.java b/src/main/java/Event.java index 669b843758..5c44e6896d 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -1,5 +1,6 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; public class Event extends Task{ protected LocalDateTime from; @@ -12,38 +13,72 @@ public Event(String description, String from, String to) { } public LocalDateTime getStartDateTime(String from) { + LocalDateTime startDateTime = null; DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); - LocalDateTime startDateTime = LocalDateTime.parse(from, dateTimeFormatter); + try { + startDateTime = LocalDateTime.parse(from, dateTimeFormatter); + return startDateTime; + } catch (DateTimeParseException | NullPointerException e) { + System.out.println("\t Wrong Wrong Date Format!\n"); + } return startDateTime; } public LocalDateTime getEndDateTime(String from) { + LocalDateTime endDateTime = null; DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); - LocalDateTime endDateTime = LocalDateTime.parse(from, dateTimeFormatter); + try { + endDateTime = LocalDateTime.parse(from, dateTimeFormatter); + return endDateTime; + } catch (DateTimeParseException | NullPointerException e) { + System.out.println("\t Wrong Wrong Date Format!\n"); + } return endDateTime; } - public String deadlineDateTime() { + public String startDateTime() { + String startDateTime = null; + String startDayOfWeek = null; DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm"); - String startDateTime = this.from.format(format); - String startDayOfWeek = this.from.getDayOfWeek().toString(); + try { + startDateTime = this.from.format(format); + startDayOfWeek = this.from.getDayOfWeek().toString(); + return startDayOfWeek + ", " + startDateTime; + } catch (DateTimeParseException | NullPointerException e) { + System.out.println("\t Wrong Wrong Date Format!\n"); + } + String endDateTime = this.to.format(format); String endDayOfWeek = this.to.getDayOfWeek().toString(); - return " (from: " + startDayOfWeek + ", " + startDateTime - + " to: " + endDayOfWeek + ", " + endDateTime + ")"; + return startDayOfWeek + ", " + startDateTime; + } + + public String endDateTime() { + String endDateTime = null; + String endDayOfWeek = null; + DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm"); + try { + endDateTime = this.to.format(format); + endDayOfWeek = this.to.getDayOfWeek().toString(); + return endDayOfWeek + ", " + endDateTime; + } catch (DateTimeParseException | NullPointerException e) { + System.out.println("\t Wrong Wrong Date Format!\n"); + } + return endDayOfWeek + ", " + endDateTime; } public String getFrom() { - return this.from; + return startDateTime(); } public String getTo() { - return this.to; + return endDateTime(); } @Override public String toString() { - return "[E]" + super.toString() + deadlineDateTime(); + return "[E]" + super.toString() + " (from: " + startDateTime() + + " to: " + endDateTime() + ")"; } } From 817bcee0fa2e9cd03069d0191799c904c7877b43 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Mon, 13 Feb 2023 02:59:53 +0800 Subject: [PATCH 14/42] Add Increment: A-MoreOOP --- src/main/java/AddDeadlineCommand.java | 14 ++ src/main/java/AddEventCommand.java | 13 ++ src/main/java/AddTaskCommand.java | 16 ++ src/main/java/AddTodoCommand.java | 13 ++ src/main/java/Command.java | 12 + src/main/java/DateTime.java | 25 +++ src/main/java/Deadline.java | 74 +++---- src/main/java/DeleteTaskCommand.java | 16 ++ src/main/java/Duke.java | 306 ++------------------------ src/main/java/Event.java | 121 +++++----- src/main/java/ExitCommand.java | 14 ++ src/main/java/ListCommand.java | 15 ++ src/main/java/MarkTaskCommand.java | 19 ++ src/main/java/Parser.java | 77 +++++++ src/main/java/Storage.java | 77 +++++++ src/main/java/Task.java | 44 ++-- src/main/java/TaskList.java | 76 +++++++ src/main/java/Todo.java | 41 +++- src/main/java/Ui.java | 50 +++++ 19 files changed, 600 insertions(+), 423 deletions(-) create mode 100644 src/main/java/AddDeadlineCommand.java create mode 100644 src/main/java/AddEventCommand.java create mode 100644 src/main/java/AddTaskCommand.java create mode 100644 src/main/java/AddTodoCommand.java create mode 100644 src/main/java/Command.java create mode 100644 src/main/java/DateTime.java create mode 100644 src/main/java/DeleteTaskCommand.java create mode 100644 src/main/java/ExitCommand.java create mode 100644 src/main/java/ListCommand.java create mode 100644 src/main/java/MarkTaskCommand.java create mode 100644 src/main/java/Parser.java create mode 100644 src/main/java/Storage.java create mode 100644 src/main/java/TaskList.java create mode 100644 src/main/java/Ui.java diff --git a/src/main/java/AddDeadlineCommand.java b/src/main/java/AddDeadlineCommand.java new file mode 100644 index 0000000000..8b07d452cd --- /dev/null +++ b/src/main/java/AddDeadlineCommand.java @@ -0,0 +1,14 @@ +public class AddDeadlineCommand extends AddTaskCommand{ + public AddDeadlineCommand(String inputArr) { + super(inputArr); + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + Deadline deadline = Deadline.generate(this.getInputArr()); + taskList.addTask(deadline); + storage.saveData(taskList); + ui.printAddTaskMsg(taskList, deadline); + } +} + diff --git a/src/main/java/AddEventCommand.java b/src/main/java/AddEventCommand.java new file mode 100644 index 0000000000..8ee808f817 --- /dev/null +++ b/src/main/java/AddEventCommand.java @@ -0,0 +1,13 @@ +public class AddEventCommand extends AddTaskCommand { + public AddEventCommand(String inputArr) { + super(inputArr); + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + Event event = Event.generate(this.getInputArr()); + taskList.addTask(event); + storage.saveData(taskList); + ui.printAddTaskMsg(taskList, event); + } +} \ No newline at end of file diff --git a/src/main/java/AddTaskCommand.java b/src/main/java/AddTaskCommand.java new file mode 100644 index 0000000000..8a21700336 --- /dev/null +++ b/src/main/java/AddTaskCommand.java @@ -0,0 +1,16 @@ +abstract class AddTaskCommand extends Command { + + public AddTaskCommand(String inputArr) { + super(inputArr); + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + + } + + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/AddTodoCommand.java b/src/main/java/AddTodoCommand.java new file mode 100644 index 0000000000..c8476265bb --- /dev/null +++ b/src/main/java/AddTodoCommand.java @@ -0,0 +1,13 @@ +public class AddTodoCommand extends AddTaskCommand { + public AddTodoCommand(String inputArr) { + super(inputArr); + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + Todo todo = Todo.generate(this.getInputArr()); + taskList.addTask(todo); + storage.saveData(taskList); + ui.printAddTaskMsg(taskList, todo); + } +} \ No newline at end of file diff --git a/src/main/java/Command.java b/src/main/java/Command.java new file mode 100644 index 0000000000..6e44873a2a --- /dev/null +++ b/src/main/java/Command.java @@ -0,0 +1,12 @@ +abstract public class Command { + private final String inputArr; + public Command(String inputArr) { + this.inputArr = inputArr; + } + + public String getInputArr() { + return inputArr; + } + public abstract void process(TaskList taskList, Ui ui, Storage storage) throws DukeException; + public abstract boolean isExit(); +} \ No newline at end of file diff --git a/src/main/java/DateTime.java b/src/main/java/DateTime.java new file mode 100644 index 0000000000..3f3e1becd0 --- /dev/null +++ b/src/main/java/DateTime.java @@ -0,0 +1,25 @@ +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +public class DateTime { + + public static LocalDateTime getDateTime(String date) throws DukeException { + try { + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); + LocalDateTime localDateTime = LocalDateTime.parse(date, dateTimeFormatter); + return localDateTime; + } catch (DateTimeParseException e) { + throw new DukeException("\t Wrong Date Format, please write in yyyy-MM-dd HHmm.\n"); + } + } + public static String dateFormatter(String date) throws DukeException { + try { + LocalDateTime localDateTime = getDateTime(date); + return localDateTime.format(DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm")); + } catch (DateTimeParseException e) { + throw new DukeException("\t Wrong Date Format, please write in yyyy-MM-dd HHmm.\n"); + } + } + +} diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java index 37c83cc5fe..9d4383ea66 100644 --- a/src/main/java/Deadline.java +++ b/src/main/java/Deadline.java @@ -1,47 +1,47 @@ -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; - public class Deadline extends Task { - protected LocalDateTime by; - - public Deadline(String description, String by) { - super(description); - this.by = transferTOLocalDateTime(by); + private String dateTime; + private Deadline(String description, boolean isDone, String dateTime) { + super(description, isDone); + this.dateTime = dateTime; } - - public LocalDateTime transferTOLocalDateTime(String by) { - LocalDateTime dateTime = null; - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); - try { - dateTime = LocalDateTime.parse(by, dateTimeFormatter); - return dateTime; - } catch (DateTimeParseException | NullPointerException e) { - System.out.println("\t Wrong Wrong Date Format!\n"); + public static Deadline generate(String input) throws DukeException { + if (input.trim().equals("deadline")) { + throw new DukeException("\t ☹ OOPS!!! The description of a deadline cannot be empty.\n"); } + String[] inputLine = input.split(" ", 2); + if (inputLine.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The description of a deadline cannot be empty.\n"); + } + String[] descriptions = inputLine[1].split(" /by ", 2); + if (descriptions.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The date time of a deadline cannot be empty.\n"); + } + return new Deadline(descriptions[0], false, DateTime.dateFormatter(descriptions[1])); + } + public static Deadline generateTask(String[] taskLine) { + boolean check = taskLine[1].equals("1"); + return new Deadline(taskLine[2], check, taskLine[3]); + } + public String getDateTime() { return dateTime; } - - public String deadlineDateTime() { - String deadline = ""; - String dayOfWeek = ""; - DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm"); - try { - deadline = this.by.format(format); - dayOfWeek = this.by.getDayOfWeek().toString(); - return dayOfWeek + ", " + deadline; - } catch (DateTimeParseException | NullPointerException e) { - System.out.println("\t Wrong Wrong Date Format!\n"); - } - return dayOfWeek + ", " + deadline; + @Override + public String getTaskType() { + return "D"; } - - public String getBy() { - String deadline = deadlineDateTime(); - return deadline; + @Override + public String storeTaskString() { + return this.getTaskType() + " | " + this.getMarkedString() + " | " + this.getDescription() + " | " + this.getDateTime(); } @Override public String toString() { - return "[D]" + super.toString() + " (by: " + deadlineDateTime() + ")"; + String str = this.getDescription(); + boolean checked = this.isDone(); + String dateTime = this.getDateTime(); + if (checked) { + return "[D][X] " + str + " (by: " + dateTime + ")"; + } else { + return "[D][ ] " + str + " (by: " + dateTime + ")"; + } } -} +} \ No newline at end of file diff --git a/src/main/java/DeleteTaskCommand.java b/src/main/java/DeleteTaskCommand.java new file mode 100644 index 0000000000..6ae8ede401 --- /dev/null +++ b/src/main/java/DeleteTaskCommand.java @@ -0,0 +1,16 @@ +public class DeleteTaskCommand extends Command { + + public DeleteTaskCommand(String inputArr) { + super(inputArr); + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + taskList.deleteTask(this.getInputArr(), ui, storage); + } + + @Override + public boolean isExit() { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 1d905ac9a0..d85bf2a482 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,300 +1,40 @@ -import java.nio.file.StandardOpenOption; -import java.util.ArrayList; -import java.util.List; -import java.util.Scanner; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - public class Duke { + private final static String FILE_PATH = ".\\src\\data\\duke.txt"; - private Scanner input = new Scanner(System.in); - private ArrayList tasks = new ArrayList<>(); - - public void start() { - String logo = "\t ____ _ \n" - + "\t | _ \\ _ _| | _____ \n" - + "\t | | | | | | | |/ / _ \\\n" - + "\t | |_| | |_| | < __/\n" - + "\t |____/ \\__,_|_|\\_\\___|\n"; - System.out.println(logo); - System.out.println("\t Hello! I'm Duke"); - System.out.println("\t What can I do for you?\n"); - } - - public void display() { - System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); - } - - public void mark(String command) throws DukeException{ - if (command.trim().equals("mark")) { - throw new DukeException("\t ☹ OOPS!!! The description of a mark cannot be empty.\n"); - } - try { - int index = Integer.parseInt(command.split(" ")[1]) - 1; - if (index + 1 > tasks.size() || index < 0) { - throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); - } - tasks.get(index).mark(); - editData(index, "1"); - } catch (NumberFormatException | IOException ex) { - System.out.println("\t ☹ OOPS!!! Please input a valid number.\n"); - } - } - - public void unmark(String command) throws DukeException{ - if (command.trim().equals("mark")) { - throw new DukeException("\t ☹ OOPS!!! The description of a unmark cannot be empty.\n"); - } - try { - int index = Integer.parseInt(command.split(" ")[1]) - 1; - if (index + 1 > tasks.size() || index < 0) { - throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); - } else if (tasks.get(index).getStatusIcon().equals(" ")) { - throw new DukeException("\t ☹ OOPS!!! This task has not been marked yet.\n"); - } - tasks.get(index).unmark(); - editData(index, "0"); - } catch (NumberFormatException | IOException ex) { - System.out.println("\t ☹ OOPS!!! Please input a valid number.\n"); - } - } - - public void list() { - for (int i = 0; i < tasks.size(); i++) { - System.out.print("\t " + (i + 1) + "." + tasks.get(i).toString() + "\n"); - } - System.out.print("\n"); - } - - public void addTask(Task task) { - tasks.add(task); - save(task); - System.out.println("\t Got it. I've added this task:\n" - + "\t\t "+ tasks.get(tasks.size() - 1).toString() - + "\n\t Now you have " + tasks.size() + " tasks in the list.\n"); - } - public void todo(String command) throws DukeException { - if (command.trim().equals("todo")) { - throw new DukeException("\t ☹ OOPS!!! The description of a todo cannot be empty.\n"); - } - String description = command.split(" ", 2)[1]; - Todo todo = new Todo(description); - addTask(todo); - } - - public void deadline(String command) throws DukeException { - if (command.trim().equals("deadline")) { - throw new DukeException("\t ☹ OOPS!!! The description of a deadline cannot be empty.\n"); - } else if (command.trim().contains(" /by ") == false) { - throw new DukeException("\t ☹ OOPS!!! There is no deadline date or the wrong format\n"); - } - - command = command.split(" ", 2)[1]; - if (command.startsWith("/by")) { - throw new DukeException("☹ OOPS!!! The description of a deadline cannot be empty.\n"); - } else if (command.endsWith("/by")) { - throw new DukeException(("☹ OOPS!!! The due date of a deadline cannot be empty.\n")); - } - - String info[] = command.split(" /by "); - String description = info[0]; - String by = info[1]; - Deadline deadline = new Deadline(description, by); - addTask(deadline); - } - - public void event(String command) throws DukeException{ - command = command.trim(); - if (command.equals("event")) { - throw new DukeException("\t ☹ OOPS!!! The description of a event cannot be empty.\n"); - } else if (command.contains(" /from ") == false || command.contains(" /to ") == false) { - throw new DukeException("\t ☹ OOPS!!! The from date or due date of a deadline cannot be empty.\n" - + "\t Or the format is wrong.\n"); - } - - command = command.split(" ", 2)[1]; - if (command.startsWith("/from") || command.endsWith("/to") || command.contains("/from /to")) { - throw new DukeException("\t ☹ OOPS!!! The description, from date or due date of a event cannot be empty.\n"); - } - - String info[] = command.split(" /from "); - String description = info[0]; - String dates[] = info[1].split(" /to "); - String from = dates[0]; - String to = dates[1]; - - Event event = new Event(description, from, to); - addTask(event); - } - - public void delete(String command) throws DukeException, IOException { - command = command.trim(); - if (command.equals("delete")) { - throw new DukeException("\t ☹ OOPS!!! The description of a delete cannot be empty.\n"); - } - int index; - try { - index = Integer.parseInt(command.split(" ")[1]); - } catch (NumberFormatException ex) { - throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); - } - if (index < 1 || index > tasks.size()) { - throw new DukeException("\t ☹ OOPS!!! The input is out of range.\n"); - } - System.out.println("\t Noted. I've removed this task:\n" - + "\t\t " + tasks.get(index - 1).toString()); - tasks.remove(index - 1); - System.out.println("\t Now you have " + tasks.size() + " tasks in the list.\n"); - deleteData(index); - } - - public void editData(int taskIndex, String data) throws IOException { - Path file = Paths.get(".", ".\\data\\duke.txt"); - List records = Files.readAllLines(file); - String[] str = records.get(taskIndex).split(" \\| "); - str[1] = data; - String record = String.join(" | ", str); - records.set(taskIndex, record); - Files.write(file, records); - } - - public void deleteData(int taskIndex) throws IOException { - Path file = Paths.get(".", ".\\data\\duke.txt"); - - try { - List datas = Files.readAllLines(file); - datas.remove(taskIndex - 1); - Files.write(file, datas); - } catch (IOException e) { - System.out.println("\t Invalid Path."); - } - } - - public void save(Task task) { - Path file = Paths.get(".", ".\\data\\duke.txt"); - String data = ""; - if (task instanceof Todo) { - data = ("T | "); - } else if (task instanceof Deadline) { - data = "D | "; - } else { - data = "E | "; - } - if (task.getStatusIcon().equals("X")) { - data += "1 | "; - } else { - data += "0 | "; - } - data += task.getDescription(); - if (task instanceof Deadline) { - data += " | " + ((Deadline) task).getBy(); - } else if (task instanceof Event) { - data += " | " + ((Event) task).getFrom() + "-" + ((Event) task).getTo(); - } - data += "\n"; - - try { - Files.writeString(file, data, StandardOpenOption.APPEND); - } catch (IOException e) { - System.out.println("\t Invalid Path"); - } - } - - public void loadData() { - Path file = Paths.get(".", ".\\data\\duke.txt"); - try { - List datas = Files.readAllLines(file); - for (int i = 0; i < datas.size(); i++) { - String[] content = datas.get(i).split(" \\| "); - String isDone = content[1]; - String description = content[2]; - if (content[0].equals("T")) { - Todo task = new Todo(description); - tasks.add(task); - } else if (content[0].equals("D")) { - String endDate = content[3]; - Deadline task = new Deadline(description, endDate); - tasks.add(task); - } else { - String times = content[3]; - String date[] = times.split("-", 2); - String startTime = date[0]; - String endTime = date[1]; - Event task = new Event(description, startTime, endTime); - tasks.add(task); - } - if (isDone.equals("1")) { - tasks.get(i).setDone(true); - } - } - } catch (IOException e) { - System.out.println("\t Invalid Path."); - } - } - - public void checkFileExit() { - try { - Path file = Paths.get(".", ".\\data\\duke.txt"); - - if (Files.exists(file)) { - loadData(); - } else { - Files.createDirectories(file.getParent()); - Files.createFile(file); - } - } catch (IOException e) { - System.out.println("Invalid Path"); - e.printStackTrace(); - } + private final Ui ui; + private final Storage storage; + private final TaskList taskList; + public Duke() { + ui = new Ui(); + storage = new Storage(FILE_PATH); + taskList = storage.readData(); } public void run() { - start(); - display(); - checkFileExit(); - while (true) { - String command = input.nextLine(); + ui.printWelcomeMsg(); + ui.printLine(); + boolean isBye = false; + while (!isBye) { try { - if (command.equals("bye")) { - display(); - System.out.println("\t Bye. Hope to see you again soon!"); - break; - } else if (command.equals("list")) { - display(); - list(); - } else if (command.startsWith("mark")) { - display(); - mark(command); - } else if (command.startsWith("unmark")) { - display(); - unmark(command); - } else if (command.startsWith("todo")) { - display(); - todo(command); - } else if (command.startsWith("deadline")) { - display(); - deadline(command); - } else if (command.startsWith("event")) { - display(); - event(command); - } else if (command.startsWith("delete")) { - display(); - delete(command); - } else { - display(); - System.out.println("\t ☹ OOPS!!! I'm sorry, but I don't know what that means.\n"); + String input = ui.readCommand(); + Command command = Parser.parse(input); + if (command != null) { + command.process(taskList, ui, storage); + isBye = command.isExit(); } - } catch (DukeException | IOException e) { + } catch (DukeException e) { System.out.println(e.getMessage()); } } } + public Ui getUi() { + return ui; + } + public static void main(String[] args) { Duke duke = new Duke(); duke.run(); } -} +} diff --git a/src/main/java/Event.java b/src/main/java/Event.java index 5c44e6896d..1556c348d6 100644 --- a/src/main/java/Event.java +++ b/src/main/java/Event.java @@ -1,84 +1,61 @@ -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; - -public class Event extends Task{ - protected LocalDateTime from; - protected LocalDateTime to; - - public Event(String description, String from, String to) { - super(description); - this.from = getStartDateTime(from); - this.to = getEndDateTime(to); - } - - public LocalDateTime getStartDateTime(String from) { - LocalDateTime startDateTime = null; - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); - try { - startDateTime = LocalDateTime.parse(from, dateTimeFormatter); - return startDateTime; - } catch (DateTimeParseException | NullPointerException e) { - System.out.println("\t Wrong Wrong Date Format!\n"); +public class Event extends Task { + private final String start; + private final String end; + private Event(String description, boolean isDone, String start, String end) { + super(description, isDone); + this.start = start; + this.end = end; + } + public static Event generate(String input) throws DukeException { + if (input.trim().equals("event")) { + throw new DukeException("\t ☹ OOPS!!! The description of a event cannot be empty.\n"); } - return startDateTime; - } - - public LocalDateTime getEndDateTime(String from) { - LocalDateTime endDateTime = null; - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); - try { - endDateTime = LocalDateTime.parse(from, dateTimeFormatter); - return endDateTime; - } catch (DateTimeParseException | NullPointerException e) { - System.out.println("\t Wrong Wrong Date Format!\n"); + String[] inputLine = input.split(" ", 2); + if (inputLine.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The description of a event cannot be empty.\n"); } - return endDateTime; - } - - public String startDateTime() { - String startDateTime = null; - String startDayOfWeek = null; - DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm"); - try { - startDateTime = this.from.format(format); - startDayOfWeek = this.from.getDayOfWeek().toString(); - return startDayOfWeek + ", " + startDateTime; - } catch (DateTimeParseException | NullPointerException e) { - System.out.println("\t Wrong Wrong Date Format!\n"); + String[] startEndTime = inputLine[1].split(" /from "); + if (startEndTime.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The start time of a event cannot be empty.\n"); } - - String endDateTime = this.to.format(format); - String endDayOfWeek = this.to.getDayOfWeek().toString(); - return startDayOfWeek + ", " + startDateTime; - } - - public String endDateTime() { - String endDateTime = null; - String endDayOfWeek = null; - DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm"); - try { - endDateTime = this.to.format(format); - endDayOfWeek = this.to.getDayOfWeek().toString(); - return endDayOfWeek + ", " + endDateTime; - } catch (DateTimeParseException | NullPointerException e) { - System.out.println("\t Wrong Wrong Date Format!\n"); + String[] dateTime = startEndTime[1].split(" /to "); + if (dateTime.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The end time of a event cannot be empty.\n"); } - return endDayOfWeek + ", " + endDateTime; + return new Event(startEndTime[0], false, DateTime.dateFormatter(dateTime[0]), DateTime.dateFormatter(dateTime[1])); } - public String getFrom() { - return startDateTime(); + public static Event generateTask(String[] taskLine) { + boolean isDone = taskLine[1].equals("1"); + return new Event(taskLine[2], isDone, taskLine[3], taskLine[4]); } - - public String getTo() { - return endDateTime(); + public String getStart() { + return start; + } + public String getEnd() { + return end; + } + @Override + public String getTaskType() { + return "E"; + } + @Override + public String storeTaskString() { + return this.getTaskType() + " | " + this.getMarkedString() + " | " + this.getDescription() + " | " + this.getStart() + " | " + this.getEnd(); } @Override public String toString() { - - return "[E]" + super.toString() + " (from: " + startDateTime() - + " to: " + endDateTime() + ")"; + String str = this.getDescription(); + boolean checked = this.isDone(); + String startTime = this.getStart(); + String endTime = this.getEnd(); + if (checked) { + return "[E][X] " + str + " (from: " + startTime + + " to: " + endTime + ")"; + } else { + return "[E][ ] " + str + " (from: " + startTime + + " to: " + endTime + ")"; + } } -} +} \ No newline at end of file diff --git a/src/main/java/ExitCommand.java b/src/main/java/ExitCommand.java new file mode 100644 index 0000000000..5385426773 --- /dev/null +++ b/src/main/java/ExitCommand.java @@ -0,0 +1,14 @@ +public class ExitCommand extends Command { + public ExitCommand(String inputArr) { + super(inputArr); + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) { + ui.printByeMsg(); + } + @Override + public boolean isExit() { + return true; + } +} \ No newline at end of file diff --git a/src/main/java/ListCommand.java b/src/main/java/ListCommand.java new file mode 100644 index 0000000000..0957ec6399 --- /dev/null +++ b/src/main/java/ListCommand.java @@ -0,0 +1,15 @@ +public class ListCommand extends Command { + public ListCommand(String inputArr) { + super(inputArr); + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + taskList.listTask(this.getInputArr()); + } + + @Override + public boolean isExit() { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/MarkTaskCommand.java b/src/main/java/MarkTaskCommand.java new file mode 100644 index 0000000000..abb4018c98 --- /dev/null +++ b/src/main/java/MarkTaskCommand.java @@ -0,0 +1,19 @@ +public class MarkTaskCommand extends Command { + + private final boolean isMarked; + + public MarkTaskCommand(String inputArr, boolean isMarked) { + super(inputArr); + this.isMarked = isMarked; + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + taskList.markTask(isMarked, this.getInputArr(), ui, storage); + } + + @Override + public boolean isExit() { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/Parser.java b/src/main/java/Parser.java new file mode 100644 index 0000000000..dace37945b --- /dev/null +++ b/src/main/java/Parser.java @@ -0,0 +1,77 @@ +public class Parser { + + private static final Ui ui = new Ui(); + + public static Command parse(String input) { + if (input.equals("bye")) { + ui.printLine(); + return new ExitCommand(input); + } else if (input.equals("list")) { + ui.printLine(); + return new ListCommand(input); + } else if (input.startsWith("mark")) { + ui.printLine(); + return new MarkTaskCommand(input, true); + } else if (input.startsWith("unmark")) { + ui.printLine(); + return new MarkTaskCommand(input, false); + } else if (input.startsWith("todo")) { + ui.printLine(); + return new AddTodoCommand(input); + } else if (input.startsWith("deadline")) { + ui.printLine(); + return new AddDeadlineCommand(input); + } else if (input.startsWith("event")) { + ui.printLine(); + return new AddEventCommand(input); + } else if (input.startsWith("delete")) { + ui.printLine(); + return new DeleteTaskCommand(input); + } else { + ui.printLine(); + System.out.println("\t ☹ OOPS!!! I'm sorry, but I don't know what that means.\n"); + } + return null; + } +} + + /** + private enum CommandNames { + LIST, MARK, UNMARK, TODO, DEADLINE, EVENT, DELETE, BYE + } + public static Command parse(String input) { + //String[] inputArr = input.split(" ", 2); + try { + CommandNames commandNames = CommandNames.valueOf(inputArr[0].toUpperCase()); + switch (commandNames) { + case LIST: + return new ListCommand(inputArr); + case MARK: + return new MarkTaskCommand(inputArr, true); + case UNMARK: + return new MarkTaskCommand(inputArr, false); + case TODO: + return new AddTodoCommand(inputArr); + case EVENT: + return new AddEventCommand(inputArr); + case DEADLINE: + return new AddDeadlineCommand(inputArr); + case DELETE: + return new DeleteTaskCommand(inputArr); + case BYE: + return new ExitCommand(inputArr); + default: + throw new DukeException("Unknown format"); + } + } catch (DukeException e) { + System.out.println(e.getMessage()); + } catch(NumberFormatException e) { + System.out.println("Please provide numbers"); + } catch(IllegalArgumentException e) { + System.out.println("Invalid Command"); + } catch (Exception e) { + System.out.println("Unknown error"); + } + return null; + } + **/ diff --git a/src/main/java/Storage.java b/src/main/java/Storage.java new file mode 100644 index 0000000000..6581379d12 --- /dev/null +++ b/src/main/java/Storage.java @@ -0,0 +1,77 @@ +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +public class Storage { + + private final String filePath; + + public Storage(String filePath) { + this.filePath = filePath; + checkFileExit(); + } + + public void checkFileExit() { + try { + Path file = Paths.get(".", filePath); + if (!Files.exists(file)) { + Files.createDirectories(file.getParent()); + Files.createFile(file); + } + } catch (IOException e) { + System.out.println("\t Invalid Path.\n"); + e.printStackTrace(); + } + } + + + public TaskList readData() { + ArrayList arrayList = new ArrayList<>(); + Path file = Paths.get(".", filePath); + try { + List taskLine = Files.readAllLines(file); + for (int i = 0; i < taskLine.size(); i++) { + String[] content = taskLine.get(i).split(" \\| "); + switch (content[0]) { + case "T": + arrayList.add(Todo.generateTask(content)); + break; + case "E": + arrayList.add(Event.generateTask(content)); + break; + case "D": + arrayList.add(Deadline.generateTask(content)); + break; + default: + throw new DukeException("\t Invalid data!\n"); + } + } + } catch (FileNotFoundException e) { + System.out.println("\t File not found.\n"); + } catch (DukeException e) { + System.out.println(e.getMessage()); + } catch (IOException e) { + System.out.println("\t Invalid Path.\n"); + } + return new TaskList(arrayList); + } + + + public void saveData(TaskList tasks) { + Path file = Paths.get(".", filePath); + ArrayList arrayList = tasks.getTasks(); + String data = ""; + try { + for (Task task : arrayList) { + data += task.storeTaskString() + "\n"; + } + Files.writeString(file, data); + } catch (IOException e) { + System.out.println("\t Invalid Path.\n"); + } + } +} diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 04d32dead6..d390e06323 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -1,38 +1,30 @@ -public class Task { - protected String description; - protected boolean isDone; - public Task(String description) { - this.description = description; - this.isDone = false; - } +public abstract class Task { - public String getDescription() { - return this.description; - } + private final String description; + + private boolean isDone; - public void setDone(boolean isDone) { + public Task(String description, boolean isDone) { + this.description = description; this.isDone = isDone; } - public String getStatusIcon() { - return (isDone ? "X" : " "); + public boolean isDone() { + return isDone; } - - public void mark() { - this.isDone = true; - System.out.println("\t Nice! I've marked this task as done:\n" - + "\t\t [X] " + this.description + "\n"); + public String getMarkedString() { + return isDone ? "1" : "0"; } - public void unmark() { - this.isDone = false; - System.out.println("\t OK, I've marked this task as not done yet:\n" - + "\t\t [ ] " + this.description + "\n"); + public String getDescription() { + return description; } - @Override - public String toString() { - return " [" + getStatusIcon() + "] " + this.description; + public void setDone(boolean done) { + this.isDone = done; } -} + + public abstract String storeTaskString(); + public abstract String getTaskType(); +} \ 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..31df286b63 --- /dev/null +++ b/src/main/java/TaskList.java @@ -0,0 +1,76 @@ +import java.util.ArrayList; + +public class TaskList { + private final ArrayList tasks; + public TaskList(ArrayList tasks) { + this.tasks = tasks; + } + public int getSize() { + return tasks.size(); + } + public ArrayList getTasks() { + return tasks; + } + public void listTask(String input) throws DukeException { + String[] inputLine = input.split(" ", 2); + if (inputLine.length > 1) { + throw new DukeException("\t ☹ OOPS!!! The format is invalid!\n"); + } + String str = ""; + for (int i = 0; i < tasks.size(); i++) { + str = "\t " + (i + 1) + ". " + tasks.get(i).toString(); + System.out.println(str); + } + System.out.print(""); + } + public void addTask(Task task) { + tasks.add(task); + } + + public void deleteTask(String input, Ui ui, Storage storage) throws DukeException { + if (input.trim().equals("delete")) { + throw new DukeException("\t ☹ OOPS!!! The description of a delete cannot be empty.\n"); + } + String[] inputLine = input.split(" ", 2); + if (inputLine.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The format is invalid, please give numbers.\n"); + } + int taskIndex; + try { + taskIndex = Integer.parseInt(inputLine[1]); + } catch (NumberFormatException e) { + throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); + } + int taskListSize = this.getSize(); + if (taskIndex < 1 || taskIndex > taskListSize) { + throw new DukeException("\t ☹ OOPS!!! The index is out of range.\n"); + } + Task task = tasks.get(taskIndex - 1); + tasks.remove(taskIndex - 1); + storage.saveData(this); + ui.printDeleteTaskMsg(task, tasks.size()); + } + public void markTask(boolean isDone, String input, Ui ui, Storage storage) throws DukeException { + if (input.trim().equals("mark") || input.trim().equals("unmark")) { + throw new DukeException("\t ☹ OOPS!!! Please input a number.\n"); + } + String[] inputLine = input.split(" ", 2); + if (inputLine.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The format is invalid, please give numbers.\n"); + } + int taskIndex; + try { + taskIndex = Integer.parseInt(inputLine[1]) - 1; + } catch (NumberFormatException e) { + throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); + } + int taskListSize = tasks.size(); + if (taskIndex + 1 > taskListSize || taskIndex < 0) { + throw new DukeException("\t ☹ OOPS!!! The index is out of range.\n"); + } + Task task = tasks.get(taskIndex); + task.setDone(isDone); + storage.saveData(this); + ui.printMarkTaskMsg(isDone, task); + } +} \ No newline at end of file diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java index 2a6fe09db2..774cc4a4cf 100644 --- a/src/main/java/Todo.java +++ b/src/main/java/Todo.java @@ -1,10 +1,41 @@ -public class Todo extends Task{ - public Todo(String description) { - super(description); +public class Todo extends Task { + + private Todo(String description, boolean isDone) { + super(description, isDone); } + + public static Todo generate(String input) throws DukeException { + if (input.trim().equals("todo")) { + throw new DukeException("\t ☹ OOPS!!! The description of a todo cannot be empty.\n"); + } + String[] inputLine = input.split(" ", 2); + if (inputLine.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The description of a todo cannot be empty.\n"); + } + return new Todo(inputLine[1], false); + } + + public static Todo generateTask(String[] taskLine) { + boolean isDone = taskLine[1].equals("1"); + return new Todo(taskLine[2], isDone); + } + @Override + public String getTaskType() { + return "T"; + } + @Override + public String storeTaskString() { + return this.getTaskType() + " | " + this.getMarkedString() + " | " + this.getDescription(); + } @Override public String toString() { - return "[T]" + super.toString(); + boolean checked = this.isDone(); + String str = this.getDescription(); + if (checked) { + return "[T][X] " + str; + } else { + return "[T][ ] " + str; + } } -} +} \ No newline at end of file diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java new file mode 100644 index 0000000000..a8b33e6419 --- /dev/null +++ b/src/main/java/Ui.java @@ -0,0 +1,50 @@ +import java.util.Scanner; + +public class Ui { + private final String LOGO = "\t ____ _ \n" + + "\t | _ \\ _ _| | _____ \n" + + "\t | | | | | | | |/ / _ \\\n" + + "\t | |_| | |_| | < __/\n" + + "\t |____/ \\__,_|_|\\_\\___|\n"; + private final String SEPARATE_LINE = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"; + private final String BYE_MSG = "\t Bye. Hope to see you again soon!"; + + private final Scanner scanner; + public Ui() { + scanner = new Scanner(System.in); + } + public String readCommand() { + return scanner.nextLine(); + } + public void printWelcomeMsg() { + String str = LOGO + "\t Hello! I am Duke.\n" + "\t What can I do for you?\n"; + System.out.println(str); + } + public void printLine() { + System.out.println(SEPARATE_LINE); + } + public void printAddTaskMsg(TaskList taskList, Task task) { + String str = "\t Got it. I've added this task:\n " + "\t\t " + + task.toString() + "\n\t Now you have " + taskList.getSize() + " tasks in the list\n"; + System.out.println(str); + } + public void printMarkTaskMsg(boolean isMarked, Task task) { + String str = ""; + if (isMarked) { + //str = "\t Nice! I've marked this task as done: \n" + "\t\t [" + task.getTaskType() + "] [x] " + task.getDescription() + "\n"; + str = "\t Nice! I've marked this task as done: \n" + "\t\t " + task.toString() + "\n"; + } else { + //str = "\t OK, I've marked this task as not done yet: \n" + "\t\t [" + task.getTaskType() + "] [ ] " + task.getDescription() + "\n"; + str = "\t OK, I've marked this task as not done yet: \n" + "\t\t " + task.toString() + "\n"; + } + System.out.println(str); + } + public void printDeleteTaskMsg(Task task, int size) { + String str = "\t Noted. I've removed this task:\n" + "\t\t " + + task.toString() + "\n\t Now you have " + size + " tasks in the list.\n"; + System.out.println(str); + } + public void printByeMsg() { + System.out.println(BYE_MSG); + } +} \ No newline at end of file From 6a8cd60a55cb09712f6dd5afcb737fcfeffd926e Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Mon, 13 Feb 2023 03:23:56 +0800 Subject: [PATCH 15/42] Add Increment: A-Packages --- src/main/java/command/AddDeadlineCommand.java | 21 +++++ src/main/java/command/AddEventCommand.java | 20 +++++ src/main/java/command/AddTaskCommand.java | 23 +++++ src/main/java/command/AddTodoCommand.java | 21 +++++ src/main/java/command/Command.java | 19 +++++ src/main/java/command/DeleteTaskCommand.java | 23 +++++ src/main/java/command/ExitCommand.java | 20 +++++ src/main/java/command/ListCommand.java | 22 +++++ src/main/java/command/MarkTaskCommand.java | 26 ++++++ src/main/java/duke/Duke.java | 49 +++++++++++ .../java/dukeexception/DukeException.java | 8 ++ src/main/java/storage/Storage.java | 85 +++++++++++++++++++ src/main/java/storage/TaskList.java | 82 ++++++++++++++++++ src/main/java/task/Deadline.java | 52 ++++++++++++ src/main/java/task/Event.java | 66 ++++++++++++++ src/main/java/task/Task.java | 31 +++++++ src/main/java/task/Todo.java | 45 ++++++++++ src/main/java/userinteraction/Parser.java | 81 ++++++++++++++++++ src/main/java/userinteraction/Ui.java | 55 ++++++++++++ src/main/java/utils/DateTime.java | 29 +++++++ 20 files changed, 778 insertions(+) create mode 100644 src/main/java/command/AddDeadlineCommand.java create mode 100644 src/main/java/command/AddEventCommand.java create mode 100644 src/main/java/command/AddTaskCommand.java create mode 100644 src/main/java/command/AddTodoCommand.java create mode 100644 src/main/java/command/Command.java create mode 100644 src/main/java/command/DeleteTaskCommand.java create mode 100644 src/main/java/command/ExitCommand.java create mode 100644 src/main/java/command/ListCommand.java create mode 100644 src/main/java/command/MarkTaskCommand.java create mode 100644 src/main/java/duke/Duke.java create mode 100644 src/main/java/dukeexception/DukeException.java create mode 100644 src/main/java/storage/Storage.java create mode 100644 src/main/java/storage/TaskList.java create mode 100644 src/main/java/task/Deadline.java create mode 100644 src/main/java/task/Event.java create mode 100644 src/main/java/task/Task.java create mode 100644 src/main/java/task/Todo.java create mode 100644 src/main/java/userinteraction/Parser.java create mode 100644 src/main/java/userinteraction/Ui.java create mode 100644 src/main/java/utils/DateTime.java diff --git a/src/main/java/command/AddDeadlineCommand.java b/src/main/java/command/AddDeadlineCommand.java new file mode 100644 index 0000000000..2ea7969c95 --- /dev/null +++ b/src/main/java/command/AddDeadlineCommand.java @@ -0,0 +1,21 @@ +package command; + +import dukeexception.DukeException; +import storage.Storage; +import storage.TaskList; +import task.Deadline; +import userinteraction.Ui; +public class AddDeadlineCommand extends AddTaskCommand{ + public AddDeadlineCommand(String inputArr) { + super(inputArr); + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + Deadline deadline = Deadline.generate(this.getInputArr()); + taskList.addTask(deadline); + storage.saveData(taskList); + ui.printAddTaskMsg(taskList, deadline); + } +} + diff --git a/src/main/java/command/AddEventCommand.java b/src/main/java/command/AddEventCommand.java new file mode 100644 index 0000000000..5e79f1eafa --- /dev/null +++ b/src/main/java/command/AddEventCommand.java @@ -0,0 +1,20 @@ +package command; + +import dukeexception.DukeException; +import storage.Storage; +import storage.TaskList; +import task.Event; +import userinteraction.Ui; +public class AddEventCommand extends AddTaskCommand { + public AddEventCommand(String inputArr) { + super(inputArr); + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + Event event = Event.generate(this.getInputArr()); + taskList.addTask(event); + storage.saveData(taskList); + ui.printAddTaskMsg(taskList, event); + } +} \ No newline at end of file diff --git a/src/main/java/command/AddTaskCommand.java b/src/main/java/command/AddTaskCommand.java new file mode 100644 index 0000000000..f563b8cfde --- /dev/null +++ b/src/main/java/command/AddTaskCommand.java @@ -0,0 +1,23 @@ +package command; + +import dukeexception.DukeException; +import storage.Storage; +import storage.TaskList; +import userinteraction.Ui; + +abstract class AddTaskCommand extends Command { + + public AddTaskCommand(String inputArr) { + super(inputArr); + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + + } + + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/command/AddTodoCommand.java b/src/main/java/command/AddTodoCommand.java new file mode 100644 index 0000000000..c1b5623f1a --- /dev/null +++ b/src/main/java/command/AddTodoCommand.java @@ -0,0 +1,21 @@ +package command; + +import dukeexception.DukeException; +import storage.Storage; +import storage.TaskList; +import task.Todo; +import userinteraction.Ui; + +public class AddTodoCommand extends AddTaskCommand { + public AddTodoCommand(String inputArr) { + super(inputArr); + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + Todo todo = Todo.generate(this.getInputArr()); + taskList.addTask(todo); + storage.saveData(taskList); + ui.printAddTaskMsg(taskList, todo); + } +} \ No newline at end of file diff --git a/src/main/java/command/Command.java b/src/main/java/command/Command.java new file mode 100644 index 0000000000..0269ecc332 --- /dev/null +++ b/src/main/java/command/Command.java @@ -0,0 +1,19 @@ +package command; + +import dukeexception.DukeException; +import storage.Storage; +import storage.TaskList; +import userinteraction.Ui; + +abstract public class Command { + private final String inputArr; + public Command(String inputArr) { + this.inputArr = inputArr; + } + + public String getInputArr() { + return inputArr; + } + public abstract void process(TaskList taskList, Ui ui, Storage storage) throws DukeException; + public abstract boolean isExit(); +} \ No newline at end of file diff --git a/src/main/java/command/DeleteTaskCommand.java b/src/main/java/command/DeleteTaskCommand.java new file mode 100644 index 0000000000..427b5b95e6 --- /dev/null +++ b/src/main/java/command/DeleteTaskCommand.java @@ -0,0 +1,23 @@ +package command; + +import dukeexception.DukeException; +import storage.Storage; +import storage.TaskList; +import userinteraction.Ui; + +public class DeleteTaskCommand extends Command { + + public DeleteTaskCommand(String inputArr) { + super(inputArr); + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + taskList.deleteTask(this.getInputArr(), ui, storage); + } + + @Override + public boolean isExit() { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/command/ExitCommand.java b/src/main/java/command/ExitCommand.java new file mode 100644 index 0000000000..eba904032b --- /dev/null +++ b/src/main/java/command/ExitCommand.java @@ -0,0 +1,20 @@ +package command; + +import storage.Storage; +import storage.TaskList; +import userinteraction.Ui; + +public class ExitCommand extends Command { + public ExitCommand(String inputArr) { + super(inputArr); + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) { + ui.printByeMsg(); + } + @Override + public boolean isExit() { + return true; + } +} \ No newline at end of file diff --git a/src/main/java/command/ListCommand.java b/src/main/java/command/ListCommand.java new file mode 100644 index 0000000000..5db438908c --- /dev/null +++ b/src/main/java/command/ListCommand.java @@ -0,0 +1,22 @@ +package command; + +import dukeexception.DukeException; +import storage.Storage; +import storage.TaskList; +import userinteraction.Ui; + +public class ListCommand extends Command { + public ListCommand(String inputArr) { + super(inputArr); + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + taskList.listTask(this.getInputArr()); + } + + @Override + public boolean isExit() { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/command/MarkTaskCommand.java b/src/main/java/command/MarkTaskCommand.java new file mode 100644 index 0000000000..1f7ab938bd --- /dev/null +++ b/src/main/java/command/MarkTaskCommand.java @@ -0,0 +1,26 @@ +package command; + +import dukeexception.DukeException; +import storage.Storage; +import storage.TaskList; +import userinteraction.Ui; + +public class MarkTaskCommand extends Command { + + private final boolean isMarked; + + public MarkTaskCommand(String inputArr, boolean isMarked) { + super(inputArr); + this.isMarked = isMarked; + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + taskList.markTask(isMarked, this.getInputArr(), ui, storage); + } + + @Override + public boolean isExit() { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java new file mode 100644 index 0000000000..d31b23469a --- /dev/null +++ b/src/main/java/duke/Duke.java @@ -0,0 +1,49 @@ +package duke; + +import command.Command; +import dukeexception.DukeException; +import storage.Storage; +import storage.TaskList; +import userinteraction.Parser; +import userinteraction.Ui; + +public class Duke { + private final static String FILE_PATH = ".\\src\\data\\duke.txt"; + + private final Ui ui; + private final Storage storage; + private final TaskList taskList; + public Duke() { + ui = new Ui(); + storage = new Storage(FILE_PATH); + taskList = storage.readData(); + } + + public void run() { + ui.printWelcomeMsg(); + ui.printLine(); + boolean isBye = false; + while (!isBye) { + try { + String input = ui.readCommand(); + Command command = Parser.parse(input); + if (command != null) { + command.process(taskList, ui, storage); + isBye = command.isExit(); + } + } catch (DukeException e) { + System.out.println(e.getMessage()); + } + } + } + + public Ui getUi() { + return ui; + } + + public static void main(String[] args) { + Duke duke = new Duke(); + duke.run(); + } + +} diff --git a/src/main/java/dukeexception/DukeException.java b/src/main/java/dukeexception/DukeException.java new file mode 100644 index 0000000000..7fca981340 --- /dev/null +++ b/src/main/java/dukeexception/DukeException.java @@ -0,0 +1,8 @@ +package dukeexception; + +public class DukeException extends Exception{ + + public DukeException(String message) { + super(message); + } +} diff --git a/src/main/java/storage/Storage.java b/src/main/java/storage/Storage.java new file mode 100644 index 0000000000..cb67391cd3 --- /dev/null +++ b/src/main/java/storage/Storage.java @@ -0,0 +1,85 @@ +package storage; + +import dukeexception.DukeException; +import task.Deadline; +import task.Event; +import task.Task; +import task.Todo; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +public class Storage { + + private final String filePath; + + public Storage(String filePath) { + this.filePath = filePath; + checkFileExit(); + } + + public void checkFileExit() { + try { + Path file = Paths.get(".", filePath); + if (!Files.exists(file)) { + Files.createDirectories(file.getParent()); + Files.createFile(file); + } + } catch (IOException e) { + System.out.println("\t Invalid Path.\n"); + e.printStackTrace(); + } + } + + + public TaskList readData() { + ArrayList arrayList = new ArrayList<>(); + Path file = Paths.get(".", filePath); + try { + List taskLine = Files.readAllLines(file); + for (int i = 0; i < taskLine.size(); i++) { + String[] content = taskLine.get(i).split(" \\| "); + switch (content[0]) { + case "T": + arrayList.add(Todo.generateTask(content)); + break; + case "E": + arrayList.add(Event.generateTask(content)); + break; + case "D": + arrayList.add(Deadline.generateTask(content)); + break; + default: + throw new DukeException("\t Invalid data!\n"); + } + } + } catch (FileNotFoundException e) { + System.out.println("\t File not found.\n"); + } catch (DukeException e) { + System.out.println(e.getMessage()); + } catch (IOException e) { + System.out.println("\t Invalid Path.\n"); + } + return new TaskList(arrayList); + } + + + public void saveData(TaskList tasks) { + Path file = Paths.get(".", filePath); + ArrayList arrayList = tasks.getTasks(); + String data = ""; + try { + for (Task task : arrayList) { + data += task.storeTaskString() + "\n"; + } + Files.writeString(file, data); + } catch (IOException e) { + System.out.println("\t Invalid Path.\n"); + } + } +} diff --git a/src/main/java/storage/TaskList.java b/src/main/java/storage/TaskList.java new file mode 100644 index 0000000000..05cec482fc --- /dev/null +++ b/src/main/java/storage/TaskList.java @@ -0,0 +1,82 @@ +package storage; + +import dukeexception.DukeException; +import task.Task; +import userinteraction.Ui; + +import java.util.ArrayList; + +public class TaskList { + private final ArrayList tasks; + public TaskList(ArrayList tasks) { + this.tasks = tasks; + } + public int getSize() { + return tasks.size(); + } + public ArrayList getTasks() { + return tasks; + } + public void listTask(String input) throws DukeException { + String[] inputLine = input.split(" ", 2); + if (inputLine.length > 1) { + throw new DukeException("\t ☹ OOPS!!! The format is invalid!\n"); + } + String str = ""; + for (int i = 0; i < tasks.size(); i++) { + str = "\t " + (i + 1) + ". " + tasks.get(i).toString(); + System.out.println(str); + } + System.out.print(""); + } + public void addTask(Task task) { + tasks.add(task); + } + + public void deleteTask(String input, Ui ui, Storage storage) throws DukeException { + if (input.trim().equals("delete")) { + throw new DukeException("\t ☹ OOPS!!! The description of a delete cannot be empty.\n"); + } + String[] inputLine = input.split(" ", 2); + if (inputLine.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The format is invalid, please give numbers.\n"); + } + int taskIndex; + try { + taskIndex = Integer.parseInt(inputLine[1]); + } catch (NumberFormatException e) { + throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); + } + int taskListSize = this.getSize(); + if (taskIndex < 1 || taskIndex > taskListSize) { + throw new DukeException("\t ☹ OOPS!!! The index is out of range.\n"); + } + Task task = tasks.get(taskIndex - 1); + tasks.remove(taskIndex - 1); + storage.saveData(this); + ui.printDeleteTaskMsg(task, tasks.size()); + } + public void markTask(boolean isDone, String input, Ui ui, Storage storage) throws DukeException { + if (input.trim().equals("mark") || input.trim().equals("unmark")) { + throw new DukeException("\t ☹ OOPS!!! Please input a number.\n"); + } + String[] inputLine = input.split(" ", 2); + if (inputLine.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The format is invalid, please give numbers.\n"); + } + int taskIndex; + try { + taskIndex = Integer.parseInt(inputLine[1]) - 1; + } catch (NumberFormatException e) { + throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); + } + int taskListSize = tasks.size(); + if (taskIndex + 1 > taskListSize || taskIndex < 0) { + throw new DukeException("\t ☹ OOPS!!! The index is out of range.\n"); + } + Task task = tasks.get(taskIndex); + task.setDone(isDone); + storage.saveData(this); + ui.printMarkTaskMsg(isDone, task); + } +} \ No newline at end of file diff --git a/src/main/java/task/Deadline.java b/src/main/java/task/Deadline.java new file mode 100644 index 0000000000..a3091e72a6 --- /dev/null +++ b/src/main/java/task/Deadline.java @@ -0,0 +1,52 @@ +package task; + +import dukeexception.DukeException; +import utils.DateTime; + +public class Deadline extends Task { + private String dateTime; + private Deadline(String description, boolean isDone, String dateTime) { + super(description, isDone); + this.dateTime = dateTime; + } + public static Deadline generate(String input) throws DukeException { + if (input.trim().equals("deadline")) { + throw new DukeException("\t ☹ OOPS!!! The description of a deadline cannot be empty.\n"); + } + String[] inputLine = input.split(" ", 2); + if (inputLine.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The description of a deadline cannot be empty.\n"); + } + String[] descriptions = inputLine[1].split(" /by ", 2); + if (descriptions.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The date time of a deadline cannot be empty.\n"); + } + return new Deadline(descriptions[0], false, DateTime.dateFormatter(descriptions[1])); + } + public static Deadline generateTask(String[] taskLine) { + boolean check = taskLine[1].equals("1"); + return new Deadline(taskLine[2], check, taskLine[3]); + } + public String getDateTime() { + return dateTime; + } + @Override + public String getTaskType() { + return "D"; + } + @Override + public String storeTaskString() { + return this.getTaskType() + " | " + this.getMarkedString() + " | " + this.getDescription() + " | " + this.getDateTime(); + } + @Override + public String toString() { + String str = this.getDescription(); + boolean checked = this.isDone(); + String dateTime = this.getDateTime(); + if (checked) { + return "[D][X] " + str + " (by: " + dateTime + ")"; + } else { + return "[D][ ] " + str + " (by: " + dateTime + ")"; + } + } +} \ No newline at end of file diff --git a/src/main/java/task/Event.java b/src/main/java/task/Event.java new file mode 100644 index 0000000000..298aef5da6 --- /dev/null +++ b/src/main/java/task/Event.java @@ -0,0 +1,66 @@ +package task; + +import dukeexception.DukeException; +import utils.DateTime; + +public class Event extends Task { + private final String start; + private final String end; + private Event(String description, boolean isDone, String start, String end) { + super(description, isDone); + this.start = start; + this.end = end; + } + public static Event generate(String input) throws DukeException { + if (input.trim().equals("event")) { + throw new DukeException("\t ☹ OOPS!!! The description of a event cannot be empty.\n"); + } + String[] inputLine = input.split(" ", 2); + if (inputLine.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The description of a event cannot be empty.\n"); + } + String[] startEndTime = inputLine[1].split(" /from "); + if (startEndTime.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The start time of a event cannot be empty.\n"); + } + String[] dateTime = startEndTime[1].split(" /to "); + if (dateTime.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The end time of a event cannot be empty.\n"); + } + return new Event(startEndTime[0], false, DateTime.dateFormatter(dateTime[0]), DateTime.dateFormatter(dateTime[1])); + } + + public static Event generateTask(String[] taskLine) { + boolean isDone = taskLine[1].equals("1"); + return new Event(taskLine[2], isDone, taskLine[3], taskLine[4]); + } + public String getStart() { + return start; + } + public String getEnd() { + return end; + } + @Override + public String getTaskType() { + return "E"; + } + @Override + public String storeTaskString() { + return this.getTaskType() + " | " + this.getMarkedString() + " | " + this.getDescription() + " | " + this.getStart() + " | " + this.getEnd(); + } + + @Override + public String toString() { + String str = this.getDescription(); + boolean checked = this.isDone(); + String startTime = this.getStart(); + String endTime = this.getEnd(); + if (checked) { + return "[E][X] " + str + " (from: " + startTime + + " to: " + endTime + ")"; + } else { + return "[E][ ] " + str + " (from: " + startTime + + " to: " + endTime + ")"; + } + } +} \ No newline at end of file diff --git a/src/main/java/task/Task.java b/src/main/java/task/Task.java new file mode 100644 index 0000000000..6bf18cc62e --- /dev/null +++ b/src/main/java/task/Task.java @@ -0,0 +1,31 @@ +package task; + +public abstract class Task { + + private final String description; + + private boolean isDone; + + public Task(String description, boolean isDone) { + this.description = description; + this.isDone = isDone; + } + + public boolean isDone() { + return isDone; + } + public String getMarkedString() { + return isDone ? "1" : "0"; + } + + public String getDescription() { + return description; + } + + public void setDone(boolean done) { + this.isDone = done; + } + + public abstract String storeTaskString(); + public abstract String getTaskType(); +} \ No newline at end of file diff --git a/src/main/java/task/Todo.java b/src/main/java/task/Todo.java new file mode 100644 index 0000000000..229344111c --- /dev/null +++ b/src/main/java/task/Todo.java @@ -0,0 +1,45 @@ +package task; + +import dukeexception.DukeException; + +public class Todo extends Task { + + private Todo(String description, boolean isDone) { + super(description, isDone); + } + + + public static Todo generate(String input) throws DukeException { + if (input.trim().equals("todo")) { + throw new DukeException("\t ☹ OOPS!!! The description of a todo cannot be empty.\n"); + } + String[] inputLine = input.split(" ", 2); + if (inputLine.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The description of a todo cannot be empty.\n"); + } + return new Todo(inputLine[1], false); + } + + public static Todo generateTask(String[] taskLine) { + boolean isDone = taskLine[1].equals("1"); + return new Todo(taskLine[2], isDone); + } + @Override + public String getTaskType() { + return "T"; + } + @Override + public String storeTaskString() { + return this.getTaskType() + " | " + this.getMarkedString() + " | " + this.getDescription(); + } + @Override + public String toString() { + boolean checked = this.isDone(); + String str = this.getDescription(); + if (checked) { + return "[T][X] " + str; + } else { + return "[T][ ] " + str; + } + } +} \ No newline at end of file diff --git a/src/main/java/userinteraction/Parser.java b/src/main/java/userinteraction/Parser.java new file mode 100644 index 0000000000..11f51e23f3 --- /dev/null +++ b/src/main/java/userinteraction/Parser.java @@ -0,0 +1,81 @@ +package userinteraction; + +import command.*; + +public class Parser { + + private static final Ui ui = new Ui(); + + public static Command parse(String input) { + if (input.equals("bye")) { + ui.printLine(); + return new ExitCommand(input); + } else if (input.equals("list")) { + ui.printLine(); + return new ListCommand(input); + } else if (input.startsWith("mark")) { + ui.printLine(); + return new MarkTaskCommand(input, true); + } else if (input.startsWith("unmark")) { + ui.printLine(); + return new MarkTaskCommand(input, false); + } else if (input.startsWith("todo")) { + ui.printLine(); + return new AddTodoCommand(input); + } else if (input.startsWith("deadline")) { + ui.printLine(); + return new AddDeadlineCommand(input); + } else if (input.startsWith("event")) { + ui.printLine(); + return new AddEventCommand(input); + } else if (input.startsWith("delete")) { + ui.printLine(); + return new DeleteTaskCommand(input); + } else { + ui.printLine(); + System.out.println("\t ☹ OOPS!!! I'm sorry, but I don't know what that means.\n"); + } + return null; + } +} + + /** + private enum CommandNames { + LIST, MARK, UNMARK, TODO, DEADLINE, EVENT, DELETE, BYE + } + public static command.Command parse(String input) { + //String[] inputArr = input.split(" ", 2); + try { + CommandNames commandNames = CommandNames.valueOf(inputArr[0].toUpperCase()); + switch (commandNames) { + case LIST: + return new command.ListCommand(inputArr); + case MARK: + return new command.MarkTaskCommand(inputArr, true); + case UNMARK: + return new command.MarkTaskCommand(inputArr, false); + case TODO: + return new command.AddTodoCommand(inputArr); + case EVENT: + return new command.AddEventCommand(inputArr); + case DEADLINE: + return new command.AddDeadlineCommand(inputArr); + case DELETE: + return new command.DeleteTaskCommand(inputArr); + case BYE: + return new command.ExitCommand(inputArr); + default: + throw new dukeexception.DukeException("Unknown format"); + } + } catch (dukeexception.DukeException e) { + System.out.println(e.getMessage()); + } catch(NumberFormatException e) { + System.out.println("Please provide numbers"); + } catch(IllegalArgumentException e) { + System.out.println("Invalid command.Command"); + } catch (Exception e) { + System.out.println("Unknown error"); + } + return null; + } + **/ diff --git a/src/main/java/userinteraction/Ui.java b/src/main/java/userinteraction/Ui.java new file mode 100644 index 0000000000..6398a18f87 --- /dev/null +++ b/src/main/java/userinteraction/Ui.java @@ -0,0 +1,55 @@ +package userinteraction; + +import storage.TaskList; +import task.Task; + +import java.util.Scanner; + +public class Ui { + private final String LOGO = "\t ____ _ \n" + + "\t | _ \\ _ _| | _____ \n" + + "\t | | | | | | | |/ / _ \\\n" + + "\t | |_| | |_| | < __/\n" + + "\t |____/ \\__,_|_|\\_\\___|\n"; + private final String SEPARATE_LINE = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"; + private final String BYE_MSG = "\t Bye. Hope to see you again soon!"; + + private final Scanner scanner; + public Ui() { + scanner = new Scanner(System.in); + } + public String readCommand() { + return scanner.nextLine(); + } + public void printWelcomeMsg() { + String str = LOGO + "\t Hello! I am duke.Duke.\n" + "\t What can I do for you?\n"; + System.out.println(str); + } + public void printLine() { + System.out.println(SEPARATE_LINE); + } + public void printAddTaskMsg(TaskList taskList, Task task) { + String str = "\t Got it. I've added this task:\n " + "\t\t " + + task.toString() + "\n\t Now you have " + taskList.getSize() + " tasks in the list\n"; + System.out.println(str); + } + public void printMarkTaskMsg(boolean isMarked, Task task) { + String str = ""; + if (isMarked) { + //str = "\t Nice! I've marked this task as done: \n" + "\t\t [" + task.getTaskType() + "] [x] " + task.getDescription() + "\n"; + str = "\t Nice! I've marked this task as done: \n" + "\t\t " + task.toString() + "\n"; + } else { + //str = "\t OK, I've marked this task as not done yet: \n" + "\t\t [" + task.getTaskType() + "] [ ] " + task.getDescription() + "\n"; + str = "\t OK, I've marked this task as not done yet: \n" + "\t\t " + task.toString() + "\n"; + } + System.out.println(str); + } + public void printDeleteTaskMsg(Task task, int size) { + String str = "\t Noted. I've removed this task:\n" + "\t\t " + + task.toString() + "\n\t Now you have " + size + " tasks in the list.\n"; + System.out.println(str); + } + public void printByeMsg() { + System.out.println(BYE_MSG); + } +} \ No newline at end of file diff --git a/src/main/java/utils/DateTime.java b/src/main/java/utils/DateTime.java new file mode 100644 index 0000000000..fdc57c84ca --- /dev/null +++ b/src/main/java/utils/DateTime.java @@ -0,0 +1,29 @@ +package utils; + +import dukeexception.DukeException; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +public class DateTime { + + public static LocalDateTime getDateTime(String date) throws DukeException { + try { + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); + LocalDateTime localDateTime = LocalDateTime.parse(date, dateTimeFormatter); + return localDateTime; + } catch (DateTimeParseException e) { + throw new DukeException("\t Wrong Date Format, please write in yyyy-MM-dd HHmm.\n"); + } + } + public static String dateFormatter(String date) throws DukeException { + try { + LocalDateTime localDateTime = getDateTime(date); + return localDateTime.format(DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm")); + } catch (DateTimeParseException e) { + throw new DukeException("\t Wrong Date Format, please write in yyyy-MM-dd HHmm.\n"); + } + } + +} From 1a752747527253872d12660f659e6beeea4c32f3 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Mon, 13 Feb 2023 04:22:38 +0800 Subject: [PATCH 16/42] Add Increment: A-Gradle --- build.gradle | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 885198fcfa..3322710577 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' } @@ -28,7 +29,11 @@ test { } application { - mainClassName = "seedu.duke.Duke" + mainClassName = "duke.Duke" +} + +checkstyle { + toolVersion = '10.2' } shadowJar { From f896222aebecd611ddcee42fd5e2867723e2b5ff Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Mon, 13 Feb 2023 13:33:43 +0800 Subject: [PATCH 17/42] Add Increment: A-JUnit --- src/test/java/task/DeadlineTest.java | 30 +++++++++++++++++++++++++++ src/test/java/utils/DateTimeTest.java | 18 ++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/test/java/task/DeadlineTest.java create mode 100644 src/test/java/utils/DateTimeTest.java diff --git a/src/test/java/task/DeadlineTest.java b/src/test/java/task/DeadlineTest.java new file mode 100644 index 0000000000..2c0c846f77 --- /dev/null +++ b/src/test/java/task/DeadlineTest.java @@ -0,0 +1,30 @@ +package task; + +import dukeexception.DukeException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DeadlineTest { + private String input = "deadline buy book /by 2018-09-08 1800"; + + @Test + public void storeTaskString() { + try { + Deadline deadline = Deadline.generate(input); + assertEquals(deadline.storeTaskString(), "D | 0 | buy book | Sep 08 2018 18:00"); + } catch (DukeException e) { + throw new RuntimeException(e); + } + } + + @Test + public void getTaskTypeTest() { + try { + Deadline deadline = Deadline.generate(input); + assertEquals(deadline.getTaskType(), "D"); + } catch (DukeException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/test/java/utils/DateTimeTest.java b/src/test/java/utils/DateTimeTest.java new file mode 100644 index 0000000000..5f0b18c8b1 --- /dev/null +++ b/src/test/java/utils/DateTimeTest.java @@ -0,0 +1,18 @@ +package utils; + +import dukeexception.DukeException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DateTimeTest { + @Test + public void getDateTimeTest() { + try { + assertEquals(DateTime.dateFormatter("2018-08-05 1800"), "Aug 05 2018 18:00"); + assertEquals(DateTime.dateFormatter("2022-02-02 0937"),"Feb 02 2022 09:37"); + } catch (DukeException e) { + System.out.println(e.getMessage()); + } + } +} From 5e8439925357c6e361b745de65b8162b89206a4d Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Mon, 13 Feb 2023 22:33:21 +0800 Subject: [PATCH 18/42] Add Increments as parallel branches: A-JavaDoc --- src/main/java/command/AddDeadlineCommand.java | 17 ++++++++ src/main/java/command/AddEventCommand.java | 17 ++++++++ src/main/java/command/AddTaskCommand.java | 22 +++++++++- src/main/java/command/AddTodoCommand.java | 16 ++++++++ src/main/java/command/Command.java | 24 +++++++++++ src/main/java/command/DeleteTaskCommand.java | 22 +++++++++- src/main/java/command/ExitCommand.java | 8 ++++ src/main/java/command/ListCommand.java | 16 ++++++++ src/main/java/command/MarkTaskCommand.java | 22 ++++++++++ src/main/java/duke/Duke.java | 14 +++++-- .../java/dukeexception/DukeException.java | 8 ++++ src/main/java/storage/Storage.java | 22 +++++++++- src/main/java/storage/TaskList.java | 40 ++++++++++++++++++ src/main/java/task/Deadline.java | 26 ++++++++++++ src/main/java/task/Event.java | 26 ++++++++++++ src/main/java/task/Task.java | 9 ++++ src/main/java/task/Todo.java | 22 ++++++++++ src/main/java/userinteraction/Parser.java | 41 ------------------- src/main/java/utils/DateTime.java | 18 ++++++++ 19 files changed, 342 insertions(+), 48 deletions(-) diff --git a/src/main/java/command/AddDeadlineCommand.java b/src/main/java/command/AddDeadlineCommand.java index 2ea7969c95..b5592e2508 100644 --- a/src/main/java/command/AddDeadlineCommand.java +++ b/src/main/java/command/AddDeadlineCommand.java @@ -5,11 +5,28 @@ import storage.TaskList; import task.Deadline; import userinteraction.Ui; + +/** + * Command class for adding deadline tasks. + */ public class AddDeadlineCommand extends AddTaskCommand{ + /** + * Class constructor. + * + * @param inputArr String from a user input. + */ public AddDeadlineCommand(String inputArr) { super(inputArr); } + /** + * Creates a deadline task, adds it to the task list and saves it to the file. + * + * @param taskList Stores all tasks. + * @param ui The Ui to be used for printing messages. + * @param storage Saves all tasks in a file + * @throws DukeException Checks the validation of input. + */ @Override public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { Deadline deadline = Deadline.generate(this.getInputArr()); diff --git a/src/main/java/command/AddEventCommand.java b/src/main/java/command/AddEventCommand.java index 5e79f1eafa..39029af73a 100644 --- a/src/main/java/command/AddEventCommand.java +++ b/src/main/java/command/AddEventCommand.java @@ -5,11 +5,28 @@ import storage.TaskList; import task.Event; import userinteraction.Ui; + +/** + * Command class for adding event tasks. + */ public class AddEventCommand extends AddTaskCommand { + /** + * Class constructor. + * + * @param inputArr String from a user input. + */ public AddEventCommand(String inputArr) { super(inputArr); } + /** + * Creates a deadline task, adds it to the task list and saves it to the file. + * + * @param taskList Stores all tasks. + * @param ui The Ui to be used for printing messages. + * @param storage Saves all tasks in a file + * @throws DukeException Checks the validation of input. + */ @Override public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { Event event = Event.generate(this.getInputArr()); diff --git a/src/main/java/command/AddTaskCommand.java b/src/main/java/command/AddTaskCommand.java index f563b8cfde..56e08fc2ef 100644 --- a/src/main/java/command/AddTaskCommand.java +++ b/src/main/java/command/AddTaskCommand.java @@ -5,17 +5,37 @@ import storage.TaskList; import userinteraction.Ui; +/** + * Abstract class for adding tasks. + */ abstract class AddTaskCommand extends Command { - + /** + * Class constructor. + * + * @param inputArr String from a user input. + */ public AddTaskCommand(String inputArr) { super(inputArr); } + /** + * Creates a task, adds it to the task list and saves it to the file. + * + * @param taskList Stores all tasks. + * @param ui The Ui to be used for printing messages. + * @param storage Saves all tasks in a file + * @throws DukeException Checks the validation of input. + */ @Override public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { } + /** + * Checks whether exit the program. + * + * @return Boolean Exit the program. + */ @Override public boolean isExit() { return false; diff --git a/src/main/java/command/AddTodoCommand.java b/src/main/java/command/AddTodoCommand.java index c1b5623f1a..76a700d3e2 100644 --- a/src/main/java/command/AddTodoCommand.java +++ b/src/main/java/command/AddTodoCommand.java @@ -6,11 +6,27 @@ import task.Todo; import userinteraction.Ui; +/** + * Command class for adding todo tasks. + */ public class AddTodoCommand extends AddTaskCommand { + /** + * Class constructor. + * + * @param inputArr String from a user input. + */ public AddTodoCommand(String inputArr) { super(inputArr); } + /** + * Creates a todo task, adds it to the task list and saves it to the file. + * + * @param taskList Stores all tasks. + * @param ui The Ui to be used for printing messages. + * @param storage Saves all tasks in a file + * @throws DukeException Checks the validation of input. + */ @Override public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { Todo todo = Todo.generate(this.getInputArr()); diff --git a/src/main/java/command/Command.java b/src/main/java/command/Command.java index 0269ecc332..dec81fd07b 100644 --- a/src/main/java/command/Command.java +++ b/src/main/java/command/Command.java @@ -5,8 +5,17 @@ import storage.TaskList; import userinteraction.Ui; +/** + * Abstract class about users' commands. + */ abstract public class Command { private final String inputArr; + + /** + * Class constructor. + * + * @param inputArr String from a user input. + */ public Command(String inputArr) { this.inputArr = inputArr; } @@ -14,6 +23,21 @@ public Command(String inputArr) { public String getInputArr() { return inputArr; } + + /** + * Creates a todo task, adds it to the task list and saves it to the file. + * + * @param taskList Stores all tasks. + * @param ui The Ui to be used for printing messages. + * @param storage Saves all tasks in a file + * @throws DukeException Checks the validation of input. + */ public abstract void process(TaskList taskList, Ui ui, Storage storage) throws DukeException; + + /** + * Checks whether exit the program. + * + * @return Boolean Exit the program. + */ public abstract boolean isExit(); } \ No newline at end of file diff --git a/src/main/java/command/DeleteTaskCommand.java b/src/main/java/command/DeleteTaskCommand.java index 427b5b95e6..ece4682388 100644 --- a/src/main/java/command/DeleteTaskCommand.java +++ b/src/main/java/command/DeleteTaskCommand.java @@ -5,17 +5,37 @@ import storage.TaskList; import userinteraction.Ui; +/** + * Command class for adding deadline tasks. + */ public class DeleteTaskCommand extends Command { - + /** + * Class constructor. + * + * @param inputArr String from a user input. + */ public DeleteTaskCommand(String inputArr) { super(inputArr); } + /** + * Deletes a task, both of task list and file. + * + * @param taskList Stores all tasks. + * @param ui The Ui to be used for printing messages. + * @param storage Deletes a task in a file. + * @throws DukeException Checks the validation of input. + */ @Override public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { taskList.deleteTask(this.getInputArr(), ui, storage); } + /** + * Checks whether exit the program. + * + * @return Boolean Exit the program. + */ @Override public boolean isExit() { return false; diff --git a/src/main/java/command/ExitCommand.java b/src/main/java/command/ExitCommand.java index eba904032b..c820c2b94b 100644 --- a/src/main/java/command/ExitCommand.java +++ b/src/main/java/command/ExitCommand.java @@ -4,7 +4,15 @@ import storage.TaskList; import userinteraction.Ui; +/** + * Command class for exiting the program. + */ public class ExitCommand extends Command { + /** + * Class constructor. + * + * @param inputArr String from a user input. + */ public ExitCommand(String inputArr) { super(inputArr); } diff --git a/src/main/java/command/ListCommand.java b/src/main/java/command/ListCommand.java index 5db438908c..e27bb4396f 100644 --- a/src/main/java/command/ListCommand.java +++ b/src/main/java/command/ListCommand.java @@ -5,11 +5,27 @@ import storage.TaskList; import userinteraction.Ui; +/** + * Command class for listing tasks. + */ public class ListCommand extends Command { + /** + * Class constructor. + * + * @param inputArr String from a user input. + */ public ListCommand(String inputArr) { super(inputArr); } + /** + * Lists all tasks. + * + * @param taskList Stores all tasks. + * @param ui The Ui to be used for printing messages. + * @param storage Saves all tasks in a file + * @throws DukeException Checks the validation of input. + */ @Override public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { taskList.listTask(this.getInputArr()); diff --git a/src/main/java/command/MarkTaskCommand.java b/src/main/java/command/MarkTaskCommand.java index 1f7ab938bd..8c0463c203 100644 --- a/src/main/java/command/MarkTaskCommand.java +++ b/src/main/java/command/MarkTaskCommand.java @@ -5,20 +5,42 @@ import storage.TaskList; import userinteraction.Ui; +/** + * Command class for mark or unmarking tasks. + */ public class MarkTaskCommand extends Command { private final boolean isMarked; + /** + * Class constructor. + * + * @param inputArr String from a user input. + * @param isMarked Boolean to mark or unmark the task. + */ public MarkTaskCommand(String inputArr, boolean isMarked) { super(inputArr); this.isMarked = isMarked; } + /** + * Marks or unmarks a task. + * + * @param taskList Stores all tasks. + * @param ui The Ui to be used for printing messages. + * @param storage Saves all tasks in a file + * @throws DukeException Checks the validation of input. + */ @Override public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { taskList.markTask(isMarked, this.getInputArr(), ui, storage); } + /** + * Checks whether exit the program. + * + * @return Boolean Exit the program. + */ @Override public boolean isExit() { return false; diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java index d31b23469a..734bd7a86d 100644 --- a/src/main/java/duke/Duke.java +++ b/src/main/java/duke/Duke.java @@ -7,18 +7,28 @@ import userinteraction.Parser; import userinteraction.Ui; +/** + * The main class of the program. + */ public class Duke { private final static String FILE_PATH = ".\\src\\data\\duke.txt"; private final Ui ui; private final Storage storage; private final TaskList taskList; + + /** + * Class constructor. + */ public Duke() { ui = new Ui(); storage = new Storage(FILE_PATH); taskList = storage.readData(); } + /** + * Runs the whole program. + */ public void run() { ui.printWelcomeMsg(); ui.printLine(); @@ -37,10 +47,6 @@ public void run() { } } - public Ui getUi() { - return ui; - } - public static void main(String[] args) { Duke duke = new Duke(); duke.run(); diff --git a/src/main/java/dukeexception/DukeException.java b/src/main/java/dukeexception/DukeException.java index 7fca981340..f4e8d03bfe 100644 --- a/src/main/java/dukeexception/DukeException.java +++ b/src/main/java/dukeexception/DukeException.java @@ -1,7 +1,15 @@ package dukeexception; +/** + * Exception class. + */ public class DukeException extends Exception{ + /** + * Class constructor. + * + * @param message Error message is to be printed. + */ public DukeException(String message) { super(message); } diff --git a/src/main/java/storage/Storage.java b/src/main/java/storage/Storage.java index cb67391cd3..ef3f37ff73 100644 --- a/src/main/java/storage/Storage.java +++ b/src/main/java/storage/Storage.java @@ -14,15 +14,26 @@ import java.util.ArrayList; import java.util.List; +/** + * Storage class to deal with the file. + */ public class Storage { private final String filePath; + /** + * Class constructor. + * + * @param filePath The path of a file to be stored. + */ public Storage(String filePath) { this.filePath = filePath; checkFileExit(); } + /** + * Checks whether the file exits. + */ public void checkFileExit() { try { Path file = Paths.get(".", filePath); @@ -36,7 +47,11 @@ public void checkFileExit() { } } - + /** + * Reads the tasks from the file. + * + * @return Tasklist which is stored in the file. + */ public TaskList readData() { ArrayList arrayList = new ArrayList<>(); Path file = Paths.get(".", filePath); @@ -69,6 +84,11 @@ public TaskList readData() { } + /** + * Saves tasks into the file. + * + * @param tasks Tasks are stored in the file. + */ public void saveData(TaskList tasks) { Path file = Paths.get(".", filePath); ArrayList arrayList = tasks.getTasks(); diff --git a/src/main/java/storage/TaskList.java b/src/main/java/storage/TaskList.java index 05cec482fc..b989998d83 100644 --- a/src/main/java/storage/TaskList.java +++ b/src/main/java/storage/TaskList.java @@ -6,17 +6,34 @@ import java.util.ArrayList; +/** + * Task list class which stores all tasks. + */ public class TaskList { private final ArrayList tasks; + + /** + * Class constructor. + * + * @param tasks Arraylist that stores all tasks. + */ public TaskList(ArrayList tasks) { this.tasks = tasks; } + public int getSize() { return tasks.size(); } public ArrayList getTasks() { return tasks; } + + /** + * List all the tasks. + * + * @param input User input. + * @throws DukeException Checks the validation of input. + */ public void listTask(String input) throws DukeException { String[] inputLine = input.split(" ", 2); if (inputLine.length > 1) { @@ -29,10 +46,24 @@ public void listTask(String input) throws DukeException { } System.out.print(""); } + + /** + * Adds a task into task list. + * + * @param task A task. + */ public void addTask(Task task) { tasks.add(task); } + /** + * Deletes a task in the task list. + * + * @param input User input + * @param ui The Ui to be used for printing messages. + * @param storage Deletes a task in a file. + * @throws DukeException Checks the validation of input. + */ public void deleteTask(String input, Ui ui, Storage storage) throws DukeException { if (input.trim().equals("delete")) { throw new DukeException("\t ☹ OOPS!!! The description of a delete cannot be empty.\n"); @@ -56,6 +87,15 @@ public void deleteTask(String input, Ui ui, Storage storage) throws DukeExceptio storage.saveData(this); ui.printDeleteTaskMsg(task, tasks.size()); } + + /** + * Marks or unmarks a task. + * + * @param isDone Boolean to mark or unmark a task. + * @param input User Input. + * @param ui The Ui to be used for printing messages. + * @throws DukeException Checks the validation of input. + */ public void markTask(boolean isDone, String input, Ui ui, Storage storage) throws DukeException { if (input.trim().equals("mark") || input.trim().equals("unmark")) { throw new DukeException("\t ☹ OOPS!!! Please input a number.\n"); diff --git a/src/main/java/task/Deadline.java b/src/main/java/task/Deadline.java index a3091e72a6..c5b1d9b8c6 100644 --- a/src/main/java/task/Deadline.java +++ b/src/main/java/task/Deadline.java @@ -3,12 +3,31 @@ import dukeexception.DukeException; import utils.DateTime; +/** + * Deadline class to deal with deadline tasks. + */ public class Deadline extends Task { private String dateTime; + + /** + * Class constructor. + * + * @param description The description of the task. + * @param isDone Marks or unmarks the task. + * @param dateTime Deadline date time. + */ private Deadline(String description, boolean isDone, String dateTime) { super(description, isDone); this.dateTime = dateTime; } + + /** + * Returns deadline task based on the user input. + * + * @param input User Input. + * @return Deadline task. + * @throws DukeException Checks the validation of input. + */ public static Deadline generate(String input) throws DukeException { if (input.trim().equals("deadline")) { throw new DukeException("\t ☹ OOPS!!! The description of a deadline cannot be empty.\n"); @@ -23,6 +42,13 @@ public static Deadline generate(String input) throws DukeException { } return new Deadline(descriptions[0], false, DateTime.dateFormatter(descriptions[1])); } + + /** + * Returns a deadline task from the file. + * + * @param taskLine Each line from the input file. + * @return Deadline task. + */ public static Deadline generateTask(String[] taskLine) { boolean check = taskLine[1].equals("1"); return new Deadline(taskLine[2], check, taskLine[3]); diff --git a/src/main/java/task/Event.java b/src/main/java/task/Event.java index 298aef5da6..a8c0c63834 100644 --- a/src/main/java/task/Event.java +++ b/src/main/java/task/Event.java @@ -3,14 +3,34 @@ import dukeexception.DukeException; import utils.DateTime; +/** + * Event class to deal with event tasks. + */ public class Event extends Task { private final String start; private final String end; + + /** + * Class constructor. + * + * @param description The description of the task. + * @param isDone Marks or unmarks the task. + * @param start Event start date time. + * @param start Event end date time. + */ private Event(String description, boolean isDone, String start, String end) { super(description, isDone); this.start = start; this.end = end; } + + /** + * Returns event task based on the user input. + * + * @param input User Input. + * @return Event task. + * @throws DukeException Checks the validation of input. + */ public static Event generate(String input) throws DukeException { if (input.trim().equals("event")) { throw new DukeException("\t ☹ OOPS!!! The description of a event cannot be empty.\n"); @@ -30,6 +50,12 @@ public static Event generate(String input) throws DukeException { return new Event(startEndTime[0], false, DateTime.dateFormatter(dateTime[0]), DateTime.dateFormatter(dateTime[1])); } + /** + * Returns a event task from the file. + * + * @param taskLine Each line from the input file. + * @return Event task. + */ public static Event generateTask(String[] taskLine) { boolean isDone = taskLine[1].equals("1"); return new Event(taskLine[2], isDone, taskLine[3], taskLine[4]); diff --git a/src/main/java/task/Task.java b/src/main/java/task/Task.java index 6bf18cc62e..8078e4c170 100644 --- a/src/main/java/task/Task.java +++ b/src/main/java/task/Task.java @@ -1,11 +1,20 @@ package task; +/** + * Abstract class for task. + */ public abstract class Task { private final String description; private boolean isDone; + /** + * Class constructor. + * + * @param description The description of the task. + * @param isDone Marks or unmarks the task. + */ public Task(String description, boolean isDone) { this.description = description; this.isDone = isDone; diff --git a/src/main/java/task/Todo.java b/src/main/java/task/Todo.java index 229344111c..f0e3e69651 100644 --- a/src/main/java/task/Todo.java +++ b/src/main/java/task/Todo.java @@ -2,13 +2,29 @@ import dukeexception.DukeException; +/** + * Todo class to deal with todo tasks. + */ public class Todo extends Task { + /** + * Class constructor. + * + * @param description The description of the task. + * @param isDone Marks or unmarks the task. + */ private Todo(String description, boolean isDone) { super(description, isDone); } + /** + * Returns todo task based on the user input. + * + * @param input User Input. + * @return Todo task. + * @throws DukeException Checks the validation of input. + */ public static Todo generate(String input) throws DukeException { if (input.trim().equals("todo")) { throw new DukeException("\t ☹ OOPS!!! The description of a todo cannot be empty.\n"); @@ -20,6 +36,12 @@ public static Todo generate(String input) throws DukeException { return new Todo(inputLine[1], false); } + /** + * Returns a todo task from the file. + * + * @param taskLine Each line from the input file. + * @return Todo task. + */ public static Todo generateTask(String[] taskLine) { boolean isDone = taskLine[1].equals("1"); return new Todo(taskLine[2], isDone); diff --git a/src/main/java/userinteraction/Parser.java b/src/main/java/userinteraction/Parser.java index 11f51e23f3..1486c15d9a 100644 --- a/src/main/java/userinteraction/Parser.java +++ b/src/main/java/userinteraction/Parser.java @@ -38,44 +38,3 @@ public static Command parse(String input) { return null; } } - - /** - private enum CommandNames { - LIST, MARK, UNMARK, TODO, DEADLINE, EVENT, DELETE, BYE - } - public static command.Command parse(String input) { - //String[] inputArr = input.split(" ", 2); - try { - CommandNames commandNames = CommandNames.valueOf(inputArr[0].toUpperCase()); - switch (commandNames) { - case LIST: - return new command.ListCommand(inputArr); - case MARK: - return new command.MarkTaskCommand(inputArr, true); - case UNMARK: - return new command.MarkTaskCommand(inputArr, false); - case TODO: - return new command.AddTodoCommand(inputArr); - case EVENT: - return new command.AddEventCommand(inputArr); - case DEADLINE: - return new command.AddDeadlineCommand(inputArr); - case DELETE: - return new command.DeleteTaskCommand(inputArr); - case BYE: - return new command.ExitCommand(inputArr); - default: - throw new dukeexception.DukeException("Unknown format"); - } - } catch (dukeexception.DukeException e) { - System.out.println(e.getMessage()); - } catch(NumberFormatException e) { - System.out.println("Please provide numbers"); - } catch(IllegalArgumentException e) { - System.out.println("Invalid command.Command"); - } catch (Exception e) { - System.out.println("Unknown error"); - } - return null; - } - **/ diff --git a/src/main/java/utils/DateTime.java b/src/main/java/utils/DateTime.java index fdc57c84ca..86be757755 100644 --- a/src/main/java/utils/DateTime.java +++ b/src/main/java/utils/DateTime.java @@ -6,8 +6,18 @@ import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +/** + * Local date time formatting. + */ public class DateTime { + /** + * Returns the localDateTime type of the date and time. + * + * @param date Date which is the string type. + * @return LocalDateTime type of the date and time. + * @throws DukeException Checks the validation of input. + */ public static LocalDateTime getDateTime(String date) throws DukeException { try { DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); @@ -17,6 +27,14 @@ public static LocalDateTime getDateTime(String date) throws DukeException { throw new DukeException("\t Wrong Date Format, please write in yyyy-MM-dd HHmm.\n"); } } + + /** + * Formats the date time input. + * + * @param date Date which is the string type. + * @return String type of date time. + * @throws DukeException Checks the validation of input. + */ public static String dateFormatter(String date) throws DukeException { try { LocalDateTime localDateTime = getDateTime(date); From 06a30bd72d91debd9aebad1213ca8243da277d62 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Mon, 13 Feb 2023 22:57:12 +0800 Subject: [PATCH 19/42] Add Increments as parallel branches: Level-9 --- src/main/java/command/FindTaskCommand.java | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/main/java/command/FindTaskCommand.java diff --git a/src/main/java/command/FindTaskCommand.java b/src/main/java/command/FindTaskCommand.java new file mode 100644 index 0000000000..34b44c6b5d --- /dev/null +++ b/src/main/java/command/FindTaskCommand.java @@ -0,0 +1,2 @@ +package command;public class FindTaskCommand { +} From bc80cb835e59da1764135f2a430556a50dde9faf Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Mon, 13 Feb 2023 22:58:32 +0800 Subject: [PATCH 20/42] Add Increments as parallel branches: Level-9 --- src/main/java/command/FindTaskCommand.java | 23 ++++++++++- src/main/java/storage/TaskList.java | 18 +++++++++ src/main/java/userinteraction/Parser.java | 44 ++-------------------- src/main/java/userinteraction/Ui.java | 7 +++- 4 files changed, 48 insertions(+), 44 deletions(-) diff --git a/src/main/java/command/FindTaskCommand.java b/src/main/java/command/FindTaskCommand.java index 34b44c6b5d..1eefbf1493 100644 --- a/src/main/java/command/FindTaskCommand.java +++ b/src/main/java/command/FindTaskCommand.java @@ -1,2 +1,23 @@ -package command;public class FindTaskCommand { +package command; + +import dukeexception.DukeException; +import storage.Storage; +import storage.TaskList; +import userinteraction.Ui; + +public class FindTaskCommand extends Command{ + + public FindTaskCommand(String input) { + super(input); + } + + @Override + public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + taskList.findTask(this.getInputArr(), ui); + } + + @Override + public boolean isExit() { + return false; + } } diff --git a/src/main/java/storage/TaskList.java b/src/main/java/storage/TaskList.java index 05cec482fc..50f85cabd2 100644 --- a/src/main/java/storage/TaskList.java +++ b/src/main/java/storage/TaskList.java @@ -79,4 +79,22 @@ public void markTask(boolean isDone, String input, Ui ui, Storage storage) throw storage.saveData(this); ui.printMarkTaskMsg(isDone, task); } + + public void findTask(String input, Ui ui) throws DukeException { + if (input.trim().equals("find")) { + throw new DukeException("\t ☹ OOPS!!! The description of a find cannot be empty.\n"); + } + String[] inputLine = input.split(" ", 2); + if (inputLine.length < 2) { + throw new DukeException("\t ☹ OOPS!!! The format is invalid, please give a search information.\n"); + } + ui.printFindTaskMsg(); + String str = ""; + for (int i = 0; i < tasks.size(); i++) { + if (tasks.get(i).getDescription().contains(inputLine[1])) { + str = "\t " + (i + 1) + ". " + tasks.get(i).toString(); + System.out.println(str); + } + } + } } \ No newline at end of file diff --git a/src/main/java/userinteraction/Parser.java b/src/main/java/userinteraction/Parser.java index 11f51e23f3..d400db809e 100644 --- a/src/main/java/userinteraction/Parser.java +++ b/src/main/java/userinteraction/Parser.java @@ -31,6 +31,9 @@ public static Command parse(String input) { } else if (input.startsWith("delete")) { ui.printLine(); return new DeleteTaskCommand(input); + } else if (input.startsWith("find")) { + ui.printLine(); + return new FindTaskCommand(input); } else { ui.printLine(); System.out.println("\t ☹ OOPS!!! I'm sorry, but I don't know what that means.\n"); @@ -38,44 +41,3 @@ public static Command parse(String input) { return null; } } - - /** - private enum CommandNames { - LIST, MARK, UNMARK, TODO, DEADLINE, EVENT, DELETE, BYE - } - public static command.Command parse(String input) { - //String[] inputArr = input.split(" ", 2); - try { - CommandNames commandNames = CommandNames.valueOf(inputArr[0].toUpperCase()); - switch (commandNames) { - case LIST: - return new command.ListCommand(inputArr); - case MARK: - return new command.MarkTaskCommand(inputArr, true); - case UNMARK: - return new command.MarkTaskCommand(inputArr, false); - case TODO: - return new command.AddTodoCommand(inputArr); - case EVENT: - return new command.AddEventCommand(inputArr); - case DEADLINE: - return new command.AddDeadlineCommand(inputArr); - case DELETE: - return new command.DeleteTaskCommand(inputArr); - case BYE: - return new command.ExitCommand(inputArr); - default: - throw new dukeexception.DukeException("Unknown format"); - } - } catch (dukeexception.DukeException e) { - System.out.println(e.getMessage()); - } catch(NumberFormatException e) { - System.out.println("Please provide numbers"); - } catch(IllegalArgumentException e) { - System.out.println("Invalid command.Command"); - } catch (Exception e) { - System.out.println("Unknown error"); - } - return null; - } - **/ diff --git a/src/main/java/userinteraction/Ui.java b/src/main/java/userinteraction/Ui.java index 6398a18f87..9ca45f8a81 100644 --- a/src/main/java/userinteraction/Ui.java +++ b/src/main/java/userinteraction/Ui.java @@ -36,10 +36,8 @@ public void printAddTaskMsg(TaskList taskList, Task task) { public void printMarkTaskMsg(boolean isMarked, Task task) { String str = ""; if (isMarked) { - //str = "\t Nice! I've marked this task as done: \n" + "\t\t [" + task.getTaskType() + "] [x] " + task.getDescription() + "\n"; str = "\t Nice! I've marked this task as done: \n" + "\t\t " + task.toString() + "\n"; } else { - //str = "\t OK, I've marked this task as not done yet: \n" + "\t\t [" + task.getTaskType() + "] [ ] " + task.getDescription() + "\n"; str = "\t OK, I've marked this task as not done yet: \n" + "\t\t " + task.toString() + "\n"; } System.out.println(str); @@ -49,6 +47,11 @@ public void printDeleteTaskMsg(Task task, int size) { task.toString() + "\n\t Now you have " + size + " tasks in the list.\n"; System.out.println(str); } + + public void printFindTaskMsg() { + String str = "\t Here are the matching tasks in your list:"; + System.out.println(str); + } public void printByeMsg() { System.out.println(BYE_MSG); } From 2afc4038f77ef1a498ee3ade0a72a0071c000131 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Mon, 13 Feb 2023 23:20:04 +0800 Subject: [PATCH 21/42] Add Increments as parallel branches: A-CodingStandard --- src/main/java/command/AddDeadlineCommand.java | 6 +-- src/main/java/command/AddEventCommand.java | 6 +-- src/main/java/command/AddTaskCommand.java | 4 +- src/main/java/command/AddTodoCommand.java | 6 +-- src/main/java/command/Command.java | 10 ++--- src/main/java/command/DeleteTaskCommand.java | 6 +-- src/main/java/command/ExitCommand.java | 4 +- src/main/java/command/ListCommand.java | 6 +-- src/main/java/command/MarkTaskCommand.java | 6 +-- src/main/java/duke/Duke.java | 8 ++-- src/main/java/storage/Storage.java | 24 +++++------ src/main/java/task/Deadline.java | 6 ++- src/main/java/task/Event.java | 8 +++- src/main/java/userinteraction/Parser.java | 41 ------------------- src/main/java/userinteraction/Ui.java | 17 ++++---- 15 files changed, 63 insertions(+), 95 deletions(-) diff --git a/src/main/java/command/AddDeadlineCommand.java b/src/main/java/command/AddDeadlineCommand.java index 2ea7969c95..088b139b57 100644 --- a/src/main/java/command/AddDeadlineCommand.java +++ b/src/main/java/command/AddDeadlineCommand.java @@ -6,13 +6,13 @@ import task.Deadline; import userinteraction.Ui; public class AddDeadlineCommand extends AddTaskCommand{ - public AddDeadlineCommand(String inputArr) { - super(inputArr); + public AddDeadlineCommand(String input) { + super(input); } @Override public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - Deadline deadline = Deadline.generate(this.getInputArr()); + Deadline deadline = Deadline.generate(this.getInput()); taskList.addTask(deadline); storage.saveData(taskList); ui.printAddTaskMsg(taskList, deadline); diff --git a/src/main/java/command/AddEventCommand.java b/src/main/java/command/AddEventCommand.java index 5e79f1eafa..a5471fd2cb 100644 --- a/src/main/java/command/AddEventCommand.java +++ b/src/main/java/command/AddEventCommand.java @@ -6,13 +6,13 @@ import task.Event; import userinteraction.Ui; public class AddEventCommand extends AddTaskCommand { - public AddEventCommand(String inputArr) { - super(inputArr); + public AddEventCommand(String input) { + super(input); } @Override public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - Event event = Event.generate(this.getInputArr()); + Event event = Event.generate(this.getInput()); taskList.addTask(event); storage.saveData(taskList); ui.printAddTaskMsg(taskList, event); diff --git a/src/main/java/command/AddTaskCommand.java b/src/main/java/command/AddTaskCommand.java index f563b8cfde..3a1a53b1d4 100644 --- a/src/main/java/command/AddTaskCommand.java +++ b/src/main/java/command/AddTaskCommand.java @@ -7,8 +7,8 @@ abstract class AddTaskCommand extends Command { - public AddTaskCommand(String inputArr) { - super(inputArr); + public AddTaskCommand(String input) { + super(input); } @Override diff --git a/src/main/java/command/AddTodoCommand.java b/src/main/java/command/AddTodoCommand.java index c1b5623f1a..920c981f1b 100644 --- a/src/main/java/command/AddTodoCommand.java +++ b/src/main/java/command/AddTodoCommand.java @@ -7,13 +7,13 @@ import userinteraction.Ui; public class AddTodoCommand extends AddTaskCommand { - public AddTodoCommand(String inputArr) { - super(inputArr); + public AddTodoCommand(String input) { + super(input); } @Override public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - Todo todo = Todo.generate(this.getInputArr()); + Todo todo = Todo.generate(this.getInput()); taskList.addTask(todo); storage.saveData(taskList); ui.printAddTaskMsg(taskList, todo); diff --git a/src/main/java/command/Command.java b/src/main/java/command/Command.java index 0269ecc332..c8d55d4268 100644 --- a/src/main/java/command/Command.java +++ b/src/main/java/command/Command.java @@ -6,13 +6,13 @@ import userinteraction.Ui; abstract public class Command { - private final String inputArr; - public Command(String inputArr) { - this.inputArr = inputArr; + private final String input; + public Command(String input) { + this.input = input; } - public String getInputArr() { - return inputArr; + public String getInput() { + return input; } public abstract void process(TaskList taskList, Ui ui, Storage storage) throws DukeException; public abstract boolean isExit(); diff --git a/src/main/java/command/DeleteTaskCommand.java b/src/main/java/command/DeleteTaskCommand.java index 427b5b95e6..c3bb9efe2d 100644 --- a/src/main/java/command/DeleteTaskCommand.java +++ b/src/main/java/command/DeleteTaskCommand.java @@ -7,13 +7,13 @@ public class DeleteTaskCommand extends Command { - public DeleteTaskCommand(String inputArr) { - super(inputArr); + public DeleteTaskCommand(String input) { + super(input); } @Override public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - taskList.deleteTask(this.getInputArr(), ui, storage); + taskList.deleteTask(this.getInput(), ui, storage); } @Override diff --git a/src/main/java/command/ExitCommand.java b/src/main/java/command/ExitCommand.java index eba904032b..782e742b92 100644 --- a/src/main/java/command/ExitCommand.java +++ b/src/main/java/command/ExitCommand.java @@ -5,8 +5,8 @@ import userinteraction.Ui; public class ExitCommand extends Command { - public ExitCommand(String inputArr) { - super(inputArr); + public ExitCommand(String input) { + super(input); } @Override diff --git a/src/main/java/command/ListCommand.java b/src/main/java/command/ListCommand.java index 5db438908c..157f67c18e 100644 --- a/src/main/java/command/ListCommand.java +++ b/src/main/java/command/ListCommand.java @@ -6,13 +6,13 @@ import userinteraction.Ui; public class ListCommand extends Command { - public ListCommand(String inputArr) { - super(inputArr); + public ListCommand(String input) { + super(input); } @Override public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - taskList.listTask(this.getInputArr()); + taskList.listTask(this.getInput()); } @Override diff --git a/src/main/java/command/MarkTaskCommand.java b/src/main/java/command/MarkTaskCommand.java index 1f7ab938bd..ecda7475cc 100644 --- a/src/main/java/command/MarkTaskCommand.java +++ b/src/main/java/command/MarkTaskCommand.java @@ -9,14 +9,14 @@ public class MarkTaskCommand extends Command { private final boolean isMarked; - public MarkTaskCommand(String inputArr, boolean isMarked) { - super(inputArr); + public MarkTaskCommand(String input, boolean isMarked) { + super(input); this.isMarked = isMarked; } @Override public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - taskList.markTask(isMarked, this.getInputArr(), ui, storage); + taskList.markTask(isMarked, this.getInput(), ui, storage); } @Override diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java index d31b23469a..66d697ae22 100644 --- a/src/main/java/duke/Duke.java +++ b/src/main/java/duke/Duke.java @@ -16,20 +16,20 @@ public class Duke { public Duke() { ui = new Ui(); storage = new Storage(FILE_PATH); - taskList = storage.readData(); + taskList = storage.loadData(); } public void run() { ui.printWelcomeMsg(); ui.printLine(); - boolean isBye = false; - while (!isBye) { + boolean isExit = false; + while (!isExit) { try { String input = ui.readCommand(); Command command = Parser.parse(input); if (command != null) { command.process(taskList, ui, storage); - isBye = command.isExit(); + isExit = command.isExit(); } } catch (DukeException e) { System.out.println(e.getMessage()); diff --git a/src/main/java/storage/Storage.java b/src/main/java/storage/Storage.java index cb67391cd3..aff61a06ce 100644 --- a/src/main/java/storage/Storage.java +++ b/src/main/java/storage/Storage.java @@ -37,7 +37,7 @@ public void checkFileExit() { } - public TaskList readData() { + public TaskList loadData() { ArrayList arrayList = new ArrayList<>(); Path file = Paths.get(".", filePath); try { @@ -45,17 +45,17 @@ public TaskList readData() { for (int i = 0; i < taskLine.size(); i++) { String[] content = taskLine.get(i).split(" \\| "); switch (content[0]) { - case "T": - arrayList.add(Todo.generateTask(content)); - break; - case "E": - arrayList.add(Event.generateTask(content)); - break; - case "D": - arrayList.add(Deadline.generateTask(content)); - break; - default: - throw new DukeException("\t Invalid data!\n"); + case "T": + arrayList.add(Todo.generateTask(content)); + break; + case "E": + arrayList.add(Event.generateTask(content)); + break; + case "D": + arrayList.add(Deadline.generateTask(content)); + break; + default: + throw new DukeException("\t Invalid data!\n"); } } } catch (FileNotFoundException e) { diff --git a/src/main/java/task/Deadline.java b/src/main/java/task/Deadline.java index a3091e72a6..7fb0589396 100644 --- a/src/main/java/task/Deadline.java +++ b/src/main/java/task/Deadline.java @@ -21,7 +21,8 @@ public static Deadline generate(String input) throws DukeException { if (descriptions.length < 2) { throw new DukeException("\t ☹ OOPS!!! The date time of a deadline cannot be empty.\n"); } - return new Deadline(descriptions[0], false, DateTime.dateFormatter(descriptions[1])); + return new Deadline(descriptions[0], false, + DateTime.dateFormatter(descriptions[1])); } public static Deadline generateTask(String[] taskLine) { boolean check = taskLine[1].equals("1"); @@ -36,7 +37,8 @@ public String getTaskType() { } @Override public String storeTaskString() { - return this.getTaskType() + " | " + this.getMarkedString() + " | " + this.getDescription() + " | " + this.getDateTime(); + return this.getTaskType() + " | " + this.getMarkedString() + + " | " + this.getDescription() + " | " + this.getDateTime(); } @Override public String toString() { diff --git a/src/main/java/task/Event.java b/src/main/java/task/Event.java index 298aef5da6..510ae7e2bd 100644 --- a/src/main/java/task/Event.java +++ b/src/main/java/task/Event.java @@ -27,7 +27,8 @@ public static Event generate(String input) throws DukeException { if (dateTime.length < 2) { throw new DukeException("\t ☹ OOPS!!! The end time of a event cannot be empty.\n"); } - return new Event(startEndTime[0], false, DateTime.dateFormatter(dateTime[0]), DateTime.dateFormatter(dateTime[1])); + return new Event(startEndTime[0], false, + DateTime.dateFormatter(dateTime[0]), DateTime.dateFormatter(dateTime[1])); } public static Event generateTask(String[] taskLine) { @@ -46,7 +47,10 @@ public String getTaskType() { } @Override public String storeTaskString() { - return this.getTaskType() + " | " + this.getMarkedString() + " | " + this.getDescription() + " | " + this.getStart() + " | " + this.getEnd(); + return this.getTaskType() + " | " + + this.getMarkedString() + " | " + + this.getDescription() + " | " + + this.getStart() + " | " + this.getEnd(); } @Override diff --git a/src/main/java/userinteraction/Parser.java b/src/main/java/userinteraction/Parser.java index 11f51e23f3..1486c15d9a 100644 --- a/src/main/java/userinteraction/Parser.java +++ b/src/main/java/userinteraction/Parser.java @@ -38,44 +38,3 @@ public static Command parse(String input) { return null; } } - - /** - private enum CommandNames { - LIST, MARK, UNMARK, TODO, DEADLINE, EVENT, DELETE, BYE - } - public static command.Command parse(String input) { - //String[] inputArr = input.split(" ", 2); - try { - CommandNames commandNames = CommandNames.valueOf(inputArr[0].toUpperCase()); - switch (commandNames) { - case LIST: - return new command.ListCommand(inputArr); - case MARK: - return new command.MarkTaskCommand(inputArr, true); - case UNMARK: - return new command.MarkTaskCommand(inputArr, false); - case TODO: - return new command.AddTodoCommand(inputArr); - case EVENT: - return new command.AddEventCommand(inputArr); - case DEADLINE: - return new command.AddDeadlineCommand(inputArr); - case DELETE: - return new command.DeleteTaskCommand(inputArr); - case BYE: - return new command.ExitCommand(inputArr); - default: - throw new dukeexception.DukeException("Unknown format"); - } - } catch (dukeexception.DukeException e) { - System.out.println(e.getMessage()); - } catch(NumberFormatException e) { - System.out.println("Please provide numbers"); - } catch(IllegalArgumentException e) { - System.out.println("Invalid command.Command"); - } catch (Exception e) { - System.out.println("Unknown error"); - } - return null; - } - **/ diff --git a/src/main/java/userinteraction/Ui.java b/src/main/java/userinteraction/Ui.java index 6398a18f87..c97ca6c586 100644 --- a/src/main/java/userinteraction/Ui.java +++ b/src/main/java/userinteraction/Ui.java @@ -22,7 +22,8 @@ public String readCommand() { return scanner.nextLine(); } public void printWelcomeMsg() { - String str = LOGO + "\t Hello! I am duke.Duke.\n" + "\t What can I do for you?\n"; + String str = LOGO + "\t Hello! I am duke.Duke.\n" + + "\t What can I do for you?\n"; System.out.println(str); } public void printLine() { @@ -30,23 +31,25 @@ public void printLine() { } public void printAddTaskMsg(TaskList taskList, Task task) { String str = "\t Got it. I've added this task:\n " + "\t\t " + - task.toString() + "\n\t Now you have " + taskList.getSize() + " tasks in the list\n"; + task.toString() + "\n\t Now you have " + + taskList.getSize() + " tasks in the list\n"; System.out.println(str); } public void printMarkTaskMsg(boolean isMarked, Task task) { String str = ""; if (isMarked) { - //str = "\t Nice! I've marked this task as done: \n" + "\t\t [" + task.getTaskType() + "] [x] " + task.getDescription() + "\n"; - str = "\t Nice! I've marked this task as done: \n" + "\t\t " + task.toString() + "\n"; + str = "\t Nice! I've marked this task as done: \n" + + "\t\t " + task.toString() + "\n"; } else { - //str = "\t OK, I've marked this task as not done yet: \n" + "\t\t [" + task.getTaskType() + "] [ ] " + task.getDescription() + "\n"; - str = "\t OK, I've marked this task as not done yet: \n" + "\t\t " + task.toString() + "\n"; + str = "\t OK, I've marked this task as not done yet: \n" + + "\t\t " + task.toString() + "\n"; } System.out.println(str); } public void printDeleteTaskMsg(Task task, int size) { String str = "\t Noted. I've removed this task:\n" + "\t\t " + - task.toString() + "\n\t Now you have " + size + " tasks in the list.\n"; + task.toString() + "\n\t Now you have " + + size + " tasks in the list.\n"; System.out.println(str); } public void printByeMsg() { From 895bae87a36766a2eba9ac7f7054e6ef858d23c6 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Tue, 14 Feb 2023 01:37:47 +0800 Subject: [PATCH 22/42] Add Increments as branches: A-CheckStyle --- config/checkstyle/checkstyle.xml | 434 +++++++++++++++++++++++++++++ config/checkstyle/suppressions.xml | 10 + 2 files changed, 444 insertions(+) create mode 100644 config/checkstyle/checkstyle.xml create mode 100644 config/checkstyle/suppressions.xml 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 d3b4044a4aa164faf1d67262c7858a4bd3f12edd Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Thu, 16 Feb 2023 01:16:21 +0800 Subject: [PATCH 23/42] Delete unused classes --- src/main/java/AddDeadlineCommand.java | 14 ----- src/main/java/AddEventCommand.java | 13 ----- src/main/java/AddTaskCommand.java | 16 ------ src/main/java/AddTodoCommand.java | 13 ----- src/main/java/Command.java | 12 ----- src/main/java/DateTime.java | 25 --------- src/main/java/Deadline.java | 47 ---------------- src/main/java/DeleteTaskCommand.java | 16 ------ src/main/java/Duke.java | 40 -------------- src/main/java/DukeException.java | 6 --- src/main/java/Event.java | 61 --------------------- src/main/java/ExitCommand.java | 14 ----- src/main/java/ListCommand.java | 15 ------ src/main/java/MarkTaskCommand.java | 19 ------- src/main/java/Parser.java | 77 --------------------------- src/main/java/Storage.java | 77 --------------------------- src/main/java/Task.java | 30 ----------- src/main/java/TaskList.java | 76 -------------------------- src/main/java/Todo.java | 41 -------------- src/main/java/Ui.java | 50 ----------------- 20 files changed, 662 deletions(-) delete mode 100644 src/main/java/AddDeadlineCommand.java delete mode 100644 src/main/java/AddEventCommand.java delete mode 100644 src/main/java/AddTaskCommand.java delete mode 100644 src/main/java/AddTodoCommand.java delete mode 100644 src/main/java/Command.java delete mode 100644 src/main/java/DateTime.java delete mode 100644 src/main/java/Deadline.java delete mode 100644 src/main/java/DeleteTaskCommand.java delete mode 100644 src/main/java/Duke.java delete mode 100644 src/main/java/DukeException.java delete mode 100644 src/main/java/Event.java delete mode 100644 src/main/java/ExitCommand.java delete mode 100644 src/main/java/ListCommand.java delete mode 100644 src/main/java/MarkTaskCommand.java delete mode 100644 src/main/java/Parser.java delete mode 100644 src/main/java/Storage.java delete mode 100644 src/main/java/Task.java delete mode 100644 src/main/java/TaskList.java delete mode 100644 src/main/java/Todo.java delete mode 100644 src/main/java/Ui.java diff --git a/src/main/java/AddDeadlineCommand.java b/src/main/java/AddDeadlineCommand.java deleted file mode 100644 index 8b07d452cd..0000000000 --- a/src/main/java/AddDeadlineCommand.java +++ /dev/null @@ -1,14 +0,0 @@ -public class AddDeadlineCommand extends AddTaskCommand{ - public AddDeadlineCommand(String inputArr) { - super(inputArr); - } - - @Override - public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - Deadline deadline = Deadline.generate(this.getInputArr()); - taskList.addTask(deadline); - storage.saveData(taskList); - ui.printAddTaskMsg(taskList, deadline); - } -} - diff --git a/src/main/java/AddEventCommand.java b/src/main/java/AddEventCommand.java deleted file mode 100644 index 8ee808f817..0000000000 --- a/src/main/java/AddEventCommand.java +++ /dev/null @@ -1,13 +0,0 @@ -public class AddEventCommand extends AddTaskCommand { - public AddEventCommand(String inputArr) { - super(inputArr); - } - - @Override - public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - Event event = Event.generate(this.getInputArr()); - taskList.addTask(event); - storage.saveData(taskList); - ui.printAddTaskMsg(taskList, event); - } -} \ No newline at end of file diff --git a/src/main/java/AddTaskCommand.java b/src/main/java/AddTaskCommand.java deleted file mode 100644 index 8a21700336..0000000000 --- a/src/main/java/AddTaskCommand.java +++ /dev/null @@ -1,16 +0,0 @@ -abstract class AddTaskCommand extends Command { - - public AddTaskCommand(String inputArr) { - super(inputArr); - } - - @Override - public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - - } - - @Override - public boolean isExit() { - return false; - } -} diff --git a/src/main/java/AddTodoCommand.java b/src/main/java/AddTodoCommand.java deleted file mode 100644 index c8476265bb..0000000000 --- a/src/main/java/AddTodoCommand.java +++ /dev/null @@ -1,13 +0,0 @@ -public class AddTodoCommand extends AddTaskCommand { - public AddTodoCommand(String inputArr) { - super(inputArr); - } - - @Override - public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - Todo todo = Todo.generate(this.getInputArr()); - taskList.addTask(todo); - storage.saveData(taskList); - ui.printAddTaskMsg(taskList, todo); - } -} \ No newline at end of file diff --git a/src/main/java/Command.java b/src/main/java/Command.java deleted file mode 100644 index 6e44873a2a..0000000000 --- a/src/main/java/Command.java +++ /dev/null @@ -1,12 +0,0 @@ -abstract public class Command { - private final String inputArr; - public Command(String inputArr) { - this.inputArr = inputArr; - } - - public String getInputArr() { - return inputArr; - } - public abstract void process(TaskList taskList, Ui ui, Storage storage) throws DukeException; - public abstract boolean isExit(); -} \ No newline at end of file diff --git a/src/main/java/DateTime.java b/src/main/java/DateTime.java deleted file mode 100644 index 3f3e1becd0..0000000000 --- a/src/main/java/DateTime.java +++ /dev/null @@ -1,25 +0,0 @@ -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; - -public class DateTime { - - public static LocalDateTime getDateTime(String date) throws DukeException { - try { - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm"); - LocalDateTime localDateTime = LocalDateTime.parse(date, dateTimeFormatter); - return localDateTime; - } catch (DateTimeParseException e) { - throw new DukeException("\t Wrong Date Format, please write in yyyy-MM-dd HHmm.\n"); - } - } - public static String dateFormatter(String date) throws DukeException { - try { - LocalDateTime localDateTime = getDateTime(date); - return localDateTime.format(DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm")); - } catch (DateTimeParseException e) { - throw new DukeException("\t Wrong Date Format, please write in yyyy-MM-dd HHmm.\n"); - } - } - -} diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java deleted file mode 100644 index 9d4383ea66..0000000000 --- a/src/main/java/Deadline.java +++ /dev/null @@ -1,47 +0,0 @@ -public class Deadline extends Task { - private String dateTime; - private Deadline(String description, boolean isDone, String dateTime) { - super(description, isDone); - this.dateTime = dateTime; - } - public static Deadline generate(String input) throws DukeException { - if (input.trim().equals("deadline")) { - throw new DukeException("\t ☹ OOPS!!! The description of a deadline cannot be empty.\n"); - } - String[] inputLine = input.split(" ", 2); - if (inputLine.length < 2) { - throw new DukeException("\t ☹ OOPS!!! The description of a deadline cannot be empty.\n"); - } - String[] descriptions = inputLine[1].split(" /by ", 2); - if (descriptions.length < 2) { - throw new DukeException("\t ☹ OOPS!!! The date time of a deadline cannot be empty.\n"); - } - return new Deadline(descriptions[0], false, DateTime.dateFormatter(descriptions[1])); - } - public static Deadline generateTask(String[] taskLine) { - boolean check = taskLine[1].equals("1"); - return new Deadline(taskLine[2], check, taskLine[3]); - } - public String getDateTime() { - return dateTime; - } - @Override - public String getTaskType() { - return "D"; - } - @Override - public String storeTaskString() { - return this.getTaskType() + " | " + this.getMarkedString() + " | " + this.getDescription() + " | " + this.getDateTime(); - } - @Override - public String toString() { - String str = this.getDescription(); - boolean checked = this.isDone(); - String dateTime = this.getDateTime(); - if (checked) { - return "[D][X] " + str + " (by: " + dateTime + ")"; - } else { - return "[D][ ] " + str + " (by: " + dateTime + ")"; - } - } -} \ No newline at end of file diff --git a/src/main/java/DeleteTaskCommand.java b/src/main/java/DeleteTaskCommand.java deleted file mode 100644 index 6ae8ede401..0000000000 --- a/src/main/java/DeleteTaskCommand.java +++ /dev/null @@ -1,16 +0,0 @@ -public class DeleteTaskCommand extends Command { - - public DeleteTaskCommand(String inputArr) { - super(inputArr); - } - - @Override - public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - taskList.deleteTask(this.getInputArr(), ui, storage); - } - - @Override - public boolean isExit() { - return false; - } -} \ No newline at end of file diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java deleted file mode 100644 index d85bf2a482..0000000000 --- a/src/main/java/Duke.java +++ /dev/null @@ -1,40 +0,0 @@ -public class Duke { - private final static String FILE_PATH = ".\\src\\data\\duke.txt"; - - private final Ui ui; - private final Storage storage; - private final TaskList taskList; - public Duke() { - ui = new Ui(); - storage = new Storage(FILE_PATH); - taskList = storage.readData(); - } - - public void run() { - ui.printWelcomeMsg(); - ui.printLine(); - boolean isBye = false; - while (!isBye) { - try { - String input = ui.readCommand(); - Command command = Parser.parse(input); - if (command != null) { - command.process(taskList, ui, storage); - isBye = command.isExit(); - } - } catch (DukeException e) { - System.out.println(e.getMessage()); - } - } - } - - public Ui getUi() { - return ui; - } - - public static void main(String[] args) { - Duke duke = new Duke(); - duke.run(); - } - -} diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java deleted file mode 100644 index d2a5b3057e..0000000000 --- a/src/main/java/DukeException.java +++ /dev/null @@ -1,6 +0,0 @@ -public class DukeException extends Exception{ - - public DukeException(String message) { - super(message); - } -} diff --git a/src/main/java/Event.java b/src/main/java/Event.java deleted file mode 100644 index 1556c348d6..0000000000 --- a/src/main/java/Event.java +++ /dev/null @@ -1,61 +0,0 @@ -public class Event extends Task { - private final String start; - private final String end; - private Event(String description, boolean isDone, String start, String end) { - super(description, isDone); - this.start = start; - this.end = end; - } - public static Event generate(String input) throws DukeException { - if (input.trim().equals("event")) { - throw new DukeException("\t ☹ OOPS!!! The description of a event cannot be empty.\n"); - } - String[] inputLine = input.split(" ", 2); - if (inputLine.length < 2) { - throw new DukeException("\t ☹ OOPS!!! The description of a event cannot be empty.\n"); - } - String[] startEndTime = inputLine[1].split(" /from "); - if (startEndTime.length < 2) { - throw new DukeException("\t ☹ OOPS!!! The start time of a event cannot be empty.\n"); - } - String[] dateTime = startEndTime[1].split(" /to "); - if (dateTime.length < 2) { - throw new DukeException("\t ☹ OOPS!!! The end time of a event cannot be empty.\n"); - } - return new Event(startEndTime[0], false, DateTime.dateFormatter(dateTime[0]), DateTime.dateFormatter(dateTime[1])); - } - - public static Event generateTask(String[] taskLine) { - boolean isDone = taskLine[1].equals("1"); - return new Event(taskLine[2], isDone, taskLine[3], taskLine[4]); - } - public String getStart() { - return start; - } - public String getEnd() { - return end; - } - @Override - public String getTaskType() { - return "E"; - } - @Override - public String storeTaskString() { - return this.getTaskType() + " | " + this.getMarkedString() + " | " + this.getDescription() + " | " + this.getStart() + " | " + this.getEnd(); - } - - @Override - public String toString() { - String str = this.getDescription(); - boolean checked = this.isDone(); - String startTime = this.getStart(); - String endTime = this.getEnd(); - if (checked) { - return "[E][X] " + str + " (from: " + startTime + - " to: " + endTime + ")"; - } else { - return "[E][ ] " + str + " (from: " + startTime + - " to: " + endTime + ")"; - } - } -} \ No newline at end of file diff --git a/src/main/java/ExitCommand.java b/src/main/java/ExitCommand.java deleted file mode 100644 index 5385426773..0000000000 --- a/src/main/java/ExitCommand.java +++ /dev/null @@ -1,14 +0,0 @@ -public class ExitCommand extends Command { - public ExitCommand(String inputArr) { - super(inputArr); - } - - @Override - public void process(TaskList taskList, Ui ui, Storage storage) { - ui.printByeMsg(); - } - @Override - public boolean isExit() { - return true; - } -} \ No newline at end of file diff --git a/src/main/java/ListCommand.java b/src/main/java/ListCommand.java deleted file mode 100644 index 0957ec6399..0000000000 --- a/src/main/java/ListCommand.java +++ /dev/null @@ -1,15 +0,0 @@ -public class ListCommand extends Command { - public ListCommand(String inputArr) { - super(inputArr); - } - - @Override - public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - taskList.listTask(this.getInputArr()); - } - - @Override - public boolean isExit() { - return false; - } -} \ No newline at end of file diff --git a/src/main/java/MarkTaskCommand.java b/src/main/java/MarkTaskCommand.java deleted file mode 100644 index abb4018c98..0000000000 --- a/src/main/java/MarkTaskCommand.java +++ /dev/null @@ -1,19 +0,0 @@ -public class MarkTaskCommand extends Command { - - private final boolean isMarked; - - public MarkTaskCommand(String inputArr, boolean isMarked) { - super(inputArr); - this.isMarked = isMarked; - } - - @Override - public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - taskList.markTask(isMarked, this.getInputArr(), ui, storage); - } - - @Override - public boolean isExit() { - return false; - } -} \ No newline at end of file diff --git a/src/main/java/Parser.java b/src/main/java/Parser.java deleted file mode 100644 index dace37945b..0000000000 --- a/src/main/java/Parser.java +++ /dev/null @@ -1,77 +0,0 @@ -public class Parser { - - private static final Ui ui = new Ui(); - - public static Command parse(String input) { - if (input.equals("bye")) { - ui.printLine(); - return new ExitCommand(input); - } else if (input.equals("list")) { - ui.printLine(); - return new ListCommand(input); - } else if (input.startsWith("mark")) { - ui.printLine(); - return new MarkTaskCommand(input, true); - } else if (input.startsWith("unmark")) { - ui.printLine(); - return new MarkTaskCommand(input, false); - } else if (input.startsWith("todo")) { - ui.printLine(); - return new AddTodoCommand(input); - } else if (input.startsWith("deadline")) { - ui.printLine(); - return new AddDeadlineCommand(input); - } else if (input.startsWith("event")) { - ui.printLine(); - return new AddEventCommand(input); - } else if (input.startsWith("delete")) { - ui.printLine(); - return new DeleteTaskCommand(input); - } else { - ui.printLine(); - System.out.println("\t ☹ OOPS!!! I'm sorry, but I don't know what that means.\n"); - } - return null; - } -} - - /** - private enum CommandNames { - LIST, MARK, UNMARK, TODO, DEADLINE, EVENT, DELETE, BYE - } - public static Command parse(String input) { - //String[] inputArr = input.split(" ", 2); - try { - CommandNames commandNames = CommandNames.valueOf(inputArr[0].toUpperCase()); - switch (commandNames) { - case LIST: - return new ListCommand(inputArr); - case MARK: - return new MarkTaskCommand(inputArr, true); - case UNMARK: - return new MarkTaskCommand(inputArr, false); - case TODO: - return new AddTodoCommand(inputArr); - case EVENT: - return new AddEventCommand(inputArr); - case DEADLINE: - return new AddDeadlineCommand(inputArr); - case DELETE: - return new DeleteTaskCommand(inputArr); - case BYE: - return new ExitCommand(inputArr); - default: - throw new DukeException("Unknown format"); - } - } catch (DukeException e) { - System.out.println(e.getMessage()); - } catch(NumberFormatException e) { - System.out.println("Please provide numbers"); - } catch(IllegalArgumentException e) { - System.out.println("Invalid Command"); - } catch (Exception e) { - System.out.println("Unknown error"); - } - return null; - } - **/ diff --git a/src/main/java/Storage.java b/src/main/java/Storage.java deleted file mode 100644 index 6581379d12..0000000000 --- a/src/main/java/Storage.java +++ /dev/null @@ -1,77 +0,0 @@ -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; - -public class Storage { - - private final String filePath; - - public Storage(String filePath) { - this.filePath = filePath; - checkFileExit(); - } - - public void checkFileExit() { - try { - Path file = Paths.get(".", filePath); - if (!Files.exists(file)) { - Files.createDirectories(file.getParent()); - Files.createFile(file); - } - } catch (IOException e) { - System.out.println("\t Invalid Path.\n"); - e.printStackTrace(); - } - } - - - public TaskList readData() { - ArrayList arrayList = new ArrayList<>(); - Path file = Paths.get(".", filePath); - try { - List taskLine = Files.readAllLines(file); - for (int i = 0; i < taskLine.size(); i++) { - String[] content = taskLine.get(i).split(" \\| "); - switch (content[0]) { - case "T": - arrayList.add(Todo.generateTask(content)); - break; - case "E": - arrayList.add(Event.generateTask(content)); - break; - case "D": - arrayList.add(Deadline.generateTask(content)); - break; - default: - throw new DukeException("\t Invalid data!\n"); - } - } - } catch (FileNotFoundException e) { - System.out.println("\t File not found.\n"); - } catch (DukeException e) { - System.out.println(e.getMessage()); - } catch (IOException e) { - System.out.println("\t Invalid Path.\n"); - } - return new TaskList(arrayList); - } - - - public void saveData(TaskList tasks) { - Path file = Paths.get(".", filePath); - ArrayList arrayList = tasks.getTasks(); - String data = ""; - try { - for (Task task : arrayList) { - data += task.storeTaskString() + "\n"; - } - Files.writeString(file, data); - } catch (IOException e) { - System.out.println("\t Invalid Path.\n"); - } - } -} diff --git a/src/main/java/Task.java b/src/main/java/Task.java deleted file mode 100644 index d390e06323..0000000000 --- a/src/main/java/Task.java +++ /dev/null @@ -1,30 +0,0 @@ - -public abstract class Task { - - private final String description; - - private boolean isDone; - - public Task(String description, boolean isDone) { - this.description = description; - this.isDone = isDone; - } - - public boolean isDone() { - return isDone; - } - public String getMarkedString() { - return isDone ? "1" : "0"; - } - - public String getDescription() { - return description; - } - - public void setDone(boolean done) { - this.isDone = done; - } - - public abstract String storeTaskString(); - public abstract String getTaskType(); -} \ No newline at end of file diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java deleted file mode 100644 index 31df286b63..0000000000 --- a/src/main/java/TaskList.java +++ /dev/null @@ -1,76 +0,0 @@ -import java.util.ArrayList; - -public class TaskList { - private final ArrayList tasks; - public TaskList(ArrayList tasks) { - this.tasks = tasks; - } - public int getSize() { - return tasks.size(); - } - public ArrayList getTasks() { - return tasks; - } - public void listTask(String input) throws DukeException { - String[] inputLine = input.split(" ", 2); - if (inputLine.length > 1) { - throw new DukeException("\t ☹ OOPS!!! The format is invalid!\n"); - } - String str = ""; - for (int i = 0; i < tasks.size(); i++) { - str = "\t " + (i + 1) + ". " + tasks.get(i).toString(); - System.out.println(str); - } - System.out.print(""); - } - public void addTask(Task task) { - tasks.add(task); - } - - public void deleteTask(String input, Ui ui, Storage storage) throws DukeException { - if (input.trim().equals("delete")) { - throw new DukeException("\t ☹ OOPS!!! The description of a delete cannot be empty.\n"); - } - String[] inputLine = input.split(" ", 2); - if (inputLine.length < 2) { - throw new DukeException("\t ☹ OOPS!!! The format is invalid, please give numbers.\n"); - } - int taskIndex; - try { - taskIndex = Integer.parseInt(inputLine[1]); - } catch (NumberFormatException e) { - throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); - } - int taskListSize = this.getSize(); - if (taskIndex < 1 || taskIndex > taskListSize) { - throw new DukeException("\t ☹ OOPS!!! The index is out of range.\n"); - } - Task task = tasks.get(taskIndex - 1); - tasks.remove(taskIndex - 1); - storage.saveData(this); - ui.printDeleteTaskMsg(task, tasks.size()); - } - public void markTask(boolean isDone, String input, Ui ui, Storage storage) throws DukeException { - if (input.trim().equals("mark") || input.trim().equals("unmark")) { - throw new DukeException("\t ☹ OOPS!!! Please input a number.\n"); - } - String[] inputLine = input.split(" ", 2); - if (inputLine.length < 2) { - throw new DukeException("\t ☹ OOPS!!! The format is invalid, please give numbers.\n"); - } - int taskIndex; - try { - taskIndex = Integer.parseInt(inputLine[1]) - 1; - } catch (NumberFormatException e) { - throw new DukeException("\t ☹ OOPS!!! Please input a valid number.\n"); - } - int taskListSize = tasks.size(); - if (taskIndex + 1 > taskListSize || taskIndex < 0) { - throw new DukeException("\t ☹ OOPS!!! The index is out of range.\n"); - } - Task task = tasks.get(taskIndex); - task.setDone(isDone); - storage.saveData(this); - ui.printMarkTaskMsg(isDone, task); - } -} \ No newline at end of file diff --git a/src/main/java/Todo.java b/src/main/java/Todo.java deleted file mode 100644 index 774cc4a4cf..0000000000 --- a/src/main/java/Todo.java +++ /dev/null @@ -1,41 +0,0 @@ -public class Todo extends Task { - - private Todo(String description, boolean isDone) { - super(description, isDone); - } - - - public static Todo generate(String input) throws DukeException { - if (input.trim().equals("todo")) { - throw new DukeException("\t ☹ OOPS!!! The description of a todo cannot be empty.\n"); - } - String[] inputLine = input.split(" ", 2); - if (inputLine.length < 2) { - throw new DukeException("\t ☹ OOPS!!! The description of a todo cannot be empty.\n"); - } - return new Todo(inputLine[1], false); - } - - public static Todo generateTask(String[] taskLine) { - boolean isDone = taskLine[1].equals("1"); - return new Todo(taskLine[2], isDone); - } - @Override - public String getTaskType() { - return "T"; - } - @Override - public String storeTaskString() { - return this.getTaskType() + " | " + this.getMarkedString() + " | " + this.getDescription(); - } - @Override - public String toString() { - boolean checked = this.isDone(); - String str = this.getDescription(); - if (checked) { - return "[T][X] " + str; - } else { - return "[T][ ] " + str; - } - } -} \ No newline at end of file diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java deleted file mode 100644 index a8b33e6419..0000000000 --- a/src/main/java/Ui.java +++ /dev/null @@ -1,50 +0,0 @@ -import java.util.Scanner; - -public class Ui { - private final String LOGO = "\t ____ _ \n" - + "\t | _ \\ _ _| | _____ \n" - + "\t | | | | | | | |/ / _ \\\n" - + "\t | |_| | |_| | < __/\n" - + "\t |____/ \\__,_|_|\\_\\___|\n"; - private final String SEPARATE_LINE = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"; - private final String BYE_MSG = "\t Bye. Hope to see you again soon!"; - - private final Scanner scanner; - public Ui() { - scanner = new Scanner(System.in); - } - public String readCommand() { - return scanner.nextLine(); - } - public void printWelcomeMsg() { - String str = LOGO + "\t Hello! I am Duke.\n" + "\t What can I do for you?\n"; - System.out.println(str); - } - public void printLine() { - System.out.println(SEPARATE_LINE); - } - public void printAddTaskMsg(TaskList taskList, Task task) { - String str = "\t Got it. I've added this task:\n " + "\t\t " + - task.toString() + "\n\t Now you have " + taskList.getSize() + " tasks in the list\n"; - System.out.println(str); - } - public void printMarkTaskMsg(boolean isMarked, Task task) { - String str = ""; - if (isMarked) { - //str = "\t Nice! I've marked this task as done: \n" + "\t\t [" + task.getTaskType() + "] [x] " + task.getDescription() + "\n"; - str = "\t Nice! I've marked this task as done: \n" + "\t\t " + task.toString() + "\n"; - } else { - //str = "\t OK, I've marked this task as not done yet: \n" + "\t\t [" + task.getTaskType() + "] [ ] " + task.getDescription() + "\n"; - str = "\t OK, I've marked this task as not done yet: \n" + "\t\t " + task.toString() + "\n"; - } - System.out.println(str); - } - public void printDeleteTaskMsg(Task task, int size) { - String str = "\t Noted. I've removed this task:\n" + "\t\t " + - task.toString() + "\n\t Now you have " + size + " tasks in the list.\n"; - System.out.println(str); - } - public void printByeMsg() { - System.out.println(BYE_MSG); - } -} \ No newline at end of file From 74bdb53bafaa7c0b7fe8a8f8d2e8fecf2a6e175c Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Thu, 16 Feb 2023 02:01:03 +0800 Subject: [PATCH 24/42] Add Increments as branches: Level-10 --- build.gradle | 15 +++++ src/main/java/command/AddDeadlineCommand.java | 4 +- src/main/java/command/AddEventCommand.java | 4 +- src/main/java/command/AddTaskCommand.java | 4 +- src/main/java/command/AddTodoCommand.java | 4 +- src/main/java/command/Command.java | 2 +- src/main/java/command/DeleteTaskCommand.java | 4 +- src/main/java/command/ExitCommand.java | 4 +- src/main/java/command/FindTaskCommand.java | 4 +- src/main/java/command/InvalidCommand.java | 43 ++++++++++++ src/main/java/command/ListCommand.java | 4 +- src/main/java/command/MarkTaskCommand.java | 4 +- src/main/java/duke/DialogBox.java | 61 ++++++++++++++++++ src/main/java/duke/Duke.java | 12 ++++ src/main/java/duke/Launcher.java | 9 +++ src/main/java/duke/Main.java | 31 +++++++++ src/main/java/duke/MainWindow.java | 58 +++++++++++++++++ src/main/java/storage/TaskList.java | 21 +++--- src/main/java/userinteraction/Parser.java | 13 +--- src/main/java/userinteraction/Ui.java | 35 +++++----- src/main/resources/images/DaDuke.png | Bin 0 -> 20386 bytes src/main/resources/images/DaUser.png | Bin 0 -> 5024 bytes src/main/resources/view/DialogBox.fxml | 16 +++++ src/main/resources/view/MainWindow.fxml | 19 ++++++ 24 files changed, 314 insertions(+), 57 deletions(-) create mode 100644 src/main/java/command/InvalidCommand.java create mode 100644 src/main/java/duke/DialogBox.java create mode 100644 src/main/java/duke/Launcher.java create mode 100644 src/main/java/duke/Main.java create mode 100644 src/main/java/duke/MainWindow.java create mode 100644 src/main/resources/images/DaDuke.png create mode 100644 src/main/resources/images/DaUser.png create mode 100644 src/main/resources/view/DialogBox.fxml create mode 100644 src/main/resources/view/MainWindow.fxml diff --git a/build.gradle b/build.gradle index 3322710577..71f4540aed 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,21 @@ repositories { dependencies { testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.5.0' testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.5.0' + + String javaFxVersion = '11' + + implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'linux' + implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'linux' + implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'linux' + implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'win' + implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'mac' + implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'linux' } test { diff --git a/src/main/java/command/AddDeadlineCommand.java b/src/main/java/command/AddDeadlineCommand.java index 8ffb402e66..070c60feb4 100644 --- a/src/main/java/command/AddDeadlineCommand.java +++ b/src/main/java/command/AddDeadlineCommand.java @@ -30,11 +30,11 @@ public AddDeadlineCommand(String input) { * @throws DukeException Checks the validation of input. */ @Override - public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + public String process(TaskList taskList, Ui ui, Storage storage) throws DukeException { Deadline deadline = Deadline.generate(this.getInput()); taskList.addTask(deadline); storage.saveData(taskList); - ui.printAddTaskMsg(taskList, deadline); + return ui.printAddTaskMsg(taskList, deadline); } } diff --git a/src/main/java/command/AddEventCommand.java b/src/main/java/command/AddEventCommand.java index 899b1077e5..f91f61311d 100644 --- a/src/main/java/command/AddEventCommand.java +++ b/src/main/java/command/AddEventCommand.java @@ -29,10 +29,10 @@ public AddEventCommand(String input) { * @throws DukeException Checks the validation of input. */ @Override - public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + public String process(TaskList taskList, Ui ui, Storage storage) throws DukeException { Event event = Event.generate(this.getInput()); taskList.addTask(event); storage.saveData(taskList); - ui.printAddTaskMsg(taskList, event); + return ui.printAddTaskMsg(taskList, event); } } \ No newline at end of file diff --git a/src/main/java/command/AddTaskCommand.java b/src/main/java/command/AddTaskCommand.java index 24db807ee1..13524b7f46 100644 --- a/src/main/java/command/AddTaskCommand.java +++ b/src/main/java/command/AddTaskCommand.java @@ -27,8 +27,8 @@ public AddTaskCommand(String input) { * @throws DukeException Checks the validation of input. */ @Override - public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - + public String process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + return null; } /** diff --git a/src/main/java/command/AddTodoCommand.java b/src/main/java/command/AddTodoCommand.java index 99e6b46d6e..ed575c07e7 100644 --- a/src/main/java/command/AddTodoCommand.java +++ b/src/main/java/command/AddTodoCommand.java @@ -29,10 +29,10 @@ public AddTodoCommand(String input) { * @throws DukeException Checks the validation of input. */ @Override - public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + public String process(TaskList taskList, Ui ui, Storage storage) throws DukeException { Todo todo = Todo.generate(this.getInput()); taskList.addTask(todo); storage.saveData(taskList); - ui.printAddTaskMsg(taskList, todo); + return ui.printAddTaskMsg(taskList, todo); } } \ No newline at end of file diff --git a/src/main/java/command/Command.java b/src/main/java/command/Command.java index 9d00d23d20..713618c04f 100644 --- a/src/main/java/command/Command.java +++ b/src/main/java/command/Command.java @@ -31,7 +31,7 @@ public String getInput() { * @param storage Saves all tasks in a file * @throws DukeException Checks the validation of input. */ - public abstract void process(TaskList taskList, Ui ui, Storage storage) throws DukeException; + public abstract String process(TaskList taskList, Ui ui, Storage storage) throws DukeException; /** * Checks whether exit the program. diff --git a/src/main/java/command/DeleteTaskCommand.java b/src/main/java/command/DeleteTaskCommand.java index b7676e7a53..08eb12001d 100644 --- a/src/main/java/command/DeleteTaskCommand.java +++ b/src/main/java/command/DeleteTaskCommand.java @@ -27,8 +27,8 @@ public DeleteTaskCommand(String input) { * @throws DukeException Checks the validation of input. */ @Override - public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - taskList.deleteTask(this.getInput(), ui, storage); + public String process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + return taskList.deleteTask(this.getInput(), ui, storage); } /** diff --git a/src/main/java/command/ExitCommand.java b/src/main/java/command/ExitCommand.java index 1c70218e00..cf0eae0bc0 100644 --- a/src/main/java/command/ExitCommand.java +++ b/src/main/java/command/ExitCommand.java @@ -18,8 +18,8 @@ public ExitCommand(String input) { } @Override - public void process(TaskList taskList, Ui ui, Storage storage) { - ui.printByeMsg(); + public String process(TaskList taskList, Ui ui, Storage storage) { + return ui.printByeMsg(); } @Override public boolean isExit() { diff --git a/src/main/java/command/FindTaskCommand.java b/src/main/java/command/FindTaskCommand.java index f80d0d99b4..bbac1ab4a8 100644 --- a/src/main/java/command/FindTaskCommand.java +++ b/src/main/java/command/FindTaskCommand.java @@ -12,8 +12,8 @@ public FindTaskCommand(String input) { } @Override - public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - taskList.findTask(this.getInput(), ui); + public String process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + return taskList.findTask(this.getInput(), ui); } @Override diff --git a/src/main/java/command/InvalidCommand.java b/src/main/java/command/InvalidCommand.java new file mode 100644 index 0000000000..76dfce369f --- /dev/null +++ b/src/main/java/command/InvalidCommand.java @@ -0,0 +1,43 @@ +package command; + +import dukeexception.DukeException; +import storage.Storage; +import storage.TaskList; +import userinteraction.Ui; + +/** + * Command class for adding deadline tasks. + */ +public class InvalidCommand extends Command { + /** + * Class constructor. + * + * @param input String from a user input. + */ + public InvalidCommand(String input) { + super(input); + } + + /** + * Deletes a task, both of task list and file. + * + * @param taskList Stores all tasks. + * @param ui The Ui to be used for printing messages. + * @param storage Deletes a task in a file. + * @throws DukeException Checks the validation of input. + */ + @Override + public String process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + return ui.printWrongMsg(); + } + + /** + * Checks whether exit the program. + * + * @return Boolean Exit the program. + */ + @Override + public boolean isExit() { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/command/ListCommand.java b/src/main/java/command/ListCommand.java index faa5eadfc1..f723693033 100644 --- a/src/main/java/command/ListCommand.java +++ b/src/main/java/command/ListCommand.java @@ -28,8 +28,8 @@ public ListCommand(String input) { * @throws DukeException Checks the validation of input. */ @Override - public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - taskList.listTask(this.getInput()); + public String process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + return taskList.listTask(this.getInput()); } @Override diff --git a/src/main/java/command/MarkTaskCommand.java b/src/main/java/command/MarkTaskCommand.java index f58dcb8ae1..67e115515c 100644 --- a/src/main/java/command/MarkTaskCommand.java +++ b/src/main/java/command/MarkTaskCommand.java @@ -32,8 +32,8 @@ public MarkTaskCommand(String input, boolean isMarked) { * @throws DukeException Checks the validation of input. */ @Override - public void process(TaskList taskList, Ui ui, Storage storage) throws DukeException { - taskList.markTask(isMarked, this.getInput(), ui, storage); + public String process(TaskList taskList, Ui ui, Storage storage) throws DukeException { + return taskList.markTask(isMarked, this.getInput(), ui, storage); } /** diff --git a/src/main/java/duke/DialogBox.java b/src/main/java/duke/DialogBox.java new file mode 100644 index 0000000000..d183f8252b --- /dev/null +++ b/src/main/java/duke/DialogBox.java @@ -0,0 +1,61 @@ +package duke; + +import java.io.IOException; +import java.util.Collections; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.HBox; + +/** + * An example of a custom control using FXML. + * This control represents a dialog box consisting of an ImageView to represent the speaker's face and a label + * containing text from the speaker. + */ +public class DialogBox extends HBox { + @FXML + private Label dialog; + @FXML + private ImageView displayPicture; + + private DialogBox(String text, Image img) { + try { + FXMLLoader fxmlLoader = new FXMLLoader(MainWindow.class.getResource("/view/DialogBox.fxml")); + fxmlLoader.setController(this); + fxmlLoader.setRoot(this); + fxmlLoader.load(); + } catch (IOException e) { + e.printStackTrace(); + } + + dialog.setText(text); + displayPicture.setImage(img); + } + + /** + * Flips the dialog box such that the ImageView is on the left and text on the right. + */ + private void flip() { + ObservableList tmp = FXCollections.observableArrayList(this.getChildren()); + Collections.reverse(tmp); + getChildren().setAll(tmp); + setAlignment(Pos.TOP_LEFT); + } + + public static DialogBox getUserDialog(String text, Image img) { + return new DialogBox(text, img); + } + + public static DialogBox getDukeDialog(String text, Image img) { + var db = new DialogBox(text, img); + db.flip(); + return db; + } +} \ No newline at end of file diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java index 2a31f47d9b..c7bf63eb43 100644 --- a/src/main/java/duke/Duke.java +++ b/src/main/java/duke/Duke.java @@ -47,6 +47,18 @@ public void run() { } } + public String getResponse(String input) { + try { + Command command = Parser.parse(input); + return command.process(taskList, ui, storage); + } catch (DukeException e) { + return e.getMessage(); + } + } + + public Ui getUi() { + return ui; + } public static void main(String[] args) { Duke duke = new Duke(); duke.run(); diff --git a/src/main/java/duke/Launcher.java b/src/main/java/duke/Launcher.java new file mode 100644 index 0000000000..b8c0f9c373 --- /dev/null +++ b/src/main/java/duke/Launcher.java @@ -0,0 +1,9 @@ +package duke; + +import javafx.application.Application; + +public class Launcher { + public static void main(String[] args) { + Application.launch(Main.class, args); + } +} diff --git a/src/main/java/duke/Main.java b/src/main/java/duke/Main.java new file mode 100644 index 0000000000..7575a4a34d --- /dev/null +++ b/src/main/java/duke/Main.java @@ -0,0 +1,31 @@ +package duke; + +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.layout.AnchorPane; +import javafx.stage.Stage; + +import java.io.IOException; + +/** + * A GUI for Duke using FXML. + */ +public class Main extends Application { + + private Duke duke = new Duke(); + + @Override + public void start(Stage stage) { + try { + FXMLLoader fxmlLoader = new FXMLLoader(Main.class.getResource("/view/MainWindow.fxml")); + AnchorPane ap = fxmlLoader.load(); + Scene scene = new Scene(ap); + stage.setScene(scene); + fxmlLoader.getController().setDuke(duke); + stage.show(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/duke/MainWindow.java b/src/main/java/duke/MainWindow.java new file mode 100644 index 0000000000..4f4fae8e27 --- /dev/null +++ b/src/main/java/duke/MainWindow.java @@ -0,0 +1,58 @@ +package duke; + +import javafx.application.Platform; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TextField; +import javafx.scene.image.Image; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.VBox; +/** + * Controller for MainWindow. Provides the layout for the other controls. + */ +public class MainWindow extends AnchorPane { + @FXML + private ScrollPane scrollPane; + @FXML + private VBox dialogContainer; + @FXML + private TextField userInput; + @FXML + private Button sendButton; + + private Duke duke; + + private Image userImage = new Image(this.getClass().getResourceAsStream("/images/DaUser.png")); + private Image dukeImage = new Image(this.getClass().getResourceAsStream("/images/DaDuke.png")); + + @FXML + public void initialize() { + scrollPane.vvalueProperty().bind(dialogContainer.heightProperty()); + } + + public void setDuke(Duke d) { + duke = d; + dialogContainer.getChildren().add(DialogBox.getDukeDialog( + duke.getUi().printWelcomeMsg(), dukeImage) + ); + } + + /** + * Creates two dialog boxes, one echoing user input and the other containing Duke's reply and then appends them to + * the dialog container. Clears the user input after processing. + */ + @FXML + private void handleUserInput() { + String input = userInput.getText(); + String response = duke.getResponse(input); + dialogContainer.getChildren().addAll( + DialogBox.getUserDialog(input, userImage), + DialogBox.getDukeDialog(response, dukeImage) + ); + if (response.equals(duke.getUi().printByeMsg())) { + Platform.exit(); + } + userInput.clear(); + } +} \ No newline at end of file diff --git a/src/main/java/storage/TaskList.java b/src/main/java/storage/TaskList.java index 359a02e720..8f5fbe2a9b 100644 --- a/src/main/java/storage/TaskList.java +++ b/src/main/java/storage/TaskList.java @@ -34,17 +34,16 @@ public ArrayList getTasks() { * @param input User input. * @throws DukeException Checks the validation of input. */ - public void listTask(String input) throws DukeException { + public String listTask(String input) throws DukeException { String[] inputLine = input.split(" ", 2); if (inputLine.length > 1) { throw new DukeException("\t ☹ OOPS!!! The format is invalid!\n"); } String str = ""; for (int i = 0; i < tasks.size(); i++) { - str = "\t " + (i + 1) + ". " + tasks.get(i).toString(); - System.out.println(str); + str += "\t " + (i + 1) + ". " + tasks.get(i).toString() + "\n"; } - System.out.print(""); + return str; } /** @@ -64,7 +63,7 @@ public void addTask(Task task) { * @param storage Deletes a task in a file. * @throws DukeException Checks the validation of input. */ - public void deleteTask(String input, Ui ui, Storage storage) throws DukeException { + public String deleteTask(String input, Ui ui, Storage storage) throws DukeException { if (input.trim().equals("delete")) { throw new DukeException("\t ☹ OOPS!!! The description of a delete cannot be empty.\n"); } @@ -85,7 +84,7 @@ public void deleteTask(String input, Ui ui, Storage storage) throws DukeExceptio Task task = tasks.get(taskIndex - 1); tasks.remove(taskIndex - 1); storage.saveData(this); - ui.printDeleteTaskMsg(task, tasks.size()); + return ui.printDeleteTaskMsg(task, tasks.size()); } /** @@ -96,7 +95,7 @@ public void deleteTask(String input, Ui ui, Storage storage) throws DukeExceptio * @param ui The Ui to be used for printing messages. * @throws DukeException Checks the validation of input. */ - public void markTask(boolean isDone, String input, Ui ui, Storage storage) throws DukeException { + public String markTask(boolean isDone, String input, Ui ui, Storage storage) throws DukeException { if (input.trim().equals("mark") || input.trim().equals("unmark")) { throw new DukeException("\t ☹ OOPS!!! Please input a number.\n"); } @@ -117,10 +116,10 @@ public void markTask(boolean isDone, String input, Ui ui, Storage storage) throw Task task = tasks.get(taskIndex); task.setDone(isDone); storage.saveData(this); - ui.printMarkTaskMsg(isDone, task); + return ui.printMarkTaskMsg(isDone, task); } - public void findTask(String input, Ui ui) throws DukeException { + public String findTask(String input, Ui ui) throws DukeException { if (input.trim().equals("find")) { throw new DukeException("\t ☹ OOPS!!! The description of a find cannot be empty.\n"); } @@ -132,9 +131,9 @@ public void findTask(String input, Ui ui) throws DukeException { String str = ""; for (int i = 0; i < tasks.size(); i++) { if (tasks.get(i).getDescription().contains(inputLine[1])) { - str = "\t " + (i + 1) + ". " + tasks.get(i).toString(); - System.out.println(str); + str += "\t " + (i + 1) + ". " + tasks.get(i).toString() + "\n"; } } + return str; } } \ No newline at end of file diff --git a/src/main/java/userinteraction/Parser.java b/src/main/java/userinteraction/Parser.java index d400db809e..a287f4055a 100644 --- a/src/main/java/userinteraction/Parser.java +++ b/src/main/java/userinteraction/Parser.java @@ -8,36 +8,25 @@ public class Parser { public static Command parse(String input) { if (input.equals("bye")) { - ui.printLine(); return new ExitCommand(input); } else if (input.equals("list")) { - ui.printLine(); return new ListCommand(input); } else if (input.startsWith("mark")) { - ui.printLine(); return new MarkTaskCommand(input, true); } else if (input.startsWith("unmark")) { - ui.printLine(); return new MarkTaskCommand(input, false); } else if (input.startsWith("todo")) { - ui.printLine(); return new AddTodoCommand(input); } else if (input.startsWith("deadline")) { - ui.printLine(); return new AddDeadlineCommand(input); } else if (input.startsWith("event")) { - ui.printLine(); return new AddEventCommand(input); } else if (input.startsWith("delete")) { - ui.printLine(); return new DeleteTaskCommand(input); } else if (input.startsWith("find")) { - ui.printLine(); return new FindTaskCommand(input); } else { - ui.printLine(); - System.out.println("\t ☹ OOPS!!! I'm sorry, but I don't know what that means.\n"); + return new InvalidCommand(input); } - return null; } } diff --git a/src/main/java/userinteraction/Ui.java b/src/main/java/userinteraction/Ui.java index 43e593d491..beaf38018c 100644 --- a/src/main/java/userinteraction/Ui.java +++ b/src/main/java/userinteraction/Ui.java @@ -21,21 +21,21 @@ public Ui() { public String readCommand() { return scanner.nextLine(); } - public void printWelcomeMsg() { - String str = LOGO + "\t Hello! I am duke.Duke.\n" + + public String printWelcomeMsg() { + String str = LOGO + "\t Hello! I am Duke.\n" + "\t What can I do for you?\n"; - System.out.println(str); + return str; } - public void printLine() { - System.out.println(SEPARATE_LINE); + public String printLine() { + return SEPARATE_LINE; } - public void printAddTaskMsg(TaskList taskList, Task task) { + public String printAddTaskMsg(TaskList taskList, Task task) { String str = "\t Got it. I've added this task:\n " + "\t\t " + task.toString() + "\n\t Now you have " + taskList.getSize() + " tasks in the list\n"; - System.out.println(str); + return str; } - public void printMarkTaskMsg(boolean isMarked, Task task) { + public String printMarkTaskMsg(boolean isMarked, Task task) { String str = ""; if (isMarked) { str = "\t Nice! I've marked this task as done: \n" + @@ -44,20 +44,25 @@ public void printMarkTaskMsg(boolean isMarked, Task task) { str = "\t OK, I've marked this task as not done yet: \n" + "\t\t " + task.toString() + "\n"; } - System.out.println(str); + return str; } - public void printDeleteTaskMsg(Task task, int size) { + public String printDeleteTaskMsg(Task task, int size) { String str = "\t Noted. I've removed this task:\n" + "\t\t " + task.toString() + "\n\t Now you have " + size + " tasks in the list.\n"; - System.out.println(str); + return str; } - public void printFindTaskMsg() { + public String printFindTaskMsg() { String str = "\t Here are the matching tasks in your list:"; - System.out.println(str); + return str; } - public void printByeMsg() { - System.out.println(BYE_MSG); + + public String printWrongMsg() { + String str = "\t ☹ OOPS!!! I'm sorry, but I don't know what that means.\n"; + return str; + } + public String printByeMsg() { + return BYE_MSG; } } \ No newline at end of file diff --git a/src/main/resources/images/DaDuke.png b/src/main/resources/images/DaDuke.png new file mode 100644 index 0000000000000000000000000000000000000000..ef08b4e4b7afd90922778a31964591aff4b8f8e0 GIT binary patch literal 20386 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 z zxX2W6s)m9eE@6o$Pu>zHVZ9~a_!n?5BujyE?2Xr#1~CQ*qMn`bQK!n z8gG@SWYoPdtDTG_-TWMqJ_zPfPd*K=C{SK(;h1jck8a2 z*y5Nf4Bnl}t|8d54ytbWY5RdAoty?YvNveYCRetLabyn2kj$#RiG9tezmW#vo zTnARi0QMBGzZg$OA3iI!bGr#G9?+&(&*)a%g@KvZwbYApJs50a+{*2Nu~rh3Fbl%3 z#$Td4BX@#+%N+wQ8@TCMy?gfV7+|*J)IxB5v?DXiL-sx5lH_>u{;r9ZBD9I)Xix_j zh4`B6qv=D*@!MCu5SG()w>2c;Sp?G0&*`hJ`k#`^N`2ES9X+cLLzg>iZNPt^&*yjwda@Q#c`lRlw6ReYF5`lCjZm&{z<>R zX3t}Q@iAbH@aJ;xAIs?$4@FwyBeY8l31~NNpSWM*e(q?lMmX`W1^M>fRF1l5*7Z8q z?vx<^e!%_)^Oul)bsr4*q%Z%{Ud00oSIqVt3c?I>l9I=oP z+QAX%UX^}GsOOKCeHtC2aI#si)!m; zSm3S7dr!Ook1a%_1f=DSKMv#t#d(U)moY7n*u@4)#%8ADL)BS{J?p3EAs}uI!`D2D zcYl0z=liG)7JImiZ(~gzd1ui7V;gjFjwbAv%2MU5Bf&22JpzWwY4wjgM2(J$H@f&5 ziK{7tHvK~sW>`kT>EcdT>aA?!|V@CyTlyh=5vWV(kth z@7Wa%NEYyKPP0Vmk&2Zv&fjB3ecD}Gfx1hu;xJ&BL+rTKdd$d!*Q zN`2Dy2-r|o#)OFcc^UrU7*Ixf8;PbahUCQCJoK~I$k#Ed7epmJ5#vQl~4=1}d0WZrzGFI=sjOF4afbF&`RRX2212Ud|| zNRoS%%k+Mh=V1LEGrD!CtaZW0A2A;b=H7)Cy%6q4+f+I4#{A~Z-)x^+U{l$O(ixF| z)`Z883`K=qb4Wvr$v(V{Us>`guX}q$&DxAGRJ5ory*RR`sX=b&GbR357%Mz+02n`t zePfn4G8mTg@nVPfsEBf2dmQa1yC#%YbmSzvpZm?dN9urF3JU;|+cMIv(~beGnKk0- zYL|Xy!A>?5$!sc88Qi`D7+!_Ee40V(mV13*FST!n?ebu^MKcu?%lS@L@<_kQA66mcVYggeicYK19SE8&vsde`#9=a-;yNnJ zE!XAmY^gp3q(Km{C=(Swxs}UAE9{maNJ-IWXe^5O4MF8+q^{5Iyx?P)^vTLQdtnJK z%Tr(%EX9)F} zIeh_c{8T~`OcNqQJ&*^BZ=M$Wj*4BZP%BTVTQ}fP#ZUCNeO!ASe6It=8*Dh?3KT@4 zX5BJN&AP|PUF(~mUr;6)pE|%_6>pr9pftf}{iP2Ld{U2kxoXp7ju;S3W>Bi5V?VFu z>i%nt%*YRmTTOhC-N3`yo|Bl6@tfFk{XpRGvzc)rZBvh<>vBc)BJ z>V@W`8gVdh~H#$lEDs8p=(4k0qmF#>%-Xu18T&mdtX;6-uW@e$AkIOnH zS}vr)pmQy0e$$%wu1MP4a~0&b&`UI@Sp1;^LTtz$xw`M~lxddmUAx}Lt`D-e^_*w(k)@jw z^<@Ip`-yTEO6f@y$1Y)?kmmF6fIeBy#!9vZe~jqdCHS-|&&v33ce5pA0$S<(AI#mw z16w|sisVK2)o8_-(U`o@z7eW&L5oLNc!Cjw9vJqd#plZxnchmPC`4trzBJQ*|>m z<7Nu!9(viVn;^L@kxRfwI)_=-YHY4t>%%0?X4#uzp4Zj7%EXiPcG^EF; zcls04@Bck1?Fd}MZ>xI;oepV2K`sO3@wc%+LFd(K89lQg$M}${XBLT)FecLHi7+ao z#2_*zJHW@MCf1@fLAOF+NRaO%V-I5MXr{TRR$apk=Dze5cGr~}|_CbU!7?phMSnRkuVXA9}J`&%2WQD zpw@mD{@7j$`$Uhrd9uUjW~A2^p6oWTj+IVDX`dx`AgCjqq+ya&IXuAl`V@X*VBq+O;pNIcJ-fO{7X(@X;|~jG70ZrY)!3bqRpa$*A6%*#tkoCPdkBCiHTr%&TW|KO#beohj(fjOPHR>w#e--#U`n zIh!rc!TE@OWu&zD4!@fFCHZ=f?KhTou5+KP0hGMEYXoZ8D?o`&)X54PTt91^k%Zyv z9$X2WaFCtDrl{FCDf$?w56Pk>Dw=)HY!J7|aURNvjPgpzsLKm!8caf+BCu)~&e?mx z!6{Cqbg_m^>uRJLzc2P>Sfab`qrV8rlKW!&|B&}=$EcmSk`TZ2mPKw@ZXZoe1V30s zxjgJ2P#)XysayCMK$+VfyKG(4>v5D#>l+q54oINpzU8T!|bvW#$TV=|I2aA z+NDCP)=DBi&d}31>lpCeVeiAmbpXJzXowi`dKefnLik%UZ-x!cWWizb{p0Cb#1tFz z43Dy){G!wA#{hSeta`nA-6V~$7{W{B`w2W=f!%=1P2EbJm*#J3f&MbS)APvGt)uzO z;Kv#QUnRTsz(N9eo}y=Urz^;}@17^d#@*QM&L*3D313RWVFe?l$$Z#dI@<%tPOM|7 zateHZ@AqmBi>?Wl2@4vZ5Qae80~3=sTIO$ZcS9RRLI}xcwHIin0cAa5{js})ygSbl zKu+&wd*1Z0WDGC9tlL39g%ylEdp(_}Qe?i!H}U7ddy3CX;AD89R6!d0Y?NZ#f@YZG z;0MiZ3|@UMe?>ZX$2mR%vaO=Mxpu+i9^7EQ-oWL*Roq#E->lHsJ3d6D=gV zNSG-sDYX$Nd%M7$#s9-f2Mnq(S&ar5#Tvx-85U7vd5Y>}Ym@d~7*&Wm*liz%!Eeer z1(dbdb(*St(5rW!%F9_^@pEo+m-qBy-x@Q~WDk|O8D%2&{gjcnojaR(dUyu1)tJb zZv-C5S+Xg8Bk-gsJ*vdK{N~;&`U;}vfz=?bh^H|Ar*nW&8gCbcqW_fYg&B({R5V-T zCw8P-y53ex^LL2ZWt7_4^0Uu1tPdxM4v@8QT5EZMK`*PStpkV%zWP}^ks`MKp46HA zYIHF9x76qI4U?UKCJe|gJZ_oaaeIZ>!;79N44Sd`v#gh)>HgruPN-8t zAwGuqL|gxAeZ8x>r&S(M;)laDJ~reUpSluts~tC#pSY)hNvV^JRKCry*?FMVBHgO- zTY0s6wb(9jdFZ04?V>{Ls+u`?+bMKA$bwk=zMQ)(fIM(Wbz+BtKG>hPOfbw(;HuDt ztPItFNfn{|Ad$J)tWRZ1y%qF)C0&^tJ}U#AnC$$#cl3w+j^LLPfGq%virMIN^$#yD zPM|=0j4&T&Kbxz=i7->*wL%hu8g}nnY|`UWQX~FL7yNVMQjs5!8)nMRDMK)`o1?<4 z=Y5=BBJ9M)6vM>D^t-tIqa9*#JeLhTFOnw8$;y1V5&FR^RXo1MHZjmp;U&;V=is(Q zoOA!a(Y{Y6?`jkrB}QwFdYxPkc$*p=uP)~DW2sej$=!#~PdoHev-`#9fOgk92g zNu_-8QCNoOR7xyVSK%E~)z$INA?K9g0J7$=rIY@Tw1tG32F1Zr`c@TU)5`U*hJD8< z0j_y#2IL(pn=yP$EGZLpO5J)a*{?QF-XHkwD{!7I{@n#l zgU09ojQc-&EH#yZtK@}rnxjB`I5bff7QXRrfMAy{hc;TZ(*!-dJM}4^db8d6Znb2W zA9HuBDCR3)`!ILB72ii)S%~z`i*rGLeOL3+yd6vxYFi++#qUfbt%s^$oHAK5+BTY> zw&rjp6F2!#CD=q+Z#L?ND&IJ_aY#=LUjz^d)G6A(qt|CJ)+Kr2V)EFdx8U;a^-cN6 z*S(BGHfPWJ7yRNLF>w~KccHo=lI!_M*r0NRU`RnoMTrhseYHnYRF78pD9XvJa;pnAF zFX)AxMM)$lp&k*1`y3bk5N0+c#GrwV|YOWc_@;<4Y|u zUD@fdyGfKgy?W&fcO^9QN|aa52S22bMi!MRmyfUVR?t#-BV1`S4V^!_EwrvRCHjs| zK2A7E_Y>x8f95VNfh8hNVyaXpWSwHd1LA7Sb6jtQgGWVfLTUG`Wv=n(qE*!>k+n~r zLE}C)-*%6BgElq=zcUyEs1YroJlsbZtq^ z(=j|hYiu}O|BT(Jjfi8GAMxFnq~3s{YoeO9w?;Yyf*w5helY#C&)WWFk8VC);Jpq) zEOQ!C8#UsaP1`0{=Lh1+o)<4{eHZJ@a=n{`utnPla}q4D*q{&n9oq#%Vh2C+>r=~g z-lyHx1U3r4)mv-39HD%;;6maF#nssvH+*V72Kbi`nGMtBhtxC7Al=RI-1k-7yj`k( z(9>r| za&rY?KA#6D?DoS?zyG3n4y3w=Z>gNK0m`kI*Cl{ap`So;VpFyD8ja3NG)@izYT9rt zXvnf3Y`7zLF=<4K0BL6TkKP7zjC*E%#tv4Sr_37{>KA`Cbp)o^L+keqp6x(m&}u2MWyQ%D1HS3v8k7JADhYu;JYY4anFqpfDfH9qe~83z8&HM z#XAW|%9`fVcJg@DjQ79D%RjnxfaslrfXv)Qo2Mn3aUnP_`)$MA3l0L2zjm(#bu{A^ z0-G@he|Qk_c{rS>| z#_2S7BV8Zr5S`f7BeQ4s3LarO`g36Sh9blLdzW@(QFYVDX_zycP^R6~F`(uP6)l;U zFob?XPFRdFzN5F8YtcZ+z3i_uo=tHL%~ywbDlD(%WMwT^Nc@%n z&p46}m@)D}drR&l3z<+$n^v)R$(8U(7RCio+|!@~lkepvT{xoT3){jeeSQk$tEtIO zO=&`=e}hXzq4uvGXlu3VBsxD*b#me;K1kfy;w0g0z3c$O@aS)AsHm}Z0#8nQFF1W& zwD0Bv3p18T;Rh|p01+OVJST)~o$%5f)~$a{QSNg)qLHy)1Zsuwn=1&GFeDMPPFpmO zRDR~_lA!etjSI*{I=-_FeV1ZC+WBC$e&d2rS>Hf)2N-G%N8)8L^(fd97os7Qy!1(_R7H7IVEU~+|Y~ij{)ZW*gq%$E=Q`E)w@59mn zjUCpH3kw7pXItG1UdWCG#Cxe)_Q6&2g&bQ_K!pr>%69&xl0z@fo?noV*x`n)u$l6J z4lL{3E}W%k+()Ps>ATx>g)NmG?hF^QLu5LP6AR$612EX^kQisFwQ`b!`}qZLSfIRz zsT{pvZt+%aFD&%bXLmM1p-*G`7ujLp9z{2QM>FA0mLED$z0`bo_7qDT}(6 z?}2|W zz7mMTJstRv>@Vi!ZYTcGOu0l$j=*0YHG|sVd<+Qwr6#=2Fjlli zTRxz@b4}SBp0_07zpsCVND4Mi#D7q*X5+i3^1W!Q^7kr+P!yqfzb^|ppaXEQ7&y(QMy1(?yWfoFiU}w&9TjdI z%vaH?V+T-`gz736B8=?(8Ry{c@Mq~VP)rVrP-Pn;EzuwJA`gcoRa(vr9+8bBC@YW5$>d<%vthe;cQxa~y&RL|{T@TUF9zjrK4{7r%1}lZ5FxgQ z(v?=-94SR?^k#>dyyW;5WPBK}yq_pCyjQ1Z1C8%}14qU0hqov64!{RhnF<^~1*UwkW(kS> z$r#e>LWHAFRuNJQyi8*+5b1V`?UYW*@tgNFb*0Y}6HZ`yOe(3@`KGODi zP7ePBwSWGy)B-igDZ1Tzdkq&M7SmEnAgNvFCYG#XKNZvAqnh0}>4eF~Hf*q*YQtkl zlXxkp?Vp6;ADy#VlUB^kT-z`|G3a`+Qy8rmmkA|t*$f8{)WjRPR`h-qe_aygyb4Q0 zZjekJ(3fn#3*WN8KtIb*vV&@1SP{sab4Ak zGsbXc7>(9gFh<;#FYf@W^!7Gzt&7OiyA+K;581d&ta@*#x75 z=S2~@q<|g4wg~2W6pI?N5V3}cNl4KRY|pp#djKwHg!Gex`2Fbw+3cbK`G9W6UQ=6q z@(hkexu_JVSl6MCd+Hw9uFtB_Bf(?er2_Ta2_6A@zu_{zufZ7l@Ezx9Csx9fZ`5$sbPQK>g%F6DLkBnB0b${u&(&dvae_+7wF`yLM zhFHpwPPyUPI`>Am*JZ0vIDoU>yy5A3DY%N%~ER_so@X24FKk$zASCPa!kr3QPul2DJ-k;*q@L+6Q|nMfb-? zaa+*@Iu&Fc!#6+ul|qShW%=?CDf~Zc-uK))WG!+acQxAZyFP-@UrT`6y9tG;tU)-3 ziF!@$<%3Icqo(hh`TNprGp{1n?#;epg69!?4>m5sr+>98q=a9L zP**k!i&`Oz5l_!rcQ4+hYN?(!|8C=wA7JxrC7^Eh304qxuTJE*M*Xxu4*B^Hv7(tl zpl!n$!xu(D`y(sCbv?K=?yW`heTs$fW6}&dkyjP}YUXUpiVv1-19xAV)x*2}DAC(q z*A`*z?zPsrHrDoMW%suQ#mM*Nrb1u6>M~%QSS~``j79e%8DgxD%W$*=msC5+01Q9IMT)x==m0m`^p)zT|{4Xd5$8DJd=(_Etz8NvI;vYg^;@lR~>M=0@mksK4x8Ck{ACFn%A*QmPN%%h{eQ9}ZU|4>wKZviUhDd-;Ez!O-FYVrVQjzJlMd}!nDqQg}Rpv4M zHUYAYyxYcJ4D*ex;}N%G=A0T@nEsvUt(%RtdP=0!FW!Euu;Qi z2eF;h%?B+n<|=z3W3JfTLPQe8@IQCGpmk9?E$KVicfBz4#&)a)FzObtCe_7AUga5G zjTo(-%o|-drOF_ygPeM+fuQXN6^o&1N`p1|YZ26! zpB^K5Pb7QJeQ2kUkW3XVmC!&3euQH%GX4*HwO9Gtcqt3HuA6M`2Ys*u|Isn;z?0MW9sWD^sv!GT{A3H@}(9i>) za?bSG&rpm^Rpolmz5B`$`4d46!v!N0q4p2v-`WSj1$FFVVCHQ(h;0H~)dF<+{g+YNw|M!+L?X>A9k}5#Xe2qXcd457bT{B02z8AElkTdMVi-bmuN~+if z*hKl{B*cF!O!i}H2z-DhB^S(+Yn`tvggV3AnxjNNhW@$Dy%~)DFw8A$!=B=+b%2HP+kV zKEK`rRYBp-T~kM93yJA$I!gN{mVR5yxBsL)k29(sg;lr^z5P}4Q^-KBoL+ER8*Q>1 zLL~8K9s+O=X*VqVEL8F%Y7W(m$qEh>2j$inw=jytz`lpSgaj~<&1EqUnU94wLYkpv znW5!yHWczO8)ESZTx%IRwHE>rq}~bO-I8Rkzl_~SV@8URo{P@GOX99K?UdUC>*?|#F-hVy zzcPp>weZw6j%uoRp-9?!y~t6v}M7laPV!risL4Tr`e>d?8?(knJOU|tgCN=2ES|g%ZkSXh%--9ax zJ8WQ%E5h$u&1w~NC>y2$)-$?MKBz~u!2l{22Ge(pfBbybjFBghn&#j_V|P-XVt|(; z5C=U=o%>hb@Cxp>&V+2Xvc_B@p!Vi`jGFUIx<)iJ?CbE>@*Z+pniy#Clnc|;y#AZU zLLbGYf52z_kC&e3dTC(+1&eHyV0Z8!$n(wIbAZYD)rhtq5}{OkKPG7{(;DESMxuz7 zu}VUOkF4r-Ijz25!wM=Ebu#LRjFJ$m%!&Z)aWU1UHRj3#TP}Wq)do+?Pz<9I z2kWL98^(G*US7cM3tD<&JPidn#@2?_GY*zs(aG}@y!FlzJ|{TrEu*Gnp6d;afP|xq z4q0X}ohm_xxbfN2l%Tn0*HjsYPuKO|`9#rf9uuz&Xxj{+kM(5SiEbIEF6*73JU$=Q71>XrX3tiW ziH!-tYm$v>d4uuJ1qa8h}dc#4to8k@WfmlM}!#;EpqvskKuv^$E83&6ZS+J3u@-RViUd!)V%ztti3->El(uP0wgS4-1y;ZLLcF9yQ{( z^x<8FYQI<53Z^Y13UuE7WZ?g+klJH2f|rgTBE#=*TZ|d;t3{99mC5sU&QSD6=+&?95$M4 zY{IC+{g61N)gIiyM>iFX)H(XhAe3{A#>wAmZ=RDa;#b}P|I2+I08k8XD%9n+gFqd{ zq{dTbq-j9b2sq10;{qg=6;^eOq8wlPJsUxVhmKrFruX!*f?f;1;MJyIYu||eTv0f% zIoqrqGPk2)82b&!1?O5T)%SXKEp5Yd;r4N_ni}B)7hhmUQ*1;|3WTM_soBQlv3G*| z-l2Jd&si(36dHpTs6Rx0s9$YV!Cn!{n>+|0C>tn_-0>Y=(Zv)wXF@B?CWDmxCdx+e zv-5K+u6*FU;sVmrEVVxd;hwfw@c=nTVdfx}^+ESj;xiM8x$y=!lqYYC%nM^V;uLUU zo{a2T<};!fjFC$q>vTJ8)Wnnslm=FMuCYOr%BU1=x}pOTPtI(zP>}f^!Wlo5;gp@S z3^(zm2+0A4CS`0&AJQG5ipxD3Q^cba&!C>-Q0R-dLRLb78TYA3K(yYOTr%kILvgUZDI@uIr z%80Gzr%n|)Fzy}}CaV^gu-ohCxO;-bc7?hy`B7bGWKBcvcXzQu&n?kQjebW9^g(y` zKXcv^5(mgWCzb9kpG7EW6CmR;>ceH(eS2e&>-e6yP(Q0uFP2g5HCD!G#@2~WIhmw( z6P(2ccRB4{agFNTwa)cmMl1`HUXoG22~`AEuADy>34Ve$Z*STlLJdGVd^!$OJWthh z`Ogg$VRCYTN(iPa^R!CwQOklq-O*S%ou|IEqs$a@W2EN9=LV@Ve?H)ZfA6B7e(X~_ zPpNpV1;j;SgXyl8x_W!NDz@TUH>$%CrHJoGr>$+Wf4_5c|Lqhg)ZKB{Z;uG3{$c)1GOeFFd<*|dB}H_V zX~IQa?FILCU|TcP_J=>_1yJSVKMy@=+slIs!B5YJ^Yz`qkj@V>Pr93$U7cAQmBj}n aU2J9YO(Cz;Zv8`b_`mCa;smZYMA%rQu1SfA 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 ZB)9E<*ZkG`Up)4&!vBqU0_J}_@;_LkF=+q* literal 0 HcmV?d00001 diff --git a/src/main/resources/view/DialogBox.fxml b/src/main/resources/view/DialogBox.fxml new file mode 100644 index 0000000000..e433809947 --- /dev/null +++ b/src/main/resources/view/DialogBox.fxml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml new file mode 100644 index 0000000000..832f84382e --- /dev/null +++ b/src/main/resources/view/MainWindow.fxml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + - \ No newline at end of file + From 6882f686916411971ebb0dab711120ea1ae58a86 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Fri, 17 Feb 2023 19:23:38 +0800 Subject: [PATCH 31/42] Resolve the command error Solve the issues about spacing after some commands. --- src/main/java/userinteraction/Parser.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/userinteraction/Parser.java b/src/main/java/userinteraction/Parser.java index c51336585c..508aad5ec4 100644 --- a/src/main/java/userinteraction/Parser.java +++ b/src/main/java/userinteraction/Parser.java @@ -15,9 +15,9 @@ public class Parser { * @return The corresponding command. */ public static Command parse(String input) { - if (input.equals("bye")) { + if (input.trim().equals("bye")) { return new ExitCommand(input); - } else if (input.equals("list")) { + } else if (input.trim().equals("list")) { return new ListCommand(input); } else if (input.startsWith("mark")) { return new MarkTaskCommand(input, true); @@ -33,7 +33,7 @@ public static Command parse(String input) { return new DeleteTaskCommand(input); } else if (input.startsWith("find")) { return new FindTaskCommand(input); - } else if (input.equals("help")) { + } else if (input.trim().equals("help")) { return new HelpCommand(input); } else { return new InvalidCommand(input); From ac9981274a5d74ea6657c6a50d2e79952bef7d79 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Fri, 17 Feb 2023 19:33:13 +0800 Subject: [PATCH 32/42] Fix the import format order issues --- src/main/java/duke/DialogBox.java | 6 +++--- src/main/java/duke/Main.java | 6 +++--- src/main/java/duke/MainWindow.java | 1 + src/main/java/storage/Storage.java | 12 +++++------- src/main/java/storage/TaskList.java | 4 ++-- src/main/java/userinteraction/Parser.java | 12 +++++++++++- src/main/java/userinteraction/Ui.java | 4 ++-- src/main/java/utils/DateTime.java | 4 ++-- 8 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/main/java/duke/DialogBox.java b/src/main/java/duke/DialogBox.java index 00aaa62de6..bbfc5faec0 100644 --- a/src/main/java/duke/DialogBox.java +++ b/src/main/java/duke/DialogBox.java @@ -1,5 +1,8 @@ package duke; +import java.io.IOException; +import java.util.Collections; + import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; @@ -12,9 +15,6 @@ import javafx.scene.layout.HBox; import javafx.scene.layout.Region; -import java.io.IOException; -import java.util.Collections; - /** diff --git a/src/main/java/duke/Main.java b/src/main/java/duke/Main.java index 4137d6f715..a2cacb8d4f 100644 --- a/src/main/java/duke/Main.java +++ b/src/main/java/duke/Main.java @@ -1,14 +1,14 @@ package duke; + +import java.io.IOException; + import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.layout.AnchorPane; import javafx.stage.Stage; -import java.io.IOException; - - /** * A GUI for Duke using FXML. diff --git a/src/main/java/duke/MainWindow.java b/src/main/java/duke/MainWindow.java index e5ccf20d11..a3dc65075a 100644 --- a/src/main/java/duke/MainWindow.java +++ b/src/main/java/duke/MainWindow.java @@ -8,6 +8,7 @@ import javafx.scene.image.Image; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.VBox; + /** * Controller for MainWindow. Provides the layout for the other controls. */ diff --git a/src/main/java/storage/Storage.java b/src/main/java/storage/Storage.java index 98c263b622..351da57ade 100644 --- a/src/main/java/storage/Storage.java +++ b/src/main/java/storage/Storage.java @@ -1,11 +1,5 @@ package storage; -import dukeexception.DukeException; -import task.Deadline; -import task.Event; -import task.Task; -import task.Todo; - import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Files; @@ -14,7 +8,11 @@ import java.util.ArrayList; import java.util.List; - +import dukeexception.DukeException; +import task.Deadline; +import task.Event; +import task.Task; +import task.Todo; /** * Storage class to deal with the file. diff --git a/src/main/java/storage/TaskList.java b/src/main/java/storage/TaskList.java index a3053a168a..41846d1575 100644 --- a/src/main/java/storage/TaskList.java +++ b/src/main/java/storage/TaskList.java @@ -1,11 +1,11 @@ package storage; +import java.util.ArrayList; + import dukeexception.DukeException; import task.Task; import userinteraction.Ui; -import java.util.ArrayList; - /** * Task list class which stores all tasks. diff --git a/src/main/java/userinteraction/Parser.java b/src/main/java/userinteraction/Parser.java index 508aad5ec4..35552c3251 100644 --- a/src/main/java/userinteraction/Parser.java +++ b/src/main/java/userinteraction/Parser.java @@ -1,6 +1,16 @@ package userinteraction; -import command.*; +import command.AddDeadLineCommand; +import command.AddEventCommand; +import command.AddToDoCommand; +import command.Command; +import command.DeleteTaskCommand; +import command.ExitDukeCommand; +import command.FindTaskCommand; +import command.HelpCommand; +import command.InvalidCommand; +import command.ListCommand; +import command.MarkTaskCommand; /** * Parses all the user input into corresponding commands to be executed. diff --git a/src/main/java/userinteraction/Ui.java b/src/main/java/userinteraction/Ui.java index 1674379fe7..9d687fb985 100644 --- a/src/main/java/userinteraction/Ui.java +++ b/src/main/java/userinteraction/Ui.java @@ -1,11 +1,11 @@ package userinteraction; +import java.util.Scanner; + import storage.Storage; import storage.TaskList; import task.Task; -import java.util.Scanner; - /** * Ui that displays commands' message. */ diff --git a/src/main/java/utils/DateTime.java b/src/main/java/utils/DateTime.java index 86be757755..da492c2660 100644 --- a/src/main/java/utils/DateTime.java +++ b/src/main/java/utils/DateTime.java @@ -1,11 +1,11 @@ package utils; -import dukeexception.DukeException; - import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import dukeexception.DukeException; + /** * Local date time formatting. */ From 3b97191dfacc130ff28b37c3c4cc5d668129dab4 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Fri, 17 Feb 2023 19:37:30 +0800 Subject: [PATCH 33/42] Fix import format in parser class --- src/main/java/userinteraction/Parser.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/userinteraction/Parser.java b/src/main/java/userinteraction/Parser.java index 35552c3251..93bbd331f5 100644 --- a/src/main/java/userinteraction/Parser.java +++ b/src/main/java/userinteraction/Parser.java @@ -1,11 +1,11 @@ package userinteraction; -import command.AddDeadLineCommand; +import command.AddDeadlineCommand; import command.AddEventCommand; -import command.AddToDoCommand; +import command.AddTodoCommand; import command.Command; import command.DeleteTaskCommand; -import command.ExitDukeCommand; +import command.ExitCommand; import command.FindTaskCommand; import command.HelpCommand; import command.InvalidCommand; From 9ff9abba9194b252b97f6cb230eb1dcec6c015a2 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Fri, 17 Feb 2023 19:53:19 +0800 Subject: [PATCH 34/42] Fix checkstyle error --- src/main/java/userinteraction/Ui.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/userinteraction/Ui.java b/src/main/java/userinteraction/Ui.java index 9d687fb985..6163c78f80 100644 --- a/src/main/java/userinteraction/Ui.java +++ b/src/main/java/userinteraction/Ui.java @@ -10,13 +10,6 @@ * Ui that displays commands' message. */ public class Ui { - private final String LOGO = "\t ____ _ \n" - + "\t | _ \\ _ _| | _____ \n" - + "\t | | | | | | | |/ / _ \\\n" - + "\t | |_| | |_| | < __/\n" - + "\t |____/ \\__,_|_|\\_\\___|\n"; - - private final String BYE_MSG = "\t Bye. Hope to see you again soon!"; private final Scanner scanner; public Ui() { @@ -32,6 +25,12 @@ public String readCommand() { * @return Returns the welcome message. */ public String printWelcomeMsg() { + String LOGO = "\t ____ _ \n" + + "\t | _ \\ _ _| | _____ \n" + + "\t | | | | | | | |/ / _ \\\n" + + "\t | |_| | |_| | < __/\n" + + "\t |____/ \\__,_|_|\\_\\___|\n"; + String str = LOGO + "\t Hello! I am Duke.\n" + "\t What can I do for you?\n"; return str; @@ -114,6 +113,7 @@ public String printHelpMsg(Storage storage) { return storage.loadHelpExplanationFile(); } public String printByeMsg() { + String BYE_MSG = "\t Bye. Hope to see you again soon!"; return BYE_MSG; } } From 26f91eb08e2e465e02b94e7fdb8385b2c88bf0a4 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Fri, 17 Feb 2023 19:58:53 +0800 Subject: [PATCH 35/42] Add java doc in ui class --- src/main/java/userinteraction/Ui.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/userinteraction/Ui.java b/src/main/java/userinteraction/Ui.java index 6163c78f80..68493157ab 100644 --- a/src/main/java/userinteraction/Ui.java +++ b/src/main/java/userinteraction/Ui.java @@ -25,13 +25,13 @@ public String readCommand() { * @return Returns the welcome message. */ public String printWelcomeMsg() { - String LOGO = "\t ____ _ \n" + String logo = "\t ____ _ \n" + "\t | _ \\ _ _| | _____ \n" + "\t | | | | | | | |/ / _ \\\n" + "\t | |_| | |_| | < __/\n" + "\t |____/ \\__,_|_|\\_\\___|\n"; - String str = LOGO + "\t Hello! I am Duke.\n" + String str = logo + "\t Hello! I am Duke.\n" + "\t What can I do for you?\n"; return str; } @@ -112,8 +112,14 @@ public String printWrongMsg() { public String printHelpMsg(Storage storage) { return storage.loadHelpExplanationFile(); } + + /** + * Display the bye message when exit the program. + * + * @return The bye message. + */ public String printByeMsg() { - String BYE_MSG = "\t Bye. Hope to see you again soon!"; - return BYE_MSG; + String byeMsg = "\t Bye. Hope to see you again soon!"; + return byeMsg; } } From 832d46a088503386d53d6d46cd40b6ba1b62031f Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Fri, 17 Feb 2023 20:06:23 +0800 Subject: [PATCH 36/42] Fix checkstyle error of DeadlineTest and DateTimeTest classes --- src/test/java/task/DeadlineTest.java | 6 ++++-- src/test/java/utils/DateTimeTest.java | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/test/java/task/DeadlineTest.java b/src/test/java/task/DeadlineTest.java index 2c0c846f77..5446a1b019 100644 --- a/src/test/java/task/DeadlineTest.java +++ b/src/test/java/task/DeadlineTest.java @@ -1,9 +1,11 @@ package task; -import dukeexception.DukeException; +import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; +import dukeexception.DukeException; + public class DeadlineTest { private String input = "deadline buy book /by 2018-09-08 1800"; diff --git a/src/test/java/utils/DateTimeTest.java b/src/test/java/utils/DateTimeTest.java index 5f0b18c8b1..2df3fbdc66 100644 --- a/src/test/java/utils/DateTimeTest.java +++ b/src/test/java/utils/DateTimeTest.java @@ -1,9 +1,11 @@ package utils; -import dukeexception.DukeException; +import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; +import dukeexception.DukeException; + public class DateTimeTest { @Test From f7536e58cb4dcd3753a09a0d46c3dcdd99b6c883 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Fri, 17 Feb 2023 20:09:38 +0800 Subject: [PATCH 37/42] Fix the checkstyle error in the DateTimeTest class --- src/test/java/utils/DateTimeTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/utils/DateTimeTest.java b/src/test/java/utils/DateTimeTest.java index 2df3fbdc66..a474f79a29 100644 --- a/src/test/java/utils/DateTimeTest.java +++ b/src/test/java/utils/DateTimeTest.java @@ -12,7 +12,7 @@ public class DateTimeTest { public void getDateTimeTest() { try { assertEquals(DateTime.dateFormatter("2018-08-05 1800"), "Aug 05 2018 18:00"); - assertEquals(DateTime.dateFormatter("2022-02-02 0937"),"Feb 02 2022 09:37"); + assertEquals(DateTime.dateFormatter("2022-02-02 0937"), "Feb 02 2022 09:37"); } catch (DukeException e) { System.out.println(e.getMessage()); } From abd962bf965a8d5d242d634ca398741e52f3a737 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Fri, 17 Feb 2023 21:08:08 +0800 Subject: [PATCH 38/42] Set up a product website with a representative screenshot and user guide --- docs/README.md | 155 +++++++++++++++++++++++++++-- docs/Ui.png | Bin 0 -> 75934 bytes src/main/java/duke/MainWindow.java | 18 ++-- 3 files changed, 157 insertions(+), 16 deletions(-) create mode 100644 docs/Ui.png diff --git a/docs/README.md b/docs/README.md index 8077118ebe..67dd2648a2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,29 +1,166 @@ # User Guide +Duke chatbot is a GUI based application with basic task management functions. + ## Features -### Feature-ABC +### List all tasks `list` + +Lists all tasks are stored. + +### Add todo task `todo` + +Adds a todo task with a description. + +### Add deadline task `deadline` + +Adds a deadline task with a description and deadline datetime. + +### Add event task `event` + +Adds an event task with a description, start datetime and end datetime. + +### Delete a task `delete` + +Deletes a specific task. -Description of the feature. +### Find tasks `find` -### Feature-XYZ +Finds all tasks that contain the user input. -Description of the feature. +### Mark task `mark` + +Marks a specific task. + +### Unmark task `unmark` + +Unmarks a specific task. + +### Exit program `bye` + +Exit the program. ## Usage -### `Keyword` - Describe action +### `list` - list + +Lists all tasks are stored. + +Example of usage: +`list` + +Expected outcome: + +``` +Current tasks are: +1.[T][] Read Operating System Book +2.[D][] CS2109S Quiz (by:Feb 17 2023 23:59) +``` +### `todo` - todo TaskDescription + +Adds a todo task. + +Example of usage: +`todo Buy Book` + +Expected outcome: + +``` +Got it, I've added this task: + [T][] Buy Book +Now you have 1 tasks in the list +``` +### `deadline` - deadline TaskDescription /by yyyy-mm-dd HHmm + +Adds a deadline task. + +Example of usage: +`deadline CS2109S Quiz /by 2023-02-17 2359` + +Expected outcome: + +``` +Got it. I've added this task: + [D][] CS2109S Quiz (by:Feb 17 2023 23:59) +Now you have 2 tasks in the list +``` +### `event` - event TaskDescription /from yyyy-mm-dd HHmm /to yyyy-mm-dd HHmm + +Adds an event task. + +Example of usage: +`event Tennis Party /from 2023-02-17 0800 /to 2023-02-18 1800` + +Expected outcome: + +``` +Got it. I've added this task: + [E][] Tennis Party (from:Feb 17 2023 08:00 to:Feb 18 2023 18:00) +Now you have 2 tasks in the list +``` +### `delete` - delete TaskIndex -Describe the action and its outcome. +Deletes a specific task. Example of usage: +`delete 1` + +Expected outcome: -`keyword (optional arguments)` +``` +Noted, I've removed this task: + [T][] Buy Book +Now you have 1 tasks in the list +``` +### `find` - delete TaskDescription + +Finds all tasks that contain task description. + +Example of usage: +`find Book` Expected outcome: -Description of the outcome. +``` +1.[T][] Read Operating System Book +2.[T][] Buy Book +``` +### `mark` - mark TaskIndex + +Marks a specific task. + +Example of usage: +`mark 1` + +Expected outcome: + +``` +Nice! I've marked this task as done: + [T][X] Read Operating System Book +``` +### `unmark` - unmark TaskIndex + +Unmarks a specific task. + +Example of usage: +`unmark 1` + +Expected outcome: ``` -expected output +OK, I've marked this task as not done yet: + [T][] Read Operating System Book ``` +### `bye` - bye + +Exits the program. + +Example of usage: +`bye` + +Expected outcome: + +``` +Bye. Hope to see you again soon! +``` + diff --git a/docs/Ui.png b/docs/Ui.png new file mode 100644 index 0000000000000000000000000000000000000000..f3df40c95bc0cb4f733783f1de4befed5c913bff GIT binary patch literal 75934 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 Platform.exit()); } /** @@ -51,13 +59,9 @@ private void handleUserInput() { DialogBox.getUserDialog(input, userImage), DialogBox.getDukeDialog(response, dukeImage) ); - if (response.equals(duke.getUi().printByeMsg())) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Platform.exit(); + String exitMsg = duke.getUi().printByeMsg(); + if (response.equals(exitMsg)) { + delay.play(); } userInput.clear(); } From 769a11df047f7353de9db5068926103faa06fd07 Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Fri, 17 Feb 2023 21:22:04 +0800 Subject: [PATCH 39/42] Add help command in the user guide --- docs/README.md | 53 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 67dd2648a2..e77bd96dc9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -32,10 +32,14 @@ Finds all tasks that contain the user input. Marks a specific task. -### Unmark task `unmark` +### Unmark task `mark` Unmarks a specific task. +### Explanation of commands `help` + +Displays all commands explanation. + ### Exit program `bye` Exit the program. @@ -151,6 +155,53 @@ Expected outcome: OK, I've marked this task as not done yet: [T][] Read Operating System Book ``` +### `help` - help + +Displays explanations about all commands. + +Example of usage: +`help` + +Expected outcome: + +``` +Available commands: + +-help: show the list of all commands. + e.g. "help" + +-bye: exit the application. + e.g. "bye" + +-list: list all the tasks that are stored. + e.g. "list" + +-todo: add a todo task with a description. + e.g. "todo borrow book" + +-deadline: add a deadline task with description and due date time (after "/by"). + e.g. "deadline watch lecture /by 2019-09-08 1900" + +-event: add an event task with description, start date time (after "/from") + and end date time (after "/to"). + e.g. "event Chinese New Year /from 2023-02-12 0000 /to 2023-02-18 0000" + +-find: find any tasks contains the description, support partially search. + e.g. "find book" "find bo" + +-delete: delete the specific task based on the task number. + e.g. "delete 2" + +-mark: mark the specific task as completed based on the task number. + e.g. "mark 3" + +-unmark: unmark the specific task as not completed based on the taks number. + e.g. "unmark 5" + +Note: 1. all the date time format is "yyyy-mm-dd HHmm". + 2. task number must be within the task list size. + 3. storage file at "./src/data/duke.txt" +``` ### `bye` - bye Exits the program. From b5d8dc40c8e94b07d728f450e161eea2f129925e Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Fri, 17 Feb 2023 22:19:46 +0800 Subject: [PATCH 40/42] Finalize the features --- build.gradle | 2 +- docs/Ui.png | Bin 75934 -> 71538 bytes src/main/java/duke/DialogBox.java | 4 +-- src/main/java/duke/MainWindow.java | 3 +++ src/main/java/storage/TaskList.java | 5 ++-- src/main/java/userinteraction/Ui.java | 34 +++++++++++++++--------- src/main/resources/view/DialogBox.fxml | 7 +++-- src/main/resources/view/MainWindow.fxml | 10 +++---- 8 files changed, 39 insertions(+), 26 deletions(-) diff --git a/build.gradle b/build.gradle index 71f4540aed..eebbc9bcfc 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ test { } application { - mainClassName = "duke.Duke" + mainClassName = "duke.Launcher" } checkstyle { diff --git a/docs/Ui.png b/docs/Ui.png index f3df40c95bc0cb4f733783f1de4befed5c913bff..f06e120669cfbddd3f0c3cf03c3a7cf344c46796 100644 GIT binary patch literal 71538 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 G?|%R$uoc$; literal 75934 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 Platform.exit()); } diff --git a/src/main/java/storage/TaskList.java b/src/main/java/storage/TaskList.java index 41846d1575..9b85c87d7b 100644 --- a/src/main/java/storage/TaskList.java +++ b/src/main/java/storage/TaskList.java @@ -6,7 +6,6 @@ import task.Task; import userinteraction.Ui; - /** * Task list class which stores all tasks. */ @@ -42,7 +41,7 @@ public String listTask(String input) throws DukeException { throw new DukeException("\t OOPS!!! The format is invalid!\n"); } assert inputLine.length == 1; - String str = "\t Current tasks are: \n"; + String str = "Current tasks are: \n"; for (int i = 0; i < tasks.size(); i++) { str += "\t " + (i + 1) + ". " + tasks.get(i).toString() + "\n"; } @@ -144,7 +143,7 @@ public String findTask(String input, Ui ui) throws DukeException { } assert inputLine.length == 2; ui.printFindTaskMsg(); - String str = ""; + String str = "These are available tasks:\n"; for (int i = 0; i < tasks.size(); i++) { if (tasks.get(i).getDescription().contains(inputLine[1])) { str += "\t " + (i + 1) + ". " + tasks.get(i).toString() + "\n"; diff --git a/src/main/java/userinteraction/Ui.java b/src/main/java/userinteraction/Ui.java index 68493157ab..ffedd8c901 100644 --- a/src/main/java/userinteraction/Ui.java +++ b/src/main/java/userinteraction/Ui.java @@ -36,6 +36,16 @@ public String printWelcomeMsg() { return str; } + /** + * Display the help message at start. + * + * @return Returns the get help message. + */ + public String printGetHelpMsg() { + String str = "Input 'help' to see all available commands.\n"; + return str; + } + /** * Display adding task message. * @@ -44,8 +54,8 @@ public String printWelcomeMsg() { * @return The add task message being displayed. */ public String printAddTaskMsg(TaskList taskList, Task task) { - String str = "\t Got it. I've added this task:\n " + "\t\t " - + task.toString() + "\n\t Now you have " + String str = "Got it. I've added this task:\n " + "\t " + + task.toString() + "\nNow you have " + taskList.getSize() + " tasks in the list\n"; return str; } @@ -60,11 +70,11 @@ public String printAddTaskMsg(TaskList taskList, Task task) { public String printMarkTaskMsg(boolean isMarked, Task task) { String str = ""; if (isMarked) { - str = "\t Nice! I've marked this task as done: \n" - + "\t\t " + task.toString() + "\n"; + str = "Nice! I've marked this task as done: \n" + + "\t " + task.toString() + "\n"; } else { - str = "\t OK, I've marked this task as not done yet: \n" - + "\t\t " + task.toString() + "\n"; + str = "OK, I've marked this task as not done yet: \n" + + "\t " + task.toString() + "\n"; } return str; } @@ -77,9 +87,9 @@ public String printMarkTaskMsg(boolean isMarked, Task task) { * @return The delete task message being displayed. */ public String printDeleteTaskMsg(Task task, int size) { - String str = "\t Noted. I've removed this task:\n" + "\t\t " - + task.toString() + "\n\t Now you have " - + size + " tasks in the list.\n"; + String str = "Noted. I've removed this task:\n" + "\t " + + task.toString() + "\nNow you have " + + size + " tasks in the list\n"; return str; } @@ -89,7 +99,7 @@ public String printDeleteTaskMsg(Task task, int size) { * @return The find task message being displayed. */ public String printFindTaskMsg() { - String str = "\t Here are the matching tasks in your list:"; + String str = "Here are the matching tasks in your list:"; return str; } @@ -99,7 +109,7 @@ public String printFindTaskMsg() { * @return The invalid command message being displayed. */ public String printWrongMsg() { - String str = "\t OOPS!!! I'm sorry, but I don't know what that means.\n"; + String str = "OOPS!!! I'm sorry, but I don't know what that means.\n"; return str; } @@ -119,7 +129,7 @@ public String printHelpMsg(Storage storage) { * @return The bye message. */ public String printByeMsg() { - String byeMsg = "\t Bye. Hope to see you again soon!"; + String byeMsg = "Bye. Hope to see you again soon!"; return byeMsg; } } diff --git a/src/main/resources/view/DialogBox.fxml b/src/main/resources/view/DialogBox.fxml index c57607c98a..80927ba52f 100644 --- a/src/main/resources/view/DialogBox.fxml +++ b/src/main/resources/view/DialogBox.fxml @@ -8,10 +8,13 @@ - diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index 8859c558c8..3241877641 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -7,16 +7,16 @@ - + - - - + - + From 8cd75f8bde71d1a3d1569f1cacea2166d9ed4c7d Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Fri, 17 Feb 2023 23:22:26 +0800 Subject: [PATCH 41/42] Fix no match tasks while using find command --- src/main/java/storage/TaskList.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/storage/TaskList.java b/src/main/java/storage/TaskList.java index 9b85c87d7b..3fd7781d83 100644 --- a/src/main/java/storage/TaskList.java +++ b/src/main/java/storage/TaskList.java @@ -142,13 +142,18 @@ public String findTask(String input, Ui ui) throws DukeException { throw new DukeException("\t OOPS!!! The format is invalid, please give a search information.\n"); } assert inputLine.length == 2; - ui.printFindTaskMsg(); - String str = "These are available tasks:\n"; + boolean availableTasks = false; + String str = ui.printFindTaskMsg(); for (int i = 0; i < tasks.size(); i++) { if (tasks.get(i).getDescription().contains(inputLine[1])) { + availableTasks = true; str += "\t " + (i + 1) + ". " + tasks.get(i).toString() + "\n"; } } - return str; + if (availableTasks) { + return str; + } else { + return "There is no matched tasks!"; + } } } From a19d9e3e8043488a1fd1b714eaf7a6094a2f6c7f Mon Sep 17 00:00:00 2001 From: QIU QIANHUI <672271700@qq.com> Date: Fri, 17 Feb 2023 23:51:34 +0800 Subject: [PATCH 42/42] Fix some errors to make it more user friendly --- src/main/java/duke/Duke.java | 3 +-- src/main/java/storage/Storage.java | 13 +++++-------- src/main/java/storage/TaskList.java | 10 +++++++--- src/main/java/userinteraction/Ui.java | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java index 65998b7cae..0b046f2af4 100644 --- a/src/main/java/duke/Duke.java +++ b/src/main/java/duke/Duke.java @@ -12,7 +12,6 @@ */ public class Duke { private static final String FILE_PATH = ".\\src\\data\\duke.txt"; - private static final String HELP_FILEPATH = ".\\src\\main\\resources\\explanation\\help.txt"; private final Ui ui; private final Storage storage; @@ -23,7 +22,7 @@ public class Duke { */ public Duke() { ui = new Ui(); - storage = new Storage(FILE_PATH, HELP_FILEPATH); + storage = new Storage(FILE_PATH); taskList = storage.loadData(); } diff --git a/src/main/java/storage/Storage.java b/src/main/java/storage/Storage.java index 351da57ade..60ea8b620d 100644 --- a/src/main/java/storage/Storage.java +++ b/src/main/java/storage/Storage.java @@ -2,6 +2,7 @@ import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -14,6 +15,7 @@ import task.Task; import task.Todo; + /** * Storage class to deal with the file. */ @@ -21,16 +23,13 @@ public class Storage { private final String filePath; - private final String helpFilePath; - /** * Class constructor. * * @param filePath The path of a file to be stored. */ - public Storage(String filePath, String helpFilePath) { + public Storage(String filePath) { this.filePath = filePath; - this.helpFilePath = helpFilePath; checkFileExit(); } @@ -112,11 +111,10 @@ public void saveData(TaskList tasks) { * @return Returns all available commands. */ public String loadHelpExplanationFile() { - Path file = Paths.get(".", helpFilePath); + InputStream helpStream = this.getClass().getResourceAsStream("/explanation/help.txt"); String explanation = ""; try { - byte[] bs = Files.readAllBytes(file); - explanation = new String(bs); + explanation = new String(helpStream.readAllBytes()); } catch (FileNotFoundException e) { System.out.println("\t File not found.\n"); } catch (IOException e) { @@ -124,5 +122,4 @@ public String loadHelpExplanationFile() { } return explanation; } - } diff --git a/src/main/java/storage/TaskList.java b/src/main/java/storage/TaskList.java index 3fd7781d83..ba58681db0 100644 --- a/src/main/java/storage/TaskList.java +++ b/src/main/java/storage/TaskList.java @@ -45,7 +45,11 @@ public String listTask(String input) throws DukeException { for (int i = 0; i < tasks.size(); i++) { str += "\t " + (i + 1) + ". " + tasks.get(i).toString() + "\n"; } - return str; + if (tasks.size() == 0) { + return "There is no task yet!"; + } else { + return str; + } } /** @@ -135,11 +139,11 @@ public String markTask(boolean isDone, String input, Ui ui, Storage storage) thr */ public String findTask(String input, Ui ui) throws DukeException { if (input.trim().equals("find")) { - throw new DukeException("\t OOPS!!! The description of a find cannot be empty.\n"); + throw new DukeException("OOPS!!! The description of a find cannot be empty.\n"); } String[] inputLine = input.split(" ", 2); if (inputLine.length < 2) { - throw new DukeException("\t OOPS!!! The format is invalid, please give a search information.\n"); + throw new DukeException("OOPS!!! The format is invalid, please give a search information.\n"); } assert inputLine.length == 2; boolean availableTasks = false; diff --git a/src/main/java/userinteraction/Ui.java b/src/main/java/userinteraction/Ui.java index ffedd8c901..6428cba7a1 100644 --- a/src/main/java/userinteraction/Ui.java +++ b/src/main/java/userinteraction/Ui.java @@ -99,7 +99,7 @@ public String printDeleteTaskMsg(Task task, int size) { * @return The find task message being displayed. */ public String printFindTaskMsg() { - String str = "Here are the matching tasks in your list:"; + String str = "Here are the matching tasks in your list:\n"; return str; }