import logging import os import sys # Add parent directory to path to allow importing web module sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from web.services.feature_service import FeatureService from web.config import Config from web.app import create_app import sqlite3 # Setup logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) L3_DB_PATH = Config.DB_L3_PATH SCHEMA_PATH = os.path.join(Config.BASE_DIR, 'database', 'L3', 'schema.sql') def _get_existing_columns(conn, table_name): cur = conn.execute(f"PRAGMA table_info({table_name})") return {row[1] for row in cur.fetchall()} def _ensure_columns(conn, table_name, columns): existing = _get_existing_columns(conn, table_name) for col, col_type in columns.items(): if col in existing: continue conn.execute(f"ALTER TABLE {table_name} ADD COLUMN {col} {col_type}") def init_db(): l3_dir = os.path.dirname(L3_DB_PATH) if not os.path.exists(l3_dir): os.makedirs(l3_dir) conn = sqlite3.connect(L3_DB_PATH) with open(SCHEMA_PATH, 'r', encoding='utf-8') as f: conn.executescript(f.read()) _ensure_columns( conn, "dm_player_features", { "rd_phase_kill_early_share": "REAL", "rd_phase_kill_mid_share": "REAL", "rd_phase_kill_late_share": "REAL", "rd_phase_death_early_share": "REAL", "rd_phase_death_mid_share": "REAL", "rd_phase_death_late_share": "REAL", "rd_phase_kill_early_share_t": "REAL", "rd_phase_kill_mid_share_t": "REAL", "rd_phase_kill_late_share_t": "REAL", "rd_phase_kill_early_share_ct": "REAL", "rd_phase_kill_mid_share_ct": "REAL", "rd_phase_kill_late_share_ct": "REAL", "rd_phase_death_early_share_t": "REAL", "rd_phase_death_mid_share_t": "REAL", "rd_phase_death_late_share_t": "REAL", "rd_phase_death_early_share_ct": "REAL", "rd_phase_death_mid_share_ct": "REAL", "rd_phase_death_late_share_ct": "REAL", "rd_firstdeath_team_first_death_rounds": "INTEGER", "rd_firstdeath_team_first_death_win_rate": "REAL", "rd_invalid_death_rounds": "INTEGER", "rd_invalid_death_rate": "REAL", "rd_pressure_kpr_ratio": "REAL", "rd_pressure_perf_ratio": "REAL", "rd_pressure_rounds_down3": "INTEGER", "rd_pressure_rounds_normal": "INTEGER", "rd_matchpoint_kpr_ratio": "REAL", "rd_matchpoint_perf_ratio": "REAL", "rd_matchpoint_rounds": "INTEGER", "rd_comeback_kill_share": "REAL", "rd_comeback_rounds": "INTEGER", "rd_trade_response_10s_rate": "REAL", "rd_weapon_top_json": "TEXT", "rd_roundtype_split_json": "TEXT", "map_stability_coef": "REAL", "basic_avg_knife_kill": "REAL", "basic_avg_zeus_kill": "REAL", "basic_zeus_pick_rate": "REAL", }, ) conn.commit() conn.close() logger.info("L3 DB Initialized/Updated with Schema.") def main(): logger.info("Starting L3 Builder (Delegating to FeatureService)...") # 1. Ensure Schema is up to date init_db() # 2. Rebuild Features using the centralized logic try: app = create_app() with app.app_context(): count = FeatureService.rebuild_all_features() logger.info(f"Successfully rebuilt features for {count} players.") except Exception as e: logger.error(f"Error rebuilding features: {e}") import traceback traceback.print_exc() if __name__ == "__main__": main()