Developer Guide for lesSON
Table of Contents
- Acknowledgements
- Setting up, getting started
- Design
- Implementation
- Documentation, logging, testing, configuration, dev-ops
- Appendix: Planned Enhancements
- Appendix: Effort
- Appendix: Requirements
- Appendix: Instructions for manual testing
Acknowledgements
- This project is a part of the se-education.org initiative. If you would like to contribute code to this project, see se-education.org for more info.
Setting up, getting started
Refer to the guide Setting up and getting started.
Design

.puml
files used to create diagrams in this document docs/diagrams
folder. Refer to the PlantUML Tutorial at se-edu/guides to learn how to create and edit diagrams.
Architecture
The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
Main components of the architecture
Main
(consisting of classes Main
and MainApp
) is in charge of the app launch and shut down.
- At app launch, it initializes the other components in the correct sequence, and connects them up with each other.
- At shut down, it shuts down the other components and invokes cleanup methods where necessary.
The bulk of the app’s work is done by the following four components:
-
UI
: The UI of the App. -
Logic
: The command executor. -
Model
: Holds the data of the App in memory. -
Storage
: Reads data from, and writes data to, the hard disk.
Commons
represents a collection of classes used by multiple other components.
How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete 1
.
Each of the four main components (also shown in the diagram above),
- defines its API in an
interface
with the same name as the Component. - implements its functionality using a concrete
{Component Name}Manager
class (which follows the corresponding APIinterface
mentioned in the previous point.
For example, the Logic
component defines its API in the Logic.java
interface and implements its functionality using the LogicManager.java
class which follows the Logic
interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component’s being coupled to the implementation of a component), as illustrated in the (partial) class diagram below.
The sections below give more details of each component.
UI component
The API of this component is specified in Ui.java
The UI consists of a MainWindow
that is made up of parts e.g.CommandBox
, ResultDisplay
, CardListPanel
, StatusBarFooter
etc. All these, including the MainWindow
, inherit from the abstract UiPart
class which captures the commonalities between classes that represent parts of the visible GUI.
The UI
component uses the JavaFx UI framework. The layout of these UI parts are defined in matching .fxml
files that are in the src/main/resources/view
folder. For example, the layout of the MainWindow
is specified in MainWindow.fxml
The UI
component,
- executes user commands using the
Logic
component. - listens for changes to
Model
data so that the UI can be updated with the modified data. - keeps a reference to the
Logic
component, because theUI
relies on theLogic
to execute commands. - depends on some classes in the
Model
component, as it displaysCard
object residing in theModel
. - answer of the Card created is hidden from the user when they browse the Deck
- user can scroll to see the different
Card
listed in lesSON
Logic component
API : Logic.java
Here’s a (partial) class diagram of the Logic
component:
The sequence diagram below illustrates the interactions within the Logic
component, taking execute("delete 1")
API call as an example.

DeleteCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
How the Logic
component works:
- When
Logic
is called upon to execute a command, it is passed to anDeckParser
object which in turn creates a parser that matches the command (e.g.,DeleteCommandParser
) and uses it to parse the command. - This results in a
Command
object (more precisely, an object of one of its subclasses e.g.,DeleteCommand
) which is executed by theLogicManager
. - The command can communicate with the
Model
when it is executed (e.g. to delete a card). - The result of the command execution is encapsulated as a
CommandResult
object which is returned back fromLogic
.
Here are the other classes in Logic
(omitted from the class diagram above) that are used for parsing a user command:
How the parsing works:
- When called upon to parse a user command, the
DeckParser
class creates anXYZCommandParser
(XYZ
is a placeholder for the specific command name e.g.,AddCommandParser
) which uses the other classes shown above to parse the user command and create aXYZCommand
object (e.g.,AddCommand
) which theDeckParser
returns back as aCommand
object. - All
XYZCommandParser
classes (e.g.,AddCommandParser
,DeleteCommandParser
, …) inherit from theParser
interface so that they can be treated similarly where possible e.g, during testing.
Model component
API : Model.java
The Model
component,
- stores the flashcard deck data i.e., all
Card
objects (which are contained in aUniqueCardList
object). - stores the currently ‘selected’
Card
objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiableObservableList<Card>
that can be ‘observed’ e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. - stores a
UserPref
object that represents the user’s preferences. This is exposed to the outside as aReadOnlyUserPref
objects. - does not depend on any of the other three components (as the
Model
represents data entities of the domain, they should make sense on their own without depending on other components)

