Add weekly historical leaderboard metrics

This commit is contained in:
devRaGonSa
2026-03-21 00:06:03 +01:00
parent 2ef0f9ebc7
commit 8a888f4cff
5 changed files with 202 additions and 5 deletions

View File

@@ -27,6 +27,14 @@ DEFAULT_HISTORICAL_SERVERS = (
)
DEFAULT_WEEKLY_WINDOW_DAYS = 7
DEFAULT_REFRESH_OVERLAP_HOURS = 12
SUPPORTED_WEEKLY_LEADERBOARD_METRICS = frozenset(
{
"kills",
"deaths",
"support",
"matches_over_100_kills",
}
)
def initialize_historical_storage(*, db_path: Path | None = None) -> Path:
@@ -763,16 +771,20 @@ def get_historical_player_profile(
}
def list_weekly_top_kills(
def list_weekly_leaderboard(
*,
limit: int = 10,
server_id: str | None = None,
metric: str = "kills",
db_path: Path | None = None,
) -> dict[str, object]:
"""Return ranked weekly kill totals from persisted historical match stats."""
"""Return ranked weekly leaderboard totals from persisted historical match stats."""
resolved_path = initialize_historical_storage(db_path=db_path)
window_end = datetime.now(timezone.utc)
window_start = window_end - timedelta(days=DEFAULT_WEEKLY_WINDOW_DAYS)
normalized_metric = metric.strip() if isinstance(metric, str) else ""
if normalized_metric not in SUPPORTED_WEEKLY_LEADERBOARD_METRICS:
raise ValueError(f"Unsupported weekly leaderboard metric: {metric}")
where_clauses = [
"historical_matches.ended_at IS NOT NULL",
@@ -790,6 +802,16 @@ def list_weekly_top_kills(
)
params.extend([normalized_server_id, normalized_server_id])
metric_sum_expression = {
"kills": "COALESCE(SUM(historical_player_match_stats.kills), 0)",
"deaths": "COALESCE(SUM(historical_player_match_stats.deaths), 0)",
"support": "COALESCE(SUM(historical_player_match_stats.support), 0)",
"matches_over_100_kills": (
"COALESCE(SUM(CASE WHEN COALESCE(historical_player_match_stats.kills, 0) >= 100 "
"THEN 1 ELSE 0 END), 0)"
),
}[normalized_metric]
with _connect(resolved_path) as connection:
rows = connection.execute(
f"""
@@ -801,11 +823,11 @@ def list_weekly_top_kills(
historical_players.display_name AS player_name,
historical_players.steam_id,
COUNT(DISTINCT historical_matches.id) AS matches_count,
COALESCE(SUM(historical_player_match_stats.kills), 0) AS kills,
{metric_sum_expression} AS metric_value,
ROW_NUMBER() OVER (
PARTITION BY historical_servers.slug
ORDER BY
COALESCE(SUM(historical_player_match_stats.kills), 0) DESC,
{metric_sum_expression} DESC,
COUNT(DISTINCT historical_matches.id) ASC,
historical_players.display_name ASC
) AS ranking_position
@@ -845,19 +867,48 @@ def list_weekly_top_kills(
"name": row["player_name"],
"steam_id": row["steam_id"],
},
"metric": normalized_metric,
"ranking_position": int(row["ranking_position"]),
"weekly_kills": int(row["kills"] or 0),
"metric_value": int(row["metric_value"] or 0),
"matches_considered": int(row["matches_count"] or 0),
}
)
return {
"metric": normalized_metric,
"window_start": window_start.isoformat().replace("+00:00", "Z"),
"window_end": window_end.isoformat().replace("+00:00", "Z"),
"items": items,
}
def list_weekly_top_kills(
*,
limit: int = 10,
server_id: str | None = None,
db_path: Path | None = None,
) -> dict[str, object]:
"""Return ranked weekly kill totals from persisted historical match stats."""
result = list_weekly_leaderboard(
limit=limit,
server_id=server_id,
metric="kills",
db_path=db_path,
)
items = []
for item in result["items"]:
legacy_item = dict(item)
legacy_item["weekly_kills"] = legacy_item["metric_value"]
items.append(legacy_item)
return {
"metric": "kills",
"window_start": result["window_start"],
"window_end": result["window_end"],
"items": items,
}
def _connect(db_path: Path) -> sqlite3.Connection:
connection = sqlite3.connect(db_path)
connection.row_factory = sqlite3.Row

View File

@@ -10,6 +10,7 @@ from .historical_storage import (
get_historical_player_profile,
list_historical_server_summaries,
list_recent_historical_matches,
list_weekly_leaderboard,
list_weekly_top_kills,
)
from .normalizers import normalize_map_name
@@ -211,6 +212,36 @@ def build_weekly_top_kills_payload(
}
def build_weekly_leaderboard_payload(
*,
limit: int = 10,
server_id: str | None = None,
metric: str = "kills",
) -> dict[str, object]:
"""Return one weekly historical leaderboard for the requested metric."""
result = list_weekly_leaderboard(limit=limit, server_id=server_id, metric=metric)
title_by_metric = {
"kills": "Top kills semanales por servidor",
"deaths": "Top muertes semanales por servidor",
"support": "Top puntos de soporte semanales por servidor",
"matches_over_100_kills": "Top partidas de 100+ kills semanales por servidor",
}
return {
"status": "ok",
"data": {
"title": title_by_metric.get(metric, "Ranking semanal por servidor"),
"context": "historical-weekly-leaderboard",
"metric": metric,
"summary_basis": "closed-matches-last-7-days",
"window_days": 7,
"window_start": result["window_start"],
"window_end": result["window_end"],
"limit": limit,
"items": result["items"],
},
}
def build_recent_historical_matches_payload(
*,
limit: int = 20,

View File

@@ -18,6 +18,7 @@ from .payloads import (
build_server_latest_payload,
build_servers_payload,
build_trailer_payload,
build_weekly_leaderboard_payload,
build_weekly_top_kills_payload,
)
@@ -50,6 +51,21 @@ def resolve_get_payload(path: str) -> tuple[HTTPStatus | None, dict[str, object]
server_id = parse_qs(parsed.query).get("server", [None])[0]
return HTTPStatus.OK, build_weekly_top_kills_payload(limit=limit, server_id=server_id)
if parsed.path == "/api/historical/weekly-leaderboard":
limit = _parse_limit(parsed.query)
if limit is None:
return HTTPStatus.BAD_REQUEST, build_error_payload("Invalid limit parameter")
params = parse_qs(parsed.query)
server_id = params.get("server", [None])[0]
metric = params.get("metric", ["kills"])[0]
if metric not in {"kills", "deaths", "support", "matches_over_100_kills"}:
return HTTPStatus.BAD_REQUEST, build_error_payload("Invalid metric parameter")
return HTTPStatus.OK, build_weekly_leaderboard_payload(
limit=limit,
server_id=server_id,
metric=metric,
)
if parsed.path == "/api/historical/recent-matches":
limit = _parse_limit(parsed.query)
if limit is None: