Project Duke is a educational software project designed to take you through the steps of building a small software incrementally, while applying as many Java and SE techniques as possible along the way.
The project aims to build a product named Duke, a Personal Assistant Chatbot that helps a person to keep track of various things. The name Duke was chosen as a placeholder name, in honor of Duke, the Java Mascot.
Here is a sample interaction with Duke:
____________________________________________________________
____ _
| _ \ _ _| | _____
| | | | | | | |/ / _ \
| |_| | |_| | < __/
|____/ \__,_|_|\_\___|
Hello! I'm Duke
What can I do for you?
____________________________________________________________
list
____________________________________________________________
Here are the tasks in your list:
1.[T][X] read book
2.[D][ ] return book (by: June 6th)
3.[E][ ] project meeting (from: Aug 6th 2pm to: 4pm)
4.[T][X] join sports club
____________________________________________________________
todo borrow book
____________________________________________________________
Got it. I've added this task:
[T][ ] borrow book
Now you have 5 tasks in the list.
____________________________________________________________
deadline return book /by Sunday
____________________________________________________________
Got it. I've added this task:
[D][ ] return book (by: Sunday)
Now you have 6 tasks in the list.
____________________________________________________________
mark 2
____________________________________________________________
Nice! I've marked this task as done:
[D][X] return book (by: June 6th)
____________________________________________________________
blah
____________________________________________________________
OOPS!!! I'm sorry, but I don't know what that means :-(
____________________________________________________________
bye
____________________________________________________________
Bye. Hope to see you again soon!
____________________________________________________________
You are encouraged to give your chatbot another name (and a different personality if you wish), to differentiate yours from others'. In the case of the latter, please do not use slang/words that some others in the class might not know, and also avoid offensive language.
The project consists of the following increments:
Level 1
to Level 10
to indicate how each makes the product progressively "level up".(a) Give your chatbot a new name, to differentiate it from the placeholder name Duke
.
Avoid these common choices as well: Chatty
, Jarvis
, ChatBot
, Chad
(b) Implement an initial skeletal version of it that simply greets the user and exits.
Example:
____________________________________________________________
Hello! I'm [YOUR CHATBOT NAME]
What can I do for you?
____________________________________________________________
Bye. Hope to see you again soon!
____________________________________________________________
Duke.java
to match the chatbot name you selected, and remove all traces of Duke
from the source code.Improve the skeletal version of Duke so that it echos commands entered by the user, and exits when the user types the command bye
.
Example:
____________________________________________________________
Hello! I'm [YOUR CHATBOT NAME]
What can I do for you?
____________________________________________________________
list
____________________________________________________________
list
____________________________________________________________
blah
____________________________________________________________
blah
____________________________________________________________
bye
____________________________________________________________
Bye. Hope to see you again soon!
____________________________________________________________
You are strongly encouraged to customize the chatbot: In addition to the command/display formats, you can even customize the personality of the chatbot to make your chatbot unique.
Add the ability to store whatever text entered by the user and display them back to the user when requested.
Example:
____________________________________________________________
Hello! I'm [YOUR CHATBOT NAME]
What can I do for you?
____________________________________________________________
read book
____________________________________________________________
added: read book
____________________________________________________________
return book
____________________________________________________________
added: return book
____________________________________________________________
list
____________________________________________________________
1. read book
2. return book
____________________________________________________________
bye
____________________________________________________________
Bye. Hope to see you again soon!
____________________________________________________________
String[100]
) to store the items.Add the ability to mark tasks as done. Optionally, add the ability to change the status back to not done.
list
____________________________________________________________
Here are the tasks in your list:
1.[X] read book
2.[ ] return book
3.[ ] buy bread
____________________________________________________________
mark 2
____________________________________________________________
Nice! I've marked this task as done:
[X] return book
____________________________________________________________
unmark 2
____________________________________________________________
OK, I've marked this task as not done yet:
[ ] return book
____________________________________________________________
When implementing this feature, you are also recommended to implement the following extension:
Add support for tracking three types of tasks:
Example:
todo borrow book
____________________________________________________________
Got it. I've added this task:
[T][ ] borrow book
Now you have 5 tasks in the list.
____________________________________________________________
list
____________________________________________________________
Here are the tasks in your list:
1.[T][X] read book
2.[D][ ] return book (by: June 6th)
3.[E][ ] project meeting (from: Aug 6th 2pm to: 4pm)
4.[T][X] join sports club
5.[T][ ] borrow book
____________________________________________________________
deadline return book /by Sunday
____________________________________________________________
Got it. I've added this task:
[D][ ] return book (by: Sunday)
Now you have 6 tasks in the list.
____________________________________________________________
event project meeting /from Mon 2pm /to 4pm
____________________________________________________________
Got it. I've added this task:
[E][ ] project meeting (from: Mon 2pm to: 4pm)
Now you have 7 tasks in the list.
____________________________________________________________
At this point, dates/times can be treated as strings; there is no need to convert them to actual dates/times.
Example:
deadline do homework /by no idea :-p
____________________________________________________________
Got it. I've added this task:
[D][ ] do homework (by: no idea :-p)
Now you have 6 tasks in the list.
____________________________________________________________
When implementing this feature, you are also recommended to implement the following extension:
Teach the chatbot to deal with errors such as incorrect inputs entered by the user.
Example:
todo
____________________________________________________________
OOPS!!! The description of a todo cannot be empty.
____________________________________________________________
blah
____________________________________________________________
OOPS!!! I'm sorry, but I don't know what that means :-(
____________________________________________________________
You are strongly encouraged to use your own wording for the error messages, rather than use the error message given in the example above.
When implementing this feature, you are also recommended to implement the following extension:
Add support for deleting tasks from the list.
Example:
list
____________________________________________________________
Here are the tasks in your list:
1.[T][X] read book
2.[D][X] return book (by: June 6th)
3.[E][ ] project meeting (from: Aug 6th 2pm to: 4pm)
4.[T][X] join sports club
5.[T][ ] borrow book
____________________________________________________________
delete 3
____________________________________________________________
Noted. I've removed this task:
[E][ ] project meeting (from: Aug 6th 2pm to: 4pm)
Now you have 4 tasks in the list.
____________________________________________________________
When implementing this feature, you are also recommended to implement the following extension:
Save the tasks in the hard disk automatically whenever the task list changes. Load the data from the hard disk when the chatbot starts up. You may hard-code the file name and relative path from the project root e.g., ./data/duke.txt
The format of the file is up to you. Example:
T | 1 | read book
D | 0 | return book | June 6th
E | 0 | project meeting | Aug 6th 2-4pm
T | 1 | join sports club
If you use file paths in your code,
C:\data
. If not, your app can cause unpredictable results when used in another computer.Your code must the case where the data file doesn't exist at the start. Reason: when someone else takes your chatbot and runs it for the first time, the required file will not exist in their computer. Similarly, if you expect the data file to be in a specific folder (e.g., ./data/
), you must also handle the folder-does-not-exist-yet case.
Stretch goal: Handle the situation of the data file being corrupted (i.e., content not in the expected format).
Teach the chatbot how to understand dates and times. For example, if the command is deadline return book /by 2/12/2019 1800
, the chatbot should understand 2/12/2019 1800
as 2nd of December 2019, 6pm, instead of treating it as just a String.
java.time.LocalDate
(or java.time.LocalDateTime
) in your task objects. Accept dates in a format such as yyyy-mm-dd
format (e.g., 2019-10-15
) and print in a different format such as MMM dd yyyy
e.g., (Oct 15 2019
).Give users a way to find a task by searching for a keyword in the task description.
Example:
find book
____________________________________________________________
Here are the matching tasks in your list:
1.[T][X] read book
2.[D][X] return book (by: June 6th)
____________________________________________________________
Add a GUI to the chatbot. Use the JavaFX technology to implement the GUI.
Refer to the JavaFX tutorial @SE-EDU/guides to learn how to get started with JavaFX.
Go through at least up to part 4 of the tutorial. Part 5 covers cosmetic UI tweaks, and is optional to learn.
There are two non-trivial steps to take here:
You are cautioned against trying to do both in one go. Instead, complete the JavaFX tutorial as a separate project before adding a GUI to the chatbot.
Common mistake: Forgetting to add a separate Launcher
class (as explained in the JavaFX tutorial Part 1) when adding the GUI to your project.
While it is possible to represent a task list as a multi-dimensional array containing , the more natural approach is to use a Task
class to represent tasks.
As there are multiple types of tasks that have some similarity between them, you can implement classes Todo
, Deadline
and Event
classes to inherit from a Task
class.
Furthermore, use polymorphism to store all tasks in a data structure containing Task
objects e.g., Task[100]
.
Make the Task
class an abstract class. If applicable, use abstract methods as well.
Use exceptions to handle errors. For example, define a class DukeException
to represent exceptions specific to Duke.
Use the input/output redirection technique to semi-automate the testing of Duke.
Notes:
text-ui-test
folder).Use Java Collections classes for storing data. For example, you can use an ArrayList<Task>
to store the tasks. They offer many advantages (e.g., dynamic sizing, easy to find/add/delete items), over using a primitive data structure such as a normal array.
Refactor the code to extract out closely related code as classes.
Ui
: deals with interactions with the userStorage
: deals with loading tasks from the file and saving tasks in the fileParser
: deals with making sense of the user commandTaskList
: contains the task list e.g., it has operations to add/delete tasks in the listFor example, the code of the main class could look like this:
public class Duke {
private Storage storage;
private TaskList tasks;
private Ui ui;
public Duke(String filePath) {
ui = new Ui();
storage = new Storage(filePath);
try {
tasks = new TaskList(storage.load());
} catch (DukeException e) {
ui.showLoadingError();
tasks = new TaskList();
}
}
public void run() {
//...
}
public static void main(String[] args) {
new Duke("data/tasks.txt").run();
}
}
*Command
classes (i.e., AddCommand
, DeleteCommand
, ExitCommand
etc.) that inherit from an abstract Command
class, so that you can write the main logic of the App as follows: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());
} finally {
ui.showLine();
}
}
}
Your class names may differ from the ones given above. The design can differ too, if you can justify your design is a good OOP design (there is no one correct design solution for most design problems, after all).
You can get some inspiration from how the class structure of the addressbook-level2 is organized.
Add JUnit tests to test the behavior of the code.
Refer to the JUnit tutorial @se-edu/guides to find how to use JUnit (in the context of this project).
Organize the classes into suitable java packages.
Note that src/main/java
should be kept as the folder, as some tools we'll be using later will look for the Java source code in that folder by default.
For example, suppose you have the following structure now, and you wish to move Duke.java
into a package duke.ui
.
The correct way to do so is:
duke.ui
)
Do not convert src
, main
, java
into packages. For example, the following is incorrect:
src.main.java
)
duke
duke.task
, duke.command
Add JavaDoc comments to the code.
Tweak the code to comply with a given coding standard. From this point onward, ensure any new code added are compliant with the given coding standard.
Use checkStyle to detect coding style violations.
Refer the tutorial Using Checkstyle @SE-EDU/guides to learn how to use Checkstyle.
Critically examines the code and refactor to improve the code quality where necessary.
When adding this increment, follow closely the 'Code Quality' topics you have learned so far, rather than merely follow your own intuition about code quality.
Use assert
feature (not JUnit assertions) to document important assumptions that should hold at various points in the code.
Package the app as an executable JAR file so that it can be distributed easily.
You can assume the user will run the jar file in the following way only:
java -jar "{filename}.jar"
e.g., java -jar "Duke.jar"
(i.e., run the command in the same folder as the jar file).The double quotes around the filename in the java -jar "{filename}.jar"
is not normally needed, but it is needed if the filename contains special characters such as spaces or [
.
FAQ: Can we double-click the jar file to run it?
A: Yes, that usually works too, being able to do so is not a requirement here. Instead, the java -jar
command is the recommended way to run the jar file.
Refer to the tutorial Working with JAR files @SE-EDU/guides to find how to create JAR files (in the context of this project).
If your project is being revision controlled using Git/GitHub,
do not commit the JAR file created. Reason: We don't normally commit generated binary files into the repository.
Instead, you can make the JAR file available (via the GitHub release mechanism) in the following manner.
v0.1
Attach binaries by dropping them ...
.Use Gradle to automate some of the build tasks of the project, as follows:
add-gradle-support
in the Duke repo. Merge that branch to your master
branch.Requirements for this increment:
A-JUnit
increment).Use GitHub Actions to set up Continuous Integration (CI).
The workflow specified by this .yml
file is a good candidate for this project. The last three segments are related to I/O redirection tests; can be deleted if not applicable to your project.
Refer to the Using GitHub Actions @SE-EDU/guides to learn how to use that .yml
file to set up GitHub actions.
Also note that pushing a GitHub Actions related file to GitHub requires you to authenticate using a that has workflow
permissions (because you are modifying a workflow of your repo). If you are using Sourcetree, you can refer to Sourcetree Guide @SE-EDU/guides to learn how to connect Sourcetree with GitHub using a PAT.
Use third-party libraries in your project. For example, you can use the Natty library to parse strings into meaningful dates.
Add a User Guide to the project in the following way:
docs\README.md
. See this guide to GitHub flavored Markdown (GFMD).Pages
on the menu on the left edge of page.Source
as: [ Branch: master ] branch and [ /docs ] folder and click Save
.https://{your username}.github.io/{repo name}/
to view the user guide of your product. Note: it could take 5-10 minutes for GitHub to update the page.Minimal:
How detailed should the user guide be? It should be fit-for-purpose. i.e., think from the user's point of view and include as much information as necessary for the user (while trying to keep it as short as possible -- users don't have the patience to read lengthy user guides either), in a format as friendly to the user as possible.
You can use the 'Features' section of this user guide as a benchmark.
Add a Developer Guide to the project, explaining the design and implementation to future developers.
Release the product to be used by potential users. e.g., you can make it available on GitHub
Improve the GUI to make it more polished. Some examples:
You can take inspiration from these past projects. If you adopt any ideas from them, don't forget to give credit to the original author.
Choose a unique personality for Duke, and tweak the following aspects to go with that personality:
Write more JUnit tests, to test nearly all code that can be tested automatically.
You may omit code that are hard to test automatically e.g., GUI functionality (test those manually instead).
This can include more manual testing as well e.g., testing on different OSes, different screen resolution, different OS language settings (English vs Chinese)
Improve the code to handle all errors you anticipate the product will encounter during usage.
Some examples of errors:
Use AI tools (e.g., GitHub Copilot, ChatGPT) to enhance your chatbot code. For example, you can get AI tools to help you,
Provide a way for an event to be tentatively scheduled in multiple slots, and later to be confirmed to one the slots.
Provide support for managing recurring tasks e.g., a weekly project meeting.
Support the managing of tasks that need to be done after a specific time/task e.g., return book after the exam is over.
Provide support for managing tasks that need to be done within a certain period e.g., collect certificate between Jan 15 and 25th.
Provide support for managing tasks that takes a fixed amount of time but does not have a fixed start/end time e.g., reading the sales report (needs 2 hours).
Provide a way to get reminders about tasks e.g., remind the user about upcoming deadlines.
Provide a way for the user to find free times e.g., when is the nearest day in which I have a 4 hour free slot?.
Provide a way to view tasks in the form of a schedule e.g., view the schedule for a specific date.
Deal with schedule anomalies e.g., detect if a task being added clashes with another task in the list.
Add the ability to recognize and deal with duplicate items. e.g., the same task added multiple times.
Provide more flexibility with the data source e.g., the ability for the user to specify which file to use as the data source.
The ability to sort items e.g., sort deadlines chronologically.
Support more natural date formats e.g., Mon
in a user command can be interpreted as the date of the next Monday in the calendar.
All more flexibility in search e.g., find items even if the keyword matches the item only partially.
Support a way to easily edit details of items e.g., change the end time of an event without changing anything else.
Minimal: the ability to update an existing item without having to delete it first
Other ideas:
Provide a way to attach priorities to items e.g., mark an item as a high
priority (or priority level 1
).
Provide a way to archive items so that the user can remove items from the app but still keep a record of them somewhere e.g., archive all tasks in the list into a file so that the user can start over with a clean slate.
Provide a way to perform tasks on multiple items e.g., delete some specific items in one go.
Provide a way to leverage statistics about the items managed by the App e.g., show the number of tasks that have been completed in the past week.
Provide a way to undo a command.
Minimal: the ability to undo the most recent command.
Provide in-App guidance to users.
Minimal: add a command to access a help page.
Other ideas:
Make the command syntax more flexible.
Minimal: provide shorter aliases for keywords e.g., t
can be shorter alias for todo
.
Other ideas:
Support managing info about contacts e.g., details of friends
Support managing info about small snippets of textual information the user wants to record e.g., one's own waist size, a name of a movie that the user wants to remember
Support managing info about expenses e.g., the amounts spent on food, books, transport, etc.
Support keeping records of loans given/taken e.g., money lent/owed to colleagues/friends
Support recording info about places e.g., info about restaurants visited, for future reference
Provide the ability to learn/memorize things e.g., learn vocabulary, answers to questions
Support managing info about clients e.g., for an insurance agent to keep track of clients