179 lines
6.2 KiB
Python
179 lines
6.2 KiB
Python
from db import get_connection
|
|
|
|
|
|
def create_match_clock_table() -> None:
|
|
query = """
|
|
CREATE TABLE IF NOT EXISTS match_clocks (
|
|
match_id BIGINT PRIMARY KEY REFERENCES matches(id) ON DELETE CASCADE,
|
|
current_period VARCHAR(10) NOT NULL DEFAULT '1H',
|
|
timer_running BOOLEAN NOT NULL DEFAULT FALSE,
|
|
accumulated_seconds INTEGER NOT NULL DEFAULT 0,
|
|
period_started_at TIMESTAMP NULL,
|
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
"""
|
|
|
|
conn = get_connection()
|
|
try:
|
|
with conn.cursor() as cur:
|
|
cur.execute(query)
|
|
conn.commit()
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
def ensure_match_clock(match_id: int) -> None:
|
|
query = """
|
|
INSERT INTO match_clocks (match_id, current_period, timer_running, accumulated_seconds, period_started_at, updated_at)
|
|
VALUES (%s, '1H', FALSE, 0, NULL, NOW())
|
|
ON CONFLICT (match_id) DO NOTHING;
|
|
"""
|
|
|
|
conn = get_connection()
|
|
try:
|
|
with conn.cursor() as cur:
|
|
cur.execute(query, (match_id,))
|
|
conn.commit()
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
def get_match_clock(match_id: int) -> dict:
|
|
ensure_match_clock(match_id)
|
|
|
|
query = """
|
|
SELECT
|
|
match_id,
|
|
current_period,
|
|
timer_running,
|
|
accumulated_seconds,
|
|
period_started_at,
|
|
CASE
|
|
WHEN timer_running = TRUE AND period_started_at IS NOT NULL
|
|
THEN accumulated_seconds + FLOOR(EXTRACT(EPOCH FROM (NOW() - period_started_at)))::INT
|
|
ELSE accumulated_seconds
|
|
END AS current_seconds
|
|
FROM match_clocks
|
|
WHERE match_id = %s;
|
|
"""
|
|
|
|
conn = get_connection()
|
|
try:
|
|
with conn.cursor() as cur:
|
|
cur.execute(query, (match_id,))
|
|
row = cur.fetchone()
|
|
finally:
|
|
conn.close()
|
|
|
|
return {
|
|
"match_id": row[0],
|
|
"current_period": row[1],
|
|
"timer_running": bool(row[2]),
|
|
"accumulated_seconds": row[3] or 0,
|
|
"period_started_at": row[4].isoformat() if row[4] else None,
|
|
"current_seconds": row[5] or 0,
|
|
}
|
|
|
|
|
|
def update_match_clock(match_id: int, action: str, seconds: int | None = None) -> dict:
|
|
ensure_match_clock(match_id)
|
|
|
|
conn = get_connection()
|
|
try:
|
|
with conn.cursor() as cur:
|
|
if action == "start_1h":
|
|
cur.execute(
|
|
"""
|
|
UPDATE match_clocks
|
|
SET current_period = '1H', timer_running = TRUE, accumulated_seconds = 0,
|
|
period_started_at = NOW(), updated_at = NOW()
|
|
WHERE match_id = %s;
|
|
""",
|
|
(match_id,),
|
|
)
|
|
elif action == "pause":
|
|
cur.execute(
|
|
"""
|
|
UPDATE match_clocks
|
|
SET accumulated_seconds = CASE
|
|
WHEN timer_running = TRUE AND period_started_at IS NOT NULL
|
|
THEN accumulated_seconds + FLOOR(EXTRACT(EPOCH FROM (NOW() - period_started_at)))::INT
|
|
ELSE accumulated_seconds
|
|
END,
|
|
timer_running = FALSE,
|
|
period_started_at = NULL,
|
|
updated_at = NOW()
|
|
WHERE match_id = %s;
|
|
""",
|
|
(match_id,),
|
|
)
|
|
elif action == "halftime":
|
|
cur.execute(
|
|
"""
|
|
UPDATE match_clocks
|
|
SET accumulated_seconds = CASE
|
|
WHEN timer_running = TRUE AND period_started_at IS NOT NULL
|
|
THEN accumulated_seconds + FLOOR(EXTRACT(EPOCH FROM (NOW() - period_started_at)))::INT
|
|
ELSE accumulated_seconds
|
|
END,
|
|
current_period = 'HT',
|
|
timer_running = FALSE,
|
|
period_started_at = NULL,
|
|
updated_at = NOW()
|
|
WHERE match_id = %s;
|
|
""",
|
|
(match_id,),
|
|
)
|
|
elif action == "start_2h":
|
|
cur.execute(
|
|
"""
|
|
UPDATE match_clocks
|
|
SET current_period = '2H', timer_running = TRUE,
|
|
accumulated_seconds = CASE WHEN accumulated_seconds < 2700 THEN 2700 ELSE accumulated_seconds END,
|
|
period_started_at = NOW(),
|
|
updated_at = NOW()
|
|
WHERE match_id = %s;
|
|
""",
|
|
(match_id,),
|
|
)
|
|
elif action == "finish":
|
|
cur.execute(
|
|
"""
|
|
UPDATE match_clocks
|
|
SET accumulated_seconds = CASE
|
|
WHEN timer_running = TRUE AND period_started_at IS NOT NULL
|
|
THEN accumulated_seconds + FLOOR(EXTRACT(EPOCH FROM (NOW() - period_started_at)))::INT
|
|
ELSE accumulated_seconds
|
|
END,
|
|
current_period = 'FT',
|
|
timer_running = FALSE,
|
|
period_started_at = NULL,
|
|
updated_at = NOW()
|
|
WHERE match_id = %s;
|
|
""",
|
|
(match_id,),
|
|
)
|
|
elif action == "set_time":
|
|
if seconds is None or not isinstance(seconds, int) or seconds < 0:
|
|
raise ValueError("invalid_seconds")
|
|
cur.execute(
|
|
"""
|
|
UPDATE match_clocks
|
|
SET accumulated_seconds = %s,
|
|
period_started_at = CASE WHEN timer_running THEN NOW() ELSE NULL END,
|
|
updated_at = NOW()
|
|
WHERE match_id = %s;
|
|
""",
|
|
(seconds, match_id),
|
|
)
|
|
else:
|
|
raise ValueError("invalid_clock_action")
|
|
conn.commit()
|
|
except Exception:
|
|
conn.rollback()
|
|
raise
|
|
finally:
|
|
conn.close()
|
|
|
|
return get_match_clock(match_id)
|