from __future__ import annotations from typing import Dict, List from quiz.models import QuizSession from quiz.scoring import compute_mastery_delta, should_unlock_revision_quest, mastery_recommendation from storage.mastery import MasteryStore class ProgressAgent: """ Deterministic mastery calculation. No LLM call. Aggregates correct/total per topic from the session and persists to MasteryStore. """ def __init__(self, mastery_store: MasteryStore): self._mastery = mastery_store def update_from_session(self, session: QuizSession) -> Dict: topic_stats: Dict[str, Dict[str, int]] = {} for q in session.questions: if q.topic not in topic_stats: topic_stats[q.topic] = {"correct": 0, "total": 0} topic_stats[q.topic]["total"] += 1 if q.topic not in session.wrong_topics: topic_stats[q.topic]["correct"] += 1 mastery_updates = [] for topic, stats in topic_stats.items(): self._mastery.update(topic, stats["correct"], stats["total"]) mastery_updates.append({"topic": topic, "correct": stats["correct"], "total": stats["total"]}) weak = [u["topic"] for u in mastery_updates if should_unlock_revision_quest(compute_mastery_delta(u["correct"], u["total"]))] overall = session.score / len(session.questions) if session.questions else 0.0 recommendation = mastery_recommendation(overall) return {"mastery_updates": mastery_updates, "weak_topics": weak, "recommendation": recommendation}