3.0.3: Cant fix team avg. removed.
This commit is contained in:
@@ -6,6 +6,7 @@ from web.database import execute_db, query_db
|
||||
from web.config import Config
|
||||
from datetime import datetime
|
||||
import os
|
||||
import json
|
||||
from werkzeug.utils import secure_filename
|
||||
|
||||
bp = Blueprint('players', __name__, url_prefix='/players')
|
||||
@@ -231,6 +232,41 @@ def charts_data(steam_id):
|
||||
radar_data = {}
|
||||
radar_dist = FeatureService.get_roster_features_distribution(steam_id)
|
||||
|
||||
# Task 1: Strict Team Average Calculation
|
||||
team_avg_radar = None
|
||||
lineups = WebService.get_lineups()
|
||||
if lineups:
|
||||
target_lineup = None
|
||||
try:
|
||||
p_ids = [str(i) for i in json.loads(lineups[0].get("player_ids_json") or "[]")]
|
||||
if str(steam_id) in p_ids:
|
||||
target_lineup = p_ids
|
||||
except:
|
||||
target_lineup = None
|
||||
|
||||
if target_lineup:
|
||||
# Calculate strict average for this lineup
|
||||
team_sums = {
|
||||
'score_aim': 0.0, 'score_defense': 0.0, 'score_utility': 0.0,
|
||||
'score_clutch': 0.0, 'score_economy': 0.0, 'score_pace': 0.0,
|
||||
'score_pistol': 0.0, 'score_stability': 0.0
|
||||
}
|
||||
member_count = 0
|
||||
|
||||
for member_id in target_lineup:
|
||||
mf = FeatureService.get_player_features(member_id)
|
||||
if mf:
|
||||
member_count += 1
|
||||
for k in team_sums:
|
||||
team_sums[k] += float(mf.get(k) or 0.0)
|
||||
|
||||
if member_count > 0:
|
||||
team_avg_radar = {k: v / member_count for k, v in team_sums.items()}
|
||||
# Fallback: if calculated avg is all zeros (e.g. teammates have no stats),
|
||||
# treat as None to trigger global fallback in frontend
|
||||
if sum(team_avg_radar.values()) == 0:
|
||||
team_avg_radar = None
|
||||
|
||||
if features:
|
||||
# Dimensions: AIM, DEFENSE, UTILITY, CLUTCH, ECONOMY, PACE (6 Dimensions)
|
||||
# Use calculated scores (0-100 scale)
|
||||
@@ -266,7 +302,8 @@ def charts_data(steam_id):
|
||||
return jsonify({
|
||||
'trend': {'labels': trend_labels, 'values': trend_values},
|
||||
'radar': radar_data,
|
||||
'radar_dist': radar_dist
|
||||
'radar_dist': radar_dist,
|
||||
'team_avg_radar': team_avg_radar
|
||||
})
|
||||
|
||||
# --- API for Comparison ---
|
||||
@@ -297,14 +334,15 @@ def api_batch_stats():
|
||||
|
||||
# 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)
|
||||
'AIM': float(f.get('score_aim') or 0.0),
|
||||
'DEFENSE': float(f.get('score_defense') or 0.0),
|
||||
'UTILITY': float(f.get('score_utility') or 0.0),
|
||||
'CLUTCH': float(f.get('score_clutch') or 0.0),
|
||||
'ECONOMY': float(f.get('score_economy') or 0.0),
|
||||
'PACE': float(f.get('score_pace') or 0.0),
|
||||
'PISTOL': float(f.get('score_pistol') or 0.0),
|
||||
'STABILITY': float(f.get('score_stability') or 0.0)
|
||||
}
|
||||
|
||||
# 2. Basic Stats for Table
|
||||
@@ -347,22 +385,22 @@ def api_batch_stats():
|
||||
'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),
|
||||
'first_death_t': float(f.get('tac_fd_rate') or 0),
|
||||
'first_death_ct': float(f.get('tac_fd_rate') 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),
|
||||
'rws_t': float(f.get('core_avg_rws') or 0),
|
||||
'rws_ct': float(f.get('core_avg_rws') or 0),
|
||||
'multikill_t': float(f.get('tac_multikill_rate') or 0),
|
||||
'multikill_ct': float(f.get('tac_multikill_rate') 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)
|
||||
'hs_t': float(f.get('core_hs_rate') or 0),
|
||||
'hs_ct': float(f.get('core_hs_rate') or 0),
|
||||
'obj_t': float(f.get('core_avg_plants') or 0),
|
||||
'obj_ct': float(f.get('core_avg_defuses') or 0)
|
||||
}
|
||||
|
||||
stats.append({
|
||||
|
||||
@@ -52,6 +52,41 @@ def api_analyze():
|
||||
'kd': total_kd / count if count else 0,
|
||||
'adr': total_adr / count if count else 0
|
||||
}
|
||||
|
||||
# Calculate 8-Dimension Averages
|
||||
radar_keys = {
|
||||
'score_aim': 'AIM', 'score_defense': 'DEFENSE', 'score_utility': 'UTILITY',
|
||||
'score_clutch': 'CLUTCH', 'score_economy': 'ECONOMY', 'score_pace': 'PACE',
|
||||
'score_pistol': 'PISTOL', 'score_stability': 'STABILITY'
|
||||
}
|
||||
radar_stats = {v: 0.0 for v in radar_keys.values()}
|
||||
|
||||
if count > 0:
|
||||
for p in player_data:
|
||||
stats = p.get('stats', {})
|
||||
for k, v in radar_keys.items():
|
||||
radar_stats[v] += float(stats.get(k) or 0.0)
|
||||
|
||||
for k in radar_stats:
|
||||
radar_stats[k] /= count
|
||||
|
||||
# Calculate Chemistry
|
||||
# Formula: Base on shared matches and win rate
|
||||
# Max Score = 100
|
||||
# 50% weight on match count (Cap at 50 matches = 50 pts)
|
||||
# 50% weight on win rate (100% WR = 50 pts)
|
||||
|
||||
avg_shared_count = 0
|
||||
avg_shared_winrate = 0
|
||||
|
||||
if shared_matches:
|
||||
avg_shared_count = len(shared_matches)
|
||||
wins = sum(1 for m in shared_matches if m['is_win'])
|
||||
avg_shared_winrate = wins / len(shared_matches)
|
||||
|
||||
chem_match_score = min(50, avg_shared_count) # 1 point per match, max 50
|
||||
chem_win_score = avg_shared_winrate * 50
|
||||
chemistry_score = chem_match_score + chem_win_score
|
||||
|
||||
# 4. Map Stats Calculation
|
||||
map_stats = {} # {map_name: {'count': 0, 'wins': 0}}
|
||||
@@ -84,6 +119,8 @@ def api_analyze():
|
||||
'players': player_data,
|
||||
'shared_matches': [dict(m) for m in shared_matches],
|
||||
'avg_stats': avg_stats,
|
||||
'radar_stats': radar_stats,
|
||||
'chemistry_score': chemistry_score,
|
||||
'map_stats': map_stats_list,
|
||||
'total_shared_matches': total_shared_matches
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user