1.2.3-hotfix: Fixed data center not showing graphs.
This commit is contained in:
@@ -2,7 +2,7 @@ from flask import Blueprint, render_template, request, jsonify, redirect, url_fo
|
||||
from web.services.stats_service import StatsService
|
||||
from web.services.feature_service import FeatureService
|
||||
from web.services.web_service import WebService
|
||||
from web.database import execute_db
|
||||
from web.database import execute_db, query_db
|
||||
from web.config import Config
|
||||
from datetime import datetime
|
||||
import os
|
||||
@@ -233,16 +233,139 @@ def api_batch_stats():
|
||||
p = StatsService.get_player_info(sid)
|
||||
|
||||
if f and p:
|
||||
# Convert sqlite3.Row to dict if necessary
|
||||
if hasattr(f, 'keys'): # It's a Row object or similar
|
||||
f = dict(f)
|
||||
|
||||
# 1. Radar Scores (Normalized 0-100)
|
||||
# Use safe conversion with default 0 if None
|
||||
# Force 0.0 if value is 0 or None to ensure JSON compatibility
|
||||
radar = {
|
||||
'STA': float(f.get('score_sta') or 0.0),
|
||||
'BAT': float(f.get('score_bat') or 0.0),
|
||||
'HPS': float(f.get('score_hps') or 0.0),
|
||||
'PTL': float(f.get('score_ptl') or 0.0),
|
||||
'SIDE': float(f.get('score_tct') or 0.0),
|
||||
'UTIL': float(f.get('score_util') or 0.0)
|
||||
}
|
||||
|
||||
# 2. Basic Stats for Table
|
||||
basic = {
|
||||
'rating': float(f.get('basic_avg_rating') or 0),
|
||||
'kd': float(f.get('basic_avg_kd') or 0),
|
||||
'adr': float(f.get('basic_avg_adr') or 0),
|
||||
'kast': float(f.get('basic_avg_kast') or 0),
|
||||
'hs_rate': float(f.get('basic_headshot_rate') or 0),
|
||||
'fk_rate': float(f.get('basic_first_kill_rate') or 0),
|
||||
'matches': int(f.get('matches_played') or 0)
|
||||
}
|
||||
|
||||
# 3. Side Stats
|
||||
side = {
|
||||
'rating_t': float(f.get('side_rating_t') or 0),
|
||||
'rating_ct': float(f.get('side_rating_ct') or 0),
|
||||
'kd_t': float(f.get('side_kd_t') or 0),
|
||||
'kd_ct': float(f.get('side_kd_ct') or 0),
|
||||
'entry_t': float(f.get('side_entry_rate_t') or 0),
|
||||
'entry_ct': float(f.get('side_entry_rate_ct') or 0),
|
||||
'kast_t': float(f.get('side_kast_t') or 0),
|
||||
'kast_ct': float(f.get('side_kast_ct') or 0),
|
||||
'adr_t': float(f.get('side_adr_t') or 0),
|
||||
'adr_ct': float(f.get('side_adr_ct') or 0)
|
||||
}
|
||||
|
||||
# 4. Detailed Stats (Expanded for Data Center - Aligned with Profile)
|
||||
detailed = {
|
||||
# Row 1
|
||||
'rating_t': float(f.get('side_rating_t') or 0),
|
||||
'rating_ct': float(f.get('side_rating_ct') or 0),
|
||||
'kd_t': float(f.get('side_kd_t') or 0),
|
||||
'kd_ct': float(f.get('side_kd_ct') or 0),
|
||||
|
||||
# Row 2
|
||||
'win_rate_t': float(f.get('side_win_rate_t') or 0),
|
||||
'win_rate_ct': float(f.get('side_win_rate_ct') or 0),
|
||||
'first_kill_t': float(f.get('side_first_kill_rate_t') or 0),
|
||||
'first_kill_ct': float(f.get('side_first_kill_rate_ct') or 0),
|
||||
|
||||
# Row 3
|
||||
'first_death_t': float(f.get('side_first_death_rate_t') or 0),
|
||||
'first_death_ct': float(f.get('side_first_death_rate_ct') or 0),
|
||||
'kast_t': float(f.get('side_kast_t') or 0),
|
||||
'kast_ct': float(f.get('side_kast_ct') or 0),
|
||||
|
||||
# Row 4
|
||||
'rws_t': float(f.get('side_rws_t') or 0),
|
||||
'rws_ct': float(f.get('side_rws_ct') or 0),
|
||||
'multikill_t': float(f.get('side_multikill_rate_t') or 0),
|
||||
'multikill_ct': float(f.get('side_multikill_rate_ct') or 0),
|
||||
|
||||
# Row 5
|
||||
'hs_t': float(f.get('side_headshot_rate_t') or 0),
|
||||
'hs_ct': float(f.get('side_headshot_rate_ct') or 0),
|
||||
'obj_t': float(f.get('side_obj_t') or 0),
|
||||
'obj_ct': float(f.get('side_obj_ct') or 0)
|
||||
}
|
||||
|
||||
stats.append({
|
||||
'username': p['username'],
|
||||
'steam_id': sid,
|
||||
'radar': {
|
||||
'STA': f['basic_avg_rating'] or 0,
|
||||
'BAT': f['bat_avg_duel_win_rate'] or 0,
|
||||
'HPS': f['hps_clutch_win_rate_1v1'] or 0,
|
||||
'PTL': f['ptl_pistol_win_rate'] or 0,
|
||||
'SIDE': f['side_rating_ct'] or 0,
|
||||
'UTIL': f['util_usage_rate'] or 0
|
||||
}
|
||||
'avatar_url': p['avatar_url'],
|
||||
'radar': radar,
|
||||
'basic': basic,
|
||||
'side': side,
|
||||
'detailed': detailed
|
||||
})
|
||||
return jsonify(stats)
|
||||
|
||||
@bp.route('/api/batch_map_stats')
|
||||
def api_batch_map_stats():
|
||||
steam_ids = request.args.get('ids', '').split(',')
|
||||
steam_ids = [sid for sid in steam_ids if sid]
|
||||
|
||||
if not steam_ids:
|
||||
return jsonify({})
|
||||
|
||||
# Query L2 for Map Stats grouped by Player and Map
|
||||
# We need to construct a query that can be executed via execute_db or query_db
|
||||
# Since StatsService usually handles this, we can write raw SQL here or delegate.
|
||||
# Raw SQL is easier for this specific aggregation.
|
||||
|
||||
placeholders = ','.join('?' for _ in steam_ids)
|
||||
sql = f"""
|
||||
SELECT
|
||||
mp.steam_id_64,
|
||||
m.map_name,
|
||||
COUNT(*) as matches,
|
||||
SUM(CASE WHEN mp.is_win THEN 1 ELSE 0 END) as wins,
|
||||
AVG(mp.rating) as avg_rating,
|
||||
AVG(mp.kd_ratio) as avg_kd,
|
||||
AVG(mp.adr) as avg_adr
|
||||
FROM fact_match_players mp
|
||||
JOIN fact_matches m ON mp.match_id = m.match_id
|
||||
WHERE mp.steam_id_64 IN ({placeholders})
|
||||
GROUP BY mp.steam_id_64, m.map_name
|
||||
ORDER BY matches DESC
|
||||
"""
|
||||
|
||||
# We need to import query_db if not available in current scope (it is imported at top)
|
||||
from web.database import query_db
|
||||
rows = query_db('l2', sql, steam_ids)
|
||||
|
||||
# Structure: {steam_id: [ {map: 'de_mirage', stats...}, ... ]}
|
||||
result = {}
|
||||
for r in rows:
|
||||
sid = r['steam_id_64']
|
||||
if sid not in result:
|
||||
result[sid] = []
|
||||
|
||||
result[sid].append({
|
||||
'map_name': r['map_name'],
|
||||
'matches': r['matches'],
|
||||
'win_rate': (r['wins'] / r['matches']) if r['matches'] else 0,
|
||||
'rating': r['avg_rating'],
|
||||
'kd': r['avg_kd'],
|
||||
'adr': r['avg_adr']
|
||||
})
|
||||
|
||||
return jsonify(result)
|
||||
|
||||
Reference in New Issue
Block a user