From 3bb3d61c2e50261097c6bb49cd27e13a6c07e2eb Mon Sep 17 00:00:00 2001 From: Jacky Yang Date: Thu, 29 Jan 2026 12:18:05 +0800 Subject: [PATCH] 3.0.2- rollback --- web/routes/players.py | 27 +++++-------- web/routes/tactics.py | 42 ++------------------ web/services/feature_service.py | 8 +--- web/services/stats_service.py | 22 +++++----- web/templates/players/list.html | 6 +-- web/templates/tactics/board.html | 26 ++++++------ web/templates/tactics/index.html | 64 ++++++------------------------ web/templates/teams/clubhouse.html | 6 +-- 8 files changed, 55 insertions(+), 146 deletions(-) diff --git a/web/routes/players.py b/web/routes/players.py index 5a7f444..a0f9d65 100644 --- a/web/routes/players.py +++ b/web/routes/players.py @@ -299,27 +299,20 @@ def api_batch_stats(): # Use safe conversion with default 0 if None # Force 0.0 if value is 0 or None to ensure JSON compatibility radar = { - '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) + '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 - rating_val = f.get('core_avg_rating2') - if rating_val is None: - rating_val = f.get('core_avg_rating') - if rating_val is None: - rating_val = f.get('basic_avg_rating') basic = { - 'rating': float(rating_val or 0), - 'kd': float(f.get('core_avg_kd') or f.get('basic_avg_kd') or 0), - 'adr': float(f.get('core_avg_adr') or f.get('basic_avg_adr') or 0), - 'kast': float(f.get('core_avg_kast') or f.get('basic_avg_kast') or 0), + '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) diff --git a/web/routes/tactics.py b/web/routes/tactics.py index d6b1a5a..dcf5d5c 100644 --- a/web/routes/tactics.py +++ b/web/routes/tactics.py @@ -27,7 +27,6 @@ def api_analyze(): total_kd = 0 total_adr = 0 count = 0 - radar_vectors = [] for p in players: p_dict = dict(p) @@ -38,25 +37,10 @@ def api_analyze(): player_data.append(p_dict) if stats: - rating_val = stats.get('core_avg_rating2') - if rating_val is None: - rating_val = stats.get('core_avg_rating') - if rating_val is None: - rating_val = stats.get('basic_avg_rating') - total_rating += rating_val or 0 - total_kd += stats.get('core_avg_kd', stats.get('basic_avg_kd', 0)) or 0 - total_adr += stats.get('core_avg_adr', stats.get('basic_avg_adr', 0)) or 0 + total_rating += stats.get('basic_avg_rating', 0) or 0 + total_kd += stats.get('basic_avg_kd', 0) or 0 + total_adr += stats.get('basic_avg_adr', 0) or 0 count += 1 - radar_vectors.append([ - float(stats.get('score_aim') or 0), - float(stats.get('score_defense') or 0), - float(stats.get('score_utility') or 0), - float(stats.get('score_clutch') or 0), - float(stats.get('score_economy') or 0), - float(stats.get('score_pace') or 0), - float(stats.get('score_pistol') or 0), - float(stats.get('score_stability') or 0) - ]) # 2. Shared Matches shared_matches = StatsService.get_shared_matches(steam_ids) @@ -69,23 +53,6 @@ def api_analyze(): 'adr': total_adr / count if count else 0 } - chemistry = 0 - if len(radar_vectors) >= 2: - def cosine_sim(a, b): - dot = sum(x * y for x, y in zip(a, b)) - na = sum(x * x for x in a) ** 0.5 - nb = sum(y * y for y in b) ** 0.5 - if na == 0 or nb == 0: - return 0 - return dot / (na * nb) - - sims = [] - for i in range(len(radar_vectors)): - for j in range(i + 1, len(radar_vectors)): - sims.append(cosine_sim(radar_vectors[i], radar_vectors[j])) - if sims: - chemistry = sum(sims) / len(sims) * 100 - # 4. Map Stats Calculation map_stats = {} # {map_name: {'count': 0, 'wins': 0}} total_shared_matches = len(shared_matches) @@ -118,8 +85,7 @@ def api_analyze(): 'shared_matches': [dict(m) for m in shared_matches], 'avg_stats': avg_stats, 'map_stats': map_stats_list, - 'total_shared_matches': total_shared_matches, - 'chemistry': chemistry + 'total_shared_matches': total_shared_matches }) # API: Save Board diff --git a/web/services/feature_service.py b/web/services/feature_service.py index 22f403a..115cb30 100644 --- a/web/services/feature_service.py +++ b/web/services/feature_service.py @@ -78,12 +78,8 @@ class FeatureService: } for legacy_key, l3_key in alias_map.items(): - legacy_val = f.get(legacy_key) - l3_val = f.get(l3_key) - if legacy_val is None and l3_val is not None: - f[legacy_key] = l3_val - elif l3_val is None and legacy_val is not None: - f[l3_key] = legacy_val + if legacy_key not in f or f.get(legacy_key) is None: + f[legacy_key] = f.get(l3_key) if f.get("matches_played") is None: f["matches_played"] = f.get("total_matches", 0) or 0 diff --git a/web/services/stats_service.py b/web/services/stats_service.py index 4079178..23738a8 100644 --- a/web/services/stats_service.py +++ b/web/services/stats_service.py @@ -733,19 +733,16 @@ class StatsService: from web.services.feature_service import FeatureService import json + # 1. Get Active Roster IDs lineups = WebService.get_lineups() active_roster_ids = [] - target_steam_id = str(target_steam_id) if lineups: - for lineup in lineups: - try: - raw_ids = json.loads(lineup.get('player_ids_json') or '[]') - roster_ids = [str(uid) for uid in raw_ids] - if target_steam_id in roster_ids: - active_roster_ids = roster_ids - break - except Exception: - continue + try: + raw_ids = json.loads(lineups[0]['player_ids_json']) + active_roster_ids = [str(uid) for uid in raw_ids] + except: + pass + if not active_roster_ids: return None @@ -755,8 +752,11 @@ class StatsService: return None stats_map = {str(row["steam_id_64"]): FeatureService._normalize_features(dict(row)) for row in rows} + target_steam_id = str(target_steam_id) + + # If target not in map (e.g. no L3 data), try to add empty default if target_steam_id not in stats_map: - return None + stats_map[target_steam_id] = {} metrics = [ # TIER 1: CORE diff --git a/web/templates/players/list.html b/web/templates/players/list.html index a71e879..eb663ba 100644 --- a/web/templates/players/list.html +++ b/web/templates/players/list.html @@ -40,15 +40,15 @@
- {{ "%.2f"|format(player.core_avg_rating2 or player.core_avg_rating or 0) }} + {{ "%.2f"|format(player.basic_avg_rating|default(0)) }} Rating
- {{ "%.2f"|format(player.core_avg_kd or 0) }} + {{ "%.2f"|format(player.basic_avg_kd|default(0)) }} K/D
- {{ "%.1f"|format((player.core_avg_kast or 0) * 100) }}% + {{ "%.1f"|format((player.basic_avg_kast|default(0)) * 100) }}% KAST
diff --git a/web/templates/tactics/board.html b/web/templates/tactics/board.html index 5a562c2..29e42c3 100644 --- a/web/templates/tactics/board.html +++ b/web/templates/tactics/board.html @@ -338,10 +338,10 @@ function tacticsBoard() { this.radarChart = new Chart(ctx, { type: 'radar', data: { - labels: ['枪法', '生存', '道具', '残局', '经济', '节奏', '手枪', '稳定'], + labels: ['RTG', 'K/D', 'KST', 'ADR', 'IMP', 'UTL'], datasets: [{ label: 'Avg', - data: [0, 0, 0, 0, 0, 0, 0, 0], + data: [0, 0, 0, 0, 0, 0], backgroundColor: 'rgba(139, 92, 246, 0.2)', borderColor: 'rgba(139, 92, 246, 1)', pointBackgroundColor: 'rgba(139, 92, 246, 1)', @@ -354,7 +354,7 @@ function tacticsBoard() { scales: { r: { beginAtZero: true, - max: 100, + max: 1.5, grid: { color: 'rgba(156, 163, 175, 0.1)' }, angleLines: { color: 'rgba(156, 163, 175, 0.1)' }, pointLabels: { font: { size: 9 } }, @@ -368,22 +368,20 @@ function tacticsBoard() { updateRadar() { if (this.activePlayers.length === 0) { - this.radarChart.data.datasets[0].data = [0, 0, 0, 0, 0, 0, 0, 0]; + this.radarChart.data.datasets[0].data = [0, 0, 0, 0, 0, 0]; this.radarChart.update(); return; } - let totals = [0, 0, 0, 0, 0, 0, 0, 0]; + let totals = [0, 0, 0, 0, 0, 0]; this.activePlayers.forEach(p => { const s = p.stats || {}; - totals[0] += s.score_aim || 0; - totals[1] += s.score_defense || 0; - totals[2] += s.score_utility || 0; - totals[3] += s.score_clutch || 0; - totals[4] += s.score_economy || 0; - totals[5] += s.score_pace || 0; - totals[6] += s.score_pistol || 0; - totals[7] += s.score_stability || 0; + totals[0] += s.basic_avg_rating || 0; + totals[1] += s.basic_avg_kd || 0; + totals[2] += s.basic_avg_kast || 0; + totals[3] += (s.basic_avg_adr || 0) / 100; + totals[4] += s.bat_avg_impact || 1.0; + totals[5] += s.util_usage_rate || 0.5; }); const count = this.activePlayers.length; @@ -395,4 +393,4 @@ function tacticsBoard() { } } -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/web/templates/tactics/index.html b/web/templates/tactics/index.html index 5c8fe7f..24f172a 100644 --- a/web/templates/tactics/index.html +++ b/web/templates/tactics/index.html @@ -120,7 +120,7 @@
- Rating: + Rating:
@@ -149,15 +149,9 @@

📈 综合评分

-
-
- Team Rating - -
-
- Chemistry - -
+
+ Team Rating +
@@ -532,10 +526,13 @@ function tacticsApp() { // Unwrap proxy if needed const rawData = JSON.parse(JSON.stringify(this.dataResult)); - const radarKeys = ['AIM', 'DEFENSE', 'UTILITY', 'CLUTCH', 'ECONOMY', 'PACE', 'PISTOL', 'STABILITY']; const datasets = rawData.map((p, idx) => { const color = this.getPlayerColor(idx); - const d = radarKeys.map(k => (p.radar?.[k] || 0)); + const d = [ + p.radar.BAT || 0, p.radar.PTL || 0, p.radar.HPS || 0, + p.radar.SIDE || 0, p.radar.UTIL || 0, p.radar.STA || 0 + ]; + return { label: p.username, data: d, @@ -546,49 +543,12 @@ function tacticsApp() { }; }); - const valuesByDim = radarKeys.map(() => []); - rawData.forEach(p => { - radarKeys.forEach((k, i) => { - valuesByDim[i].push(Number(p.radar?.[k] || 0)); - }); - }); - const avgVals = valuesByDim.map(arr => arr.length ? arr.reduce((a, b) => a + b, 0) / arr.length : 0); - const minVals = valuesByDim.map(arr => arr.length ? Math.min(...arr) : 0); - const maxVals = valuesByDim.map(arr => arr.length ? Math.max(...arr) : 0); - - datasets.push({ - label: 'Avg', - data: avgVals, - borderColor: '#64748b', - backgroundColor: 'rgba(100, 116, 139, 0.08)', - borderWidth: 2, - pointRadius: 0 - }); - datasets.push({ - label: 'Max', - data: maxVals, - borderColor: '#16a34a', - backgroundColor: 'rgba(22, 163, 74, 0.05)', - borderWidth: 1, - borderDash: [4, 3], - pointRadius: 0 - }); - datasets.push({ - label: 'Min', - data: minVals, - borderColor: '#dc2626', - backgroundColor: 'rgba(220, 38, 38, 0.05)', - borderWidth: 1, - borderDash: [4, 3], - pointRadius: 0 - }); - // Recreate Chart with Profile-aligned config const ctx = canvas.getContext('2d'); this.radarChart = new Chart(ctx, { type: 'radar', data: { - labels: ['枪法 (Aim)', '生存 (Defense)', '道具 (Utility)', '残局 (Clutch)', '经济 (Economy)', '节奏 (Pace)', '手枪 (Pistol)', '稳定 (Stability)'], + labels: ['BAT (火力)', 'PTL (手枪)', 'HPS (抗压)', 'SIDE (阵营)', 'UTIL (道具)', 'STA (稳定)'], datasets: datasets }, options: { @@ -635,7 +595,7 @@ function tacticsApp() { this.radarChart = new Chart(ctx, { type: 'radar', data: { - labels: ['枪法 (Aim)', '生存 (Defense)', '道具 (Utility)', '残局 (Clutch)', '经济 (Economy)', '节奏 (Pace)', '手枪 (Pistol)', '稳定 (Stability)'], + labels: ['BAT (火力)', 'PTL (手枪)', 'HPS (抗压)', 'SIDE (阵营)', 'UTIL (道具)', 'STA (稳定)'], datasets: [] }, options: { @@ -817,4 +777,4 @@ function tacticsApp() { } } -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/web/templates/teams/clubhouse.html b/web/templates/teams/clubhouse.html index 1887b66..0026181 100644 --- a/web/templates/teams/clubhouse.html +++ b/web/templates/teams/clubhouse.html @@ -69,7 +69,7 @@ -
+
Rating
@@ -78,10 +78,6 @@
K/D
-
-
总评
-
-