Добавленна функция Pregame_JSON, которая сохраняет Team Comparison

This commit is contained in:
2025-10-28 15:54:51 +03:00
parent 1839b8aec3
commit 5ab179e47b

View File

@@ -36,6 +36,7 @@ TELEGRAM_CHAT_ID = -4803699526
# Глобальный лок для потокобезопасной записи JSON # Глобальный лок для потокобезопасной записи JSON
_write_lock = threading.Lock() _write_lock = threading.Lock()
_pregame_done_for_game = {}
# Карта всех ручек API, с интервалами опроса в секундах. # Карта всех ручек API, с интервалами опроса в секундах.
URLS = [ URLS = [
@@ -495,7 +496,9 @@ def poll_game_live(
with ThreadPoolExecutor(max_workers=5) as executor: with ThreadPoolExecutor(max_workers=5) as executor:
while True: while True:
if stop_event.is_set(): if stop_event.is_set():
logger.info(f"[POLL] stop_event set -> break live poll for game {game_id}") logger.info(
f"[POLL] stop_event set -> break live poll for game {game_id}"
)
break break
now = time.time() now = time.time()
@@ -532,13 +535,17 @@ def poll_game_live(
# data может быть: # data может быть:
# {"status":"404","message":"Not found","result":None} # {"status":"404","message":"Not found","result":None}
# или {"status":"200","result":{"gameStatus":"Online", ...}} # или {"status":"200","result":{"gameStatus":"Online", ...}}
ls_result = data.get("result") if isinstance(data, dict) else None ls_result = (
data.get("result") if isinstance(data, dict) else None
)
game_status = "" game_status = ""
if isinstance(ls_result, dict): if isinstance(ls_result, dict):
game_status = (ls_result.get("gameStatus") or "").lower() game_status = (ls_result.get("gameStatus") or "").lower()
if game_status in ("resultconfirmed", "finished", "result"): if game_status in ("resultconfirmed", "finished", "result"):
logger.info(f"[POLL] Game {game_id} finished by live-status") logger.info(
f"[POLL] Game {game_id} finished by live-status"
)
game_finished = True game_finished = True
except Exception as e: except Exception as e:
@@ -553,7 +560,7 @@ def poll_game_live(
if game_finished: if game_finished:
break break
time.sleep(.5) time.sleep(0.5)
if stop_event.is_set(): if stop_event.is_set():
logger.info( logger.info(
@@ -634,7 +641,9 @@ def build_render_state() -> dict:
player["stats"] = stat player["stats"] = stat
# total по команде # total по команде
team["total"] = box_team.get("total", {}) if isinstance(box_team, dict) else {} team["total"] = (
box_team.get("total", {}) if isinstance(box_team, dict) else {}
)
# периоды и общий счёт # периоды и общий счёт
if isinstance(box_score_data["result"], dict): if isinstance(box_score_data["result"], dict):
@@ -674,7 +683,9 @@ def render_loop(stop_event: threading.Event, out_name: str = "game") -> None:
state = build_render_state() state = build_render_state()
except Exception as build_err: except Exception as build_err:
# до тех пор, пока api_game не готов или битый — просто ждём # до тех пор, пока api_game не готов или битый — просто ждём
logger.debug(f"[RENDER_THREAD] build_render_state not ready: {build_err}") logger.debug(
f"[RENDER_THREAD] build_render_state not ready: {build_err}"
)
time.sleep(0.2) time.sleep(0.2)
continue continue
@@ -1589,6 +1600,101 @@ def Team_Both_Stat(merged: dict) -> None:
logger.error(f"Ошибка при обработке командной статистики: {e}", exc_info=True) logger.error(f"Ошибка при обработке командной статистики: {e}", exc_info=True)
def Pregame_data_json(data: dict) -> None:
teams = []
for data_team in (data["teamStats1"], data["teamStats2"]):
temp_team = {
"team": data_team["team"]["name"],
"games": data_team["games"],
"points": round(
(data_team["totalStats"]["points"] / data_team["games"]), 1
),
"points_2": round(
(
data_team["totalStats"]["goal2"]
* 100
/ data_team["totalStats"]["shot2"]
),
1,
),
"points_3": round(
(
data_team["totalStats"]["goal3"]
* 100
/ data_team["totalStats"]["shot3"]
),
1,
),
"points_23": round(
(
data_team["totalStats"]["goal23"]
* 100
/ data_team["totalStats"]["shot23"]
),
1,
),
"points_1": round(
(
data_team["totalStats"]["goal1"]
* 100
/ data_team["totalStats"]["shot1"]
),
1,
),
"assists": round(
(data_team["totalStats"]["assist"] / data_team["games"]), 1
),
"rebounds": round(
(
(
data_team["totalStats"]["defRebound"]
+ data_team["totalStats"]["offRebound"]
)
/ data_team["games"]
),
1,
),
"steals": round((data_team["totalStats"]["steal"] / data_team["games"]), 1),
"turnovers": round(
(data_team["totalStats"]["turnover"] / data_team["games"]), 1
),
"blocks": round(
(data_team["totalStats"]["blockShot"] / data_team["games"]), 1
),
"fouls": round((data_team["totalStats"]["foul"] / data_team["games"]), 1),
}
teams.append(temp_team)
atomic_write_json(teams, "team_comparison")
logger.info("Сохранил payload: team_comparison.json")
def Pregame_data(pregame_raw: dict, game_stub: dict) -> None:
"""
Обработка предматчевых данных (Pregame).
Вызывается один раз ДО начала матча, если матч сегодня.
Вход:
pregame_raw -> ответ от /pregame (dict или None)
game_stub -> today_game["game"] из календаря (минимальная информация о матче)
"""
try:
out = {
"game": game_stub or {},
"pregame": (
pregame_raw.get("result")
if isinstance(pregame_raw, dict)
else pregame_raw
),
"generatedAt": _now_iso(),
}
Pregame_data_json(out["pregame"])
# сохраняем файл
# atomic_write_json(out["pregame"], "pregame")
# logger.info("Сохранил payload: pregame.json")
except Exception as e:
logger.error(f"Ошибка в Pregame_data: {e}", exc_info=True)
def Scores_Quarter(merged: dict) -> None: def Scores_Quarter(merged: dict) -> None:
""" """
Пишет счёт по четвертям и овертаймам в static/scores.json. Пишет счёт по четвертям и овертаймам в static/scores.json.
@@ -1680,7 +1786,11 @@ def Standing_func(
for item in items: for item in items:
comp = item.get("comp", {}) comp = item.get("comp", {})
comp_name = (comp.get("name") or "unknown_comp").replace(" ", "_").replace("|", "") comp_name = (
(comp.get("name") or "unknown_comp")
.replace(" ", "_")
.replace("|", "")
)
if item.get("standings"): if item.get("standings"):
standings_rows = item["standings"] standings_rows = item["standings"]
@@ -1697,8 +1807,16 @@ def Standing_func(
and "totalGoalPlus" in df.columns and "totalGoalPlus" in df.columns
and "totalGoalMinus" in df.columns and "totalGoalMinus" in df.columns
): ):
tw = pd.to_numeric(df["totalWin"], errors="coerce").fillna(0).astype(int) tw = (
td = pd.to_numeric(df["totalDefeat"], errors="coerce").fillna(0).astype(int) pd.to_numeric(df["totalWin"], errors="coerce")
.fillna(0)
.astype(int)
)
td = (
pd.to_numeric(df["totalDefeat"], errors="coerce")
.fillna(0)
.astype(int)
)
df["w_l"] = tw.astype(str) + " / " + td.astype(str) df["w_l"] = tw.astype(str) + " / " + td.astype(str)
@@ -1723,8 +1841,16 @@ def Standing_func(
df["procent"] = df.apply(calc_percent, axis=1) df["procent"] = df.apply(calc_percent, axis=1)
tg_plus = pd.to_numeric(df["totalGoalPlus"], errors="coerce").fillna(0).astype(int) tg_plus = (
tg_minus = pd.to_numeric(df["totalGoalMinus"], errors="coerce").fillna(0).astype(int) pd.to_numeric(df["totalGoalPlus"], errors="coerce")
.fillna(0)
.astype(int)
)
tg_minus = (
pd.to_numeric(df["totalGoalMinus"], errors="coerce")
.fillna(0)
.astype(int)
)
df["plus_minus"] = tg_plus - tg_minus df["plus_minus"] = tg_plus - tg_minus
@@ -1872,11 +1998,39 @@ def get_data_API(
return "live_done" return "live_done"
if phase == "upcoming": if phase == "upcoming":
# матч сегодня, но ещё не начался (Scheduled / NotStarted / Draft)
# не генерим финал, не спим до завтра
logger.info( logger.info(
f"Матч {game_id} сегодня, но ещё не начался (status={effective_status}). Ждём старт." f"Матч {game_id} сегодня, но ещё не начался (status={effective_status}). Подготовка pregame."
) )
# дергаем pregame только один раз за матч
if not _pregame_done_for_game.get(game_id):
try:
pregame_raw = fetch_api_data(
session,
"pregame",
host=HOST,
league=league,
season=season,
game_id=game_id,
lang=lang,
)
Pregame_data(
pregame_raw=pregame_raw,
game_stub=today_game["game"],
)
_pregame_done_for_game[game_id] = True
logger.info(
f"[get_data_API] pregame данные собраны для game_id={game_id}"
)
except Exception as e:
logger.exception(
f"[get_data_API] ошибка при подготовке pregame для {game_id}: {e}"
)
# матч сегодня, ждём старта
return "upcoming" return "upcoming"
if phase == "finished": if phase == "finished":