1. About the Project
My team and I were tasked with morphing a basic commandline interface addressbook application(AB4) for our software engineering project. We decided to morph the application into a Flashcard management application called TopDeck
TopDeck is a user-friendly flashcard management application that aims to help users better memorise any content that they desire. The main functionality of the application include managing a list of decks, managing the cards within each deck and having study sessions. Users can use it to learn a language, remember a math formula or simply recall an answer to a question.
I was in-charge of the card’s management feature within the application and these include creating, reading, updating and deleting (CRUD) a card within a deck as well as searching for cards that the user is interested in. The following sections illustrate these enhancements as well as the relevant sections that I have included in the user and developer guides.
2. Glossary
The following symbols are used throughout the application and represent the following:
NOTE |
CAUTION |
3. Summary of Contributions
This section shows a summary of my coding, documentation, and other helpful contributions to the team project.
Enhancement added: I added the ability for users to add, delete and edit cards. Along with the usual CRUD operation, I also added a find and clear feature for the cards.
-
Justification: A user should be able to modify a deck to customize the study session that the user will experience. A find feature will help the user to locate the specific card especially when they want to recall the question or answer to the specific question.
-
Highlights: The CRUD operation has to work with the existing commands and data structure in AB4. This was challenging as the
Undo
andRedo
methods in the original application leverages on the immutability of the data structure. Also, our application maintains a state object which the UI is dependent on. As such, there is also a need to ensure both the state of the application and the model is consistent with each other after every command. -
Credits: The edit command has an auto-complete feature which was implemented by my teammate Wei Heng.
Code contributed:
Other contributions:
Project management:
-
There were a total of 4 milestones, I managed the milestone tracking through out the whole project through the issue tracker on GitHub.
Enhancements to existing feature:
Community:
4. Contributions to the User Guide
We had to update the original User Guide with new instructions for the different enhancements implemented. The following is an extract from TopDeck User Guide that I have written.
(Start of extract)
4.1. Cards View
These commands are only available in cards view.
In this section, the active deck is the deck used in the open
command.
4.1.1. Adding a card to the active deck: add
Format: add q/QUESTION a/ANSWER [t/TAG]
Outcome: Creates a new card with question and answers and adds it to the current deck.
Example: add q/Hello a/World t/TopDeckSample
Below is an example of what the user should see upon the execution of the command:
Before:
After:
4.1.2. Editing a card in the active deck: edit
Format: edit INDEX q/QUESTION a/ANSWER [t/TAG]
Outcome: Edits the text of the card at INDEX
.
Example: edit 1 q/Edit Hello a/World t/Editted
Auto-Complete: Instead of typing the whole command,
TopDeck also provides an auto-complete feature for the edit
command.
Users need only type edit INDEX
and TopDeck will fill up the commandline
for the user to edit accordingly.
4.1.3. Finding a card in the active deck by name: find
Format: find KEYWORD [KEYWORD]…
Search for phrases: TopDeck provides the user the ability to search for
specific question by searching for a whole phrase instead of only individual words.
This is done by putting "
around KEYWORD
.
The find command searches all KEYWORD
between 2 "
and so there should not be any "
character in KEYWORD
.
Searching using phrases only searches the question.
Outcome: Lists all cards within the current deck containing KEYWORD
in its text.
find will only search for full-matching words. For e.g. Animals will not be found if
animal is used to search for it.
|
The entire phrase inside " will be matched word for word. For example, find "Is there a question"
will display the questions with the entire phrase Is there a question and the question
Is there a question? will not be matched due to the extra ?
|
Example:
-
find Singapore
Below is the result of executing this command:
(End of extract)
5. Contributions to the Developer Guide
The following section is an extract of my additions to TopDeck Developer Guide.
(Start of extract)
5.1. Card management
5.1.1. Current implementation
Card management is currently facilitated by Model
which implements the following operations:
-
hasCard(Card card, Deck deck)
-
addCard(Card card, Deck deck)
-
removeCard(Card target, Deck deck)
-
editCard(Card newCard, Deck deck)
The CRUD operations are exposed in the Model interface as Model#addCard(Card card, Deck deck)
,
Model#deleteCard(Card target, Deck deck)
and Model#setCard(Card target, Card newCard, Deck deck)
.
For each operation, there are 2 objects that need to be updated namely, VersionedTopDeck
and CardsView
.
Each CRUD operation called by `ModelManager`can be broken down into the following steps:
Here is a code snippet for VersionedTopDeck#addCard(Card newCard, Deck deck)
which shows the sequence
of functions carried out and returns the newly edited deck to ModelManager
:
public Deck addCard(Card card, Deck activeDeck) throws DuplicateCardException, DeckNotFoundException { requireAllNonNull(card, activeDeck); if (!decks.contains(activeDeck)) { throw new DeckNotFoundException(); } if (activeDeck.hasCard(card)) { throw new DuplicateCardException(); } Deck editedDeck = new Deck(activeDeck); editedDeck.addCard(card); decks.setDeck(activeDeck, editedDeck); . . . return editedDeck; }
All other CRUD operations works similarly. Instead of VersionedTopDeck.addCard(Card card, Deck activeDeck) ,
VersionedTopDeck.deleteCard(Card target, Deck activeDeck) or
VersionedTopDeck.setCard(Card target, Card newCard, Deck activeDeck) is called.
|
Given below is an example usage scenario of how the add operation works and how it interacts with Undo/Redo:
Step 1. The user starts up the application and is in the DecksView
. The user then
executes the open 1
command to open the first deck(D1 in the figure). This should change the
ViewState
in the ModelManager
from DeckView
to CardsView
and causes
CardsView.activeDeck
to point to the first deck as per figure 4.3.2. For more information, refer to
the Deck feature.
Step 2. The user executes add q/question a/answer
to add the new card into the current deck.
The add
command is parsed and calls Model#addCard(Card card, Deck deck)
.
VersionedTopDeck(Card newCard, Deck deck)
is then called. D3 which is a copy
of D1 is created and the new card is added to D3. VersionedTopDeck
is then updated
as per figure 4.3.3 by calling UniqueDeckList.setDeck(Deck target, Deck editedDeck)
.
Step 3. Next, the CardsView is updated creating a new CardsView
that points to D3
as in figure 4.3.4
Step 4. Once that is done, the ModelManager.filteredItems
list and the UI is being updated to
reflect the change.
Below is a sequence diagram to illustrate the sequence of activities upon calling
Model#addCard(Card card, Deck deck)
:
5.1.2. Design considerations
Aspect: Data structure of cards
-
Alternative 1(current choice): Have a list of cards within each deck
-
Pros: Allows for decks features such as import and export. Also, any search operation is done within the deck only.
-
Cons: There is a need to implement an extra
Deck
data structure and makes the model more complicated.
-
-
Alternative 2(current choice): Have a global list of cards with tags.
-
Pros: Updating of UI will be easier as there is one global list only.
-
Cons: In order to study the cards, the application has to search through the global list to find the cards with the tags that we want to study. Organisation of cards will also be messy as the only form of organisation for cards is through tagging.
-
-
Reason for choice 1: Choice one was chosen as it would allow the user an extra layer of organisation(
Deck
andTag
) when managing cards.
Aspect: How CRUD operation should work
-
Alternative 1 (current choice): Recreate the CardViews after each operation
-
Pros: Leverages on the current implementation of
VersionTopDeck
making it easier to implement. -
Cons: There is a memory and operation overhead as a new
CardsView
is constantly being created. Also, there is a need to refresh the UI at every update as the UI needs to render the newCardsView
.
-
-
Alternative 2: Alter the card list in
CardsView
and the model upon each operation-
Pros: Only has to update the active Deck in CardsView and the model
-
Cons: As
CardsView.activeDeck
can only reference to one deck only, the current Undo/Redo feature will have to be re-implemented to store the previous commands and the object changed.
-
-
Reason for choice 1: Choice one was chosen in order to retain the Undo/Redo function and to leverage on the original architecture instead of changing it.
(End of extract)