Skip to content

B2C Practice Player (real PYQs, structured sessions)

Status: Building (v1) Owner: Bhanu Surfaces: apps/web (new PracticeSession page, Study Plan CTA rewire), apps/backend (exam question store, practice sessions + attempts)

Why this exists (Product Mindset Gate)

  1. Who asked for it? Bhanu (owner), from dogfooding the Study Plan practice flow, with explicit competitor reference (Brilliant, Sololearn). Self-initiated hypothesis; no user interview or ticket behind it, and we say so.
  2. What user pain? A learner taps "Start practice" on a ranked chapter and lands in a chatbot streaming generated questions as chat bubbles. Ten questions means scrolling a conversation: no one-question-at-a-time focus, no instant right/wrong, no session progress, free-text answers. Every serious exam-prep product (Brilliant, Sololearn, Embibe, Physics Wallah, Allen) drills through a structured player, none through chat.
  3. Cost of NOT doing it? (a) Daily-repeat retention: nobody drills 20 chapters in chat form, and practice is the loop Pro sells. (b) M2 is blocked: the mastery write-path needs clean per-question attempt events (chapter, correct/incorrect, timestamp). Chat free-text cannot produce that reliably, so accuracyPct stays null and the Study Plan never personalizes.
  4. Validated or a guess? Guess, competitor-pattern informed. 7 B2C users in prod, no local usage data. Strong prior, honestly unvalidated.
  5. How we know it worked? Session completion rate (started -> finished), practice sessions per learner per week, next-day repeat rate. Sean Ellis counterfactual: swap the player back to chat a week after shipping; active learners would complain "where's the quiz mode".

Decisions (made with owner, 2026-07-02)

  • Question source: real PYQs via ETL. The knowledge_base_status bank (6,493 questions, 1:1 answers + explanations, 100% chapter/topic-tagged, complexity-tagged) is copied into the app DB by an ETL script. The player serves real past-exam questions: instant, deterministic, no hallucinated answer keys, and each question can carry its "JEE 2018" provenance badge.
  • Player replaces chat practice. "Start practice" (Study Plan today card, chapter rows, and the B2C practice intent tile) opens the player. Chat remains for get_help / understand / revise.

What v1 is

  • PracticeSession page: one question at a time, options as tappable cards, instant correct/incorrect on submit, explanation reveal, progress ("3 of 10"), session summary (score, per-question review, back to plan).
  • Backend: exam_questions store (ETL-fed), practice_sessions + practice_attempts tables, endpoints to start a session, submit an attempt (server grades; correct answer never ships in the session payload), and read a summary.
  • Session composition: 10 questions, chapter-scoped, mixed complexity (cold-start rule from the strategic-practice doc), text-only questions (figures excluded in v1).
  • Attempts are persisted. This table is the substrate M2's interaction counters read from.
  • "Ask AI" on the feedback state: deep-links into the get_help chat with the question, the learner's answer, and the correct answer pre-seeded (uses the existing location.state seed handshake).

Non-goals (v1)

  • Figure/diagram questions (has_figure, 1,107 of 6,493) — needs asset serving; v1 filters them out.
  • Adaptive within-session difficulty (v1 fixes the set at start; adaptivity comes with M2 mastery).
  • LLM top-up for chapters with thin PYQ coverage (hybrid mode was considered, deferred; thin chapters just get shorter sets).
  • Timed/exam-mode sessions, mixed-chapter mock tests, spaced-repetition scheduling (due_revisions still 0).
  • Trainer-authored practice paths (B2B homework/mock-test flows untouched).

Rejected alternatives

  • LLM-generated questions in a player shell (fastest ship): rejected. Latency per set, answer-key hallucination risk, no provenance, and attempts against generated questions are weaker mastery evidence than attempts against tagged PYQs.
  • Keep chat as a second practice entry point: rejected. Two competing practice surfaces split the funnel metric the Gate defines and confuse "where do I practice".
  • Serving questions live from knowledge_base_status: rejected. The request path stays inside the app DB (same rule as the Study Plan engine); the bank DB is a pipeline artifact, not a serving store.

How it works

Study Plan CTA ──► /practice/session?subject=X&chapter=Y
                        │  POST /api/v1/practice-sessions
              picks 10 text-only questions for chapter (complexity mix)
                        │  learner answers one by one
              POST /practice-sessions/{id}/attempts  (server grades)
                        │  correct? + explanation back per question
              summary screen ──► back to Study Plan
              (attempts persisted ──► M2 interaction counters)

ETL: scripts/etl_exam_questions.py reads the bank DB (read-only DSN via env) and upserts into exam_questions. Run per environment; the bank stays the source of truth until the ingestion repo owns this.

Changelog

  • 2026-07-02 — doc created alongside v1 implementation (same PR).
  • 2026-07-02 — "Ask AI" promoted from non-goal to v1 after owner dogfood (chat felt missing from the drill); KaTeX rendering added for questions/options/explanations (bank content is LaTeX-heavy).