Product Documentation

Quiz Mechanics

Formal specification of quiz behavior, state management, scoring logic, and edge-case handling. This document is the authoritative reference for how the quiz engine operates.

Question Types

Each quiz draws 8 questions from a shuffled pool. Four question formats are supported.

Multiple Choice

Four options (A-D). Select the single correct answer. Options are locked immediately on selection.

Strict index equality — selectedIndex === correctIndex.

True / False

Two options (True or False). Select the statement that matches the claim.

Boolean equality — selectedAnswer === correctAnswer.

Image-Based

A reference image is shown alongside four text options. Identical to multiple choice in validation.

Strict index equality — selectedIndex === correctIndex.

Fill-in-the-Blank

A sentence with a blank. Type the answer and submit. Case-insensitive with whitespace normalization.

Normalized string match against an array of accepted answers.

State Machine & Lifecycle

The quiz engine enforces a strict finite-state machine. Every transition is validated against a compile-time transition table — invalid transitions are silently rejected, preventing race conditions and double-mutation.

readyquestionansweredfeedbacktransitioningquestion/completed
FromToTrigger
readyquestionUser clicks "Start Quiz"
questionansweredUser selects answer or timer expires
answeredfeedbackAutomatic after 2500ms or user tap
feedbacktransitioningUser clicks "Continue"
transitioningquestionExit animation completes (next question)
transitioningcompletedNo more questions
completedreadyUser clicks "Restart"

Scoring Logic

Each correct answer earns points from three additive components, multiplied by difficulty. Incorrect answers always score 0 — no partial credit.

totalPoints = (basePoints + timeBonus + streakBonus) × difficultyMultiplier

Base Points

Easy: 100 | Medium: 200 | Hard: 300

Time Bonus

Up to +50 pts. Full bonus for answering within 25% of the time limit; linear decay to 0 at 100%.

Streak Bonus

+25 pts per consecutive correct answer (max +200). Resets to 0 on any incorrect answer.

Difficulty Multiplier

Easy: x1 | Medium: x1.5 | Hard: x2 — applied to (base + time + streak).

Grade Thresholds

Final grade is determined by the percentage of questions answered correctly (not points).

SSupreme95%+
AExcellent85%+
BGreat75%+
CGood60%+
DFair40%+
FTry Again0%+

Feedback Handling

After every answer, two phases of feedback are shown to reinforce learning.

Answered Phase (2.5s)

Options are locked immediately. The correct answer pulses green; an incorrect selection shakes red. Other options dim to 50% opacity. This phase lasts 2500ms (configurable via FEEDBACK_DISPLAY_MS) before automatically advancing to the feedback panel.

Feedback Phase

An explanation panel slides in below the question card, showing a contextual explanation sourced from the question data. A "Continue" button advances to the next question. Points earned and streak status are displayed inline.

Edge Cases & Safety Guarantees

The engine is designed to prevent every known class of state corruption.

Timer Expiry

If the timer reaches zero, a sentinel value (-1) is submitted. The answer is always scored as incorrect with 0 points.

Double-Click Protection

Every state transition is validated against a strict transition table. Clicking "Continue" twice is silently rejected — the second call finds the state is no longer "feedback" and returns without mutating.

Stale Answer Prevention

The current answer is derived by question ID (not array position). Even if answers are reordered or a question is somehow skipped, the UI always shows feedback for the correct question.

Animation–State Synchronisation

The "answered" intermediate state gives the animation system a full settled render frame before the feedback panel appears. Pulse/shake targets are defined within the same variant set as the entry animation, preventing orphaned animation states.

User Interaction Rules

1

One answer per question. Once an option is selected (or the timer expires), the answer is final. There is no undo mechanism.

2

Timer is per-question. Each question has its own time limit (defined in question data). The timer resets on every new question.

3

Questions are shuffled per session. The order is randomized using Fisher-Yates shuffle on session start. Restarting produces a new order.

4

Results are persisted to localStorage. Quiz history, best scores, and streaks are stored client-side and survive page refreshes.

5

No backwards navigation. Users cannot return to a previous question. The quiz is strictly forward-progressing.

Ready to Play?

Now that you know the rules, put your knowledge to the test.