1.0.2-hotfix: Added matchlist new features.

This commit is contained in:
2026-01-26 02:53:31 +08:00
parent 81739392da
commit d8b70c1cf7
7 changed files with 320 additions and 33 deletions

View File

@@ -44,6 +44,109 @@ class StatsService:
matches = query_db('l2', sql, args)
# Enrich matches with Avg ELO, Party info, and Our Team Result
if matches:
match_ids = [m['match_id'] for m in matches]
placeholders = ','.join('?' for _ in match_ids)
# Fetch ELO
elo_sql = f"""
SELECT match_id, AVG(group_origin_elo) as avg_elo
FROM fact_match_teams
WHERE match_id IN ({placeholders}) AND group_origin_elo > 0
GROUP BY match_id
"""
elo_rows = query_db('l2', elo_sql, match_ids)
elo_map = {row['match_id']: row['avg_elo'] for row in elo_rows}
# Fetch Max Party Size
party_sql = f"""
SELECT match_id, MAX(cnt) as max_party
FROM (
SELECT match_id, match_team_id, COUNT(*) as cnt
FROM fact_match_players
WHERE match_id IN ({placeholders}) AND match_team_id > 0
GROUP BY match_id, match_team_id
)
GROUP BY match_id
"""
party_rows = query_db('l2', party_sql, match_ids)
party_map = {row['match_id']: row['max_party'] for row in party_rows}
# --- New: Determine "Our Team" Result ---
# Logic: Check if any player from `active_roster` played in these matches.
# Use WebService to get the active roster
from web.services.web_service import WebService
import json
lineups = WebService.get_lineups()
active_roster_ids = []
if lineups:
try:
# Load IDs and ensure they are all strings for DB comparison consistency
raw_ids = json.loads(lineups[0]['player_ids_json'])
active_roster_ids = [str(uid) for uid in raw_ids]
except:
pass
# If no roster, we can't determine "Our Result"
if not active_roster_ids:
result_map = {}
else:
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
"""
# Combine args: match_ids + roster_ids
combined_args = match_ids + active_roster_ids
our_rows = query_db('l2', our_result_sql, combined_args)
# Map match_id -> result ('win', 'loss', 'draw', 'mixed')
result_map = {}
match_sides = {}
match_winners = {}
for r in our_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']
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 our_on_winner > 0 and our_on_loser == 0:
result_map[mid] = 'win'
elif our_on_loser > 0 and our_on_winner == 0:
result_map[mid] = 'loss'
elif our_on_winner > 0 and our_on_loser > 0:
result_map[mid] = 'mixed'
else:
result_map[mid] = None
# 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'])
# Count total for pagination
count_sql = f"SELECT COUNT(*) as cnt FROM fact_matches WHERE {where_str}"
total = query_db('l2', count_sql, args[:-2], one=True)['cnt']
@@ -243,20 +346,25 @@ class StatsService:
@staticmethod
def get_player_trend(steam_id, limit=20):
sql = """
SELECT m.start_time, mp.rating, mp.kd_ratio, mp.adr, m.match_id, m.map_name
FROM fact_match_players mp
JOIN fact_matches m ON mp.match_id = m.match_id
WHERE mp.steam_id_64 = ?
ORDER BY m.start_time ASC
"""
# We fetch all then slice last 'limit' in python or use subquery.
# DESC LIMIT gets recent, but we want chronological for chart.
# So: SELECT ... ORDER BY time DESC LIMIT ? -> then reverse in code.
# We need party_size: count of players with same match_team_id in the same match
# Using a correlated subquery for party_size
sql = """
SELECT * FROM (
SELECT m.start_time, mp.rating, mp.kd_ratio, mp.adr, m.match_id, m.map_name, mp.is_win
SELECT
m.start_time,
mp.rating,
mp.kd_ratio,
mp.adr,
m.match_id,
m.map_name,
mp.is_win,
mp.match_team_id,
(SELECT COUNT(*)
FROM fact_match_players p2
WHERE p2.match_id = mp.match_id
AND p2.match_team_id = mp.match_team_id
AND p2.match_team_id > 0 -- Ensure we don't count 0 (solo default) as a massive party
) as party_size
FROM fact_match_players mp
JOIN fact_matches m ON mp.match_id = m.match_id
WHERE mp.steam_id_64 = ?