This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
"""
|
||||
League Reliability Loader
|
||||
=========================
|
||||
Loads pre-computed per-league odds reliability scores from
|
||||
data/league_reliability.json. Called once at orchestrator startup.
|
||||
|
||||
The reliability score (0.0 – 1.0) represents how well-calibrated
|
||||
a league's betting odds are based on historical Brier Score analysis.
|
||||
|
||||
Usage:
|
||||
from utils.league_reliability import load_league_reliability
|
||||
lookup = load_league_reliability()
|
||||
rel = lookup.get(league_id, 0.35)
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from typing import Dict
|
||||
|
||||
|
||||
_DATA_FILE = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"..",
|
||||
"data",
|
||||
"league_reliability.json",
|
||||
)
|
||||
|
||||
|
||||
def load_league_reliability() -> Dict[str, float]:
|
||||
"""
|
||||
Returns a dict mapping league_id → odds_reliability (0.0-1.0).
|
||||
Falls back gracefully to an empty dict if the file is missing.
|
||||
"""
|
||||
if not os.path.isfile(_DATA_FILE):
|
||||
print(
|
||||
f"⚠️ league_reliability.json not found at {_DATA_FILE}. "
|
||||
"All leagues will use default reliability (0.35)."
|
||||
)
|
||||
return {}
|
||||
|
||||
try:
|
||||
with open(_DATA_FILE, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
lookup: Dict[str, float] = data.get("lookup", {})
|
||||
total = len(lookup)
|
||||
print(f"✅ Loaded odds reliability for {total} leagues")
|
||||
return lookup
|
||||
|
||||
except (json.JSONDecodeError, KeyError, TypeError) as exc:
|
||||
print(f"⚠️ Failed to parse league_reliability.json: {exc}")
|
||||
return {}
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
"""
|
||||
Top leagues loader utility.
|
||||
|
||||
Loads league IDs from top_leagues.json with light validation and caching.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
from typing import Any, Set
|
||||
|
||||
|
||||
def _candidate_paths() -> list[Path]:
|
||||
here = Path(__file__).resolve()
|
||||
# .../ai-engine/utils/top_leagues.py
|
||||
repo_root = here.parents[2]
|
||||
ai_engine_root = here.parents[1]
|
||||
return [
|
||||
repo_root / "top_leagues.json",
|
||||
ai_engine_root / "top_leagues.json",
|
||||
]
|
||||
|
||||
|
||||
def _extract_ids(payload: Any) -> Set[str]:
|
||||
ids: Set[str] = set()
|
||||
if not isinstance(payload, list):
|
||||
return ids
|
||||
|
||||
for item in payload:
|
||||
if isinstance(item, str):
|
||||
val = item.strip()
|
||||
if val:
|
||||
ids.add(val)
|
||||
continue
|
||||
|
||||
if isinstance(item, dict):
|
||||
for key in ("id", "league_id", "leagueId"):
|
||||
raw = item.get(key)
|
||||
if raw is not None:
|
||||
val = str(raw).strip()
|
||||
if val:
|
||||
ids.add(val)
|
||||
break
|
||||
|
||||
return ids
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def load_top_league_ids() -> Set[str]:
|
||||
for path in _candidate_paths():
|
||||
if not path.exists():
|
||||
continue
|
||||
try:
|
||||
with path.open("r", encoding="utf-8") as f:
|
||||
payload = json.load(f)
|
||||
return _extract_ids(payload)
|
||||
except Exception:
|
||||
continue
|
||||
return set()
|
||||
|
||||
Reference in New Issue
Block a user