""" Spatial Processor - Handles classic spatial (xyz) data Responsibilities: - Extract attacker/victim position data from classic round_list - Update fact_round_events with spatial coordinates - Prepare data for future heatmap/tactical board analysis """ import sqlite3 import logging logger = logging.getLogger(__name__) class SpatialProcessor: @staticmethod def process(match_data, conn: sqlite3.Connection) -> bool: """ Process spatial data from classic round_list Args: match_data: MatchData object with round_list parsed conn: L2 database connection Returns: bool: True if successful """ try: if not hasattr(match_data, 'data_round_list') or not match_data.data_round_list: return True round_list = match_data.data_round_list.get('round_list', []) if not round_list: return True cursor = conn.cursor() update_count = 0 for idx, rd in enumerate(round_list, start=1): round_num = idx # Process kill events with spatial data all_kill = rd.get('all_kill', []) for kill in all_kill: attacker = kill.get('attacker', {}) victim = kill.get('victim', {}) attacker_steam_id = str(attacker.get('steamid_64', '')) victim_steam_id = str(victim.get('steamid_64', '')) event_time = kill.get('pasttime', 0) # Extract positions attacker_pos = attacker.get('pos', {}) victim_pos = victim.get('pos', {}) attacker_pos_x = attacker_pos.get('x', 0) if isinstance(attacker_pos, dict) else 0 attacker_pos_y = attacker_pos.get('y', 0) if isinstance(attacker_pos, dict) else 0 attacker_pos_z = attacker_pos.get('z', 0) if isinstance(attacker_pos, dict) else 0 victim_pos_x = victim_pos.get('x', 0) if isinstance(victim_pos, dict) else 0 victim_pos_y = victim_pos.get('y', 0) if isinstance(victim_pos, dict) else 0 victim_pos_z = victim_pos.get('z', 0) if isinstance(victim_pos, dict) else 0 # Update existing event with spatial data # We match by match_id, round_num, attacker, victim, and event_time cursor.execute(''' UPDATE fact_round_events SET attacker_pos_x = ?, attacker_pos_y = ?, attacker_pos_z = ?, victim_pos_x = ?, victim_pos_y = ?, victim_pos_z = ? WHERE match_id = ? AND round_num = ? AND attacker_steam_id = ? AND victim_steam_id = ? AND event_time = ? AND event_type = 'kill' AND data_source_type = 'classic' ''', ( attacker_pos_x, attacker_pos_y, attacker_pos_z, victim_pos_x, victim_pos_y, victim_pos_z, match_data.match_id, round_num, attacker_steam_id, victim_steam_id, event_time )) if cursor.rowcount > 0: update_count += 1 logger.debug(f"Updated {update_count} events with spatial data for match {match_data.match_id}") return True except Exception as e: logger.error(f"Error processing spatial data for match {match_data.match_id}: {e}") import traceback traceback.print_exc() return False