elmeg-demo/backend/routers/leaderboards.py

97 lines
2.7 KiB
Python

from fastapi import APIRouter, Depends, Query
from sqlmodel import Session, select, func, desc
from typing import List, Optional
from database import get_session
from models import Review, Show, Venue, User, Profile
router = APIRouter(
prefix="/leaderboards",
tags=["leaderboards"]
)
@router.get("/shows/top")
def get_top_shows(limit: int = 10, session: Session = Depends(get_session)):
"""Get top rated shows based on average review score"""
# Group by show_id, calc avg score, count reviews
# Filter for shows with at least 1 review (or maybe 2 to be significant?)
# SQLModel doesn't support complex group_by/having easily in pure pythonic way sometimes,
# but we can use session.exec with a direct select.
query = (
select(
Show,
Venue,
func.avg(Review.score).label("avg_score"),
func.count(Review.id).label("review_count")
)
.join(Review, Review.show_id == Show.id)
.join(Venue, Show.venue_id == Venue.id)
.group_by(Show.id, Venue.id)
.having(func.count(Review.id) >= 1)
.order_by(desc("avg_score"), desc("review_count"))
.limit(limit)
)
results = session.exec(query).all()
return [
{
"show": show,
"venue": venue,
"avg_score": round(score, 2),
"review_count": count
}
for show, venue, score, count in results
]
@router.get("/venues/top")
def get_top_venues(limit: int = 10, session: Session = Depends(get_session)):
"""Get top rated venues"""
query = (
select(
Venue,
func.avg(Review.score).label("avg_score"),
func.count(Review.id).label("review_count")
)
.join(Review, Review.venue_id == Venue.id)
.group_by(Venue.id)
.order_by(desc("avg_score"))
.limit(limit)
)
results = session.exec(query).all()
return [
{
"venue": venue,
"avg_score": round(score, 2),
"review_count": count
}
for venue, score, count in results
]
@router.get("/users/active")
def get_active_users(limit: int = 10, session: Session = Depends(get_session)):
"""Get users with most reviews"""
query = (
select(
Profile,
func.count(Review.id).label("review_count")
)
.join(User, User.id == Profile.user_id)
.join(Review, Review.user_id == User.id)
.group_by(Profile.id)
.order_by(desc("review_count"))
.limit(limit)
)
results = session.exec(query).all()
return [
{
"profile": profile,
"review_count": count
}
for profile, count in results
]