174 lines
5.6 KiB
Python
174 lines
5.6 KiB
Python
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(),
|
|
}
|
|
|