View the Project on GitHub

Zhixiang Teoh - Project Portfolio Page


eCardnomics is a desktop flashcard application to quickly create, manage, and access new flashcards via a Command Line Interface (CLI). eCardnomics is targeted at economics students in Junior College in Singapore, and aims to enhance students’ study experience as an efficient and handy aid for active recall.

The main goals of this application are to help students store and segment their economics subject syllabus into different decks, consolidate bite-sized information within each topic by way of flash cards, and offer a fun way for students to study and revise.

Summary of Contributions

Code contributed

Summary: tP Code Dashboard

In short, I did the following:



Enhancements implemented

In v1.0, I split the work with Wayne in implementing the Deck Mode commands. Specifically, I implemented:

DeleteCommand required me to implement a y/n prompt method for the Ui class, to be used by DeckParser, which was later used by all commands in the application that utilise y/n prompts. Example of the user-interface of the y/n prompt.

In v2.0, I implemented the Game Mode feature. For this, our team originally thought it would be just another command implemented as part of Normal Mode or Deck Mode, but I felt it deserved its own mode. I created a separate package, game, and parser class GameParser for Game Mode , with the game package abstracting away the entire Game Mode implementation from the rest of the application.

So the resulting game package is structured as such:

  | Game
  | GameEngine
     | runGameLoop(), update()
  | GameStorage
     | originalDeck, deque, retestStore

Here, I tried as much as possible to incorporate the Single Responsibility Principle, both within the game classes and the SRP-ness of the existing classes.

Contributions to team-based tasks

Some examples:

Review/mentoring contributions

Some examples:

Contributions beyond the project team

Notable posts/responses posted in forum, and peer software testing:

Contributions to the UG

Mainly Introduction, v1.0 Normal Mode commands, Features - Game Mode, Command Summary.

UG Extracts

Features - Game Mode


Questions are displayed in a randomised order. At each question, the user will:

  1. Try to attempt an answer at the question, by typing at the prompt; then
  2. Press <enter> (optionally with an empty attempt).

Then, the correct answer is displayed, and our ‘advanced’ algorithm scores the user’s attempt against the correct answer. Finally, the user is given the option to re-attempt the question later. See below for example gamplay.

[Deck - Micro-Economics]
  > list
// ------------------------------------------------------------
// You are now viewing deck: Micro-Economics
// 1. Question: What is the Law of demand?
// 2. Question: What is the Law of supply?
// 3. Question: What is price elasticity of demand?
// 4. Question: What is price elasticity of supply?
// ------------------------------------------------------------
[Deck - Micro-Economics]
  > start

Contributions to the DG

Mainly Commands section and Exceptions section under Design, and Game Mode section under Features.

Relevant Pull Requests for DG:

DG Extracts

Design - Exceptions section

Feature Implementation - Game Mode

General Architecture



Example Use Case

For a more contextual use case, consider the following scenario of Econs Wiz attempting the Game Mode for the first deck, Demand-Supply, in his deck list.

Note: Focus on the biggest box in the diagram!


API: seedu/ecardnomics/game

Since there are quite a few things going on in this diagram, here are the key takeaways (the last of which arguably the most important):

Sequential Flow

For a more formal sequential flow of the inner workings of Game Mode, the following elaborates the execution sequence of Game Mode, from after a start command has been parsed in Normal Mode:


In the above diagram the key takeaway is the existence of an intermediary game:Game object that holds GameEngine and GameStorage together. In fact, this is the sole purpose of the Game class: to hold the current game instance, in a Single-Responsibility-Principle (SRP) and Object-Oriented Programming (OOP) manner. This intermediary role of the Game class is also illustrated in the upper part of the earlier use case diagram. Note how it is from this game object that the main game loop, run and managed by GameEngine, is started.


The main game loop. As with all simple games, this flash card game mode is fundamentally built on the concept of a possibly never-ending game loop with specific end conditions. In this case, the main end condition is explicitly that the command object that is parsed and returned upon the getAttempt() call (that prompts the user for an answer attempt) is either a DoneGameCommand or ExitCommand.

This is not the only end condition, though, because the other important but implicit end scenario is when the question pool is exhausted (i.e., storage.deque is empty) and the retest question pool (storage.retestStore ) is empty.

Naturally, the other sequence of special note here is the whole update() sequence, and even more specifically the updateDeque() call within the update() sequence. Notice how updateDeque() calls createRandomisedStack(storage .retestStore) with the retestStore as argument. This essentially creates a new randomised question pool from the retest question pool.

Notice how this updateDeque() sequence is only called exactly when the storage.deque is empty (i.e., when all questions have been popped off the question pool). This is important because it ensures that the user encounters all available questions in the deque at least once before the retest questions are later displayed. Cross-check this with the detailed descriptions of the inner workings of the game loop implementation shown in the earlier architecture and use case diagrams.

Lastly, notice how refreshRetestStore() is called at the end of updateDeque() to, as its name suggests, clear the retest question pool to get ready to store the next wave of retest questions. This is also covered in the bottom few lines of the GameEngine portion of the use case diagram.