PROJECT: Cardi Buddy


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 to force 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 and force 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:

  1. OpenCommand

  2. AddCommand

  3. DeleteDeckCommand

  4. DeleteCardCommand

  5. TestCommand

  6. AnswerCommand

  7. NextCommand

  8. QuitCommand

  9. SkipCommand

  10. SearchCardCommand

  11. StatisticsCommand

  12. 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.

LogicToUiSequenceDiagram
Figure 1. Sequence diagram showing how LogicToUiManager accesses the Ui to display a question during a test session.

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.

TestFocusClassDiagram
Figure 2. Class diagram for the test session package.
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 the INDEX.

  • 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.

Table 1. Summary of Test Feature Commands
Command Class Corresponding user input Description Conditions Exceptions Thrown

TestCommand

test INDEX

Creates a TestSession for the specified deck at that index.

-

EmptyDeckException

AnswerCommand

ans USER_ANSWER

Submits the user’s answer to the TestSession.

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

next

Displays the next question.

The user must already have answered the question.

UnansweredQuestionException

SkipCommand

skip

Skips the current question. Does not require the user to submit an answer.

The user must not have submitted a correct answer.

AlreadyCorrectException

QuitCommand

quit

Quits the test session.

-

-

ForceCommand

force

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. A TestSession object containing the indicated Deck is created.

  • The TestSession object creates a HashMap named testResults 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:

TestSequenceDiagram
Figure 3. A sequence diagram illustrating the logic flow when a TestSession is created. The first question in the provided deck will immediately be displayed.
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 a TestResult object

  • testResults stands for a HashMap<Flashcard, TestResult> object stored in the TestSession object

  • testQueue is a LinkedList<Flashcard> that stores the queue of flashcards to be tested.

TestSessionActivityDiagram
Figure 4. Overall activity diagram for the different use cases, extension cases omitted.

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 when next or skip 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’s CardType (image or normal) and getting its AnswerType.

    • 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

  1. User requests to start a test session with a chosen deck.

  2. CardiBuddy displays the test session page to the user, with the first question displayed.

  3. 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

  1. User submits their answer to a question not tested before.

  2. CardiBuddy gets the result of the user’s answer. The user answered the question correctly.

  3. CardiBuddy creates a new record for this flashcard to save this correct result.

  4. 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

  1. User requests to skip the current question.

  2. CardiBuddy modifies its records to show that this flashcard was skipped

  3. CardiBuddy removes the next flashcard in the queue.

  4. 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

  1. User requests to force their answer to be marked as correct

  2. 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

  1. User requests to go to the next question.

  2. 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:

  1. 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

  2. No steep learning curve

    • Command words are intuitive and uncomplicated

    • Easy for computing students to learn and remember

  3. Retests cards

    • More tests for flashcards that the student got wrong

  4. 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

      1. Should work on any mainstream OS as long as it has Java 11 or above installed.

      2. Should be able to hold up to 100 decks without a noticeable sluggishness in performance for typical usage.

      3. Each deck should be able to hold up to 100 flashcards without a noticeable sluggishness in performance for typical usage.

      4. 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.