Improve draft UI state handling, layout, and order logic
- Added current/next pick info, updated server draft logic for order/snake - Refactored WebSocketContext, removed dead code, improved CSS/layout - Cleaned up template blocks, admin, and participant panel structure
This commit is contained in:
@@ -4,8 +4,11 @@ from datetime import datetime, timedelta
|
||||
from boxofficefantasy.models import Movie
|
||||
from django.contrib.auth.models import User
|
||||
from draft.constants import DraftPhase
|
||||
from draft.models import DraftSessionSettings
|
||||
from draft.models import DraftSession
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Dict, List, Literal, Optional, Sequence, Tuple
|
||||
import random
|
||||
|
||||
class DraftCacheKeys:
|
||||
def __init__(self, id):
|
||||
@@ -73,12 +76,12 @@ class DraftCacheKeys:
|
||||
# return f"{self.prefix}:user:{user_id}:channel"
|
||||
|
||||
class DraftStateManager:
|
||||
def __init__(self, session_id: int, settings: DraftSessionSettings):
|
||||
self.session_id = session_id
|
||||
def __init__(self, session: DraftSession):
|
||||
self.session_id = session.hashid
|
||||
self.cache = cache
|
||||
self.keys = DraftCacheKeys(session_id)
|
||||
self.keys = DraftCacheKeys(self.session_id)
|
||||
self._initial_phase = self.cache.get(self.keys.phase, DraftPhase.WAITING.value)
|
||||
self.settings = settings
|
||||
self.settings = session.settings
|
||||
|
||||
# === Phase Management ===
|
||||
@property
|
||||
@@ -114,6 +117,13 @@ class DraftStateManager:
|
||||
if not isinstance(draft_order, list):
|
||||
return
|
||||
self.cache.set(self.keys.draft_order,json.dumps(draft_order))
|
||||
|
||||
def determine_draft_order(self, users: list[User]):
|
||||
draft_order = random.sample(
|
||||
users, len(users)
|
||||
)
|
||||
self.draft_order = [user.username for user in draft_order]
|
||||
return self.draft_order
|
||||
|
||||
@property
|
||||
def draft_index(self):
|
||||
@@ -122,6 +132,42 @@ class DraftStateManager:
|
||||
@draft_index.setter
|
||||
def draft_index(self, draft_index: int):
|
||||
self.cache.set(self.keys.draft_index, int(draft_index))
|
||||
|
||||
def draft_index_advance(self, n: int = 1):
|
||||
self.draft_index += n
|
||||
return self.draft_index
|
||||
|
||||
def next_picks(
|
||||
self,
|
||||
*,
|
||||
from_overall: int | None = None,
|
||||
count: int | None = None,
|
||||
include_current: bool = False,
|
||||
) -> List[dict]:
|
||||
"""
|
||||
Convenience: return the next `count` picks starting after `from_overall`
|
||||
(or after current draft_index if omitted). Each item:
|
||||
{overall, round, pick_in_round, participant}
|
||||
"""
|
||||
if not self.draft_order:
|
||||
return []
|
||||
n = len(self.draft_order)
|
||||
count = count if count else len(self.draft_order)
|
||||
start = self.draft_index if from_overall is None else int(from_overall)
|
||||
start = start if include_current else start + 1
|
||||
|
||||
out: List[dict] = []
|
||||
for overall in range(start, start + count):
|
||||
r, p = _round_and_pick(overall, n)
|
||||
order_type = "snake"
|
||||
order = _round_order(r, order_type, self.draft_order)
|
||||
out.append({
|
||||
"overall": overall,
|
||||
"round": r,
|
||||
"pick_in_round": p,
|
||||
"participant": order[p - 1],
|
||||
})
|
||||
return out
|
||||
|
||||
# === Current Nomination / Bid ===
|
||||
def start_nomination(self, movie_id: int):
|
||||
@@ -155,6 +201,7 @@ class DraftStateManager:
|
||||
|
||||
# === Sync Snapshot ===
|
||||
def get_summary(self) -> dict:
|
||||
picks = self.next_picks(include_current=True)
|
||||
return {
|
||||
"phase": self.phase,
|
||||
"draft_order": self.draft_order,
|
||||
@@ -164,4 +211,18 @@ class DraftStateManager:
|
||||
# "bids": self.get_bids(),
|
||||
"bidding_timer_end": self.get_timer_end(),
|
||||
"bidding_timer_start": self.get_timer_start(),
|
||||
}
|
||||
"current_pick": picks[0] if picks else None,
|
||||
"next_picks": picks[1:] if picks else []
|
||||
}
|
||||
|
||||
OrderType = Literal["snake", "linear"]
|
||||
def _round_and_pick(overall: int, n: int) -> Tuple[int, int]:
|
||||
"""overall -> (round_1_based, pick_in_round_1_based)"""
|
||||
r = overall // n + 1
|
||||
p = overall % n + 1
|
||||
return r, p
|
||||
|
||||
def _round_order(round_num: int, order_type: OrderType, r1: Sequence[Any]) -> Sequence[Any]:
|
||||
if order_type == "linear" or (round_num % 2 == 1):
|
||||
return r1
|
||||
return list(reversed(r1)) # even rounds in snake
|
||||
Reference in New Issue
Block a user