Spaces:
Sleeping
Sleeping
| import hashlib | |
| import secrets | |
| from datetime import datetime, timedelta | |
| from sqlalchemy.orm import Session | |
| from app.db.models import User, QuizResult, StudySession | |
| # ── Password | |
| def hash_password(password: str) -> str: | |
| salt = secrets.token_hex(16) | |
| hashed = hashlib.sha256((password + salt).encode()).hexdigest() | |
| return f"{salt}:{hashed}" | |
| def verify_password(plain: str, hashed: str) -> bool: | |
| try: | |
| salt, hash_val = hashed.split(":") | |
| return hashlib.sha256((plain + salt).encode()).hexdigest() == hash_val | |
| except: | |
| return False | |
| # ── User CRUD | |
| def get_user_by_email(db: Session, email: str): | |
| return db.query(User).filter(User.email == email).first() | |
| def get_user_by_username(db: Session, username: str): | |
| return db.query(User).filter(User.username == username).first() | |
| def get_user_by_id(db: Session, user_id: int): | |
| return db.query(User).filter(User.id == user_id).first() | |
| def create_user(db: Session, username: str, email: str, password: str): | |
| user = User( | |
| username=username, | |
| email=email, | |
| password=hash_password(password), | |
| created_at=datetime.utcnow() | |
| ) | |
| db.add(user) | |
| db.commit() | |
| db.refresh(user) | |
| return user | |
| def update_streak(db: Session, user: User): | |
| now = datetime.utcnow() | |
| if user.last_login: | |
| diff = (now.date() - user.last_login.date()).days | |
| if diff == 1: | |
| user.streak_days += 1 | |
| elif diff > 1: | |
| user.streak_days = 1 | |
| else: | |
| user.streak_days = 1 | |
| user.last_login = now | |
| db.commit() | |
| # ── Quiz Results | |
| def save_quiz_result(db: Session, user_id: int, req): | |
| result = QuizResult( | |
| user_id=user_id, | |
| topic=req.topic, | |
| score=req.score, | |
| total_questions=req.total_questions, | |
| correct_answers=req.correct_answers, | |
| difficulty=req.difficulty, | |
| duration_sec=req.duration_sec | |
| ) | |
| db.add(result) | |
| # Mise à jour du niveau utilisateur | |
| user = get_user_by_id(db, user_id) | |
| if user: | |
| results = db.query(QuizResult).filter(QuizResult.user_id == user_id).all() | |
| if len(results) > 0: | |
| avg = sum(r.score for r in results) / len(results) | |
| if avg >= 80: | |
| user.niveau = "expert" | |
| elif avg >= 60: | |
| user.niveau = "intermédiaire" | |
| else: | |
| user.niveau = "débutant" | |
| db.commit() | |
| db.refresh(result) | |
| return result | |
| # ── Profile | |
| def get_student_profile(db: Session, user_id: int) -> dict: | |
| user = get_user_by_id(db, user_id) | |
| if not user: | |
| return {} | |
| quiz_results = db.query(QuizResult).filter( | |
| QuizResult.user_id == user_id | |
| ).order_by(QuizResult.created_at.desc()).all() | |
| sessions = db.query(StudySession).filter( | |
| StudySession.user_id == user_id | |
| ).all() | |
| scores = [r.score for r in quiz_results] | |
| avg_score = round(sum(scores) / len(scores), 1) if scores else 0 | |
| best_score = max(scores) if scores else 0 | |
| # Top matières | |
| subjects = {} | |
| for s in sessions: | |
| subjects[s.subject] = subjects.get(s.subject, 0) + 1 | |
| top_subjects = sorted( | |
| [{"subject": k, "count": v} for k, v in subjects.items()], | |
| key=lambda x: x["count"], reverse=True | |
| )[:5] | |
| recent_quiz = [ | |
| { | |
| "topic": r.topic, | |
| "score": r.score, | |
| "date": r.created_at.strftime("%d/%m/%Y"), | |
| "difficulty": r.difficulty | |
| } | |
| for r in quiz_results[:10] | |
| ] | |
| return { | |
| "user": { | |
| "username": user.username, | |
| "email": user.email, | |
| "niveau": user.niveau, | |
| "streak_days": user.streak_days, | |
| "member_since": user.created_at.strftime("%d/%m/%Y") if user.created_at else "N/A" | |
| }, | |
| "stats": { | |
| "total_sessions": len(sessions), | |
| "total_quiz": len(quiz_results), | |
| "average_score": avg_score, | |
| "best_score": best_score, | |
| "top_subjects": top_subjects | |
| }, | |
| "recent_quiz": recent_quiz | |
| } | |
| def get_progress(db: Session, user_id: int) -> dict: | |
| results = db.query(QuizResult).filter( | |
| QuizResult.user_id == user_id | |
| ).order_by(QuizResult.created_at.asc()).all() | |
| return { | |
| "progression": [ | |
| {"date": r.created_at.strftime("%d/%m"), "score": r.score, "topic": r.topic} | |
| for r in results | |
| ] | |
| } |