Study-with-ChampAI / quiz /engine.py
SolusOps's picture
feat: quiz package
676d6d1 verified
Raw
History Blame Contribute Delete
1.71 kB
from __future__ import annotations
from dataclasses import dataclass
from quiz.models import QuizSession
from quiz.scoring import xp_for_question, streak_label, compute_grade
@dataclass
class AnswerResult:
is_correct: bool
correct_idx: int
xp_delta: int
streak_label: str
grade: str
was_boss: bool
class QuizEngine:
def submit_next(self, session: QuizSession, selected_idx: int) -> AnswerResult:
"""Submit answer for the current question (regular or boss — auto-detected via is_boss)."""
if session.is_finished:
raise RuntimeError("Cannot submit answer: session is finished.")
question = session.current_question
is_correct = (selected_idx == question.correct_idx)
xp_delta = 0
if is_correct:
session.score += 1
xp_delta = xp_for_question(question.difficulty, is_boss=question.is_boss)
session.xp_earned += xp_delta
if not question.is_boss:
session.consecutive_correct += 1
else:
session.consecutive_correct = 0
if question.topic not in session.wrong_topics:
session.wrong_topics.append(question.topic)
session.current_idx += 1
label = streak_label(session.consecutive_correct)
grade = compute_grade(session.score, session.current_idx)
return AnswerResult(is_correct=is_correct, correct_idx=question.correct_idx,
xp_delta=xp_delta, streak_label=label, grade=grade,
was_boss=question.is_boss)
def final_grade(self, session: QuizSession) -> str:
return compute_grade(session.score, len(session.questions))