PROJECT: FlashSpeed

Overview

FlashSpeed is a text-based flashcard application which enables users to store virtual flashcards, categorize them within decks, and launch review sessions of cards within those decks. It is designed for university students who are learning a foreign language or reading a language module.

It was developed as a team project for the CS2103T Software Engineering module in the National University of Singapore (NUS). FlashSpeed was built on top of the AddressBook-Level3 project created by the SE-EDU initiative. FlashSpeed is written in Java and has a GUI created using JavaFX. Users interact with FlashSpeed mainly using textual commands.

Summary of contributions

My roles in this project include being the technical leader and in-charge of the User Guide. As technical leader my responsibilities include ensuring the establishment of the week’s tasks, adherence to the proper development workflow, and quality checks on pull requests.

  • Major enhancement: Added the ability to edit cards and edit using shortened commands.

    • What it does: Allows the user to perform the editing of card values using any one of three different command formats, where two of the formats are shortened forms (i.e. edit INDEX FRONT:BACK, edit INDEX :BACK, edit INDEX FRONT:).

    • Justification: This feature improves the product significantly because a user will be able to perform the editing of only the values they want to change, rather than having to retype the same value. This provides convenience and overall efficiency to the user. This functionality had the possibility to require a change in the entire logical chain but I decided that a reuse of existing functionality (e.g. add, delete, etc. to perform a Card replacement) would both reduce the possibility of logical bugs and code rewrite.

    • Highlights: This is the only command in the application which can take in multiple formats. The implementation of this feature required design considerations across the entire model of the application (e.g. overwrite values in the Card or do a full replacement with a new Card, where should the new Card interface with the Deck to retrieve the unchanged values if any, etc.) The edit functionality fulfilled its extended goals while being able to be treated as another standard command by the user and other developers.

  • Minor enhancement: Added the implementations for the functional units of the application, i.e. Cards, Decks, and its UniqueCardLists.

    • Highlights: These are the abstractions of data which makes FlashSpeed a flashcard application. They are built in such a way that developers of the higher level logic and model management can treat them as total black boxes. These are also the items which users will be interacting with mostly.

  • Code contributed: [Functional code] [Test code]

    • > 1.2k LoC

    • > 40 Pull Requests: PRs

  • Documentation contributed:

    • User Guide:

      • In-charge of document

      • Wrote or edited all sections either fully or partially

      • Reformatted the structure and layout for ease of readability and navigability (e.g. topic headings, section spacing, etc.)

      • Maintenance of document to be up-to-date with current application version

      • Added all tips and notes, command summary table, etc.

    • Developer Guide:

    • Others:

      • Wrote the content in the README and site home page which includes our product description, marketing blurb, and target users

  • Other contributions:

    • Project management:

      • Managed all releases v1.1 - v1.4 (6 releases) on GitHub

    • Enhancements to existing features:

      • Added functionality and methods in ModelManager which uses our Cards and Decks as functional units

    • Review/mentoring contributions:

    • Changes:

      • Morphed product site to be in line with our FlashSpeed product and branding

      • Morphed codebase to remove and replace all AddressBook-Level3 references to become FlashSpeed

    • Tools:

      • Set-up of Netlify

      • Set-up and maintenance of GitHub issue tracker

      • Maintenance of Travis according to project workflow

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.

Introduction

FlashSpeed is a text-based flashcard application specifically designed for university students who are learning a foreign language. University students often have hectic schedules. With this in mind, FlashSpeed was created to allow students to be able to study and revise foreign vocabulary on the fly. With a single command, you can start a quick study session on FlashSpeed whenever!

Keeping, flipping, and tracking physical flashcards can be a pain. FlashSpeed enhances the studying process by having virtual flashcards and a smarter review system. Users will be tested more frequently on flashcards that they had trouble memorizing previously. By using FlashSpeed, you will learn faster and remember for longer!

This guide will walk you through the many exciting features of FlashSpeed as well as give step-by-step instructions on how to use them. Helpful tips and notes are also provided!

We hope you enjoy using our app. Happy FlashSpeeding!

Language Support

FlashSpeed can support almost every popular language and their associated script. You can even use emojis in your cards! 😍

You can use FlashSpeed to study:

  • Japanese

  • Korean

  • French

  • Spanish

  • German

  • Hindi

  • Russian

  • …​and many more!

The display of the characters may be limited to your own operating systems’s language support. Please refer to your operating system’s manual or user guide to find out the languages and scripts supported.
Technical info: FlashSpeed, which is built with Java, supports the Unicode standard with UTF-16 character encoding for textual representation.

Library view

Even though the commands in this section are mainly library based, you can use them in both the Library view and Deck view!
library
Figure 1. No deck selected. You’re now in Library view.

Selecting a deck : select

Format: select <index>

  • Formal definition: Selects and shows all cards in the deck at the specified index. The index refers to the index number shown in the displayed decks list. The index must be a positive integer 1, 2, 3, …​

