opus-stats-score

This commit is contained in:
2026-10-25 14:20:49 +01:00
parent 5fc79197f6
commit 407cc22911
2 changed files with 116 additions and 1 deletions
+42
View File
@@ -1,3 +1,5 @@
import csv
from ninja import Router, File
from ninja.files import UploadedFile
from ninja.pagination import paginate
@@ -5,6 +7,8 @@ from ninja.errors import HttpError
from django.db import transaction
from django.core.files.base import ContentFile
from django.core.cache import cache
from django.http import HttpRequest, HttpResponse
from ninja.security import django_auth_is_staff
from django.utils import timezone
from django.shortcuts import get_object_or_404
from typing import List
@@ -395,3 +399,41 @@ def get_stats(request, event_path: str):
if total_responses
else 0,
}
@router.get(f"{PREFIX}/points.csv", auth=django_auth_is_staff)
@decorate_view(require_game_enabled(OPUS_MAGNUM_APP_ID))
def points_csv(request: HttpRequest, event_path: str):
"""Admin-only: points per player for each puzzle of the active collection,
one column per puzzle (1 puzzle = 1 round), `;` separated."""
puzzles = list(
SteamCollectionItem.objects.filter(
collection__is_active=True, collection__event=request.event
).order_by("order_index")
)
points = {}
for response in (
PuzzleResponse.objects.filter(
needs_manual_validation=False,
submission__event=request.event,
submission__user__isnull=False,
puzzle__in=puzzles,
)
.filter_user_best_response()
.select_related("submission__user")
):
user_points = points.setdefault(response.submission.user.username, {})
user_points[response.puzzle_id] = response.rank_points or 0
# text/plain so browsers render it inline - most force-download text/csv
response = HttpResponse(content_type="text/plain; charset=utf-8")
writer = csv.writer(response, delimiter=";")
writer.writerow(["username", *(puzzle.title for puzzle in puzzles)])
for username, user_points in sorted(
points.items(), key=lambda item: (-sum(item[1].values()), item[0])
):
writer.writerow(
[username, *(user_points.get(puzzle.id, 0) for puzzle in puzzles)]
)
return response