fix(score): return user score & remove duplicated scores
This commit is contained in:
@@ -2,6 +2,7 @@ from collections.abc import Sequence
|
||||
from datetime import UTC, date, datetime
|
||||
import json
|
||||
import math
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from app.calculator import (
|
||||
@@ -328,22 +329,39 @@ async def get_leaderboard(
|
||||
mods: list[str] | None = None,
|
||||
user: User | None = None,
|
||||
limit: int = 50,
|
||||
) -> tuple[list[Score], Score | None]:
|
||||
) -> tuple[list[Score], Score | None, int]:
|
||||
mods = mods or []
|
||||
mode = mode.to_special_mode(mods)
|
||||
|
||||
wheres = await _score_where(type, beatmap, mode, mods, user)
|
||||
if wheres is None:
|
||||
return [], None
|
||||
query = (
|
||||
select(BestScore)
|
||||
.where(*wheres)
|
||||
.limit(limit)
|
||||
.order_by(col(BestScore.total_score).desc())
|
||||
)
|
||||
if mods:
|
||||
query = query.params(w=json.dumps(mods))
|
||||
scores = [s.score for s in await session.exec(query)]
|
||||
return [], None, 0
|
||||
count = (await session.exec(select(func.count()).where(*wheres))).one()
|
||||
scores: dict[int, Score] = {}
|
||||
max_score = sys.maxsize
|
||||
while limit > 0:
|
||||
query = (
|
||||
select(BestScore)
|
||||
.where(*wheres, BestScore.total_score < max_score)
|
||||
.limit(limit)
|
||||
.order_by(col(BestScore.total_score).desc())
|
||||
)
|
||||
if mods:
|
||||
query = query.params(w=json.dumps(mods))
|
||||
extra_need = 0
|
||||
for s in await session.exec(query):
|
||||
if s.user_id in scores:
|
||||
extra_need += 1
|
||||
count -= 1
|
||||
if s.total_score > scores[s.user_id].total_score:
|
||||
scores[s.user_id] = s.score
|
||||
else:
|
||||
scores[s.user_id] = s.score
|
||||
if max_score > s.total_score:
|
||||
max_score = s.total_score
|
||||
limit = extra_need
|
||||
|
||||
result_scores = sorted(scores.values(), key=lambda u: u.total_score, reverse=True)
|
||||
user_score = None
|
||||
if user:
|
||||
self_query = (
|
||||
@@ -366,9 +384,9 @@ async def get_leaderboard(
|
||||
user_bs = (await session.exec(self_query)).first()
|
||||
if user_bs:
|
||||
user_score = user_bs.score
|
||||
if user_score and user_score not in scores:
|
||||
scores.append(user_score)
|
||||
return scores, user_score
|
||||
if user_score and user_score not in result_scores:
|
||||
result_scores.append(user_score)
|
||||
return result_scores, user_score, count
|
||||
|
||||
|
||||
async def get_score_position_by_user(
|
||||
@@ -719,7 +737,8 @@ async def process_user(
|
||||
statistics.hit_accuracy = acc_sum
|
||||
if add_to_db:
|
||||
session.add(mouthly_playcount)
|
||||
await process_beatmap_playcount(session, user.id, score.beatmap_id)
|
||||
with session.no_autoflush:
|
||||
await process_beatmap_playcount(session, user.id, score.beatmap_id)
|
||||
await session.commit()
|
||||
await session.refresh(user)
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ async def get_scores(
|
||||
)
|
||||
).all()
|
||||
else:
|
||||
scores, _ = await get_leaderboard(
|
||||
scores, _, _ = await get_leaderboard(
|
||||
session,
|
||||
beatmap_id,
|
||||
GameMode.from_int_extra(ruleset_id),
|
||||
|
||||
@@ -169,7 +169,8 @@ async def submit_score(
|
||||
|
||||
class BeatmapScores(BaseModel):
|
||||
scores: list[ScoreResp]
|
||||
userScore: ScoreResp | None = None
|
||||
user_score: BeatmapUserScore | None = None
|
||||
score_count: int = 0
|
||||
|
||||
|
||||
@router.get(
|
||||
@@ -201,14 +202,21 @@ async def get_beatmap_scores(
|
||||
status_code=404, detail="this server only contains lazer scores"
|
||||
)
|
||||
|
||||
all_scores, user_score = await get_leaderboard(
|
||||
all_scores, user_score, count = await get_leaderboard(
|
||||
db, beatmap_id, mode, type=type, user=current_user, limit=limit, mods=mods
|
||||
)
|
||||
|
||||
return BeatmapScores(
|
||||
user_score_resp = await ScoreResp.from_db(db, user_score) if user_score else None
|
||||
resp = BeatmapScores(
|
||||
scores=[await ScoreResp.from_db(db, score) for score in all_scores],
|
||||
userScore=await ScoreResp.from_db(db, user_score) if user_score else None,
|
||||
user_score=BeatmapUserScore(
|
||||
score=user_score_resp, position=user_score_resp.rank_global or 0
|
||||
)
|
||||
if user_score_resp
|
||||
else None,
|
||||
score_count=count,
|
||||
)
|
||||
return resp
|
||||
|
||||
|
||||
class BeatmapUserScore(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user