import os
import json
import socket
import platform
import numpy as np
import pandas as pd
import streamlit as st
import sys
from streamlit_autorefresh import st_autorefresh
st.set_page_config(
page_title="Баскетбол",
page_icon="🏀",
layout="wide",
initial_sidebar_state="expanded",
menu_items={"About": "версия 1.8 22.01.2025"},
)
REMOVE_PADDING_FROM_SIDES = """
"""
st.markdown(REMOVE_PADDING_FROM_SIDES, unsafe_allow_html=True)
st_autorefresh()
# Функции для стилизации
def highlight_max(data):
# Преобразуем данные к числовому типу, заменяя некорректные значения на NaN
numeric_data = pd.to_numeric(data, errors="coerce")
max_value = numeric_data.max() if pd.notna(numeric_data.max()) else None
return [
"background-color: green" if pd.notna(v) and v == max_value and v > 0 else ""
for v in numeric_data
]
def color_win(s):
return [
(
"background-color: ForestGreen"
if v == True
else "background-color: #FF4B4B" if v == False else None
)
for v in s
]
def highlight_grey(s):
return ["background-color: grey"] * len(s) if s.foul == 5 else [""] * len(s)
def highlight_foul(s):
return [
(
"background-color: orange"
if v == 4
else "background-color: red" if v == 5 else ""
)
for v in s
]
def load_json_data(filepath):
"""
Загружает данные из JSON файла и кэширует их.
Возвращает None, если файл не удается прочитать.
"""
try:
with open(filepath, "r", encoding="utf-8") as file:
return json.load(file)
except (json.JSONDecodeError, FileNotFoundError):
return None
def show_df(container, data, *, base_row_h=38, min_rows=12, max_h=1200, **kwargs):
# вычисляем высоту
try:
n = len(data)
except Exception:
n = 0
h = base_row_h * max(n, min_rows)
# зажимаем в допустимый диапазон
if not isinstance(h, int):
h = int(h)
h = max(0, min(h, max_h))
# если высота 0 или данных мало — не передаём height вовсе
if h <= 0 or n == 0:
container.dataframe(data, **kwargs)
else:
container.dataframe(data, height=h, **kwargs)
# Функция для обработки данных одной команды
def process_team_data(team_json, columns_to_include):
team_data = pd.json_normalize(team_json)
# Оставляем только нужные колонки
team_data = team_data[:12][columns_to_include]
# Обработка height и weight
for column in ["height", "weight"]:
if column in team_data.columns:
team_data[column] = team_data[column].apply(
lambda value: "" if value == 0 else value
)
return team_data
def process_player_data(team_json, player_index):
team_data = pd.json_normalize(team_json)
player_data = team_data.iloc[player_index]
season_total = {
"name": "Season Total",
"game_count": str(player_data["TGameCount"]),
"start_count": str(player_data["TStartCount"]),
"pts": str(player_data["TPoints"]),
"pt-2": str(player_data["TShots2"]),
"pt-3": str(player_data["TShots3"]),
"pt-1": str(player_data["TShots1"]),
"fg": str(player_data["TShots23"]),
"ast": str(player_data["TAssist"]),
"stl": str(player_data["TSteal"]),
"blk": str(player_data["TBlocks"]),
"dreb": str(player_data["TDefRebound"]),
"oreb": str(player_data["TOffRebound"]),
"reb": str(player_data["TRebound"]),
# "to": str(player_data["TTurnover"]),
# "foul": str(player_data["TFoul"]),
"fouled": str(player_data["TOpponentFoul"]),
"dunk": str(player_data["TDunk"]),
"time": str(player_data["TPlayedTime"]),
}
season_avg = {
"name": "Season Average",
"game_count": "",
"start_count": "",
"pts": str(player_data["AvgPoints"]),
"pt-2": str(player_data["Shot2Percent"]),
"pt-3": str(player_data["Shot3Percent"]),
"pt-1": str(player_data["Shot1Percent"]),
"fg": str(player_data["Shot23Percent"]),
"ast": str(player_data["AvgAssist"]),
"stl": str(player_data["AvgSteal"]),
"blk": str(player_data["AvgBlocks"]),
"dreb": str(player_data["AvgDefRebound"]),
"oreb": str(player_data["AvgOffRebound"]),
"reb": str(player_data["AvgRebound"]),
# "to": str(player_data["AvgTurnover"]),
# "foul": str(player_data["AvgFoul"]),
"fouled": str(player_data["AvgOpponentFoul"]),
"dunk": str(player_data["AvgDunk"]),
"time": str(player_data["AvgPlayedTime"]),
}
career_total = {
"name": "Career Total",
"game_count": str(player_data["CareerTGameCount"]),
"start_count": str(player_data["CareerTStartCount"]),
"pts": str(player_data["CareerTPoints"]),
"pt-2": str(player_data["CareerTShots2"]),
"pt-3": str(player_data["CareerTShots3"]),
"pt-1": str(player_data["CareerTShots1"]),
"fg": str(player_data["CareerTShots23"]),
"ast": str(player_data["CareerTAssist"]),
"stl": str(player_data["CareerTSteal"]),
"blk": str(player_data["CareerTBlocks"]),
"dreb": str(player_data["CareerTDefRebound"]),
"oreb": str(player_data["CareerTOffRebound"]),
"reb": str(player_data["CareerTRebound"]),
# "to": str(player_data["CareerTTurnover"]),
# "foul": str(player_data["CareerTFoul"]),
"fouled": str(player_data["CareerTOpponentFoul"]),
"dunk": str(player_data["CareerTDunk"]),
"time": str(player_data["CareerTPlayedTime"]),
}
return [season_total, season_avg, career_total], player_data
config = {
"flag": st.column_config.ImageColumn("flag"),
"roleShort": st.column_config.TextColumn("R", width=27),
"num": st.column_config.TextColumn("#", width=27),
"NameGFX": st.column_config.TextColumn(width=170),
"isOn": st.column_config.TextColumn("🏀", width=27),
"pts": st.column_config.NumberColumn("PTS", width=27),
"pt-2": st.column_config.TextColumn("2-PT", width=45),
"pt-3": st.column_config.TextColumn("3-PT", width=45),
"pt-1": st.column_config.TextColumn("FT", width=45),
"fg": st.column_config.TextColumn("FG", width=45),
"ast": st.column_config.NumberColumn("AS", width=27),
"stl": st.column_config.NumberColumn("ST", width=27),
"blk": st.column_config.NumberColumn("BL", width=27),
"blkVic": st.column_config.NumberColumn("BV", width=27),
"dreb": st.column_config.NumberColumn("DR", width=27),
"oreb": st.column_config.NumberColumn("OR", width=27),
"reb": st.column_config.NumberColumn("R", width=27),
"to": st.column_config.NumberColumn("TO", width=27),
"foul": st.column_config.NumberColumn("F", width=27),
"fouled": st.column_config.NumberColumn("Fed", width=27),
"plusMinus": st.column_config.NumberColumn("+/-", width=27),
"dunk": st.column_config.NumberColumn("DUNK", width=27),
"kpi": st.column_config.NumberColumn("KPI", width=27),
"time": st.column_config.TextColumn("TIME"),
"game_count": st.column_config.TextColumn("G", width=27),
"start_count": st.column_config.TextColumn("S", width=27),
"q_pts": st.column_config.TextColumn("PTS", width=27),
"q_ast": st.column_config.TextColumn("AS", width=27),
"q_stl": st.column_config.TextColumn("ST", width=27),
"q_blk": st.column_config.TextColumn("BL", width=27),
"q_reb": st.column_config.TextColumn("R", width=27),
"q_rnk": st.column_config.TextColumn("KPI", width=27),
"q_f": st.column_config.TextColumn("F", width=27),
"q_f_on": st.column_config.TextColumn("Fed", width=27),
"q_to": st.column_config.TextColumn("TO", width=27),
"q_time": st.column_config.TextColumn("TIME"),
"q_pt2": st.column_config.TextColumn("2-PT", width=45),
"q_pt3": st.column_config.TextColumn("3-PT", width=45),
"q_pt23": st.column_config.TextColumn("FG", width=45),
"q_ft": st.column_config.TextColumn("FT", width=45),
}
config_season = {
"flag": st.column_config.ImageColumn("flag"),
"roleShort": st.column_config.TextColumn("R", width=27),
"num": st.column_config.TextColumn("#", width=27),
"NameGFX": st.column_config.TextColumn(width=170),
"isOn": st.column_config.TextColumn("🏀", width=27),
"pts": st.column_config.TextColumn("PTS", width=40),
"pt-2": st.column_config.TextColumn("2-PT", width=60),
"pt-3": st.column_config.TextColumn("3-PT", width=60),
"pt-1": st.column_config.TextColumn("FT", width=60),
"fg": st.column_config.TextColumn("FG", width=60),
"ast": st.column_config.TextColumn("AS", width=40),
"stl": st.column_config.TextColumn("ST", width=40),
"blk": st.column_config.TextColumn("BL", width=40),
"blkVic": st.column_config.TextColumn("BV", width=40),
"dreb": st.column_config.TextColumn("DR", width=40),
"oreb": st.column_config.TextColumn("OR", width=40),
"reb": st.column_config.TextColumn("R", width=40),
"to": st.column_config.TextColumn("TO", width=40),
"foul": st.column_config.TextColumn("F", width=40),
"fouled": st.column_config.TextColumn("Fed", width=40),
"plusMinus": st.column_config.TextColumn("+/-", width=40),
"dunk": st.column_config.TextColumn("DUNK", width=40),
"kpi": st.column_config.TextColumn("KPI", width=40),
"time": st.column_config.TextColumn("TIME"),
"game_count": st.column_config.TextColumn("G", width=40),
"start_count": st.column_config.TextColumn("S", width=40),
}
if "player1" not in st.session_state:
st.session_state.player1 = None
if "player2" not in st.session_state:
st.session_state.player2 = None
# myhost = platform.node()
# FOLDER_JSON = ""
# if platform == "win32":
# FOLDER_JSON = "JSON"
# else:
# FOLDER_JSON = "static"
myhost = platform.node()
if sys.platform.startswith("win"): # было: if platform == "win32":
FOLDER_JSON = "JSON"
else:
FOLDER_JSON = "static"
def get_ip_address():
try:
# Попытка получить IP-адрес с использованием внешнего сервиса
# Может потребоваться подключение к интернету
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ip_address = s.getsockname()[0]
except socket.error:
# Если не удалось получить IP-адрес через внешний сервис,
# используем метод для локального получения IP
ip_address = socket.gethostbyname(socket.gethostname())
return ip_address
def load_data_from_json2(filepath):
directory = FOLDER_JSON
os.makedirs(directory, exist_ok=True)
filepath = os.path.join(directory, f"{filepath}.json")
ip = get_ip_address()
host = ip_check.get(ip, {}).get("host")
# st.write(filepath)
key = filepath.replace(f"static/{host}_", "").replace(".json","") # Создаём уникальный ключ на основе значения filepath
# st.write(key)
temp = load_json_data(filepath)
# st.write(temp)
if key not in st.session_state:
st.session_state[key] = temp
else:
st.session_state[key] = temp
def load_data_from_json(filepath):
directory = FOLDER_JSON
os.makedirs(directory, exist_ok=True)
filepath_full = os.path.join(directory, f"{filepath}.json")
ip = get_ip_address()
host = ip_check.get(ip, {}).get("host") or "" # безопаснее
# Ключ в session_state: <имя файла> без префикса _
# Пример: static/abc_game_online.json -> game_online
base = os.path.basename(filepath_full).replace(".json","")
key = base.replace(f"{host}_", "", 1)
temp = load_json_data(filepath_full) # None, если нет файла/парсинга
st.session_state[key] = temp # ключ гарантированно создаётся
try:
with open("match_id.json", "r", encoding="utf-8") as f:
ip_check = json.load(f)
except (FileNotFoundError, json.JSONDecodeError):
ip_check = {}
ip_address = get_ip_address()
prefix = ip_check.get(ip_address, {}).get("host")
# load_data_from_json(f"{prefix}_game_online")
# cached_game_online = st.session_state.game_online
# # for i in cached_game_online["result"]:
# # print(i)
# # print(cached_game_online["result"]["plays"])
# load_data_from_json(f"{prefix}_team1")
# cached_team1 = st.session_state.team1
# load_data_from_json(f"{prefix}_team2")
# cached_team2 = st.session_state.team2
# load_data_from_json(f"{prefix}_referee")
# cached_referee = st.session_state.referee
# try:
# load_data_from_json(f'{prefix}_standings_{cached_game_online["result"]["league"]["tag"]}')
# except TypeError:
# pass
# if cached_game_online:
# cached_standings = st.session_state[
# f'standings_{cached_game_online["result"]["league"]["tag"]}'
# ]
# else:
# cached_standings = None
# load_data_from_json(f"{prefix}_scores_quarter")
# cached_scores_quarter = st.session_state.scores_quarter
# load_data_from_json(f"{prefix}_play_by_play")
# cached_play_by_play = st.session_state.play_by_play
# load_data_from_json(f"{prefix}_team_stats")
# cached_team_stats = st.session_state.team_stats
# load_data_from_json(f"{prefix}_scores")
# cached_scores = st.session_state.scores
# load_data_from_json(f"{prefix}_live_status")
# cached_live_status = st.session_state.live_status
# load_data_from_json(f"{prefix}_schedule")
# cached_schedule = st.session_state.schedule
load_data_from_json(f"{prefix}_game_online")
cached_game_online = st.session_state.get("game_online")
load_data_from_json(f"{prefix}_team1")
cached_team1 = st.session_state.get("team1")
load_data_from_json(f"{prefix}_team2")
cached_team2 = st.session_state.get("team2")
load_data_from_json(f"{prefix}_referee")
cached_referee = st.session_state.get("referee")
# standings — может не быть тега/файла
league_tag = None
if isinstance(cached_game_online, dict):
league_tag = ((cached_game_online.get("result") or {}).get("league") or {}).get("tag")
if league_tag:
load_data_from_json(f"{prefix}_standings_{league_tag}")
cached_standings = st.session_state.get(f"standings_{league_tag}") if league_tag else None
load_data_from_json(f"{prefix}_scores_quarter")
cached_scores_quarter = st.session_state.get("scores_quarter")
load_data_from_json(f"{prefix}_play_by_play")
cached_play_by_play = st.session_state.get("play_by_play")
load_data_from_json(f"{prefix}_team_stats")
cached_team_stats = st.session_state.get("team_stats")
load_data_from_json(f"{prefix}_scores")
cached_scores = st.session_state.get("scores") or [] # важно!
load_data_from_json(f"{prefix}_live_status")
cached_live_status = st.session_state.get("live_status")
load_data_from_json(f"{prefix}_schedule")
cached_schedule = st.session_state.get("schedule")
# st.session_state
def ensure_state(key: str, default=None):
# Инициализирует ключ один раз и возвращает значение
return st.session_state.setdefault(key, default)
# period_max = 0
# if cached_play_by_play and cached_game_online and cached_game_online["result"]["plays"]:
# df_data_pbp = pd.DataFrame(cached_play_by_play)
# if "play" in df_data_pbp:
# period_max = df_data_pbp.iloc[0]["period"]
# count_quarter = [
# f"Четверть {i}" if i < 5 else f"Овертайм {i-4}"
# for i in range(1, int(period_max) + 1)
# ]
# for i in range(period_max):
# i += 1
# key_team1 = f"team1_{i}"
# key_team2 = f"team2_{i}"
# load_data_from_json(key_team1)
# load_data_from_json(key_team2)
# # if key_quarter_team1:
# # key_quarter_team1 = st.session_state[key_quarter_team1]
# # if key_quarter_team2:
# # key_quarter_team2 = st.session_state[key_quarter_team2]
# key_quarter_team1 = st.session_state.get(key_team1) # None, если ключа нет
# key_quarter_team2 = st.session_state.get(key_team2)
period_max = 0
if isinstance(cached_play_by_play, list) and isinstance(cached_game_online, dict):
plays = (cached_game_online.get("result") or {}).get("plays") or []
if plays:
df_data_pbp = pd.DataFrame(cached_play_by_play)
if not df_data_pbp.empty and "period" in df_data_pbp.columns:
period_max = int(df_data_pbp.iloc[0]["period"])
count_quarter = [
f"Четверть {i}" if i < 5 else f"Овертайм {i-4}"
for i in range(1, period_max + 1)
]
for i in range(1, period_max + 1):
key_team1 = f"team1_{i}"
key_team2 = f"team2_{i}"
load_data_from_json(key_team1)
load_data_from_json(key_team2)
_q1 = st.session_state.get(key_team1) # может быть None — это ок
_q2 = st.session_state.get(key_team2)
timeout1 = []
timeout2 = []
# if cached_game_online:
# for event in cached_game_online["result"]["plays"]:
# if event["play"] == 23:
# if event["startNum"] == 1:
# timeout1.append(event)
# elif event["startNum"] == 2:
# timeout2.append(event)
# # with st.expander(""):
# col1, col4, col2, col5, col3 = st.columns([1, 5, 3, 5, 1])
# col1.image(cached_game_online["result"]["team1"]["logo"], width=100)
# team1_name = cached_game_online["result"]["team1"]["name"]
# team2_name = cached_game_online["result"]["team2"]["name"]
# col2.markdown(
# f"{team1_name} — {team2_name}
",
# unsafe_allow_html=True,
# )
# col3.image(cached_game_online["result"]["team2"]["logo"], width=100)
# col4_1, col4_2, col4_3 = col4.columns((1, 1, 1))
# delta_color_1 = (
# "off"
# if int(cached_team_stats[0]["val1"]) == int(cached_team_stats[0]["val2"])
# else "normal"
# )
# col4_1.metric(
# "Points",
# cached_team_stats[0]["val1"],
# int(cached_team_stats[0]["val1"]) - int(cached_team_stats[0]["val2"]),
# delta_color_1,
# )
# col4_3.metric("TimeOuts", len(timeout1))
# col5_1, col5_2, col5_3 = col5.columns((1, 1, 1))
# col5_3.metric(
# "Points",
# cached_team_stats[0]["val2"],
# int(cached_team_stats[0]["val2"]) - int(cached_team_stats[0]["val1"]),
# delta_color_1,
# )
# col5_1.metric("TimeOuts", len(timeout2))
# # print(cached_live_status)
# if cached_live_status is not None:
# col4_2.metric("Fouls", cached_live_status[0]["foulsA"])
# col5_2.metric("Fouls", cached_live_status[0]["foulsB"])
if isinstance(cached_game_online, dict):
result = cached_game_online.get("result") or {}
plays = result.get("plays") or []
timeout1, timeout2 = [], []
for event in plays:
if isinstance(event, dict) and event.get("play") == 23:
if event.get("startNum") == 1:
timeout1.append(event)
elif event.get("startNum") == 2:
timeout2.append(event)
col1, col4, col2, col5, col3 = st.columns([1, 5, 3, 5, 1])
t1 = (result.get("team1") or {})
t2 = (result.get("team2") or {})
if t1.get("logo"):
col1.image(t1["logo"], width=100)
team1_name = t1.get("name") or ""
team2_name = t2.get("name") or ""
if team1_name or team2_name:
col2.markdown(
f"{team1_name} — {team2_name}
",
unsafe_allow_html=True,
)
if t2.get("logo"):
col3.image(t2["logo"], width=100)
col4_1, col4_2, col4_3 = col4.columns((1, 1, 1))
col5_1, col5_2, col5_3 = col5.columns((1, 1, 1))
# Points метрики безопасно
val1 = val2 = None
if isinstance(cached_team_stats, list) and len(cached_team_stats) > 0:
v1 = cached_team_stats[0].get("val1")
v2 = cached_team_stats[0].get("val2")
if v1 is not None and v2 is not None:
val1, val2 = int(v1), int(v2)
delta_color_1 = "off" if val1 == val2 else "normal"
col4_1.metric("Points", v1, val1 - val2, delta_color_1)
col5_3.metric("Points", v2, val2 - val1, delta_color_1)
col4_3.metric("TimeOuts", len(timeout1))
col5_1.metric("TimeOuts", len(timeout2))
if isinstance(cached_live_status, list) and cached_live_status:
foulsA = (cached_live_status[0] or {}).get("foulsA")
foulsB = (cached_live_status[0] or {}).get("foulsB")
if foulsA is not None:
col4_2.metric("Fouls", foulsA)
if foulsB is not None:
col5_2.metric("Fouls", foulsB)
# if cached_game_online and cached_game_online["result"]["plays"]:
# col_1_col = [f"col_1_{i}" for i in range(1, int(period_max) + 1)]
# col_2_col = [f"col_2_{i}" for i in range(1, int(period_max) + 1)]
# count_q = 0
# cached_scores = cached_scores or []
# score_by_quarter_1 = [x["score1"] for x in cached_scores if x["score1"] != ""]
# score_by_quarter_2 = [x["score2"] for x in cached_scores if x["score2"] != ""]
# if score_by_quarter_1 != []:
# col_1_col = col4.columns([1 for i in range(1, len(score_by_quarter_1) + 1)])
# col_2_col = col5.columns([1 for i in range(1, len(score_by_quarter_2) + 1)])
# # print(score_by_quarter_1)
# for q1, q2, col1, col2 in zip(
# score_by_quarter_1, score_by_quarter_2, col_1_col, col_2_col
# ):
# count_q += 1
# name_q = ""
# if count_q > 4:
# name_q = f"OT{count_q-4}"
# else:
# name_q = f"Q{count_q}"
# # print(q1, q2)
# delta_color = "off" if int(q1) == int(q2) else "normal"
# col1.metric(name_q, q1, int(q1) - int(q2), delta_color, border=True)
# col2.metric(name_q, q2, int(q2) - int(q1), delta_color, border=True)
if isinstance(cached_game_online, dict) and ((cached_game_online.get("result") or {}).get("plays") or []):
col_1_col = [f"col_1_{i}" for i in range(1, period_max + 1)]
col_2_col = [f"col_2_{i}" for i in range(1, period_max + 1)]
count_q = 0
score_by_quarter_1 = [x.get("score1") for x in cached_scores if isinstance(x, dict) and x.get("score1") not in ("", None)]
score_by_quarter_2 = [x.get("score2") for x in cached_scores if isinstance(x, dict) and x.get("score2") not in ("", None)]
if score_by_quarter_1:
col_1_col = col4.columns([1 for _ in range(len(score_by_quarter_1))])
col_2_col = col5.columns([1 for _ in range(len(score_by_quarter_2))])
for q1, q2, col1_i, col2_i in zip(score_by_quarter_1, score_by_quarter_2, col_1_col, col_2_col):
count_q += 1
name_q = f"OT{count_q-4}" if count_q > 4 else f"Q{count_q}"
try:
delta_color = "off" if int(q1) == int(q2) else "normal"
col1_i.metric(name_q, q1, int(q1) - int(q2), delta_color, border=True)
col2_i.metric(name_q, q2, int(q2) - int(q1), delta_color, border=True)
except (ValueError, TypeError):
# если кривые данные в JSON, просто пропустим
pass
(
tab_temp_1,
tab_temp_2,
tab_temp_3,
tab_temp_4,
tab_temp_5,
tab_temp_6,
tab_pbp,
tab_temp_7,
tab_temp_8,
tab_schedule,
) = st.tabs(
[
"Игроки",
"Команды",
"Судьи",
"Турнирная таблица",
"Статистика четвертей",
"Ход игры",
"События игры",
"Статистика по четвертям",
"Milestones",
"Прошедшие/будущие матчи",
]
)
def check_milestone(value, milestone_type, name, num, where):
milestone_checks = {
"PTS": "point",
"AST": "assist",
"BLK": "block",
"REB": "rebound",
"DREB": "defensive rebound",
"OREB": "offensive rebound",
"STL": "steal",
"GAMES": "game",
}
if milestone_type == "GAMES":
list_data = [*range(50, 5100, 50)]
if int(value) % 100 in [49, 99]:
diff = [l - int(value) for l in list_data]
positive_numbers = [num for num in diff if num > -1]
count = 0
for i in diff:
count += 1
if i == min(positive_numbers):
break
full_word = [
word
for w, word in milestone_checks.items()
if w.lower() == milestone_type.lower()
][0]
# print(positive_numbers)
if min(positive_numbers) != 0:
word = full_word if min(positive_numbers) == 1 else f"{full_word}s"
if where == "season":
where = "in this season"
elif where == "league":
where = "in career VTB"
string_value = f"{name} needs {min(positive_numbers)} {word} to reach {list_data[count-1]} {full_word}s {where}"
else:
string_value = ""
return {
"NameGFX": f"{name} ({num})",
"type": milestone_type.upper(),
"value": value,
"string_value": string_value,
}
else:
list_data = [*range(100, 5100, 100)]
if (int(value) % 100) >= 90 or (int(value) % 1000) in list_data:
diff = [l - int(value) for l in list_data]
positive_numbers = [num for num in diff if num > -1]
count = 0
for i in diff:
count += 1
if i == min(positive_numbers):
break
# print(positive_numbers)
full_word = [
word
for w, word in milestone_checks.items()
if w.lower() == milestone_type.lower()
][0]
# print(positive_numbers)
if min(positive_numbers) != 0:
word = full_word if min(positive_numbers) == 1 else f"{full_word}s"
if where == "season":
where = "in this season"
elif where == "league":
where = "in career VTB"
string_value = f"{name} needs {min(positive_numbers)} {word} to reach {list_data[count-1]} {full_word}s {where}"
else:
string_value = ""
return {
"NameGFX": f"{name} ({num})",
"type": milestone_type.upper(),
"value": value,
"string_value": string_value,
}
return None
def milestones(data):
new_data_season = []
new_data_career = []
for d in data:
if d["startRole"] == "Player":
milestone_checks = {
"PTS": d["TPoints"],
"AST": d["TAssist"],
"BLK": d["TBlocks"],
"REB": d["TRebound"],
"DREB": d["TDefRebound"],
"OREB": d["TOffRebound"],
"STL": d["TSteal"],
"GAMES": d["TGameCount"],
}
milestone_career_checks = {
"PTS": d["CareerTPoints"],
"AST": d["CareerTAssist"],
"BLK": d["CareerTBlocks"],
"REB": d["CareerTRebound"],
"DREB": d["CareerTDefRebound"],
"OREB": d["CareerTOffRebound"],
"STL": d["CareerTSteal"],
"GAMES": d["CareerTGameCount"],
}
for milestone_type, value in milestone_checks.items():
milestone_data = check_milestone(
value, milestone_type, d["NameGFX"], d["num"], "season"
)
if milestone_data:
new_data_season.append(milestone_data)
for milestone_type_car, value_car in milestone_career_checks.items():
milestone_data_car = check_milestone(
value_car, milestone_type_car, d["NameGFX"], d["num"], "league"
)
if milestone_data_car:
new_data_career.append(milestone_data_car)
return new_data_season, new_data_career
columns_game = [
"num",
# "roleShort",
"NameGFX",
"isOn",
# "flag",
"pts",
"pt-2",
"pt-3",
"pt-1",
"fg",
"ast",
"stl",
"blk",
"blkVic",
"dreb",
"oreb",
"reb",
"to",
"foul",
"fouled",
"plusMinus",
"dunk",
"kpi",
"time",
]
# print(cached_team1)
if cached_team1 and cached_team2:
team1_data = process_team_data(cached_team1, columns_game)
team2_data = process_team_data(cached_team2, columns_game)
# team1_data["pts"] = pd.to_numeric(team1_data["pts"], errors="coerce")
# team2_data["pts"] = pd.to_numeric(team2_data["pts"], errors="coerce")
# team1_data["ast"] = pd.to_numeric(team1_data["ast"], errors="coerce")
# team2_data["ast"] = pd.to_numeric(team2_data["ast"], errors="coerce")
# team1_data["stl"] = pd.to_numeric(team1_data["stl"], errors="coerce")
# team2_data["stl"] = pd.to_numeric(team2_data["stl"], errors="coerce")
# team1_data["blk"] = pd.to_numeric(team1_data["blk"], errors="coerce")
# team2_data["blk"] = pd.to_numeric(team2_data["blk"], errors="coerce")
# team1_data["blkVic"] = pd.to_numeric(team1_data["blkVic"], errors="coerce")
# team2_data["blkVic"] = pd.to_numeric(team2_data["blkVic"], errors="coerce")
# team1_data["dreb"] = pd.to_numeric(team1_data["dreb"], errors="coerce")
# team2_data["dreb"] = pd.to_numeric(team2_data["dreb"], errors="coerce")
# team1_data["oreb"] = pd.to_numeric(team1_data["oreb"], errors="coerce")
# team2_data["oreb"] = pd.to_numeric(team2_data["oreb"], errors="coerce")
# team1_data["reb"] = pd.to_numeric(team1_data["reb"], errors="coerce")
# team2_data["reb"] = pd.to_numeric(team2_data["reb"], errors="coerce")
# team1_data["to"] = pd.to_numeric(team1_data["to"], errors="coerce")
# team2_data["to"] = pd.to_numeric(team2_data["to"], errors="coerce")
# team1_data["foul"] = pd.to_numeric(team1_data["foul"], errors="coerce")
# team2_data["foul"] = pd.to_numeric(team2_data["foul"], errors="coerce")
# team1_data["fouled"] = pd.to_numeric(team1_data["fouled"], errors="coerce")
# team2_data["fouled"] = pd.to_numeric(team2_data["fouled"], errors="coerce")
# team1_data["plusMinus"] = pd.to_numeric(team1_data["plusMinus"], errors="coerce")
# team2_data["plusMinus"] = pd.to_numeric(team2_data["plusMinus"], errors="coerce")
# team1_data["dunk"] = pd.to_numeric(team1_data["dunk"], errors="coerce")
# team2_data["dunk"] = pd.to_numeric(team2_data["dunk"], errors="coerce")
# team1_data["kpi"] = pd.to_numeric(team1_data["kpi"], errors="coerce")
# team2_data["kpi"] = pd.to_numeric(team2_data["kpi"], errors="coerce")
# Стилизация данных
team1_styled = (
team1_data.style.apply(highlight_grey, axis=1)
.apply(highlight_foul, subset="foul")
.apply(highlight_max, subset="pts")
)
team2_styled = (
team2_data.style.apply(highlight_grey, axis=1)
.apply(highlight_foul, subset="foul")
.apply(highlight_max, subset="pts")
)
# Вывод данных
col_player1, col_player2 = tab_temp_1.columns((5, 5))
event1 = col_player1.dataframe(
team1_styled,
column_config=config,
hide_index=True,
height=460,
on_select="rerun",
selection_mode=[
"single-row",
],
)
event2 = col_player2.dataframe(
team2_styled,
column_config=config,
hide_index=True,
height=460,
on_select="rerun",
selection_mode=[
"single-row",
],
)
# if event1.selection["rows"]:
# player_index = event1.selection["rows"][0]
# selected_player_1 = process_player_data(cached_team1, player_index)
# col_player1.dataframe(
# selected_player_1,
# column_config=config_season,
# hide_index=True,
# )
# if event2.selection["rows"]:
# player_index = event2.selection["rows"][0]
# selected_player_2 = process_player_data(cached_team2, player_index)
# col_player2.dataframe(
# selected_player_2,
# column_config=config_season,
# hide_index=True,
# )
if event1.selection and event1.selection.get("rows"):
selected_index1 = event1.selection["rows"][0]
st.session_state["player1"] = (
selected_index1 # Сохранение состояния в session_state
)
if st.session_state["player1"] is not None:
selected_player_1, player_data_1 = process_player_data(
cached_team1, st.session_state["player1"]
)
if player_data_1["num"]:
z, a, b, c, d, e = col_player1.columns((1, 6, 1, 1, 1, 1))
z.metric("Номер", player_data_1["num"], border=False)
a.metric("Игрок", player_data_1["NameGFX"], border=False)
b.metric("Амплуа", player_data_1["roleShort"], border=False)
c.metric("Возраст", player_data_1["age"], border=False)
d.metric("Рост", player_data_1["height"].split()[0], border=False)
e.metric("Вес", player_data_1["weight"].split()[0], border=False)
col_player1.dataframe(
selected_player_1,
column_config=config_season,
hide_index=True,
)
if event2.selection and event2.selection.get("rows"):
selected_index2 = event2.selection["rows"][0]
st.session_state["player2"] = (
selected_index2 # Сохранение состояния в session_state
)
if st.session_state["player2"] is not None:
selected_player_2, player_data_2 = process_player_data(
cached_team2, st.session_state["player2"]
)
if player_data_2["num"]:
z, a, b, c, d, e = col_player2.columns((1, 6, 1, 1, 1, 1))
z.metric("Номер", player_data_2["num"], border=False)
a.metric("Игрок", player_data_2["NameGFX"], border=False)
b.metric("Амплуа", player_data_2["roleShort"], border=False)
c.metric("Возраст", player_data_2["age"], border=False)
d.metric("Рост", player_data_2["height"].split()[0], border=False)
e.metric("Вес", player_data_2["weight"].split()[0], border=False)
col_player2.dataframe(
selected_player_2,
column_config=config_season,
hide_index=True,
)
# if event2.selection and event2.selection.get("rows"):
# selected_index2 = event2.selection["rows"][0]
# st.session_state["player2"] = (
# selected_index2 # Сохранение состояния в session_state
# )
# selected_player_2, player_data_2 = process_player_data(
# cached_team2, selected_index2
# )
# st.session_state["player2_data"] = selected_player_2
# if st.session_state["player2_data"]:
# col_player2.dataframe(
# st.session_state["player2_data"],
# column_config=config_season,
# hide_index=True,
# )
# if cached_team_stats:
# cached_team_stats_new = [
# cached_team_stats[0],
# *cached_team_stats[25:29], # Распаковка элементов среза
# cached_team_stats[7],
# cached_team_stats[33],
# *cached_team_stats[9:11], # Распаковка элементов среза
# *cached_team_stats[15:17], # Распаковка элементов среза
# ]
# tab_temp_2.table(
# cached_team_stats_new,
# )
if isinstance(cached_team_stats, list) and len(cached_team_stats) >= 34:
cached_team_stats_new = [
cached_team_stats[0],
*cached_team_stats[25:29],
cached_team_stats[7],
cached_team_stats[33],
*cached_team_stats[9:11],
*cached_team_stats[15:17],
]
tab_temp_2.table(cached_team_stats_new)
if isinstance(cached_referee, (list, pd.DataFrame)):
tab_temp_3.dataframe(cached_referee, height=600, column_config={"flag": st.column_config.ImageColumn("flag")})
column_config_ref = {
"flag": st.column_config.ImageColumn(
"flag",
),
}
if cached_referee:
tab_temp_3.dataframe(cached_referee, height=600, column_config=column_config_ref)
def highlight_teams(s):
try:
if s.iloc[0] in (
cached_game_online["result"]["team1"]["teamId"],
cached_game_online["result"]["team2"]["teamId"],
):
return ["background-color: #FF4B4B"] * len(s)
else:
return [""] * len(s)
except NameError:
return [""] * len(s)
# if cached_standings:
# df_st = pd.json_normalize(cached_standings)
# cached_standings = df_st.style.apply(highlight_teams, axis=1)
# tab_temp_4.dataframe(
# cached_standings,
# column_config={
# "logo": st.column_config.ImageColumn(
# "logo",
# ),
# },
# hide_index=True,
# height=610,
# )
if cached_standings:
df_st = pd.json_normalize(cached_standings)
def highlight_teams(s):
try:
t1 = ((cached_game_online or {}).get("result") or {}).get("team1", {}).get("teamId")
t2 = ((cached_game_online or {}).get("result") or {}).get("team2", {}).get("teamId")
if s.iloc[0] in (t1, t2):
return ["background-color: #FF4B4B"] * len(s)
except Exception:
pass
return [""] * len(s)
styled = df_st.style.apply(highlight_teams, axis=1)
tab_temp_4.dataframe(
styled,
column_config={"logo": st.column_config.ImageColumn("logo")},
hide_index=True,
height=610,
)
# if cached_scores_quarter:
# column_config = {}
# for quarter in ["Q1", "Q2", "Q3", "Q4", "OT1", "OT2", "OT3", "OT4"]:
# column_name = f"score_avg{quarter}"
# column_config[column_name] = st.column_config.NumberColumn(
# column_name, format="%.1f"
# )
# columns_quarters_name = ["Q1", "Q2", "Q3", "Q4"]
# columns_quarters_name_ot = ["OT1", "OT2", "OT3", "OT4"]
# columns_quarters = tab_temp_5.columns((1, 1, 1, 1))
# for index, col in enumerate(columns_quarters):
# df_col = [
# {
# "team": cached_scores_quarter[0]["team"],
# "W": cached_scores_quarter[0][f"win{columns_quarters_name[index]}"],
# "L": cached_scores_quarter[0][f"lose{columns_quarters_name[index]}"],
# "D": cached_scores_quarter[0][f"draw{columns_quarters_name[index]}"],
# "PTS": cached_scores_quarter[0][f"score{columns_quarters_name[index]}"],
# "AVG": cached_scores_quarter[0][
# f"score_avg{columns_quarters_name[index]}"
# ],
# },
# {
# "team": cached_scores_quarter[1]["team"],
# "W": cached_scores_quarter[1][f"win{columns_quarters_name[index]}"],
# "L": cached_scores_quarter[1][f"lose{columns_quarters_name[index]}"],
# "D": cached_scores_quarter[1][f"draw{columns_quarters_name[index]}"],
# "PTS": cached_scores_quarter[1][f"score{columns_quarters_name[index]}"],
# "AVG": cached_scores_quarter[1][
# f"score_avg{columns_quarters_name[index]}"
# ],
# },
# ]
# col.write(columns_quarters_name[index])
# col.dataframe(df_col)
# for index, col in enumerate(columns_quarters):
# df_col = [
# {
# "team": cached_scores_quarter[0]["team"],
# "W": cached_scores_quarter[0][f"win{columns_quarters_name_ot[index]}"],
# "L": cached_scores_quarter[0][f"lose{columns_quarters_name_ot[index]}"],
# "D": cached_scores_quarter[0][f"draw{columns_quarters_name_ot[index]}"],
# "PTS": cached_scores_quarter[0][
# f"score{columns_quarters_name_ot[index]}"
# ],
# "AVG": cached_scores_quarter[0][
# f"score_avg{columns_quarters_name_ot[index]}"
# ],
# },
# {
# "team": cached_scores_quarter[1]["team"],
# "W": cached_scores_quarter[1][f"win{columns_quarters_name_ot[index]}"],
# "L": cached_scores_quarter[1][f"lose{columns_quarters_name_ot[index]}"],
# "D": cached_scores_quarter[1][f"draw{columns_quarters_name_ot[index]}"],
# "PTS": cached_scores_quarter[1][
# f"score{columns_quarters_name_ot[index]}"
# ],
# "AVG": cached_scores_quarter[1][
# f"score_avg{columns_quarters_name_ot[index]}"
# ],
# },
# ]
# col.write(columns_quarters_name_ot[index])
# col.dataframe(df_col)
if isinstance(cached_scores_quarter, list) and len(cached_scores_quarter) >= 2:
column_config = {}
for quarter in ["Q1", "Q2", "Q3", "Q4", "OT1", "OT2", "OT3", "OT4"]:
column_name = f"score_avg{quarter}"
column_config[column_name] = st.column_config.NumberColumn(column_name, format="%.1f")
columns_quarters_name = ["Q1", "Q2", "Q3", "Q4"]
columns_quarters_name_ot = ["OT1", "OT2", "OT3", "OT4"]
columns_quarters = tab_temp_5.columns((1, 1, 1, 1))
# Основные четверти
for index, col in enumerate(columns_quarters):
q = columns_quarters_name[index]
df_col = [
{
"team": cached_scores_quarter[0].get("team"),
"W": cached_scores_quarter[0].get(f"win{q}"),
"L": cached_scores_quarter[0].get(f"lose{q}"),
"D": cached_scores_quarter[0].get(f"draw{q}"),
"PTS": cached_scores_quarter[0].get(f"score{q}"),
"AVG": cached_scores_quarter[0].get(f"score_avg{q}"),
},
{
"team": cached_scores_quarter[1].get("team"),
"W": cached_scores_quarter[1].get(f"win{q}"),
"L": cached_scores_quarter[1].get(f"lose{q}"),
"D": cached_scores_quarter[1].get(f"draw{q}"),
"PTS": cached_scores_quarter[1].get(f"score{q}"),
"AVG": cached_scores_quarter[1].get(f"score_avg{q}"),
},
]
col.write(q)
col.dataframe(df_col)
# Овертаймы
for index, col in enumerate(columns_quarters):
q = columns_quarters_name_ot[index]
df_col = [
{
"team": cached_scores_quarter[0].get("team"),
"W": cached_scores_quarter[0].get(f"win{q}"),
"L": cached_scores_quarter[0].get(f"lose{q}"),
"D": cached_scores_quarter[0].get(f"draw{q}"),
"PTS": cached_scores_quarter[0].get(f"score{q}"),
"AVG": cached_scores_quarter[0].get(f"score_avg{q}"),
},
{
"team": cached_scores_quarter[1].get("team"),
"W": cached_scores_quarter[1].get(f"win{q}"),
"L": cached_scores_quarter[1].get(f"lose{q}"),
"D": cached_scores_quarter[1].get(f"draw{q}"),
"PTS": cached_scores_quarter[1].get(f"score{q}"),
"AVG": cached_scores_quarter[1].get(f"score_avg{q}"),
},
]
col.write(q)
col.dataframe(df_col)
# if cached_play_by_play and isinstance(cached_game_online, dict):
# plays = cached_game_online.get("result", {}).get("plays")
# if plays:
# tab_temp_6.table(cached_play_by_play)
if isinstance(cached_play_by_play, list) and isinstance(cached_game_online, dict):
plays = (cached_game_online.get("result") or {}).get("plays") or []
if plays:
tab_temp_6.table(cached_play_by_play)
# print(cached_game_online["result"]["plays"])
# if cached_game_online and cached_game_online["result"]["plays"]:
# columns_quarter = tab_temp_7.tabs(count_quarter)
# columns_quarter_for_st = [
# "num",
# "NameGFX",
# "q_pts",
# "q_pt2",
# "q_pt3",
# "q_ft",
# "q_pt23",
# "q_ast",
# "q_stl",
# "q_blk",
# "q_reb",
# "q_to",
# "q_f",
# "q_f_on",
# "q_rnk",
# "q_time",
# ]
# for i in range(period_max):
# col_quarter1, col_quarter2 = columns_quarter[i].columns((5, 5))
# key_quarter_team1 = f"team1_{i+1}"
# load_data_from_json(key_quarter_team1)
# key_quarter_team1 = st.session_state[key_quarter_team1]
# # print(key_quarter_team1)
# df_team1 = pd.DataFrame(key_quarter_team1)
# count_players_1 = len(df_team1)
# col_quarter1.dataframe(
# df_team1[columns_quarter_for_st].style.apply(highlight_max, subset="q_pts"),
# column_config=config,
# hide_index=True,
# height=38 * count_players_1 if count_players_1 > 10 else None,
# )
# key_quarter_team2 = f"team2_{i+1}"
# load_data_from_json(key_quarter_team2)
# key_quarter_team2 = st.session_state[key_quarter_team2]
# df_team2 = pd.DataFrame(key_quarter_team2)
# count_players_2 = len(df_team2)
# col_quarter2.dataframe(
# df_team2[columns_quarter_for_st].style.apply(highlight_max, subset="q_pts"),
# column_config=config,
# hide_index=True,
# height=38 * count_players_2 if count_players_2 > 10 else None,
# )
# if cached_team1 and cached_team2:
# data_team_season_1, data_team_career_1 = milestones(cached_team1)
# data_team_season_2, data_team_career_2 = milestones(cached_team2)
# tab7_col1, tab7_col2 = tab_temp_8.columns((5, 5))
# tab7_col1.dataframe(data_team_season_1)
# tab7_col2.dataframe(data_team_season_2)
# tab7_col1.dataframe(data_team_career_1)
# tab7_col2.dataframe(data_team_career_2)
def schedule_selected_team(team_id, data, game_id, selected, away_team_id):
columns = [
"game.localDate",
"team1.name",
"team1.logo",
"game.score",
"team2.logo",
"team2.name",
"game.fullScore",
"win",
]
df_schedule_new = data.loc[
# (data["game.id"] < game_id)
# &
(
(data["team1.teamId"].isin([team_id]))
| (data["team2.teamId"].isin([team_id]))
)
]
df_schedule_new.loc[:, "game.fullScore"] = df_schedule_new[
"game.fullScore"
].str.split(",")
conditions = [
(df_schedule_new["team1.teamId"] == team_id)
& (df_schedule_new["game.score1"] > df_schedule_new["game.score2"]),
(df_schedule_new["team1.teamId"] == team_id)
& (df_schedule_new["game.score1"] < df_schedule_new["game.score2"]),
(df_schedule_new["team2.teamId"] == team_id)
& (df_schedule_new["game.score2"] > df_schedule_new["game.score1"]),
(df_schedule_new["team2.teamId"] == team_id)
& (df_schedule_new["game.score2"] < df_schedule_new["game.score1"]),
]
values = [True, False, True, False]
df_schedule_new = df_schedule_new.copy()
df_schedule_new.loc[:, "win"] = np.select(conditions, values, default=None)
mask = pd.Series(True, index=df_schedule_new.index)
# Проверяем каждое выбранное условие и объединяем с маской
if selected:
if "Дома" in selected:
mask &= df_schedule_new["team1.teamId"] == team_id
if "В гостях" in selected:
mask &= df_schedule_new["team2.teamId"] == team_id
if "Выигрыши" in selected:
mask &= df_schedule_new["win"] == True
if "Поражения" in selected:
mask &= df_schedule_new["win"] == False
if "Друг с другом" in selected:
mask &= df_schedule_new["team1.teamId"].isin(
[away_team_id, team_id]
) & df_schedule_new["team2.teamId"].isin([away_team_id, team_id])
# print(selected)
return df_schedule_new[columns].loc[mask]
def get_in(d, path, default=None):
cur = d
for key in path:
if not isinstance(cur, dict):
return default
cur = cur.get(key, default)
if cur is default:
return default
return cur
if tab_schedule:
if cached_schedule and "items" in cached_schedule:
cached_schedule = cached_schedule["items"]
pd_schedule = pd.json_normalize(cached_schedule)
# team1_id = st.session_state["game_online"]["result"]["team1"]["teamId"]
# team1_name = st.session_state["game_online"]["result"]["team1"]["name"]
# team2_id = st.session_state["game_online"]["result"]["team2"]["teamId"]
# team2_name = st.session_state["game_online"]["result"]["team2"]["name"]
# game_id = st.session_state["game_online"]["result"]["game"]["id"]
game_online = st.session_state.get("game_online")
team1_id = get_in(game_online, ["result", "team1", "teamId"])
team1_name = get_in(game_online, ["result", "team1", "name"])
team2_id = get_in(game_online, ["result", "team2", "teamId"])
team2_name = get_in(game_online, ["result", "team2", "name"])
game_id = get_in(game_online, ["result", "game", "id"])
col1_schedule, col2_schedule = tab_schedule.columns((5, 5))
options = ["Дома", "В гостях", "Выигрыши", "Поражения", "Друг с другом"]
selection1 = col1_schedule.segmented_control(
"Фильтр", options, selection_mode="multi", key="1"
)
selection2 = col2_schedule.segmented_control(
"Фильтр", options, selection_mode="multi", key="2"
)
team1_data = schedule_selected_team(
team1_id, pd_schedule, game_id, selection1, team2_id
)
team2_data = schedule_selected_team(
team2_id, pd_schedule, game_id, selection2, team1_id
)
def highlight_two_teams(s):
try:
if str(s.loc["team1.name"]) in (
team1_name,
team2_name,
) and str(s.loc["team2.name"]) in (
team1_name,
team2_name,
):
return ["background-color: #FF4B4B"] * len(s)
else:
return [""] * len(s)
except NameError:
return [""] * len(s)
column_config = {
"team1.name": st.column_config.TextColumn("Команда1", width=150),
"team2.name": st.column_config.TextColumn("Команда2", width=150),
"game.score": st.column_config.TextColumn(
"Счёт",
),
"game.localDate": st.column_config.TextColumn(
"Дата",
),
"game.fullScore": st.column_config.Column(
"Счёт по четвертям",
),
"team1.logo": st.column_config.ImageColumn("Лого1", width=50),
"team2.logo": st.column_config.ImageColumn("Лого2", width=50),
}
count_game_1 = len(team1_data)
count_game_2 = len(team2_data)
team1_data = team1_data.style.apply(highlight_two_teams, axis=1).apply(
color_win, subset="win"
)
team2_data = team2_data.style.apply(highlight_two_teams, axis=1).apply(
color_win, subset="win"
)
height1 = 38 * max(count_game_1, 10)
height2 = 38 * max(count_game_2, 10)
col1_schedule.dataframe(
team1_data,
hide_index=True,
height=int(min(height1, 1200)),
column_config=column_config,
)
col2_schedule.dataframe(
team2_data,
hide_index=True,
height=int(min(height2, 1200)),
column_config=column_config,
)
# with open("PlayTypeID.json", "r", encoding="utf-8") as f:
# play_type_id = json.load(f)
# # print(play_type_id)
# teams_data = cached_game_online["result"]["teams"]
# teams_temp = sorted(
# teams_data[1]["starts"], key=lambda x: x["playerNumber"], reverse=False
# ) + sorted(teams_data[2]["starts"], key=lambda x: x["playerNumber"], reverse=False)
# # print(teams_temp)
# list_fullname = [None] + [
# f"({x['displayNumber']}) {x['firstName']} {x['lastName']}"
# for x in teams_temp
# if x["startRole"] == "Player"
# ]
def get_play_info(play):
# Ищем в списке play_type_id элемент, у которого PlayTypeID совпадает с play
for item in play_type_id:
if item["PlayTypeID"] == play:
return item["PlayInfoSite"]
return None # Если совпадение не найдено
def get_player_name(start_num):
# Ищем в списке teams_temp элемент, у которого startNum совпадает с temp_data_pbp["startNum"]
for player in teams_temp:
if player["startNum"] == start_num:
return f"{player['firstName']} {player['lastName']}"
return None # Если совпадение не найдено
def get_event_time(row):
if row != 0:
time_str = 6000 - row
if time_str == 0:
time_str = "0:00"
else:
time_str = time_str // 10
time_str = f"{time_str // 60}:{str(time_str % 60).zfill(2)}"
return time_str
# with tab_pbp:
# temp_data_pbp = pd.DataFrame(cached_game_online["result"]["plays"])
# col1_pbp, col2_pbp = tab_pbp.columns((3, 4))
# option_player = col1_pbp.selectbox(
# "Выбрать игрока",
# list_fullname,
# )
# options_pbp = ["1 очко", "2 очка", "3 очка"]
# selection_pbp = col1_pbp.segmented_control(
# "Фильтр", options_pbp, selection_mode="multi", key=3
# )
# if not temp_data_pbp.empty:
# options_quarter = [
# (f"{i+1} четверть" if i + 1 < 5 else f"{i-3} овертайм")
# for i in range(max(temp_data_pbp["period"]))
# ]
# selection_quarter = col1_pbp.segmented_control(
# "Выбор четверти", options_quarter, selection_mode="multi", key=4
# )
# temp_data_pbp["info"] = temp_data_pbp["play"].map(get_play_info)
# temp_data_pbp["who"] = temp_data_pbp["startNum"].map(get_player_name)
# temp_data_pbp["time"] = temp_data_pbp["sec"].map(get_event_time)
# # Инициализируем маску фильтрации (все строки по умолчанию)
# mask1 = pd.Series(True, index=temp_data_pbp.index)
# if option_player:
# start_number = [
# x["startNum"]
# for x in teams_temp
# if f"({x['displayNumber']}) {x['firstName']} {x['lastName']}"
# == option_player
# ][0]
# mask1 &= temp_data_pbp["startNum"] == start_number
# # Фильтрация по типу очков
# if selection_pbp:
# plays_mapping = {"1 очко": 1, "2 очка": 2, "3 очка": 3}
# selected_plays = [plays_mapping[play] for play in selection_pbp]
# mask1 &= temp_data_pbp["play"].isin(selected_plays)
# # Фильтрация по четверти
# if selection_quarter:
# select_quart = [
# index + 1
# for index, quarter in enumerate(options_quarter)
# if quarter in selection_quarter
# ]
# mask1 &= temp_data_pbp["period"].isin(select_quart)
# # Применяем маску фильтрации
# filtered_data_pbp = temp_data_pbp[mask1]
# count_pbp = len(filtered_data_pbp)
# column_pbp = [
# "num",
# "info",
# "who",
# "period",
# "time",
# ]
# column_config_pbp = {
# "info": st.column_config.TextColumn(width="medium"),
# "who": st.column_config.TextColumn(width="large"),
# }
# col2_pbp.dataframe(
# filtered_data_pbp[column_pbp],
# column_config=column_config_pbp,
# hide_index=True,
# height=(38 * count_pbp if count_pbp > 10 else None),
# )
# Безопасная загрузка PlayTypeID
try:
with open("PlayTypeID.json", "r", encoding="utf-8") as f:
play_type_id = json.load(f)
except (FileNotFoundError, json.JSONDecodeError):
play_type_id = []
# Безопасное получение команд и игроков
# teams_section = ((cached_game_online or {}).get("result") or {}).get("teams") or {}
# starts1 = (teams_section.get(1) or {}).get("starts") or []
# starts2 = (teams_section.get(2) or {}).get("starts") or []
teams_section = ((cached_game_online or {}).get("result") or {}).get("teams") or {}
# Если teams_section — список (например, [{"starts": [...]}, {...}])
if isinstance(teams_section, list):
if len(teams_section) >= 2:
starts1 = (teams_section[0] or {}).get("starts") or []
starts2 = (teams_section[1] or {}).get("starts") or []
elif len(teams_section) == 1:
starts1 = (teams_section[0] or {}).get("starts") or []
starts2 = []
else:
starts1 = []
starts2 = []
# Если teams_section — словарь (обычно {"1": {...}, "2": {...}})
elif isinstance(teams_section, dict):
starts1 = (teams_section.get(1) or teams_section.get("1") or {}).get("starts") or []
starts2 = (teams_section.get(2) or teams_section.get("2") or {}).get("starts") or []
else:
starts1 = []
starts2 = []
teams_temp = sorted([x for x in starts1 if isinstance(x, dict)], key=lambda x: x.get("playerNumber", 0)) \
+ sorted([x for x in starts2 if isinstance(x, dict)], key=lambda x: x.get("playerNumber", 0))
list_fullname = [None] + [
f"({x.get('displayNumber')}) {x.get('firstName','')} {x.get('lastName','')}".strip()
for x in teams_temp
if x.get("startRole") == "Player"
]
def get_play_info(play):
for item in play_type_id:
if isinstance(item, dict) and item.get("PlayTypeID") == play:
return item.get("PlayInfoSite")
return None
def get_player_name(start_num):
for player in teams_temp:
if player.get("startNum") == start_num:
return f"{player.get('firstName','')} {player.get('lastName','')}".strip()
return None
def get_event_time(row):
if isinstance(row, (int, float)) and row != 0:
time_val = 6000 - int(row)
if time_val <= 0:
return "0:00"
time_val //= 10
return f"{time_val // 60}:{str(time_val % 60).zfill(2)}"
return None
with tab_pbp:
plays = ((cached_game_online or {}).get("result") or {}).get("plays") or []
if plays:
temp_data_pbp = pd.DataFrame(plays)
col1_pbp, col2_pbp = tab_pbp.columns((3, 4))
option_player = col1_pbp.selectbox("Выбрать игрока", list_fullname)
options_pbp = ["1 очко", "2 очка", "3 очка"]
selection_pbp = col1_pbp.segmented_control("Фильтр", options_pbp, selection_mode="multi", key=3)
if not temp_data_pbp.empty and "period" in temp_data_pbp.columns:
options_quarter = [
(f"{i+1} четверть" if i + 1 < 5 else f"{i-3} овертайм")
for i in range(int(temp_data_pbp["period"].max()))
]
selection_quarter = col1_pbp.segmented_control("Выбор четверти", options_quarter, selection_mode="multi", key=4)
temp_data_pbp["info"] = temp_data_pbp["play"].map(get_play_info)
temp_data_pbp["who"] = temp_data_pbp["startNum"].map(get_player_name)
temp_data_pbp["time"] = temp_data_pbp["sec"].map(get_event_time)
mask1 = pd.Series(True, index=temp_data_pbp.index)
if option_player:
# безопасный поиск startNum
for x in teams_temp:
display = f"({x.get('displayNumber')}) {x.get('firstName','')} {x.get('lastName','')}".strip()
if display == option_player:
mask1 &= temp_data_pbp["startNum"] == x.get("startNum")
break
if selection_pbp:
plays_mapping = {"1 очко": 1, "2 очка": 2, "3 очка": 3}
selected_plays = [plays_mapping[p] for p in selection_pbp if p in plays_mapping]
mask1 &= temp_data_pbp["play"].isin(selected_plays)
if selection_quarter:
select_quart = [i+1 for i, q in enumerate(options_quarter) if q in selection_quarter]
mask1 &= temp_data_pbp["period"].isin(select_quart)
filtered_data_pbp = temp_data_pbp[mask1]
count_pbp = len(filtered_data_pbp)
column_pbp = ["num", "info", "who", "period", "time"]
column_config_pbp = {
"info": st.column_config.TextColumn(width="medium"),
"who": st.column_config.TextColumn(width="large"),
}
col2_pbp.dataframe(
filtered_data_pbp[column_pbp],
column_config=column_config_pbp,
hide_index=True,
height=(38 * count_pbp if count_pbp > 10 else None),
)
else:
st.info("Данных play-by-play нет.")