diff --git a/README.md b/ReadMe.md similarity index 100% rename from README.md rename to ReadMe.md diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..da661670 --- /dev/null +++ b/build.gradle @@ -0,0 +1,61 @@ +plugins { + id 'java' + id 'application' + id 'checkstyle' + id 'com.github.johnrengelman.shadow' version '5.1.0' +} + +repositories { + mavenCentral() + jcenter() +} + +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' + // https://mvnrepository.com/artifact/com.sun.mail/javax.mail + testCompile 'junit:junit:4.12' + compile 'junit:junit:4.12' + +} + +test { + useJUnitPlatform() + testLogging { + events "passed", "skipped", "failed" + showExceptions true + exceptionFormat "full" + showCauses true + showStackTraces true + showStandardStreams = false + } +} + +jar{ + manifest { + attributes( + 'Main-Class': 'Dukes.Duke' + ) + } +} + +run { + enableAssertions = true +} + +application { + mainClassName = "Dukes.Duke" +} + +shadowJar { + archiveBaseName = "Duke" + archiveClassifier = null +} + +checkstyle { + toolVersion = '8.23' +} + +run{ + standardInput = System.in +} diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml new file mode 100644 index 00000000..7e1ce222 --- /dev/null +++ b/config/checkstyle/checkstyle.xml @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml new file mode 100644 index 00000000..135ea49e --- /dev/null +++ b/config/checkstyle/suppressions.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/data/duke.txt b/data/duke.txt new file mode 100644 index 00000000..be5d5973 --- /dev/null +++ b/data/duke.txt @@ -0,0 +1,3 @@ +T | 0 | read book +D | 1 | return book | 12 Dec 2019, 06:00 PM +E | 0 | join club | 11 Jan 2020, 09:00 AM diff --git a/docs/Command Summary.PNG b/docs/Command Summary.PNG new file mode 100644 index 00000000..eea01f37 Binary files /dev/null and b/docs/Command Summary.PNG differ diff --git a/docs/README.md b/docs/README.md index fd440695..d55632d4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,20 +1,230 @@ # User Guide +Project Dukes.Duke is a educational software project that helps user to keep track of various things. +
The link is [website for product user guid ](https://linqing42.github.io/ip/) + +## Quick start + +1. Ensure you have Java 11 or above installed in your Computer +1. Download the IntelliJ +1. Set up the correct JDK version as follows: + 1. Click `Configure` > `Structure for New Projects` and then `Project Settings` > `Project` > `Project SDK` + 1. If JDK 11 is listed in the drop down, select it. If it is not, click `New...` and select the directory where you installed JDK 11 + 1. Click `OK` +1. Download the latest project from [here](https://github.com/linqing42/ip). +1. Import the project into Intellij. +1. Go to the sr folder and find src\main\java\Dukes\Dukes.Duke +1. Right click the Dukes.Duke and select Run Dukes.Duke +1. The program now should run on the Console (usually located at the bottom side) +1. Type the command and press Enter to execute it.
+1.Refer to teh [Feature](#features) below for details of each command. ## Features ### Feature 1 -Description of feature. +Adding a task: todo + +## Usage +Adding a task in the task list and show the total number of task in the list. Therefore, the user know the task that he need to do. + +### `todo` - Adding a task into a task list. +
>The keyword 'todo' with description can be **upper and lowercase letters** and its outcome will not include the keyword. +
>If you key in the keyword without description. There will be an error message:"☹ OOPS!!! The description of a todo cannot be empty. " + +**Format**: todo Description + +**Example of usage**: +
TOdo Read BOOK + +**Expected outcome**: +
Got it. I've added this task: +
[T][X] Read BOOK +
Now you have [index number] task in the list. + +### Feature 2 +Adding a deadline task: deadline + +## Usage +Adding a deadline task helps to know the deadline for the specific task in the task list and show the total number of task in the list. + +### `deadline` - Adding a deadline task + +
>The keyword 'deadline' with description can be **upper and lowercase letters**. +
>The outcome will not include the keyword with date and time format: dd MMM yyyy, hh:mm a +
>If you key in the keyword without description. There will be an error message:"OOPS!!! The description of a deadline cannot be empty." +
>If you missing the date and time or /by, there will be an reminder message:"Please specify the deadline date and time." + +**Format**: deadline Description /by dd/mm/yyyy HHmm + +**Example of usage**: +
deadline return book /by 12/12/2019 1800 + +**Expected outcome**: +
Got it. I've added this task: +
[D][X] return book (by:12 Dec 2019, 06:00 PM) +
Now you have [index number] task in the list. + +### Feature 3 +Adding an event task: event ## Usage +Adding an event task helps to remember to join or complete the event with specific date and time in the task list and show the total number of task in the list. + +### `event` - Adding an event task +
>The keyword 'event' with description can be **upper and lowercase letters**. +
>The outcome will not include the keyword with date adn time format: dd MMM yyyy, hh:mm a +
>If you key in the keyword without description. There will be an error message:"☹ OOPS!!! The description of a event cannot be empty." +
>If you missing the date and time or /by, there will be an reminder message:"Please specify the event date and time." + +**Format**: event Description /by dd/mm/yyyy HHmm -### `Keyword` - Describe action +**Example of usage**: +
EVENT join club /at 12/11/2019 0900 + +**Expected outcome**: +
Got it. I've added this task: +
[E][X] join club (at:12 Nov 2019, 09:00 AM) + +### Feature 4 +Marking a specific task: done + +## Usage +Marking a specific task to remind the user that he has finished the task. + +### `done` - Marking a specific task from the task list. +
>The keyword 'done' can be **upper and lowercase letters** +
>The outcome will be change the X to ✓ in the specific task. +
>The index refers to the index number shown in the displayed task list and the index **must be positive integer** 1,2,3... +
>If you key in the keyword without INDEX. There will be an error message:"please key in correct format." + +**Format**: done INDEX + +**Example of usage**: +
step 1: TODO READ BOOK +
step 2: Done 1 or DONE 1 or done 1 + +**Expected outcome**: +
Nice! I've marked this task as done: +
[T][Done] READ BOOK + +### Feature 5 +Deleting a task: delete + +## Usage +Delete a specific task from task list to helps remove the completed task and tidy the task list. It will show the total number of tasks left in the task list. + +### `delete` - Deleting a specific task from the task list. +
>The keyword 'delete' can be **upper and lowercase letters** and its outcome will be remove the specific task and reduce the total number of task in the list. +
>The index refers to the index number shown in the displayed task list and the index **must be a positive integer** 1,2,3... +
>If you key in the keyword without INDEX. There will be an error message:"☹ OOPS!!! There is no specific task to delete." + +**Format**: delete INDEX + +**Example of usage**: +
step 1.TODO READ BOOK +
step 2: done 1 +
steps 3:Delete 1 or DELETE 1 or delete 1 + +**Expected outcome**: +
Noted. I've removed this task: +
[T][✓] READ BOOK +
Now you have [INDEX-1] task in the list. + +### Feature 6 +Listing all tasks: list + +## Usage +It shows a list of all task in the task list with a number. it helps to summarize the task list. + +### `list` - Listing all tasks with number. +
>The keyword 'list' can be **upper and lowercase letters** and its outcome will be show a list of task in the task list +
>If you key in the keyword with empty task.There will be an error message:"OOPS!!! There are no tasks in your list." + +**Format**: list + +**Example of usage**: +
step 1.TODO READ BOOK +
step 2. list or List or LIST + +**Expected outcome**: +
Here are the tasks in your list: +
1.[T][X] READ BOOK + + +### Feature 7 +Locating tasks by description_keyword: find + +## Usage +It helps to search a task that contain any of the given description_keyword, and the search is case-insensitive. e.g book will match BOOK. Therefore, the user can easily find out the specific task base on find function. +### `find` - Locating tasks with given description_keyword +
>The keyword 'find' can be **upper and lowercase letters** and its outcome will be show a list of task in the task list when the task is match the specific description keywords. +
>The order of the description_keyword does not matter. +
>If you key in the specific description keyword that does not match the task in your list.There will be an error message:"☹ OOPS!!! There is no matching tasks in your list." +
>If you only key in the **keyword**, there will be an error message:"OOPS!!! The description of a find cannot be empty." + +**Format**: find description_keyword[more_keyword] + +**Example of usage**: +
step 1.TODO READ BOOK +
step 2. todo join club +
step 3. find book or Find BOok or FIND BOOK + +**Expected outcome**: +
Here are the matching tasks in your list: +
1.[T][X] READ BOOK + +### Feature 8 +Exiting the program: exit/bye + +## Usage +It helps to end the program and display the list of a task will be save in the hard disk. +### `exit/bye` - Exiting the program +
The keyword 'exit/bye' can be **upper and lowercase letters** and its outcome will be show a list of task in the task list that will be save in hard disk and a bye message. + +**Format**: exit +
**Format**: bye + +**Example of usage**: +
step 1.TODO READ BOOK +
step 2. todo join club +
step 3. bye/exit/BYE/EXIT/Bye/Exit + +**Expected outcome**: +
Your following tasks will be save: +
[T][X] READ BOOK +
[T][X] join club +
Bye. Hope to see you again soon! + +### Feature 9 +Saving the task in the hard-disk + +## Usage +It helps to save the tasks in the hard disk automatically after exiting the program, and the format of display will be change when task save in hard disk. It saves the user's time as there is no need to save manually. + +**Example of usage**: +
step 1. todo read book +
step 2. deadline return book /by 12/11/2019 1800 +
step 3. event join club /at 11/2/2020 1300 +
step 4. done 1 +
step 5. bye + +**Expected outcome**: save into /data/duke.txt +
T | 1 | read book +
D | 0 | return book | 12 Nov 2019, 06:00 PM +
E | 0 | join club | 11 Feb 2020, 01:00 PM + +### Feature 10 +Exceptions message + +## Usage +It helps to handle error message that will guid the user. -Describe action and its outcome. +**Example of usage**: +
read book -Example of usage: +**Expected outcome**: +
OOPS!!! I'm sorry, but I don't know what that means :-( -`keyword (optional arguments)` +## Command Summary -Expected outcome: +![image of Command Summary](Command Summary.PNG) -`outcome` diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 00000000..ddeb671b --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-time-machine \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..87b738cb Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..dff5b12d --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat Jan 16 12:30:57 CST 2021 +distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..65356d43 --- /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 seedu.tracker.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 seedu.tracker.command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..f2ff81e3 --- /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' seedu.tracker.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 seedu.tracker.command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the seedu.tracker.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 seedu.tracker.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/settings.gradle b/settings.gradle new file mode 100644 index 00000000..f67afec9 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'Duke' + diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java deleted file mode 100644 index 5d313334..00000000 --- a/src/main/java/Duke.java +++ /dev/null @@ -1,10 +0,0 @@ -public class Duke { - public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - } -} diff --git a/src/main/java/Dukes/Duke.java b/src/main/java/Dukes/Duke.java new file mode 100644 index 00000000..cc9ff9c0 --- /dev/null +++ b/src/main/java/Dukes/Duke.java @@ -0,0 +1,69 @@ +package Dukes; + +import Dukes.Exceptions.DukeException; +import Dukes.Tasks.TaskList; +import Dukes.command.Command; +import Dukes.parser.Parser; +import Dukes.storage.Storage; + + +/** + * The Dukes.Duke program implements an application that can store a list of task,save to a txt file. + * and print the task on the screen. + * it link to other classes which is an member for Dukes.Duke such as Storage, Task and Ui Class + * + * @author LIN QING + * @version 1.0 + * @since 18/1/2021 + */ +public class Duke { + private final Storage storage; + private TaskList tasks; + private final Ui ui; + /** + * @param path program will store the task in this path + */ + public Duke(String path) { + ui = new Ui(); + storage = new Storage(path); + try { + tasks = new TaskList(storage.load()); + } catch ( DukeException e ) { + ui.printLoadingError("Problem reading file. Starting with an empty task list."); + tasks = new TaskList(); + } + } + + /** + * run program implements an application that simply shows the tasks and print on the screen + * DukeException if the command word not in the case. + */ + public void run() { + ui.printWelcome(); + boolean isExit = false; + while (!isExit) { + try { + String fullCommand = ui.readCommand(); + ui.showLine(); + Command c = Parser.parse(fullCommand); + c.execute(tasks, ui, storage); + isExit = c.isExit(); + } catch (DukeException e) { + ui.showError(e.getMessage()); + } finally { + ui.showLine(); + } + } + } + /** + * This is main method which made use of Dukes.Duke and run methods + */ + public static void main(String[] args){ + assert (args.length) > 0; + new Duke("data/duke.txt").run(); + } +} + + + + diff --git a/src/main/java/Dukes/Exceptions/DukeException.java b/src/main/java/Dukes/Exceptions/DukeException.java new file mode 100644 index 00000000..d7484d74 --- /dev/null +++ b/src/main/java/Dukes/Exceptions/DukeException.java @@ -0,0 +1,11 @@ +package Dukes.Exceptions; +/** + * Represents a checked exception. + * A DukeException object corresponds to an exception that is thrown when user inputs are invalid or contain + * the wrong format. + */ +public class DukeException extends Exception { + public DukeException(String message) { + super(message); + } + } \ No newline at end of file diff --git a/src/main/java/Dukes/Exceptions/FileNotFoundException.java b/src/main/java/Dukes/Exceptions/FileNotFoundException.java new file mode 100644 index 00000000..41716894 --- /dev/null +++ b/src/main/java/Dukes/Exceptions/FileNotFoundException.java @@ -0,0 +1,12 @@ +package Dukes.Exceptions; + +/** + * Represents a checked exception. + * A FileNotFoundException object corresponds to an exception that is thrown where file are invalid or + * have some issues. + */ +public class FileNotFoundException extends DukeException { + public FileNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/Dukes/Tasks/Deadline.java b/src/main/java/Dukes/Tasks/Deadline.java new file mode 100644 index 00000000..c599665b --- /dev/null +++ b/src/main/java/Dukes/Tasks/Deadline.java @@ -0,0 +1,27 @@ +package Dukes.Tasks; + +/** + * deadline task description /by specific date and time e.g. return book by 12/12/2019 1800. + * + */ +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 + ")"; + } + + @Override + public String toWriteFile() { + return "D | " + getFileStatusIcon() + " | " + description + " | " + by; + + } +} + diff --git a/src/main/java/Dukes/Tasks/Event.java b/src/main/java/Dukes/Tasks/Event.java new file mode 100644 index 00000000..baa31e57 --- /dev/null +++ b/src/main/java/Dukes/Tasks/Event.java @@ -0,0 +1,23 @@ +package Dukes.Tasks; + +/** + * Represents an event task that start at a specific date and time. eg. event join team /at 12/12/2019 1800. + */ +public class Event extends Task { + protected String at; + + public Event(String description, String at) { + super(description); + this.at = at; + } + + @Override + public String toString() { + return "[E]" + super.toString() + "(at:" + at + ")"; + } + @Override + public String toWriteFile() { + return "E | " + getFileStatusIcon() + " | " + description + " | " + at; + } +} + diff --git a/src/main/java/Dukes/Tasks/Task.java b/src/main/java/Dukes/Tasks/Task.java new file mode 100644 index 00000000..48ab0555 --- /dev/null +++ b/src/main/java/Dukes/Tasks/Task.java @@ -0,0 +1,57 @@ +package Dukes.Tasks; + +/** + * Represents a Task. + * Parent class of all other types of tasks. + * A Task object corresponds to a task to be added to a TaskList. + */ +public abstract class Task { + protected String description; + protected boolean isDone; + /** + * Constructor for Task. + * @param description Description of the task. + */ + public Task(String description) { + this.description = description; + this.isDone = false; + } + /** + * Returns a tick icon if the task is completed and return a X icon if otherwise. + * @return Icon to indicate status of the task. + */ + public String getStatusIcon() { + return (isDone ? "Done" : "X"); + } + public String getFileStatusIcon() { + return (isDone ? "1" : "0"); + } + /** + * Sets the task as done. + */ + public Task markAsDone() { + this.isDone = true; + return this; + } + /** + * Get the description of the task + * + * @return the description of the task + */ + public String getDescription() { + return this.description; + } + + @Override + public String toString() { + return "[" + getStatusIcon() + "] " + description; + } + + public String toWriteFile() { + return "T | " + getFileStatusIcon() + " | " + description; + } + +} + + + diff --git a/src/main/java/Dukes/Tasks/TaskList.java b/src/main/java/Dukes/Tasks/TaskList.java new file mode 100644 index 00000000..9fa2b11d --- /dev/null +++ b/src/main/java/Dukes/Tasks/TaskList.java @@ -0,0 +1,28 @@ +package Dukes.Tasks; + +import java.util.ArrayList; + +/** + * Create a TaskList to store Task objects. + */ +public class TaskList { + protected ArrayList tasks = new ArrayList(100); + public ArrayList list = new ArrayList(); + + + public TaskList() { + + } + + public TaskList(ArrayList load) { + } + + public boolean isEmpty() { + return false; + } + +} + + + + diff --git a/src/main/java/Dukes/Tasks/ToDo.java b/src/main/java/Dukes/Tasks/ToDo.java new file mode 100644 index 00000000..a527391c --- /dev/null +++ b/src/main/java/Dukes/Tasks/ToDo.java @@ -0,0 +1,25 @@ +package Dukes.Tasks; + +/** + * Represents a todo task. + * An ToDoobject corresponds to a type of Task object with a task to be completed. + */ +public class ToDo extends Task { + + public ToDo(String description) { + super(description); + } + + @Override + public String toString() { + return "[T]" + super.toString(); + } + + @Override + public String toWriteFile() { + return "T | " + getFileStatusIcon() + " | " + description; + } + + + +} diff --git a/src/main/java/Dukes/Ui.java b/src/main/java/Dukes/Ui.java new file mode 100644 index 00000000..c961c36e --- /dev/null +++ b/src/main/java/Dukes/Ui.java @@ -0,0 +1,95 @@ +package Dukes; + +import Dukes.Tasks.Task; +import Dukes.Tasks.TaskList; + +import java.util.ArrayList; +import java.util.Scanner; + +/** + * Create a UI class to manage user interface for users and handles interaction between the user + */ +public class Ui { + private Scanner in = new Scanner(System.in); + /** + * Reads user input. + * @return User input. + */ + public String readCommand() { + return in.nextLine(); + } + + public Ui() { + } + + public void showLine() { + System.out.println("____________________________________________________________\n"); + } + + public void showError(String message) { + System.out.println(message); + } + /** + * Prints the Dukes.Duke logo and greets the user for the first time the program is run. + */ + public void printWelcome() { + String logo = " ____ _ \n" + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; + System.out.println("Hello from\n" + logo); + System.out.println("Hello! I'm Dukes\nWhat can I do for you?\n"); + + } + /** + * Prints the bye message and the list that will be save in hard disk when the user exits the program. + */ + public void showExitMessage(ArrayList tasks) { + + System.out.println("Your following tasks will be save: "); + for (Task t : tasks) { + System.out.println(t); + } + System.out.println("Bye. Hope to see you again soon!"); + } + /** + * Prints the error when the information in storage could not be loaded. + */ + public void printLoadingError(String s) { + System.out.println(s); + } + + + public static int indexDetails(String input) { + int number = Integer.parseInt(input.substring(input.indexOf(' ') + 1)) - 1; + return number; + } + /** + * Prints the message to inform user of a successful addition of a task to the list. + * @param task Task that has been added. + * @param numberOfTasks Number of tasks currently in the list. + */ + public void printAddedMessage(Task task, int numberOfTasks) { + System.out.println("Got it. I've added this task: \n" + task); + System.out.println("Now you have " + numberOfTasks + (numberOfTasks == 1 ? " task" : " tasks") + " in the list."); + } /** + * Prints the message to inform user of a successful deletion. + * @param task Task that has been deleted. + * @param numberOfTasks Number of tasks left in the list. + */ + public void printDeleteMessage(Task task, int numberOfTasks) { + System.out.println("Noted. I've removed this task: \n" + task); + System.out.println("Now you have " + numberOfTasks + (numberOfTasks == 1 ? " task" : " tasks") + " in the list."); + } + /** + * Prints the message to inform user that a task has been successfully marked as done. + * @param task Task that has been marked as done. + */ + public void printDoneMessage(Task task) { + System.out.println("Nice! I've marked this task as done:\n" + + task); + } + +} + diff --git a/src/main/java/Dukes/command/AddCommand.java b/src/main/java/Dukes/command/AddCommand.java new file mode 100644 index 00000000..bb6e131b --- /dev/null +++ b/src/main/java/Dukes/command/AddCommand.java @@ -0,0 +1,26 @@ +package Dukes.command; + +import Dukes.storage.Storage; +import Dukes.Tasks.Task; +import Dukes.Tasks.TaskList; +import Dukes.Ui; +/** + * Create an AddCommand. It will add a Deadline, Event, todo task to the user list and save it. + */ +public class AddCommand extends Command { + public AddCommand(Task task) { + super.task = task; + } + + /** + * Adds a Deadline/ Event/ Todo task to the task list and save the list to disk and display to user + * @param tasks TaskList to be appended. + * @param ui UI to interact with user. + * @param storage Storage to read and write files,temporary save and store in hard disk. + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) { + tasks.list.add(task); + ui.printAddedMessage(task, tasks.list.size()); + } +} diff --git a/src/main/java/Dukes/command/Command.java b/src/main/java/Dukes/command/Command.java new file mode 100644 index 00000000..399b792d --- /dev/null +++ b/src/main/java/Dukes/command/Command.java @@ -0,0 +1,29 @@ +package Dukes.command; + +import Dukes.storage.Storage; +import Dukes.Tasks.Task; +import Dukes.Tasks.TaskList; +import Dukes.Ui; +import Dukes.Exceptions.DukeException; +/** + * Represents a command. + * Parent class of all other types of commands to perform some action. + */ +public abstract class Command { + + protected Task task; + protected int index; + protected String keyWord; + + + public abstract void execute(TaskList tasks, Ui ui, Storage storage) throws DukeException; + + /** + * Checks if this object is an ExitCommand. + * @return Whether this command is an exit command. + */ + public boolean isExit() { + return false; + } + +} diff --git a/src/main/java/Dukes/command/DeleteCommand.java b/src/main/java/Dukes/command/DeleteCommand.java new file mode 100644 index 00000000..05abcc0a --- /dev/null +++ b/src/main/java/Dukes/command/DeleteCommand.java @@ -0,0 +1,33 @@ +package Dukes.command; + +import Dukes.storage.Storage; +import Dukes.Tasks.TaskList; +import Dukes.Tasks.Task; +import Dukes.Ui; +import Dukes.Exceptions.DukeException; +/** + * Create a DeleteCommand. It removes user's task from the list. + */ +public class DeleteCommand extends Command { + public DeleteCommand(int index) { + super.index = index; + } + + /** + * Adds a delete task from list with a specific index if index is valid, save the task to user's list. + * + * @param tasks TaskList to be appended. + * @param ui UI to interact with user. + * @param storage Storage to read and write files and temporary store in hard disk. + * @throws DukeException If user key in a number that is not in the TaskList. + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) throws DukeException { + try { + Task deletedTask = tasks.list.remove(index); + ui.printDeleteMessage(deletedTask, tasks.list.size()); + } catch (IndexOutOfBoundsException e) { + throw new DukeException("Please key in a number from the list"); + } + } +} diff --git a/src/main/java/Dukes/command/DoneCommand.java b/src/main/java/Dukes/command/DoneCommand.java new file mode 100644 index 00000000..cd8faffa --- /dev/null +++ b/src/main/java/Dukes/command/DoneCommand.java @@ -0,0 +1,39 @@ +package Dukes.command; + +import Dukes.storage.Storage; +import Dukes.Tasks.TaskList; +import Dukes.Tasks.Task; +import Dukes.Ui; +import Dukes.Exceptions.DukeException; + +/** + * Represents a done command. + * A DoneCommand object corresponds to a command to mark a TaskList object + * in a TaskList as done. + */ +public class DoneCommand extends Command { + /** + * Constructor for DoneCommand. + * @param index Index of object that is to be marked as done in a TaskList object. + */ + public DoneCommand(int index) { + super.index = index; + } + /** + * Mark a task in the task list as done if specified index is valid, save the task list and display to user + * + * @param tasks TaskList to be appended. + * @param ui UI to interact with user. + * @param storage Storage to read and write files and temporary store in hard disk. + * @throws DukeException If user key in a number that is not in the TaskList. + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) throws DukeException { + try { + Task doneTask = tasks.list.get(index).markAsDone(); + ui.printDoneMessage(doneTask); + } catch (IndexOutOfBoundsException e) { + throw new DukeException("Please key in a number from the list"); + } + } +} diff --git a/src/main/java/Dukes/command/ExitCommand.java b/src/main/java/Dukes/command/ExitCommand.java new file mode 100644 index 00000000..3b6c107a --- /dev/null +++ b/src/main/java/Dukes/command/ExitCommand.java @@ -0,0 +1,29 @@ +package Dukes.command; + +import Dukes.storage.Storage; +import Dukes.Tasks.TaskList; +import Dukes.Ui; +/** + * Create an ExitCommand. It ends and exit the programme and stores user's tasks. + */ +public class ExitCommand extends Command { + /** + * Saves the tasks into storage and display bye message to the user. + * @param tasks TaskList to be appended. + * @param ui UI to interact with user. + * @param storage Storage to read and write files and temporary store in hard disk. + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) { + ui.showExitMessage(tasks.list); + storage.saveTaskFile(tasks.list); + } + /** + * Checks if this object is an ExitCommand. + * @return Whether this command is an exit command. + */ + public boolean isExit() { + return true; + } + +} diff --git a/src/main/java/Dukes/command/FindCommand.java b/src/main/java/Dukes/command/FindCommand.java new file mode 100644 index 00000000..0851ec4a --- /dev/null +++ b/src/main/java/Dukes/command/FindCommand.java @@ -0,0 +1,52 @@ +package Dukes.command; + +import Dukes.Exceptions.DukeException; +import Dukes.storage.Storage; +import Dukes.Tasks.Task; +import Dukes.Tasks.TaskList; +import Dukes.Ui; + + +/** + * Creates a FindCommand. It search for tasks when given keyword. + */ +public class FindCommand extends Command { + public FindCommand(String keyWord) { + this.keyWord = keyWord; + } + + /** + * Finds the tasks with the given keyword. + * + * @param tasks TaskList to be appended. + * @param ui UI to interact with user. + * @param storage Storage to read and write files. + */ + + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) throws DukeException { + TaskList filteredTasks = new TaskList(); + int count = 0; + try { + for (Task task : tasks.list) { + String description = task.getDescription().toLowerCase(); + if (description.contains(keyWord)) { + filteredTasks.list.add(task); + count += 1; + } + } + if (count == 0) { + throw new DukeException("OOPS!!! There is no matching task in the list"); + } else { + System.out.println("Here are the matching tasks in your list:"); + for (int i = 0; i < filteredTasks.list.size(); i++) { + System.out.println((i + 1) + "." + filteredTasks.list.get(i)); + } + } + }catch (IndexOutOfBoundsException e) { + System.out.print("Current task is empty in your list."); + } + } + } + + diff --git a/src/main/java/Dukes/command/ListCommand.java b/src/main/java/Dukes/command/ListCommand.java new file mode 100644 index 00000000..db33433f --- /dev/null +++ b/src/main/java/Dukes/command/ListCommand.java @@ -0,0 +1,39 @@ +package Dukes.command; + +import Dukes.storage.Storage; +import Dukes.Tasks.TaskList; +import Dukes.Ui; +/** + * Create a ListCommand. It lists all tasks for users. + */ +public class ListCommand extends Command { + /** + * Constructor for ListCommand. + */ + public ListCommand() { + super(); + } + /** + * List all the tasks in the task list that was saved on the disk, and display to user + * @param tasks TaskList to be appended. + * @param ui UI to interact with user. + * @param storage Storage to read and write files and temporary store in hard disk. + * @throws IndexOutOfBoundsException if there is empty list. + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) { + try { + int count =tasks.list.size(); + if(count ==0) { + System.out.println("OOPS!!! There are no tasks in your list."); + }else{ + System.out.println(" Here are the tasks in your list:"); + for (int i = 0; i < tasks.list.size(); i++) { + System.out.println(" " + (i + 1) + "." + tasks.list.get(i)); + } + } + } catch (IndexOutOfBoundsException e) { + System.out.print("current task is empty in your list."); + } + } +} diff --git a/src/main/java/Dukes/parser/Parser.java b/src/main/java/Dukes/parser/Parser.java new file mode 100644 index 00000000..8eb6bcf6 --- /dev/null +++ b/src/main/java/Dukes/parser/Parser.java @@ -0,0 +1,123 @@ +package Dukes.parser; + +import Dukes.Exceptions.DukeException; +import Dukes.Tasks.Deadline; +import Dukes.Tasks.Event; +import Dukes.Tasks.Task; +import Dukes.Tasks.ToDo; +import Dukes.Ui; +import Dukes.command.*; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Parser program containing methods that deals with parsing the user command to extract meaningful details from it. + */ +public class Parser { + /** + * Processes the user input and creates the corresponding commands. + * + * @param input Command input by user. + * @return Corresponding command that is input by user. + * @throws DukeExceptionIf a new command cannot be created due to invalid input parameters. + */ + + public static Command parse(String input) throws DukeException { + Task taskWord; + String keyword; + Command c = null; + String action = input.split(" ")[0].toLowerCase(); + SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy HHmm"); + SimpleDateFormat formatter = new SimpleDateFormat("dd MMM yyyy, hh:mm a"); + switch (action) { + case "list": + c = new ListCommand(); + break; + + case "todo": + if (input.length() < 6) { + throw new DukeException("OOPS!!! The description of a todo cannot be empty."); + } + taskWord = new ToDo(input.substring(5)); + c = new AddCommand(taskWord); + break; + + case "delete": + if (input.isEmpty() || input.length() < 7) { + throw new DukeException("OOPS!!! There is no specific task to delete.\n"); + } + int toDelete = Ui.indexDetails(input); + c = new DeleteCommand(toDelete); + break; + + case "done": + if (input.length() < 6) { + throw new DukeException("please key in correct format.\n"); + } + int toEdit = Ui.indexDetails(input); + c = new DoneCommand(toEdit); + break; + + case "deadline": + if (input.length() < 10) { + throw new DukeException("OOPS!!! The description of a deadline cannot be empty.\n"); + } + String[] splitDetail = input.split("/by"); + if (splitDetail.length < 2) { + throw new DukeException("Please specify the deadline date and time.\n"); + } + String task = splitDetail[0].substring(9); + String by = splitDetail[1]; + try { + Date byDeadline = format.parse(by); + taskWord = new Deadline(task, formatter.format(byDeadline)); + }catch (Exception e){ + throw new DukeException("Please input a date in this format : dd/MM/yyyy HHmm"); + } + c = new AddCommand(taskWord); + break; + + case "event": + if (input.length() < 7) { + throw new DukeException("OOPS!!! The description of a event cannot be empty.\n"); + } + String[] splitEvent = input.split("/at"); + if (splitEvent.length < 2) { + throw new DukeException("Please specify the event date and time\n"); + } + String event = splitEvent[0].substring(6); + String time = splitEvent[1]; + try { + Date timeEvent = format.parse(time); + taskWord = new Event(event, formatter.format(timeEvent)); + }catch(Exception e){ + throw new DukeException("Please input a date in this format : dd/MM/yyyy HHmm"); + } + c = new AddCommand(taskWord); + break; + case "find": + if (input.length() < 6) { + throw new DukeException("OOPS!!! The description of a find cannot be empty.\n"); + } + try { + keyword = input.substring(5).toLowerCase(); + c = new FindCommand(keyword); + break; + } catch (NumberFormatException e) { + throw new DukeException("please key in correct format."); + } + + case "bye": + case "exit": + c = new ExitCommand(); + break; + + default: + throw new DukeException("OOPS!!! I'm sorry, but I don't know what that means :-("); + } + return c; + } + +} + diff --git a/src/main/java/Dukes/storage/Storage.java b/src/main/java/Dukes/storage/Storage.java new file mode 100644 index 00000000..f042da0f --- /dev/null +++ b/src/main/java/Dukes/storage/Storage.java @@ -0,0 +1,73 @@ +package Dukes.storage; + +import Dukes.Tasks.Deadline; +import Dukes.Tasks.Event; +import Dukes.Tasks.Task; +import Dukes.Tasks.ToDo; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Scanner; + +/** + * Represents a storage in the hard disk. + */ +public class Storage { + private ArrayList details = new ArrayList<>(); + public static String path = "data/duke.txt"; + + public Storage(String path) { + this.path = path; + } + + public ArrayList load() throws Dukes.Exceptions.FileNotFoundException { + try { + File file = new File(path); + file.createNewFile(); + Scanner in = new Scanner(file); + while (in.hasNext()) { + String input = in.nextLine(); + String[] strArr = input.split(" \\| "); + Task tasks = null; + if (strArr[0].equals("T")) { + tasks = new ToDo(strArr[2]); + } else if (strArr[0].equals("D")) { + tasks = new Deadline(strArr[2], strArr[3]); + } else if (strArr[0].equals("E")) { + tasks = new Event(strArr[2], strArr[3]); + } else { + throw new Dukes.Exceptions.FileNotFoundException("Previous Tasks are corrupted. Please resetting your task . ."); + } + if (strArr[1].equals("1")) { + tasks.markAsDone(); + } + details.add(input); + } + } catch (FileNotFoundException e) { + System.out.println("You have no task."); + } catch (IOException e) { + System.out.println("Problem occurred while creating a new file in Storage"); + assert (false); + } + return details; + } + + + public void saveTaskFile(ArrayList task) { + try { + FileWriter fw = new FileWriter("data/duke.txt"); + String fileDetails = ""; + for (Task t : task) { + fileDetails += t.toWriteFile() + "\n"; + } + fw.write(fileDetails); + fw.close(); + } catch (IOException e) { + System.out.println("FileWriting got problem"); + } + } +} + diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 00000000..3b0baec5 --- /dev/null +++ b/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: Dukes.Duke + diff --git a/src/test/Dukes/DukesTest.java b/src/test/Dukes/DukesTest.java new file mode 100644 index 00000000..064aff05 --- /dev/null +++ b/src/test/Dukes/DukesTest.java @@ -0,0 +1,12 @@ +package Dukes; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DukeTest { + @Test + public void dummyTest() { + assertEquals(2, 2); + } +} diff --git a/src/test/Dukes/ParsersTest.java b/src/test/Dukes/ParsersTest.java new file mode 100644 index 00000000..9d830143 --- /dev/null +++ b/src/test/Dukes/ParsersTest.java @@ -0,0 +1,33 @@ +package Dukes; + + +import Dukes.parser.Parser; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class ParserTest { + @Test + public void parseExit() { + Parser exit = new Parser(); + Command command; + try { + command = Parser.parse("exit"); + assertTrue(command instanceof ExitCommand); + } catch (Exception e) { + fail("Should not shown thrown Exception."); + } + } + @Test + public void parseBye() { + Parser bye = new Parser(); + Command command; + try { + command = Parser.parse("bye"); + assertTrue(command instanceof ExitCommand); + } catch (Exception e) { + fail("Should not shown thrown Exception."); + } + } + +} diff --git a/src/test/Dukes/ToDoTest.java b/src/test/Dukes/ToDoTest.java new file mode 100644 index 00000000..1e4073df --- /dev/null +++ b/src/test/Dukes/ToDoTest.java @@ -0,0 +1,17 @@ +package Dukes; + +import Dukes.Tasks.ToDo; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ToDoTest { + @Test + public void ToDoTest() { + ToDo todo = new ToDo("return book"); + assertEquals("[T][X] return book", todo.toString()); + assertEquals("T | 0 | return book", todo.toWriteFile()); + } + +} + diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 657e74f6..276f6e09 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -5,3 +5,31 @@ Hello from | |_| | |_| | < __/ |____/ \__,_|_|\_\___| +Hello! I'm Dukes.Duke +What can I do for you? + +Got it, I've added the following task: + [T][?] borrow book +Now you have 1 tasks in the list. +___________________________________________________________________ + +Got it. I've added this task: + [D][?] deadline return book (by: Sunday) +Now you have 2 tasks in the list. +___________________________________________________________________ + +Got it. I've added this task: + [E][?] event project meeting (at: Mon 2-4pm) +Now you have 3 tasks in the list. +___________________________________________________________________ + + Nice! I've marked this task as done: +[D][?] deadline return book (by: Sunday) +___________________________________________________________________ + + ___________________________________________________________________ + Here are the tasks in your list: + 1.[T][?] borrow book + 2.[D][?] deadline return book (by: Sunday) + 3.[E][?] event project meeting (at: Mon 2-4pm) + Bye. Hope to see you again soon! diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e69de29b..49a12133 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -0,0 +1,6 @@ +todo borrow book +deadline return book /by Sunday +event project meeting /at Mon 2-4pm +done 2 +list +bye \ No newline at end of file diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index d0facc63..346bd533 100644 --- a/text-ui-test/runtest.bat +++ b/text-ui-test/runtest.bat @@ -7,11 +7,13 @@ REM delete output from previous run del ACTUAL.TXT REM compile the code into the bin folder -javac -cp ..\src -Xlint:none -d ..\bin ..\src\main\java\Duke.java +javac -cp ..\src\main\java\Dukes -Xlint:none -d ..\bin ..\src\main\java\Dukes\Duke.java + IF ERRORLEVEL 1 ( echo ********** BUILD FAILURE ********** exit /b 1 ) + REM no error here, errorlevel == 0 REM run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh deleted file mode 100644 index e169618a..00000000 --- a/text-ui-test/runtest.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -# create bin directory if it doesn't exist -if [ ! -d "../bin" ] -then - mkdir ../bin -fi - -# delete output from previous run -if [ -e "./ACTUAL.TXT" ] -then - rm ACTUAL.TXT -fi - -# compile the code into the bin folder, terminates if error occurred -if ! javac -cp ../src -Xlint:none -d ../bin ../src/main/java/Duke.java -then - echo "********** BUILD FAILURE **********" - exit 1 -fi - -# run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT -java -classpath ../bin Duke < input.txt > ACTUAL.TXT - -# convert to UNIX format -cp EXPECTED.TXT EXPECTED-UNIX.TXT -dos2unix ACTUAL.TXT EXPECTED-UNIX.TXT - -# compare the output to the expected output -diff ACTUAL.TXT EXPECTED-UNIX.TXT -if [ $? -eq 0 ] -then - echo "Test result: PASSED" - exit 0 -else - echo "Test result: FAILED" - exit 1 -fi \ No newline at end of file