Sync alternativer
This commit is contained in:
121
linedance-api/app/routers/alt_dance_ratings.py
Normal file
121
linedance-api/app/routers/alt_dance_ratings.py
Normal file
@@ -0,0 +1,121 @@
|
||||
"""
|
||||
alt_dance_ratings.py — Community alternativ-dans ratings endpoint.
|
||||
"""
|
||||
import uuid as _uuid
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
from pydantic import BaseModel
|
||||
from app.core.database import get_db
|
||||
from app.core.security import get_current_user
|
||||
from app.models import User, Song, Dance, CommunityDanceAlt, DanceAltRating
|
||||
|
||||
router = APIRouter(prefix="/alt-ratings", tags=["alt-ratings"])
|
||||
|
||||
|
||||
class SubmitAltRequest(BaseModel):
|
||||
song_id: str # server song UUID
|
||||
dance_name: str
|
||||
rating: int # 1-5
|
||||
|
||||
|
||||
@router.post("/submit")
|
||||
def submit_alt_rating(
|
||||
req: SubmitAltRequest,
|
||||
db: Session = Depends(get_db),
|
||||
me: User = Depends(get_current_user),
|
||||
):
|
||||
"""Indsend eller opdater rating for en alternativ-dans på en sang."""
|
||||
if not 1 <= req.rating <= 5:
|
||||
raise HTTPException(400, "Rating skal være 1-5")
|
||||
|
||||
song = db.query(Song).filter_by(id=req.song_id).first()
|
||||
if not song:
|
||||
raise HTTPException(404, "Sang ikke fundet")
|
||||
|
||||
dance = db.query(Dance).filter(
|
||||
Dance.name.ilike(req.dance_name)
|
||||
).first()
|
||||
if not dance:
|
||||
raise HTTPException(404, "Dans ikke fundet")
|
||||
|
||||
# Find eller opret community alt-dans
|
||||
alt = db.query(CommunityDanceAlt).filter_by(
|
||||
song_mbid=song.mbid or None,
|
||||
song_title=song.title,
|
||||
song_artist=song.artist,
|
||||
alt_dance_id=dance.id,
|
||||
).first()
|
||||
|
||||
if not alt:
|
||||
alt = CommunityDanceAlt(
|
||||
id=str(_uuid.uuid4()),
|
||||
song_mbid=song.mbid or None,
|
||||
song_title=song.title,
|
||||
song_artist=song.artist,
|
||||
alt_dance_id=dance.id,
|
||||
submitted_by=me.id,
|
||||
avg_rating=float(req.rating),
|
||||
rating_count=1,
|
||||
)
|
||||
db.add(alt)
|
||||
db.flush()
|
||||
|
||||
# Opdater eller indsæt brugerens rating
|
||||
existing_rating = db.query(DanceAltRating).filter_by(
|
||||
alternative_id=alt.id,
|
||||
user_id=me.id,
|
||||
).first()
|
||||
|
||||
if existing_rating:
|
||||
old_score = existing_rating.score
|
||||
existing_rating.score = req.rating
|
||||
# Opdater gennemsnit
|
||||
total = alt.avg_rating * alt.rating_count - old_score + req.rating
|
||||
alt.avg_rating = total / alt.rating_count
|
||||
else:
|
||||
db.add(DanceAltRating(
|
||||
id=str(_uuid.uuid4()),
|
||||
alternative_id=alt.id,
|
||||
user_id=me.id,
|
||||
score=req.rating,
|
||||
))
|
||||
# Opdater gennemsnit
|
||||
total = alt.avg_rating * alt.rating_count + req.rating
|
||||
alt.rating_count += 1
|
||||
alt.avg_rating = total / alt.rating_count
|
||||
|
||||
db.commit()
|
||||
return {"status": "ok", "avg_rating": alt.avg_rating, "rating_count": alt.rating_count}
|
||||
|
||||
|
||||
@router.get("/for-song/{song_id}")
|
||||
def get_alt_ratings_for_song(
|
||||
song_id: str,
|
||||
db: Session = Depends(get_db),
|
||||
me: User = Depends(get_current_user),
|
||||
):
|
||||
"""Hent community alternativ-danse med ratings for en sang."""
|
||||
song = db.query(Song).filter_by(id=song_id).first()
|
||||
if not song:
|
||||
raise HTTPException(404, "Sang ikke fundet")
|
||||
|
||||
alts = db.query(CommunityDanceAlt).filter(
|
||||
(CommunityDanceAlt.song_mbid == song.mbid) if song.mbid else
|
||||
((CommunityDanceAlt.song_title == song.title) &
|
||||
(CommunityDanceAlt.song_artist == song.artist))
|
||||
).all()
|
||||
|
||||
result = []
|
||||
for alt in alts:
|
||||
my_rating = db.query(DanceAltRating).filter_by(
|
||||
alternative_id=alt.id,
|
||||
user_id=me.id,
|
||||
).first()
|
||||
result.append({
|
||||
"dance_name": alt.alt_dance.name,
|
||||
"avg_rating": round(alt.avg_rating, 1),
|
||||
"rating_count": alt.rating_count,
|
||||
"my_rating": my_rating.score if my_rating else None,
|
||||
})
|
||||
|
||||
return result
|
||||
@@ -10,6 +10,7 @@ from datetime import datetime, timezone
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.orm import Session
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
from app.core.database import get_db
|
||||
from app.core.security import get_current_user
|
||||
@@ -53,6 +54,7 @@ class SongAltDanceData(BaseModel):
|
||||
dance_name: str
|
||||
level_name: str = ""
|
||||
note: str = ""
|
||||
user_rating: Optional[int] = None
|
||||
|
||||
class PlaylistSongData(BaseModel):
|
||||
song_local_id: str
|
||||
@@ -224,6 +226,47 @@ def push(
|
||||
dance_id = dance_id_map.get(key)
|
||||
if not dance_id:
|
||||
continue
|
||||
# Opdater community rating hvis bruger har givet en vurdering
|
||||
if sa.user_rating and 1 <= sa.user_rating <= 5:
|
||||
from app.models import CommunityDanceAlt, DanceAltRating
|
||||
song_obj = db.query(Song).filter_by(id=song_id).first()
|
||||
if song_obj:
|
||||
alt = db.query(CommunityDanceAlt).filter_by(
|
||||
song_title=song_obj.title,
|
||||
song_artist=song_obj.artist,
|
||||
alt_dance_id=dance_id,
|
||||
).first()
|
||||
if not alt:
|
||||
alt = CommunityDanceAlt(
|
||||
id=str(uuid.uuid4()),
|
||||
song_mbid=song_obj.mbid or None,
|
||||
song_title=song_obj.title,
|
||||
song_artist=song_obj.artist,
|
||||
alt_dance_id=dance_id,
|
||||
submitted_by=me.id,
|
||||
avg_rating=float(sa.user_rating),
|
||||
rating_count=1,
|
||||
)
|
||||
db.add(alt)
|
||||
db.flush()
|
||||
existing_r = db.query(DanceAltRating).filter_by(
|
||||
alternative_id=alt.id, user_id=me.id
|
||||
).first()
|
||||
if existing_r:
|
||||
old_score = existing_r.score
|
||||
existing_r.score = sa.user_rating
|
||||
total = alt.avg_rating * alt.rating_count - old_score + sa.user_rating
|
||||
alt.avg_rating = total / alt.rating_count
|
||||
else:
|
||||
db.add(DanceAltRating(
|
||||
id=str(uuid.uuid4()),
|
||||
alternative_id=alt.id,
|
||||
user_id=me.id,
|
||||
score=sa.user_rating,
|
||||
))
|
||||
total = alt.avg_rating * alt.rating_count + sa.user_rating
|
||||
alt.rating_count += 1
|
||||
alt.avg_rating = total / alt.rating_count
|
||||
db.execute(_sa.text(
|
||||
"INSERT IGNORE INTO song_alt_dances (id, song_id, dance_id, note) "
|
||||
"VALUES (:id, :song_id, :dance_id, :note)"
|
||||
@@ -401,10 +444,30 @@ def pull(
|
||||
"dance_order": sd.dance_order,
|
||||
})
|
||||
|
||||
# Community alternativ-danse (top 500 mest ratede)
|
||||
from app.models import CommunityDanceAlt, DanceAltRating
|
||||
community_alts = []
|
||||
for alt in db.query(CommunityDanceAlt).order_by(
|
||||
CommunityDanceAlt.avg_rating.desc()
|
||||
).limit(500).all():
|
||||
my_rating = db.query(DanceAltRating).filter_by(
|
||||
alternative_id=alt.id, user_id=me.id
|
||||
).first()
|
||||
community_alts.append({
|
||||
"song_mbid": alt.song_mbid or "",
|
||||
"song_title": alt.song_title,
|
||||
"song_artist": alt.song_artist,
|
||||
"dance_name": alt.alt_dance.name if alt.alt_dance else "",
|
||||
"avg_rating": round(alt.avg_rating, 1),
|
||||
"rating_count": alt.rating_count,
|
||||
"my_rating": my_rating.score if my_rating else None,
|
||||
})
|
||||
|
||||
return {
|
||||
"levels": levels,
|
||||
"dances": dances,
|
||||
"shared": shared,
|
||||
"my_playlists": my_playlists,
|
||||
"song_tags": song_tags,
|
||||
"levels": levels,
|
||||
"dances": dances,
|
||||
"shared": shared,
|
||||
"my_playlists": my_playlists,
|
||||
"song_tags": song_tags,
|
||||
"community_alts": community_alts,
|
||||
}
|
||||
Reference in New Issue
Block a user