feat: add unified contest pool and realtime game modes

This commit is contained in:
2026-08-10 00:31:21 +08:00
parent 97ca20413e
commit 40e9462842
18 changed files with 822 additions and 152 deletions
+23 -3
View File
@@ -8,9 +8,11 @@ from .models import Contest, ContestAttempt, MathGameAttempt, RealtimeMatch
from .services import (
cancel_waiting_match,
create_challenge,
finalize_game_match,
find_match,
join_challenge,
match_payload,
notify_match_on_commit,
refresh_match_state,
start_attempt,
submit_attempt,
@@ -64,7 +66,11 @@ class AttemptSubmitView(APIView):
class MatchmakingView(APIView):
def post(self, request, slug):
contest = get_object_or_404(Contest, slug=slug)
match = find_match(request.user, contest)
match = find_match(
request.user,
contest,
request.data.get("game_kind", RealtimeMatch.GameKind.QUIZ),
)
return Response(match_payload(match, request.user), status=status.HTTP_202_ACCEPTED)
@@ -83,7 +89,11 @@ class MatchStateView(APIView):
class ChallengeCreateView(APIView):
def post(self, request, slug):
contest = get_object_or_404(Contest, slug=slug)
match = create_challenge(request.user, contest)
match = create_challenge(
request.user,
contest,
request.data.get("game_kind", RealtimeMatch.GameKind.QUIZ),
)
return Response(match_payload(match, request.user), status=status.HTTP_201_CREATED)
@@ -158,19 +168,29 @@ class MathGameStartView(APIView):
payload = start_game(
request.user,
kind,
request.data.get("difficulty", MathGameAttempt.Difficulty.STANDARD),
MathGameAttempt.Difficulty.STANDARD,
)
return Response(payload, status=status.HTTP_201_CREATED)
class MathGameSubmitView(APIView):
def post(self, request, attempt_id):
attempt = get_object_or_404(
MathGameAttempt,
id=attempt_id,
user=request.user,
)
payload = submit_game(
request.user,
attempt_id,
request.data,
request.headers.get("Idempotency-Key"),
)
if attempt.match_id:
match = finalize_game_match(attempt.match_id)
if match.status != RealtimeMatch.Status.COMPLETED:
notify_match_on_commit(match.id, "submitted")
return Response(match_payload(match, request.user))
return Response(payload)