Overview
CardiBuddy is a desktop flashcard application made with NUS Computing students in mind, and is a useful study aid. The user interacts with it using a CLI, and it has a GUI created with JavaFX. CardiBuddy is written in Java, and has about 10 kLoC.
Summary of contributions
-
Major enhancement: Test Feature (the ability to start a test session on selected flashcards)
-
This feature allows the user to test themselves on their subject content by:
-
1. Fetching the flashcards of the deck at the user’s specified index and displaying them question by question.
-
2. Adding flashcards back into the test session if they got it wrong (retesting)
-
3. Marking the user’s answer, and showing them their result (Right or Wrong).
-
4. Storing the test results for each flashcard (number of tries for this flashcard, whether this flashcard was answered correctly / wrongly / was skipped) to generate statistics for the user to view at the end of each test.
-
5. Giving users the ability to force their initially marked wrong answers to be marked as correct, even if those answers differ from the flashcard’s stored answer. (force correct)
-
6. Giving users the ability to skip questions when needed. (skipping)
-
7. Giving users the ability to quit the ongoing test session halfway.
-
-
Justification:
-
This feature improves the product significantly - a flashcard application can not be without a testing feature. In addition, this feature provides enhancements on top of basic testing - such as
retesting
,skipping
and the ability toforce
correct answers. -
Retesting
forces the student to revisit the questions they answered wrongly again, and the question will stop being retested only if the user finally manages to answer it correctly. This drilling and increased exposure to questions the user is unsure of will help him or her get more familiar with the concept being tested. -
Skipping
andforce
correcting provides great flexibility in how the user chooses to answer questions, and allows for paraphrasing of answers to boost information retention. -
Quitting
the test session halfway hands the power over to the user to decide when to stop the test session. This lets the user have greater control over their revision, and saves them the time needed to complete the test session in its entirety, if they have decided that they are sufficiently prepared.
-
-
Highlights:
-
This enhancement is a major overhaul to the application, and required an in-depth analysis of design alternatives.
-
All of the classes used for the test feature were not provided by the stock AddressBook3 application, but had to be created from scratch.
-
The implementation was challenging as it required deep analysis of the application in order to figure out how to replace the existing JavaFX scene with the test session.
-
In addition, the test session required tight integration with other aspects of the application such as Flashcards and Decks, and constant communication and clarification with the team was required.
-
-
-
Minor enhancement: Created Java and FXML files for flashcards and decks as part of the Ui component.
-
Code contributed: [Functional code and Test code Written]
-
Other contributions:
-
Documentation:
-
Enhanced the developer’s guide, and wrote many of the common sections in the developer’s guide.
-
Modified existing class diagrams in the developer’s guide to adapt to our enhancements on the existing code base.
-
-
Community:
-
Reported bugs and suggestions for other teams in the class (examples: here)
-
-
Contributions to the User Guide
Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users. |
Testing
Overview
Of course, you did not create all those decks and flashcards just so you can admire them! It’s time to get your revision on. Start a test session
for a deck to begin testing yourself!
A test session
works just like how flashcard testing works in real life - You look at the question, think of the answer, and 'flip' the card around to see if your answer matches the one on the flashcard.
The difference here is that you do not need to manually keep track of how many flashcards you got right and wrong — CardiBuddy does all that for you!
In addition, you will also get to see a summary of how you’ve done at the end of your test session
.
Retesting
A test session
in CardiBuddy is special - it includes a retesting feature to make sure you know your content well.
When you answer a flashcard’s question wrongly, you will encounter it again later on in the same test session
. There is no need to do this manually - CardiBuddy does this for you too.
Hence if you keep getting a question wrong, a test session
can go on and on forever - unless you finally get it right, or you manually quit the test session
!
Starting a test session for a deck: test INDEX
To start your test session
, replace INDEX
with the index number of the deck you wish to test. This number will be to the left of the title of your deck, when you are viewing all your decks as a list.
What this command does:
-
A test session will immediately replace the normal deck and flashcard list view.
-
The first question of the test session will be shown to you.
Example Usage:
-
test 1
Creates a test session for the 1st deck.
To answer the question: ans YOUR_ANSWER
Replace YOUR ANSWER
with your answer to the displayed question.
What this command does:
-
Submits your answer, and checks your answer against the flashcard’s stored answer
-
Displays the result of your answer (CORRECT or WRONG)
-
Displays your answer and the flashcard’s answer
Example Usage:
-
ans CardiBuddy
To answer the question: "What is the name of this application?"
Don’t want to answer? Skip a question with: skip
What this command does:
-
If you already know the answer to the question, and don’t want to waste your time answering it, just type
skip
to go to the next question. -
Your skipped flashcard will not impact your overall test score, and CardiBuddy will merely remove it from your current test session.
Note:
-
You can use this command if either:
-
You have not answered the question.
-
You have answered the question, but you got it wrong.
-
-
CardiBuddy will not let you use
skip
if you have already gotten that question correct.
To force your wrong answer to be marked as correct: force
What this command does:
-
CardiBuddy’s uses automated marking to mark your answers. It takes your answer word for word when checking against the model answer stored in your flashcard.
-
If your answer differs from the model answer, it will be marked as wrong.
-
After submitting your answer, you will get to see the model answer and your answer, for you to compare them.
-
If you feel that your answer still meets the question’s requirements, you can
force
your answer to be marked as correct.
To go to the next question: next
What this command does:
-
After submitting your answer, type
next
to go to the next question (if there are any left to test).
Note:
-
You can only type
next
once you have submitted your answer.
Quit the test session halfway: quit
What this command does:
-
Allows you to quit the current test session even before it is completed.
Contributions to the Developer Guide
Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project. |
LogicToUiManager
This class serves as a bridge between relevant Command
classes and the Ui
, for use cases that do not update the ObservableList
. It calls specific methods in the MainWindow
class to modify the display to the user according to the Command
executed.
The LogicToUiManager
object is created upon startup in the MainApp class, and there can exist only one instance of it throughout the use of CardiBuddy.
Commands that make use of LogicToUiManager
:
-
OpenCommand
-
AddCommand
-
DeleteDeckCommand
-
DeleteCardCommand
-
TestCommand
-
AnswerCommand
-
NextCommand
-
QuitCommand
-
SkipCommand
-
SearchCardCommand
-
StatisticsCommand
-
ListCommand
The following sequence diagram illustrates how the LogicToUiManager
can be used to modify the MainWindow
, when CardiBuddy needs to display the flashcard question to the user during a Test Session
. More details on Test Session
in the section: [test-session].
This diagram is also an extension of the sequence diagram found in that section.
Test feature
Design
A flashcard application is not complete without the ability to test oneself.
Model Component
The following classes can be found inside cardibuddy/model/testsession.
The test feature revolves around 2 classes: TestSession
and TestResult
.
TestSession
stores the tested deck, retrieves the questions to be tested, acts according to the user’s commands and manages the test queue.
TestResult
stores the Result
(explained below) of each individual test on a flashcard. That is, whether the flashcard was answered wrongly, correctly, or was skipped. Result
is an enums class to store these 3 outcomes.
Another enums class used is AnswerType
which contains 3 answering options to display to the user - True/False, MCQ or Short Answer.
To ensure good design practice, Test Session
is not exposed to the other classes, but is instead called using the ModelManager
.
The following figure is a more focused class diagram for the cardibuddy/model/testsession package, and displays important methods and fields used.
Click here to view the full class diagram for the Model
component, to see all the classes within Model
interact.
Logic Component
The test feature makes use of a suite of Command
classes exclusive to a TestSession
. These Command
classes are part of the Logic component of CardiBuddy, and can be found within the cardibuddy/logic/testsession package.
These commands allow the user to perform the following during a test session:
-
The user will enter
test INDEX
to start the test session for the deck at theINDEX
. -
The user will enter
ans
followed by their answer to the question. -
The user can use the
next
command to view the next question. -
The user can choose to
skip
questions -
The user can choose to
quit
the session halfway -
The user can choose to
force
correct their answer if they wish to manually mark their answer as correct.
The above commands can only be triggered when certain conditions are met. The following table provides a summary of all the Command
classes related to the test feature, as well as the conditions for their execution and exceptions thrown when these conditions are not met.
Command Class | Corresponding user input | Description | Conditions | Exceptions Thrown |
---|---|---|---|---|
TestCommand |
|
Creates a |
- |
EmptyDeckException |
AnswerCommand |
|
Submits the user’s answer to the |
The user has not already submitted an answer to the displayed question. The answer submitted must be comply with the question type (True False, MCQ, or Short Answer) |
AlreadyAnsweredException, IncorrectAnswerFormatException |
NextCommand |
|
Displays the next question. |
The user must already have answered the question. |
UnansweredQuestionException |
SkipCommand |
|
Skips the current question. Does not require the user to submit an answer. |
The user must not have submitted a correct answer. |
AlreadyCorrectException |
QuitCommand |
|
Quits the test session. |
- |
- |
ForceCommand |
|
Forces CardiBuddy to mark the user’s submitted answer as correct. |
The user must have submitted an incorrect answer. |
UnansweredQuestionException, AlreadyCorrectException |
Using the test feature
Starting a Test Session
Users can start a TestSession with a chosen Deck
:
-
The
index
of the deck will be provided by the user and parsed by Cardi Buddy. ATestSession
object containing the indicatedDeck
is created. -
The
TestSession
object creates a HashMap namedtestResults
that contains<Flashcard, TestResult>
for easy access to the testing history.
The following is a UML Sequence Diagram of how a TestSession
object is created when the test INDEX
command is called:
Other commands included in the Test Feature
Aside from TestCommand
which is called to create the TestSession
, there are specific commands that can be used only when a TestSession is running. These commands have certain conditions that must be met before they can be executed. Otherwise, they will throw a CommandException
.
For example, other application-wide commands, such as add deck
and delete card
will not be allowed to be executed during the TestSession.
The following activity diagrams describe the logic flow.
Note the following terminology used in the activity diagrams:
-
tr
stands for aTestResult
object -
testResults
stands for aHashMap<Flashcard, TestResult>
object stored in theTestSession
object -
testQueue
is aLinkedList<Flashcard>
that stores the queue of flashcards to be tested.
For more descriptive use case scenarios from a user’s perspective, please take a look at Use Cases.
Design considerations
Aspect: Data structure for the test queue
-
Alternative 1
-
Use an ArrayList to store the flashcards in the test queue.
-
Pros:
-
Makes use of the current data structure used to store flashcards in a list.
-
Easy retrieval of flashcards at indices.
-
Easy iteration of the flashcard list.
-
-
Cons:
-
Possible difficulties in designing how flashcards should be retested.
-
It is possible that we create a large ArrayList, and split it such that the first half is used for flashcards that have not been tested, and the second half be used for flashcards that are going to be retested.
-
However, this approach is unnecessarily complicated, and uses excessive memory space.
-
In addition, it is still difficult to check if flashcards have been tested before, which is part of our feature which counts the number of times a flashcard has been attempted.
-
-
Alternative 2 (current choice)
-
Use a LinkedList to store the flashcards in the test queue.
-
Pros:
-
Easy insertion and removal of flashcards from the front and back of the queue, which is the main driver behind a test session.
-
-
Cons:
-
Difficult to retrieve flashcards at indices, and check if a flashcard has been visited before
-
In addition, other features of CardiBuddy require the easy retrieval of flashcards such as the get(index) method offered by ArrayList.
-
-
Why we went with this:
-
Logically, a test session will not be used as often as the other commands that entail retrieval of elements at a specific index, such as the
edit
command. -
There may be some overhead in converting the ArrayList used to a LinkedList, but our tests have showed minimal lag in starting a test session.
-
-
Workarounds:
-
To still retain the ability to check if a flashcard has been visited before, we use a separate HashMap data structure that makes use of flashcards that have been visited before as keys.
-
-
A HashMap will also allow us to link a flashcard to a specific TestResult, and modify it as needed (such as when a user calls force correct on the flashcard).
-
Aspect: How to store the results of each individual test on a flashcard
-
Alternative 1
-
Use a
Result
enums to indicate if the question was correct, wrong or skipped-
Pros:
-
An enums class improves code readability, and ensures that there are only 3 possible results linked to each flashcard.
-
-
Cons:
-
Too simplistic and does not give room for further enhancements as described below.
-
-
-
Alternative 2 (current choice)
-
Use a custom
TestResult
class that stores the user answer, as well as the model flashcard answer-
Pros:
-
Provides room for further customisation, such as recording the number of attempts on the flashcard, which alternative 1 was unable to achieve.
-
More Object-Oriented Design, and keeps
TestSession
from getting too cluttered.
-
-
Cons:
-
Higher chance for error as more code and methods needed to be written.
-
-
Aspect: When to replace the current
variable holding the latest flashcard that was tested
-
Alternative 1
-
Move on to the next question, hence replacing
current
, as soon as the user submits their answer.-
Pros:
-
Simple and easy to implement
-
-
Cons:
-
This would have been fine in the initial stages, but would not work after further enhancements (
skip
,force
) were added. -
The 2 mentioned enhancements require modifying of the
testResults
HashMap, and hence require the flashcard they are being used on as a key to retrieve and modify the TestResult.
-
-
-
Alternative 2 (current choice)
-
Only replace
current
with the next flashcard whennext
orskip
is used.-
Pros:
-
These 2 commands are the ones that trigger the displaying of the next question in the queue to the user.
-
This ensures that should there be a need to retrieve the current flashcard, such as in modifying the
testResults
HashMap as well as checking the flashcard’sCardType
(image or normal) and getting itsAnswerType
.
-
-
Cons:
-
This complicates the code, and may possibly be difficult to understand for another developer.
-
-
Workarounds:
-
Do our best to document the test feature in this Developer’s Guide, and supplement it with activity diagrams and other explanations to help the reader better understand the workings of this feature. == User Stories
-
-
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
|
new user |
see usage instructions |
refer to instructions when I forget how to use CardiBuddy |
|
student currently taking cs2105 |
edit my flashcards |
change or add extra information whenever I learn something new |
|
student practicing for my finals |
create test sessions |
repeatedly test myself on the same content |
|
student studying for finals |
see the flashcards that I got correct during test sessions |
know what content I am more familiar with |
|
student studying for finals |
test flashcards that I got wrong more often during test sessions |
better remember unfamiliar content |
|
student taking many modules |
create new decks to contain my flashcards |
organise my notes and modules |
|
student who is very busy |
easily search for a deck that I want to access |
more efficient with my time |
|
student who likes to keep things organised |
delete decks of the modules that I am no longer taking |
be more organised |
|
student with many content-heavy modules |
easily search for any flashcards that are relevant to my modules |
more efficient with my time |
|
student |
revisit previous test sessions |
continue my revision |
|
student |
set priority levels for the flashcards I am less familiar with |
it will appear more often during future test sessions |
|
student |
tag flashcards with different topics |
filter and revise the topics that I am less familiar with |
|
student taking timed examinations |
time myself during a test session |
better prepared to think under timed conditions |
|
student who likes designing and aesthetics |
customise the colours and fonts of the flashcards |
tweak the theme to my preferences |
|
student who owns multiple devices |
access flashcards on all my devices |
revise them while travelling |
|
student who receives flashcard images from her friends |
drag and drop the images into the application |
conveniently create new flashcards |
|
student with short attention span |
play memory games in the application |
remember my key concepts better |
|
competitive student |
graded on a bell-curve with other Computer Science students who are using the same application |
see how well I have revised compared to the rest |
|
student |
edit other people’s decks |
fill in any gaps in my knowledge |
|
student taking modules with other friends |
collaborate on decks with other users |
help each other revise the content |
|
student who likes to store content to study on her phone |
convert the flashcards to images |
so that I can refer to them easily |
|
student who likes to study with her friends |
send my friends flashcards that I created |
share my flashcards with them |
|
student who needs incentive |
earn rewards |
will be motivated to use the flashcards more |
|
student with a short attention span |
add animations to my flashcards |
remain entertained |
Appendix A: Use Cases
(For all use cases below, the System is the CardiBuddy
and the Actor is the user
, unless specified otherwise)
Test Sessions
Use case: Starting a test session
MSS
-
User requests to start a test session with a chosen deck.
-
CardiBuddy displays the test session page to the user, with the first question displayed.
-
CardiBuddy awaits the user’s answer.
Use case ends.
Extensions
-
1a. The given index is invalid
-
i. CardiBuddy shows an error message
-
ii. Use case resumes at step 1.
-
-
2a. The deck is empty
-
i. Use case ends.
-
Use case: Submitting an answer
MSS
-
User submits their answer to a question not tested before.
-
CardiBuddy gets the result of the user’s answer. The user answered the question correctly.
-
CardiBuddy creates a new record for this flashcard to save this correct result.
-
CardiBuddy displays the result to the user.
Use case ends.
Inclusions
-
1a. The current flashcard has been answered before.
-
i. CardiBuddy modifies its records by increasing the number of tries logged for this flashcard.
-
ii. Use case resumes at step 3.
-
-
2a. The user got the question wrong.
-
i. CardiBuddy creates a new record for this flashcard to save this wrong result.
-
ii. CardiBuddy appends this flashcard to the back of the queue for retesting later.
-
iii. Use case resumes at step 4.
-
Use case: Skipping a question
MSS
-
User requests to skip the current question.
-
CardiBuddy modifies its records to show that this flashcard was skipped
-
CardiBuddy removes the next flashcard in the queue.
-
CardiBuddy displays the question on this flashcard to the user.
Use case ends.
Extensions
-
1a. The user has already answered this question correctly
-
i. CardiBuddy shows an error message and prompts user to type 'next' instead
-
ii. Use case ends.
-
Inclusions
-
1a. The user has already answered this question wrongly
-
i. CardiBuddy removes this flashcard, that was set to be retested, from the back of the queue
-
ii. Use case resumes at step 2.
-
Use case: Forcing a wrong answer to be marked correct
MSS
-
User requests to force their answer to be marked as correct
-
CardiBuddy acknowledges the user’s request and changes the recorded result for this flashcard + Use case ends.
Extensions
-
1a. The user has not answered the question yet
-
i. CardiBuddy shows an error message and tells the user to answer the question first, or skip it
-
ii. Use case ends.
-
-
1a. The user is trying to force correct their already correct answer
-
i. CardiBuddy shows an error message and prompts the user to type 'next'
-
ii. Use case ends.
-
Use case: Going to the next question
MSS
-
User requests to go to the next question.
-
CardiBuddy removes the next flashcard in the queue and displays its question to the user.
Use case ends.
Inclusions
-
2a. There are no more flashcards in the queue
-
i. CardiBuddy ends the test session, and returns the user to the home page
-
ii. Use case ends.
-
Extensions
-
1a. The user has not answered the question yet
-
i. CardiBuddy shows an error message and prompts the user to answer the question or skip it.
-
ii. Use case ends. == Product Scope Target users: NUS School of Computing students
-
Target user profile:
-
enrolled in content-heavy modules in university
-
has a need for an effective way to revise and memorise content
-
values efficiency
-
prefer desktop apps over other types
-
able to type quickly
-
generally prefers typing over mouse input
-
is reasonably comfortable using CLI apps
Value proposition:
-
Time efficient
-
It is easier for fast typers to add and delete flashcards
-
Unlike regular GUI apps in the market, minimal navigation and clicking is required
-
Faster loading time for CLI applications
-
-
No steep learning curve
-
Command words are intuitive and uncomplicated
-
Easy for computing students to learn and remember
-
-
Retests cards
-
More tests for flashcards that the student got wrong
-
-
Flexible answering
-
Students can paraphrase their answers, and manually evaluate if their answers are correct
-
No need for word-for-word answers
-
Accommodates different module types and scenarios eg. having to describe a situation, or a diagram
-
Paraphrasing is also a much more effective way to learn, compared to rote memorisation == Product Survey
-
Quizlet
Author: Andrew Sutherland
Pros:
-
User can create an account
-
Clean user interface
-
Ability to search for decks created by other users
-
Ability to turn flashcard questions into 3 different kinds of questions: True and False, MCQ and short answer
-
3 different ways to test self: Test, Write and Swipe/Flip
-
Ability to play a timed matching game to match questions to their answers
-
"Don’t know" option if the user does not know the answer to the question.
Cons:
-
Confusing options for tests: "write", "test" and "swipe/flip"
-
Both "write" and "test" tests the user on flashcard content.
-
However, "write" allows the user to force correct on the flashcard while "test" only allows the user to skip the question.
-
Hence answers need to be written word for word to be marked as correct when using "test"
-
The "swipe/flip" test option is not displayed together with the write and test options, and user has to navigate around before stumbling onto it.
-
These similar options may overwhelm the user with too much choice.
-
Naming of the options are also not clear (eg. "write")
-
-
-
Scrolling view of flashcards at the end of test sessions, instead of a list view of the cards and their outcomes.
-
Difficult to add a new flashcard to an existing deck
-
Had to explore many options before finding a "…" button at the top right hand corner, which displayed a dropdown list of options for the set. User has to select edit set, before being able to
-
-
More confusing naming
-
Statistics (not seen, familiar, mastered for flashcards are nested under the option "Learn" == Non Functional Requirements
-
Should work on any mainstream OS as long as it has Java
11
or above installed. -
Should be able to hold up to 100 decks without a noticeable sluggishness in performance for typical usage.
-
Each deck should be able to hold up to 100 flashcards without a noticeable sluggishness in performance for typical usage.
-
A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
-
-