pdf-quiz-generator/backend/alembic/versions/e1f2a3b4c5d6_used_hint.py
Daniel 789cd1cc81 feat: right after a tip is its own slice
Opening a tip before answering is a nudge. The answer that follows is
still right — it is counted as right, and the percentage is not docked —
but it is not the same as right, so it keeps its own arc on the donut and
its own line in the legend: "3 correct after a tip".

attempt_answers.used_hint records it. The player reports which questions
had a tip opened before the answer went in; a tip read afterwards is
revision and does not count, which is the difference two of the tests
turn on. Both endings agree about it — an explicit submit carries the
list, and an exam that runs out takes it from the saved progress, so a
tab closing cannot launder a score.

Found while wiring this: RichText declared its component overrides inline
in the render, so every one was a fresh component type and React
remounted the whole rendered tree on each render. An open tip closed
itself every time the exam clock ticked. The map is memoised now.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TqXevQJhxFrM7jJg82cgZN
2026-09-12 01:51:03 +02:00

28 lines
786 B
Python

"""Record whether a tip was opened before the question was answered.
Getting an answer right after reading a nudge is not the same as getting it
right, and neither is it wrong. Kept as its own fact so the analysis can say
which it was rather than folding one into the other.
Rows written before tips existed take 0. That is not a guess: there was
nothing to open.
Revision ID: e1f2a3b4c5d6
Revises: d0e1f2a3b4c5
"""
import sqlalchemy as sa
from alembic import op
revision = "e1f2a3b4c5d6"
down_revision = "d0e1f2a3b4c5"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.add_column("attempt_answers", sa.Column(
"used_hint", sa.Boolean(), nullable=False, server_default="0"))
def downgrade() -> None:
op.drop_column("attempt_answers", "used_hint")