1.7.0: New features.
This commit is contained in:
@@ -5,21 +5,24 @@ import os
|
||||
class StatsService:
|
||||
@staticmethod
|
||||
def resolve_avatar_url(steam_id, avatar_url):
|
||||
"""
|
||||
Resolves avatar URL with priority:
|
||||
1. Local File (web/static/avatars/{steam_id}.jpg/png) - User override
|
||||
2. DB Value (avatar_url)
|
||||
"""
|
||||
try:
|
||||
# Check local file first (User Request: "directly associate if exists")
|
||||
base = os.path.join(current_app.root_path, 'static', 'avatars')
|
||||
for ext in ('.jpg', '.png', '.jpeg'):
|
||||
fname = f"{steam_id}{ext}"
|
||||
fpath = os.path.join(base, fname)
|
||||
if os.path.exists(fpath):
|
||||
return url_for('static', filename=f'avatars/{fname}')
|
||||
|
||||
# Fallback to DB value if valid
|
||||
if avatar_url and str(avatar_url).strip():
|
||||
return avatar_url
|
||||
base = os.path.join(current_app.root_path, 'static', 'avatars')
|
||||
# Check jpg/png in order
|
||||
for ext in ('.jpg', '.png'):
|
||||
fname = f"{steam_id}{ext}"
|
||||
if os.path.exists(os.path.join(base, fname)):
|
||||
url = url_for('static', filename=f'avatars/{fname}')
|
||||
try:
|
||||
# Persist fallback URL into L2 for future reads
|
||||
execute_db('l2', "UPDATE dim_players SET avatar_url = ? WHERE steam_id_64 = ?", [url, str(steam_id)])
|
||||
except Exception:
|
||||
pass
|
||||
return url
|
||||
|
||||
return None
|
||||
except Exception:
|
||||
return avatar_url
|
||||
@@ -739,6 +742,9 @@ class StatsService:
|
||||
'side_headshot_rate_ct', 'side_headshot_rate_t',
|
||||
'side_defuses_ct', 'side_plants_t',
|
||||
'util_avg_nade_dmg', 'util_avg_flash_time', 'util_avg_flash_enemy', 'util_usage_rate',
|
||||
# New: ECO & PACE
|
||||
'eco_avg_damage_per_1k', 'eco_rating_eco_rounds', 'eco_kd_ratio', 'eco_avg_rounds',
|
||||
'pace_avg_time_to_first_contact', 'pace_trade_kill_rate', 'pace_opening_kill_time', 'pace_avg_life_time',
|
||||
# New: Party Size Stats
|
||||
'party_1_win_rate', 'party_1_rating', 'party_1_adr',
|
||||
'party_2_win_rate', 'party_2_rating', 'party_2_adr',
|
||||
@@ -759,6 +765,9 @@ class StatsService:
|
||||
# Mapping for L2 legacy calls (if any) - mainly map 'rating' to 'basic_avg_rating' etc if needed
|
||||
# But here we just use L3 columns directly.
|
||||
|
||||
# Define metrics where LOWER is BETTER
|
||||
lower_is_better = ['pace_avg_time_to_first_contact', 'pace_opening_kill_time']
|
||||
|
||||
result = {}
|
||||
|
||||
for m in metrics:
|
||||
@@ -768,8 +777,10 @@ class StatsService:
|
||||
if not values:
|
||||
result[m] = None
|
||||
continue
|
||||
|
||||
values.sort(reverse=True)
|
||||
|
||||
# Sort: Reverse (High to Low) by default, unless in lower_is_better
|
||||
is_reverse = m not in lower_is_better
|
||||
values.sort(reverse=is_reverse)
|
||||
|
||||
# Rank
|
||||
try:
|
||||
@@ -783,7 +794,8 @@ class StatsService:
|
||||
'total': len(values),
|
||||
'min': min(values),
|
||||
'max': max(values),
|
||||
'avg': sum(values) / len(values)
|
||||
'avg': sum(values) / len(values),
|
||||
'inverted': not is_reverse # Flag for frontend to invert bar
|
||||
}
|
||||
|
||||
# Legacy mapping for top cards (rating, kd, adr, kast)
|
||||
|
||||
Reference in New Issue
Block a user