-- Enable Foreign Keys PRAGMA foreign_keys = ON; -- 1. Dimension: Players -- Stores persistent player information. -- Conflict resolution: UPSERT on steam_id_64. CREATE TABLE IF NOT EXISTS dim_players ( steam_id_64 TEXT PRIMARY KEY, uid INTEGER, -- 5E Platform ID username TEXT, avatar_url TEXT, domain TEXT, created_at INTEGER, -- Timestamp updated_at INTEGER, -- Timestamp last_seen_match_id TEXT -- To track when this info was last updated ); CREATE INDEX IF NOT EXISTS idx_dim_players_uid ON dim_players(uid); -- 2. Dimension: Maps CREATE TABLE IF NOT EXISTS dim_maps ( map_id INTEGER PRIMARY KEY AUTOINCREMENT, map_name TEXT UNIQUE NOT NULL, map_desc TEXT ); -- 3. Fact: Matches CREATE TABLE IF NOT EXISTS fact_matches ( match_id TEXT PRIMARY KEY, match_code TEXT, map_name TEXT, start_time INTEGER, end_time INTEGER, duration INTEGER, winner_team INTEGER, -- 1 or 2 score_team1 INTEGER, score_team2 INTEGER, server_ip TEXT, server_port INTEGER, location TEXT, data_source_type TEXT CHECK(data_source_type IN ('leetify', 'classic', 'unknown')), -- 'leetify' has economy data, 'classic' has detailed xyz processed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_fact_matches_time ON fact_matches(start_time); -- 4. Fact: Match Player Stats (Wide Table) -- Aggregated stats for a player in a specific match CREATE TABLE IF NOT EXISTS fact_match_players ( match_id TEXT, steam_id_64 TEXT, team_id INTEGER, -- 1 or 2 -- Basic Stats kills INTEGER DEFAULT 0, deaths INTEGER DEFAULT 0, assists INTEGER DEFAULT 0, headshot_count INTEGER DEFAULT 0, kd_ratio REAL, adr REAL, rating REAL, -- 5E Rating rating2 REAL, rating3 REAL, rws REAL, mvp_count INTEGER DEFAULT 0, elo_change REAL, rank_score INTEGER, is_win BOOLEAN, -- Advanced Stats (VIP/Plus) kast REAL, entry_kills INTEGER, entry_deaths INTEGER, awp_kills INTEGER, clutch_1v1 INTEGER, clutch_1v2 INTEGER, clutch_1v3 INTEGER, clutch_1v4 INTEGER, clutch_1v5 INTEGER, flash_assists INTEGER, flash_duration REAL, jump_count INTEGER, damage_total INTEGER, damage_received INTEGER, assisted_kill INTEGER, awp_kill INTEGER, benefit_kill INTEGER, day TEXT, defused_bomb INTEGER, end_1v1 INTEGER, end_1v2 INTEGER, end_1v3 INTEGER, end_1v4 INTEGER, end_1v5 INTEGER, explode_bomb INTEGER, first_death INTEGER, first_kill INTEGER, flash_enemy INTEGER, flash_team INTEGER, flash_team_time REAL, flash_time REAL, game_mode TEXT, group_id INTEGER, hold_total INTEGER, id INTEGER, is_highlight INTEGER, is_most_1v2 INTEGER, is_most_assist INTEGER, is_most_awp INTEGER, is_most_end INTEGER, is_most_first_kill INTEGER, is_most_headshot INTEGER, is_most_jump INTEGER, is_svp INTEGER, is_tie INTEGER, kill_1 INTEGER, kill_2 INTEGER, kill_3 INTEGER, kill_4 INTEGER, kill_5 INTEGER, many_assists_cnt1 INTEGER, many_assists_cnt2 INTEGER, many_assists_cnt3 INTEGER, many_assists_cnt4 INTEGER, many_assists_cnt5 INTEGER, map TEXT, match_code TEXT, match_mode TEXT, match_team_id INTEGER, match_time INTEGER, per_headshot REAL, perfect_kill INTEGER, planted_bomb INTEGER, revenge_kill INTEGER, round_total INTEGER, season TEXT, team_kill INTEGER, throw_harm INTEGER, throw_harm_enemy INTEGER, uid INTEGER, year TEXT, PRIMARY KEY (match_id, steam_id_64), FOREIGN KEY (match_id) REFERENCES fact_matches(match_id) ON DELETE CASCADE -- Intentionally not enforcing FK on steam_id_64 strictly to allow stats even if player dim missing, but ideally it should match. ); CREATE TABLE IF NOT EXISTS fact_match_players_t ( match_id TEXT, steam_id_64 TEXT, team_id INTEGER, kills INTEGER DEFAULT 0, deaths INTEGER DEFAULT 0, assists INTEGER DEFAULT 0, headshot_count INTEGER DEFAULT 0, kd_ratio REAL, adr REAL, rating REAL, rating2 REAL, rating3 REAL, rws REAL, mvp_count INTEGER DEFAULT 0, elo_change REAL, rank_score INTEGER, is_win BOOLEAN, kast REAL, entry_kills INTEGER, entry_deaths INTEGER, awp_kills INTEGER, clutch_1v1 INTEGER, clutch_1v2 INTEGER, clutch_1v3 INTEGER, clutch_1v4 INTEGER, clutch_1v5 INTEGER, flash_assists INTEGER, flash_duration REAL, jump_count INTEGER, damage_total INTEGER, damage_received INTEGER, assisted_kill INTEGER, awp_kill INTEGER, benefit_kill INTEGER, day TEXT, defused_bomb INTEGER, end_1v1 INTEGER, end_1v2 INTEGER, end_1v3 INTEGER, end_1v4 INTEGER, end_1v5 INTEGER, explode_bomb INTEGER, first_death INTEGER, first_kill INTEGER, flash_enemy INTEGER, flash_team INTEGER, flash_team_time REAL, flash_time REAL, game_mode TEXT, group_id INTEGER, hold_total INTEGER, id INTEGER, is_highlight INTEGER, is_most_1v2 INTEGER, is_most_assist INTEGER, is_most_awp INTEGER, is_most_end INTEGER, is_most_first_kill INTEGER, is_most_headshot INTEGER, is_most_jump INTEGER, is_svp INTEGER, is_tie INTEGER, kill_1 INTEGER, kill_2 INTEGER, kill_3 INTEGER, kill_4 INTEGER, kill_5 INTEGER, many_assists_cnt1 INTEGER, many_assists_cnt2 INTEGER, many_assists_cnt3 INTEGER, many_assists_cnt4 INTEGER, many_assists_cnt5 INTEGER, map TEXT, match_code TEXT, match_mode TEXT, match_team_id INTEGER, match_time INTEGER, per_headshot REAL, perfect_kill INTEGER, planted_bomb INTEGER, revenge_kill INTEGER, round_total INTEGER, season TEXT, team_kill INTEGER, throw_harm INTEGER, throw_harm_enemy INTEGER, uid INTEGER, year TEXT, PRIMARY KEY (match_id, steam_id_64), FOREIGN KEY (match_id) REFERENCES fact_matches(match_id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS fact_match_players_ct ( match_id TEXT, steam_id_64 TEXT, team_id INTEGER, kills INTEGER DEFAULT 0, deaths INTEGER DEFAULT 0, assists INTEGER DEFAULT 0, headshot_count INTEGER DEFAULT 0, kd_ratio REAL, adr REAL, rating REAL, rating2 REAL, rating3 REAL, rws REAL, mvp_count INTEGER DEFAULT 0, elo_change REAL, rank_score INTEGER, is_win BOOLEAN, kast REAL, entry_kills INTEGER, entry_deaths INTEGER, awp_kills INTEGER, clutch_1v1 INTEGER, clutch_1v2 INTEGER, clutch_1v3 INTEGER, clutch_1v4 INTEGER, clutch_1v5 INTEGER, flash_assists INTEGER, flash_duration REAL, jump_count INTEGER, damage_total INTEGER, damage_received INTEGER, assisted_kill INTEGER, awp_kill INTEGER, benefit_kill INTEGER, day TEXT, defused_bomb INTEGER, end_1v1 INTEGER, end_1v2 INTEGER, end_1v3 INTEGER, end_1v4 INTEGER, end_1v5 INTEGER, explode_bomb INTEGER, first_death INTEGER, first_kill INTEGER, flash_enemy INTEGER, flash_team INTEGER, flash_team_time REAL, flash_time REAL, game_mode TEXT, group_id INTEGER, hold_total INTEGER, id INTEGER, is_highlight INTEGER, is_most_1v2 INTEGER, is_most_assist INTEGER, is_most_awp INTEGER, is_most_end INTEGER, is_most_first_kill INTEGER, is_most_headshot INTEGER, is_most_jump INTEGER, is_svp INTEGER, is_tie INTEGER, kill_1 INTEGER, kill_2 INTEGER, kill_3 INTEGER, kill_4 INTEGER, kill_5 INTEGER, many_assists_cnt1 INTEGER, many_assists_cnt2 INTEGER, many_assists_cnt3 INTEGER, many_assists_cnt4 INTEGER, many_assists_cnt5 INTEGER, map TEXT, match_code TEXT, match_mode TEXT, match_team_id INTEGER, match_time INTEGER, per_headshot REAL, perfect_kill INTEGER, planted_bomb INTEGER, revenge_kill INTEGER, round_total INTEGER, season TEXT, team_kill INTEGER, throw_harm INTEGER, throw_harm_enemy INTEGER, uid INTEGER, year TEXT, PRIMARY KEY (match_id, steam_id_64), FOREIGN KEY (match_id) REFERENCES fact_matches(match_id) ON DELETE CASCADE ); -- 5. Fact: Rounds CREATE TABLE IF NOT EXISTS fact_rounds ( match_id TEXT, round_num INTEGER, winner_side TEXT CHECK(winner_side IN ('CT', 'T', 'None')), win_reason INTEGER, -- Raw integer from source win_reason_desc TEXT, -- Mapped description (e.g. 'TargetBombed') duration REAL, end_time_stamp TEXT, ct_score INTEGER, t_score INTEGER, -- Leetify Specific ct_money_start INTEGER, t_money_start INTEGER, PRIMARY KEY (match_id, round_num), FOREIGN KEY (match_id) REFERENCES fact_matches(match_id) ON DELETE CASCADE ); -- 6. Fact: Round Events (The largest table) -- Unifies Kills, Bomb Events, etc. CREATE TABLE IF NOT EXISTS fact_round_events ( event_id TEXT PRIMARY KEY, -- UUID match_id TEXT, round_num INTEGER, event_type TEXT CHECK(event_type IN ('kill', 'bomb_plant', 'bomb_defuse', 'suicide', 'unknown')), event_time INTEGER, -- Seconds from round start -- Participants attacker_steam_id TEXT, victim_steam_id TEXT, assister_steam_id TEXT, flash_assist_steam_id TEXT, trade_killer_steam_id TEXT, -- Weapon & Context weapon TEXT, is_headshot BOOLEAN DEFAULT 0, is_wallbang BOOLEAN DEFAULT 0, is_blind BOOLEAN DEFAULT 0, is_through_smoke BOOLEAN DEFAULT 0, is_noscope BOOLEAN DEFAULT 0, -- Spatial Data (From RoundList) attacker_pos_x INTEGER, attacker_pos_y INTEGER, attacker_pos_z INTEGER, victim_pos_x INTEGER, victim_pos_y INTEGER, victim_pos_z INTEGER, -- Economy/Score Impact (From Leetify) score_change_attacker REAL, score_change_victim REAL, FOREIGN KEY (match_id, round_num) REFERENCES fact_rounds(match_id, round_num) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS idx_round_events_match ON fact_round_events(match_id); CREATE INDEX IF NOT EXISTS idx_round_events_attacker ON fact_round_events(attacker_steam_id); -- 7. Fact: Round Player Economy/Status -- Snapshots of player state at round start/end CREATE TABLE IF NOT EXISTS fact_round_player_economy ( match_id TEXT, round_num INTEGER, steam_id_64 TEXT, side TEXT CHECK(side IN ('CT', 'T')), start_money INTEGER, equipment_value INTEGER, -- Inventory Summary main_weapon TEXT, has_helmet BOOLEAN, has_defuser BOOLEAN, -- Round Performance Summary (Leetify) round_performance_score REAL, PRIMARY KEY (match_id, round_num, steam_id_64), FOREIGN KEY (match_id, round_num) REFERENCES fact_rounds(match_id, round_num) ON DELETE CASCADE );