"""Minimal Flask app for Hugging Face Docker Space: landing, analysis, replay placeholder.""" from __future__ import annotations from pathlib import Path import duckdb from flask import Flask, render_template, request APP_DIR = Path(__file__).resolve().parent DEMO_CSV = APP_DIR / "demo_data" / "demo_trials.csv" PRESETS: list[dict[str, str]] = [ { "id": "summary", "label": "Summary (count, mean RT, age range)", "sql": """ SELECT COUNT(*)::INT AS n_trials, ROUND(AVG(rt_ms), 2) AS mean_rt_ms, MIN(age)::INT AS min_age, MAX(age)::INT AS max_age FROM read_csv_auto(?) """, }, { "id": "by_age", "label": "Mean RT by age", "sql": """ SELECT age, COUNT(*)::INT AS n_trials, ROUND(AVG(rt_ms), 2) AS mean_rt_ms FROM read_csv_auto(?) GROUP BY age ORDER BY age """, }, ] PRESET_CHOICES = [{"id": p["id"], "label": p["label"]} for p in PRESETS] def create_app() -> Flask: app = Flask(__name__, static_folder="static", template_folder="templates") @app.get("/health") def health() -> tuple[str, int]: return "ok", 200 @app.get("/") def landing(): return render_template("landing.html") @app.get("/analysis") def analysis(): preset_id = (request.args.get("preset") or "summary").strip() preset = next((p for p in PRESETS if p["id"] == preset_id), PRESETS[0]) error: str | None = None table_html: str | None = None if not DEMO_CSV.is_file(): error = f"Demo data missing at {DEMO_CSV}" else: try: con = duckdb.connect(database=":memory:") rel = con.execute(preset["sql"], [str(DEMO_CSV)]) df = rel.fetchdf() table_html = df.to_html(classes="data", index=False, border=0) except Exception as exc: # noqa: BLE001 — surface query errors in the UI error = str(exc) return render_template( "analysis.html", presets=PRESET_CHOICES, current_preset=preset["id"], table_html=table_html, error=error, ) @app.get("/replay") def replay(): return render_template("replay.html") return app app = create_app()