2.0.0 Alpha: Data Refinery
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Iterable
|
||||
from typing import Any
|
||||
|
||||
from web.database import query_db
|
||||
|
||||
@@ -138,20 +138,47 @@ class FeatureService:
|
||||
}
|
||||
order_col = sort_map.get(sort_by, "core_avg_rating")
|
||||
|
||||
where = []
|
||||
args: list[Any] = []
|
||||
if search:
|
||||
where.append("steam_id_64 IN (SELECT steam_id_64 FROM dim_players WHERE username LIKE ?)")
|
||||
args.append(f"%{search}%")
|
||||
where_sql = f"WHERE {' AND '.join(where)}" if where else ""
|
||||
|
||||
rows = query_db(
|
||||
"l3",
|
||||
f"SELECT * FROM dm_player_features {where_sql} ORDER BY {order_col} DESC LIMIT ? OFFSET ?",
|
||||
args + [per_page, offset],
|
||||
)
|
||||
total_row = query_db("l3", f"SELECT COUNT(*) as cnt FROM dm_player_features {where_sql}", args, one=True)
|
||||
total = int(total_row["cnt"]) if total_row else 0
|
||||
dim_rows = query_db(
|
||||
"l2",
|
||||
"""
|
||||
SELECT steam_id_64
|
||||
FROM dim_players
|
||||
WHERE LOWER(username) LIKE LOWER(?) OR steam_id_64 LIKE ?
|
||||
""",
|
||||
[f"%{search}%", f"%{search}%"],
|
||||
)
|
||||
matching_ids = [str(row["steam_id_64"]) for row in dim_rows]
|
||||
rows = []
|
||||
for start in range(0, len(matching_ids), 500):
|
||||
chunk = matching_ids[start:start + 500]
|
||||
placeholders = ",".join("?" for _ in chunk)
|
||||
rows.extend(query_db(
|
||||
"l3",
|
||||
f"SELECT * FROM dm_player_features "
|
||||
f"WHERE steam_id_64 IN ({placeholders})",
|
||||
chunk,
|
||||
))
|
||||
rows = sorted(
|
||||
rows,
|
||||
key=lambda row: row[order_col] if row[order_col] is not None else float("-inf"),
|
||||
reverse=True,
|
||||
)
|
||||
total = len(rows)
|
||||
rows = rows[offset:offset + per_page]
|
||||
else:
|
||||
rows = query_db(
|
||||
"l3",
|
||||
f"SELECT * FROM dm_player_features "
|
||||
f"ORDER BY {order_col} DESC LIMIT ? OFFSET ?",
|
||||
[per_page, offset],
|
||||
)
|
||||
total_row = query_db(
|
||||
"l3",
|
||||
"SELECT COUNT(*) as cnt FROM dm_player_features",
|
||||
one=True,
|
||||
)
|
||||
total = int(total_row["cnt"]) if total_row else 0
|
||||
|
||||
players = [FeatureService._normalize_features(dict(r)) for r in rows] if rows else []
|
||||
players = [p for p in players if p]
|
||||
@@ -160,19 +187,11 @@ class FeatureService:
|
||||
|
||||
@staticmethod
|
||||
def get_roster_features_distribution(target_steam_id: str):
|
||||
from web.services.web_service import WebService
|
||||
import json
|
||||
from web.services.team_context_service import TeamContextService
|
||||
|
||||
lineups = WebService.get_lineups()
|
||||
roster_ids: list[str] = []
|
||||
|
||||
if lineups:
|
||||
try:
|
||||
p_ids = [str(i) for i in json.loads(lineups[0].get("player_ids_json") or "[]")]
|
||||
if str(target_steam_id) in p_ids:
|
||||
roster_ids = p_ids
|
||||
except Exception:
|
||||
roster_ids = []
|
||||
roster_ids = TeamContextService.get_active_roster_ids()
|
||||
if str(target_steam_id) not in roster_ids:
|
||||
roster_ids = []
|
||||
|
||||
if not roster_ids:
|
||||
return None
|
||||
@@ -202,7 +221,17 @@ class FeatureService:
|
||||
sample_keys = list(p.keys())
|
||||
break
|
||||
|
||||
lower_is_better = {"int_timing_first_contact_time", "tac_avg_fd", "core_avg_match_duration"}
|
||||
lower_is_better = {
|
||||
"int_timing_first_contact_time",
|
||||
"int_trade_response_time",
|
||||
"tac_avg_fd",
|
||||
"tac_fd_rate",
|
||||
"core_avg_match_duration",
|
||||
"core_dpr",
|
||||
"meta_rating_volatility",
|
||||
"meta_map_stability",
|
||||
"meta_elo_tier_stability",
|
||||
}
|
||||
|
||||
result: dict[str, Any] = {}
|
||||
for m in sample_keys:
|
||||
@@ -224,16 +253,22 @@ class FeatureService:
|
||||
values = []
|
||||
for p in stats_map.values():
|
||||
v = (p or {}).get(m)
|
||||
if v is None:
|
||||
continue
|
||||
try:
|
||||
values.append(float(v) if v is not None else 0.0)
|
||||
values.append(float(v))
|
||||
except (ValueError, TypeError):
|
||||
values.append(0.0)
|
||||
continue
|
||||
|
||||
target_val_raw = (stats_map.get(target_steam_id) or {}).get(m)
|
||||
if target_val_raw is None or not values:
|
||||
result[m] = None
|
||||
continue
|
||||
try:
|
||||
target_val = float(target_val_raw) if target_val_raw is not None else 0.0
|
||||
target_val = float(target_val_raw)
|
||||
except (ValueError, TypeError):
|
||||
target_val = 0.0
|
||||
result[m] = None
|
||||
continue
|
||||
|
||||
is_reverse = m not in lower_is_better
|
||||
# Sort values. For standard metrics, higher is better (reverse=True).
|
||||
@@ -251,9 +286,9 @@ class FeatureService:
|
||||
"val": target_val,
|
||||
"rank": rank,
|
||||
"total": len(values_sorted),
|
||||
"min": min(values_sorted) if values_sorted else 0,
|
||||
"max": max(values_sorted) if values_sorted else 0,
|
||||
"avg": (sum(values_sorted) / len(values_sorted)) if values_sorted else 0,
|
||||
"min": min(values_sorted),
|
||||
"max": max(values_sorted),
|
||||
"avg": sum(values_sorted) / len(values_sorted),
|
||||
"inverted": not is_reverse,
|
||||
}
|
||||
return result
|
||||
|
||||
Reference in New Issue
Block a user