Files
SkinsPins/app/database.py
T
Rolf 8601584099 Add playing handicap, 6-digit login code, and game UX improvements
- Playing handicap: computed at game creation (WHS formula), stored on
  game_players alongside per-hole strokes allocation; displayed on game
  summary with HC card and / markers on scorecard (only when SI defined);
  live game shows +N per player card when SI exists, HC total otherwise;
  new game confirmation previews computed HC per player

- Login: 6-digit code sent alongside magic link in every auth email;
  check_email page has auto-advancing digit inputs with paste support;
  new POST /auth/verify-code route handles code verification

- Game view: Score/Card toggle fixed with position:fixed to always show
  above nav bar on mobile; swipe on score view changes holes, swipe on
  scorecard switches tabs; dirty tracking prevents saving unmodified holes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 20:37:08 +01:00

133 lines
4.9 KiB
Python

import os
import aiosqlite
DATABASE_PATH = os.getenv("DATABASE_PATH", "/data/skinspins.db")
async def get_db():
async with aiosqlite.connect(DATABASE_PATH) as db:
db.row_factory = aiosqlite.Row
yield db
async def init_db():
async with aiosqlite.connect(DATABASE_PATH) as db:
await db.executescript("""
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
name TEXT,
handicap REAL,
avatar TEXT,
is_onboarded INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS invitations (
id TEXT PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
invited_by TEXT NOT NULL,
created_at TEXT NOT NULL,
FOREIGN KEY (invited_by) REFERENCES users(id)
);
CREATE TABLE IF NOT EXISTS magic_link_tokens (
id TEXT PRIMARY KEY,
email TEXT NOT NULL,
token TEXT UNIQUE NOT NULL,
expires_at TEXT NOT NULL,
used_at TEXT
);
CREATE TABLE IF NOT EXISTS sessions (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
token TEXT UNIQUE NOT NULL,
expires_at TEXT NOT NULL,
created_at TEXT NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE TABLE IF NOT EXISTS courses (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
holes INTEGER NOT NULL DEFAULT 18,
location TEXT,
created_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS course_holes (
id TEXT PRIMARY KEY,
course_id TEXT NOT NULL,
hole_number INTEGER NOT NULL,
par INTEGER NOT NULL DEFAULT 4,
UNIQUE (course_id, hole_number),
FOREIGN KEY (course_id) REFERENCES courses(id)
);
CREATE TABLE IF NOT EXISTS course_tees (
id TEXT PRIMARY KEY,
course_id TEXT NOT NULL,
name TEXT NOT NULL,
slope INTEGER NOT NULL,
rating REAL NOT NULL,
FOREIGN KEY (course_id) REFERENCES courses(id)
);
CREATE TABLE IF NOT EXISTS games (
id TEXT PRIMARY KEY,
format TEXT NOT NULL DEFAULT 'bingo_bango_bongo',
holes_count INTEGER NOT NULL,
status TEXT NOT NULL DEFAULT 'lobby',
created_by TEXT NOT NULL,
created_at TEXT NOT NULL,
course_id TEXT,
FOREIGN KEY (created_by) REFERENCES users(id),
FOREIGN KEY (course_id) REFERENCES courses(id)
);
CREATE TABLE IF NOT EXISTS game_players (
id TEXT PRIMARY KEY,
game_id TEXT NOT NULL,
user_id TEXT NOT NULL,
handicap_snapshot REAL,
joined_at TEXT NOT NULL,
UNIQUE (game_id, user_id),
FOREIGN KEY (game_id) REFERENCES games(id),
FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE TABLE IF NOT EXISTS hole_scores (
id TEXT PRIMARY KEY,
game_id TEXT NOT NULL,
hole_number INTEGER NOT NULL,
user_id TEXT NOT NULL,
strokes INTEGER,
bingo INTEGER NOT NULL DEFAULT 0,
bango REAL NOT NULL DEFAULT 0.0,
bongo INTEGER NOT NULL DEFAULT 0,
updated_by TEXT NOT NULL,
updated_at TEXT NOT NULL,
UNIQUE (game_id, hole_number, user_id),
FOREIGN KEY (game_id) REFERENCES games(id),
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (updated_by) REFERENCES users(id)
);
""")
await db.commit()
# Migrations for columns added after initial release
for migration in [
"ALTER TABLE games ADD COLUMN course_id TEXT REFERENCES courses(id)",
"ALTER TABLE game_players ADD COLUMN tee_id TEXT REFERENCES course_tees(id)",
"ALTER TABLE course_holes ADD COLUMN stroke_index INTEGER",
"ALTER TABLE games ADD COLUMN carryover INTEGER NOT NULL DEFAULT 1",
"ALTER TABLE game_players ADD COLUMN playing_handicap INTEGER",
"ALTER TABLE game_players ADD COLUMN strokes_allocation TEXT",
"ALTER TABLE magic_link_tokens ADD COLUMN code TEXT",
]:
try:
await db.execute(migration)
await db.commit()
except Exception:
pass # column already exists