1.0.3: Enhanced match detail - Added h2h and roundhistory.
This commit is contained in:
@@ -93,52 +93,87 @@ class StatsService:
|
||||
if not active_roster_ids:
|
||||
result_map = {}
|
||||
else:
|
||||
# 1. Get UIDs for Roster Members involved in these matches
|
||||
# We query fact_match_players to ensure we get the UIDs actually used in these matches
|
||||
roster_placeholders = ','.join('?' for _ in active_roster_ids)
|
||||
|
||||
# We cast steam_id_64 to TEXT to ensure match even if stored as int
|
||||
our_result_sql = f"""
|
||||
SELECT mp.match_id, mp.team_id, m.winner_team, COUNT(*) as our_count
|
||||
FROM fact_match_players mp
|
||||
JOIN fact_matches m ON mp.match_id = m.match_id
|
||||
WHERE mp.match_id IN ({placeholders})
|
||||
AND CAST(mp.steam_id_64 AS TEXT) IN ({roster_placeholders})
|
||||
GROUP BY mp.match_id, mp.team_id
|
||||
uid_sql = f"""
|
||||
SELECT DISTINCT steam_id_64, uid
|
||||
FROM fact_match_players
|
||||
WHERE match_id IN ({placeholders})
|
||||
AND CAST(steam_id_64 AS TEXT) IN ({roster_placeholders})
|
||||
"""
|
||||
combined_args_uid = match_ids + active_roster_ids
|
||||
uid_rows = query_db('l2', uid_sql, combined_args_uid)
|
||||
|
||||
# Combine args: match_ids + roster_ids
|
||||
combined_args = match_ids + active_roster_ids
|
||||
our_rows = query_db('l2', our_result_sql, combined_args)
|
||||
# Set of "Our UIDs" (as strings)
|
||||
our_uids = set()
|
||||
for r in uid_rows:
|
||||
if r['uid']:
|
||||
our_uids.add(str(r['uid']))
|
||||
|
||||
# Map match_id -> result ('win', 'loss', 'draw', 'mixed')
|
||||
# 2. Get Group UIDs and Winner info from fact_match_teams
|
||||
# We need to know which group contains our UIDs
|
||||
teams_sql = f"""
|
||||
SELECT fmt.match_id, fmt.group_id, fmt.group_uids, m.winner_team
|
||||
FROM fact_match_teams fmt
|
||||
JOIN fact_matches m ON fmt.match_id = m.match_id
|
||||
WHERE fmt.match_id IN ({placeholders})
|
||||
"""
|
||||
teams_rows = query_db('l2', teams_sql, match_ids)
|
||||
|
||||
# 3. Determine Result per Match
|
||||
result_map = {}
|
||||
|
||||
match_sides = {}
|
||||
match_winners = {}
|
||||
# Group data by match
|
||||
match_groups = {} # match_id -> {group_id: [uids...], winner: int}
|
||||
|
||||
for r in our_rows:
|
||||
for r in teams_rows:
|
||||
mid = r['match_id']
|
||||
if mid not in match_sides: match_sides[mid] = {}
|
||||
match_sides[mid][r['team_id']] = r['our_count']
|
||||
match_winners[mid] = r['winner_team']
|
||||
gid = r['group_id']
|
||||
uids_str = r['group_uids'] or ""
|
||||
# Split and clean UIDs
|
||||
uids = set(str(u).strip() for u in uids_str.split(',') if u.strip())
|
||||
|
||||
for mid, sides in match_sides.items():
|
||||
winner = match_winners.get(mid)
|
||||
if not winner:
|
||||
result_map[mid] = 'draw'
|
||||
continue
|
||||
|
||||
our_on_winner = sides.get(winner, 0)
|
||||
loser = 2 if winner == 1 else 1
|
||||
our_on_loser = sides.get(loser, 0)
|
||||
if mid not in match_groups:
|
||||
match_groups[mid] = {'groups': {}, 'winner': r['winner_team']}
|
||||
|
||||
if our_on_winner > 0 and our_on_loser == 0:
|
||||
match_groups[mid]['groups'][gid] = uids
|
||||
|
||||
# Analyze
|
||||
for mid, data in match_groups.items():
|
||||
winner_gid = data['winner']
|
||||
groups = data['groups']
|
||||
|
||||
our_in_winner = False
|
||||
our_in_loser = False
|
||||
|
||||
# Check each group
|
||||
for gid, uids in groups.items():
|
||||
# Intersection of Our UIDs and Group UIDs
|
||||
common = our_uids.intersection(uids)
|
||||
if common:
|
||||
if gid == winner_gid:
|
||||
our_in_winner = True
|
||||
else:
|
||||
our_in_loser = True
|
||||
|
||||
if our_in_winner and not our_in_loser:
|
||||
result_map[mid] = 'win'
|
||||
elif our_on_loser > 0 and our_on_winner == 0:
|
||||
elif our_in_loser and not our_in_winner:
|
||||
result_map[mid] = 'loss'
|
||||
elif our_on_winner > 0 and our_on_loser > 0:
|
||||
result_map[mid] = 'mixed'
|
||||
elif our_in_winner and our_in_loser:
|
||||
result_map[mid] = 'mixed'
|
||||
else:
|
||||
result_map[mid] = None
|
||||
# Fallback: If UID matching failed (maybe missing UIDs), try old team_id method?
|
||||
# Or just leave it as None (safe)
|
||||
pass
|
||||
|
||||
# Convert to dict to modify
|
||||
matches = [dict(m) for m in matches]
|
||||
for m in matches:
|
||||
m['avg_elo'] = elo_map.get(m['match_id'], 0)
|
||||
m['max_party'] = party_map.get(m['match_id'], 1)
|
||||
m['our_result'] = result_map.get(m['match_id'])
|
||||
|
||||
# Convert to dict to modify
|
||||
matches = [dict(m) for m in matches]
|
||||
@@ -387,3 +422,78 @@ class StatsService:
|
||||
"""
|
||||
return query_db('l2', sql)
|
||||
|
||||
@staticmethod
|
||||
def get_head_to_head_stats(match_id):
|
||||
"""
|
||||
Returns a matrix of kills between players.
|
||||
List of {attacker_steam_id, victim_steam_id, kills}
|
||||
"""
|
||||
sql = """
|
||||
SELECT attacker_steam_id, victim_steam_id, COUNT(*) as kills
|
||||
FROM fact_round_events
|
||||
WHERE match_id = ? AND event_type = 'kill'
|
||||
GROUP BY attacker_steam_id, victim_steam_id
|
||||
"""
|
||||
return query_db('l2', sql, [match_id])
|
||||
|
||||
@staticmethod
|
||||
def get_match_round_details(match_id):
|
||||
"""
|
||||
Returns a detailed dictionary of rounds, events, and economy.
|
||||
{
|
||||
round_num: {
|
||||
info: {winner_side, win_reason_desc, end_time_stamp...},
|
||||
events: [ {event_type, event_time, attacker..., weapon...}, ... ],
|
||||
economy: { steam_id: {main_weapon, equipment_value...}, ... }
|
||||
}
|
||||
}
|
||||
"""
|
||||
# 1. Base Round Info
|
||||
rounds_sql = "SELECT * FROM fact_rounds WHERE match_id = ? ORDER BY round_num"
|
||||
rounds_rows = query_db('l2', rounds_sql, [match_id])
|
||||
|
||||
if not rounds_rows:
|
||||
return {}
|
||||
|
||||
# 2. Events
|
||||
events_sql = """
|
||||
SELECT * FROM fact_round_events
|
||||
WHERE match_id = ?
|
||||
ORDER BY round_num, event_time
|
||||
"""
|
||||
events_rows = query_db('l2', events_sql, [match_id])
|
||||
|
||||
# 3. Economy (if avail)
|
||||
eco_sql = """
|
||||
SELECT * FROM fact_round_player_economy
|
||||
WHERE match_id = ?
|
||||
"""
|
||||
eco_rows = query_db('l2', eco_sql, [match_id])
|
||||
|
||||
# Structure Data
|
||||
result = {}
|
||||
|
||||
# Initialize rounds
|
||||
for r in rounds_rows:
|
||||
r_num = r['round_num']
|
||||
result[r_num] = {
|
||||
'info': dict(r),
|
||||
'events': [],
|
||||
'economy': {}
|
||||
}
|
||||
|
||||
# Group events
|
||||
for e in events_rows:
|
||||
r_num = e['round_num']
|
||||
if r_num in result:
|
||||
result[r_num]['events'].append(dict(e))
|
||||
|
||||
# Group economy
|
||||
for eco in eco_rows:
|
||||
r_num = eco['round_num']
|
||||
sid = eco['steam_id_64']
|
||||
if r_num in result:
|
||||
result[r_num]['economy'][sid] = dict(eco)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
Reference in New Issue
Block a user