- Complete rewrite for single Court Manager user - Feature 1: Player Management (CRUD, ELO, skill level) - Feature 2: Court Reservation (timeline, override) - Feature 3: Match Event Builder (3-step wizard) - Step 1: Event setup with player selection + stage calculator - Step 2: Stage configurator (Open/Skill/RR/Tournament) - Step 3: Auto bracket generation - Feature 4: Live Court View (main dashboard, 2x2 grid) - Event Control: score entry, bracket advancement, court assignment - Screen view: TV display per court (/screen/:id) - Seed: 8 players, 4 courts, 1 completed + 1 active event - Routes: / players courts events events/new events/:id screen/:id
164 lines
3.7 KiB
Python
164 lines
3.7 KiB
Python
from typing import Optional, List
|
|
from pydantic import BaseModel
|
|
from datetime import datetime
|
|
|
|
|
|
# Player schemas
|
|
class PlayerCreate(BaseModel):
|
|
name: str
|
|
contact: Optional[str] = None
|
|
skill_level: str = "Beginner"
|
|
|
|
class PlayerUpdate(BaseModel):
|
|
name: Optional[str] = None
|
|
contact: Optional[str] = None
|
|
skill_level: Optional[str] = None
|
|
|
|
class PlayerOut(BaseModel):
|
|
id: int
|
|
name: str
|
|
contact: Optional[str]
|
|
skill_level: str
|
|
matches_played: int
|
|
wins: int
|
|
losses: int
|
|
elo: float
|
|
created_at: datetime
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Court schemas
|
|
class CourtCreate(BaseModel):
|
|
name: str
|
|
court_type: str = "Sport Court"
|
|
|
|
class CourtStatusUpdate(BaseModel):
|
|
status: str # available/in_use/reserved/maintenance
|
|
|
|
class ReservationCreate(BaseModel):
|
|
player_id: Optional[int] = None
|
|
group_name: Optional[str] = None
|
|
start_time: datetime
|
|
end_time: datetime
|
|
notes: Optional[str] = None
|
|
|
|
class ReservationOut(BaseModel):
|
|
id: int
|
|
court_id: int
|
|
player_id: Optional[int]
|
|
group_name: Optional[str]
|
|
start_time: datetime
|
|
end_time: datetime
|
|
notes: Optional[str]
|
|
player: Optional[PlayerOut] = None
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
class CourtOut(BaseModel):
|
|
id: int
|
|
name: str
|
|
court_type: str
|
|
status: str
|
|
reservations: List[ReservationOut] = []
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Event schemas
|
|
class EventCreate(BaseModel):
|
|
name: str
|
|
format: str = "Singles"
|
|
courts_count: int = 1
|
|
|
|
class EventUpdate(BaseModel):
|
|
name: Optional[str] = None
|
|
format: Optional[str] = None
|
|
courts_count: Optional[int] = None
|
|
|
|
class EventPlayerAdd(BaseModel):
|
|
player_id: int
|
|
skill_level_override: Optional[str] = None
|
|
|
|
class EventPlayerOut(BaseModel):
|
|
id: int
|
|
player_id: int
|
|
skill_level_override: Optional[str]
|
|
player: PlayerOut
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Stage schemas
|
|
class StageCreate(BaseModel):
|
|
name: str
|
|
match_type: str # Open/Skill-Based/Round Robin/Tournament
|
|
rounds: int = 1
|
|
advance_count: int = 0
|
|
order: int = 0
|
|
|
|
class StageUpdate(BaseModel):
|
|
name: Optional[str] = None
|
|
match_type: Optional[str] = None
|
|
rounds: Optional[int] = None
|
|
advance_count: Optional[int] = None
|
|
|
|
class StageOut(BaseModel):
|
|
id: int
|
|
event_id: int
|
|
name: str
|
|
match_type: str
|
|
rounds: int
|
|
advance_count: int
|
|
status: str
|
|
order: int
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Match schemas
|
|
class MatchScoreUpdate(BaseModel):
|
|
score1: int
|
|
score2: int
|
|
|
|
class MatchCourtAssign(BaseModel):
|
|
court_id: Optional[int]
|
|
|
|
class MatchOut(BaseModel):
|
|
id: int
|
|
stage_id: int
|
|
court_id: Optional[int]
|
|
round_number: int
|
|
match_number: int
|
|
player1_id: Optional[int]
|
|
player2_id: Optional[int]
|
|
team1_players: Optional[List[int]]
|
|
team2_players: Optional[List[int]]
|
|
score1: Optional[int]
|
|
score2: Optional[int]
|
|
winner_id: Optional[int]
|
|
winner_team: Optional[int]
|
|
status: str
|
|
bracket_position: Optional[str]
|
|
next_winner_match_id: Optional[int]
|
|
next_loser_match_id: Optional[int]
|
|
scheduled_time: Optional[datetime]
|
|
started_at: Optional[datetime]
|
|
completed_at: Optional[datetime]
|
|
player1: Optional[PlayerOut] = None
|
|
player2: Optional[PlayerOut] = None
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Dashboard schema
|
|
class DashboardCourtData(BaseModel):
|
|
court: CourtOut
|
|
current_match: Optional[MatchOut] = None
|
|
elapsed_seconds: Optional[int] = None
|
|
|
|
class DashboardData(BaseModel):
|
|
courts: List[DashboardCourtData]
|
|
upcoming_matches: List[MatchOut]
|
|
active_event: Optional[dict] = None
|