синхронизация текущего времени матча во всех браузерах, тест 1
This commit is contained in:
78
app.py
78
app.py
@@ -440,6 +440,49 @@ def logout(request: Request):
|
||||
return response
|
||||
|
||||
|
||||
|
||||
class ClockStatePayload(BaseModel):
|
||||
currentPeriod: str | None = None
|
||||
matchClockSeconds: int = 0
|
||||
timerRunning: bool = False
|
||||
pausedAccumulatedSeconds: int | None = None
|
||||
sourceClientId: str | None = None
|
||||
|
||||
|
||||
# Простое общее состояние часов для всех браузеров.
|
||||
# localStorage остаётся резервом на стороне клиента.
|
||||
MATCH_CLOCK_STATES: Dict[int, dict] = {}
|
||||
|
||||
|
||||
def build_clock_state_payload(match_id: int) -> dict:
|
||||
state = MATCH_CLOCK_STATES.get(match_id)
|
||||
if not state:
|
||||
return {
|
||||
"exists": False,
|
||||
"currentPeriod": None,
|
||||
"matchClockSeconds": 0,
|
||||
"timerRunning": False,
|
||||
"serverSavedAt": None,
|
||||
"sourceClientId": None,
|
||||
}
|
||||
|
||||
seconds = int(state.get("matchClockSeconds") or 0)
|
||||
timer_running = bool(state.get("timerRunning"))
|
||||
saved_at = float(state.get("serverSavedAt") or time.time())
|
||||
|
||||
if timer_running:
|
||||
seconds += max(0, int(time.time() - saved_at))
|
||||
|
||||
return {
|
||||
"exists": True,
|
||||
"currentPeriod": state.get("currentPeriod"),
|
||||
"matchClockSeconds": max(0, seconds),
|
||||
"timerRunning": timer_running,
|
||||
"serverSavedAt": saved_at,
|
||||
"sourceClientId": state.get("sourceClientId"),
|
||||
}
|
||||
|
||||
|
||||
class MatchEventPayload(BaseModel):
|
||||
side: str
|
||||
type: str
|
||||
@@ -1082,6 +1125,41 @@ def save_formation(session_token: str, payload: FormationSavePayload):
|
||||
return {"success": True}
|
||||
|
||||
|
||||
@app.get("/admin/session/{session_token}/clock-state")
|
||||
def api_get_clock_state(session_token: str):
|
||||
session_row = get_match_session_by_token(session_token)
|
||||
if not session_row:
|
||||
return JSONResponse({"error": "session_not_found"}, status_code=404)
|
||||
|
||||
match_id = session_row[1]
|
||||
return build_clock_state_payload(match_id)
|
||||
|
||||
|
||||
@app.post("/admin/session/{session_token}/clock-state")
|
||||
def api_save_clock_state(session_token: str, payload: ClockStatePayload):
|
||||
session_row = get_match_session_by_token(session_token)
|
||||
if not session_row:
|
||||
return JSONResponse({"error": "session_not_found"}, status_code=404)
|
||||
|
||||
match_id = session_row[1]
|
||||
seconds = max(0, int(payload.matchClockSeconds or 0))
|
||||
|
||||
MATCH_CLOCK_STATES[match_id] = {
|
||||
"currentPeriod": payload.currentPeriod,
|
||||
"matchClockSeconds": seconds,
|
||||
"timerRunning": bool(payload.timerRunning),
|
||||
"pausedAccumulatedSeconds": (
|
||||
int(payload.pausedAccumulatedSeconds)
|
||||
if payload.pausedAccumulatedSeconds is not None
|
||||
else seconds
|
||||
),
|
||||
"serverSavedAt": time.time(),
|
||||
"sourceClientId": payload.sourceClientId,
|
||||
}
|
||||
|
||||
return build_clock_state_payload(match_id)
|
||||
|
||||
|
||||
@app.get("/admin/session/{session_token}/events")
|
||||
def api_get_events(session_token: str):
|
||||
session_row = get_match_session_by_token(session_token)
|
||||
|
||||
Reference in New Issue
Block a user