diff --git a/README.md b/README.md index 84755485a7..5dc79b47cb 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,11 @@ # Tutorials -Duke Increment | Tutorial +duke.Duke Increment | Tutorial ---------------|--------------- `A-Gradle` | [Gradle Tutorial](tutorials/gradleTutorial.md) `A-TextUiTesting` | [Text UI Testing Tutorial](tutorials/textUiTestingTutorial.md) -`Level-10` | JavaFX tutorials:
→ [Part 1: Introduction to JavaFX][fx1]
→ [Part 2: Creating a GUI for Duke][fx2]
→ [Part 3: Interacting with the user][fx3]
→ [Part 4: Introduction to FXML][fx4] +`Level-10` | JavaFX tutorials:
→ [Part 1: Introduction to JavaFX][fx1]
→ [Part 2: Creating a GUI for duke.Duke][fx2]
→ [Part 3: Interacting with the user][fx3]
→ [Part 4: Introduction to FXML][fx4] [fx1]: [fx2]: diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000000..c4192631f2 --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000..a924fdab92 --- /dev/null +++ b/build.gradle @@ -0,0 +1,41 @@ +plugins { + id 'java' + id 'application' + id 'checkstyle' + id 'com.github.johnrengelman.shadow' version '5.1.0' +} + +group 'duke' +version '0.1.0' + +repositories { + mavenCentral() +} + +application { + // Change this to your main class. + mainClassName = "duke.Duke" +} + +run { + standardInput = System.in +} + +checkstyle { + toolVersion = '8.23' +} + +shadowJar { + archiveBaseName = "duke" + archiveVersion = "0.1.3" + archiveClassifier = null + archiveAppendix = null +} + +dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter:5.5.0' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml new file mode 100644 index 0000000000..b1a57ba6c0 --- /dev/null +++ b/config/checkstyle/checkstyle.xml @@ -0,0 +1,257 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/duke.txt b/data/duke.txt new file mode 100644 index 0000000000..3650a1a14f --- /dev/null +++ b/data/duke.txt @@ -0,0 +1,4 @@ +T | 1 | read book +D | 0 | return book | June 6th +E | 1 | project meeting | Aug 6th 2-4pm +T | 1 | join sports club diff --git a/docs/README.md b/docs/README.md index fd44069597..3ac3988052 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,20 +1,111 @@ -# User Guide +# Duke - User Guide +By: `WANG JINGTAN` Since: `Jan 2020` +* [Introduction](#1-introduction) +* [Quick Start](#2-quick-start) +* [Features](#3-features) + * [Viewing help](#31-viewing-help--help) + * [Adding tasks](#32-adding-tasks) + * [Checking data](#33-checking-date-check) + * [Finding a task](#34-finding-a-task-find) + * [Having done a task](#35-having-done-a-task-done) + * [Deleting a task](#36-deleting-a-task-delete) + * [Listing all tasks](#37-listing-all-tasks-list) + * [Exiting duke](#38-exiting-duke-bye) + * [Saving the tasks](#39-saving-the-tasks) +* [FAQ](#4-faq) +* [Command Summary](#5-command-summary) -## Features +## 1. Introduction +Duke is for those who wants to **record daily life tasks on desktop**. +It is a Personal Assistant Chatbot that helps a person to keep track of various things. +As a **Command Line Interface (CLI) application**, it is suitable for those who type fast. -### Feature 1 +## 2. Quick Start +1. Ensure you have JAVA '11' or above installed in your Computer. +2. Download the latest duke.jar [here](https://github.com/JTWang2000/duke). +3. Copy the file to an empty folder where you want to use as the home folder for your Duke. +4. Open a command window in that folder. +5. Run the command `java -jar duke.jar`. The CLI should appear in a few seconds. +![Enter page](enter.png) +6. Some example commands you can try: + * `help` : shows all the command you can try + * `todo clean the house`: add `clean the house` to duke + * `bye` : exit the app +7. Refer to [Section 3. Features](#3-features) for details of each command. Description of feature. -## Usage +## 3. Features +### 3.1 Viewing help : `help` +Format: `help` -### `Keyword` - Describe action +### 3.2 Adding tasks: +All the tasks are not done when they are first created. +##### 3.2.1 Adding to do: `todo` +Adds a task that needs to be done

+Format: `todo TASK`

+Examples: +* `todo Clean the house` +* `todo laundry` +##### 3.2.3 Adding deadline: `deadline` +Adds a task that has deadline

+Format: `deadline TASK /by TIME`

+*The `TIME` is suggested to follow format:`yyyy-mm-dd`*

+Examples: +* `deadline assignment /by 2020-03-01` +* `deadline coding exercise /by tomorrow midnight` +##### 3.2.3 Adding event : `event` +Adds a task that happens on a specific day

+Format: `event TASK /at TIME`

+*The `TIME` is suggested to follow format:`yyyy-mm-dd`*

+Examples: +* `event read book /at 2020-03-06` +* `event group meeting /at 6pm` -Describe action and its outcome. +### 3.3 Checking date: `check` +Checks deadline/event occurs on that day

+Format: `check yyyy-mm-dd`

+Example: `check 2020-03-01` -Example of usage: +### 3.4 Finding a task: `find` +Finds a task by its keyword in the task description

+Format: `find KEYWORD`

+Example: `find book` -`keyword (optional arguments)` +### 3.5 Having done a task: `done` +Marks a task as done.

+Format: `done INDEX`

+*INDEX is a number starts from 1* -Expected outcome: +### 3.6 Deleting a task: `delete` +Deletes a task.

+Format: `delete INDEX`

+*INDEX is a number starts from 1* + +### 3.7 Listing all tasks: `list` +Lists all the tasks.

+Format: `list` + +### 3.8 Exiting duke: `bye` +Exits the app.

+Format: `bye` + +### 3.9 Saving the tasks +Tasks in duke are saved in the hard disk automatically. You can find all the existing tasks in the data folder in the Duke folder. + +## 4. FAQ +**Q**: How do I transfer my data to another Computer?

+**A**: Install the app in the other computer and copy the data folder in previous Duke folder to the new Duke Folder. + +**Q**: What if I accidentally input something wrong?

+**A**: Duke can handle such error. No worry. + +## 5. Command Summary +* **Help** `help` +* **Add**

`todo TASK`

`deadline TASK /by yyyy-mm-dd`

`event TASK /at yyyy-mm-dd` +* **Check** `check yyyy-mm-dd` +* **Find** `find KEYWORD` +* **Done** `done INDEX` +* **Delete** `delete INDEX` +* **List** `list` +* **Exit** `bye` -`outcome` diff --git a/docs/enter.png b/docs/enter.png new file mode 100644 index 0000000000..beb96e7727 Binary files /dev/null and b/docs/enter.png differ diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..87b738cbd0 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..aaa8f5cb02 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Feb 17 10:19:33 SGT 2020 +distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.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 100755 index 0000000000..af6708ff22 --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## 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"' + +# 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, switch paths to Windows format before running java +if $cygwin ; 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=$((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" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000000..6d57edc706 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@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 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" + +@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/settings.gradle b/settings.gradle new file mode 100644 index 0000000000..d1e92fe5db --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'duke' diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java deleted file mode 100644 index 5d313334cc..0000000000 --- a/src/main/java/Duke.java +++ /dev/null @@ -1,10 +0,0 @@ -public class Duke { - public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - } -} diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java new file mode 100644 index 0000000000..0624539112 --- /dev/null +++ b/src/main/java/duke/Duke.java @@ -0,0 +1,74 @@ +package duke; + +import duke.command.Command; +import duke.common.DukeException; +import duke.parser.Parser; +import duke.storage.Storage; +import duke.tasklist.TaskList; +import duke.ui.Ui; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; + +import static duke.common.Constants.CREATE_FILE_PATH; +import static duke.common.Constants.FILE_PATH; + +public class Duke { + + private Storage storage; + private TaskList tasks; + private Ui ui; + + /** + * Initializes Duke object. + * + * @param filePath Place where hard disk data stores + */ + public Duke(String filePath) { + ui = new Ui(); + tasks = new TaskList(); + storage = new Storage(filePath); + try { + storage.load(tasks); + } catch (FileNotFoundException e) { + ui.showLoadingError(); + File newFolder = new File(CREATE_FILE_PATH); + newFolder.mkdirs(); + try { + File f = new File(FILE_PATH); + f.createNewFile(); + } catch (IOException error) { + System.out.println("\tUnknown errors: " + error.getMessage()); + } + } + } + + /** + * Runs the Duke object. + */ + public void run() { + ui.showWelcome(); + boolean isExit = false; + while (!isExit) { + try { + String fullCommand = ui.readCommand(); + ui.showLine(); // show the divider line ("_______") + Command c = Parser.parse(fullCommand); + c.execute(tasks, ui, storage); + isExit = c.isExit(); + } catch (DukeException e) { + ui.showError(e.getMessage()); + } catch (IOException e) { + ui.showError(e.getMessage()); + } finally { + ui.showLine(); + } + } + } + + public static void main(String[] args) { + new Duke(FILE_PATH).run(); + } +} + diff --git a/src/main/java/duke/command/AddCommand.java b/src/main/java/duke/command/AddCommand.java new file mode 100644 index 0000000000..8734d7eea3 --- /dev/null +++ b/src/main/java/duke/command/AddCommand.java @@ -0,0 +1,34 @@ +package duke.command; + +import duke.tasklist.TaskList; +import duke.storage.Storage; +import duke.tasklist.task.Task; +import duke.ui.Ui; + +import java.io.IOException; + +/** + * Deals with commands related to adding tasks. + */ +public class AddCommand extends Command { + private Task newtask; + + public AddCommand(Task newtask) { + this.newtask = newtask; + } + + /** + * Adds a new task in taskList, updates ui and backup file. + * + * @param tasks Stores all tasks. + * @param ui Deals with user interface. + * @param storage Deals with back up file. + * @throws IOException If cannot find back up file in the hard disk. + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) throws IOException { + tasks.addTask(newtask); + ui.showAddTaskMessage(tasks); + storage.write(tasks); + } +} diff --git a/src/main/java/duke/command/CheckCommand.java b/src/main/java/duke/command/CheckCommand.java new file mode 100644 index 0000000000..bae68ee016 --- /dev/null +++ b/src/main/java/duke/command/CheckCommand.java @@ -0,0 +1,67 @@ +package duke.command; + +import duke.common.DukeException; +import duke.storage.Storage; +import duke.tasklist.TaskList; +import duke.ui.Ui; + +import java.io.IOException; +import java.time.LocalDate; +import java.time.format.DateTimeParseException; +import java.util.ArrayList; + +/** + * Deals with command that can check deadline/event by time. + */ +public class CheckCommand extends Command { + + /** User input time.*/ + private static String checkString; + /** Stores the task index that matches.*/ + private static ArrayList checkCount; + + public CheckCommand(String checkString) { + this.checkString = checkString; + checkCount = new ArrayList<>(); + } + + /** + * Checks if a string follows an identified time format. + * + * @return True if it follows, false if it does not follow. + */ + private Boolean isLocalDateFormat() { + try { + LocalDate.parse(this.checkString); + } catch (DateTimeParseException e) { + return false; + } + return true; + } + + /** + * Checks tasks occuring on a specific date. + * + * @param tasks Stores all tasks. + * @param ui Deals with user interface. + * @param storage Deals with back up file. + * @throws DukeException If the format of time is not correct. + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) throws DukeException { + if (!isLocalDateFormat()) { + throw new DukeException("\t Please follow the format: check yyyy-mm-dd"); + } + LocalDate date = LocalDate.parse(checkString); + for (int i = 0; i < tasks.size(); i++) { + if ((tasks.getATask(i).getTime() == null)) { + /** either it is a todo event or the time does not follow standard */ + continue; + } + if (tasks.getATask(i).getTime().equals(date)) { + checkCount.add(i); + } + } + ui.showFindTask(tasks,checkCount); + } +} diff --git a/src/main/java/duke/command/Command.java b/src/main/java/duke/command/Command.java new file mode 100644 index 0000000000..618d48c4b4 --- /dev/null +++ b/src/main/java/duke/command/Command.java @@ -0,0 +1,33 @@ +package duke.command; + +import duke.common.DukeException; +import duke.tasklist.TaskList; +import duke.storage.Storage; +import duke.ui.Ui; + +import java.io.IOException; + +/** + * Deals with user Command. + * Abstract class since there can not be general command. + */ +public abstract class Command { + public Command(){ + } + + /** + * Deals with iteration between tasks, ui and storage. + * + * @param tasks Stores all tasks. + * @param ui Deals with user interface. + * @param storage Deals with back up file. + * @throws IOException If cannot find back up file in the hard disk. + * @throws DukeException Deals with other exception. + */ + public abstract void execute(TaskList tasks, Ui ui, Storage storage) throws IOException, DukeException; + + public Boolean isExit() { + return false; + } + +} diff --git a/src/main/java/duke/command/DeleteCommand.java b/src/main/java/duke/command/DeleteCommand.java new file mode 100644 index 0000000000..5a123182f8 --- /dev/null +++ b/src/main/java/duke/command/DeleteCommand.java @@ -0,0 +1,38 @@ +package duke.command; + +import duke.common.DukeException; +import duke.tasklist.TaskList; +import duke.storage.Storage; +import duke.ui.Ui; + +import java.io.IOException; + +/** + * Deals with commands related to deleting tasks. + */ +public class DeleteCommand extends Command { + private int deleteCount; + + public DeleteCommand(int deleteCount) { + /** The array index will be actual count minus one.*/ + this.deleteCount = deleteCount - 1; + } + + /** + * Delete tasks, asks ui to show deleted task, and updates backup files. + * + * @param tasks Stores all tasks. + * @param ui Deals with user interface. + * @param storage Deals with back up file. + * @throws IOException If cannot find back up file in the hard disk. + * @throws DukeException If the intended delete index is invalid e.g. not exist. + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) throws IOException, DukeException { + if (deleteCount + 1 > tasks.size()) { + throw new DukeException("\tThere is no task " + (deleteCount + 1) + ". Please reconsider the index."); + } + ui.showDeleteMessage(tasks.deleteTask(deleteCount),tasks); + storage.write(tasks); + } +} diff --git a/src/main/java/duke/command/DoneCommand.java b/src/main/java/duke/command/DoneCommand.java new file mode 100644 index 0000000000..fc5f708a9d --- /dev/null +++ b/src/main/java/duke/command/DoneCommand.java @@ -0,0 +1,39 @@ +package duke.command; + +import duke.common.DukeException; +import duke.tasklist.TaskList; +import duke.storage.Storage; +import duke.ui.Ui; + +import java.io.IOException; + +/** + * Deals with command related to mark tasks as done. + */ +public class DoneCommand extends Command { + private int doneCount; + + public DoneCommand(int doneCount) { + /** The array index will be actual count minus one */ + this.doneCount = doneCount - 1; + } + + /** + * Marks a task as done, asks ui to show task marked as done, and updates back up file. + * + * @param tasks Stores all tasks. + * @param ui Deals with user interface. + * @param storage Deals with back up file. + * @throws IOException If cannot find back up file in the hard disk. + * @throws DukeException If the intended task to mark as done is invalid e.g. not exist. + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) throws IOException, DukeException { + if (doneCount + 1 > tasks.size()) { + throw new DukeException("\tThere is no task " + (doneCount + 1) + ". Please reconsider the index."); + } + tasks.getATask(this.doneCount).markAsDone(); + ui.showMarkAsDoneMessage(tasks,this.doneCount); + storage.write(tasks); + } +} diff --git a/src/main/java/duke/command/ExitCommand.java b/src/main/java/duke/command/ExitCommand.java new file mode 100644 index 0000000000..682bd039d0 --- /dev/null +++ b/src/main/java/duke/command/ExitCommand.java @@ -0,0 +1,31 @@ +package duke.command; + +import duke.storage.Storage; +import duke.tasklist.TaskList; +import duke.ui.Ui; + +/** + * Deals with command related to exit the Duke. + */ +public class ExitCommand extends Command { + public ExitCommand() { + + } + + @Override + public Boolean isExit() { + return true; + } + + /** + * Updates ui to show Goodbye. + * + * @param tasks Stores all tasks, useless here. + * @param ui Deals with user interface. + * @param storage Deals with back up file, useless here. + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) { + ui.showGoodByeMessage(); + } +} diff --git a/src/main/java/duke/command/FindCommand.java b/src/main/java/duke/command/FindCommand.java new file mode 100644 index 0000000000..dd5b3352fc --- /dev/null +++ b/src/main/java/duke/command/FindCommand.java @@ -0,0 +1,42 @@ +package duke.command; + +import duke.common.DukeException; +import duke.storage.Storage; +import duke.tasklist.TaskList; +import duke.ui.Ui; + +import java.io.IOException; +import java.util.ArrayList; + +/** + * Deals with command that can find a task by searching for a keyword. + */ +public class FindCommand extends Command { + + /** User input keyword.*/ + private static String findString; + /** Stores the task index that matches.*/ + private static ArrayList findCount; + + public FindCommand(String findString) { + this.findString = findString; + findCount = new ArrayList<>(); + } + + /** + * Finds tasks by searching for the keyword. + * + * @param tasks Stores all tasks. + * @param ui Deals with user interface. + * @param storage Deals with back up file. + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) { + for (int i = 0; i < tasks.size(); i++) { + if (tasks.getATask(i).getDescription().contains(findString)) { + findCount.add(i); + } + } + ui.showFindTask(tasks,findCount); + } +} diff --git a/src/main/java/duke/command/HelpCommand.java b/src/main/java/duke/command/HelpCommand.java new file mode 100644 index 0000000000..5bc7a97c11 --- /dev/null +++ b/src/main/java/duke/command/HelpCommand.java @@ -0,0 +1,18 @@ +package duke.command; + +import duke.storage.Storage; +import duke.tasklist.TaskList; +import duke.ui.Ui; + +/** + * Deals with command that shows help message. + */ +public class HelpCommand extends Command { + public HelpCommand() { + } + + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) { + ui.showHelpMessage(); + } +} diff --git a/src/main/java/duke/command/InvalidCommand.java b/src/main/java/duke/command/InvalidCommand.java new file mode 100644 index 0000000000..5128b00324 --- /dev/null +++ b/src/main/java/duke/command/InvalidCommand.java @@ -0,0 +1,28 @@ +package duke.command; + +import duke.common.DukeException; +import duke.tasklist.TaskList; +import duke.storage.Storage; +import duke.ui.Ui; + +/** + * Deals with command that cannot be recognized. + */ +public class InvalidCommand extends Command { + + public InvalidCommand(){ + } + + /** + * Throws exception since there is invalid command. + * + * @param tasks Stores all tasks, useless here. + * @param ui Deals with user interface, useless here. + * @param storage Deals with back up file, useless here. + * @throws DukeException Exists since the command is invalid. + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) throws DukeException { + throw new DukeException("\t Sorry.I do not understand you."); + } +} diff --git a/src/main/java/duke/command/ListCommand.java b/src/main/java/duke/command/ListCommand.java new file mode 100644 index 0000000000..7a1e146cf9 --- /dev/null +++ b/src/main/java/duke/command/ListCommand.java @@ -0,0 +1,27 @@ +package duke.command; + +import duke.common.DukeException; +import duke.tasklist.TaskList; +import duke.storage.Storage; +import duke.ui.Ui; + +/** + * Deals with command related to list all tasks. + */ +public class ListCommand extends Command { + /** + * Lists all tasks and asks ui to show tasks. + * + * @param tasks Stores all tasks. + * @param ui Deals with user interface. + * @param storage Deals with back up file, useless here. + * @throws DukeException If there is no task in list. + */ + @Override + public void execute(TaskList tasks, Ui ui, Storage storage) throws DukeException { + if (tasks.size() == 0) { + throw new DukeException("\tCurrently, there is no task in the list!"); + } + ui.showListOfTasks(tasks); + } +} diff --git a/src/main/java/duke/common/Constants.java b/src/main/java/duke/common/Constants.java new file mode 100644 index 0000000000..45313c306b --- /dev/null +++ b/src/main/java/duke/common/Constants.java @@ -0,0 +1,34 @@ +package duke.common; + +/** + * Stores all constant values. + */ +public final class Constants { + public static final String LOGO = " ____ _ \n" + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; + + public static final String TODO = "todo"; + public static final String DEADLINE = "deadline"; + public static final String EVENT = "event"; + public static final String BYE = "bye"; + public static final String CHECK = "check"; + public static final String DELETE = "delete"; + public static final String DONE = "done"; + public static final String FIND = "find"; + public static final String HELP = "help"; + public static final String LIST = "list"; + + public static final String LINE_BREAK = "\t____________________________________________________________"; + + public static final int TODO_LENGTH = 5; + public static final int DEADLINE_LENGTH = 9; + public static final int EVENT_LENGTH = 6; + public static final int FORMAT_LENGTH = 5; + + public static final String FILE_PATH = "data/duke.txt"; + public static final String CREATE_FILE_PATH = System.getProperty("user.dir") + "/data"; +} + diff --git a/src/main/java/duke/common/DukeException.java b/src/main/java/duke/common/DukeException.java new file mode 100644 index 0000000000..13a2e981ef --- /dev/null +++ b/src/main/java/duke/common/DukeException.java @@ -0,0 +1,7 @@ +package duke.common; + +public class DukeException extends Exception { + public DukeException(String s) { + super(s); + } +} diff --git a/src/main/java/duke/parser/Parser.java b/src/main/java/duke/parser/Parser.java new file mode 100644 index 0000000000..f2797827db --- /dev/null +++ b/src/main/java/duke/parser/Parser.java @@ -0,0 +1,125 @@ +package duke.parser; + +import duke.command.Command; +import duke.command.AddCommand; +import duke.command.ExitCommand; +import duke.command.CheckCommand; +import duke.command.DeleteCommand; +import duke.command.DoneCommand; +import duke.command.FindCommand; +import duke.command.HelpCommand; +import duke.command.ListCommand; +import duke.command.InvalidCommand; +import duke.common.DukeException; +import duke.tasklist.task.Deadline; +import duke.tasklist.task.Event; +import duke.tasklist.task.Todo; + +import static duke.common.Constants.TODO; +import static duke.common.Constants.DEADLINE; +import static duke.common.Constants.EVENT; +import static duke.common.Constants.BYE; +import static duke.common.Constants.CHECK; +import static duke.common.Constants.DELETE; +import static duke.common.Constants.DONE; +import static duke.common.Constants.FIND; +import static duke.common.Constants.HELP; +import static duke.common.Constants.LIST; +import static duke.common.Constants.TODO_LENGTH; +import static duke.common.Constants.DEADLINE_LENGTH; +import static duke.common.Constants.EVENT_LENGTH; +import static duke.common.Constants.FORMAT_LENGTH; + +/** + * Deals with making sense of the user command. + */ +public class Parser { + public Parser() { + + } + + /** + * Checks if a string is integer. + * + * @param str Input string. + * @return True if it is integer, else returns false. + */ + public static boolean isNumeric(String str) { + try { + Integer.parseInt(str); + return true; + } catch (NumberFormatException e) { + return false; + } + } + + /** + * Deals with making sense of the user command. + * + * @param fullCommand User input. + * @return Returns different types of command. + * @throws DukeException When user's command does not match with command standard. + */ + public static Command parse(String fullCommand) throws DukeException { + String[] responses = fullCommand.split(" "); + switch (responses[0]) { + case TODO: + if (responses.length < 2) { + throw new DukeException("\tThe description of a todo cannot be empty."); + } + return new AddCommand(new Todo(fullCommand.substring(TODO_LENGTH))); + case DEADLINE: + if (responses.length < 2) { + throw new DukeException("\tThe description of a deadline cannot be empty."); + } + int deadlineDividerPosition = fullCommand.indexOf(" /by"); + if (deadlineDividerPosition == -1) { + throw new DukeException("\tPlease follow the format: deadline thingsToDo /by time"); + } + String deadlineName = fullCommand.substring(DEADLINE_LENGTH,deadlineDividerPosition); + String deadlineTime = fullCommand.substring(deadlineDividerPosition + FORMAT_LENGTH); + return new AddCommand(new Deadline(deadlineName,deadlineTime)); + case EVENT: + if (responses.length < 2) { + throw new DukeException("\tThe description of a event cannot be empty."); + } + int eventDividerPosition = fullCommand.indexOf(" /at"); + if (eventDividerPosition == -1) { + throw new DukeException("\tPlease follow the format: event thingsToDo /at time"); + } + String eventName = fullCommand.substring(EVENT_LENGTH,eventDividerPosition); + String eventTime = fullCommand.substring(eventDividerPosition + FORMAT_LENGTH); + return new AddCommand(new Event(eventName,eventTime)); + case BYE: + return new ExitCommand(); + case CHECK: + if (responses.length < 2) { + throw new DukeException("\tPlease input the thing you want to check."); + } + return new CheckCommand(responses[1]); + case DELETE: + if (responses.length < 2 || !isNumeric(responses[1])) { + throw new DukeException("\tPlease input a task number that you want to delete"); + } + int deleteCount = Integer.parseInt(responses[1]); + return new DeleteCommand(deleteCount); + case DONE: + if (responses.length < 2 || !isNumeric(responses[1])) { + throw new DukeException("\tPlease input a task number that you want to mark as done"); + } + return new DoneCommand(Integer.parseInt(responses[1])); + case FIND: + if (responses.length < 2) { + throw new DukeException("\tPlease input the thing you want to find."); + } + return new FindCommand(responses[1]); + case HELP: + return new HelpCommand(); + case LIST: + return new ListCommand(); + default: + return new InvalidCommand(); + } + } +} + diff --git a/src/main/java/duke/storage/Storage.java b/src/main/java/duke/storage/Storage.java new file mode 100644 index 0000000000..5abc083189 --- /dev/null +++ b/src/main/java/duke/storage/Storage.java @@ -0,0 +1,89 @@ +package duke.storage; + +import duke.tasklist.TaskList; +import duke.tasklist.task.Deadline; +import duke.tasklist.task.Event; +import duke.tasklist.task.Todo; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Scanner; + +/** + * Deals with loading tasks from the file and saving tasks in the file. + */ +public class Storage { + private static String filePath; + + public Storage() { + } + + public Storage(String filePath) { + this.filePath = filePath; + } + + /** + * Changes the format of a task in file to correct format of a task in taskList. + * Then stores the right format task to list. + * + * @param oneTask A line in the hard disk. + * @param tasks Stores taskList. + */ + public static void loadATask(String oneTask, TaskList tasks) { + String[] taskSplit = oneTask.split(" \\| "); + switch (taskSplit[0]) { + case "T": + tasks.addTask(new Todo(taskSplit[2])); + break; + case "D": + tasks.addTask(new Deadline(taskSplit[2],taskSplit[3])); + break; + case "E": + tasks.addTask(new Event(taskSplit[2],taskSplit[3])); + break; + default: + break; + } + if (taskSplit[1].equals("1")) { + tasks.getATask(tasks.size() - 1).markAsDone(); + } + } + + /** + * Loads the content in the file to taskList. + * + * @param tasks Stores taskList. + * @throws FileNotFoundException If there is no back up file. + */ + public void load(TaskList tasks) throws FileNotFoundException { + File f = new File(filePath); + if (!f.exists()) { + throw new FileNotFoundException(); + } + Scanner s = new Scanner(f); + while (s.hasNext()) { + String oneTask; + loadATask(s.nextLine(),tasks); + } + } + + /** + * Writes a list of tasks to hard disk file. + * + * @param tasks Stores taskList. + * @throws IOException There is no back up file. + */ + public static void write(TaskList tasks) throws IOException { + File f = new File(filePath); + if (!f.exists()) { + throw new IOException(); + } + FileWriter fw = new FileWriter(filePath); + for (int i = 0; i < tasks.size(); i++) { + fw.write(tasks.getATask(i).toFile() + "\n"); + } + fw.close(); + } +} diff --git a/src/main/java/duke/tasklist/TaskList.java b/src/main/java/duke/tasklist/TaskList.java new file mode 100644 index 0000000000..215f08bc4d --- /dev/null +++ b/src/main/java/duke/tasklist/TaskList.java @@ -0,0 +1,33 @@ +package duke.tasklist; + +import duke.tasklist.task.Task; + +import java.util.ArrayList; + +/** + * Contains the task list. + * It has operations to add/delete tasks in the list. + */ +public class TaskList { + private static ArrayList tasks; + + public TaskList() { + this.tasks = new ArrayList<>(); + } + + public static void addTask(Task task) { + tasks.add(task); + } + + public static Task deleteTask(int deleteCount) { + return tasks.remove(deleteCount); + } + + public Task getATask(int taskCount) { + return this.tasks.get(taskCount); + } + + public int size() { + return tasks.size(); + } +} diff --git a/src/main/java/duke/tasklist/task/Deadline.java b/src/main/java/duke/tasklist/task/Deadline.java new file mode 100644 index 0000000000..1381f351d8 --- /dev/null +++ b/src/main/java/duke/tasklist/task/Deadline.java @@ -0,0 +1,48 @@ +package duke.tasklist.task; + + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.Locale; + +/** + * Stores a deadline task. + */ +public class Deadline extends Task { + + protected String by; + protected LocalDate time; + + /** + * Initializes the deadline class. + * Transforms the user input time to LocalDate format if the input format is correct. + * + * @param description User task. + * @param by Time limit. + */ + public Deadline(String description,String by) { + super(description); + try { + this.time = LocalDate.parse(by); + this.by = time.format(DateTimeFormatter.ofPattern("MMM d yyyy", Locale.US)) + ", " + time.getDayOfWeek(); + } catch (DateTimeParseException e) { + this.by = by; + } + } + + @Override + public LocalDate getTime() { + return this.time; + } + + @Override + public String toString() { + return "[D]" + super.toString() + " (by: " + by + ")"; + } + + @Override + public String toFile() { + return "D | " + super.toFile() + " | " + by; + } +} diff --git a/src/main/java/duke/tasklist/task/Event.java b/src/main/java/duke/tasklist/task/Event.java new file mode 100644 index 0000000000..4d70af56f1 --- /dev/null +++ b/src/main/java/duke/tasklist/task/Event.java @@ -0,0 +1,49 @@ +package duke.tasklist.task; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.Locale; + +import static duke.common.Constants.EVENT; + +/** + * Stores an event class. + */ +public class Event extends Task { + + protected String at; + protected LocalDate time; + + /** + * Initializes the deadline class. + * Transforms the user input time to LocalDate format if the input format is correct. + * + * @param description User task. + * @param at Time slot to do the event. + */ + public Event(String description,String at) { + super(description); + try { + this.time = LocalDate.parse(at); + this.at = time.format(DateTimeFormatter.ofPattern("MMM d yyyy", Locale.US)) + ", " + time.getDayOfWeek(); + } catch (DateTimeParseException e) { + this.at = at; + } + } + + @Override + public LocalDate getTime() { + return this.time; + } + + @Override + public String toString() { + return "[E]" + super.toString() + " (at: " + at + ")"; + } + + @Override + public String toFile() { + return "E | " + super.toFile() + " | " + at; + } +} diff --git a/src/main/java/duke/tasklist/task/Task.java b/src/main/java/duke/tasklist/task/Task.java new file mode 100644 index 0000000000..3dd7e50052 --- /dev/null +++ b/src/main/java/duke/tasklist/task/Task.java @@ -0,0 +1,55 @@ +package duke.tasklist.task; + +import java.time.LocalDate; + +/** + * Stores a task. + * Since there is no task without type, this super class is an abstract class. + */ +public abstract class Task { + protected String description; + protected boolean isDone; + + public Task(){ + } + + public Task(String description) { + this.description = description; + this.isDone = false; + } + + public String getStatusIcon() { + /** Return tick or X symbols. */ + return (isDone ? "/" : " "); + } + + public String getDescription() { + return description; + } + + public LocalDate getTime() { + return null; + } + + public void markAsDone() { + isDone = true; + } + + /** + * Prints a task appropriately. + * + * @return A string to display. + */ + public String toString() { + return "[" + getStatusIcon() + "] " + this.description; + } + + /** + * Stores a task according to back up file standard. + * + * @return A string to store. + */ + public String toFile() { + return ((isDone ? "1" : "0") + " | " + this.description); + } +} diff --git a/src/main/java/duke/tasklist/task/Todo.java b/src/main/java/duke/tasklist/task/Todo.java new file mode 100644 index 0000000000..ccc3c55887 --- /dev/null +++ b/src/main/java/duke/tasklist/task/Todo.java @@ -0,0 +1,21 @@ +package duke.tasklist.task; + +/** + * Stores a todo task. + */ +public class Todo extends Task { + + public Todo(String description) { + super(description); + } + + @Override + public String toString() { + return "[T]" + super.toString(); + } + + @Override + public String toFile() { + return "T | " + super.toFile(); + } +} diff --git a/src/main/java/duke/ui/Ui.java b/src/main/java/duke/ui/Ui.java new file mode 100644 index 0000000000..0cd05cfd97 --- /dev/null +++ b/src/main/java/duke/ui/Ui.java @@ -0,0 +1,140 @@ +package duke.ui; + +import duke.common.DukeException; +import duke.tasklist.TaskList; +import duke.tasklist.task.Task; + +import java.util.ArrayList; +import java.util.Scanner; + +import static duke.common.Constants.LINE_BREAK; +import static duke.common.Constants.LOGO; + +/** + * Deals with interactions with the user. + */ +public class Ui { + private static Scanner in = new Scanner(System.in); + + public Ui() { + System.out.println("Hello from\n" + LOGO); + } + + public String readCommand() { + return in.nextLine(); + } + + public void showLine() { + System.out.println(LINE_BREAK); + } + + /** + * Generates and prints the welcome message upon the start of the application. + */ + public void showWelcome() { + showLine(); + System.out.println("\tHello! I'm duke.Duke"); + System.out.println("\tWhat can I do for you?"); + showLine(); + System.out.println(); + } + + /** + * Displays prompt message that a new task is added in the task list. + * Displays the newly added task and current task count. + * + * @param tasks Store the taskList. + */ + public void showAddTaskMessage(TaskList tasks) { + System.out.println("\tGot it. I've added this task:"); + System.out.println("\t " + tasks.getATask(tasks.size() - 1)); + System.out.println("\tNow you have " + tasks.size() + " tasks in the list"); + } + + /** + * Generates and prints the goodbye message upon the end of the application. + */ + public void showGoodByeMessage() { + System.out.println("\tBye. Hope to see you again soon!"); + } + + /** + * Displays tasks that has been found either by keyword/time. + * + * @param tasks Stores the taskList. + * @param findCount Stores the matching task index. + */ + public void showFindTask(TaskList tasks, ArrayList findCount) { + if (findCount.size() > 0) { + System.out.println("\tHere are the matching tasks in your list:"); + for (Integer i : findCount) { + System.out.println("\t" + (i + 1) + "." + tasks.getATask(i)); + } + } else { + System.out.println("\t No matching tasks."); + } + } + + /** + * Displays prompt message that a task is marked as done. + * Displays the task that is marked done. + * + * @param tasks Store the task list. + * @param doneCount The task that is done. + */ + public void showMarkAsDoneMessage(TaskList tasks, int doneCount) { + System.out.println("\tNice! I've marked this task as done:"); + System.out.println("\t yes! " + tasks.getATask(doneCount).getDescription()); + } + + /** + * Displays prompt message that a task is deleted. + * Displays the task that is deleted and the task count. + * + * @param deleteTask The task that is deleted. + * @param tasks Stored the taskList. + */ + public void showDeleteMessage(Task deleteTask, TaskList tasks) { + System.out.println("\tNoted. I've removed this task:"); + System.out.println("\t " + deleteTask); + System.out.println("\tNow you have " + tasks.size() + " tasks in the list."); + } + + /** + * Displays all usage and format of this program. + */ + public void showHelpMessage() { + System.out.println("\tBelow is what Duke can do for you:"); + System.out.println("\t todo TASK : add a task that needs to do"); + System.out.println("\t deadline TASK /by TIME(yyyy-mm-dd) : add a task that has a certain deadline"); + System.out.println("\t event TASK /at TIME(yyyy-mm-dd) : add a task that happens on a day"); + System.out.println("\t bye : exit the program"); + System.out.println("\t check yyyy-mm-dd : check deadline/event occuring on that day"); + System.out.println("\t delete INDEX : delete a task by its number index"); + System.out.println("\t done INDEX : mark a task as done by its number index"); + System.out.println("\t find KEYWORD : find a task by its keyword"); + System.out.println("\t list : list all tasks"); + } + + /** + * Displays all list of tasks and if they are done. + * + * @param tasks Stores taskList. + * @throws DukeException If there is no tasks in current taskList. + */ + public void showListOfTasks(TaskList tasks) throws DukeException { + System.out.println("\tHere are the tasks in your list:"); + for (int i = 0; i < tasks.size(); i++) { + System.out.println("\t" + (i + 1) + "." + tasks.getATask(i)); + } + } + + public void showLoadingError() { + System.out.println("\tCreating back up file in the hard disk..."); + } + + public void showError(String error) { + System.out.println(error); + } +} + diff --git a/text-ui-test/ACTUAL.TXT b/text-ui-test/ACTUAL.TXT new file mode 100644 index 0000000000..e3cf05e244 --- /dev/null +++ b/text-ui-test/ACTUAL.TXT @@ -0,0 +1,130 @@ +Hello from + ____ _ +| _ \ _ _| | _____ +| | | | | | | |/ / _ \ +| |_| | |_| | < __/ +|____/ \__,_|_|\_\___| + + Creating back up file in the hard disk... + ____________________________________________________________ + Hello! I'm duke.Duke + What can I do for you? + ____________________________________________________________ + + ____________________________________________________________ + Below is what Duke can do for you: + todo task : add a task that needs to do + deadline task /by time(dddd-mm-yy) : add a task that has a certain deadline + event task /at time(dddd-mm-yy) : add a task that happens on a day + bye : exit the program + check dddd-mm-yy : check deadline/event occuring on that day + delete index : delete a task by its number index + done index : mark a task as done by its number index + find keyword : find a task by its keyword + list : list all tasks + ____________________________________________________________ + ____________________________________________________________ + Please input a task number that you want to mark as done + ____________________________________________________________ + ____________________________________________________________ + Currently, there is no task in the list! + ____________________________________________________________ + ____________________________________________________________ + Got it. I've added this task: + [T][ ] read book + Now you have 1 tasks in the list + ____________________________________________________________ + ____________________________________________________________ + Got it. I've added this task: + [T][ ] sleep + Now you have 2 tasks in the list + ____________________________________________________________ + ____________________________________________________________ + The description of a todo cannot be empty. + ____________________________________________________________ + ____________________________________________________________ + Sorry.I do not understand you. + ____________________________________________________________ + ____________________________________________________________ + Got it. I've added this task: + [D][ ] cs2113 (by: Tuesday) + Now you have 3 tasks in the list + ____________________________________________________________ + ____________________________________________________________ + Got it. I've added this task: + [D][ ] assignment (by: Mar 21 2020, SATURDAY) + Now you have 4 tasks in the list + ____________________________________________________________ + ____________________________________________________________ + Got it. I've added this task: + [E][ ] project meeting (at: Mon 2-4pm) + Now you have 5 tasks in the list + ____________________________________________________________ + ____________________________________________________________ + Got it. I've added this task: + [E][ ] concert (at: Mar 21 2020, SATURDAY) + Now you have 6 tasks in the list + ____________________________________________________________ + ____________________________________________________________ + Here are the matching tasks in your list: + 4.[D][ ] assignment (by: Mar 21 2020, SATURDAY) + 6.[E][ ] concert (at: Mar 21 2020, SATURDAY) + ____________________________________________________________ + ____________________________________________________________ + The description of a event cannot be empty. + ____________________________________________________________ + ____________________________________________________________ + Here are the matching tasks in your list: + 1.[T][ ] read book + ____________________________________________________________ + ____________________________________________________________ + The description of a deadline cannot be empty. + ____________________________________________________________ + ____________________________________________________________ + Please input the thing you want to find. + ____________________________________________________________ + ____________________________________________________________ + No matching tasks. + ____________________________________________________________ + ____________________________________________________________ + Nice! I've marked this task as done: + yes! sleep + ____________________________________________________________ + ____________________________________________________________ + Please input a task number that you want to mark as done + ____________________________________________________________ + ____________________________________________________________ + Nice! I've marked this task as done: + yes! cs2113 + ____________________________________________________________ + ____________________________________________________________ + There is no task 10. Please reconsider the index. + ____________________________________________________________ + ____________________________________________________________ + Here are the tasks in your list: + 1.[T][ ] read book + 2.[T][/] sleep + 3.[D][/] cs2113 (by: Tuesday) + 4.[D][ ] assignment (by: Mar 21 2020, SATURDAY) + 5.[E][ ] project meeting (at: Mon 2-4pm) + 6.[E][ ] concert (at: Mar 21 2020, SATURDAY) + ____________________________________________________________ + ____________________________________________________________ + Noted. I've removed this task: + [T][/] sleep + Now you have 5 tasks in the list. + ____________________________________________________________ + ____________________________________________________________ + Please input a task number that you want to delete + ____________________________________________________________ + ____________________________________________________________ + Here are the tasks in your list: + 1.[T][ ] read book + 2.[D][/] cs2113 (by: Tuesday) + 3.[D][ ] assignment (by: Mar 21 2020, SATURDAY) + 4.[E][ ] project meeting (at: Mon 2-4pm) + 5.[E][ ] concert (at: Mar 21 2020, SATURDAY) + ____________________________________________________________ + ____________________________________________________________ + Bye. Hope to see you again soon! + ____________________________________________________________ diff --git a/text-ui-test/EXPECTED.txt b/text-ui-test/EXPECTED.txt new file mode 100644 index 0000000000..e3cf05e244 --- /dev/null +++ b/text-ui-test/EXPECTED.txt @@ -0,0 +1,130 @@ +Hello from + ____ _ +| _ \ _ _| | _____ +| | | | | | | |/ / _ \ +| |_| | |_| | < __/ +|____/ \__,_|_|\_\___| + + Creating back up file in the hard disk... + ____________________________________________________________ + Hello! I'm duke.Duke + What can I do for you? + ____________________________________________________________ + + ____________________________________________________________ + Below is what Duke can do for you: + todo task : add a task that needs to do + deadline task /by time(dddd-mm-yy) : add a task that has a certain deadline + event task /at time(dddd-mm-yy) : add a task that happens on a day + bye : exit the program + check dddd-mm-yy : check deadline/event occuring on that day + delete index : delete a task by its number index + done index : mark a task as done by its number index + find keyword : find a task by its keyword + list : list all tasks + ____________________________________________________________ + ____________________________________________________________ + Please input a task number that you want to mark as done + ____________________________________________________________ + ____________________________________________________________ + Currently, there is no task in the list! + ____________________________________________________________ + ____________________________________________________________ + Got it. I've added this task: + [T][ ] read book + Now you have 1 tasks in the list + ____________________________________________________________ + ____________________________________________________________ + Got it. I've added this task: + [T][ ] sleep + Now you have 2 tasks in the list + ____________________________________________________________ + ____________________________________________________________ + The description of a todo cannot be empty. + ____________________________________________________________ + ____________________________________________________________ + Sorry.I do not understand you. + ____________________________________________________________ + ____________________________________________________________ + Got it. I've added this task: + [D][ ] cs2113 (by: Tuesday) + Now you have 3 tasks in the list + ____________________________________________________________ + ____________________________________________________________ + Got it. I've added this task: + [D][ ] assignment (by: Mar 21 2020, SATURDAY) + Now you have 4 tasks in the list + ____________________________________________________________ + ____________________________________________________________ + Got it. I've added this task: + [E][ ] project meeting (at: Mon 2-4pm) + Now you have 5 tasks in the list + ____________________________________________________________ + ____________________________________________________________ + Got it. I've added this task: + [E][ ] concert (at: Mar 21 2020, SATURDAY) + Now you have 6 tasks in the list + ____________________________________________________________ + ____________________________________________________________ + Here are the matching tasks in your list: + 4.[D][ ] assignment (by: Mar 21 2020, SATURDAY) + 6.[E][ ] concert (at: Mar 21 2020, SATURDAY) + ____________________________________________________________ + ____________________________________________________________ + The description of a event cannot be empty. + ____________________________________________________________ + ____________________________________________________________ + Here are the matching tasks in your list: + 1.[T][ ] read book + ____________________________________________________________ + ____________________________________________________________ + The description of a deadline cannot be empty. + ____________________________________________________________ + ____________________________________________________________ + Please input the thing you want to find. + ____________________________________________________________ + ____________________________________________________________ + No matching tasks. + ____________________________________________________________ + ____________________________________________________________ + Nice! I've marked this task as done: + yes! sleep + ____________________________________________________________ + ____________________________________________________________ + Please input a task number that you want to mark as done + ____________________________________________________________ + ____________________________________________________________ + Nice! I've marked this task as done: + yes! cs2113 + ____________________________________________________________ + ____________________________________________________________ + There is no task 10. Please reconsider the index. + ____________________________________________________________ + ____________________________________________________________ + Here are the tasks in your list: + 1.[T][ ] read book + 2.[T][/] sleep + 3.[D][/] cs2113 (by: Tuesday) + 4.[D][ ] assignment (by: Mar 21 2020, SATURDAY) + 5.[E][ ] project meeting (at: Mon 2-4pm) + 6.[E][ ] concert (at: Mar 21 2020, SATURDAY) + ____________________________________________________________ + ____________________________________________________________ + Noted. I've removed this task: + [T][/] sleep + Now you have 5 tasks in the list. + ____________________________________________________________ + ____________________________________________________________ + Please input a task number that you want to delete + ____________________________________________________________ + ____________________________________________________________ + Here are the tasks in your list: + 1.[T][ ] read book + 2.[D][/] cs2113 (by: Tuesday) + 3.[D][ ] assignment (by: Mar 21 2020, SATURDAY) + 4.[E][ ] project meeting (at: Mon 2-4pm) + 5.[E][ ] concert (at: Mar 21 2020, SATURDAY) + ____________________________________________________________ + ____________________________________________________________ + Bye. Hope to see you again soon! + ____________________________________________________________ diff --git a/text-ui-test/data/duke.txt b/text-ui-test/data/duke.txt new file mode 100644 index 0000000000..26f5e35dd7 --- /dev/null +++ b/text-ui-test/data/duke.txt @@ -0,0 +1,5 @@ +T | 0 | read book +D | 1 | cs2113 | Tuesday +D | 0 | assignment | Mar 21 2020, SATURDAY +E | 0 | project meeting | Mon 2-4pm +E | 0 | concert | Mar 21 2020, SATURDAY diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt new file mode 100644 index 0000000000..f1be38bf74 --- /dev/null +++ b/text-ui-test/input.txt @@ -0,0 +1,26 @@ +help +done +list +todo read book +todo sleep +todo +heyhey +deadline cs2113 /by Tuesday +deadline assignment /by 2020-03-21 +event project meeting /at Mon 2-4pm +event concert /at 2020-03-21 +check 2020-03-21 +event +find book +deadline +find +find exam +done 2 +done +done 3 +done 10 +list +delete 2 +delete +list +bye \ No newline at end of file diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat new file mode 100644 index 0000000000..591121e6b8 --- /dev/null +++ b/text-ui-test/runtest.bat @@ -0,0 +1,21 @@ +@ECHO OFF + +REM create bin directory if it doesn't exist +if not exist ..\bin mkdir ..\bin + +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 ..\src\main\java\duke\command\*.java ..\src\main\java\duke\common\*.java ..\src\main\java\duke\parser\*.java ..\src\main\java\duke\storage\*.java ..\src\main\java\duke\taskList\*.java ..\src\main\java\duke\taskList\task\*.java ..\src\main\java\duke\ui\*.java +IF ERRORLEVEL 1 ( + echo ********** BUILD FAILURE ********** + exit /b 1 +) +REM no error here, errorlevel == 0 + +REM run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT +java -classpath ..\bin duke.Duke < input.txt > ACTUAL.TXT + +REM compare the output to the expected output +FC ACTUAL.TXT EXPECTED.TXT diff --git a/tutorials/gradleTutorial.md b/tutorials/gradleTutorial.md index 08292b118d..2d60727f2b 100644 --- a/tutorials/gradleTutorial.md +++ b/tutorials/gradleTutorial.md @@ -30,10 +30,10 @@ As a developer, you write a _build file_ that describes the project. A build fil git checkout master git merge gradle ``` -1. Open the `build.gradle` file in an editor. Update the following code block to point to the main class (i.e., the one containing the `main` method) of your application. The code below assumes your main class is `seedu.duke.Duke` +1. Open the `build.gradle` file in an editor. Update the following code block to point to the main class (i.e., the one containing the `main` method) of your application. The code below assumes your main class is `seedu.duke.duke.Duke` ```groovy application { - mainClassName = "seedu.duke.Duke" + mainClassName = "seedu.duke.duke.Duke" } ``` 1. To check if Gradle has been added to the project correctly, open a terminal window, navigate to the root directory of your project and run the command `gradlew run`. This should result in Gradle running the main method of your project. @@ -146,7 +146,7 @@ By convention, java tests belong in `src/test/java` folder. Create a new `test/j src ├─main │ └─java -│ └─seedu/duke/Duke.java +│ └─seedu/duke/duke.Duke.java └─test └─java └─seedu/duke/DukeTest.java diff --git a/tutorials/javaFxTutorialPart1.md b/tutorials/javaFxTutorialPart1.md index 561daeca43..d9c611fbb7 100644 --- a/tutorials/javaFxTutorialPart1.md +++ b/tutorials/javaFxTutorialPart1.md @@ -27,24 +27,31 @@ A JavaFX application is like a play you are directing. Instead of creating props Update your `build.gradle` to include the following lines: ```groovy -plugins { - id 'java' - id 'org.openjfx.javafxplugin' version '0.0.7' -} - repositories { mavenCentral() } -javafx { - version = "11.0.2" - modules = [ 'javafx.controls', 'javafx.fxml' ] +dependencies { + 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' } ``` ## Writing your first program -As customary, let’s start off with a simple “Hello World” program. Modify your `Duke` class to extend `javafx.application.Application`. This requires you to override the `Application#start()` method and provide a concrete implementation. Notice that the method signature for `Application#start()` has a parameter `Stage`. This is the _primary stage_ that JavaFX provides. +As customary, let’s start off with a simple “Hello World” program. Modify your `duke.Duke` class to extend `javafx.application.Application`. This requires you to override the `Application#start()` method and provide a concrete implementation. Notice that the method signature for `Application#start()` has a parameter `Stage`. This is the _primary stage_ that JavaFX provides. ```java import javafx.application.Application; @@ -52,7 +59,7 @@ import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.stage.Stage; -public class Duke extends Application { +public class duke.Duke extends Application { // ... @@ -73,7 +80,7 @@ Next, we create another Java class, `Launcher`, as an entry point to our applica The `Launcher` class is reproduced below in its entirety. ```java -import javafx.application.Application; +import duke.Duke;import javafx.application.Application; /** * A launcher class to workaround classpath issues. diff --git a/tutorials/javaFxTutorialPart2.md b/tutorials/javaFxTutorialPart2.md index f24a0cd6ad..ade0b458cd 100644 --- a/tutorials/javaFxTutorialPart2.md +++ b/tutorials/javaFxTutorialPart2.md @@ -1,8 +1,8 @@ -# JavaFX Tutorial Part 2 - Creating a GUI for Duke +# JavaFX Tutorial Part 2 - Creating a GUI for duke.Duke -In this tutorial, we will be creating a GUI for Duke from scratch based on the following mockup. +In this tutorial, we will be creating a GUI for duke.Duke from scratch based on the following mockup. -![Mockup for Duke](assets/DukeMockup.png) +![Mockup for duke.Duke](assets/DukeMockup.png) ## JavaFX controls @@ -34,7 +34,7 @@ But how do we get the exact layout we want in the UI? JavaFX provides that funct One way to obtain the layout in the mockup is as follows. -![Duke's layout](assets/DukeSceneGraph.png) +![duke.Duke's layout](assets/DukeSceneGraph.png) To get that layout, we create a new `AnchorPane` and add our controls to it. Similarly, we create a new `VBox` to hold the contents of the `ScrollPane`. The code should look something like this: @@ -49,7 +49,7 @@ import javafx.scene.layout.VBox; import javafx.stage.Stage; -public class Duke extends Application { +public class duke.Duke extends Application { private ScrollPane scrollPane; private VBox dialogContainer; @@ -88,7 +88,7 @@ public class Duke extends Application { Run the application and you should see something like this: -![Duke's raw layout](assets/RawLayout.png) +![duke.Duke's raw layout](assets/RawLayout.png) That is not what we were expecting, what did we forget to do? @@ -106,7 +106,7 @@ Add the following code to the bottom of the `start` method. You'll have to add ` //... //Step 2. Formatting the window to look as expected - stage.setTitle("Duke"); + stage.setTitle("duke.Duke"); stage.setResizable(false); stage.setMinHeight(600.0); stage.setMinWidth(400.0); @@ -141,7 +141,7 @@ Add the following code to the bottom of the `start` method. You'll have to add ` Run the application again. It should now look like this: -![Duke's Final layout](assets/FinalLayout.png) +![duke.Duke's Final layout](assets/FinalLayout.png) ## Exercises diff --git a/tutorials/javaFxTutorialPart3.md b/tutorials/javaFxTutorialPart3.md index a9e1bdddd3..813079f3fa 100644 --- a/tutorials/javaFxTutorialPart3.md +++ b/tutorials/javaFxTutorialPart3.md @@ -8,7 +8,7 @@ Rather than to do everything in one try, let’s iterate and build up towards ou JavaFX has an _event-driven architecture style_. As such, we programmatically define _handler_ methods to execute as a response to certain _events_. When an event is detected, JavaFX will call the respective handlers. -For Duke, there are two events that we want to respond to, namely the user pressing `Enter` in the `TextField` and left-clicking the `Button`. These are the `onAction` event for the `TextField` and the `onMouseClicked` event for the `Button`. +For duke.Duke, there are two events that we want to respond to, namely the user pressing `Enter` in the `TextField` and left-clicking the `Button`. These are the `onAction` event for the `TextField` and the `onMouseClicked` event for the `Button`. For now, let’s have the application add a new `Label` with the text from the `TextField`. Update the `Main` class as follows. You'll need to add an `import javafx.scene.control.Label;` too. ```java @@ -103,7 +103,7 @@ import javafx.scene.image.ImageView; ``` Next, add two images to the `main/resources/images` folder. -For this tutorial, we have two images `DaUser.png` and `DaDuke.png` to represent the user avatar and Duke's avatar respectively but you can use any image you want. +For this tutorial, we have two images `DaUser.png` and `DaDuke.png` to represent the user avatar and duke.Duke's avatar respectively but you can use any image you want. Image|Filename ---|--- @@ -112,7 +112,7 @@ Image|Filename ```java -public class Duke extends Application { +public class duke.Duke extends Application { // ... private Image user = new Image(this.getClass().getResourceAsStream("/images/DaUser.png")); private Image duke = new Image(this.getClass().getResourceAsStream("/images/DaDuke.png")); @@ -124,7 +124,7 @@ Add a new method to handle user input: ```java /** * Iteration 2: - * Creates two dialog boxes, one echoing user input and the other containing Duke's reply and then appends them to + * Creates two dialog boxes, one echoing user input and the other containing duke.Duke's reply and then appends them to * the dialog container. Clears the user input after processing. */ private void handleUserInput() { @@ -142,7 +142,7 @@ private void handleUserInput() { * Replace this stub with your completed method. */ private String getResponse(String input) { - return "Duke heard: " + input; + return "duke.Duke heard: " + input; } ``` @@ -170,7 +170,7 @@ Run the program and see how it works. ## Iteration 3 – Adding custom behavior to DialogBox -One additional benefit of defining a custom control is that we can add behavior specific to our `DialogBox`. Let’s add a method to flip a dialog box such that the image on the left to differentiate between user input and Duke’s output. +One additional benefit of defining a custom control is that we can add behavior specific to our `DialogBox`. Let’s add a method to flip a dialog box such that the image on the left to differentiate between user input and duke.Duke’s output. ```java /** @@ -224,7 +224,7 @@ Run the application and play around with it. ![DialogBoxes Iteration 3](assets/DialogBoxesIteration3.png) Congratulations! -You have successfully implemented a fully functional GUI for Duke! +You have successfully implemented a fully functional GUI for duke.Duke! ## Exercises diff --git a/tutorials/javaFxTutorialPart4.md b/tutorials/javaFxTutorialPart4.md index 0e0ab280c4..638505a99b 100644 --- a/tutorials/javaFxTutorialPart4.md +++ b/tutorials/javaFxTutorialPart4.md @@ -29,7 +29,7 @@ FXML is a XML-based language that allows us to define our user interface. Proper The FXML snippet define a TextField similar to the one that we programmatically defined previous in Tutorial 2. Notice how concise FXML is compared to the plain Java version. -Let's return to Duke and convert it to use FXML instead. +Let's return to duke.Duke and convert it to use FXML instead. # Rebuilding the Scene using FXML @@ -101,14 +101,14 @@ We will get to that later. ## Using Controllers -As part of the effort to separate the code handling Duke's logic and UI, let's _refactor_ the UI-related code to its own class. +As part of the effort to separate the code handling duke.Duke's logic and UI, let's _refactor_ the UI-related code to its own class. We call these UI classes _controllers_. Let's implement the `MainWindow` controller class that we specified in `MainWindow.fxml`. **MainWindow.java** ```java -import javafx.fxml.FXML; +import duke.Duke;import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.ScrollPane; import javafx.scene.control.TextField; @@ -143,7 +143,7 @@ public class MainWindow extends AnchorPane { } /** - * Creates two dialog boxes, one echoing user input and the other containing Duke's reply and then appends them to + * Creates two dialog boxes, one echoing user input and the other containing duke.Duke's reply and then appends them to * the dialog container. Clears the user input after processing. */ @FXML @@ -168,7 +168,7 @@ Similarly, methods like private methods like `handleUserInput` can be used in FX ## Using FXML in our application -Let's create a new `Main` class as the bridge between the existing logic in `Duke` and the UI in `MainWindow`. +Let's create a new `Main` class as the bridge between the existing logic in `duke.Duke` and the UI in `MainWindow`. **Main.java** ```java @@ -182,7 +182,7 @@ import javafx.scene.layout.AnchorPane; import javafx.stage.Stage; /** - * A GUI for Duke using FXML. + * A GUI for duke.Duke using FXML. */ public class Main extends Application { diff --git a/tutorials/textUiTestingTutorial.md b/tutorials/textUiTestingTutorial.md index f397d76aef..b421fa37da 100644 --- a/tutorials/textUiTestingTutorial.md +++ b/tutorials/textUiTestingTutorial.md @@ -13,7 +13,7 @@ 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 -Xlint:none -d ..\bin ..\src\main\java\duke.Duke.java IF ERRORLEVEL 1 ( echo ********** BUILD FAILURE ********** exit /b 1 @@ -21,7 +21,7 @@ REM no error here, errorlevel == 0 REM run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT - java -classpath ..\bin Duke < input.txt > ACTUAL.TXT + java -classpath ..\bin duke.Duke < input.txt > ACTUAL.TXT REM compare the output to the expected output FC ACTUAL.TXT EXPECTED.TXT @@ -44,14 +44,14 @@ 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 + if ! javac -cp ../src -Xlint:none -d ../bin ../src/main/java/duke.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 + java -classpath ../bin duke.Duke < input.txt > ACTUAL.TXT # compare the output to the expected output diff ACTUAL.TXT EXPECTED.TXT