mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-17 14:04:20 +01:00
Scoreboard optimizations (#1475)
* The top scoreboard endpoint `/api/v1/scoreboard/top/<count>` is now more performant (3x) due to better response generation In local testing I went from 3.5s to 1.2s.
This commit is contained in:
@@ -9,7 +9,8 @@
|
|||||||
* Add `/api/v1/challenges?view=admin` to allow admin users to see all challenges regardless of their visibility state
|
* Add `/api/v1/challenges?view=admin` to allow admin users to see all challenges regardless of their visibility state
|
||||||
* Add `/api/v1/users?view=admin` to allow admin users to see all users regardless of their hidden/banned state
|
* Add `/api/v1/users?view=admin` to allow admin users to see all users regardless of their hidden/banned state
|
||||||
* Add `/api/v1/teams?view=admin` to allow admin users to see all teams regardless of their hidden/banned state
|
* Add `/api/v1/teams?view=admin` to allow admin users to see all teams regardless of their hidden/banned state
|
||||||
* The scoreboard endpoint `/api/v1/scoreboard` is now significantly more performant due to better response generation
|
* The scoreboard endpoint `/api/v1/scoreboard` is now significantly more performant (20x) due to better response generation
|
||||||
|
* The top scoreboard endpoint `/api/v1/scoreboard/top/<count>` is now more performant (3x) due to better response generation
|
||||||
* The scoreboard endpoint `/api/v1/scoreboard` will no longer show hidden/banned users in a non-hidden team
|
* The scoreboard endpoint `/api/v1/scoreboard` will no longer show hidden/banned users in a non-hidden team
|
||||||
|
|
||||||
**Deployment**
|
**Deployment**
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
from flask_restx import Namespace, Resource
|
from flask_restx import Namespace, Resource
|
||||||
|
|
||||||
from sqlalchemy.orm import joinedload
|
from sqlalchemy.orm import joinedload
|
||||||
@@ -119,15 +121,11 @@ class ScoreboardDetail(Resource):
|
|||||||
solves = solves.all()
|
solves = solves.all()
|
||||||
awards = awards.all()
|
awards = awards.all()
|
||||||
|
|
||||||
for i, team in enumerate(team_ids):
|
# Build a mapping of accounts to their solves and awards
|
||||||
response[i + 1] = {
|
solves = solves + awards
|
||||||
"id": standings[i].account_id,
|
solves_mapper = defaultdict(list)
|
||||||
"name": standings[i].name,
|
|
||||||
"solves": [],
|
|
||||||
}
|
|
||||||
for solve in solves:
|
for solve in solves:
|
||||||
if solve.account_id == team:
|
solves_mapper[solve.account_id].append(
|
||||||
response[i + 1]["solves"].append(
|
|
||||||
{
|
{
|
||||||
"challenge_id": solve.challenge_id,
|
"challenge_id": solve.challenge_id,
|
||||||
"account_id": solve.account_id,
|
"account_id": solve.account_id,
|
||||||
@@ -137,20 +135,17 @@ class ScoreboardDetail(Resource):
|
|||||||
"date": isoformat(solve.date),
|
"date": isoformat(solve.date),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
for award in awards:
|
|
||||||
if award.account_id == team:
|
# Sort all solves by date
|
||||||
response[i + 1]["solves"].append(
|
for team_id in solves_mapper:
|
||||||
{
|
solves_mapper[team_id] = sorted(
|
||||||
"challenge_id": None,
|
solves_mapper[team_id], key=lambda k: k["date"]
|
||||||
"account_id": award.account_id,
|
|
||||||
"team_id": award.team_id,
|
|
||||||
"user_id": award.user_id,
|
|
||||||
"value": award.value,
|
|
||||||
"date": isoformat(award.date),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
response[i + 1]["solves"] = sorted(
|
|
||||||
response[i + 1]["solves"], key=lambda k: k["date"]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for i, team in enumerate(team_ids):
|
||||||
|
response[i + 1] = {
|
||||||
|
"id": standings[i].account_id,
|
||||||
|
"name": standings[i].name,
|
||||||
|
"solves": solves_mapper.get(standings[i].account_id, []),
|
||||||
|
}
|
||||||
return {"success": True, "data": response}
|
return {"success": True, "data": response}
|
||||||
|
|||||||
Reference in New Issue
Block a user