Files
website/dev/populate-db/populate.py
T

145 lines
4.0 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
import argparse
import os
import sqlite3
import sys
from pathlib import Path
import requests
def find_project_root():
direnv_file = os.environ.get("DIRENV_FILE")
if direnv_file:
return Path(direnv_file).parent.resolve()
direnv_dir = os.environ.get("DIRENV_DIR")
if direnv_dir:
return Path(direnv_dir).resolve()
cwd = Path.cwd().resolve()
for parent in [cwd] + list(cwd.parents):
if (parent / "flake.nix").exists():
return parent
raise RuntimeError(
"Cannot find project root. Set DIRENV_FILE or DIRENV_DIR, "
"or run from within the project tree."
)
def fetch_json(api_root, path):
url = f"{api_root}{path}"
resp = requests.get(url, timeout=30)
resp.raise_for_status()
return resp.json()
def main():
parser = argparse.ArgumentParser(
description="Populate a local SQLite DB from production data"
)
parser.add_argument(
"--url",
default=os.environ.get("PHENIX_URL", "https://ballephenix.com"),
help="Source API root (default: https://ballephenix.com)",
)
parser.add_argument(
"--db",
default=None,
help="Path to SQLite DB (default: <project-root>/phenix.db)",
)
parser.add_argument(
"--force",
action="store_true",
help="Clear existing games before inserting",
)
args = parser.parse_args()
api_root = args.url.rstrip("/")
project_root = find_project_root()
db_path = Path(args.db) if args.db else project_root / "phenix.db"
years = fetch_json(api_root, "/api/available-years.json")
print(f"Years on source: {len(years)} ({min(years)}–{max(years)})")
all_games = []
for year in years:
games = fetch_json(api_root, f"/api/results/{year}.json")
all_games.extend(games)
print(f"Total games fetched: {len(all_games)}")
conn = sqlite3.connect(str(db_path))
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS games (
id TEXT PRIMARY KEY,
date TEXT NOT NULL,
time TEXT NOT NULL,
home TEXT NOT NULL,
away TEXT NOT NULL,
year INTEGER NOT NULL,
home_score INTEGER,
away_score INTEGER,
practice INTEGER NOT NULL DEFAULT 0,
rain INTEGER NOT NULL DEFAULT 0,
UNIQUE(date, time)
)
""")
if args.force:
cursor.execute("DELETE FROM games")
print("Cleared existing games")
inserted = 0
skipped = 0
errors = 0
for g in all_games:
try:
home_score = int(g["homeScore"]) if g.get("homeScore") is not None else None
away_score = int(g["awayScore"]) if g.get("awayScore") is not None else None
except (ValueError, TypeError):
home_score = None
away_score = None
try:
cursor.execute(
"""
INSERT OR IGNORE INTO games
(id, date, time, home, away, year, home_score, away_score, practice, rain)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
g.get("id", ""),
g["date"],
g.get("time", ""),
g.get("home", ""),
g.get("away", ""),
g.get("year", 0),
home_score,
away_score,
1 if g.get("practice") else 0,
1 if g.get("rain") else 0,
),
)
if cursor.rowcount > 0:
inserted += 1
else:
skipped += 1
except sqlite3.Error as e:
print(f"DB error on {g.get('date')} {g.get('time')}: {e}", file=sys.stderr)
errors += 1
conn.commit()
conn.close()
print(f"Inserted: {inserted}, skipped: {skipped}, errors: {errors}")
print(f"Database: {db_path}")
if __name__ == "__main__":
main()