feat: clock + place games
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from django.http import HttpRequest
|
||||
from django.utils import timezone
|
||||
from ninja import Router
|
||||
from ninja.decorators import decorate_view
|
||||
|
||||
from games.decorators import require_game_enabled
|
||||
|
||||
from .models import PRESS_BONUS_SECONDS, ClockTimer, Press
|
||||
from .schemas import ClockStateOut, PlayerStatsOut
|
||||
from .scoring import ranked_players
|
||||
|
||||
router = Router()
|
||||
|
||||
PREFIX = "/events/{event_path}/clock"
|
||||
|
||||
|
||||
@router.get(f"{PREFIX}/current", response=ClockStateOut)
|
||||
@decorate_view(require_game_enabled(path="clock"))
|
||||
def current_state(request: HttpRequest, event_path: str):
|
||||
timer = ClockTimer.current(request.event)
|
||||
timer.reset_if_expired()
|
||||
now = timezone.now()
|
||||
|
||||
next_press_at = None
|
||||
cooldown_seconds = None
|
||||
if request.user.is_authenticated:
|
||||
last_press = (
|
||||
Press.objects.filter(player=request.user, event=request.event)
|
||||
.order_by("-pressed_at")
|
||||
.first()
|
||||
)
|
||||
if last_press is not None:
|
||||
candidate = last_press.pressed_at + timedelta(
|
||||
seconds=last_press.cooldown_seconds
|
||||
)
|
||||
if candidate > now:
|
||||
next_press_at = candidate
|
||||
cooldown_seconds = last_press.cooldown_seconds
|
||||
|
||||
return {
|
||||
"server_time": now,
|
||||
"end_time": timer.end_time,
|
||||
"initial_duration": timer.initial_duration,
|
||||
"press_bonus_seconds": PRESS_BONUS_SECONDS,
|
||||
"next_press_at": next_press_at,
|
||||
"cooldown_seconds": cooldown_seconds,
|
||||
}
|
||||
|
||||
|
||||
@router.get(f"{PREFIX}/me", response=PlayerStatsOut)
|
||||
@decorate_view(require_game_enabled(path="clock"))
|
||||
def my_stats(request: HttpRequest, event_path: str):
|
||||
ranked = list(
|
||||
ranked_players(request.event)
|
||||
.values("id", "points", "rank")
|
||||
.order_by("-points", "id")
|
||||
)
|
||||
total_players = len(ranked)
|
||||
my_index = next(
|
||||
(i for i, row in enumerate(ranked) if row["id"] == request.user.id), None
|
||||
)
|
||||
|
||||
mine = ranked[my_index] if my_index is not None else None
|
||||
above = ranked[my_index - 1] if my_index is not None and my_index > 0 else None
|
||||
below = (
|
||||
ranked[my_index + 1]
|
||||
if my_index is not None and my_index + 1 < total_players
|
||||
else None
|
||||
)
|
||||
|
||||
return {
|
||||
"points": mine["points"] if mine else 0.0,
|
||||
"rank": mine["rank"] if mine else total_players,
|
||||
"total_players": total_players,
|
||||
"points_above": above["points"] if above else None,
|
||||
"points_below": below["points"] if below else None,
|
||||
}
|
||||
Reference in New Issue
Block a user