cache for result api
This commit is contained in:
parent
9e5ab8539a
commit
25072e8eb4
@ -61,8 +61,14 @@ def results(request: HttpRequest) -> dict:
|
||||
|
||||
|
||||
@router.get("top-submissions", response=TournamentSubmissionsOut)
|
||||
def top_submissions(request: HttpRequest, limit: int = 5) -> TournamentSubmissionsOut:
|
||||
def top_submissions(request: HttpRequest, limit: int = 5) -> dict:
|
||||
"""Get tournament top submissions for each puzzle. Only available when tournament is closed."""
|
||||
cache_key = f"api:results:top_submissions:{limit}"
|
||||
cached_data = cache.get(cache_key)
|
||||
|
||||
if cached_data is not None:
|
||||
return cached_data
|
||||
|
||||
collection = get_object_or_404(SteamCollection, is_active=True)
|
||||
|
||||
# Only allow access when tournament is closed
|
||||
@ -70,15 +76,16 @@ def top_submissions(request: HttpRequest, limit: int = 5) -> TournamentSubmissio
|
||||
raise HttpError(403, "Tournament is still accepting submissions")
|
||||
|
||||
# Get all puzzles
|
||||
puzzles = SteamCollectionItem.objects.filter(collection=collection).order_by("order_index")
|
||||
puzzles = SteamCollectionItem.objects.filter(collection=collection).order_by(
|
||||
"order_index"
|
||||
)
|
||||
|
||||
# Build response
|
||||
submissions_list = []
|
||||
for puzzle in puzzles:
|
||||
# Get the top N responses for this puzzle (ranked by points, highest first)
|
||||
top_responses = (
|
||||
PuzzleResponse.objects
|
||||
.filter(puzzle=puzzle, needs_manual_validation=False)
|
||||
PuzzleResponse.objects.filter(puzzle=puzzle, needs_manual_validation=False)
|
||||
.filter_user_best_response()
|
||||
.annotate_rank_points()
|
||||
.order_by("-rank_points")[:limit]
|
||||
@ -92,23 +99,30 @@ def top_submissions(request: HttpRequest, limit: int = 5) -> TournamentSubmissio
|
||||
response_files = [
|
||||
WinnerFileOut(
|
||||
file_url=file.file_url or "",
|
||||
original_filename=file.original_filename
|
||||
original_filename=file.original_filename,
|
||||
)
|
||||
for file in files
|
||||
]
|
||||
|
||||
# Calculate total coefficient
|
||||
total_coef = None
|
||||
if puzzle.points_factor and response.final_cost is not None and response.final_cycles is not None and response.final_area is not None:
|
||||
if (
|
||||
puzzle.points_factor
|
||||
and response.final_cost is not None
|
||||
and response.final_cycles is not None
|
||||
and response.final_area is not None
|
||||
):
|
||||
total_coef = (
|
||||
puzzle.points_factor.cost * response.final_cost +
|
||||
puzzle.points_factor.cycles * response.final_cycles +
|
||||
puzzle.points_factor.area * response.final_area
|
||||
puzzle.points_factor.cost * response.final_cost
|
||||
+ puzzle.points_factor.cycles * response.final_cycles
|
||||
+ puzzle.points_factor.area * response.final_area
|
||||
)
|
||||
|
||||
submission_data = WinnerResponseOut(
|
||||
user_id=response.submission.user.id if response.submission.user else 0,
|
||||
username=response.submission.user.username if response.submission.user else "Anonymous",
|
||||
username=response.submission.user.username
|
||||
if response.submission.user
|
||||
else "Anonymous",
|
||||
final_cost=response.final_cost,
|
||||
final_cycles=response.final_cycles,
|
||||
final_area=response.final_area,
|
||||
@ -126,12 +140,20 @@ def top_submissions(request: HttpRequest, limit: int = 5) -> TournamentSubmissio
|
||||
)
|
||||
)
|
||||
|
||||
return TournamentSubmissionsOut(submissions=submissions_list)
|
||||
data = {"submissions": submissions_list}
|
||||
cache.set(f"api:results:top_submissions:{limit}", data, 300)
|
||||
return data
|
||||
|
||||
|
||||
@router.get("puzzle-results", response=TournamentPuzzleResultsOut)
|
||||
def puzzle_results(request: HttpRequest, limit: int = 5) -> TournamentPuzzleResultsOut:
|
||||
def puzzle_results(request: HttpRequest, limit: int = 5) -> dict:
|
||||
"""Get tournament results organized by puzzle with coefficients. Only available when tournament is closed."""
|
||||
cache_key = f"api:results:puzzle_results:{limit}"
|
||||
cached_data = cache.get(cache_key)
|
||||
|
||||
if cached_data is not None:
|
||||
return cached_data
|
||||
|
||||
collection = get_object_or_404(SteamCollection, is_active=True)
|
||||
|
||||
# Only allow access when tournament is closed
|
||||
@ -139,15 +161,16 @@ def puzzle_results(request: HttpRequest, limit: int = 5) -> TournamentPuzzleResu
|
||||
raise HttpError(403, "Tournament is still accepting submissions")
|
||||
|
||||
# Get all puzzles
|
||||
puzzles = SteamCollectionItem.objects.filter(collection=collection).order_by("order_index")
|
||||
puzzles = SteamCollectionItem.objects.filter(collection=collection).order_by(
|
||||
"order_index"
|
||||
)
|
||||
|
||||
# Build response
|
||||
results_list = []
|
||||
for puzzle in puzzles:
|
||||
# Get the top N responses for this puzzle (ranked by points)
|
||||
top_responses = (
|
||||
PuzzleResponse.objects
|
||||
.filter(puzzle=puzzle, needs_manual_validation=False)
|
||||
PuzzleResponse.objects.filter(puzzle=puzzle, needs_manual_validation=False)
|
||||
.filter_user_best_response()
|
||||
.annotate_rank_points()
|
||||
.order_by("-rank_points")[:limit]
|
||||
@ -161,24 +184,31 @@ def puzzle_results(request: HttpRequest, limit: int = 5) -> TournamentPuzzleResu
|
||||
response_files = [
|
||||
WinnerFileOut(
|
||||
file_url=file.file_url or "",
|
||||
original_filename=file.original_filename
|
||||
original_filename=file.original_filename,
|
||||
)
|
||||
for file in files
|
||||
]
|
||||
|
||||
# Calculate total coefficient
|
||||
total_coef = None
|
||||
if puzzle.points_factor and response.final_cost is not None and response.final_cycles is not None and response.final_area is not None:
|
||||
if (
|
||||
puzzle.points_factor
|
||||
and response.final_cost is not None
|
||||
and response.final_cycles is not None
|
||||
and response.final_area is not None
|
||||
):
|
||||
total_coef = (
|
||||
puzzle.points_factor.cost * response.final_cost +
|
||||
puzzle.points_factor.cycles * response.final_cycles +
|
||||
puzzle.points_factor.area * response.final_area
|
||||
puzzle.points_factor.cost * response.final_cost
|
||||
+ puzzle.points_factor.cycles * response.final_cycles
|
||||
+ puzzle.points_factor.area * response.final_area
|
||||
)
|
||||
|
||||
submission_data = PuzzleSubmissionWithRankOut(
|
||||
rank=rank,
|
||||
user_id=response.submission.user.id if response.submission.user else 0,
|
||||
username=response.submission.user.username if response.submission.user else "Anonymous",
|
||||
username=response.submission.user.username
|
||||
if response.submission.user
|
||||
else "Anonymous",
|
||||
final_cost=response.final_cost,
|
||||
final_cycles=response.final_cycles,
|
||||
final_area=response.final_area,
|
||||
@ -206,4 +236,6 @@ def puzzle_results(request: HttpRequest, limit: int = 5) -> TournamentPuzzleResu
|
||||
)
|
||||
)
|
||||
|
||||
return TournamentPuzzleResultsOut(results=results_list)
|
||||
data = {"results": results_list}
|
||||
cache.set(f"api:results:puzzle_results:{limit}", data, 300)
|
||||
return data
|
||||
|
||||
@ -4,7 +4,6 @@ from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("submissions", "0013_steamcollectionitem_points_value"),
|
||||
]
|
||||
|
||||
@ -3,7 +3,13 @@ from typing import List, Optional
|
||||
from datetime import datetime
|
||||
from uuid import UUID
|
||||
|
||||
from .models import Submission, PuzzleResponse, SubmissionFile, SteamCollectionItem, SteamCollection
|
||||
from .models import (
|
||||
Submission,
|
||||
PuzzleResponse,
|
||||
SubmissionFile,
|
||||
SteamCollectionItem,
|
||||
SteamCollection,
|
||||
)
|
||||
|
||||
|
||||
# Input Schemas
|
||||
|
||||
Loading…
Reference in New Issue
Block a user