Tag
list in the Deck
, which Card
references. This allows Deck
to only require one Tag
object per unique tag, instead of each Card
needing their own Tag
objects.
Storage component
API : Storage.java
The Storage
component,
- can save both deck data and user preference data in JSON format, and read them back into corresponding objects.
- inherits from both
DeckStorage
andUserPrefStorage
, which means it can be treated as either one (if only the functionality of only one is needed). - depends on some classes in the
Model
component (because theStorage
component’s job is to save/retrieve objects that belong to theModel
)
Common classes
Classes used by multiple components are in the seedu.address.commons
package.
Below is an example of the object diagram of how the cards are stored in the Deck
class
Implementation
This section describes some noteworthy details on how certain features are implemented.
Add Command
The add command can be found in the LogicManager
class. User input is first parsed into the DeckParser
class using the parseCommand
to validate if its add command with the specified fields and format.
The add command is exposed in the Model
interface as the Model#addCard
Below is the overview on the add command:
Here is the flow of how the add command is featured.
- User inputs the following valid input
add q/what does + mean in boolean algebra? a/it means OR.
- The command is parsed into the
DeckParser
to verify that it has the correct format and parameters - Add command is executed, and if there is no duplicate entry found in
DeckStorage
, a new flashcard with the corresponding data will be created - New generated flashcard is then stored in the
DeckStorage
Below is the sequence diagram for this flow:
Design Considerations
Aspect: Duplicate Entry Detection:
-
Alternative 1 (current choice): No restriction on case sensitivity and mark down syntax
- Pros: Increased flexibility on how users wish to create flashcards, up to user’s choice, duplicate entry is determined only by the question and the answer input.
- Cons: Might lead to duplicate entries of cards of similar content .
-
Alternative 2: Clean the user input to obtain their intended question and answer
- Pros: Reduces chances of duplicate cards in deck
- Cons: Increased developer time to create such filtering functionality with little benefit
Delete Command
The delete command can be found in the LogicManager
class. User input is first parsed into the DeckParser
class using the parseCommand
to validate if it is a valid delete command with the specified fields and format.
The delete command is exposed in the Model
interface as the Model#setCard
Below is the overview on the delete command:
Here is the flow of how the delete command is featured.
- User inputs the following valid input
delete 1
- The command is parsed into the
DeckParser
to verify that it has the correct format and parameter - Delete command is now executed. If the index is valid, when it is greater than 0 and a card exists at the specified index, the specified card is now deleted from view.
- The corresponding card is also deleted from storage.
Below is the sequence diagram for this flow:
Filtering by Tag
The list
command supports filtering the deck by tag by entering the relevant tag(s) in the command parameters. This allows the users to
view specific groups of cards under the same tag
, granting them more control over their study material.

list
command also provides support for filtering by question keywords. The implementation is largely the same as filtering by tag.
Implementation
Performing a list
command involves executing ListCommand
.
- This command is parsed by
ListCommandParser
. -
ListCommandParser#parse()
parses the user input to return aListCommand
object that will be executed.
Given below is an example usage of the list
command to filter the deck and how the filtering mechanism behaves at each step.
- Suppose the user has a deck containing some cards with the tag
CS2103T
. The user keys in this command to filter by theCS2103T
tag.list t/CS2103T
Note: At least one tag should be provided.
-
The
ListCommandParser
will execute to get the field and keyword pairs using theArgumentTokenizer
. This parses every parameter into a list ofPredicate<Card>
objects. The parser then returns aListCommand
object with the list of predicates. -
The
ListCommand#execute()
method is invoked by theLogicManager
. The list of predicates is combined into a singlePredicate<Card>
object. Then,ListCommand
callsModel#updateFilteredCardList()
with thePredicate<Card>
to update the filtered flashcard list with a new list, filtered by the tag entered. - Finally, the
ListCommand
creates aCommandResult
object that contains feedback and displays the filtered flashcard list to the user. This result is then returned to theLogicManager
. As a result, the deck will now display only the cards with theCS2103T
tag.
The sequence diagram below shows the process of filtering the deck with tags.

