diff --git a/get_data.py b/get_data.py index 44f3a8c..86990a7 100644 --- a/get_data.py +++ b/get_data.py @@ -3922,6 +3922,56 @@ async def commentary(): or "—" ) + # тайм-ауты (пытаемся аккуратно вытащить, если есть в live-status) + home_side = ( + ls_dict.get("home") + or ls_dict.get("team1") + or ls_dict.get("homeTeam") + or {} + ) + away_side = ( + ls_dict.get("away") + or ls_dict.get("team2") + or ls_dict.get("awayTeam") + or {} + ) + + def pick_from(side: dict, top: dict, side_keys, top_keys) -> str: + """Берём первое непустое значение из side или из ls_dict.""" + if isinstance(side, dict): + for k in side_keys: + v = side.get(k) + if v not in (None, "", " "): + return str(v) + if isinstance(top, dict): + for k in top_keys: + v = top.get(k) + if v not in (None, "", " "): + return str(v) + return "—" + ts = result.get("team_stats", {}) or {} + + timeout_block = ts.get("timeout_left", {}) or {} + + # val1 и val2 — это именно значения для команд 1 и 2 + timeouts1 = timeout_block.get("val1") + timeouts2 = timeout_block.get("val2") + + # если пусто — ставим дефис + timeouts1 = str(timeouts1) if timeouts1 not in (None, "") else "—" + timeouts2 = str(timeouts2) if timeouts2 not in (None, "") else "—" + fouls1 = pick_from( + home_side, + ls_dict, + ["fouls", "fouls1", "foulsA", "teamFouls", "team1Fouls"], + ["fouls1", "foulsA", "homeFouls", "team1Fouls"], + ) + fouls2 = pick_from( + away_side, + ls_dict, + ["fouls", "fouls2", "foulsB", "teamFouls", "team2Fouls"], + ["fouls2", "foulsB", "awayFouls", "team2Fouls"], + ) # счёт по четвертям quarters = ["Q1", "Q2", "Q3", "Q4", "OT1", "OT2", "OT3", "OT4"] score_rows = [] @@ -3931,18 +3981,51 @@ async def commentary(): parts = fs_list[i].split(":") s1, s2 = (parts + ["", ""])[:2] score_rows.append((q, s1, s2)) + labels = [] + for i in range(len(fs_list)): + if i < 4: + labels.append(f"Q{i+1}") + else: + labels.append(f"OT{i-3}") - # как в /team1 и /team2 + score_rows = [] + for label, item in zip(labels, fs_list): + parts = item.split(":") + s1, s2 = (parts + ["", ""])[:2] + score_rows.append((label, s1, s2)) + + quarters_html = "".join( + f'
{q}' + f'{s1} : {s2}
' + for (q, s1, s2) in score_rows + if s1.strip() != "" and s2.strip() != "" + ) + + # данные по командам, как в /team1 и /team2 team1_players = await team("team1") team2_players = await team("team2") team1_json = json.dumps(team1_players, ensure_ascii=False) team2_json = json.dumps(team2_players, ensure_ascii=False) - def render_players_table(players, title, team_key: str) -> str: - header = """ - - + def render_players_table(players, title: str, team_key: str) -> str: + """ + Рендер таблицы игроков для commentary. + + - Показываем только игроков с startRole == "Player" + - Пропускаем строки без имени + - Корректно считаем REB (если нет 'reb', используем dreb + oreb) + - Вешаем data-on-court для дальнейшей подсветки в JS + - Для Foul добавляем классы foul-yellow / foul-red (4 и 5+) + - Колонки после MIN помечены .extra-col (прячутся галочкой) + """ + + # шапка таблицы + table_header = f""" +

{title}

