93 lines
3.6 KiB
Python
93 lines
3.6 KiB
Python
"""Маршруты работы с профилем."""
|
||
|
||
from __future__ import annotations
|
||
|
||
from fastapi import APIRouter, Depends
|
||
from sqlalchemy.orm import Session, selectinload
|
||
|
||
from app.api.deps import get_current_user
|
||
from app.db.session import get_db
|
||
from app.models.rank import Rank
|
||
from app.models.user import User, UserRole, UserCompetency
|
||
from app.models.mission import SubmissionStatus
|
||
from app.schemas.progress import ProgressSnapshot
|
||
from app.schemas.rank import RankBase
|
||
from app.schemas.user import LeaderboardEntry, UserCompetencyRead, UserProfile
|
||
from app.services.rank import build_progress_snapshot
|
||
|
||
router = APIRouter(prefix="/api", tags=["profile"])
|
||
|
||
|
||
@router.get("/me", response_model=UserProfile, summary="Профиль пилота")
|
||
def get_profile(
|
||
*, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)
|
||
) -> UserProfile:
|
||
"""Возвращаем профиль и связанные сущности."""
|
||
|
||
db.refresh(current_user)
|
||
for item in current_user.competencies:
|
||
_ = item.competency
|
||
for artifact in current_user.artifacts:
|
||
_ = artifact.artifact
|
||
return UserProfile.model_validate(current_user)
|
||
|
||
|
||
@router.get("/ranks", response_model=list[RankBase], summary="Перечень рангов")
|
||
def list_ranks(
|
||
*, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)
|
||
) -> list[RankBase]:
|
||
"""Возвращаем ранги по возрастанию требований."""
|
||
|
||
ranks = db.query(Rank).order_by(Rank.required_xp).all()
|
||
return [RankBase.model_validate(rank) for rank in ranks]
|
||
|
||
|
||
@router.get("/progress", response_model=ProgressSnapshot, summary="Прогресс до следующего ранга")
|
||
def get_progress(
|
||
*, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)
|
||
) -> ProgressSnapshot:
|
||
"""Возвращаем агрегированную информацию о выполненных условиях следующего ранга."""
|
||
|
||
db.refresh(current_user)
|
||
_ = current_user.submissions
|
||
_ = current_user.competencies
|
||
snapshot = build_progress_snapshot(current_user, db)
|
||
return snapshot
|
||
|
||
|
||
@router.get("/leaderboard", response_model=list[LeaderboardEntry], summary="Лидерборд пилотов")
|
||
def leaderboard(
|
||
*, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)
|
||
) -> list[LeaderboardEntry]:
|
||
"""Возвращаем пилотов, отсортированных по опыту с перечислением компетенций."""
|
||
|
||
users = (
|
||
db.query(User)
|
||
.filter(User.role == UserRole.PILOT)
|
||
.options(
|
||
selectinload(User.current_rank),
|
||
selectinload(User.competencies).selectinload(UserCompetency.competency),
|
||
selectinload(User.submissions),
|
||
)
|
||
.order_by(User.xp.desc(), User.created_at)
|
||
.all()
|
||
)
|
||
|
||
leaderboard: list[LeaderboardEntry] = []
|
||
for user in users:
|
||
completed = sum(1 for submission in user.submissions if submission.status == SubmissionStatus.APPROVED)
|
||
competencies = [UserCompetencyRead.model_validate(entry) for entry in user.competencies]
|
||
leaderboard.append(
|
||
LeaderboardEntry(
|
||
user_id=user.id,
|
||
full_name=user.full_name,
|
||
rank_title=user.current_rank.title if user.current_rank else None,
|
||
xp=user.xp,
|
||
mana=user.mana,
|
||
completed_missions=completed,
|
||
competencies=competencies,
|
||
)
|
||
)
|
||
|
||
return leaderboard
|