ListCommandParser
and ListCommand
should end at the destroy marker (X)
but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Design considerations:
Aspect: How list
executes with filter parameters:
-
Alternative 1 (current choice): Filter through the whole deck using the filter method on a stream of cards.
- Pros: Easy to implement.
- Cons:
- May have performance issues when Deck eventually gets too big.
- Inefficient if specific tag is a small fraction of Deck.
-
Alternative 2: Construct a 'mini-deck' for each tag.
- Pros: Quick search for all cards with specific tag.
- Cons:
- Will use more memory.
- Adding/Deleting/Editing cards will require modifications to 'mini-deck'.
Random Command
The random
command enables the user to practise with a random card from the deck.
It offers compatibility with the solve
and set
commands by making sure the index of the
randomly selected card is remembered for those commands.
Implementation
Performing a random
command involves executing RandomCommand
.
- This command does not have its own parser because it does not require any parameters.
- Hence, this command is directly executed by
LogicManager
- Suppose the user has a deck containing some cards. The user keys in this command to practise a random card.
random
- A new
RandomCommand
object is created byDeckParser
.Note: This is slightly different from other commands, as there is no need for parsing by its own parser because there are no additional parameters to be parsed for this command.
-
The
RandomCommand#execute()
method is invoked by theLogicManager
.RandomCommand
then callsModel#getFilteredCardList()
to get the deck list, so as to generate a random index. The random index is generated by callingRandomCommand#generateRandomIndex()
. This random index is saved in theModel
by callingModel#setRandomIndex()
. This is so that the index can be accessed later by commandssolve
andset
. - A random card is selected with the newly generated index, which is then used to return a
CommandResult
toLogicManager
. As a result, the randomly selected card’s question will be shown to the user to practise with.
The sequence diagram below shows the process of randomly selecting a card to practise.