+
+ + @@ -3959,68 +4042,113 @@ async def commentary(): - + + + """ - rows = [] - for p in players: - # только игроки - if p.get("startRole") not in ("Player", ""): + + rows_html: list[str] = [] + + for p in players or []: + # 1) Только реальные игроки + if p.get("startRole") != "Player": continue - num = p.get("num", "") - pid = p.get("id", "") - name = p.get("NameGFX") or p.get("name", "") - pts = p.get("pts", "") - reb = p.get("reb", (p.get("dreb", 0) or 0) + (p.get("oreb", 0) or 0)) - ast = p.get("ast", "") - stl = p.get("stl", "") - blk = p.get("blk", "") - time_played = p.get("time", "") + # 2) Имя (если пустое — пропускаем) + name = (p.get("NameGFX") or p.get("name") or "").strip() + if not name: + continue - fg = p.get("fg", "") - pt2 = p.get("pt-2", "") - pt3 = p.get("pt-3", "") - pt1 = p.get("pt-1", "") - to = p.get("to", "") - foul = p.get("foul", "") - plus_minus = p.get("plusMinus", "") - kpi = p.get("kpi", "") + # 3) Базовые поля + num = p.get("num") or "" + pid = p.get("id") or "" - rows.append( - f""" - - - - - - - - - - - - - - - - - - + pts = p.get("pts") + pts = "" if pts is None else pts + + # REB: если нет 'reb', то dreb + oreb + reb = p.get("reb") + if reb in ("", None): + dreb = p.get("dreb") or 0 + oreb = p.get("oreb") or 0 + reb_val = dreb + oreb + else: + reb_val = reb + + ast = p.get("ast") or "" + stl = p.get("stl") or "" + blk = p.get("blk") or "" + time_played = p.get("time") or "" + + fg = p.get("fg") or "" + pt2 = p.get("pt-2") or "" + pt3 = p.get("pt-3") or "" + pt1 = p.get("pt-1") or "" + to = p.get("to") or "" + + foul_raw = p.get("foul") + foul_str = "" if foul_raw is None else str(foul_raw) + + plus_minus = p.get("plusMinus") or "" + kpi = p.get("kpi") or "" + + # 4) классы по фолам + foul_class = "" + try: + foul_int = int(foul_str) + except (TypeError, ValueError): + foul_int = None + + if foul_int == 4: + foul_class = "foul-yellow" + elif foul_int is not None and foul_int >= 5: + foul_class = "foul-red" + + # 5) флаг isOnCourt → в data-атрибут (цвет строки считает JS) + on_court = bool(p.get("isOnCourt")) + row_attrs = f' data-on-court="{str(on_court).lower()}"' + + row_html = f""" + + + + + + + + + + + + + + + + + + """ + + rows_html.append(row_html) + + # Если вдруг ни одного игрока не прошло фильтр – покажем заглушку + if not rows_html: + rows_html.append( + '' ) - return f""" -

{title}

- {header} - {''.join(rows)} + table_footer = """ +
# Игрок PTSFoul +/- KPI
{num} - {name} - {pts}{reb}{ast}{stl}{blk}{time_played}{fg}{pt2}{pt3}{pt1}{to}{foul}{plus_minus}{kpi}
{num} + {name} + {pts}{reb_val}{ast}{stl}{blk}{time_played}{fg}{pt2}{pt3}{pt1}{to}{foul_str}{plus_minus}{kpi}
Нет данных по игрокам.
""" - # (pbp можно добавить сюда, я его пока опустил, чтобы не раздувать код) + return table_header + "".join(rows_html) + table_footer + + # пока без PBP, при необходимости подставишь сюда pbp_html pbp_html = "" game_time_str = GAME_START_DT.strftime("%d.%m.%Y %H:%M") if GAME_START_DT else "N/A" @@ -4030,8 +4158,41 @@ async def commentary(): Комментаторский дашборд - -

{team1_name} vs {team2_name}

-
- Счёт: {score_now or "—"} • Статус: {live_status} • Начало: {game_time_str} -
+
+
+
{team1_name}
+
+ Тайм-аутов осталось: {timeouts1}
+ Фолы: {fouls1} +
+
-

Счёт по четвертям

- - - {''.join(f"".format(q=q, s1=s1, s2=s2) for (q, s1, s2) in score_rows)} -
Период{team1_name}{team2_name}
{{q}}{{s1}}{{s2}}
+
+
{score_now or "—"}
+
+ Статус: {live_status} • Начало: {game_time_str} +
+
+ {quarters_html or 'Пока нет данных по четвертям.'} +
+
+ +
+
{team2_name}
+
+ Тайм-аутов осталось: {timeouts2}
+ Фолы: {fouls2} +
+
+