Merge remote-tracking branch 'origin/main' into Barabanov_TEST

This commit is contained in:
2025-10-22 10:49:11 +00:00
7 changed files with 5162 additions and 11786 deletions

3165
get_data.py Normal file

File diff suppressed because it is too large Load Diff

13
match_id.json Normal file
View File

@@ -0,0 +1,13 @@
{
"10.0.85.2111": {"host": "", "tag": "vtb", "root": 1, "team": ""},
"10.10.35.21": {"host": "gfx", "tag": "vtb", "root": 1, "team": "Lokomotiv Kuban"},
"10.10.35.22": {"host": "krd", "tag": "vtb", "root": 1, "team": "Lokomotiv Kuban1"},
"10.10.35.23": {"host": "ekb", "tag": "vtb", "root": 1, "team": "uralmash1"},
"10.10.35.24": {"host": "per", "tag": "vtb", "root": 1, "team": "betcity parma1"},
"10.10.35.25": {"host": "sar", "tag": "vtb", "root": 1, "team": "avtodor1"},
"10.10.35.26": {"host": "spb", "tag": "vtb", "root": 1, "team": "zenit1"},
"10.10.35.27": {"host": "sam", "tag": "vtb", "root": 1, "team": "samara1"},
"10.10.35.28": {"host": "msk1", "tag": "vtb", "root": 1, "team": "mba-mai1"},
"10.10.35.29": {"host": "msk2", "tag": "vtb", "root": 1, "team": "Pari Nizhny Novgorod1"},
"10.10.35.30": {"host": "kaz", "tag": "vtb", "root": 1, "team": "unics1"}
}

View File

@@ -1,97 +0,0 @@
Dim url As String = "https://ekb.tvstart.ru/app/static/ekb_team1.json"
Dim json As String = ""
' Чтение URL
Try
Dim wc As New System.Net.WebClient
wc.Encoding = System.Text.Encoding.UTF8
json = wc.DownloadString(url)
Catch ex As Exception
Console.WriteLine("Ошибка загрузки JSON: " & ex.Message)
Return
End Try
' --- Парсинг первых 12 num + NameGFX ---
Dim nums(11) As String
Dim names(11) As String
Dim count As Integer = 0
Dim pos As Integer = 0
While count < 12
' ищем "num"
Dim k As Integer = json.IndexOf("""num""", pos)
If k = -1 Then Exit While
Dim c As Integer = json.IndexOf(":", k)
If c = -1 Then Exit While
Dim j As Integer = c + 1
While j < json.Length AndAlso Char.IsWhiteSpace(json(j))
j += 1
End While
Dim numVal As String = ""
If j < json.Length AndAlso json(j) = """"c Then
j += 1
Dim startQ As Integer = j
While j < json.Length AndAlso json(j) <> """"c
j += 1
End While
numVal = json.Substring(startQ, j - startQ)
j += 1
Else
Dim startN As Integer = j
While j < json.Length AndAlso (Char.IsDigit(json(j)) OrElse json(j) = "-"c OrElse json(j) = "."c)
j += 1
End While
numVal = json.Substring(startN, j - startN)
End If
' ищем "NameGFX"
pos = j
Dim kn As Integer = json.IndexOf("""NameGFX""", pos)
If kn = -1 Then Exit While
Dim cn As Integer = json.IndexOf(":", kn)
If cn = -1 Then Exit While
Dim jn As Integer = cn + 1
While jn < json.Length AndAlso Char.IsWhiteSpace(json(jn))
jn += 1
End While
Dim nameVal As String = ""
If jn < json.Length AndAlso json(jn) = """"c Then
jn += 1
Dim startGN As Integer = jn
While jn < json.Length AndAlso json(jn) <> """"c
jn += 1
End While
nameVal = json.Substring(startGN, jn - startGN)
jn += 1
End If
nums(count) = numVal
names(count) = nameVal
count += 1
pos = jn
End While
' --- Выводим результат ---
Console.WriteLine("=== Первые " & count.ToString() & " игроков ===")
For i As Integer = 0 To count - 1
Console.WriteLine(nums(i) & "_" & names(i))
Next
' --- Выводим результат ---
Console.WriteLine("=== Первые " & count.ToString() & " игроков ===")
For i As Integer = 0 To count - 1
Console.WriteLine(nums(i) & "_" & names(i))
' === Отправляем в титр TeamRoster.gtzip ===
' Номер
API.Function("SetText", Input:="TeamRoster.gtzip", SelectedName:="PlayerNamber" & (i + 1).ToString() & ".Text", Value:=nums(i))
' Имя
API.Function("SetText", Input:="TeamRoster.gtzip", SelectedName:="PlayerName" & (i + 1).ToString() & ".Text", Value:=names(i))
Next