RandomCommand
should end at the destroy marker (X)
but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Design considerations:
Aspect: How random command is parsed:
-
Alternative 1: Modify
PractiseCommand
andPractiseCommandParser
to accept anr
parameter to practise a random question- Pros: Similar command format with
solve
andset
, so it may be easier to use for some users. - Cons: Harder to manage codebase because
PractiseCommand
will have two different responsibilities (i.e. practising in order and randomly)
- Pros: Similar command format with
-
Alternative 2 (Current Choice): Implement a new command
random
instead of adding it as an option onpractise
- Pros:
- Easier to implement and manage code
- More extensible in the future if random needs to accept any parameters
- Cons: No significant cons
- Pros:
Markdown support feature
Implementation
The feature aims to support Markdown based language for inputs and renders the corresponding display (i.e. ** Bold ** will become Bold).
This provides users the freedom to adapt the content within the card, granting them more control over their study material. Users would be able to highlight more specific
part of the Answer
which would be the key concept tested in the exam.
Given below is an example usage of the Markdown support feature.
-
User creates a card.
-
User executes
add q/ What base is hexadecimal in? a/ Hexadecimal is in **Base 16**
-
AddCommandParser
will parse in the input and then, parse in the values collected in the multimap to aMarkdownParser
to create a newCard
. -
The
Card
is added to theModel
to be added to theDeck
. -
The
UI
renders theCard
with the relevant fields meant to be written in Markdown.
Design considerations:
Aspect: How Markdown support executes:
-
Alternative 1 : Use existing libraries that support Markdown using JavaFX.
- Pros: Easy to implement.
- Cons:
- Dependency on third party library.
- Increase application size
- Many features included in the library are redundant
-
Alternative 2 (Current Choice): Individually support each type of Markdown language by creating our own implementation for each syntax.
- Pros: Scope of support can be determined by developer.
- Cons:
- Time-consuming.
- Potential for Bugs
Finalised Implementation:
Settled on using alternative 2 as it allows us to be flexible on what Markdown Syntax we want to implement. We decided to implement bold, italic and underline since they are the most commonly used ones. This also greatly reduces the application file size.
Spaced Repetition Feature
Implementation
This features aim to implement a Spaced Repetition system to schedule cards based on the level of difficulty indicated by the user. In combination with the difficulty feature, Spaced Repetition determines when is the next recommended revision date for each flashcard, to make users give more of their attention to the difficult ones and practice it earlier, optimising learning.
Using the difficulty system, we can decide a nextPracticeDate
for the specified card based on the difficulty selected by the user.
This helps to remove the need to manually set nextPracticeDate
, and provides user with a more intuitive way to determine their nextPracticeDate
based on difficulty
.
This is also a key feature of the app, which allows for automatic scheduling of cards and removes it off the users hands.
Possible difficulty inputs: easy
, medium
, hard
Any wrong input will result in an error being flagged out
Given below is an example usage of the Spaced Repetition Feature.
-
Assuming the user has existing cards in lesson, with their own set of questions and answers. These questions are sorted by a due date
nextPracticeDate
. Cards also have a hidden field known aslastPracticeDate
. -
After the user uses the
practise
command andsolve
command, he uses theset
command to set how difficult he felt the card was when he was practising the card. -
After setting the difficulty, the system will calculate a new
nextPracticeDate
. Firstly, it applies a multiplier (based on difficulty: 3, 1.5, 0.5 for easy, medium, hard respectively) to the amount of time betweenlastPracticeDate
andnextPracticeDate
, obtaining a duration. This duration is then added to the currentnextPracticeDate
to calculate the newnextPracticeDate
. If there is no suitablelastPracticeDate
to use, then this calculation alternatively adds a base duration (of 4 hours) * multiplier tonextPracticeDate
. -
The card’s
nextPracticeDate
andlastPracticeDate
is then updated with the new fields. -
The card is automatically sorted in the list according to the new
nextPracticeDate
and the more difficult cards will now appear earlier when using thepractice
command without index now.
Data Transfer Functionality
Both export and import features are not to be mistaken as a Command as it is meant to be used before the user decides to use our application for revision purposes.
Export
We implemented an export functionality to allow our users to port over their data with ease.
The export button will allow users to access a copy of the deck.json
file and has a copy button function that allows
users to copy over their deck.json file with ease.
Design considerations:
Aspect: How can we showcase the data while preventing users from editing directly:
- We decided that showing a copy of the text found in
deck.json
will prevent the user from directly editingdeck.json
, and thus prevents any accidental erasure of the deck should the user tamper with it unknowningly.
Given below is an example usage of the Export Feature.
-
User generates cards according to their needs and produced a deck for revision
-
User wishes to share their deck with peers or online, and needs a fixed format to be used across all lesSON applications
-
User navigates to the menu bar at the top of the screen and presses on it.
-
The dropdown menu displays the export function, and it produces the text of the
deck.json
to be copied -
User proceeds to click on the copy data button, and it is copied to the users clipboard
Import
We implemented an import functionality to allow our users to port over their data with ease.
The Import button will allow users who have received the text from the Export function to transfer the deck of carss over, thereby effectively importing over the shared deck of cards generated by another user.
Design considerations:
Aspect: Ineffective way to modify state of deck from Import window :
-
Alternative 1 : Investigate more into how we can update the deck of cards from Import window
- Pros: Smoother user experience as the application stays running
- Cons: Requires more extensive testing and research
-
Alternative 2: Make the application restart so that it re-opens with the updated deck
- Pros: Saves a lot of time as the logic to do so hinges on pre-existing features to operate.
- Cons: User is forced to exit the application upon import, which might lead to a less than ideal user experience.
Given below is an example usage of the Import Feature.
-
User A has used lesSON and already a pre-existing deck of cards.
-
User A then clicks on the Export button (mentioned above).
-
User B receives the text from User A either via message, text or email.
-
User B opens lesSON and clicks on the menu button.
-
User B clicks on the Import menu button and copies and pastes the text received from A into the text field.
-
User B clicks on Import data button which will then import the data and closes the application
-
User B re-opens lesSON to see his new functional deck of cards.
[Proposed] Undo/redo feature
Proposed Implementation
The proposed undo/redo mechanism is facilitated by VersionedDeck
. It extends Deck
with an undo/redo history, stored internally as an deckStateList
and currentStatePointer
. Additionally, it implements the following operations:
-
VersionedDeck#commit()
Saves the current deck state in its history. -
VersionedDeck#undo()
Restores the previous deck state from its history. -
VersionedDeck#redo()
Restores a previously undone deck state from its history.
These operations are exposed in the Model
interface as Model#commitDeck()
, Model#undoDeck()
and Model#redoDeck()
respectively.
Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
-
The user launches the application for the first time. The
VersionedDeck
will be initialized with the initial deck state, and thecurrentStatePointer
pointing to that single deck state. -
The user executes
delete 5
command to delete the 5th card in the deck. Thedelete
command callsModel#commitDeck()
, causing the modified state of the deck after thedelete 5
command executes to be saved in thedeckStateList
, and thecurrentStatePointer
is shifted to the newly inserted deck state. -
The user executes
add q/What …
to add a new card. Theadd
command also callsModel#commitDeck()
, causing another modified deck state to be saved into thedeckStateList
.Note: If a command fails its execution, it will not call
Model#commitDeck()
, so the deck state will not be saved into thedeckStateList
.
-
The user now decides that adding the card was a mistake, and decides to undo that action by executing the
undo
command. Theundo
command will callModel#undoDeck()
, which will shift thecurrentStatePointer
once to the left, pointing it to the previous deck state, and restores the deck to that state.Note: If the
currentStatePointer
is at index 0, pointing to the initial Deck state, then there are no previous Deck states to restore. Theundo
command usesModel#canUndoDeck()
to check if this is the case. If so, it will return an error to the user rather than attempting to perform the undo.
The following sequence diagram shows how the undo operation works:
Note: The lifeline for
UndoCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The
redo
command does the opposite — it callsModel#redoDeck()
, which shifts thecurrentStatePointer
once to the right, pointing to the previously undone state, and restores the deck to that state.Note: If the
currentStatePointer
is at indexdeckStateList.size() - 1
, pointing to the latest deck state, then there are no undone Deck states to restore. Theredo
command usesModel#canRedoDeck()
to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
-
The user then decides to execute the command
list
. Commands that do not modify the deck, such aslist
, will usually not callModel#commitDeck()
,Model#undoDeck()
orModel#redoDeck()
. Thus, thedeckStateList
remains unchanged. -
The user executes
clear
, which callsModel#commitDeck()
. Since thecurrentStatePointer
is not pointing at the end of thedeckStateList
, all deck states after thecurrentStatePointer
will be purged. Reason: It no longer makes sense to redo theadd q/What …
command. This is the behavior that most modern desktop applications follow.
The following activity diagram summarizes what happens when a user executes a new command:
Design considerations:
Aspect: How undo & redo executes:
-
Alternative 1 (current choice): Saves the entire deck.
- Pros: Easy to implement.
- Cons: May have performance issues in terms of memory usage.
-
Alternative 2: Individual command knows how to undo/redo by
itself.
- Pros: Will use less memory (e.g. for
delete
, just save the card being deleted). - Cons: We must ensure that the implementation of each individual command are correct.
- Pros: Will use less memory (e.g. for
Documentation, logging, testing, configuration, dev-ops
Appendix: Planned Enhancements
- The current logic for adding and editing
tag
allows for duplicatetag
for a single flashcard.- Users that use the
edit
oradd
command with duplicatetags
in the command can create a flashcard with redundant tags for a single flashcard. - We plan to enforce uniqueness in the list of
tags
by using a Java Set data structure instead of a Java List data structure.
- Users that use the
- The current parser logic for
hint
does not support the use ofr
index.- Users that use
random
to practise a random question are unable to usehint r
to check the hint of the question. - We plan to allow
hint
command to acceptr
index to that it can show the user the hint of the randomly selected question.
- Users that use
- Current logic for Markdown syntax does not allow for the multiple Markdown syntax to be stacked for a single phrase.
- Users that want to create a bold and underlined phrase might try
<u>**WORD**</u>
. However, this does not result in the expected outcome “**WORD**” and cause unexpected styling in the DisplayView. - We plan to refine the parsing of Markdown syntax to ensure the parsing of syntax for a particular phrase checks for every syntax instead of the first valid syntax, so that user can apply more than 1 font styles to a part of the text.
- Users that want to create a bold and underlined phrase might try
Appendix: Effort
Project Overview
Our project, lesSON, emerged from the adaptation of AB3 code into a dynamic flashcard application. Users engage in a two-phase learning process, viewing flashcards initially and then practicing recall. The collaborative efforts of our 5-person team resulted in a feature-rich app encompassing CRUD operations, dual-phase learning, spaced repetition, and additional features like hints and goal-setting.
Project Challenges
Adapting existing code required meticulous modifications to align with the unique requirements of a flashcard app. The main differentiating design consideration was the transition from AB3, which was mainly an information hub, to lesSON which required a 2 stage design so that the user can create and practise cards with ease.
Development Effort
The development effort invested in lesSON covered various aspects, including feature implementation, refactoring, and quality assurance. The team dedicated substantial time to refine and optimize the codebase, ensuring a robust and user-friendly flashcard application. Additionally, the presence of the automated codecov bot ensured that the code we pushed was well covered and would flag out any possible flaws in our implementation that was not covered by automated testing.
Achievements
Noteworthy achievements include successful CRUD operations, dual-phase learning, spaced repetition, and additional user-centric features.
Comparison with AB3
lesSON differentiates itself from AB3 by introducing a more dynamic and engaging learning experience. The two-phase structure, combined with features like difficulty settings and prioritized card ordering, positions lesSON as a more advanced and versatile educational tool. We introduced the element of spaced repetition so that our users can benefit the most from the studying experience. Additionally, we also include an auto priority system that would place cards that required more attention at the very front so that users can practise them more often.
Conclusion
The successful transformation of AB3 into lesSON highlights the team’s adaptability and technical expertise. Overcoming challenges, especially during the refactoring phase, demonstrates our commitment to delivering a robust and innovative flashcard application. Despite the similar looking UI, much of the consideration and design implementation went towards brainstorming how the 2 stages were to be implemented such that they complement each other and were intuitive to the user.
Appendix: Requirements
Product scope
Target user profile:
- is a Computer Science University student in NUS
- wishes to excel in their studies
- requires a learning aid that enforces their understanding and memorisation of the content taught
- may take several courses at once and each course is expected to have multiple topics/concepts
- prefer desktop apps over other types
- can type fast
- prefers typing to mouse interactions
- is reasonably comfortable using CLI apps
- decently familiar with the idea of flashcards and their usages in an academic setting
Value proposition: For Computing students in University who struggle with memorisation and consolidation of knowledge, our app provides users the ability to create categorised flashcards to organise concepts taught to them fast. Optimised for CLI and users who type fast.
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 | create a new flashcard | start adding content |
* * * |
user | edit the content of an existing flashcard | update my study materials |
* * * |
user | delete a flashcard | remove irrelevant content |
* * * |
user | view a list of all my flashcards | quickly access my study materials |
* * * |
user | organise my flashcards with tags | manage my study materials efficiently |
* |
user | search for a specific flashcard | edit the card accordingly |
* * |
user | sort my flashcards by date created or modified | view them in an organised manner |
* |
user who learns better with pictures | add images to my flashcards | enhance my learning experience |
* * * |
user who wants to update my flashcards | modify answers to my flashcard | make sure that my content is up to date |
* * * |
user | practise with my flashcards | test my knowledge |
* * |
user | shuffle the order of my flashcards during practice | avoid memorising in a fixed sequence |
* * * |
user | mark a flashcard as “learnt” during practice | track my progress |
* |
user | see statistics on my practice sessions, such as the number of cards reviewed and the time spent | |
* * * |
user | tag my flashcards with course IDs and coursework | easily categorise them by subject |
* * * |
user | tag my flashcards with the type of concept (e.g., definitions, formulas, field) | filter them for specific study needs |
* * |
user | can change my tag colours | personalise my studying methods |
* * |
user | enable spaced repetition for my flashcards | optimise my memorization process |
* * |
user | adjust the spacing intervals for spaced repetition | personalise my learning experience |
* * |
diligent user | review flashcards due for repetition | reinforce my memory |
* * |
experienced user | format the text on my flashcards using Markdown or a similar markup language | create personalised rich content |
* |
experienced user | preview the formatted text on my flashcards | ensure it appears as intended |
* * |
picky user | customise the app’s colour scheme and interface | personalise my learning environment |
* * |
user | reset my progress and start fresh with my flashcards | can reattempt my studies |
* * |
user | export my flashcards to a file | back up my data or share it with others |
* * |
user | import flashcards from an external file | easily migrate or collaborate on study materials |
* * * |
user | access a user guide | learn how to use the app effectively |
* * |
user | receive notifications to remind me of my study sessions and flashcard reviews | |
* * |
user | set daily or weekly study goals | track my progress toward my learning objectives |
* |
user | provide feedback or report issues to the app developers | contribute to app improvement |
* |
multilingual user | input non-english characters | study in other languages |
Use cases
(For all use cases below, the System is lesSON
and the Actor is the user
, unless specified otherwise)
Use case: UC01 Creating a card
MSS:
- User inputs command to create a card, along with the necessary details.
- lesSON displays a success message.
- The answer generated is not visible to the user until card selected is practised.
Use case ends.
Extension:
- 1a. lesSON detects that the given parameters are invalid
- 1a1. lesSON displays an error message.
Use case ends.
- 1b. lesSON detects that the necessary parameters are missing
- 1b1. lesSON displays an error message.
Use case ends
- 1c. lesSON detects that any parameters input is empty (no input after prefix)
- 1c1. lesSON displays an error message.
Use case ends.
Use case: UC02 deleting a card
MSS:
- User displays all cards (UC04).
- User inputs command to delete a card, along with the index of the card.
- lesSON displays a success message.
Use case ends.
Extension:
- 1a. lesSON detects that the given index is invalid
- 1a1. lesSON displays an error message.
Use case ends.
Use case: UC03 filtering the card deck
MSS:
- User displays all cards (UC04).
- User inputs command to filter the cards, including the tags to filter the deck.
- lesSON displays the cards that fulfill the condition using the tags.
Use case ends.
Extension:
- 1a. lesSON detects the given parameters are invalid
- 1a1. lesSON displays an error message.
Use case ends.
Use case: UC04 displaying all cards
MSS:
- User inputs command to view all cards.
- lesSON displays all cards.
Use case ends.
Use case: UC05 editing a card
MSS:
- User displays all cards (UC04).
- User inputs command to edit a card, along with the necessary details.
- lesSON displays a success message.
Use case ends.
Extension:
- 1a. lesSON detects that the given parameters are invalid
- 1a1. lesSON displays a error message.
Use case ends.
Use case: UC06 practise a card
MSS:
- User displays all cards (UC04).
- User inputs command to practise a card with its index.
- lesSON displays the question of the specified card.
Use case ends.
Extension:
- 1a. lesSON detects that the given index is invalid
- 1a1. lesSON displays a error message.
Use case ends.
Use case: UC07 solve a card
MSS:
- User displays all cards (UC04).
- User inputs command to solve a card with its index.
- lesSON displays the question and the answer of the specified card.
Use case ends.
Extension:
- 1a. lesSON detects that the given index is invalid
- 1a1. lesSON displays a error message.
Use case ends.
Use case: UC08 set difficulty for a card
MSS:
- User displays all cards (UC04).
- User inputs command to set a difficulty of a card, by specifying its index and the difficulty.
- lesSON displays the question and the answer of the specified card.
Use case ends.
Extension:
- 1a. lesSON detects that the given parameters are invalid
- 1a1. lesSON displays a error message
Use case ends.
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 1000 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.
- User must be educated and willing to use flashcards to learn the content
- Display box should be able to show the user’s full input
Glossary
- Mainstream OS: Windows, Linux, Unix, OS-X
- Flashcard: A two-sided card containing a question and an answer
- Tag: A label used to categorise flashcards
- Deck: A series of cards that is stored in lesSON
- Index: The position of the card in the deck
- CLI: A text-based interface where you interact with the software by typing commands into a terminal or command prompt, providing more direct and precise control over the system.
- GUI: A user-friendly interface that allows you to interact with the software through visual elements like windows, icons, buttons, and menus, making it easy to navigate with a mouse and keyboard.
Appendix: Instructions for manual testing
Given below are instructions to test the app manually.

Launch and shutdown
-
Initial launch
-
Download the jar file and copy into an empty folder
-
Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
-
-
Saving window preferences
-
Resize the window to an optimum size. Move the window to a different location. Close the window.
-
Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-
-
Exiting the application
-
Press the exit button in the
File
menu button or enter theexit
command. -
Application window should close and exit as normal.
-
Adding a card
-
Adding a card with question and answer parameters.
-
Prerequisites: List all cards using the
list
command. Multiple cards in the list. -
Test case:
add q/What is the opcode for R-format instructions a/000000
Expected: Addition of card with its details shown in the result display. Card is added to deck. -
Test case:
add q/What is the opcode for R-format instructions
Expected: Card is not created, error message appears mentioning correct format to follow. -
Test case:
add q/What is the opcode for R-format instructions a/000000
add q/What is the opcode for R-format instructions a/000000
Expected: Duplicate card is detected, error message appears mentioning no duplicate cards allowed
-
Deleting a card
-
Deleting a card while all card are being shown
-
Prerequisites: List all cards using the
list
command. Multiple cards in the list. -
Test case:
delete 1
Expected: First card is deleted from the list. Details of the deleted card shown in the status message. -
Test case:
delete 0
Expected: No card is deleted. Error details shown in the status message. -
Other incorrect delete commands to try:
delete
,delete x
,...
(where x is larger than the list size)
Expected: Similar to previous.
-
Listing cards
- Listing all cards
- Prerequisites: List all cards using the
list
command. Multiple cards in the list. -
Test case:
list t/CS2100
Expected: All cards with the CS2100 tag is shown in the deck. -
Test case:
list q/What
Expected: All cards starting with What is shown in the deck. - Test case:
list potato
Expected: All cards in deck is shown, extraneous input is ignored.
- Prerequisites: List all cards using the
Editing a card
- Editing a card’s question
-
Prerequisite: A card which you wish to edit is already in the deck.
-
Test case:
edit 1 q/Question 1
Expected: Edits the first card’s question to be set as Question 1. -
Test case:
edit 1 q/
Expected: Blank input detected after parameter, error message appears. -
Other incorrect edit commands to try:
edit
,edit 1 x/
,...
(where x is other prefixes)
Expected: Similar to previous.
-
- Editing a card’s answer
-
Prerequisite: A card which you wish to edit is already in the deck.
-
Test case:
edit 1 a/Answer 1
Expected: Edits the first card’s Answer to be set as Answer 1. -
Test case:
edit 1 a/
Expected: Blank input detected after parameter, error message appears. -
Other incorrect edit commands to try:
edit
,edit 1 x/
,...
(where x is other prefixes)
Expected: Similar to previous.
-
- Editing a card’s tag
-
Prerequisite: A card which you wish to edit is already in the deck.
-
Test case:
edit 1 t/Tag 1
Expected: Edits the first card’s Tag to be set as Tag 1. -
Test case:
edit 1 t/
Expected: Removes the tag from the card. -
Other incorrect edit commands to try:
edit
,edit 1 x/
,...
(where x is other prefixes)
Expected: Error message appears.
-
- Editing a card’s hint
-
Prerequisite: A card which you wish to edit is already in the deck.
-
Test case:
edit 1 h/Hint 1
Expected: Edits the first card’s Tag to be set as Tag 1. -
Test case:
edit 1 h/
Expected: Blank input detected after parameter, error message appears. -
Other incorrect edit commands to try:
edit
,edit 1 x/
,...
(where x is other prefixes)
Expected: Similar to previous.
-
Practising a card
- Practising a card
-
Prerequisite: A card which you wish to practise is already in the deck.
-
Test case:
practise 1
Expected: Practises the first card in the deck. -
Test case:
practise 1 potato
Expected: Additional input detected after index, error message appears. -
Other incorrect practise commands to try:
practise
,practise 1 x/
,...
(where x is other prefixes)
Expected: Similar to previous.
-
Solving a card
-
Solving a card
- Prerequisites: List all cards using the
list
command. Multiple cards in the list. - Test case:
solve
Expected: The answer of the first card is displayed. - Test case:
solve 2
Expected: The answer of the second card is displayed. - Test case:
solve 0
Expected: No card is solved. Error details shown in the status message. - Other incorrect delete commands to try:
solve x
,...
(where x is larger than the list size or negative)
Expected: Similar to previous.
- Prerequisites: List all cards using the
Setting difficulty of a card
-
Setting difficulty of a card
- Prerequisites: List all cards using the
list
command. Multiple cards in the list. - Test case:
set d/easy
Expected: The difficulty of the first card is set to easy and new difficulty is displayed. The ‘due date’ of the card is changed to reflect the difficulty based on the spaced repetition system. - Test case:
set 2 d/medium
Expected: Similar to previous but difficulty is now medium and new ‘due date’ is later. - Test case:
set d/invalid
Expected: Difficulty is not set. Error details shown in the status message. - Test case:
set 0 d/hard
Expected: Difficulty is not set. Error details shown in the status message. - Other incorrect delete commands to try:
set x d/hard
,set d/y
,...
(where x is larger than the list size or negative and y is any other invalid difficulty)
Expected: Similar to previous.
- Prerequisites: List all cards using the
Setting a goal
-
Setting goal of a session
- Test case:
goal 1
Expected: Goal of the session is set to 1 and displayed in the goal box. - Test case:
goal invalid
Expected: Goal is not updated. Error details shown in the status message. - Test case:
goal 0
Expected: Goal is not updated. Error details shown in the status message. - Other incorrect delete commands to try:
goal
,goal x
,...
(where x is larger than the MAX_INTEGER or negative)
Expected: Similar to previous.
- Test case:
Choosing a random card
- Selecting a random card
-
Prerequisite: There are multiple cards shown in the deck.
-
Test case:
random
Expected: Randomly chooses a card in the deck and sets its index asr
-
Test case:
random x
Expected: Additional input detected after index, error message appears. -
Other incorrect random commands to try:
random
,random 1 x/
,...
(where x is other prefixes)
Expected: Similar to previous.
-
Clearing a deck
- Cleansing a deck of all cards
-
Prerequisite: There are multiple cards shown in the deck.
-
Test case:
clear
Expected: Removes all cards in the deck. -
Other incorrect random commands to try:
clearx
(where x is other prefixes)
Expected: Error message appears.
-
Getting help
-
Getting help from user guide
- Test case:
help
Expected: Help window pops up with the link to user guide. - Other incorrect random commands to try:
helpx
(where x is other prefixes)
Expected: Error message appears.
- Test case: