import json from web.database import query_db from web.services.roster_version_service import RosterVersionService from web.services.team_context_service import TeamContextService class TeamPerformanceService: @staticmethod def _player_identity_map(steam_ids): if not steam_ids: return {} placeholders = ','.join('?' for _ in steam_ids) rows = query_db( 'l2', f""" SELECT steam_id_64, username, avatar_url FROM dim_players WHERE steam_id_64 IN ({placeholders}) """, steam_ids, ) return {str(row['steam_id_64']): dict(row) for row in rows} @staticmethod def get_team_summary(): roster_ids = TeamContextService.get_active_roster_ids() if not roster_ids: return { 'matches': 0, 'wins': 0, 'win_rate': 0, 'avg_rating': 0, 'maps': [], } placeholders = ','.join('?' for _ in roster_ids) rows = query_db( 'l2', f""" SELECT p.match_id, CASE WHEN p.group_id IN (1, 2) THEN p.group_id WHEN p.team_id IN (1, 2) THEN p.team_id END AS team_key, COUNT(DISTINCT p.steam_id_64) AS roster_count, AVG(p.rating) AS avg_rating, MAX(p.is_win) AS is_win, m.map_name, m.start_time FROM fact_match_players p JOIN fact_matches m ON m.match_id = p.match_id WHERE p.steam_id_64 IN ({placeholders}) GROUP BY p.match_id, team_key HAVING roster_count >= 2 AND team_key IS NOT NULL ORDER BY m.start_time DESC """, roster_ids, ) matches = len(rows) wins = sum(int(row['is_win'] or 0) for row in rows) map_stats = {} for row in rows: item = map_stats.setdefault( row['map_name'] or 'Unknown', {'map_name': row['map_name'] or 'Unknown', 'matches': 0, 'wins': 0}, ) item['matches'] += 1 item['wins'] += int(row['is_win'] or 0) maps = [] for item in map_stats.values(): item['win_rate'] = item['wins'] / item['matches'] maps.append(item) maps.sort(key=lambda item: item['matches'], reverse=True) return { 'matches': matches, 'wins': wins, 'losses': matches - wins, 'win_rate': wins / matches if matches else 0, 'avg_rating': ( sum(float(row['avg_rating'] or 0) for row in rows) / matches if matches else 0 ), 'maps': maps, } @staticmethod def get_current_roster(): members = RosterVersionService.get_current_members() identities = TeamPerformanceService._player_identity_map( [member['steam_id_64'] for member in members] ) result = [] for member in members: item = dict(member) item.update(identities.get(str(member['steam_id_64']), {})) result.append(item) return result @staticmethod def get_top_duos(limit=12): rows = query_db( 'l3', """ SELECT * FROM dm_duo_stats ORDER BY sample_reliable DESC, matches DESC, win_rate DESC, avg_combined_rating DESC LIMIT ? """, [limit], ) steam_ids = { str(value) for row in rows for value in (row['steam_id_a'], row['steam_id_b']) } identities = TeamPerformanceService._player_identity_map(sorted(steam_ids)) result = [] for row in rows: item = dict(row) item['player_a'] = identities.get(str(row['steam_id_a']), {}) item['player_b'] = identities.get(str(row['steam_id_b']), {}) result.append(item) return result @staticmethod def get_top_lineups(player_count=None, limit=12): args = [] where = '' if player_count: where = 'WHERE player_count = ?' args.append(int(player_count)) args.append(limit) rows = query_db( 'l3', f""" SELECT * FROM dm_lineup_stats {where} ORDER BY sample_reliable DESC, matches DESC, win_rate DESC, avg_team_rating DESC LIMIT ? """, args, ) all_ids = set() parsed = [] for row in rows: item = dict(row) item['player_ids'] = [ str(value) for value in json.loads(item['player_ids_json']) ] all_ids.update(item['player_ids']) parsed.append(item) identities = TeamPerformanceService._player_identity_map(sorted(all_ids)) for item in parsed: item['players'] = [ identities.get(steam_id, {'username': steam_id}) for steam_id in item['player_ids'] ] return parsed @staticmethod def get_dashboard(): return { 'summary': TeamPerformanceService.get_team_summary(), 'roster': TeamPerformanceService.get_current_roster(), 'versions': RosterVersionService.list_versions(), 'duos': TeamPerformanceService.get_top_duos(), 'lineups': TeamPerformanceService.get_top_lineups(), }