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)
|
@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."""
|
"""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)
|
collection = get_object_or_404(SteamCollection, is_active=True)
|
||||||
|
|
||||||
# Only allow access when tournament is closed
|
# 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")
|
raise HttpError(403, "Tournament is still accepting submissions")
|
||||||
|
|
||||||
# Get all puzzles
|
# 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
|
# Build response
|
||||||
submissions_list = []
|
submissions_list = []
|
||||||
for puzzle in puzzles:
|
for puzzle in puzzles:
|
||||||
# Get the top N responses for this puzzle (ranked by points, highest first)
|
# Get the top N responses for this puzzle (ranked by points, highest first)
|
||||||
top_responses = (
|
top_responses = (
|
||||||
PuzzleResponse.objects
|
PuzzleResponse.objects.filter(puzzle=puzzle, needs_manual_validation=False)
|
||||||
.filter(puzzle=puzzle, needs_manual_validation=False)
|
|
||||||
.filter_user_best_response()
|
.filter_user_best_response()
|
||||||
.annotate_rank_points()
|
.annotate_rank_points()
|
||||||
.order_by("-rank_points")[:limit]
|
.order_by("-rank_points")[:limit]
|
||||||
@ -92,23 +99,30 @@ def top_submissions(request: HttpRequest, limit: int = 5) -> TournamentSubmissio
|
|||||||
response_files = [
|
response_files = [
|
||||||
WinnerFileOut(
|
WinnerFileOut(
|
||||||
file_url=file.file_url or "",
|
file_url=file.file_url or "",
|
||||||
original_filename=file.original_filename
|
original_filename=file.original_filename,
|
||||||
)
|
)
|
||||||
for file in files
|
for file in files
|
||||||
]
|
]
|
||||||
|
|
||||||
# Calculate total coefficient
|
# Calculate total coefficient
|
||||||
total_coef = None
|
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 = (
|
total_coef = (
|
||||||
puzzle.points_factor.cost * response.final_cost +
|
puzzle.points_factor.cost * response.final_cost
|
||||||
puzzle.points_factor.cycles * response.final_cycles +
|
+ puzzle.points_factor.cycles * response.final_cycles
|
||||||
puzzle.points_factor.area * response.final_area
|
+ puzzle.points_factor.area * response.final_area
|
||||||
)
|
)
|
||||||
|
|
||||||
submission_data = WinnerResponseOut(
|
submission_data = WinnerResponseOut(
|
||||||
user_id=response.submission.user.id if response.submission.user else 0,
|
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_cost=response.final_cost,
|
||||||
final_cycles=response.final_cycles,
|
final_cycles=response.final_cycles,
|
||||||
final_area=response.final_area,
|
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)
|
@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."""
|
"""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)
|
collection = get_object_or_404(SteamCollection, is_active=True)
|
||||||
|
|
||||||
# Only allow access when tournament is closed
|
# 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")
|
raise HttpError(403, "Tournament is still accepting submissions")
|
||||||
|
|
||||||
# Get all puzzles
|
# 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
|
# Build response
|
||||||
results_list = []
|
results_list = []
|
||||||
for puzzle in puzzles:
|
for puzzle in puzzles:
|
||||||
# Get the top N responses for this puzzle (ranked by points)
|
# Get the top N responses for this puzzle (ranked by points)
|
||||||
top_responses = (
|
top_responses = (
|
||||||
PuzzleResponse.objects
|
PuzzleResponse.objects.filter(puzzle=puzzle, needs_manual_validation=False)
|
||||||
.filter(puzzle=puzzle, needs_manual_validation=False)
|
|
||||||
.filter_user_best_response()
|
.filter_user_best_response()
|
||||||
.annotate_rank_points()
|
.annotate_rank_points()
|
||||||
.order_by("-rank_points")[:limit]
|
.order_by("-rank_points")[:limit]
|
||||||
@ -161,24 +184,31 @@ def puzzle_results(request: HttpRequest, limit: int = 5) -> TournamentPuzzleResu
|
|||||||
response_files = [
|
response_files = [
|
||||||
WinnerFileOut(
|
WinnerFileOut(
|
||||||
file_url=file.file_url or "",
|
file_url=file.file_url or "",
|
||||||
original_filename=file.original_filename
|
original_filename=file.original_filename,
|
||||||
)
|
)
|
||||||
for file in files
|
for file in files
|
||||||
]
|
]
|
||||||
|
|
||||||
# Calculate total coefficient
|
# Calculate total coefficient
|
||||||
total_coef = None
|
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 = (
|
total_coef = (
|
||||||
puzzle.points_factor.cost * response.final_cost +
|
puzzle.points_factor.cost * response.final_cost
|
||||||
puzzle.points_factor.cycles * response.final_cycles +
|
+ puzzle.points_factor.cycles * response.final_cycles
|
||||||
puzzle.points_factor.area * response.final_area
|
+ puzzle.points_factor.area * response.final_area
|
||||||
)
|
)
|
||||||
|
|
||||||
submission_data = PuzzleSubmissionWithRankOut(
|
submission_data = PuzzleSubmissionWithRankOut(
|
||||||
rank=rank,
|
rank=rank,
|
||||||
user_id=response.submission.user.id if response.submission.user else 0,
|
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_cost=response.final_cost,
|
||||||
final_cycles=response.final_cycles,
|
final_cycles=response.final_cycles,
|
||||||
final_area=response.final_area,
|
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):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
("submissions", "0013_steamcollectionitem_points_value"),
|
("submissions", "0013_steamcollectionitem_points_value"),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -3,7 +3,13 @@ from typing import List, Optional
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
from .models import Submission, PuzzleResponse, SubmissionFile, SteamCollectionItem, SteamCollection
|
from .models import (
|
||||||
|
Submission,
|
||||||
|
PuzzleResponse,
|
||||||
|
SubmissionFile,
|
||||||
|
SteamCollectionItem,
|
||||||
|
SteamCollection,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Input Schemas
|
# Input Schemas
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user