""" Match Processor - Handles fact_matches and fact_match_teams Responsibilities: - Extract match basic information from JSON - Process team data (group1/group2) - Store raw JSON fields (treat_info, response metadata) - Set data_source_type marker """ import sqlite3 import json import logging from typing import Any, Dict logger = logging.getLogger(__name__) def safe_int(val): """Safely convert value to integer""" try: return int(float(val)) if val is not None else 0 except: return 0 def safe_float(val): """Safely convert value to float""" try: return float(val) if val is not None else 0.0 except: return 0.0 def safe_text(val): """Safely convert value to text""" return "" if val is None else str(val) class MatchProcessor: @staticmethod def process(match_data, conn: sqlite3.Connection) -> bool: """ Process match basic info and team data Args: match_data: MatchData object containing parsed JSON conn: L2 database connection Returns: bool: True if successful """ try: cursor = conn.cursor() # Build column list and values dynamically to avoid count mismatches columns = [ 'match_id', 'match_code', 'map_name', 'start_time', 'end_time', 'duration', 'winner_team', 'score_team1', 'score_team2', 'server_ip', 'server_port', 'location', 'has_side_data_and_rating2', 'match_main_id', 'demo_url', 'game_mode', 'game_name', 'map_desc', 'location_full', 'match_mode', 'match_status', 'match_flag', 'status', 'waiver', 'year', 'season', 'round_total', 'cs_type', 'priority_show_type', 'pug10m_show_type', 'credit_match_status', 'knife_winner', 'knife_winner_role', 'most_1v2_uid', 'most_assist_uid', 'most_awp_uid', 'most_end_uid', 'most_first_kill_uid', 'most_headshot_uid', 'most_jump_uid', 'mvp_uid', 'response_code', 'response_message', 'response_status', 'response_timestamp', 'response_trace_id', 'response_success', 'response_errcode', 'treat_info_raw', 'round_list_raw', 'leetify_data_raw', 'data_source_type' ] values = [ match_data.match_id, match_data.match_code, match_data.map_name, match_data.start_time, match_data.end_time, match_data.duration, match_data.winner_team, match_data.score_team1, match_data.score_team2, match_data.server_ip, match_data.server_port, match_data.location, match_data.has_side_data_and_rating2, match_data.match_main_id, match_data.demo_url, match_data.game_mode, match_data.game_name, match_data.map_desc, match_data.location_full, match_data.match_mode, match_data.match_status, match_data.match_flag, match_data.status, match_data.waiver, match_data.year, match_data.season, match_data.round_total, match_data.cs_type, match_data.priority_show_type, match_data.pug10m_show_type, match_data.credit_match_status, match_data.knife_winner, match_data.knife_winner_role, match_data.most_1v2_uid, match_data.most_assist_uid, match_data.most_awp_uid, match_data.most_end_uid, match_data.most_first_kill_uid, match_data.most_headshot_uid, match_data.most_jump_uid, match_data.mvp_uid, match_data.response_code, match_data.response_message, match_data.response_status, match_data.response_timestamp, match_data.response_trace_id, match_data.response_success, match_data.response_errcode, match_data.treat_info_raw, match_data.round_list_raw, match_data.leetify_data_raw, match_data.data_source_type ] # Build SQL dynamically placeholders = ','.join(['?' for _ in columns]) columns_sql = ','.join(columns) sql = f"INSERT OR REPLACE INTO fact_matches ({columns_sql}) VALUES ({placeholders})" cursor.execute(sql, values) # Process team data for team in match_data.teams: team_row = ( match_data.match_id, team.group_id, team.group_all_score, team.group_change_elo, team.group_fh_role, team.group_fh_score, team.group_origin_elo, team.group_sh_role, team.group_sh_score, team.group_tid, team.group_uids ) cursor.execute(''' INSERT OR REPLACE INTO fact_match_teams ( match_id, group_id, group_all_score, group_change_elo, group_fh_role, group_fh_score, group_origin_elo, group_sh_role, group_sh_score, group_tid, group_uids ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ''', team_row) logger.debug(f"Processed match {match_data.match_id}") return True except Exception as e: logger.error(f"Error processing match {match_data.match_id}: {e}") import traceback traceback.print_exc() return False