Ship Steam login, D1 player sync, and cached「我」dashboard.
Players get a fast TTL-backed homepage (local profile / Cloudflare D1) with dense UI polish; login unlocks /home without blocking on every OpenDota refresh. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
-- Climperor multi-user player data (D1 climperor-users)
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
account_id INTEGER PRIMARY KEY,
|
||||
steamid TEXT NOT NULL UNIQUE,
|
||||
personaname TEXT,
|
||||
avatar TEXT,
|
||||
public_share INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL,
|
||||
last_login_at TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS player_profiles (
|
||||
account_id INTEGER PRIMARY KEY REFERENCES users(account_id),
|
||||
rank_tier INTEGER,
|
||||
leaderboard_rank INTEGER,
|
||||
availability_status TEXT,
|
||||
availability_note TEXT,
|
||||
availability_complete INTEGER NOT NULL DEFAULT 0,
|
||||
source TEXT,
|
||||
fetched_at TEXT,
|
||||
enriched_at TEXT,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS player_stats (
|
||||
account_id INTEGER NOT NULL REFERENCES users(account_id),
|
||||
scope TEXT NOT NULL, -- career | recent20 | recent180
|
||||
sample INTEGER NOT NULL DEFAULT 0,
|
||||
wins INTEGER NOT NULL DEFAULT 0,
|
||||
losses INTEGER NOT NULL DEFAULT 0,
|
||||
winrate REAL,
|
||||
kills INTEGER,
|
||||
deaths INTEGER,
|
||||
assists INTEGER,
|
||||
kda REAL,
|
||||
avg_kills REAL,
|
||||
avg_deaths REAL,
|
||||
avg_assists REAL,
|
||||
avg_gpm REAL,
|
||||
avg_xpm REAL,
|
||||
avg_hero_damage REAL,
|
||||
payload_json TEXT,
|
||||
updated_at TEXT NOT NULL,
|
||||
PRIMARY KEY (account_id, scope)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS player_heroes (
|
||||
account_id INTEGER NOT NULL REFERENCES users(account_id),
|
||||
hero_id INTEGER NOT NULL,
|
||||
hero_key TEXT,
|
||||
hero_name_loc TEXT,
|
||||
games INTEGER NOT NULL DEFAULT 0,
|
||||
wins INTEGER NOT NULL DEFAULT 0,
|
||||
winrate REAL,
|
||||
last_played INTEGER,
|
||||
updated_at TEXT NOT NULL,
|
||||
PRIMARY KEY (account_id, hero_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS player_matches (
|
||||
account_id INTEGER NOT NULL REFERENCES users(account_id),
|
||||
match_id INTEGER NOT NULL,
|
||||
start_time INTEGER,
|
||||
duration INTEGER,
|
||||
won INTEGER,
|
||||
hero_id INTEGER,
|
||||
hero_key TEXT,
|
||||
hero_name_loc TEXT,
|
||||
kills INTEGER,
|
||||
deaths INTEGER,
|
||||
assists INTEGER,
|
||||
kda REAL,
|
||||
gpm INTEGER,
|
||||
xpm INTEGER,
|
||||
hero_damage INTEGER,
|
||||
game_mode INTEGER,
|
||||
lobby_type INTEGER,
|
||||
r2_key TEXT,
|
||||
updated_at TEXT NOT NULL,
|
||||
PRIMARY KEY (account_id, match_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_player_matches_start
|
||||
ON player_matches(account_id, start_time DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS player_peers (
|
||||
account_id INTEGER NOT NULL REFERENCES users(account_id),
|
||||
peer_account_id INTEGER NOT NULL,
|
||||
personaname TEXT,
|
||||
avatar TEXT,
|
||||
games INTEGER NOT NULL DEFAULT 0,
|
||||
wins INTEGER NOT NULL DEFAULT 0,
|
||||
winrate REAL,
|
||||
updated_at TEXT NOT NULL,
|
||||
PRIMARY KEY (account_id, peer_account_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sync_jobs (
|
||||
id TEXT PRIMARY KEY,
|
||||
account_id INTEGER NOT NULL,
|
||||
kind TEXT NOT NULL, -- login_refresh | publish_match | backfill
|
||||
match_id INTEGER,
|
||||
status TEXT NOT NULL, -- queued | running | done | error
|
||||
attempts INTEGER NOT NULL DEFAULT 0,
|
||||
lease_until TEXT,
|
||||
error TEXT,
|
||||
next_retry_at TEXT,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_sync_jobs_status
|
||||
ON sync_jobs(status, next_retry_at);
|
||||
Reference in New Issue
Block a user