2.0.0 Alpha: Data Refinery
This commit is contained in:
+36
-44
@@ -1,15 +1,16 @@
|
||||
from flask import Blueprint, render_template, request, jsonify, redirect, url_for, flash, current_app, session
|
||||
from web.services.stats_service import StatsService
|
||||
from web.services.feature_service import FeatureService
|
||||
from web.services.player_profile_service import PlayerProfileService
|
||||
from web.services.web_service import WebService
|
||||
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')
|
||||
ALLOWED_AVATAR_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.webp'}
|
||||
|
||||
@bp.route('/')
|
||||
def index():
|
||||
@@ -41,7 +42,12 @@ def detail(steam_id):
|
||||
# Use steam_id as filename to ensure uniqueness per player
|
||||
# Preserve extension
|
||||
ext = os.path.splitext(file.filename)[1].lower()
|
||||
if not ext: ext = '.jpg'
|
||||
if (
|
||||
ext not in ALLOWED_AVATAR_EXTENSIONS
|
||||
or not (file.mimetype or '').startswith('image/')
|
||||
):
|
||||
flash('Avatar must be a JPG, PNG, or WebP image.', 'error')
|
||||
return redirect(url_for('players.detail', steam_id=steam_id))
|
||||
|
||||
filename = f"{steam_id}{ext}"
|
||||
upload_folder = os.path.join(current_app.root_path, 'static', 'avatars')
|
||||
@@ -177,33 +183,9 @@ def detail(steam_id):
|
||||
history_asc = StatsService.get_player_trend(steam_id, limit=1000)
|
||||
history = history_asc[::-1] if history_asc else []
|
||||
|
||||
# Calculate Map Stats
|
||||
map_stats = {}
|
||||
for match in history:
|
||||
m_name = match['map_name']
|
||||
if m_name not in map_stats:
|
||||
map_stats[m_name] = {'matches': 0, 'wins': 0, 'adr_sum': 0, 'rating_sum': 0}
|
||||
|
||||
map_stats[m_name]['matches'] += 1
|
||||
if match['is_win']:
|
||||
map_stats[m_name]['wins'] += 1
|
||||
map_stats[m_name]['adr_sum'] += (match['adr'] or 0)
|
||||
map_stats[m_name]['rating_sum'] += (match['rating'] or 0)
|
||||
|
||||
map_stats_list = []
|
||||
for m_name, data in map_stats.items():
|
||||
cnt = data['matches']
|
||||
map_stats_list.append({
|
||||
'map_name': m_name,
|
||||
'matches': cnt,
|
||||
'win_rate': data['wins'] / cnt,
|
||||
'adr': data['adr_sum'] / cnt,
|
||||
'rating': data['rating_sum'] / cnt
|
||||
})
|
||||
map_stats_list.sort(key=lambda x: x['matches'], reverse=True)
|
||||
|
||||
# --- New: Recent Performance Stats ---
|
||||
# recent_stats = StatsService.get_recent_performance_stats(steam_id)
|
||||
map_stats_list = PlayerProfileService.get_map_stats(steam_id)
|
||||
period_stats = PlayerProfileService.get_period_stats(steam_id)
|
||||
records = PlayerProfileService.get_records(steam_id)
|
||||
|
||||
return render_template('players/profile.html',
|
||||
player=player,
|
||||
@@ -213,6 +195,8 @@ def detail(steam_id):
|
||||
history=history,
|
||||
distribution=distribution,
|
||||
map_stats=map_stats_list,
|
||||
period_stats=period_stats,
|
||||
records=records,
|
||||
l2_stats=l2_stats,
|
||||
side_stats=side_stats)
|
||||
|
||||
@@ -223,9 +207,13 @@ def like_comment(comment_id):
|
||||
|
||||
@bp.route('/<steam_id>/charts_data')
|
||||
def charts_data(steam_id):
|
||||
# ... (existing code) ...
|
||||
# Trend Data
|
||||
trends = StatsService.get_player_trend(steam_id, limit=1000)
|
||||
period_key = request.args.get('period', 'last_20')
|
||||
if period_key not in PlayerProfileService.PERIOD_KEYS:
|
||||
period_key = 'last_20'
|
||||
trends = PlayerProfileService.get_period_history(steam_id, period_key)
|
||||
if not trends:
|
||||
trends = StatsService.get_player_trend(steam_id, limit=20)
|
||||
period_summary = PlayerProfileService.get_period(steam_id, period_key)
|
||||
|
||||
# Radar Data (Construct from features)
|
||||
features = FeatureService.get_player_features(steam_id)
|
||||
@@ -234,17 +222,11 @@ def charts_data(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:
|
||||
from web.services.team_context_service import TeamContextService
|
||||
|
||||
active_roster_ids = TeamContextService.get_active_roster_ids()
|
||||
target_lineup = active_roster_ids if str(steam_id) in active_roster_ids else None
|
||||
if target_lineup:
|
||||
# Calculate strict average for this lineup
|
||||
team_sums = {
|
||||
'score_aim': 0.0, 'score_defense': 0.0, 'score_utility': 0.0,
|
||||
@@ -303,9 +285,19 @@ def charts_data(steam_id):
|
||||
'trend': {'labels': trend_labels, 'values': trend_values},
|
||||
'radar': radar_data,
|
||||
'radar_dist': radar_dist,
|
||||
'team_avg_radar': team_avg_radar
|
||||
'team_avg_radar': team_avg_radar,
|
||||
'period': period_summary,
|
||||
})
|
||||
|
||||
|
||||
@bp.route('/<steam_id>/period_stats')
|
||||
def period_stats(steam_id):
|
||||
period_key = request.args.get('period', 'last_20')
|
||||
period = PlayerProfileService.get_period(steam_id, period_key)
|
||||
if not period:
|
||||
return jsonify({'error': 'Unknown period or player'}), 404
|
||||
return jsonify(period)
|
||||
|
||||
# --- API for Comparison ---
|
||||
@bp.route('/api/search')
|
||||
def api_search():
|
||||
|
||||
Reference in New Issue
Block a user