- Add worker-api/ with TypeScript + Wrangler setup - D1 database schema (bots, matches, jobs, rating_history) - Glicko-2 rating system implementation with unit tests - Job coordination endpoints (claim, heartbeat, result, fail) - Bot management endpoints (register, list, update, rotate-key) - Cron handlers (matchmaker, health checker, stale job reaper) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
112 lines
3.7 KiB
SQL
112 lines
3.7 KiB
SQL
-- AI Code Battle D1 Schema
|
|
-- Phase 4: Match Orchestration
|
|
|
|
-- Bots table: stores registered bots
|
|
CREATE TABLE IF NOT EXISTS bots (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
owner_id TEXT NOT NULL,
|
|
endpoint_url TEXT NOT NULL,
|
|
api_key_hash TEXT NOT NULL,
|
|
rating REAL NOT NULL DEFAULT 1500.0,
|
|
rating_deviation REAL NOT NULL DEFAULT 350.0,
|
|
rating_volatility REAL NOT NULL DEFAULT 0.06,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
last_health_check TEXT,
|
|
health_status TEXT DEFAULT 'unknown',
|
|
matches_played INTEGER NOT NULL DEFAULT 0,
|
|
matches_won INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_bots_owner ON bots(owner_id);
|
|
CREATE INDEX IF NOT EXISTS idx_bots_rating ON bots(rating DESC);
|
|
|
|
-- Matches table: stores match metadata
|
|
CREATE TABLE IF NOT EXISTS matches (
|
|
id TEXT PRIMARY KEY,
|
|
status TEXT NOT NULL DEFAULT 'pending',
|
|
winner_id TEXT,
|
|
turns INTEGER,
|
|
end_reason TEXT,
|
|
map_id TEXT NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
started_at TEXT,
|
|
completed_at TEXT
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_matches_status ON matches(status);
|
|
CREATE INDEX IF NOT EXISTS idx_matches_created ON matches(created_at DESC);
|
|
|
|
-- Match participants: links bots to matches
|
|
CREATE TABLE IF NOT EXISTS match_participants (
|
|
id TEXT PRIMARY KEY,
|
|
match_id TEXT NOT NULL,
|
|
bot_id TEXT NOT NULL,
|
|
player_index INTEGER NOT NULL,
|
|
score INTEGER NOT NULL DEFAULT 0,
|
|
rating_before REAL NOT NULL,
|
|
rating_after REAL,
|
|
rating_deviation_before REAL NOT NULL,
|
|
rating_deviation_after REAL,
|
|
FOREIGN KEY (match_id) REFERENCES matches(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (bot_id) REFERENCES bots(id) ON DELETE CASCADE,
|
|
UNIQUE(match_id, bot_id),
|
|
UNIQUE(match_id, player_index)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_match_participants_match ON match_participants(match_id);
|
|
CREATE INDEX IF NOT EXISTS idx_match_participants_bot ON match_participants(bot_id);
|
|
|
|
-- Jobs table: match execution jobs for workers
|
|
CREATE TABLE IF NOT EXISTS jobs (
|
|
id TEXT PRIMARY KEY,
|
|
match_id TEXT NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'pending',
|
|
worker_id TEXT,
|
|
claimed_at TEXT,
|
|
heartbeat_at TEXT,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
completed_at TEXT,
|
|
error_message TEXT,
|
|
FOREIGN KEY (match_id) REFERENCES matches(id) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_jobs_status ON jobs(status);
|
|
CREATE INDEX IF NOT EXISTS idx_jobs_worker ON jobs(worker_id);
|
|
CREATE INDEX IF NOT EXISTS idx_jobs_heartbeat ON jobs(heartbeat_at);
|
|
|
|
-- Rating history: tracks rating changes over time
|
|
CREATE TABLE IF NOT EXISTS rating_history (
|
|
id TEXT PRIMARY KEY,
|
|
bot_id TEXT NOT NULL,
|
|
match_id TEXT NOT NULL,
|
|
rating_before REAL NOT NULL,
|
|
rating_after REAL NOT NULL,
|
|
rating_deviation REAL NOT NULL,
|
|
recorded_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
FOREIGN KEY (bot_id) REFERENCES bots(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (match_id) REFERENCES matches(id) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_rating_history_bot ON rating_history(bot_id);
|
|
CREATE INDEX IF NOT EXISTS idx_rating_history_time ON rating_history(recorded_at DESC);
|
|
|
|
-- Maps table: stores generated maps
|
|
CREATE TABLE IF NOT EXISTS maps (
|
|
id TEXT PRIMARY KEY,
|
|
width INTEGER NOT NULL,
|
|
height INTEGER NOT NULL,
|
|
walls TEXT NOT NULL,
|
|
spawns TEXT NOT NULL,
|
|
cores TEXT NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
-- Bot secrets: stores API keys for bots (separate for security)
|
|
CREATE TABLE IF NOT EXISTS bot_secrets (
|
|
bot_id TEXT PRIMARY KEY,
|
|
api_key_hash TEXT NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
FOREIGN KEY (bot_id) REFERENCES bots(id) ON DELETE CASCADE
|
|
);
|