If you want to view the cards in a particular deck, you can use select followed by the deck’s index number. The index number is the number to the left of its name. After selecting a deck, FlashSpeed will enter the Deck view and show all the cards in that deck.

In the Deck view, you can use any of the Deck mode commands listed in 3.3. Deck view.

Example:

  • select 1
    Selects and shows all cards in the 1st deck.

Ui
Figure 2. Selecting a deck and showing its cards.

View

Command

Library

Deck

Play

help

exit

reset

select

create

remove

rename

play

add

edit

delete

return

flip

yes

no

stop

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.

Architecture

FlashSpeed is mainly built on top of a few core components, runner components, and helper components. The core is where the bulk of the design decisions are made and data processing is performed.

The Architecture Diagram below gives a high-level overview of the FlashSpeed App.

ArchitectureDiagram
Figure 3. Architecture Diagram

Given below is a quick overview of each component.

The Runners:

Main has two classes called Main and MainApp. It is responsible for,

  • At launch: Initializes the core components in the correct sequence, sets up their initial states, and connects them up with each other.

  • At exit: Performs cleanup of components where necessary and shuts down FlashSpeed.

The Helpers:

Commons represents a collection of classes used by multiple other components. The following classes plays an important role at the architecture level:

  • LogsCenter : Writes log messages from many different running components to the FlashSpeed’s log file and console.

  • Index : Provides storage of index numbers and easy conversion between one- and zero-based indices.

  • Messages : Keeps many user-visible messages for invalid user actions.

  • Exceptions : Contains different types of specific exceptions which can occur due to invalid user actions.

The Core:

  • UI: The UI of FlashSpeed.

  • Logic: The command executor.

  • Model: Holds the data and current state of FlashSpeed in-memory.

  • Storage: Reads data from and writes data to a data file on the hard disk.


Editing a Card: Shortcut Formats

Current Implementation

The edit command allows for the values of a Card’s face(s) to be changed.

Accepted syntax:

  • edit INDEX FRONT:BACK

  • edit INDEX :BACK

  • edit INDEX FRONT:

This functionality is implemented by replacing the Card to be edited in the Deck with a new Card containing the new face values (FRONT and BACK). The shortcut versions of the command (second and third formats above) allows for one face value of the Card to be edited while preserving the other face value. In this situation, the unedited face value in the new Card will be a blank string (since either FRONT or BACK will be a blank string). Subsequently, this blank value will be replaced by the associated value in the Card to be replaced.

Below is a summary of the operations flow during the editing of a card.

EditCardActivityDiagram
Figure 4. Operations flow during an Edit command.
Validation and extraction of input in parser

The validation of the arguments in the edit command is performed in EditCommandParser#parse(). Note that the validation only checks that the command is well-formed, i.e. understandable by FlashSpeed. It does not check for the validity of the command in the current environment (e.g. if we are currently in Deck view or not). This is for separation of parsing logic and model management logic.

In EditCommandParser#parse(), the INDEX of the card to be edited and the new face value(s) are extracted from the arguments in the edit command. The INDEX is converted to an Index object. An EditCardCommand object is then constructed with the Index and the new Card as its parameters.

Execution of Command object

When EditCardCommand#execute() is executed, the environment is then checked. The edit command is only valid when we are currently in a Deck, thus a check on the current view is performed using ModelManager#getView(). Then the Index of the card to be edited is checked by ensuring it is in the range of [0, size of current Deck) using ModelManager#getCurrentDeck().getSize().

To perform a replacement of a Card in the current Deck, we need the old Card and the new Card. The old Card is required so we can know which Card is to be replaced via an equality check and also to know the face value which needs to be preserved (if needed). We can get the Card to be edited using ModelManager#getCard() with the provided Index. The new Card can then be created. We can then perform the replacement using ModelManager#replaceCard() with the old Card and the new Card as the parameters.

The following sequence diagram shows the sequence of operations due to an edit command.

EditSequenceDiagram
Figure 5. Operations performed for the edit 1 fr:bk command.

Design Considerations

Aspect: How the replacement Card is formed during the start of execution
  • Alternative 1 (current choice): A blank string in a face of the new Card means we use the face value in the Card to be replaced.

    • Pros: Easy to implement. Can use the extracted values in the arguments as is. Let the final step (UniqueCardList#replace()) handle the replacement logic.

    • Cons: From EditCardCommandParser until the end of the command execution in LogicManager, there may exist a Card with a face containing a blank string. May not be a desirable object to have.

  • Alternative 2: Get the Card to be edited directly in EditCardCommandParser so we can immediately produce the new Card with its final face values.

    • Pros: The Card to replace the old Card will be fully formed from the start.

    • Cons: No separation of parsing and model management logic since we would need to do a view check and get a Card from the current Deck all while in the parser.