first commit
This commit is contained in:
178
repositories/match_clock_repository.py
Normal file
178
repositories/match_clock_repository.py
Normal file
@@ -0,0 +1,178 @@
|
||||
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)
|
||||
Reference in New Issue
Block a user