chartbastan/backend/app/services/badge_service.py
2026-02-01 09:31:38 +01:00

191 lines
6.8 KiB
Python

"""
Service de gestion des badges
"""
from sqlalchemy.orm import Session
from typing import List, Dict, Any
from datetime import datetime
from app.models.badge import Badge, UserBadge
from app.models.user import User
from app.models.user_prediction import UserPrediction
from app.lib.badges import (
BADGES,
isBadgeUnlocked,
getBadgeById,
)
class BadgeService:
"""Service pour la gestion des badges"""
def __init__(self, db: Session):
self.db = db
def get_user_criteria(self, user_id: int) -> Dict[str, int]:
"""
Récupère les critères actuels de l'utilisateur
"""
# Nombre de prédictions consultées
predictions_count = self.db.query(UserPrediction).filter(
UserPrediction.user_id == user_id
).count()
# Nombre de prédictions correctes (pour l'instant on utilise une valeur par défaut)
# TODO: Implémenter la logique de calcul des prédictions correctes
correct_predictions = 0
# Nombre de jours consécutifs (streak)
# TODO: Implémenter la logique de calcul de streak
streak_days = 0
# Nombre de partages
# TODO: Implémenter la logique de suivi des partages
share_count = 0
# Nombre de parrainages
# TODO: Implémenter la logique de suivi des parrainages
referral_count = 0
return {
"predictions_count": predictions_count,
"correct_predictions": correct_predictions,
"streak_days": streak_days,
"share_count": share_count,
"referral_count": referral_count,
}
def check_and_unlock_badges(self, user_id: int) -> Dict[str, Any]:
"""
Vérifie et débloque les nouveaux badges pour un utilisateur
"""
# Récupérer les critères actuels de l'utilisateur
user_criteria = self.get_user_criteria(user_id)
# Récupérer les badges déjà débloqués par l'utilisateur
unlocked_badges = self.db.query(UserBadge).filter(
UserBadge.user_id == user_id
).all()
unlocked_badge_ids = set()
for ub in unlocked_badges:
badge = self.db.query(Badge).filter(Badge.id == ub.badge_id).first()
if badge:
unlocked_badge_ids.add(badge.badge_id)
# Vérifier tous les badges potentiels
newly_unlocked_badges = []
for badge_def in BADGES:
if badge_def["id"] not in unlocked_badge_ids:
# Vérifier si le badge peut être débloqué
criteria_type = badge_def["criteria"]["type"]
criteria_value = badge_def["criteria"]["value"]
if user_criteria[criteria_type] >= criteria_value:
# Débloquer le badge
new_badge = self._unlock_badge(user_id, badge_def)
if new_badge:
newly_unlocked_badges.append(new_badge)
total_badges = len(unlocked_badges) + len(newly_unlocked_badges)
# Générer un message de notification
message = ""
if len(newly_unlocked_badges) > 0:
if len(newly_unlocked_badges) == 1:
message = f'🎉 Félicitations ! Vous avez débloqué le badge "{newly_unlocked_badges[0]["name"]}" !'
else:
badge_names = ', '.join(b["name"] for b in newly_unlocked_badges)
message = f'🎉 Félicitations ! Vous avez débloqué {len(newly_unlocked_badges)} nouveaux badges : {badge_names} !'
return {
"new_badges": newly_unlocked_badges,
"total_badges": total_badges,
"message": message,
}
def _unlock_badge(self, user_id: int, badge_def: Dict[str, Any]) -> Dict[str, Any] | None:
"""
Débloque un badge pour un utilisateur
"""
try:
# Récupérer ou créer le badge dans la base de données
db_badge = self.db.query(Badge).filter(
Badge.badge_id == badge_def["id"]
).first()
if not db_badge:
# Créer le badge dans la base de données
db_badge = Badge(
badge_id=badge_def["id"],
name=badge_def["name"],
description=badge_def["description"],
icon=badge_def["icon"],
category=badge_def["category"],
criteria_type=badge_def["criteria"]["type"],
criteria_value=badge_def["criteria"]["value"],
criteria_description=badge_def["criteria"]["description"],
rarity=badge_def["rarity"],
points=badge_def["points"],
created_at=datetime.utcnow(),
)
self.db.add(db_badge)
self.db.flush()
# Créer le badge utilisateur
user_badge = UserBadge(
user_id=user_id,
badge_id=db_badge.id,
unlocked_at=datetime.utcnow(),
)
self.db.add(user_badge)
self.db.commit()
return {
"id": db_badge.id,
"badgeId": db_badge.badge_id,
"name": db_badge.name,
"description": db_badge.description,
"icon": db_badge.icon,
"category": db_badge.category,
"rarity": db_badge.rarity,
"points": db_badge.points,
}
except Exception as e:
self.db.rollback()
print(f"Erreur lors du déblocage du badge {badge_def['id']}: {e}")
return None
def get_user_badges(self, user_id: int) -> List[Dict[str, Any]]:
"""
Récupère tous les badges débloqués par un utilisateur
"""
user_badges = self.db.query(UserBadge).filter(
UserBadge.user_id == user_id
).all()
result = []
for ub in user_badges:
badge = self.db.query(Badge).filter(Badge.id == ub.badge_id).first()
if badge:
result.append({
"id": ub.id,
"userId": ub.user_id,
"badgeId": ub.badge_id,
"unlockedAt": ub.unlocked_at.isoformat(),
"badge": {
"id": badge.id,
"badgeId": badge.badge_id,
"name": badge.name,
"description": badge.description,
"icon": badge.icon,
"category": badge.category,
"rarity": badge.rarity,
"points": badge.points,
"createdAt": badge.created_at.isoformat(),
}
})
return result