Files
pragativeer-v2/backend/analytics.py

64 lines
2.4 KiB
Python

from sqlmodel import Session, select
from datetime import datetime, timedelta
from collections import Counter
from uuid import UUID
import models
def generate_parent_report(student_id: UUID, session: Session) -> dict:
"""
Aggregates granular performance data for a specific student
into a clean, simple, parent-friendly schema.
"""
# 1. Fetch Student Baseline Info
student = session.get(models.User, student_id)
if not student:
return {"error": "Student record not found."}
# 2. Compile Last 7 Days Time & Attempts Data
seven_days_ago = datetime.utcnow() - timedelta(days=7)
attempts = session.exec(
select(models.Attempt)
.where(models.Attempt.user_id == student_id)
.where(models.Attempt.submitted_at >= seven_days_ago)
).all()
total_time_spent_seconds = sum((a.time_taken or 0) for a in attempts)
total_time_spent_minutes = round(total_time_spent_seconds / 60, 1)
# 3. Calculate 7-Day Accuracy Trend Line Data
# Group accuracy by date strings for simple frontend parsing
trend_data = []
for i in range(6, -1, -1):
target_date = (datetime.utcnow() - timedelta(days=i)).date()
daily_attempts = [a for a in attempts if a.submitted_at.date() == target_date]
if daily_attempts:
avg_accuracy = sum(a.accuracy for a in daily_attempts) / len(daily_attempts)
trend_data.append({"date": target_date.strftime("%b %d"), "accuracy": round(avg_accuracy, 1)})
else:
trend_data.append({"date": target_date.strftime("%b %d"), "accuracy": 0.0})
# 4. Extract Top "Areas of Concern" (Active un-mastered mistakes)
active_mistakes = session.exec(
select(models.Mistake)
.where(models.Mistake.user_id == student_id)
.where(models.Mistake.is_mastered == False)
).all()
# Aggregate topic counts to find where they struggle most
topic_counter = Counter([m.topic for m in active_mistakes])
top_concerns = [
{"topic": topic, "pending_errors": count}
for topic, count in topic_counter.most_common(3)
]
return {
"student_name": student.name,
"streak_count": student.streak_count,
"weekly_minutes_spent": total_time_spent_minutes,
"total_tests_attempted_this_week": len(attempts),
"accuracy_trend": trend_data,
"areas_of_concern": top_concerns,
"last_active": student.last_active.strftime("%Y-%m-%d %H:%M:%S")
}