View File

@@ -1,16 +0,0 @@
import requests
import json
url = "https://org.infobasket.su/Widget/GetOnline/921412?format=json&lang=ru"
response = requests.get(url)
response.raise_for_status()
data = response.json()
# print(data)
team1 = data["GameTeams"][0]
team2 = data["GameTeams"][1]
print(team1)

11252
temp.json

File diff suppressed because it is too large Load Diff

1984
visual.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,421 +0,0 @@
*** visual.py 2025-01-22 00:00:00.000000000 +0000
--- visual.py 2025-10-07 00:00:00.000000000 +0000
***************
*** 1,10 ****
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",
--- 1,10 ----
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",
***************
*** 164,169 ****
--- 164,216 ----
def ensure_state(key: str, default=None):
# Инициализирует ключ один раз и возвращает значение
return st.session_state.setdefault(key, default)
+
+ # ======== UNIVERSAL SAFE RENDER WRAPPER ========
+ def _is_empty_like(x) -> bool:
+ if x is None:
+ return True
+ # DataFrame
+ if isinstance(x, pd.DataFrame):
+ return x.empty
+ # Pandas Styler
+ try:
+ # импортируем лениво, чтобы не ломаться, если нет pandas.io.formats.style в рантайме
+ from pandas.io.formats.style import Styler # type: ignore
+ if isinstance(x, Styler):
+ # у Styler нет __len__, но есть .data
+ return getattr(x, "data", pd.DataFrame()).empty
+ except Exception:
+ pass
+ # пустые коллекции
+ if isinstance(x, (list, tuple, dict, set)):
+ return len(x) == 0
+ return False
+
+ def safe_show(func, *args, **kwargs):
+ """
+ Безопасно вызывает функции отображения Streamlit (dataframe, table, metric, image, markdown, ...).
+ - Ничего не рендерит, если основной аргумент данных пуст/None.
+ - Нормализует height (убирает None, <0; приводит к int).
+ - Возвращает результат вызова func (нужно для dataframe-selection).
+ - Перехватывает исключения и показывает предупреждение.
+ """
+ # Если среди позиционных/именованных аргументов есть пустые/None-данные — не показываем
+ for a in args:
+ if _is_empty_like(a):
+ return None
+ for k, v in kwargs.items():
+ # пропускаем не-данные параметры (типа width/unsafe_allow_html)
+ if k.lower() in ("height", "width", "use_container_width", "unsafe_allow_html", "on_select", "selection_mode", "column_config", "hide_index", "border", "delta_color", "key"):
+ continue
+ if _is_empty_like(v):
+ return None
+
+ # height -> валидный int, иначе уберём
+ if "height" in kwargs:
+ h = kwargs.get("height")
+ if h is None:
+ kwargs.pop("height")
+ else:
+ try:
+ h = int(h)
+ if h < 0:
+ kwargs.pop("height")
+ else:
+ kwargs["height"] = h
+ except Exception:
+ kwargs.pop("height")
+
+ try:
+ return func(*args, **kwargs)
+ except Exception as e:
+ st.warning(f"⚠️ Ошибка при отображении: {e}")
+ return None
+ # ======== /SAFE WRAPPER ========
+
***************
*** 221,231 ****
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"<h2 style='text-align: center'>{team1_name} — {team2_name}</h2>",
- unsafe_allow_html=True,
- )
- if t2.get("logo"):
- col3.image(t2["logo"], width=100)
+ safe_show(col1.image, t1.get("logo"), width=100)
+ if team1_name or team2_name:
+ safe_show(
+ col2.markdown,
+ f"<h2 style='text-align: center'>{team1_name} — {team2_name}</h2>",
+ unsafe_allow_html=True,
+ )
+ safe_show(col3.image, t2.get("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))
***************
*** 237,253 ****
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)
+ safe_show(col4_1.metric, "Points", v1, val1 - val2, delta_color_1)
+ safe_show(col5_3.metric, "Points", v2, val2 - val1, delta_color_1)
- col4_3.metric("TimeOuts", len(timeout1))
- col5_1.metric("TimeOuts", len(timeout2))
+ safe_show(col4_3.metric, "TimeOuts", len(timeout1))
+ safe_show(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)
+ safe_show(col4_2.metric, "Fouls", foulsA)
if foulsB is not None:
- col5_2.metric("Fouls", foulsB)
+ safe_show(col5_2.metric, "Fouls", foulsB)
***************
*** 270,280 ****
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)
+ safe_show(col1_i.metric, name_q, q1, int(q1) - int(q2), delta_color, border=True)
+ safe_show(col2_i.metric, name_q, q2, int(q2) - int(q1), delta_color, border=True)
except (ValueError, TypeError):
# если кривые данные в JSON, просто пропустим
pass
***************
*** 403,424 ****
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",
- ],
- )
+ event1 = safe_show(
+ col_player1.dataframe,
+ team1_styled,
+ column_config=config,
+ hide_index=True,
+ height=460,
+ on_select="rerun",
+ selection_mode=["single-row"],
+ )
+ event2 = safe_show(
+ col_player2.dataframe,
+ team2_styled,
+ column_config=config,
+ hide_index=True,
+ height=460,
+ on_select="rerun",
+ selection_mode=["single-row"],
+ )
if event1 and getattr(event1, "selection", None) and event1.selection.get("rows"):
selected_index1 = event1.selection["rows"][0]
st.session_state["player1"] = (
selected_index1 # Сохранение состояния в session_state
***************
*** 433,441 ****
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,
- )
+ safe_show(z.metric, "Номер", player_data_1["num"], border=False)
+ safe_show(a.metric, "Игрок", player_data_1["NameGFX"], border=False)
+ safe_show(b.metric, "Амплуа", player_data_1["roleShort"], border=False)
+ safe_show(c.metric, "Возраст", player_data_1["age"], border=False)
+ safe_show(d.metric, "Рост", player_data_1["height"].split()[0], border=False)
+ safe_show(e.metric, "Вес", player_data_1["weight"].split()[0], border=False)
+
+ safe_show(
+ col_player1.dataframe,
+ selected_player_1,
+ column_config=config_season,
+ hide_index=True,
+ )
***************
*** 446,454 ****
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,
- )
+ safe_show(z.metric, "Номер", player_data_2["num"], border=False)
+ safe_show(a.metric, "Игрок", player_data_2["NameGFX"], border=False)
+ safe_show(b.metric, "Амплуа", player_data_2["roleShort"], border=False)
+ safe_show(c.metric, "Возраст", player_data_2["age"], border=False)
+ safe_show(d.metric, "Рост", player_data_2["height"].split()[0], border=False)
+ safe_show(e.metric, "Вес", player_data_2["weight"].split()[0], border=False)
+
+ safe_show(
+ col_player2.dataframe,
+ selected_player_2,
+ column_config=config_season,
+ hide_index=True,
+ )
***************
*** 459,468 ****
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)
+ safe_show(tab_temp_2.table, cached_team_stats_new)
***************
*** 470,484 ****
- 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)
+ safe_show(tab_temp_3.dataframe, cached_referee, height=600, column_config=column_config_ref)
***************
*** 503,511 ****
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,
- )
+ safe_show(
+ tab_temp_4.dataframe,
+ styled,
+ column_config={"logo": st.column_config.ImageColumn("logo")},
+ hide_index=True,
+ height=610,
+ )
***************
*** 552,558 ****
]
col.write(q)
- col.dataframe(df_col)
+ safe_show(col.dataframe, df_col)
# Овертаймы
for index, col in enumerate(columns_quarters):
q = columns_quarters_name_ot[index]
df_col = [
--- 564,570 ----
***************
*** 572,578 ****
]
col.write(q)
- col.dataframe(df_col)
+ safe_show(col.dataframe, df_col)
***************
*** 582,586 ****
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)
+ safe_show(tab_temp_6.table, cached_play_by_play)
***************
*** 703,724 ****
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,
- )
+ safe_show(
+ col1_schedule.dataframe,
+ team1_data,
+ hide_index=True,
+ height=int(min(height1, 1200)),
+ column_config=column_config,
+ )
+ safe_show(
+ col2_schedule.dataframe,
+ team2_data,
+ hide_index=True,
+ height=int(min(height2, 1200)),
+ column_config=column_config,
+ )
***************
*** 836,845 ****
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),
- )
+ safe_show(
+ 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 нет.")