diff --git a/get_data.py b/get_data.py new file mode 100644 index 0000000..379a1bb --- /dev/null +++ b/get_data.py @@ -0,0 +1,3165 @@ +from __future__ import annotations +import os +import sys +import json +import time +import socket +import urllib3 +import logging +import logging.config +import argparse +import platform +import requests +import threading +import numpy as np +import pandas as pd +from threading import Event, Lock +from concurrent.futures import ThreadPoolExecutor, as_completed +from typing import List, Dict, Any +from datetime import datetime, timedelta, timezone +from ipaddress import ip_address as _ip_parse +import errno + +urllib3.disable_warnings() + + +# === Настройки и логгер === +myhost = platform.node() +VERSION = "v.2.1 от 08.10.2025" +TAGS = [ + {"tag": "vtb", "name": "Единая Лига ВТБ", "lang": "en"}, + {"tag": "vtbyouth", "name": "Молодежка ВТБ", "lang": ""}, + {"tag": "rfb-deti", "name": "Дети", "lang": ""}, + {"tag": "rfb-silent", "name": "Тихий!баскетбол", "lang": ""}, + {"tag": "orgRoot", "name": "Все соревнования", "lang": ""}, + {"tag": "vtb-supercup", "name": "Супер-Кубок ЕЛ ВТБ", "lang": ""}, + {"tag": "uba-leto", "name": "UBA лето", "lang": "ru"}, + {"tag": "phygital-russia-cup-m", "name": "Фиджитал кубок", "lang": "ru"}, + {"tag": "phygital", "name": "Фиджитал", "lang": "ru"}, + {"tag": "3x3Root", "name": "3х3", "lang": "ru"}, + {"tag": "LS3x3", "name": "Лига Сильных 3х3", "lang": "ru"}, + {"tag": "uba", "name": "ЮБА", "lang": "ru"}, + {"tag": "uba-main", "name": "ЮБА-маин", "lang": "ru"}, + {"tag": "msl", "name": "Суперлига. Мужчины", "lang": ""}, + {"tag": "mhl", "name": "Высшая лига. Мужчины", "lang": ""}, + {"tag": "mcup", "name": "Кубок России. Мужчины", "lang": ""}, + {"tag": "wpremier", "name": "Премьер-Лига. Женщины", "lang": ""}, + {"tag": "wsl", "name": "Суперлига. Женщины", "lang": ""}, + {"tag": "whl", "name": "Высшая лига. Женщины", "lang": ""}, + {"tag": "wcup", "name": "Кубок России. Женщины", "lang": ""}, + {"tag": "uba-summer", "name": "UBA Leto", "lang": "ru"}, + {"tag": "unics", "name": "UNICS", "lang": "ru"}, +] + +TOKEN = "7639240596:AAH0YtdQoWZSC-_R_EW4wKAHHNLIA0F_ARY" +GROUP_CHAT = 228977654 + +if not os.path.exists("logs"): + os.makedirs("logs") +if not os.path.exists("JSON"): + os.makedirs("JSON") + +LOG_CONFIG = { + "version": 1, + "handlers": { + "telegram": { + "class": "telegram_handler.TelegramHandler", + "level": "INFO", + "token": TOKEN, + "chat_id": GROUP_CHAT, + "formatter": "telegram", + }, + "console": { + "class": "logging.StreamHandler", + "level": "DEBUG", + "formatter": "simple", + "stream": "ext://sys.stdout", + }, + "file": { + "class": "logging.FileHandler", + "level": "DEBUG", + "formatter": "simple", + "filename": f"logs/GFX_{myhost}.log", + "encoding": "utf-8", + }, + }, + "loggers": { + __name__: {"handlers": ["console", "file", "telegram"], "level": "DEBUG"}, + }, + "formatters": { + "telegram": { + "class": "telegram_handler.HtmlFormatter", + "format": "%(levelname)s %(message)s", + "use_emoji": "True", + }, + "simple": { + "class": "logging.Formatter", + "format": "%(asctime)s %(levelname)-8s %(funcName)s() - %(message)s", + "datefmt": "%d.%m.%Y %H:%M:%S", + }, + }, +} + +logging.config.dictConfig(LOG_CONFIG) +logger = logging.getLogger(__name__) +logger.handlers[2].formatter.use_emoji = True + +# Глобальный кэш и лок для потокобезопасности +_GAME_CACHE: dict[tuple[int, str], dict] = {} +_GAME_CACHE_LOCK = Lock() + +THROTTLE_OLD_MINUTES = 30 + +FOLDER_JSON = "JSON" if sys.platform.startswith("win") else "static" +# --- режим однократного прогона для старого матча --- +RUN_ONCE = False # включится, если матч не Online +CURRENT_GAME_ID: int | None = None + + +def is_game_online(game_id: int) -> bool: + """True, если матч в статусе Online (live-status). Возвращает False при любом нештатном ответе.""" + global URL + try: + live = get_json(f"{URL}api/abc/games/live-status?id={game_id}") + + if not isinstance(live, dict): + logger.warning(f"live-status: неожиданный тип ответа: {type(live).__name__}") + return False + + status = live.get("status") + result = live.get("result") or {} + if not isinstance(result, dict): + logger.warning(f"live-status: 'result' не dict: {type(result).__name__}") + return False + print(status) + if status == "Not Found": + return False + + game_status = result.get("gameStatus") + logger.debug(f"live-status raw: status={status}, gameStatus={game_status}") + + return (status == "Ok") and (game_status == "Online") + + except Exception as e: + logger.error(f"is_game_online: ошибка при запросе live-status для game_id={game_id}: {e}", exc_info=True) + return False + + +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 read_match_id_json(path="match_id.json", attempts=10, delay=0.2): + """Надёжное чтение match_id.json с ретраями при EBUSY/битом JSON.""" + d = delay + for i in range(attempts): + try: + if not os.path.isfile(path): + return {} + with open(path, "r", encoding="utf-8") as f: + return json.load(f) + except json.JSONDecodeError: + # файл переписывают — подождём и попробуем снова + time.sleep(d) + d = min(d * 1.6, 2.0) + except OSError as e: + # EBUSY (errno=16) — подождём и ещё раз + if getattr(e, "errno", None) == errno.EBUSY: + time.sleep(d) + d = min(d * 1.6, 2.0) + continue + # иные ошибки — пробрасываем дальше + raise + logger.error( + "Не удалось прочитать match_id.json после нескольких попыток; возвращаю {}" + ) + return {} + + +# === Аргументы командной строки === +parser = argparse.ArgumentParser(description="VTB Data Fetcher") +parser.add_argument("--league", type=str, default="vtb", help="League tag") +parser.add_argument("--lang", type=str, default="en", help="Language") +# parser.add_argument("--team", type=str, required=True, help="Team name") +# parser.add_argument("--region", type=int, default=0, help="for tvstart.ru") + +group = parser.add_mutually_exclusive_group(required=True) +group.add_argument("--team", type=str, help="Team name") +group.add_argument("--region", action="store_true", help="for tvstart.ru") + +args = parser.parse_args() + +LEAGUE = args.league +LANG = args.lang + +if args.team: + TEAM = args.team +else: # значит указан --region + ip_check = read_match_id_json("match_id.json") or {} + + ip_address = get_ip_address() + TEAM = ip_check.get(ip_address, {}).get("team") + + if TEAM is None: + parser.error("Не удалось определить команду по IP. Укажите --team явно.") + + +# === Глобальные настройки === +TIMEOUT_ONLINE = 1 +FETCH_INTERVAL = 2 +TIMEOUT_DATA_OFF = 60 + + +game_online_data = None +game_online_lock = threading.Lock() +game_status_data = None +game_status_lock = threading.Lock() + + +def _is_local_ip(ip: str) -> bool: + """True, если IP локальный/loopback/link-local или не распарсился.""" + try: + ipobj = _ip_parse(ip) + return ipobj.is_private or ipobj.is_loopback or ipobj.is_link_local + except Exception: + # Если get_ip_address() вернул что-то странное — считаем локальным, чтобы не префиксовать. + return True + + +def _ipcheck() -> str: + """Возвращает префикс для имени файла по IP. + Если IP локальный или host не найден — возвращает пустую строку. + """ + try: + ip_str = get_ip_address() + except Exception: + ip_str = None + ip_map = globals().get("ip_check") or {} + if ip_str and isinstance(ip_map, dict): + host = (ip_map.get(ip_str) or {}).get("host") + if host: + return f"{host}_" + return "" + + +def rewrite_file(filename: str, data: dict, directory: str = "JSON") -> None: + """ + Перезаписывает JSON-файл с заданными данными. + Если запуск локальный (локальный IP), префикс host в имени файла не используется. + Если IP не локальный и есть словарь ip_check с хостами — добавим префикс host_. + """ + # Если глобальная константа задана — используем её + try: + directory = FOLDER_JSON # type: ignore[name-defined] + except NameError: + # иначе используем аргумент по умолчанию/переданный + pass + + os.makedirs(directory, exist_ok=True) + + host_prefix = _ipcheck() + # print(host_prefix) + # host_prefix = "spb_" + filepath = os.path.join(directory, f"{host_prefix}{filename}.json") + # print(filepath) # оставил как у тебя; можно заменить на logger.debug при желании + + try: + with open(filepath, "w", encoding="utf-8") as f: + json.dump(data, f, ensure_ascii=False, indent=2) + logger.debug(f"Файл {filepath} перезаписан.") + except Exception as e: + logger.error(f"Ошибка при записи файла {filepath}: {e}") + + +def get_json(url: str, timeout: int = 10, verify_ssl: bool = True) -> dict | None: + """ + Получает JSON-ответ по указанному URL. + + Args: + url (str): URL для запроса. + timeout (int): Таймаут запроса в секундах. + verify_ssl (bool): Проверять ли SSL-сертификат. + + Returns: + dict | None: Распарсенный JSON или None при ошибке. + """ + try: + logger.debug(f"Пытаюсь получить данные с {url}") + response = requests.get(url, timeout=timeout, verify=verify_ssl) + response.raise_for_status() # выбросит исключение, если статус != 2xx + return response.json() + except requests.RequestException as e: + logger.warning(f"Ошибка при запросе: {url}\n{e}") + return None + except ValueError as e: + logger.warning(f"Некорректный JSON-ответ от {url}:\n{e}") + return None + + +def Game_Online2(game_id: int) -> dict | None: + """ + Получает и объединяет данные об игре, включая онлайн-информацию. + + Использует глобальные переменные: URL и LANG. + + Args: + game_id (int): ID матча. + + Returns: + dict | None: Объект игры или None при ошибке. + """ + global URL, LANG + + def build_url(endpoint: str) -> str: + return f"{URL}api/abc/games/{endpoint}?Id={game_id}&Lang={LANG}" + + # 1. Получаем box score + box_score = get_json(build_url("box-score")) + + if not box_score or box_score.get("status") != "Ok": + # Получаем данные старого матча + game = get_json(build_url("game")) + if game: + logger.debug("У нас получилось получить данные со старого матча") + else: + logger.warning( + f"Не удалось получить данные старого матча: game_id={game_id}" + ) + return game + + # 2. Получаем онлайн-данные + game = get_json(build_url("game")) + play_by_play = get_json(build_url("play-by-play")) + + if not game or not play_by_play: + logger.warning(f"Ошибка при получении онлайн-данных для матча {game_id}") + return None + + try: + # 3. Совмещаем статистику + for index_team, team in enumerate(game["result"]["teams"][1:]): + box_team = box_score["result"]["teams"][index_team] + for player in team.get("starts", []): + stat = next( + ( + s + for s in box_team.get("starts", []) + if s.get("startNum") == player.get("startNum") + ), + None, + ) + if stat: + player["stats"] = stat + + team["total"] = box_team.get("total", {}) + + # 4. Добавляем дополнительные данные + game["result"]["plays"] = play_by_play.get("result", []) + game["result"]["scoreByPeriods"] = box_score["result"].get("scoreByPeriods", []) + game["result"]["fullScore"] = box_score["result"].get("fullScore", {}) + + logger.debug("Склеил данные по онлайн матчу") + return game + + except Exception as e: + logger.error(f"Ошибка при обработке данных игры {game_id}: {e}") + return None + + +def Game_Online(game_id: int) -> dict | None: + """ + Получает и объединяет данные об игре, включая онлайн-информацию, + с троттлингом обновления "старых" матчей (не чаще, чем раз в 30 минут). + + Использует глобальные переменные: URL и LANG. + + Args: + game_id (int): ID матча. + + Returns: + dict | None: Объект игры или None при ошибке. + """ + global URL, LANG, _GAME_CACHE, _GAME_CACHE_LOCK + + now = datetime.now(timezone.utc) + cache_key = (game_id, str(LANG)) + + # Время троттлинга для старых матчей + OLD_GAME_THROTTLE_MINUTES = 10 + + # 0. Предварительная проверка: если недавно получали "старый" матч — отдаем кэш + with _GAME_CACHE_LOCK: + cached = _GAME_CACHE.get(cache_key) + if ( + cached + and cached.get("mode") == "old" + and (now - cached.get("ts", now)) + < timedelta(minutes=OLD_GAME_THROTTLE_MINUTES) + ): + return cached.get("data") + + def build_url(endpoint: str) -> str: + return f"{URL}api/abc/games/{endpoint}?Id={game_id}&Lang={LANG}" + + box_score = get_json(build_url("box-score")) + print(box_score) + if not box_score or box_score.get("status") != "Ok": + # Проверим — матч сейчас online? + live = get_json(f"{URL}api/abc/games/live-status?id={game_id}") + is_online = bool( + live + and live.get("status") == "Ok" + and live.get("result", {}).get("gameStatus") == "Online" + ) + + game = get_json(build_url("game")) + if game: + logger.debug("У нас получилось получить данные со старого матча") + # Только если матч не в онлайн-режиме — кладём в кэш как 'old' + if not is_online: + with _GAME_CACHE_LOCK: + _GAME_CACHE[cache_key] = {"mode": "old", "ts": now, "data": game} + else: + logger.warning( + f"Не удалось получить данные старого матча: game_id={game_id}" + ) + return game + + # 1. Получаем box score + # box_score = get_json(build_url("box-score")) + + # if not box_score or box_score.get("status") != "Ok": + # # Получаем данные старого матча (и кэшируем их с режимом 'old') + # live = get_json(f"{URL}api/abc/games/live-status?id={game_id}") + # is_online = bool(live and live.get("status") == "Ok" and live.get("result", {}).get("gameStatus") == "Online") + + # game = get_json(build_url("game")) + # if game: + # logger.debug("У нас получилось получить данные со старого матча") + # if not is_online: + # with _GAME_CACHE_LOCK: + # _GAME_CACHE[cache_key] = {"mode": "old", "ts": now, "data": game} + # else: + # logger.warning(f"Не удалось получить данные старого матча: game_id={game_id}") + # return game + + # game = get_json(build_url("game")) + # if game: + # logger.debug("У нас получилось получить данные со старого матча") + # with _GAME_CACHE_LOCK: + # _GAME_CACHE[cache_key] = {"mode": "old", "ts": now, "data": game} + # else: + # logger.warning( + # f"Не удалось получить данные старого матча: game_id={game_id}" + # ) + # # Даже неудачный ответ имеет смысл закэшировать как 'old' на короткое время, + # # но чтобы не скрыть будущий успех, кэшируем только при наличии данных. + # return game + + # 2. Получаем онлайн-данные + game = get_json(build_url("game")) + play_by_play = get_json(build_url("play-by-play")) + + if not game or not play_by_play: + logger.warning(f"Ошибка при получении онлайн-данных для матча {game_id}") + return None + + try: + # 3. Совмещаем статистику + for index_team, team in enumerate(game["result"]["teams"][1:]): + box_team = box_score["result"]["teams"][index_team] + for player in team.get("starts", []): + stat = next( + ( + s + for s in box_team.get("starts", []) + if s.get("startNum") == player.get("startNum") + ), + None, + ) + if stat: + player["stats"] = stat + + team["total"] = box_team.get("total", {}) + + # 4. Добавляем дополнительные данные + game["result"]["plays"] = play_by_play.get("result", []) + game["result"]["scoreByPeriods"] = box_score["result"].get("scoreByPeriods", []) + game["result"]["fullScore"] = box_score["result"].get("fullScore", {}) + + logger.debug("Склеил данные по онлайн матчу") + + # Обновляем кэш и снимаем режим 'old' + with _GAME_CACHE_LOCK: + _GAME_CACHE[cache_key] = {"mode": "online", "ts": now, "data": game} + + return game + + except Exception as e: + logger.error(f"Ошибка при обработке данных игры {game_id}: {e}") + return None + + +def game_online_loop(game_id: int, stop_event: threading.Event) -> None: + """ + Цикл обновления онлайн-данных игры с заданным интервалом. + + Args: + game_id (int): ID игры. + stop_event (threading.Event): Событие для остановки цикла. + """ + global game_online_data, RUN_ONCE, CURRENT_GAME_ID + single_run = RUN_ONCE + while not stop_event.is_set(): + try: + data = Game_Online(game_id) + if data: + with game_online_lock: + game_online_data = data + else: + logger.warning(f"Game_Online вернул None для game_id={game_id}") + except Exception as e: + logger.error(f"Ошибка в game_online_loop: {e}", exc_info=True) + + # --- однократный режим для старого матча --- + if single_run: + logger.info("game_online_loop: однократный режим — выхожу из потока.") + return + + stop_event.wait(TIMEOUT_ONLINE) + + +def coach_team_stat(data: list[dict], team_id: int) -> dict: + """ + Считает статистику тренера по матчам и сезонам для конкретной команды. + + Args: + data (list[dict]): Список сезонов с данными. + team_id (int): ID команды. + + Returns: + dict: Статистика тренера. + """ + total_games = total_wins = total_loses = seasons = 0 + + for d in data or []: + team = d.get("team") + if team and team.get("id") == team_id: + seasons += 1 + total_games += d.get("games", 0) + total_wins += d.get("wins", 0) + total_loses += d.get("loses", 0) + + return { + "games": total_games, + "wins": total_wins, + "loses": total_loses, + "gamesAsCoach": total_games, + "winsAsCoach": total_wins, + "losesAsCoach": total_loses, + "season": seasons, + } + + +def safe_int(value: any, default: int = 0) -> int: + """ + Безопасное преобразование значения в int. Возвращает default при ошибке. + + Args: + value: Значение для преобразования (строка, число и т.п.). + default: Значение по умолчанию при ошибке. + + Returns: + Целое число или default. + """ + try: + if isinstance(value, str): + value = value.strip() + return int(float(value)) + except (ValueError, TypeError): + return default + + +def format_time(seconds: float | int) -> str: + """ + Форматирует время в секундах в строку "M:SS". + + Args: + seconds (float | int): Количество секунд. + + Returns: + str: Время в формате "M:SS". + """ + try: + total_seconds = int(float(seconds)) + minutes = total_seconds // 60 + sec = total_seconds % 60 + return f"{minutes}:{sec:02}" + except (ValueError, TypeError): + return "0:00" + + +def safe_percent(numerator: float | int | str, denominator: float | int | str) -> str: + """ + Безопасно вычисляет процент (numerator / denominator * 100), округляя до 1 знака. + + Args: + numerator: Числитель (может быть числом или строкой). + denominator: Знаменатель (может быть числом или строкой). + + Returns: + Строка с процентом, например "75.0%" или "0.0%" при ошибке. + """ + try: + num = float(str(numerator).strip()) + den = float(str(denominator).strip()) + if den == 0: + return "0.0%" + return f"{round(num * 100 / den, 1)}%" + except (ValueError, TypeError): + return "0.0%" + + +def calc_shot_percent_by_type( + sum_stat: dict | None, + item_stats: dict, + online: bool, + shot_types: int | list[int] = 1, + digits: int = 1, + empty: str = "0.0%", +) -> str: + """ + Возвращает процент реализации бросков по одному или нескольким типам (goalX / shotX). + + Args: + sum_stat: Сезонная статистика игрока или None. + item_stats: Онлайн-статистика (например, item["stats"]). + online: Учитывать ли онлайн-данные. + shot_types: Целое число или список номеров бросков (1, 2, 3, или [2, 3]). + digits: Кол-во знаков после запятой. + empty: Что возвращать при отсутствии данных или делении на 0. + + Returns: + Строка процента, например '68.5%' или '0.0%'. + """ + if isinstance(shot_types, int): + shot_types = [shot_types] + + if not sum_stat or item_stats is None: + return empty + + total_goal = 0 + total_shot = 0 + # print(item_stats) + for t in shot_types: + # print(t) + goal_key = f"goal{t}" + shot_key = f"shot{t}" + + sum_goal_raw = sum_stat.get(goal_key) + sum_shot_raw = sum_stat.get(shot_key) + item_goal_raw = item_stats.get(goal_key) + item_shot_raw = item_stats.get(shot_key) + + # Если какие-либо данные отсутствуют, или являются "", считаем 0 + sum_goal = safe_int(sum_goal_raw if sum_goal_raw != "" else 0) + sum_shot = safe_int(sum_shot_raw if sum_shot_raw != "" else 0) + + item_goal = safe_int(item_goal_raw if item_goal_raw != "" else 0) + item_shot = safe_int(item_shot_raw if item_shot_raw != "" else 0) + + total_goal += sum_goal + (item_goal if online else 0) + total_shot += sum_shot + (item_shot if online else 0) + + if total_shot == 0: + return empty + + percent = round(total_goal * 100 / total_shot, digits) + return f"{percent}%" + + +def calc_total_shots_str( + sum_stat: dict | None, + item_stats: dict, + online: bool, + shot_types: int | list[int], + empty: str = "0/0", +) -> str: + """ + Формирует строку вида 'goalX/shotX' или сумму по нескольким типам бросков. + + Args: + sum_stat: Сезонная статистика игрока (может быть None). + item_stats: Онлайн-статистика из item["stats"]. + online: Добавлять ли онлайн-значения. + shot_types: Один номер броска (int) или список (например, [2, 3] для TShots23). + empty: Что возвращать при отсутствии данных. + + Returns: + Строка вида '5/8' или '0/0' при ошибке/отсутствии данных. + """ + if isinstance(shot_types, int): + shot_types = [shot_types] + + if not sum_stat or item_stats is None: + return empty + + total_goal = 0 + total_shot = 0 + + for t in shot_types: + goal_key = f"goal{t}" + shot_key = f"shot{t}" + + if sum_stat.get(shot_key) == "" or item_stats.get(shot_key) == "": + return empty + + goal = safe_int(sum_stat.get(goal_key)) + shot = safe_int(sum_stat.get(shot_key)) + + if online: + goal += safe_int(item_stats.get(goal_key) or 0) + shot += safe_int(item_stats.get(shot_key) or 0) + + total_goal += goal + total_shot += shot + + return f"{total_goal}/{total_shot}" + + +def sum_stat_with_online( + stat_name: str, base_stat: dict | None, online_stat: dict | None, online: bool +) -> int: + base = safe_int((base_stat or {}).get(stat_name)) + online_val = safe_int((online_stat or {}).get(stat_name)) if online else 0 + return base + online_val + + +def get_carrer_high(player_id, name_stat): + try: + directory = FOLDER_JSON # type: ignore[name-defined] + except NameError: + # иначе используем аргумент по умолчанию/переданный + pass + + os.makedirs(directory, exist_ok=True) + + host_prefix = _ipcheck() + # print(host_prefix) + # host_prefix = "spb_" + filepath = os.path.join(directory, f"{host_prefix}{player_id}.json") + # print(filepath) # оставил как у тебя; можно заменить на logger.debug при желании + + try: + with open(filepath, "r", encoding="utf-8") as f: + player_data = json.load(f) + max_points = 0 + + for item in player_data: + if item.get("class") == "Normal": + points = item["stats"].get(name_stat) + if points and points.isdigit(): # Проверяем, что значение числовое + points = int(points) + if points > max_points: + max_points = points + return max_points + except Exception as ex: + logger.warning(f"[{player_id}] {ex}") + return None + + +def Json_Team_Generation(who, data, stop_event): + logger.info(f"START making json for {data[who]}, {data[f'{who}_id']}") + global game_online_data, RUN_ONCE + initialized = False + did_write = False # 👈 флаг: была ли хотя бы одна успешная запись файлов + + # 👇 В однократном режиме дождёмся, пока OnlineLoop положит данные (до 5 сек) + if RUN_ONCE: + t0 = time.time() + while not stop_event.is_set(): + with game_online_lock: + if game_online_data is not None: + break + if time.time() - t0 > 5: # таймаут ожидания + logger.warning(f"Json_Team_Generation[{who}]: нет game_online_data >5с, попробую всё равно.") + break + time.sleep(0.05) + + while not stop_event.is_set(): + try: + with game_online_lock: + game_online_data_copy = game_online_data + if game_online_data_copy is not None: + if who == "team1": + logger.debug( + f"send {game_online_data_copy['result']['team1']['name']}" + ) + for i in game_online_data_copy["result"]["teams"]: + if i["teamNumber"] == 1: + payload = i + elif who == "team2": + logger.debug( + f"send {game_online_data_copy['result']['team2']['name']}" + ) + for i in game_online_data_copy["result"]["teams"]: + if i["teamNumber"] == 2: + payload = i + + # print(payload) + # получаю ID игроков + + url = f"{URL}api/abc/games/live-status?id={data['game_id']}" + json_live_status = get_json(url) + online = ( + True + if json_live_status + and "status" in json_live_status + and json_live_status["status"] == "Ok" + and json_live_status["result"]["gameStatus"] == "Online" + else False + ) + # online = True + + # получаю статистику на игроков по сезону и карьере + if not initialized: + player_ids = [ + i["personId"] + for i in payload["starts"] + if i["startRole"] == "Player" + ] + print(player_ids) + coach_ids = [ + i["personId"] + for i in payload["starts"] + if i["startRole"] == "Coach" and i["personId"] is not None + ] + print(coach_ids) + player_season_stat = [] + player_career_stat = [] + coach_stat = [] + with ThreadPoolExecutor() as pool: + player_season_stat_temp = [ + pool.submit(Player_Stat_Season, player_id, data["season"]) + for player_id in player_ids + ] + player_career_stat_temp = [ + pool.submit(Player_Stat_Career, player_id) + for player_id in player_ids + ] + coach_stat_temp = [ + pool.submit( + Coach_Stat, coach_id, data["season"], data[f"{who}_id"] + ) + for coach_id in coach_ids + ] + player_futures = [ + pool.submit(Player_all_game, pid) for pid in player_ids + ] + all_players_games = [] + for fut in as_completed(player_futures): + try: + all_players_games.append(fut.result()) + except Exception as e: + logger.exception(f"Ошибка при обработке игрока: {e}") + + player_season_stat += [ + res.result() for res in player_season_stat_temp + ] + player_career_stat += [ + res.result() for res in player_career_stat_temp + ] + coach_stat += [res.result() for res in coach_stat_temp] + + initialized = True + # print(coach_stat) + # while not stop_event.is_set(): + role_list = [ + ("Center", "C"), + ("Guard", "G"), + ("Forward", "F"), + ("Power Forward", "PF"), + ("Small Forward", "SF"), + ("Shooting Guard", "SG"), + ("Point Guard", "PG"), + ("Forward-Center", "FC"), + ] + starts = payload["starts"] + HeadCoachStatsCareer, HeadCoachStatsTeam = "", "" + team = [] + # print(starts) + for item in starts: + # print(player_season_stat) + + row_player_season = next( + ( + v + for row in player_season_stat + if row + for k, v in row.items() + if k == item["personId"] + ), + None, + ) + row_player_career = next( + ( + v + for row in player_career_stat + if row + for k, v in row.items() + if k == item["personId"] + ), + None, + ) + # print(item) + row_coach_stat = next( + ( + v + for row in coach_stat + if row + for k, v in row.items() + if k == item["personId"] + ), + None, + ) + row_player_season_avg, sum_stat = ( + ( + next( + ( + r["stats"] + for r in row_player_season + if r["class"] == "Avg" + ), + None, + ), + next( + ( + r["stats"] + for r in row_player_season + if r["class"] == "Sum" + ), + None, + ), + ) + if row_player_season + else (None, None) + ) + row_player_career_avg, row_player_career_sum = ( + ( + next( + ( + r["stats"] + for r in row_player_career + if r["class"] == "Avg" + ), + None, + ), + next( + ( + r["stats"] + for r in row_player_career + if r["class"] == "Sum" + ), + None, + ), + ) + if row_player_career + else (None, None) + ) + if row_coach_stat: + games_word = ( + "game" if row_coach_stat[-1]["games"] in [0, 1] else "games" + ) + total_season = len(row_coach_stat) - 1 + season_word = "season" if total_season == 1 else "seasons" + procent = ( + round( + (row_coach_stat[-1]["wins"] * 100) + / row_coach_stat[-1]["games"], + 1, + ) + if row_coach_stat[-1]["games"] != 0 + else "" + ) + # HeadCoachStatsCareer = ( + # f'{row_s["total_seasons"]} {season_word} in The VTB United League career' + # ) + HeadCoachStatsCareer = "in The VTB United League career" + if total_season == 0: + HeadCoachStatsCareer = f'{row_coach_stat[-1]["games"] if row_coach_stat[-1]["games"] != 0 else "first"} {games_word} as {data[who]} head coach' + HeadCoachStatsCareer += ( + f'\n{row_coach_stat[-1]["games"] if row_coach_stat[-1]["games"] != 0 else "first"} {games_word}: {row_coach_stat[-1]["wins"]}-{row_coach_stat[-1]["loses"]} ({procent}% wins)' + if row_coach_stat[-1]["games"] != 0 + else "" + ) + coach_team_stat_temp = coach_team_stat( + row_coach_stat, data[f"{who}_id"] + ) + games_word_team = ( + "game" + if coach_team_stat_temp["games"] in [0, 1] + else "games" + ) + season_word_team = ( + "season" + if coach_team_stat_temp["season"] == 1 + else "seasons" + ) + procent_team = ( + round( + (coach_team_stat_temp["wins"] * 100) + / coach_team_stat_temp["games"], + 1, + ) + if coach_team_stat_temp["games"] != 0 + else "" + ) + # HeadCoachStatsTeam = ( + # f'{coach_team_stat_temp["season"]} {season_word_team} as {data[f"{who}"]} head coach' + # ) + HeadCoachStatsTeam = f"{data[f'{who}']} head coach" + if coach_team_stat_temp["season"] == 0: + HeadCoachStatsTeam = f'{coach_team_stat_temp["games"] if coach_team_stat_temp["games"] != 0 else "first"} {games_word} as {data[f"{who}"]} head coach' + HeadCoachStatsTeam += ( + f'\n{coach_team_stat_temp["games"] if coach_team_stat_temp["games"] != 0 else "first"} {games_word}: {coach_team_stat_temp["wins"]}-{coach_team_stat_temp["loses"]} ({procent_team}% wins)' + if coach_team_stat_temp["games"] != 0 + else "" + ) + + text = "" + if row_player_season_avg: + if LANG == "en": + text = f"GAMES: {row_player_season_avg['games']} MINUTES: {row_player_season_avg['playedTime']} " + text += ( + f"PTS: {row_player_season_avg['points']} " + if row_player_season_avg["points"] != "" + else "" + ) + text += ( + f"REB: {row_player_season_avg['rebound']} " + if row_player_season_avg["rebound"] != "" + and float(row_player_season_avg["rebound"]) >= 1.0 + else "" + ) + text += ( + f"AST: {row_player_season_avg['assist']} " + if row_player_season_avg["assist"] != "" + and float(row_player_season_avg["assist"]) >= 1.0 + else "" + ) + text += ( + f"STL: {row_player_season_avg['steal']} " + if row_player_season_avg["steal"] != "" + and float(row_player_season_avg["steal"]) >= 1.0 + else "" + ) + text += ( + f"BLK: {row_player_season_avg['blockShot']} " + if row_player_season_avg["blockShot"] != "" + and float(row_player_season_avg["blockShot"]) >= 1.0 + else "" + ) + else: + text = f"ИГРЫ: {row_player_season_avg['games']} ВРЕМЯ: {row_player_season_avg['playedTime']} " + text += ( + f"ОЧКИ: {row_player_season_avg['points']} " + if row_player_season_avg["points"] != "" + else "" + ) + text += ( + f"ПОДБОРЫ: {row_player_season_avg['rebound']} " + if row_player_season_avg["rebound"] != "" + and float(row_player_season_avg["rebound"]) >= 1.0 + else "" + ) + text += ( + f"ПЕРЕДАЧИ: {row_player_season_avg['assist']} " + if row_player_season_avg["assist"] != "" + and float(row_player_season_avg["assist"]) >= 1.0 + else "" + ) + text += ( + f"ПЕРЕХВАТЫ: {row_player_season_avg['steal']} " + if row_player_season_avg["steal"] != "" + and float(row_player_season_avg["steal"]) >= 1.0 + else "" + ) + text += ( + f"БЛОКШОТЫ: {row_player_season_avg['blockShot']} " + if row_player_season_avg["blockShot"] != "" + and float(row_player_season_avg["blockShot"]) >= 1.0 + else "" + ) + text = text.strip() + # print(item["personId"] if item["startRole"] != "Team" else , item["startRole"]) + # if not item["personId"]: + # item["personId"] = data[f'{who}_id'] + # print(item) + # item["personId"] = item["personId"] if item["personId"] else data[f'{who}_id'] + # print(item) + # print(data[f'{who}_id'], type(data[f'{who}_id']), data) + # print(item) + player = { + "id": ( + item["personId"] + if item["personId"] + else int(data[f"{who}_id"]) + ), + "num": item["displayNumber"], + "startRole": item["startRole"], + "role": item["positionName"], + "roleShort": ( + [ + r[1] + for r in role_list + if r[0].lower() == item["positionName"].lower() + ][0] + if any( + r[0].lower() == item["positionName"].lower() + for r in role_list + ) + else "" + ), + "NameGFX": ( + f"{item['firstName'].strip()} {item['lastName'].strip()}" + if item["firstName"] is not None + and item["lastName"] is not None + else "Команда" + ), + "captain": item["isCapitan"], + "age": item["age"] if item["age"] is not None else 0, + "height": f'{item["height"]} cm' if item["height"] else 0, + "weight": f'{item["weight"]} kg' if item["weight"] else 0, + "isStart": ( + item["stats"]["isStart"] if item["stats"] else False + ), + "isOn": ( + "🏀" + if item["stats"] and item["stats"]["isOnCourt"] is True + else "" + ), + "flag": f"https://flagicons.lipis.dev/flags/4x3/{'ru' if item['countryId'] is None and item['countryName'] == 'Russia' else '' if item['countryId'] is None else item['countryId'].lower() if item['countryName'] is not None else ''}.svg", + "pts": item["stats"]["points"] if item["stats"] else 0, + "pt-2": ( + f"{item['stats']['goal2']}/{item['stats']['shot2']}" + if item["stats"] + else 0 + ), + "pt-3": ( + f"{item['stats']['goal3']}/{item['stats']['shot3']}" + if item["stats"] + else 0 + ), + "pt-1": ( + f"{item['stats']['goal1']}/{item['stats']['shot1']}" + if item["stats"] + else 0 + ), + "fg": ( + f"{item['stats']['goal2'] + item['stats']['goal3']}/{item['stats']['shot2'] + item['stats']['shot3']}" + if item["stats"] + else 0 + ), + "ast": item["stats"]["assist"] if item["stats"] else 0, + "stl": item["stats"]["steal"] if item["stats"] else 0, + "blk": item["stats"]["block"] if item["stats"] else 0, + "blkVic": item["stats"]["blocked"] if item["stats"] else 0, + "dreb": item["stats"]["defReb"] if item["stats"] else 0, + "oreb": item["stats"]["offReb"] if item["stats"] else 0, + "reb": ( + item["stats"]["defReb"] + item["stats"]["offReb"] + if item["stats"] + else 0 + ), + "to": item["stats"]["turnover"] if item["stats"] else 0, + "foul": item["stats"]["foul"] if item["stats"] else 0, + "foulT": item["stats"]["foulT"] if item["stats"] else 0, + "foulD": item["stats"]["foulD"] if item["stats"] else 0, + "foulC": item["stats"]["foulC"] if item["stats"] else 0, + "foulB": item["stats"]["foulB"] if item["stats"] else 0, + "fouled": item["stats"]["foulsOn"] if item["stats"] else 0, + "plusMinus": item["stats"]["plusMinus"] if item["stats"] else 0, + "dunk": item["stats"]["dunk"] if item["stats"] else 0, + "kpi": ( + item["stats"]["points"] + + item["stats"]["defReb"] + + item["stats"]["offReb"] + + item["stats"]["assist"] + + item["stats"]["steal"] + + item["stats"]["block"] + + item["stats"]["foulsOn"] + + (item["stats"]["goal1"] - item["stats"]["shot1"]) + + (item["stats"]["goal2"] - item["stats"]["shot2"]) + + (item["stats"]["goal3"] - item["stats"]["shot3"]) + - item["stats"]["turnover"] + - item["stats"]["foul"] + if item["stats"] + else 0 + ), + "time": ( + format_time(item["stats"]["second"]) + if item["stats"] + else "0:00" + ), + "pts1q": 0, + "pts2q": 0, + "pts3q": 0, + "pts4q": 0, + "pts1h": 0, + "pts2h": 0, + "Name1GFX": ( + item["firstName"].strip() if item["firstName"] else "" + ), + "Name2GFX": ( + item["lastName"].strip() if item["lastName"] else "" + ), + "photoGFX": ( + os.path.join( + "D:\\Photos", + LEAGUE, + data[who], + f"{item['displayNumber']}.png", + ) + if item["startRole"] == "Player" + else "" + ), + "season": text, + "isOnCourt": ( + item["stats"]["isOnCourt"] if item["stats"] else False + ), + "AvgPoints": ( + row_player_season_avg["points"] + if row_player_season_avg + and row_player_season_avg["points"] != "" + else "0.0" + ), + "AvgAssist": ( + row_player_season_avg["assist"] + if row_player_season_avg + and row_player_season_avg["assist"] != "" + else "0.0" + ), + "AvgBlocks": ( + row_player_season_avg["blockShot"] + if row_player_season_avg + and row_player_season_avg["blockShot"] != "" + else "0.0" + ), + "AvgDefRebound": ( + row_player_season_avg["defRebound"] + if row_player_season_avg + and row_player_season_avg["defRebound"] != "" + else "0.0" + ), + "AvgOffRebound": ( + row_player_season_avg["offRebound"] + if row_player_season_avg + and row_player_season_avg["offRebound"] != "" + else "0.0" + ), + "AvgRebound": ( + row_player_season_avg["rebound"] + if row_player_season_avg + and row_player_season_avg["rebound"] != "" + else "0.0" + ), + "AvgSteal": ( + row_player_season_avg["steal"] + if row_player_season_avg + and row_player_season_avg["steal"] != "" + else "0.0" + ), + "AvgTurnover": ( + row_player_season_avg["turnover"] + if row_player_season_avg + and row_player_season_avg["turnover"] != "" + else "0.0" + ), + "AvgFoul": ( + row_player_season_avg["foul"] + if row_player_season_avg + and row_player_season_avg["foul"] != "" + else "0.0" + ), + "AvgOpponentFoul": ( + row_player_season_avg["foulsOnPlayer"] + if row_player_season_avg + and row_player_season_avg["foulsOnPlayer"] != "" + else "0.0" + ), + "AvgPlusMinus": ( + row_player_season_avg["plusMinus"] + if row_player_season_avg + and row_player_season_avg["plusMinus"] != "" + else "0.0" + ), + "AvgDunk": ( + row_player_season_avg["dunk"] + if row_player_season_avg + and row_player_season_avg["dunk"] != "" + else "0.0" + ), + "AvgKPI": "0.0", + "AvgPlayedTime": ( + row_player_season_avg["playedTime"] + if row_player_season_avg + and row_player_season_avg["playedTime"] != "" + else "0:00" + ), + "Shot1Percent": calc_shot_percent_by_type( + sum_stat, item["stats"], online, shot_types=1 + ), + "Shot2Percent": calc_shot_percent_by_type( + sum_stat, item["stats"], online, shot_types=2 + ), + "Shot3Percent": calc_shot_percent_by_type( + sum_stat, item["stats"], online, shot_types=3 + ), + "Shot23Percent": calc_shot_percent_by_type( + sum_stat, item["stats"], online, shot_types=[2, 3] + ), + "TPoints": sum_stat_with_online( + "points", sum_stat, item["stats"], online + ), + "TShots1": calc_total_shots_str( + sum_stat, item["stats"], online, 1 + ), + "TShots2": calc_total_shots_str( + sum_stat, item["stats"], online, 2 + ), + "TShots3": calc_total_shots_str( + sum_stat, item["stats"], online, 3 + ), + "TShots23": calc_total_shots_str( + sum_stat, item["stats"], online, [2, 3] + ), + "TShot1Percent": calc_shot_percent_by_type( + sum_stat, item["stats"], online, shot_types=1 + ), + "TShot2Percent": calc_shot_percent_by_type( + sum_stat, item["stats"], online, shot_types=2 + ), + "TShot3Percent": calc_shot_percent_by_type( + sum_stat, item["stats"], online, shot_types=3 + ), + "TShot23Percent": calc_shot_percent_by_type( + sum_stat, item["stats"], online, shot_types=[2, 3] + ), + "TAssist": sum_stat_with_online( + "assist", sum_stat, item["stats"], online + ), + "TBlocks": sum_stat_with_online( + "blockShot", sum_stat, item["stats"], online + ), + "TDefRebound": sum_stat_with_online( + "defRebound", sum_stat, item["stats"], online + ), + "TOffRebound": sum_stat_with_online( + "offRebound", sum_stat, item["stats"], online + ), + "TRebound": ( + sum_stat_with_online( + "defRebound", sum_stat, item["stats"], online + ) + + sum_stat_with_online( + "offRebound", sum_stat, item["stats"], online + ) + ), + "TSteal": sum_stat_with_online( + "steal", sum_stat, item["stats"], online + ), + "TTurnover": sum_stat_with_online( + "turnover", sum_stat, item["stats"], online + ), + "TFoul": sum_stat_with_online( + "foul", sum_stat, item["stats"], online + ), + "TOpponentFoul": sum_stat_with_online( + "foulsOnPlayer", sum_stat, item["stats"], online + ), + "TPlusMinus": 0, + "TDunk": sum_stat_with_online( + "dunk", sum_stat, item["stats"], online + ), + "TKPI": 0, + "TPlayedTime": sum_stat["playedTime"] if sum_stat else "0:00", + "TGameCount": ( + safe_int(sum_stat["games"]) + if sum_stat and sum_stat.get("games") != "" + else 0 + ) + + (1 if online else 0), + "TStartCount": ( + safe_int(sum_stat["isStarts"]) + if sum_stat and sum_stat.get("isStarts", 0) != "" + else 0 + ), + "CareerTShots1": calc_total_shots_str( + row_player_career_sum, item["stats"], online, 1 + ), + "CareerTShots2": calc_total_shots_str( + row_player_career_sum, item["stats"], online, 2 + ), + "CareerTShots3": calc_total_shots_str( + row_player_career_sum, item["stats"], online, 3 + ), + "CareerTShots23": calc_total_shots_str( + row_player_career_sum, item["stats"], online, [2, 3] + ), + "CareerTShot1Percent": calc_shot_percent_by_type( + row_player_career_sum, item["stats"], online, 1 + ), + "CareerTShot2Percent": calc_shot_percent_by_type( + row_player_career_sum, item["stats"], online, 2 + ), + "CareerTShot3Percent": calc_shot_percent_by_type( + row_player_career_sum, item["stats"], online, 3 + ), + "CareerTShot23Percent": calc_shot_percent_by_type( + row_player_career_sum, item["stats"], online, [2, 3] + ), + "CareerTPoints": sum_stat_with_online( + "points", row_player_career_sum, item["stats"], online + ), + "CareerTAssist": sum_stat_with_online( + "assist", row_player_career_sum, item["stats"], online + ), + "CareerTBlocks": sum_stat_with_online( + "blockShot", row_player_career_sum, item["stats"], online + ), + "CareerTDefRebound": sum_stat_with_online( + "defRebound", row_player_career_sum, item["stats"], online + ), + "CareerTOffRebound": sum_stat_with_online( + "offRebound", row_player_career_sum, item["stats"], online + ), + "CareerTRebound": ( + sum_stat_with_online( + "defRebound", + row_player_career_sum, + item["stats"], + online, + ) + + sum_stat_with_online( + "offRebound", + row_player_career_sum, + item["stats"], + online, + ) + ), + "CareerTSteal": sum_stat_with_online( + "steal", row_player_career_sum, item["stats"], online + ), + "CareerTTurnover": sum_stat_with_online( + "turnover", row_player_career_sum, item["stats"], online + ), + "CareerTFoul": sum_stat_with_online( + "foul", row_player_career_sum, item["stats"], online + ), + "CareerTOpponentFoul": sum_stat_with_online( + "foulsOnPlayer", + row_player_career_sum, + item["stats"], + online, + ), + "CareerTPlusMinus": 0, # оставить как есть + "CareerTDunk": sum_stat_with_online( + "dunk", row_player_career_sum, item["stats"], online + ), + "CareerTPlayedTime": ( + row_player_career_sum["playedTime"] + if row_player_career_sum + else "0:00" + ), + "CareerTGameCount": sum_stat_with_online( + "games", row_player_career_sum, item["stats"], online + ) + + (1 if online else 0), + "CareerTStartCount": sum_stat_with_online( + "isStarts", row_player_career_sum, item["stats"], online + ), # если нужно, можно +1 при старте + "AvgCarPoints": ( + row_player_career_avg["points"] + if row_player_career_avg + and row_player_career_avg["points"] != "" + else "0.0" + ), + "AvgCarAssist": ( + row_player_career_avg["assist"] + if row_player_career_avg + and row_player_career_avg["assist"] != "" + else "0.0" + ), + "AvgCarBlocks": ( + row_player_career_avg["blockShot"] + if row_player_career_avg + and row_player_career_avg["blockShot"] != "" + else "0.0" + ), + "AvgCarDefRebound": ( + row_player_career_avg["defRebound"] + if row_player_career_avg + and row_player_career_avg["defRebound"] != "" + else "0.0" + ), + "AvgCarOffRebound": ( + row_player_career_avg["offRebound"] + if row_player_career_avg + and row_player_career_avg["offRebound"] != "" + else "0.0" + ), + "AvgCarRebound": ( + row_player_career_avg["rebound"] + if row_player_career_avg + and row_player_career_avg["rebound"] != "" + else "0.0" + ), + "AvgCarSteal": ( + row_player_career_avg["steal"] + if row_player_career_avg + and row_player_career_avg["steal"] != "" + else "0.0" + ), + "AvgCarTurnover": ( + row_player_career_avg["turnover"] + if row_player_career_avg + and row_player_career_avg["turnover"] != "" + else "0.0" + ), + "AvgCarFoul": ( + row_player_career_avg["foul"] + if row_player_career_avg + and row_player_career_avg["foul"] != "" + else "0.0" + ), + "AvgCarOpponentFoul": ( + row_player_career_avg["foulsOnPlayer"] + if row_player_career_avg + and row_player_career_avg["foulsOnPlayer"] != "" + else "0.0" + ), + "AvgCarPlusMinus": ( + row_player_career_avg["plusMinus"] + if row_player_career_avg + and row_player_career_avg["plusMinus"] != "" + else "0.0" + ), + "AvgCarDunk": ( + row_player_career_avg["dunk"] + if row_player_career_avg + and row_player_career_avg["dunk"] != "" + else "0.0" + ), + "AvgCarKPI": "0.0", + "AvgCarPlayedTime": ( + row_player_career_avg["playedTime"] + if row_player_career_avg + and row_player_career_avg["playedTime"] != "" + else "0:00" + ), + "HeadCoachStatsCareer": HeadCoachStatsCareer, + "HeadCoachStatsTeam": HeadCoachStatsTeam, + "PTS_Career_High": get_carrer_high(item["personId"], "points"), + "AST_Career_High": get_carrer_high(item["personId"], "assist"), + "REB_Career_High": get_carrer_high(item["personId"], "rebound"), + "STL_Career_High": get_carrer_high(item["personId"], "steal"), + "BLK_Career_High": get_carrer_high(item["personId"], "blockShot"), + } + team.append(player) + count_player = sum(1 for x in team if x["startRole"] == "Player") + # print(count_player) + if count_player < 12: + if team: # Check if team is not empty + empty_rows = [ + { + key: ( + False + if key in ["captain", "isStart", "isOnCourt"] + else ( + 0 + if key + in [ + "id", + "pts", + "weight", + "height", + "age", + "ast", + "stl", + "blk", + "blkVic", + "dreb", + "oreb", + "reb", + "to", + "foul", + "foulT", + "foulD", + "foulC", + "foulB", + "fouled", + "plusMinus", + "dunk", + "kpi", + ] + else "" + ) + ) + for key in team[0].keys() + } + for _ in range( + (4 if count_player <= 4 else 12) - count_player + ) + ] + team.extend(empty_rows) + role_priority = { + "Player": 0, + "": 1, + "Coach": 2, + "Team": 3, + None: 4, + "Other": 5, # на случай неизвестных + } + # print(team) + sorted_team = sorted( + team, + key=lambda x: role_priority.get( + x.get("startRole", 99), 99 + ), # 99 — по умолчанию + ) + rewrite_file(who, sorted_team) + rewrite_file(f"{who}_copy", sorted_team) + # print(sorted_team) + top_sorted_team = sorted( + filter(lambda x: x["startRole"] in ["Player", ""], sorted_team), + key=lambda x: ( + x["pts"], + x["dreb"] + x["oreb"], + x["ast"], + x["stl"], + x["blk"], + x["time"], + ), + reverse=True, + ) + for item in top_sorted_team: + item["pts"] = "" if item["num"] == "" else item["pts"] + item["foul"] = "" if item["num"] == "" else item["foul"] + rewrite_file(f"top{who.replace('t','T')}", top_sorted_team) + started_team = sorted( + filter( + lambda x: x["startRole"] == "Player" and x["isOnCourt"] is True, + sorted_team, + ), + key=lambda x: int(x["num"]), + reverse=False, + ) + rewrite_file(f"started_{who}", started_team) + # обычный цикл / однократный выход: + if RUN_ONCE: + logger.info(f"Json_Team_Generation[{who}]: однократный режим — файлы записаны, выхожу.") + return + did_write = True # 👈 отметили успешную запись + time.sleep(TIMEOUT_ONLINE) + else: + print(f"{who} НЕ ПОЛУЧАЕТСЯ ПРОЧИТАТЬ") + # --- однократный режим для старого матча --- + except Exception as e: + print(f"[{who}] Ошибка: {e}, {e.with_traceback()}") + if RUN_ONCE: + if did_write: + logger.info(f"Json_Team_Generation[{who}]: один успешный проход выполнен — выхожу.") + return + else: + # данных ещё не было — короткая задержка и ещё одна попытка + stop_event.wait(0.5) + continue + time.sleep(TIMEOUT_ONLINE) + + +def Player_Stat_Season(player_id: str, season: str) -> dict: + url = f"{URL.replace('pro.russiabasket.org', 'vtb-league.org')}api/abc/players/stats?teamId=0&Tag={LEAGUE}&season={season}&Id={player_id}" + player_stat_season = get_json(url) + + if not player_stat_season: + logger.debug(f"Пустой ответ от API для игрока {player_id} за сезон {season}") + return {player_id: default_player_stats_season()} + + items = player_stat_season.get("items") + if items: + logger.debug( + f"Данные за сезон {season} для игрока {player_id} успешно получены." + ) + return {player_id: items[-2:]} # последние две записи: Sum и Avg + + logger.debug( + f"Нет данных на игрока {player_id} за сезон {season}. Вероятно, еще не играл." + ) + return {player_id: default_player_stats_season()} + + +def Player_all_game_in_season2(player_id: str, season: str) -> dict: + url = f"{URL}api/abc/players/stats?tag={LEAGUE}&season={season}&id={player_id}" + player_games = get_json(url) + # games = {} + if not player_games: + logger.debug(f"Пустой ответ от API для игрока {player_id}") + return {player_id: default_player_stats_season()} + + for i in player_games.get("items"): + i["season"] = season + return {player_games.get("items")} + + +def Player_all_game2(player_id: str) -> dict: + url = f"{URL}api/abc/players/info?tag={LEAGUE}&id={player_id}" + player_seasons = get_json(url) + + if not player_seasons: + logger.debug(f"Пустой ответ от API для игрока {player_id}") + return {player_id: default_player_stats_season()} + + seasons = player_seasons.get("result").get("seasons") + player_game = [] + with ThreadPoolExecutor() as pool: + player_season_stat_temp = [ + pool.submit(Player_all_game_in_season, player_id, season["id"]) + for season in seasons + ] + for i in player_season_stat_temp: + print(i.result()) + player_game += [res.result() for res in player_season_stat_temp] + rewrite_file(player_id, player_game) + + +def Player_all_game_in_season(player_id: str, season: str) -> List[Dict[str, Any]]: + url = f"{URL.replace('pro.russiabasket.org', 'vtb-league.org')}api/abc/players/stats?tag={LEAGUE}&season={season}&id={player_id}&Lang={LANG}" + player_games = get_json(url) + if not player_games: + logger.debug(f"Пустой ответ от API для игрока {player_id}, сезон {season}") + return [] # возвращаем пустой список, чтобы тип был стабилен + + items = player_games.get("items") or [] + # гарантируем список словарей + if not isinstance(items, list): + logger.warning( + f"Неверный формат 'items' для {player_id}, сезон {season}: {type(items)}" + ) + return [] + + for it in items: + if isinstance(it, dict): + it["season"] = season + return items + + +def Player_all_game(player_id: str) -> List[Dict[str, Any]]: + url = f"{URL.replace('pro.russiabasket.org', 'vtb-league.org')}api/abc/players/info?tag={LEAGUE}&id={player_id}&Lang={LANG}" + player_seasons = get_json(url) + + if not player_seasons: + logger.debug(f"Пустой ответ от API для игрока {player_id}") + return [] # последовательный тип + + result = player_seasons.get("result") or {} + seasons = result.get("seasons") or [] + # seasons = [ + # {"id": 2026}, + # {"id": 2025}, + # {"id": 2024}, + # {"id": 2023}, + # {"id": 2022}, + # {"id": 2021}, + # {"id": 2020}, + # {"id": 2019}, + # {"id": 2018}, + # {"id": 2017}, + # {"id": 2016}, + # {"id": 2015}, + # {"id": 2014}, + # {"id": 2013}, + # {"id": 2012}, + # {"id": 2011}, + # {"id": 2010}, + # ] + if not isinstance(seasons, list) or not seasons: + logger.debug(f"Нет сезонов для игрока {player_id}") + return [] + + all_games: List[Dict[str, Any]] = [] + with ThreadPoolExecutor() as pool: + futures = [ + pool.submit(Player_all_game_in_season, player_id, s.get("id")) + for s in seasons + if s.get("id") + ] + for fut in as_completed(futures): + try: + items = fut.result() # это уже список словарей + all_games.extend(items) + except Exception as e: + logger.exception(f"Ошибка при сборе игр игрока {player_id}: {e}") + + # если нужно писать на диск — пишем уже готовый JSON-совместимый список + rewrite_file(player_id, all_games) + return all_games + + +def default_player_stats_season() -> list: + empty_stats = { + "games": 0, + "isStarts": "", + "points": "", + "goal2": "", + "shot2": "", + "goal3": "", + "shot3": "", + "goal1": "", + "shot1": "", + "goal23": "", + "shot23": "", + "shot2Percent": "", + "shot3Percent": "", + "shot23Percent": "", + "shot1Percent": "", + "assist": "", + "pass": "", + "steal": "", + "blockShot": "", + "blockedOwnShot": "", + "defRebound": "", + "offRebound": "", + "rebound": "", + "foulsOnPlayer": "", + "turnover": "", + "foul": "", + "second": 0, + "playedTime": "", + "dunk": "", + "fastBreak": "", + "plusMinus": None, + } + + return [ + {"team": None, "game": None, "stats": empty_stats.copy(), "class": "Sum"}, + {"team": None, "game": None, "stats": empty_stats.copy(), "class": "Avg"}, + ] + + +def default_player_stats() -> list: + empty_stats = { + "games": 0, + "isStarts": "", + "points": "", + "goal2": "", + "shot2": "", + "goal3": "", + "shot3": "", + "goal1": "", + "shot1": "", + "goal23": "", + "shot23": "", + "shot2Percent": "", + "shot3Percent": "", + "shot23Percent": "", + "shot1Percent": "", + "assist": "", + "pass": "", + "steal": "", + "blockShot": "", + "blockedOwnShot": "", + "defRebound": "", + "offRebound": "", + "rebound": "", + "foulsOnPlayer": "", + "turnover": "", + "foul": "", + "second": 0, + "playedTime": "", + "dunk": "", + "fastBreak": "", + "plusMinus": None, + } + + return [ + {"season": None, "team": None, "stats": empty_stats.copy(), "class": "Sum"}, + {"season": None, "team": None, "stats": empty_stats.copy(), "class": "Avg"}, + ] + + +def Player_Stat_Career(player_id: str) -> dict: + url = f"{URL.replace('pro.russiabasket.org', 'vtb-league.org')}api/abc/players/career?teamId=0&Tag={LEAGUE}&Id={player_id}" + player_stat_career = get_json(url) + + if not player_stat_career: + logger.debug(f"Пустой ответ от API для игрока {player_id}") + return {player_id: default_player_stats()} + + items = player_stat_career.get("items") + if items: + logger.debug(f"Данные за карьеру игрока {player_id} успешно получены.") + return {player_id: items[-2:]} # последние два сезона (Sum и Avg) + + logger.debug(f"Данные на игрока {player_id} не найдены. Вероятно, новичок.") + return {player_id: default_player_stats()} + + +def Coach_Stat(coach_id: str, season: str, team_id: str) -> dict | None: + url = f"{URL}api/abc/coaches/career?teamId={team_id}&tag={LEAGUE}&season={season}&Id={coach_id}" + coach_stat = get_json(url) + + if not coach_stat: + logger.debug(f"Пустой ответ от API для тренера {coach_id}") + return None + + items = coach_stat.get("items") + if items: + logger.debug(f"Данные за карьеру тренера {coach_id} успешно получены.") + return {coach_id: items} + + logger.debug(f"Данные для тренера {coach_id} не найдены. Возможно, он новичок.") + return None + + +def add_new_team_stat( + data: dict, + avg_age: float, + points: float, + avg_height: float, + timeout_str: str, + timeout_left: str, +) -> dict: + """ + Добавляет в словарь команды форматированную статистику. + Все значения приводятся к строкам. + + Args: + data: Исходная статистика команды. + avg_age: Средний возраст команды (строка). + points: Кортеж из 4 строк: ptsStart, ptsStart_pro, ptsBench, ptsBench_pro. + avg_height: Средний рост (в см). + timeout_str: Строка отображения таймаутов. + timeout_left: Остаток таймаутов. + + Returns: + Обновлённый словарь `data` с новыми ключами. + """ + + def safe_int(v): # Локальная защита от ValueError/TypeError + try: + return int(v) + except (ValueError, TypeError): + return 0 + + def format_percent(goal, shot): + goal, shot = safe_int(goal), safe_int(shot) + return f"{round(goal * 100 / shot)}%" if shot else "0%" + + goal1, shot1 = safe_int(data.get("goal1")), safe_int(data.get("shot1")) + goal2, shot2 = safe_int(data.get("goal2")), safe_int(data.get("shot2")) + goal3, shot3 = safe_int(data.get("goal3")), safe_int(data.get("shot3")) + + def_reb = safe_int(data.get("defReb")) + off_reb = safe_int(data.get("offReb")) + + data.update( + { + "pt-1": f"{goal1}/{shot1}", + "pt-2": f"{goal2}/{shot2}", + "pt-3": f"{goal3}/{shot3}", + "fg": f"{goal2 + goal3}/{shot2 + shot3}", + "pt-1_pro": format_percent(goal1, shot1), + "pt-2_pro": format_percent(goal2, shot2), + "pt-3_pro": format_percent(goal3, shot3), + "fg_pro": format_percent(goal2 + goal3, shot2 + shot3), + "Reb": str(def_reb + off_reb), + "avgAge": str(avg_age), + "ptsStart": str(points[0]), + "ptsStart_pro": str(points[1]), + "ptsBench": str(points[2]), + "ptsBench_pro": str(points[3]), + "avgHeight": f"{avg_height} cm", + "timeout_left": str(timeout_left), + "timeout_str": str(timeout_str), + } + ) + + # Приводим все значения к строкам, если нужно строго для сериализации + for k in data: + data[k] = str(data[k]) + + return data + + +def add_data_for_teams(new_data: list[dict]) -> tuple[float, list, float]: + """ + Возвращает усреднённые статистики команды: + - средний возраст + - очки со старта и скамейки + их доли + - средний рост + + Args: + new_data (list[dict]): Список игроков с полями "startRole", "stats", "age", "height" + + Returns: + tuple: (avg_age: float, points: list, avg_height: float) + """ + players = [item for item in new_data if item.get("startRole") == "Player"] + + points_start = 0 + points_bench = 0 + total_age = 0 + total_height = 0 + player_count = len(players) + + for player in players: + stats = player.get("stats") + if stats: + is_start = stats.get("isStart") + + # Очки + if is_start is True: + points_start += stats.get("points", 0) + elif is_start is False: + points_bench += stats.get("points", 0) + + # Возраст и рост + total_age += player.get("age", 0) or 0 + total_height += player.get("height", 0) or 0 + + total_points = points_start + points_bench + points_start_pro = ( + f"{round(points_start * 100 / total_points)}%" if total_points else "0%" + ) + points_bench_pro = ( + f"{round(points_bench * 100 / total_points)}%" if total_points else "0%" + ) + + avg_age = round(total_age / player_count, 1) if player_count else 0 + avg_height = round(total_height / player_count, 1) if player_count else 0 + + points = [points_start, points_start_pro, points_bench, points_bench_pro] + return avg_age, points, avg_height + + +def time_outs_func(data_pbp: list[dict]) -> tuple[str, int, str, int]: + """ + Вычисляет количество оставшихся таймаутов для обеих команд + и формирует строку состояния. + + Args: + data_pbp: Список игровых событий (play-by-play). + + Returns: + Кортеж: (строка команды 1, остаток, строка команды 2, остаток) + """ + timeout1 = [] + timeout2 = [] + + for event in data_pbp: + if event.get("play") == 23: + if event.get("startNum") == 1: + timeout1.append(event) + elif event.get("startNum") == 2: + timeout2.append(event) + + def timeout_status(timeout_list: list[dict], last_event: dict) -> tuple[str, int]: + period = last_event.get("period", 0) + sec = last_event.get("sec", 0) + + if period < 3: + timeout_max = 2 + count = sum(1 for t in timeout_list if t.get("period", 0) <= period) + quarter = "1st half" + elif period < 5: + count = sum(1 for t in timeout_list if 3 <= t.get("period", 0) <= period) + quarter = "2nd half" + if period == 4 and sec >= 4800 and count in (0, 1): + timeout_max = 2 + else: + timeout_max = 3 + else: + timeout_max = 1 + count = sum(1 for t in timeout_list if t.get("period", 0) == period) + quarter = f"OverTime {period - 4}" + + left = max(0, timeout_max - count) + word = "Time-outs" if left != 1 else "Time-out" + text = f"{left if left != 0 else 'No'} {word} left in {quarter}" + return text, left + + if not data_pbp: + return "", 0, "", 0 + + last_event = data_pbp[-1] + t1_str, t1_left = timeout_status(timeout1, last_event) + t2_str, t2_left = timeout_status(timeout2, last_event) + + return t1_str, t1_left, t2_str, t2_left + + +stat_name_list = [ + ("points", "Очки", "points"), + ("pt-1", "Штрафные", "free throws"), + ("pt-1_pro", "штрафные, процент", "free throws pro"), + ("pt-2", "2-очковые", "2-points"), + ("pt-2_pro", "2-очковые, процент", "2-points pro"), + ("pt-3", "3-очковые", "3-points"), + ("pt-3_pro", "3-очковые, процент", "3-points pro"), + ("fg", "очки с игры", "field goals"), + ("fg_pro", "Очки с игры, процент", "field goals pro"), + ("assist", "Передачи", "assists"), + ("pass", "", ""), + ("defReb", "подборы в защите", ""), + ("offReb", "подборы в нападении", ""), + ("Reb", "Подборы", "rebounds"), + ("steal", "Перехваты", "steals"), + ("block", "Блокшоты", "blocks"), + ("blocked", "", ""), + ("turnover", "Потери", "turnovers"), + ("foul", "Фолы", "fouls"), + ("foulsOn", "", ""), + ("foulT", "", ""), + ("foulD", "", ""), + ("foulC", "", ""), + ("foulB", "", ""), + ("second", "секунды", "seconds"), + ("dunk", "данки", "dunks"), + ("fastBreak", "", "fast breaks"), + ("plusMinus", "+/-", "+/-"), + ("avgAge", "", "avg Age"), + ("ptsBench", "", "Bench PTS"), + ("ptsBench_pro", "", "Bench PTS, %"), + ("ptsStart", "", "Start PTS"), + ("ptsStart_pro", "", "Start PTS, %"), + ("avgHeight", "", "avg height"), + ("timeout_left", "", "timeout left"), + ("timeout_str", "", "timeout str"), +] + + +def Team_Both_Stat(stop_event: threading.Event) -> None: + """ + Обновляет файл team_stats.json, содержащий сравнение двух команд. + + Аргументы: + stop_event (threading.Event): Событие для остановки цикла. + """ + logger.info("START making json for team statistics") + global game_online_data, RUN_ONCE + + while not stop_event.is_set(): + with game_online_lock: + game_data = game_online_data + + if not game_data: + time.sleep(1) + continue + + try: + teams = game_data["result"]["teams"] + plays = game_data["result"].get("plays", []) + + # Разделение команд + team_1 = next((t for t in teams if t["teamNumber"] == 1), None) + team_2 = next((t for t in teams if t["teamNumber"] == 2), None) + + if not team_1 or not team_2: + logger.warning("Не найдены обе команды в данных") + time.sleep(TIMEOUT_ONLINE) + continue + + # Таймауты + timeout_str1, timeout_left1, timeout_str2, timeout_left2 = time_outs_func( + plays + ) + + # Возраст, очки, рост + avg_age_1, points_1, avg_height_1 = add_data_for_teams( + team_1.get("starts", []) + ) + avg_age_2, points_2, avg_height_2 = add_data_for_teams( + team_2.get("starts", []) + ) + + if not team_1.get("total") or not team_2.get("total"): + logger.debug( + "Нет total у команд — пропускаю перезапись team_stats.json" + ) + stop_event.wait(TIMEOUT_ONLINE) + continue + + # Форматирование общей статистики (как и было) + total_1 = add_new_team_stat( + team_1["total"], + avg_age_1, + points_1, + avg_height_1, + timeout_str1, + timeout_left1, + ) + total_2 = add_new_team_stat( + team_2["total"], + avg_age_2, + points_2, + avg_height_2, + timeout_str2, + timeout_left2, + ) + + # # Форматирование общей статистики + # total_1 = add_new_team_stat( + # team_1["total"], + # avg_age_1, + # points_1, + # avg_height_1, + # timeout_str1, + # timeout_left1, + # ) + # total_2 = add_new_team_stat( + # team_2["total"], + # avg_age_2, + # points_2, + # avg_height_2, + # timeout_str2, + # timeout_left2, + # ) + + # Финальный JSON + result_json = [] + for key in total_1: + val1 = ( + int(total_1[key]) + if isinstance(total_1[key], float) + else total_1[key] + ) + val2 = ( + int(total_2[key]) + if isinstance(total_2[key], float) + else total_2[key] + ) + stat_rus, stat_eng = "", "" + for s in stat_name_list: + if s[0] == key: + stat_rus, stat_eng = s[1], s[2] + break + + result_json.append( + { + "name": key, + "nameGFX_rus": stat_rus, + "nameGFX_eng": stat_eng, + "val1": val1, + "val2": val2, + } + ) + + rewrite_file("team_stats", result_json) + logger.debug("Успешно записаны данные в team_stats.json") + if RUN_ONCE: + logger.info(": однократный режим — выхожу из потока.") + return + except Exception as e: + logger.error( + f"Ошибка при обработке командной статистики: {e}", exc_info=True + ) + + stop_event.wait(TIMEOUT_ONLINE) + + +def Referee(stop_event: threading.Event) -> None: + """ + Поток, создающий JSON-файл с информацией о судьях матча. + """ + logger.info("START making json for referee") + global game_online_data, RUN_ONCE + + desired_order = [ + "Crew chief", + "Referee 1", + "Referee 2", + "Commissioner", + "Ст.судья", + "Судья 1", + "Судья 2", + "Комиссар", + ] + + while not stop_event.is_set(): + with game_online_lock: + game_data = game_online_data + + if not game_data: + stop_event.wait(TIMEOUT_ONLINE) + continue + try: + # Найти судей (teamNumber == 0) + team_ref = next( + (t for t in game_data["result"]["teams"] if t["teamNumber"] == 0), None + ) + if not team_ref: + logger.warning("Не найдена судейская бригада в данных.") + stop_event.wait(TIMEOUT_DATA_OFF) + continue + + referees_raw = team_ref.get("starts", []) + # print(referees_raw) + referees = [] + + for r in referees_raw: + flag_code = ( + r.get("countryId", "").lower() if r.get("countryName") else "" + ) + referees.append( + { + "displayNumber": r.get("displayNumber", ""), + "positionName": r.get("positionName", ""), + "lastNameGFX": f"{r.get('firstName', '')} {r.get('lastName', '')}".strip(), + "secondName": r.get("secondName", ""), + "birthday": r.get("birthday", ""), + "age": r.get("age", 0), + "flag": f"https://flagicons.lipis.dev/flags/4x3/{flag_code}.svg", + } + ) + + # Сортировка по позиции + referees = sorted( + referees, + key=lambda x: ( + desired_order.index(x["positionName"]) + if x["positionName"] in desired_order + else len(desired_order) + ), + ) + + rewrite_file("referee", referees) + logger.debug("Успешно записаны судьи в файл") + if RUN_ONCE: + logger.info(": однократный режим — выхожу из потока.") + return + + except Exception as e: + logger.error(f"Ошибка в Referee потоке: {e}", exc_info=True) + + stop_event.wait(TIMEOUT_DATA_OFF) + + +def Scores_Quarter(stop_event: threading.Event) -> None: + """ + Поток, обновляющий JSON со счётом по четвертям. + """ + logger.info("START making json for scores quarter") + global game_online_data, RUN_ONCE + + quarters = ["Q1", "Q2", "Q3", "Q4", "OT1", "OT2", "OT3", "OT4"] + + while not stop_event.is_set(): + try: + with game_online_lock: + game_data = game_online_data + + if not game_data: + stop_event.wait(FETCH_INTERVAL) + continue + + rewrite_file("game_online", game_data) + + score_by_quarter = [{"Q": q, "score1": "", "score2": ""} for q in quarters] + + # Сначала пробуем fullScore + full_score_str = ( + game_data.get("result", {}).get("game", {}).get("fullScore", "") + ) + if full_score_str: + full_score_list = full_score_str.split(",") + for i, score_str in enumerate(full_score_list[: len(score_by_quarter)]): + parts = score_str.split(":") + if len(parts) == 2: + score_by_quarter[i]["score1"] = parts[0] + score_by_quarter[i]["score2"] = parts[1] + logger.debug("Счёт по четвертям получен из fullScore.") + + # Если нет fullScore, пробуем scoreByPeriods + elif "scoreByPeriods" in game_data.get("result", {}): + periods = game_data["result"]["scoreByPeriods"] + for i, score in enumerate(periods[: len(score_by_quarter)]): + score_by_quarter[i]["score1"] = str(score.get("score1", "")) + score_by_quarter[i]["score2"] = str(score.get("score2", "")) + logger.debug("Счёт по четвертям получен из scoreByPeriods.") + + else: + logger.debug("Нет данных по счёту, сохраняем пустые значения.") + + rewrite_file("scores", score_by_quarter) + + except Exception as e: + logger.error(f"Ошибка в Scores_Quarter: {e}", exc_info=True) + # --- однократный режим для старого матча --- + if RUN_ONCE: + logger.info("Scores_Quarter: однократный режим — выхожу из потока.") + return + stop_event.wait(TIMEOUT_ONLINE) + + +def status_online_func(data: dict) -> dict | None: + """ + Получает онлайн-статус игры и возвращает данные + путь к PNG-фолам. + """ + global URL + try: + game_id = data["game_id"] + url = f"{URL}api/abc/games/live-status?id={game_id}" + json_live_status = get_json(url) + + if json_live_status.get("status") != "Ok": + logger.warning(f"Live status API вернул не 'Ok': {json_live_status}") + return { + "foulsA": 0, + "foulsB": 0, + } + + status_data = json_live_status["result"] + path_to_png = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators" + ) + fouls_a = min(status_data.get("foulsA", 0), 5) + fouls_b = min(status_data.get("foulsB", 0), 5) + + status_data["foulsA_png"] = f"{path_to_png}\\Home_{fouls_a}.png" + status_data["foulsB_png"] = f"{path_to_png}\\Away_{fouls_b}.png" + + return status_data + + except Exception as e: + logger.error(f"Ошибка в status_online_func: {e}", exc_info=True) + return None + + +def Status_Online(data: dict, stop_event: threading.Event) -> None: + """ + Поток, обновляющий JSON-файл с онлайн-статусом матча. + """ + logger.info("START making json for status online") + global game_status_data, RUN_ONCE + # «Снимок» режима на момент старта потока + single_run = RUN_ONCE + while not stop_event.is_set(): + try: + result = status_online_func(data) + if result: + with game_status_lock: + game_status_data = result + rewrite_file("live_status", [game_status_data]) + logger.debug("Успешно записан онлайн-статус в файл.") + else: + logger.warning("status_online_func вернула None — пропуск записи.") + except Exception as e: + logger.error(f"Ошибка в Status_Online: {e}", exc_info=True) + # --- однократный режим для старого матча --- + if single_run: + logger.info("Status_Online: однократный режим — выхожу из потока.") + return + stop_event.wait(TIMEOUT_ONLINE) + + +def Play_By_Play(data: dict, stop_event: threading.Event) -> None: + """ + Поток, обновляющий JSON-файл с последовательностью бросков в матче. + """ + logger.info("START making json for play-by-play") + global game_online_data, LEAGUE + + while not stop_event.is_set(): + try: + with game_online_lock: + game_data = game_online_data + + if not game_data: + logger.debug("game_online_data отсутствует") + stop_event.wait(TIMEOUT_DATA_OFF) + continue + + teams = game_data.get("result", {}).get("teams", []) + team1_data = next((i for i in teams if i.get("teamNumber") == 1), None) + team2_data = next((i for i in teams if i.get("teamNumber") == 2), None) + + if not team1_data or not team2_data: + logger.warning("Не удалось получить команды из game_online_data") + stop_event.wait(TIMEOUT_DATA_OFF) + continue + + team1_name = data["team1"] + team2_name = data["team2"] + team1_startnum = [ + p["startNum"] + for p in team1_data.get("starts", []) + if p.get("startRole") == "Player" + ] + team2_startnum = [ + p["startNum"] + for p in team2_data.get("starts", []) + if p.get("startRole") == "Player" + ] + + plays = game_data.get("result", {}).get("plays", []) + if not plays: + logger.debug("нет данных в play-by-play") + stop_event.wait(TIMEOUT_DATA_OFF) + continue + + # Получение текущего времени игры + url = f"{URL}api/abc/games/live-status?id={data['game_id']}" + json_live_status = get_json(url) + last_event = plays[-1] + + # if not json_live_status or json_live_status.get("message") == "Not Found": + if not json_live_status or json_live_status.get("status") == "Not Found": + period = last_event.get("period", 1) + second = 0 + else: + period = (json_live_status or {}).get("result", {}).get("period", 1) + second = (json_live_status or {}).get("result", {}).get("second", 0) + + # Создание DataFrame из событий + df = pd.DataFrame(plays[::-1]) + + # Преобразование для лиги 3x3 + if "3x3" in LEAGUE: + df["play"].replace({2: 1, 3: 2}, inplace=True) + + df_goals = df[df["play"].isin([1, 2, 3])].copy() + if df_goals.empty: + logger.debug("нет данных о голах в play-by-play") + stop_event.wait(TIMEOUT_DATA_OFF) + continue + + # Расчёты по очкам и времени + df_goals["score1"] = ( + df_goals["startNum"].isin(team1_startnum) * df_goals["play"] + ) + df_goals["score2"] = ( + df_goals["startNum"].isin(team2_startnum) * df_goals["play"] + ) + + df_goals["score_sum1"] = df_goals["score1"].fillna(0).cumsum() + df_goals["score_sum2"] = df_goals["score2"].fillna(0).cumsum() + + df_goals["new_sec"] = ( + pd.to_numeric(df_goals["sec"], errors="coerce").fillna(0).astype(int) + // 10 + ) + df_goals["time_now"] = (600 if period < 5 else 300) - second + df_goals["quar"] = period - df_goals["period"] + + df_goals["diff_time"] = np.where( + df_goals["quar"] == 0, + df_goals["time_now"] - df_goals["new_sec"], + (600 * df_goals["quar"] - df_goals["new_sec"]) + df_goals["time_now"], + ) + + df_goals["diff_time_str"] = df_goals["diff_time"].apply( + lambda x: ( + f"{x // 60}:{str(x % 60).zfill(2)}" if isinstance(x, int) else x + ) + ) + + # Текстовые поля + def generate_text(row, with_time=False, is_rus=False): + s1, s2 = int(row["score_sum1"]), int(row["score_sum2"]) + team = ( + team1_name + if not pd.isna(row["score1"]) and row["score1"] != 0 + else team2_name + ) + + # ✅ Правильный порядок счёта в зависимости от команды + if team == team1_name: + score = f"{s1}-{s2}" + else: + score = f"{s2}-{s1}" + + time_str = ( + f" за {row['diff_time_str']}" + if is_rus + else f" in last {row['diff_time_str']}" + ) + prefix = "рывок" if is_rus else "run" + + return f"{team} {score} {prefix}{time_str if with_time else ''}" + + df_goals["text_rus"] = df_goals.apply( + lambda r: generate_text(r, is_rus=True, with_time=False), axis=1 + ) + df_goals["text_time_rus"] = df_goals.apply( + lambda r: generate_text(r, is_rus=True, with_time=True), axis=1 + ) + df_goals["text"] = df_goals.apply( + lambda r: generate_text(r, is_rus=False, with_time=False), axis=1 + ) + df_goals["text_time"] = df_goals.apply( + lambda r: generate_text(r, is_rus=False, with_time=True), axis=1 + ) + + df_goals["team"] = df_goals["score1"].apply( + lambda x: team1_name if not pd.isna(x) and x != 0 else team2_name + ) + + # Удаление лишнего + drop_cols = [ + "children", + "start", + "stop", + "hl", + "sort", + "startNum", + "zone", + "x", + "y", + ] + df_goals.drop(columns=drop_cols, inplace=True, errors="ignore") + + # Порядок колонок + main_cols = ["text", "text_time"] + all_cols = main_cols + [ + col for col in df_goals.columns if col not in main_cols + ] + df_goals = df_goals[all_cols] + + # Сохранение JSON + directory = FOLDER_JSON + os.makedirs(directory, exist_ok=True) + # ip_address = get_ip_address() + # host = ip_check.get(ip_address, {}).get("host") + host_prefix = _ipcheck() + filepath = os.path.join(directory, f"{host_prefix}play_by_play.json") + + df_goals.to_json(filepath, orient="records", force_ascii=False, indent=4) + logger.debug("Успешно положил данные об play-by-play в файл") + if RUN_ONCE: + logger.info(": однократный режим — выхожу из потока.") + return + except Exception as e: + logger.error(f"Ошибка в Play_By_Play: {e}", exc_info=True) + + stop_event.wait(TIMEOUT_ONLINE) + + +def schedule_daily_restart(): + """Перезапуск get_season_and_schedule каждый день в 00:05 (только не на Windows).""" + if not sys.platform.startswith("win"): + while True: + now = datetime.now() + next_run = (now + timedelta(days=1)).replace( + hour=0, minute=5, second=0, microsecond=0 + ) + sleep_time = (next_run - now).total_seconds() + logger.info( + f"Следующий перезапуск get_season_and_schedule запланирован на {next_run.strftime('%Y-%m-%d %H:%M')}" + ) + time.sleep(sleep_time) + + try: + logger.info("⏰ Автоматический перезапуск get_season_and_schedule()") + get_season_and_schedule() + except Exception as e: + logger.error( + f"Ошибка при автоматическом перезапуске: {e}", exc_info=True + ) + + +def clean_np_ints(obj): + if isinstance(obj, dict): + return {k: clean_np_ints(v) for k, v in obj.items()} + elif isinstance(obj, list): + return [clean_np_ints(v) for v in obj] + elif isinstance(obj, np.integer): + return int(obj) + else: + return obj + + +def get_season_and_schedule() -> dict | None: + """ + Получает текущий сезон и ближайший сыгранный матч для команды. + + Использует глобальные переменные: URL, LEAGUE, LANG, TEAM. + + Returns: + dict | None: Словарь с данными матча или None при ошибке. + """ + global URL, LEAGUE, LANG, TEAM + + try: + # Получение активного сезона + season_url = f"{URL}api/abc/comps/seasons?Tag={LEAGUE}&Lang={LANG}" + season_data = get_json(season_url) + + season = ( + season_data.get("result", [{}])[0].get("season") + if season_data and "vtb" in URL + else ( + season_data.get("items", [{}])[0].get("season") + if season_data and "pro.russiabasket" in URL + else None + ) + ) + print(season) + if not season: + logger.warning("Сезон не найден в данных.") + return None + + # season = 2025 + # Получение расписания + schedule_url = f"{URL}api/abc/comps/calendar?Tag={LEAGUE}&Season={season}&Lang={LANG}&MaxResultCount=1000" + schedule_data = get_json(schedule_url) + rewrite_file("schedule", schedule_data) + + items = schedule_data.get("items") if schedule_data else None + if not items: + logger.warning("Расписание не содержит игр.") + return None + + df = pd.json_normalize(items) + + # Преобразование и фильтрация + df["game.localDate"] = pd.to_datetime( + df["game.localDate"], format="%d.%m.%Y", errors="coerce" + ) + df["game.DateStr"] = df["game.localDate"].dt.strftime("%d.%m.%Y") + df["team1.name"] = df["team1.name"].str.strip() + + current_date = pd.to_datetime(datetime.now().date()) + + df_filtered = df[ + (df["game.localDate"] <= current_date) + & (df["team1.name"].str.lower() == TEAM.lower()) + ] + + if df_filtered.empty: + logger.warning("Нет подходящих матчей для команды на сегодня.") + return None + + last_game = df_filtered.iloc[-1] + + return clean_np_ints( + { + "season": season, + "game_id": last_game["game.id"], + "team1_id": last_game["team1.teamId"], + "team2_id": last_game["team2.teamId"], + "team1": last_game["team1.name"], + "team2": last_game["team2.name"], + "when": last_game["game.DateStr"], + "time": last_game["game.localTime"], + } + ) + + except Exception as e: + logger.error(f"Ошибка при получении сезона или расписания: {e}", exc_info=True) + return None + + +def Standing_func(data: dict, stop_event: threading.Event) -> None: + logger.info("START making json for standings") + global URL, LEAGUE, LANG, RUN_ONCE + + while not stop_event.is_set(): + try: + season = data["season"] + url = f"{URL}api/abc/comps/actual-standings?tag={LEAGUE}&season={season}&lang={LANG}" + data_standings = get_json(url) + + if data_standings and "items" in data_standings and data_standings["items"]: + standings_temp = data_standings["items"] + for item in standings_temp: + if "standings" in item and item["standings"] != []: + standings_temp = item["standings"] + df = pd.json_normalize(standings_temp) + del df["scores"] + if not df["totalWin"].isna().all(): + df["w_l"] = ( + df["totalWin"].astype(str) + + " / " + + df["totalDefeat"].astype(str) + ) + df["procent"] = df.apply( + lambda row: ( + 0 + if row["w_l"] == "0 / 0" + or row["totalGames"] == 0 + or pd.isna(row["totalWin"]) + else round( + row["totalWin"] * 100 / row["totalGames"] + + 0.000005 + ) + ), + axis=1, + ) + df["plus_minus"] = ( + df["totalGoalPlus"] - df["totalGoalMinus"] + ) + df["name"] = df["name"].replace("PBC Uralmash", "Uralmash") + directory = FOLDER_JSON + os.makedirs(directory, exist_ok=True) + host = _ipcheck() + filepath = os.path.join( + directory, + f"{host}standings_{LEAGUE}_{item['comp']['name'].replace(' ', '_')}.json", + ) + + df.to_json( + filepath, + orient="records", + force_ascii=False, + indent=4, + ) + logger.debug("Standings data saved successfully.") + elif "playoffPairs" in item and item["playoffPairs"] != []: + standings_temp = item["playoffPairs"] + df = pd.json_normalize(standings_temp) + directory = FOLDER_JSON + os.makedirs(directory, exist_ok=True) + host = _ipcheck() + filepath = os.path.join( + directory, + f"{host}standings_{LEAGUE}_{item['comp']['name'].replace(' ', '_')}.json", + ) + df.to_json( + filepath, + orient="records", + force_ascii=False, + indent=4, + ) + logger.debug("Standings data saved successfully.") + if RUN_ONCE: + logger.info(": однократный режим — выхожу из потока.") + return + except Exception as e: + logger.warning(f"Ошибка в турнирном положении: {e}") + + stop_event.wait(TIMEOUT_DATA_OFF) + + +def convert_numpy(obj): + if isinstance(obj, dict): + return {k: convert_numpy(v) for k, v in obj.items()} + elif isinstance(obj, list): + return [convert_numpy(v) for v in obj] + elif isinstance(obj, (np.integer, np.int64, np.int32)): + return int(obj) + elif isinstance(obj, (np.floating, np.float64, np.float32)): + return float(obj) + elif isinstance(obj, (np.bool_)): + return bool(obj) + elif isinstance(obj, (np.ndarray,)): + return obj.tolist() + return obj + + +def How_To_Play_Quarter(data: dict) -> None: + logger.info("START making json for How_To_Play_Quarter") + + global LEAGUE, LANG + game_id = data["game_id"] + team1_id, team2_id = data["team1_id"], data["team2_id"] + team1_name, team2_name = data["team1"], data["team2"] + season = data["season"] + + url = f"{URL}api/abc/comps/calendar?Tag={LEAGUE}&Season={season}&Lang={LANG}&MaxResultCount=1000" + schedule_data = get_json(url) + df_schedule = pd.json_normalize(schedule_data["items"]) + + df_schedule = df_schedule[ + [ + "game.id", + "ot", + "game.gameStatus", + "game.score1", + "game.score2", + "game.fullScore", + "team1.teamId", + "team1.name", + "team2.teamId", + "team2.name", + ] + ] + + df_schedule = df_schedule[ + (df_schedule["game.id"] < game_id) + & ( + df_schedule["team1.teamId"].isin([team1_id, team2_id]) + | df_schedule["team2.teamId"].isin([team1_id, team2_id]) + ) + ] + + QUARTERS = ["Q1", "Q2", "Q3", "Q4", "OT1", "OT2", "OT3", "OT4"] + + def parse_quarters(df): + temp_score_quarter = df["game.fullScore"].str.split(",") + df = df.copy() + for i in range(1, 9): + col = f"OT{i - 4}" if i > 4 else f"Q{i}" + df[col] = temp_score_quarter.apply( + lambda x: x[i - 1] if x and len(x) >= i else None + ) + return df + + def compute_results(df, team_id): + df = parse_quarters(df) + for q in QUARTERS: + + def result(row): + if pd.notna(row[q]) and ":" in row[q]: + score1, score2 = map(int, row[q].split(":")) + if row["team1.teamId"] == team_id: + return ( + "win" + if score1 > score2 + else "lose" if score1 < score2 else "draw" + ) + elif row["team2.teamId"] == team_id: + return ( + "win" + if score2 > score1 + else "lose" if score2 < score1 else "draw" + ) + return "" + + df[f"wld{q}"] = df.apply(result, axis=1) + df[f"win{q}"] = (df[f"wld{q}"] == "win").astype(int) + df[f"lose{q}"] = (df[f"wld{q}"] == "lose").astype(int) + df[f"draw{q}"] = (df[f"wld{q}"] == "draw").astype(int) + return df + + def compute_scores(df, team_id): + df = parse_quarters(df) + for q in QUARTERS: + + def score(row): + if pd.notna(row[q]) and ":" in row[q]: + score1, score2 = map(int, row[q].split(":")) + if row["team1.teamId"] == team_id: + return score1 + elif row["team2.teamId"] == team_id: + return score2 + return None + + df[f"score{q}"] = df.apply(score, axis=1) + return df + + df_team1 = compute_results(df_schedule.copy(), team1_id) + df_team2 = compute_results(df_schedule.copy(), team2_id) + df_scores1 = compute_scores(df_schedule.copy(), team1_id) + df_scores2 = compute_scores(df_schedule.copy(), team2_id) + + def aggregate_data(team_name, df_result, df_score): + team_stats = {"team": team_name} + for q in QUARTERS: + team_stats[f"win{q}"] = df_result[f"win{q}"].sum() + team_stats[f"lose{q}"] = df_result[f"lose{q}"].sum() + team_stats[f"draw{q}"] = df_result[f"draw{q}"].sum() + team_stats[f"score{q}"] = int(df_score[f"score{q}"].sum()) + team_stats[f"score_avg{q}"] = ( + round(df_score[f"score{q}"].mean(), 1) + if not df_score[f"score{q}"].isna().all() + else None + ) + return team_stats + + schedule_json_quarter = [ + aggregate_data(team1_name, df_team1, df_scores1), + aggregate_data(team2_name, df_team2, df_scores2), + ] + json_ready_data = convert_numpy(schedule_json_quarter) + rewrite_file("scores_quarter", json_ready_data) + + +def pregame_data(data: dict) -> None: + logger.info("START making json for pregame_data") + + global LEAGUE, LANG + game_id = data["game_id"] + team1_id, team2_id = data["team1_id"], data["team2_id"] + team1_name, team2_name = data["team1"], data["team2"] + season = data["season"] + + teams = [] + for team_id in (team1_id, team2_id): + url = f"{URL}api/abc/teams/stats?Tag={LEAGUE}&Season={season}&Id={team_id}" + team_stat = get_json(url) + data_team = team_stat["result"]["totalStats"] + data_team["team"] = team_stat["result"]["team"]["name"] + data_team["games"] = team_stat["result"]["games"] + temp_team = { + "team": data_team["team"], + "games": data_team["games"], + "points": round((data_team["points"] / data_team["games"]), 1), + "points_2": round((data_team["goal2"] * 100 / data_team["shot2"]), 1), + "points_3": round((data_team["goal3"] * 100 / data_team["shot3"]), 1), + "points_23": round((data_team["goal23"] * 100 / data_team["shot23"]), 1), + "points_1": round((data_team["goal1"] * 100 / data_team["shot1"]), 1), + "assists": round((data_team["assist"] / data_team["games"]), 1), + "rebounds": round( + ( + (data_team["defRebound"] + data_team["offRebound"]) + / data_team["games"] + ), + 1, + ), + "steals": round((data_team["steal"] / data_team["games"]), 1), + "turnovers": round((data_team["turnover"] / data_team["games"]), 1), + "blocks": round((data_team["blockShot"] / data_team["games"]), 1), + "fouls": round((data_team["foul"] / data_team["games"]), 1), + } + teams.append(temp_team) + rewrite_file("team_comparison", teams) + + +def main(): + global TEAM, LANG, URL, RUN_ONCE, CURRENT_GAME_ID + + if TEAM is None: + logger.critical(f"{myhost}\nКоманда не указана") + time.sleep(1) + sys.exit(1) + + logger.info( + f"{myhost}\n!!!!!!!!СТАРТ!!!!!!!!! \nHOST: {TEAM}\nTAG: {LEAGUE} \nВерсия кода: {VERSION}" + ) + + if LANG is None: + LANG = next( + (tag["lang"] for tag in TAGS if tag["tag"].lower() == LEAGUE.lower()), "" + ) + + URL = ( + "https://basket.sportoteka.org/" + if "uba" in LEAGUE.lower() + else "https://pro.russiabasket.org/" + # else "https://vtb-league.org/" + ) + + stop_event = Event() + data = get_season_and_schedule() + if not data: + logger.critical("Не удалось получить данные сезона/матча.") + sys.exit(1) + + # === Ежедневный перезапуск функции на Linux/Mac === + if not sys.platform.startswith("win"): + threading.Thread( + target=schedule_daily_restart, daemon=True, name="ScheduleRestart" + ).start() + + logger.info( + f"{myhost}\n{data['team1']} VS {data['team2']}\n{data['when']} {data['time']}" + ) + CURRENT_GAME_ID = data["game_id"] # запомним глобально id матча + # если матч НЕ онлайн — включаем однократный прогон + # RUN_ONCE = is_game_online(CURRENT_GAME_ID) + when_str = data.get("when", "").strip() + game_dt = datetime.strptime(when_str, "%d.%m.%Y") + now_date = datetime.now().date() + RUN_ONCE = True if game_dt.date() < now_date else False + if RUN_ONCE: + logger.info("Матч не Online/уже завершён — запускаю потоки в режиме ОДНОГО прохода.") + else: + logger.info("Матч в Online — работаем в циклах обновления.") + # logger.debug(data) + # data = { + # "season": 2026, + # "game_id": 921412, + # "team1_id":3059, + # "team2_id":682, + # "team1":"BETCITY PARMA", + # "team2":"Avtodor", + # } + + # Список потоков и их задач + threads = [ + threading.Thread( + target=game_online_loop, + args=(data["game_id"], stop_event), + name="OnlineLoop", + ), + threading.Thread( + target=Json_Team_Generation, + args=("team1", data, stop_event), + name="Team1JSON", + ), + threading.Thread( + target=Json_Team_Generation, + args=("team2", data, stop_event), + name="Team2JSON", + ), + threading.Thread( + target=Team_Both_Stat, args=(stop_event,), name="BothTeamsStat" + ), + threading.Thread(target=Referee, args=(stop_event,), name="Referee"), + threading.Thread( + target=Scores_Quarter, args=(stop_event,), name="QuarterScore" + ), + threading.Thread( + target=Status_Online, args=(data, stop_event), name="StatusOnline" + ), + threading.Thread( + target=Play_By_Play, args=(data, stop_event), name="PlayByPlay" + ), + threading.Thread( + target=Standing_func, args=(data, stop_event), name="Standings" + ), + ] + + # Запуск всех потоков + for t in threads: + t.start() + logger.debug(f"Поток {t.name} запущен.") + + How_To_Play_Quarter(data) + pregame_data(data) + + # try: + # while True: + # time.sleep(1) + # except KeyboardInterrupt: + # logger.info("Остановка по Ctrl+C... Завершение потоков.") + # stop_event.set() + # for t in threads: + # t.join() + # logger.debug(f"Поток {t.name} завершён.") + # logger.info("Все потоки завершены.") + + try: + if RUN_ONCE: + # 🔚 Однократный режим: ждём завершения и выходим + for t in threads: + t.join() + logger.debug(f"Поток {t.name} завершён.") + logger.info("Однократный режим: всё готово, выхожу.") + return + + # Онлайн-режим: держим процесс живым + while True: + time.sleep(1) + + except KeyboardInterrupt: + logger.info("Остановка по Ctrl+C... Завершение потоков.") + stop_event.set() + for t in threads: + t.join() + logger.debug(f"Поток {t.name} завершён.") + logger.info("Все потоки завершены.") + + +if __name__ == "__main__": + main() diff --git a/match_id.json b/match_id.json new file mode 100644 index 0000000..03f1e28 --- /dev/null +++ b/match_id.json @@ -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"} +} \ No newline at end of file diff --git a/script_team1.vb b/script_team1.vb deleted file mode 100644 index 2f08bc0..0000000 --- a/script_team1.vb +++ /dev/null @@ -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 \ No newline at end of file diff --git a/stats.py b/stats.py deleted file mode 100644 index 144ee7d..0000000 --- a/stats.py +++ /dev/null @@ -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) - diff --git a/temp.json b/temp.json deleted file mode 100644 index bd39bf3..0000000 --- a/temp.json +++ /dev/null @@ -1,11252 +0,0 @@ -{ - "IsOnline": true, - "GameStatus": 2, - "MaxPeriod": 2, - "FromDate": null, - "GameDate": "18.10.2025", - "HasTime": true, - "GameTime": "17.00", - "GameTimeMsk": "15.00", - "HasVideo": true, - "LiveID": null, - "VideoID": "\u003Ciframe src=\"https://vkvideo.ru/video_ext.php?oid=-29809500&id=456246778&autoplay=1\" width=\"100%\" height=\"450\" style=\"background-color: #000\" allow=\"autoplay; encrypted-media; fullscreen; picture-in-picture; screen-wake-lock;\" frameborder=\"0\" allowfullscreen\u003E\u003C/iframe\u003E", - "TvRu": "VK Видео, сайт Лиги ВТБ", - "TvEn": "VK Video, VTB League website", - "Online": { - "OnlineID": 0, - "GameID": 0, - "CompName1": "Regular Season", - "CompName2": "Регулярный чемпионат", - "GameDate": "/Date(1760734800000)/", - "GameTime": "/Date(1760796000000)/", - "TimeDelay": 0, - "GameNumber": "RS-023", - "RegionID": 22, - "ArenaID": 11906, - "Venue1": " ", - "Venue2": " ", - "Attendance": 0, - "PeriodCount": 4, - "PeriodExtraSeconds": 300, - "Periods": "10,10,10,10", - "Intervals": "2,15,2,2", - "PersonalFouls": 5, - "TeamFouls": "5,5,5,5", - "PlayersOnCourt": 5, - "FreeThrowValue": 1, - "FieldGoalValue": 2, - "LongShotValue": 3, - "LeftTeamNumber": 1, - "SysStatus": 1, - "SysLastChanged": "/Date(1760081305472)/", - "SysClientLastChanged": "/Date(-62135596800000)/", - "SysUser": "?" - }, - "OnlineTeams": [ - { - "OnlineTeamID": 0, - "GameID": 921412, - "TeamNumber": 0, - "TeamID": 0, - "TeamGender": 0, - "TeamName1": null, - "TeamName2": null, - "RegionName1": null, - "RegionName2": null, - "ShortName1": null, - "ShortName2": null, - "UniformNumber": 0, - "UniformType": 0, - "DominantColorARGB": "FFFFFFFF", - "SecondColorARGB": "FF000000", - "BorderColorARGB": "FFFFFFFF", - "NumberColorARGB": "FF000000", - "SysLastChanged": "/Date(1760786235211)/", - "SysStatus": 1, - "SysClientLastChanged": "/Date(-62135596800000)/", - "SysUser": "?" - }, - { - "OnlineTeamID": 0, - "GameID": 921412, - "TeamNumber": 1, - "TeamID": 3059, - "TeamGender": 0, - "TeamName1": "BETCITY PARMA", - "TeamName2": "БЕТСИТИ ПАРМА", - "RegionName1": "Perm region", - "RegionName2": "Пермский край", - "ShortName1": "BETCITY PARMA", - "ShortName2": "БЕТСИТИ ПАРМА", - "UniformNumber": 2, - "UniformType": 2, - "DominantColorARGB": "FF1B1199", - "SecondColorARGB": "FF170E62", - "BorderColorARGB": "FFEF570B", - "NumberColorARGB": "FFDA5D12", - "SysLastChanged": "/Date(1760786235591)/", - "SysStatus": 1, - "SysClientLastChanged": "/Date(-62135596800000)/", - "SysUser": "?" - }, - { - "OnlineTeamID": 0, - "GameID": 921412, - "TeamNumber": 2, - "TeamID": 682, - "TeamGender": 0, - "TeamName1": "Avtodor", - "TeamName2": "Автодор", - "RegionName1": "Saratov", - "RegionName2": "Саратов", - "ShortName1": "Avtodor", - "ShortName2": "Автодор", - "UniformNumber": 1, - "UniformType": 1, - "DominantColorARGB": "FFFFFFFF", - "SecondColorARGB": "FF000000", - "BorderColorARGB": "FF000000", - "NumberColorARGB": "FF000000", - "SysLastChanged": "/Date(1760786235602)/", - "SysStatus": 1, - "SysClientLastChanged": "/Date(-62135596800000)/", - "SysUser": "?" - } - ], - "OnlineStarts": [ - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 0, - "TeamNumber": 0, - "StartType": 5, - "PlayerNumber": 0, - "DisplayNumber": "0", - "LicenceNumber": null, - "PersonID": 0, - "PersonName1": " ", - "PersonName2": " ", - "Capitan": 0, - "PersonBirth": null, - "PersonBirthday": null, - "PosID": 0, - "CountryCodeIOC": null, - "CountryName1": null, - "CountryName2": null, - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760081305496)/", - "SysClientLastChanged": "/Date(-62135596800000)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 3, - "TeamNumber": 0, - "StartType": 4, - "PlayerNumber": 1, - "DisplayNumber": "1", - "LicenceNumber": null, - "PersonID": 126593, - "PersonName1": "Ostrovskiy Evgeniy", - "PersonName2": "Островский Евгений", - "Capitan": 0, - "PersonBirth": "18.08.1981", - "PersonBirthday": "/Date(366926400000)/", - "PosID": 101, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760081305690)/", - "SysClientLastChanged": "/Date(-62135596800000)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 4, - "TeamNumber": 0, - "StartType": 4, - "PlayerNumber": 2, - "DisplayNumber": "2", - "LicenceNumber": null, - "PersonID": 126581, - "PersonName1": "Ovinov Semen", - "PersonName2": "Овинов Семен", - "Capitan": 0, - "PersonBirth": "02.01.1979", - "PersonBirthday": "/Date(284072400000)/", - "PosID": 102, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760081305695)/", - "SysClientLastChanged": "/Date(-62135596800000)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 5, - "TeamNumber": 0, - "StartType": 4, - "PlayerNumber": 3, - "DisplayNumber": "3", - "LicenceNumber": null, - "PersonID": 126656, - "PersonName1": "Zhitlukhin Maksim", - "PersonName2": "Житлухин Максим", - "Capitan": 0, - "PersonBirth": "19.12.1986", - "PersonBirthday": "/Date(535323600000)/", - "PosID": 103, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760081305695)/", - "SysClientLastChanged": "/Date(-62135596800000)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 6, - "TeamNumber": 0, - "StartType": 4, - "PlayerNumber": 4, - "DisplayNumber": "4", - "LicenceNumber": null, - "PersonID": 126645, - "PersonName1": "Rozina Elena", - "PersonName2": "Розина Елена", - "Capitan": 0, - "PersonBirth": "30.11.1977", - "PersonBirthday": "/Date(249685200000)/", - "PosID": 104, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760081305695)/", - "SysClientLastChanged": "/Date(-62135596800000)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 43, - "TeamNumber": 0, - "StartType": 4, - "PlayerNumber": 5, - "DisplayNumber": "5", - "LicenceNumber": null, - "PersonID": 151555, - "PersonName1": "Mamaeva Mariya", - "PersonName2": "Мамаева Мария", - "Capitan": 0, - "PersonBirth": "13.10.1990", - "PersonBirthday": "/Date(655761600000)/", - "PosID": 111, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786238314)/", - "SysClientLastChanged": "/Date(1760785241977)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 45, - "TeamNumber": 0, - "StartType": 4, - "PlayerNumber": 6, - "DisplayNumber": "6", - "LicenceNumber": null, - "PersonID": 150681, - "PersonName1": "SHaykhumardanova Darya", - "PersonName2": "Шайхумарданова Дарья", - "Capitan": 0, - "PersonBirth": "19.06.1988", - "PersonBirthday": "/Date(582667200000)/", - "PosID": 112, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786238314)/", - "SysClientLastChanged": "/Date(1760785330579)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 46, - "TeamNumber": 0, - "StartType": 4, - "PlayerNumber": 7, - "DisplayNumber": "7", - "LicenceNumber": null, - "PersonID": 155871, - "PersonName1": "Zaikina Diana", - "PersonName2": "Заикина Диана", - "Capitan": 0, - "PersonBirth": "15.09.1997", - "PersonBirthday": "/Date(874267200000)/", - "PosID": 113, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786238314)/", - "SysClientLastChanged": "/Date(1760785339931)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 47, - "TeamNumber": 0, - "StartType": 4, - "PlayerNumber": 8, - "DisplayNumber": "8", - "LicenceNumber": null, - "PersonID": 126773, - "PersonName1": "Shaykhumardanov Ilya", - "PersonName2": "Шайхумарданов Илья", - "Capitan": 0, - "PersonBirth": "13.02.1985", - "PersonBirthday": "/Date(477090000000)/", - "PosID": 114, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786238315)/", - "SysClientLastChanged": "/Date(1760785349203)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 49, - "TeamNumber": 0, - "StartType": 4, - "PlayerNumber": 9, - "DisplayNumber": "9", - "LicenceNumber": null, - "PersonID": 14150, - "PersonName1": "Спиридонова Евгения", - "PersonName2": "Спиридонова Евгения", - "Capitan": 0, - "PersonBirth": "07.09.1993", - "PersonBirthday": "/Date(747345600000)/", - "PosID": 115, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786238315)/", - "SysClientLastChanged": "/Date(1760785381707)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 50, - "TeamNumber": 0, - "StartType": 4, - "PlayerNumber": 10, - "DisplayNumber": "10", - "LicenceNumber": null, - "PersonID": 14526, - "PersonName1": "Mironenko Ekaterina", - "PersonName2": "Мироненко Екатерина", - "Capitan": 0, - "PersonBirth": "24.08.1993", - "PersonBirthday": "/Date(746136000000)/", - "PosID": 120, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786238315)/", - "SysClientLastChanged": "/Date(1760785425224)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 51, - "TeamNumber": 0, - "StartType": 4, - "PlayerNumber": 11, - "DisplayNumber": "11", - "LicenceNumber": null, - "PersonID": 152618, - "PersonName1": "Zlygostev Igor", - "PersonName2": "Злыгостев Игорь", - "Capitan": 0, - "PersonBirth": "29.09.1993", - "PersonBirthday": "/Date(749246400000)/", - "PosID": 121, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786238315)/", - "SysClientLastChanged": "/Date(1760785444383)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 52, - "TeamNumber": 0, - "StartType": 4, - "PlayerNumber": 12, - "DisplayNumber": "12", - "LicenceNumber": null, - "PersonID": 151634, - "PersonName1": "Denisova Olga", - "PersonName2": "Денисова Ольга", - "Capitan": 0, - "PersonBirth": "03.01.1989", - "PersonBirthday": "/Date(599778000000)/", - "PosID": 120, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786238315)/", - "SysClientLastChanged": "/Date(1760785465711)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 48, - "TeamNumber": 0, - "StartType": 4, - "PlayerNumber": 13, - "DisplayNumber": "13", - "LicenceNumber": null, - "PersonID": 152327, - "PersonName1": "Kapatskaya Irina", - "PersonName2": "Капатская Ирина", - "Capitan": 0, - "PersonBirth": "05.07.1996", - "PersonBirthday": "/Date(836510400000)/", - "PosID": 123, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786238315)/", - "SysClientLastChanged": "/Date(1760785360138)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 22, - "TeamNumber": 1, - "StartType": 3, - "PlayerNumber": 1, - "DisplayNumber": "1", - "LicenceNumber": "051", - "PersonID": 130931, - "PersonName1": "Pashutin Evgeny", - "PersonName2": "Пашутин Евгений", - "Capitan": 0, - "PersonBirth": "06.02.1969", - "PersonBirthday": "/Date(-28436400000)/", - "PosID": 1000, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 23, - "TeamNumber": 1, - "StartType": 3, - "PlayerNumber": 2, - "DisplayNumber": "2", - "LicenceNumber": "052", - "PersonID": 128427, - "PersonName1": "Pashutin Zakhar", - "PersonName2": "Пашутин Захар", - "Capitan": 0, - "PersonBirth": "03.05.1974", - "PersonBirthday": "/Date(136756800000)/", - "PosID": 1001, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 18, - "TeamNumber": 1, - "StartType": 1, - "PlayerNumber": 2, - "DisplayNumber": "2", - "LicenceNumber": "F-138", - "PersonID": 430506, - "PersonName1": "Adams Brendan", - "PersonName2": "Адамс Брэндан", - "Capitan": 0, - "PersonBirth": "03.04.2000", - "PersonBirthday": "/Date(954705600000)/", - "PosID": 1, - "CountryCodeIOC": "US", - "CountryName1": "US", - "CountryName2": "US", - "Rank1": "", - "Rank2": "", - "Height": 193, - "Weight": 93, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 14, - "TeamNumber": 1, - "StartType": 1, - "PlayerNumber": 3, - "DisplayNumber": "3", - "LicenceNumber": "N-144", - "PersonID": 102694, - "PersonName1": "Svinin Lev", - "PersonName2": "Свинин Лев", - "Capitan": 0, - "PersonBirth": "09.10.2006", - "PersonBirthday": "/Date(1160337600000)/", - "PosID": 4, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": 206, - "Weight": 89, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 16, - "TeamNumber": 1, - "StartType": 1, - "PlayerNumber": 4, - "DisplayNumber": "4", - "LicenceNumber": "F-136", - "PersonID": 491404, - "PersonName1": "Adams Jalen", - "PersonName2": "Адамс Джейлен", - "Capitan": 0, - "PersonBirth": "11.12.1995", - "PersonBirthday": "/Date(818629200000)/", - "PosID": 1, - "CountryCodeIOC": "US", - "CountryName1": "US", - "CountryName2": "US", - "Rank1": "", - "Rank2": "", - "Height": 191, - "Weight": 88, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 15, - "TeamNumber": 1, - "StartType": 1, - "PlayerNumber": 6, - "DisplayNumber": "6", - "LicenceNumber": "F-137", - "PersonID": 432333, - "PersonName1": "Sanders Victor", - "PersonName2": "Сэндерс Виктор", - "Capitan": 0, - "PersonBirth": "16.02.1995", - "PersonBirthday": "/Date(792882000000)/", - "PosID": 2, - "CountryCodeIOC": "US", - "CountryName1": "US", - "CountryName2": "US", - "Rank1": "", - "Rank2": "", - "Height": 196, - "Weight": 90, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 53, - "TeamNumber": 1, - "StartType": 1, - "PlayerNumber": 7, - "DisplayNumber": "7", - "LicenceNumber": "N-Y-289", - "PersonID": 254110, - "PersonName1": "Golovchenko Grigory", - "PersonName2": "Головченко Григорий", - "Capitan": 0, - "PersonBirth": "28.02.2007", - "PersonBirthday": "/Date(1172610000000)/", - "PosID": 5, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786967242)/", - "SysClientLastChanged": "/Date(1760786123440)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 8, - "TeamNumber": 1, - "StartType": 1, - "PlayerNumber": 11, - "DisplayNumber": "11", - "LicenceNumber": "N-143", - "PersonID": 15638, - "PersonName1": "Ilnitskiy Stanislav", - "PersonName2": "Ильницкий Станислав", - "Capitan": 1, - "PersonBirth": "24.02.1994", - "PersonBirthday": "/Date(762037200000)/", - "PosID": 4, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": 201, - "Weight": 98, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735902)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 13, - "TeamNumber": 1, - "StartType": 1, - "PlayerNumber": 18, - "DisplayNumber": "18", - "LicenceNumber": "N-145", - "PersonID": 57610, - "PersonName1": "Stafeev Mikhail", - "PersonName2": "Стафеев Михаил", - "Capitan": 0, - "PersonBirth": "25.01.2005", - "PersonBirthday": "/Date(1106600400000)/", - "PosID": 3, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": 202, - "Weight": 102, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 19, - "TeamNumber": 1, - "StartType": 1, - "PlayerNumber": 32, - "DisplayNumber": "32", - "LicenceNumber": "F-139", - "PersonID": 491405, - "PersonName1": "Carter Terrell", - "PersonName2": "Картер Террелл", - "Capitan": 0, - "PersonBirth": "06.01.1996", - "PersonBirthday": "/Date(820875600000)/", - "PosID": 5, - "CountryCodeIOC": "US", - "CountryName1": "US", - "CountryName2": "US", - "Rank1": "", - "Rank2": "", - "Height": 208, - "Weight": 132, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 12, - "TeamNumber": 1, - "StartType": 1, - "PlayerNumber": 33, - "DisplayNumber": "33", - "LicenceNumber": "N-385", - "PersonID": 25858, - "PersonName1": "Yakushin Timofey", - "PersonName2": "Якушин Тимофей", - "Capitan": 0, - "PersonBirth": "16.01.1997", - "PersonBirthday": "/Date(853362000000)/", - "PosID": 1, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": 195, - "Weight": 90, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 10, - "TeamNumber": 1, - "StartType": 1, - "PlayerNumber": 61, - "DisplayNumber": "61", - "LicenceNumber": "N-146", - "PersonID": 52397, - "PersonName1": "Firsov Gleb", - "PersonName2": "Фирсов Глеб", - "Capitan": 0, - "PersonBirth": "17.01.2005", - "PersonBirthday": "/Date(1105909200000)/", - "PosID": 5, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": 208, - "Weight": 104, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 7, - "TeamNumber": 1, - "StartType": 1, - "PlayerNumber": 70, - "DisplayNumber": "70", - "LicenceNumber": "N-141", - "PersonID": 57608, - "PersonName1": "Egorov Ivan", - "PersonName2": "Егоров Иван", - "Capitan": 0, - "PersonBirth": "18.06.2005", - "PersonBirthday": "/Date(1119038400000)/", - "PosID": 1, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": 194, - "Weight": 86, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735902)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 9, - "TeamNumber": 1, - "StartType": 1, - "PlayerNumber": 93, - "DisplayNumber": "93", - "LicenceNumber": "N-142", - "PersonID": 15749, - "PersonName1": "Zakharov Aleksandr", - "PersonName2": "Захаров Александр", - "Capitan": 0, - "PersonBirth": "12.06.1993", - "PersonBirthday": "/Date(739828800000)/", - "PosID": 3, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": 203, - "Weight": 97, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735902)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 1, - "TeamNumber": 1, - "StartType": 0, - "PlayerNumber": 0, - "DisplayNumber": "0", - "LicenceNumber": null, - "PersonID": 0, - "PersonName1": " ", - "PersonName2": " ", - "Capitan": 0, - "PersonBirth": null, - "PersonBirthday": null, - "PosID": 0, - "CountryCodeIOC": null, - "CountryName1": null, - "CountryName2": null, - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760081305498)/", - "SysClientLastChanged": "/Date(-62135596800000)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 40, - "TeamNumber": 2, - "StartType": 3, - "PlayerNumber": 1, - "DisplayNumber": "1", - "LicenceNumber": "025", - "PersonID": 129117, - "PersonName1": "Bogicevic Milenko", - "PersonName2": "Богичевич Миленко", - "Capitan": 0, - "PersonBirth": "09.12.1976", - "PersonBirthday": "/Date(218926800000)/", - "PosID": 1000, - "CountryCodeIOC": "RS", - "CountryName1": "RS", - "CountryName2": "RS", - "Rank1": "", - "Rank2": "", - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786742313)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 41, - "TeamNumber": 2, - "StartType": 3, - "PlayerNumber": 2, - "DisplayNumber": "2", - "LicenceNumber": "026", - "PersonID": 394083, - "PersonName1": "Kulis Stipe", - "PersonName2": "Кулиш Стипе", - "Capitan": 0, - "PersonBirth": "08.01.1985", - "PersonBirthday": "/Date(473979600000)/", - "PosID": 1001, - "CountryCodeIOC": "HR", - "CountryName1": "HR", - "CountryName2": "HR", - "Rank1": "", - "Rank2": "", - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786742313)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 27, - "TeamNumber": 2, - "StartType": 1, - "PlayerNumber": 0, - "DisplayNumber": "0", - "LicenceNumber": "N-066", - "PersonID": 311124, - "PersonName1": "Sushchik Anton", - "PersonName2": "Сущик Антон", - "Capitan": 0, - "PersonBirth": "04.07.2005", - "PersonBirthday": "/Date(1120420800000)/", - "PosID": 5, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": 210, - "Weight": 105, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 28, - "TeamNumber": 2, - "StartType": 1, - "PlayerNumber": 1, - "DisplayNumber": "1", - "LicenceNumber": "N-065", - "PersonID": 51620, - "PersonName1": "Pranauskis Vitalius", - "PersonName2": "Пранаускис Виталиюс", - "Capitan": 0, - "PersonBirth": "08.12.2002", - "PersonBirthday": "/Date(1039294800000)/", - "PosID": 1, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": 195, - "Weight": 83, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 29, - "TeamNumber": 2, - "StartType": 1, - "PlayerNumber": 3, - "DisplayNumber": "3", - "LicenceNumber": "F-057", - "PersonID": 393046, - "PersonName1": "Beslac Dusan", - "PersonName2": "Беслач Душан", - "Capitan": 0, - "PersonBirth": "06.10.1998", - "PersonBirthday": "/Date(907617600000)/", - "PosID": 4, - "CountryCodeIOC": "RS", - "CountryName1": "RS", - "CountryName2": "RS", - "Rank1": "", - "Rank2": "", - "Height": 206, - "Weight": 103, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 30, - "TeamNumber": 2, - "StartType": 1, - "PlayerNumber": 4, - "DisplayNumber": "4", - "LicenceNumber": "N-061", - "PersonID": 53079, - "PersonName1": "Evseev Alexandr", - "PersonName2": "Евсеев Александр", - "Capitan": 0, - "PersonBirth": "14.02.2002", - "PersonBirthday": "/Date(1013634000000)/", - "PosID": 4, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": 205, - "Weight": 98, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 37, - "TeamNumber": 2, - "StartType": 1, - "PlayerNumber": 6, - "DisplayNumber": "6", - "LicenceNumber": "N-062", - "PersonID": 43443, - "PersonName1": "Fedorov Andrei", - "PersonName2": "Фёдоров Андрей", - "Capitan": 0, - "PersonBirth": "19.08.2003", - "PersonBirthday": "/Date(1061236800000)/", - "PosID": 3, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": 200, - "Weight": 92, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 31, - "TeamNumber": 2, - "StartType": 1, - "PlayerNumber": 8, - "DisplayNumber": "8", - "LicenceNumber": "F-060", - "PersonID": 491383, - "PersonName1": "Edwards Terrence", - "PersonName2": "Эдвардс Терренс", - "Capitan": 0, - "PersonBirth": "20.05.2002", - "PersonBirthday": "/Date(1021838400000)/", - "PosID": 2, - "CountryCodeIOC": "US", - "CountryName1": "US", - "CountryName2": "US", - "Rank1": "", - "Rank2": "", - "Height": 198, - "Weight": 93, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 38, - "TeamNumber": 2, - "StartType": 1, - "PlayerNumber": 9, - "DisplayNumber": "9", - "LicenceNumber": "N-068", - "PersonID": 26883, - "PersonName1": "Motovilov Grigory", - "PersonName2": "Мотовилов Григорий", - "Capitan": 0, - "PersonBirth": "07.02.1998", - "PersonBirthday": "/Date(886798800000)/", - "PosID": 1, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": 191, - "Weight": 88, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 32, - "TeamNumber": 2, - "StartType": 1, - "PlayerNumber": 12, - "DisplayNumber": "12", - "LicenceNumber": "N-064", - "PersonID": 33188, - "PersonName1": "Klimenko Artem", - "PersonName2": "Клименко Артем", - "Capitan": 1, - "PersonBirth": "10.01.1994", - "PersonBirthday": "/Date(758149200000)/", - "PosID": 5, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": 214, - "Weight": 114, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 33, - "TeamNumber": 2, - "StartType": 1, - "PlayerNumber": 13, - "DisplayNumber": "13", - "LicenceNumber": "N-067", - "PersonID": 40230, - "PersonName1": "Volkhin Igor", - "PersonName2": "Вольхин Игорь", - "Capitan": 0, - "PersonBirth": "30.10.1997", - "PersonBirthday": "/Date(878158800000)/", - "PosID": 3, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": 199, - "Weight": 88, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 36, - "TeamNumber": 2, - "StartType": 1, - "PlayerNumber": 24, - "DisplayNumber": "24", - "LicenceNumber": "N-063", - "PersonID": 258077, - "PersonName1": "Iakovlev Dmitrii", - "PersonName2": "Яковлев Дмитрий", - "Capitan": 0, - "PersonBirth": "12.10.2004", - "PersonBirthday": "/Date(1097524800000)/", - "PosID": 2, - "CountryCodeIOC": "RU", - "CountryName1": "RU", - "CountryName2": "RU", - "Rank1": "", - "Rank2": "", - "Height": 192, - "Weight": 80, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786735903)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 39, - "TeamNumber": 2, - "StartType": 1, - "PlayerNumber": 52, - "DisplayNumber": "52", - "LicenceNumber": "F-414", - "PersonID": 430075, - "PersonName1": "Hamilton Alex", - "PersonName2": "Хэмилтон Алекс", - "Capitan": 0, - "PersonBirth": "05.10.1993", - "PersonBirthday": "/Date(749764800000)/", - "PosID": 1, - "CountryCodeIOC": "US", - "CountryName1": "US", - "CountryName2": "US", - "Rank1": "", - "Rank2": "", - "Height": 193, - "Weight": 88, - "SysStatus": 1, - "SysLastChanged": "/Date(1760786742313)/", - "SysClientLastChanged": "/Date(1760785216377)/", - "SysUser": "?" - }, - { - "OnlineStartID": 0, - "GameID": 196330, - "StartID": 2, - "TeamNumber": 2, - "StartType": 0, - "PlayerNumber": 0, - "DisplayNumber": "0", - "LicenceNumber": null, - "PersonID": 0, - "PersonName1": " ", - "PersonName2": " ", - "Capitan": 0, - "PersonBirth": null, - "PersonBirthday": null, - "PosID": 0, - "CountryCodeIOC": null, - "CountryName1": null, - "CountryName2": null, - "Rank1": null, - "Rank2": null, - "Height": null, - "Weight": null, - "SysStatus": 1, - "SysLastChanged": "/Date(1760081305506)/", - "SysClientLastChanged": "/Date(-62135596800000)/", - "SysUser": "?" - } - ], - "OnlinePlays": [ - { - "OnlinePlayID": 0, - "GameID": 0, - "PlayID": 0, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 790, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 0, - "PlayZone": 0, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "2025-10-10T10:28:25", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:00:16", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 1, - "GameID": 0, - "PlayID": 1, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 59, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:42:02", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 2, - "GameID": 0, - "PlayID": 2, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 60, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:42:05", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 3, - "GameID": 0, - "PlayID": 3, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 21, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:47:20", - "VideoFrom": 1760788033, - "VideoTo": 1760788053 - }, - { - "OnlinePlayID": 4, - "GameID": 0, - "PlayID": 4, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 1, - "StartID": 18, - "ParentPlayID": 3, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:47:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 5, - "GameID": 0, - "PlayID": 5, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 2, - "StartID": 14, - "ParentPlayID": 3, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:47:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 6, - "GameID": 0, - "PlayID": 6, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 3, - "StartID": 15, - "ParentPlayID": 3, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:47:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 7, - "GameID": 0, - "PlayID": 7, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 4, - "StartID": 19, - "ParentPlayID": 3, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:47:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 8, - "GameID": 0, - "PlayID": 8, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 5, - "StartID": 9, - "ParentPlayID": 3, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:47:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 9, - "GameID": 0, - "PlayID": 9, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 6, - "StartID": 29, - "ParentPlayID": 3, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:47:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 10, - "GameID": 0, - "PlayID": 10, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 7, - "StartID": 31, - "ParentPlayID": 3, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:47:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 11, - "GameID": 0, - "PlayID": 11, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 8, - "StartID": 38, - "ParentPlayID": 3, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:47:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 12, - "GameID": 0, - "PlayID": 12, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 9, - "StartID": 32, - "ParentPlayID": 3, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:47:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 13, - "GameID": 0, - "PlayID": 13, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 10, - "StartID": 33, - "ParentPlayID": 3, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:47:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 14, - "GameID": 0, - "PlayID": 14, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 73, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:50:22", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 15, - "GameID": 0, - "PlayID": 15, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 61, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:53:16", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 16, - "GameID": 0, - "PlayID": 16, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 62, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:57:26", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 17, - "GameID": 0, - "PlayID": 17, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 63, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T14:58:47", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 18, - "GameID": 0, - "PlayID": 18, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 0, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:01:24", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 19, - "GameID": 0, - "PlayID": 19, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 10, - "PlaySortOrder": 0, - "StartID": 1, - "ParentPlayID": null, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:01:26", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 20, - "GameID": 0, - "PlayID": 20, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 180, - "PlaySortOrder": 0, - "StartID": 19, - "ParentPlayID": null, - "PlayTypeID": 11, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:01:42", - "VideoFrom": 1760788893, - "VideoTo": 1760788913 - }, - { - "OnlinePlayID": 21, - "GameID": 0, - "PlayID": 21, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 180, - "PlaySortOrder": 1, - "StartID": 31, - "ParentPlayID": 20, - "PlayTypeID": 26, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:01:42", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 22, - "GameID": 0, - "PlayID": 22, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 390, - "PlaySortOrder": 0, - "StartID": 33, - "ParentPlayID": null, - "PlayTypeID": 6, - "PlayZone": 10, - "PlayX": -31, - "PlayY": 74, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:03", - "VideoFrom": 1760788913, - "VideoTo": 1760788933 - }, - { - "OnlinePlayID": 23, - "GameID": 0, - "PlayID": 23, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 390, - "PlaySortOrder": 1, - "StartID": 33, - "ParentPlayID": 22, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:03", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 24, - "GameID": 0, - "PlayID": 24, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 390, - "PlaySortOrder": 2, - "StartID": 1, - "ParentPlayID": 22, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:04", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 25, - "GameID": 0, - "PlayID": 25, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 400, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:04", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 26, - "GameID": 0, - "PlayID": 26, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 400, - "PlaySortOrder": 0, - "StartID": 1, - "ParentPlayID": null, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:04", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 27, - "GameID": 0, - "PlayID": 27, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 400, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:14", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 28, - "GameID": 0, - "PlayID": 28, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 510, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:26", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 29, - "GameID": 0, - "PlayID": 29, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 510, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:29", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 30, - "GameID": 0, - "PlayID": 30, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 510, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:30", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 31, - "GameID": 0, - "PlayID": 31, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 510, - "PlaySortOrder": 0, - "StartID": 9, - "ParentPlayID": null, - "PlayTypeID": 11, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:30", - "VideoFrom": 1760788942, - "VideoTo": 1760788962 - }, - { - "OnlinePlayID": 32, - "GameID": 0, - "PlayID": 32, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 510, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:44", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 33, - "GameID": 0, - "PlayID": 33, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 620, - "PlaySortOrder": 0, - "StartID": 29, - "ParentPlayID": null, - "PlayTypeID": 6, - "PlayZone": 8, - "PlayX": 36, - "PlayY": 69, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:55", - "VideoFrom": 1760788967, - "VideoTo": 1760788987 - }, - { - "OnlinePlayID": 34, - "GameID": 0, - "PlayID": 34, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 620, - "PlaySortOrder": 1, - "StartID": 29, - "ParentPlayID": 33, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:55", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 35, - "GameID": 0, - "PlayID": 35, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 620, - "PlaySortOrder": 2, - "StartID": 38, - "ParentPlayID": 33, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:55", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 36, - "GameID": 0, - "PlayID": 36, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 620, - "PlaySortOrder": 3, - "StartID": 19, - "ParentPlayID": 33, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:56", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 37, - "GameID": 0, - "PlayID": 37, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 660, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:02:59", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 38, - "GameID": 0, - "PlayID": 38, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 660, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:03:14", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 39, - "GameID": 0, - "PlayID": 39, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 730, - "PlaySortOrder": 0, - "StartID": 14, - "ParentPlayID": null, - "PlayTypeID": 6, - "PlayZone": 11, - "PlayX": -69, - "PlayY": 4, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:03:21", - "VideoFrom": 1760788993, - "VideoTo": 1760789013 - }, - { - "OnlinePlayID": 40, - "GameID": 0, - "PlayID": 40, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 730, - "PlaySortOrder": 1, - "StartID": 14, - "ParentPlayID": 39, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:03:21", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 41, - "GameID": 0, - "PlayID": 41, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 730, - "PlaySortOrder": 2, - "StartID": 15, - "ParentPlayID": 39, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:03:21", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 42, - "GameID": 0, - "PlayID": 42, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 730, - "PlaySortOrder": 3, - "StartID": 31, - "ParentPlayID": 39, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:03:22", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 43, - "GameID": 0, - "PlayID": 43, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 760, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:03:25", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 44, - "GameID": 0, - "PlayID": 44, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 760, - "PlaySortOrder": 0, - "StartID": 15, - "ParentPlayID": null, - "PlayTypeID": 40, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:03:27", - "VideoFrom": 1760788978, - "VideoTo": 1760789008 - }, - { - "OnlinePlayID": 45, - "GameID": 0, - "PlayID": 45, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 760, - "PlaySortOrder": 1, - "StartID": 31, - "ParentPlayID": 44, - "PlayTypeID": 50, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:03:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 46, - "GameID": 0, - "PlayID": 46, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 760, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:03:36", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 47, - "GameID": 0, - "PlayID": 47, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 920, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:03:53", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 48, - "GameID": 0, - "PlayID": 48, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 920, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:03:54", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 49, - "GameID": 0, - "PlayID": 49, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 930, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:03:55", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 50, - "GameID": 0, - "PlayID": 50, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 930, - "PlaySortOrder": 0, - "StartID": 14, - "ParentPlayID": null, - "PlayTypeID": 40, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:08", - "VideoFrom": 1760789021, - "VideoTo": 1760789051 - }, - { - "OnlinePlayID": 51, - "GameID": 0, - "PlayID": 51, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 930, - "PlaySortOrder": 1, - "StartID": 32, - "ParentPlayID": 50, - "PlayTypeID": 50, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:08", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 52, - "GameID": 0, - "PlayID": 52, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 930, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:15", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 53, - "GameID": 0, - "PlayID": 53, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1010, - "PlaySortOrder": 0, - "StartID": 31, - "ParentPlayID": null, - "PlayTypeID": 5, - "PlayZone": 2, - "PlayX": -22, - "PlayY": 3, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:23", - "VideoFrom": 1760789054, - "VideoTo": 1760789074 - }, - { - "OnlinePlayID": 54, - "GameID": 0, - "PlayID": 54, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1010, - "PlaySortOrder": 1, - "StartID": 31, - "ParentPlayID": 53, - "PlayTypeID": 32, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:23", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 55, - "GameID": 0, - "PlayID": 55, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1010, - "PlaySortOrder": 2, - "StartID": 38, - "ParentPlayID": 53, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:23", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 56, - "GameID": 0, - "PlayID": 56, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1010, - "PlaySortOrder": 3, - "StartID": 9, - "ParentPlayID": 53, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:24", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 57, - "GameID": 0, - "PlayID": 57, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1070, - "PlaySortOrder": 0, - "StartID": 18, - "ParentPlayID": null, - "PlayTypeID": 5, - "PlayZone": 4, - "PlayX": 41, - "PlayY": 40, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:30", - "VideoFrom": 1760789062, - "VideoTo": 1760789082 - }, - { - "OnlinePlayID": 58, - "GameID": 0, - "PlayID": 58, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1070, - "PlaySortOrder": 1, - "StartID": 18, - "ParentPlayID": 57, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:30", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 59, - "GameID": 0, - "PlayID": 59, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1070, - "PlaySortOrder": 2, - "StartID": 32, - "ParentPlayID": 57, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:30", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 60, - "GameID": 0, - "PlayID": 60, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1130, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:36", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 61, - "GameID": 0, - "PlayID": 61, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1130, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:37", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 62, - "GameID": 0, - "PlayID": 62, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1180, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:42", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 63, - "GameID": 0, - "PlayID": 63, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1180, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:49", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 64, - "GameID": 0, - "PlayID": 64, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1180, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:50", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 65, - "GameID": 0, - "PlayID": 65, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1180, - "PlaySortOrder": 0, - "StartID": 38, - "ParentPlayID": null, - "PlayTypeID": 40, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:54", - "VideoFrom": 1760789065, - "VideoTo": 1760789095 - }, - { - "OnlinePlayID": 66, - "GameID": 0, - "PlayID": 66, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1180, - "PlaySortOrder": 1, - "StartID": 38, - "ParentPlayID": 65, - "PlayTypeID": 47, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:54", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 67, - "GameID": 0, - "PlayID": 67, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1180, - "PlaySortOrder": 2, - "StartID": 18, - "ParentPlayID": 65, - "PlayTypeID": 50, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:54", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 68, - "GameID": 0, - "PlayID": 68, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1180, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:04:58", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 69, - "GameID": 0, - "PlayID": 69, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1390, - "PlaySortOrder": 0, - "StartID": 19, - "ParentPlayID": null, - "PlayTypeID": 2, - "PlayZone": 3, - "PlayX": -4, - "PlayY": 24, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:05:20", - "VideoFrom": 1760789111, - "VideoTo": 1760789131 - }, - { - "OnlinePlayID": 70, - "GameID": 0, - "PlayID": 70, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1390, - "PlaySortOrder": 1, - "StartID": 19, - "ParentPlayID": 69, - "PlayTypeID": 35, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:05:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 71, - "GameID": 0, - "PlayID": 71, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1390, - "PlaySortOrder": 2, - "StartID": 9, - "ParentPlayID": 69, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:05:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 72, - "GameID": 0, - "PlayID": 72, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1390, - "PlaySortOrder": 3, - "StartID": 2, - "ParentPlayID": 69, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:05:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 73, - "GameID": 0, - "PlayID": 73, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1510, - "PlaySortOrder": 0, - "StartID": 33, - "ParentPlayID": null, - "PlayTypeID": 6, - "PlayZone": 7, - "PlayX": 71, - "PlayY": 12, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:05:32", - "VideoFrom": 1760789123, - "VideoTo": 1760789143 - }, - { - "OnlinePlayID": 74, - "GameID": 0, - "PlayID": 74, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1510, - "PlaySortOrder": 1, - "StartID": 33, - "ParentPlayID": 73, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:05:32", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 75, - "GameID": 0, - "PlayID": 75, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1510, - "PlaySortOrder": 2, - "StartID": 29, - "ParentPlayID": 73, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:05:32", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 76, - "GameID": 0, - "PlayID": 76, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1510, - "PlaySortOrder": 3, - "StartID": 19, - "ParentPlayID": 73, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:05:33", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 77, - "GameID": 0, - "PlayID": 77, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1680, - "PlaySortOrder": 0, - "StartID": 15, - "ParentPlayID": null, - "PlayTypeID": 6, - "PlayZone": 8, - "PlayX": 57, - "PlayY": 50, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:05:49", - "VideoFrom": 1760789141, - "VideoTo": 1760789161 - }, - { - "OnlinePlayID": 78, - "GameID": 0, - "PlayID": 78, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1680, - "PlaySortOrder": 1, - "StartID": 15, - "ParentPlayID": 77, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:05:49", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 79, - "GameID": 0, - "PlayID": 79, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1680, - "PlaySortOrder": 2, - "StartID": 19, - "ParentPlayID": 77, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:05:49", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 80, - "GameID": 0, - "PlayID": 80, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1680, - "PlaySortOrder": 3, - "StartID": 38, - "ParentPlayID": 77, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:05:50", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 81, - "GameID": 0, - "PlayID": 81, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1800, - "PlaySortOrder": 0, - "StartID": 33, - "ParentPlayID": null, - "PlayTypeID": 3, - "PlayZone": 7, - "PlayX": 72, - "PlayY": 5, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:06:01", - "VideoFrom": 1760789151, - "VideoTo": 1760789171 - }, - { - "OnlinePlayID": 82, - "GameID": 0, - "PlayID": 82, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1800, - "PlaySortOrder": 1, - "StartID": 33, - "ParentPlayID": 81, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:06:01", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 83, - "GameID": 0, - "PlayID": 83, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1800, - "PlaySortOrder": 2, - "StartID": 32, - "ParentPlayID": 81, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:06:01", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 84, - "GameID": 0, - "PlayID": 84, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1800, - "PlaySortOrder": 3, - "StartID": 1, - "ParentPlayID": 81, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:06:01", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 85, - "GameID": 0, - "PlayID": 85, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1910, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:06:12", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 86, - "GameID": 0, - "PlayID": 86, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1910, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:06:15", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 87, - "GameID": 0, - "PlayID": 87, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1910, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:06:16", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 88, - "GameID": 0, - "PlayID": 88, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1910, - "PlaySortOrder": 0, - "StartID": 38, - "ParentPlayID": null, - "PlayTypeID": 40, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:06:17", - "VideoFrom": 1760789149, - "VideoTo": 1760789179 - }, - { - "OnlinePlayID": 89, - "GameID": 0, - "PlayID": 89, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1910, - "PlaySortOrder": 1, - "StartID": 19, - "ParentPlayID": 88, - "PlayTypeID": 50, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:06:17", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 90, - "GameID": 0, - "PlayID": 90, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1910, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 7, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:06:31", - "VideoFrom": 1760789182, - "VideoTo": 1760789202 - }, - { - "OnlinePlayID": 91, - "GameID": 0, - "PlayID": 91, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1910, - "PlaySortOrder": 1, - "StartID": 39, - "ParentPlayID": 90, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:06:31", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 92, - "GameID": 0, - "PlayID": 92, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1910, - "PlaySortOrder": 2, - "StartID": 38, - "ParentPlayID": 90, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:06:31", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 93, - "GameID": 0, - "PlayID": 93, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1910, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:06:48", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 94, - "GameID": 0, - "PlayID": 94, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1960, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:06:54", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 95, - "GameID": 0, - "PlayID": 95, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 1960, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:07:13", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 96, - "GameID": 0, - "PlayID": 96, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2070, - "PlaySortOrder": 0, - "StartID": 15, - "ParentPlayID": null, - "PlayTypeID": 2, - "PlayZone": 4, - "PlayX": 40, - "PlayY": 40, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:07:24", - "VideoFrom": 1760789235, - "VideoTo": 1760789255 - }, - { - "OnlinePlayID": 97, - "GameID": 0, - "PlayID": 97, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2070, - "PlaySortOrder": 1, - "StartID": 15, - "ParentPlayID": 96, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:07:24", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 98, - "GameID": 0, - "PlayID": 98, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2070, - "PlaySortOrder": 2, - "StartID": 2, - "ParentPlayID": 96, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:07:24", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 99, - "GameID": 0, - "PlayID": 99, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2260, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:07:43", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 100, - "GameID": 0, - "PlayID": 100, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2260, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:07:44", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 101, - "GameID": 0, - "PlayID": 101, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2270, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:07:45", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 102, - "GameID": 0, - "PlayID": 102, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2270, - "PlaySortOrder": 0, - "StartID": 19, - "ParentPlayID": null, - "PlayTypeID": 40, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:07:48", - "VideoFrom": 1760789240, - "VideoTo": 1760789270 - }, - { - "OnlinePlayID": 103, - "GameID": 0, - "PlayID": 103, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2270, - "PlaySortOrder": 1, - "StartID": 31, - "ParentPlayID": 102, - "PlayTypeID": 50, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:07:48", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 104, - "GameID": 0, - "PlayID": 104, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2270, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:04", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 105, - "GameID": 0, - "PlayID": 105, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2280, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:06", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 106, - "GameID": 0, - "PlayID": 106, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2280, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:07", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 107, - "GameID": 0, - "PlayID": 107, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2370, - "PlaySortOrder": 0, - "StartID": 31, - "ParentPlayID": null, - "PlayTypeID": 6, - "PlayZone": 8, - "PlayX": 69, - "PlayY": 22, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:17", - "VideoFrom": 1760789288, - "VideoTo": 1760789308 - }, - { - "OnlinePlayID": 108, - "GameID": 0, - "PlayID": 108, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2370, - "PlaySortOrder": 1, - "StartID": 31, - "ParentPlayID": 107, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:17", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 109, - "GameID": 0, - "PlayID": 109, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2370, - "PlaySortOrder": 2, - "StartID": 33, - "ParentPlayID": 107, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:17", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 110, - "GameID": 0, - "PlayID": 110, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2370, - "PlaySortOrder": 3, - "StartID": 18, - "ParentPlayID": 107, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 111, - "GameID": 0, - "PlayID": 111, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2500, - "PlaySortOrder": 0, - "StartID": 9, - "ParentPlayID": null, - "PlayTypeID": 6, - "PlayZone": 7, - "PlayX": 70, - "PlayY": 6, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:30", - "VideoFrom": 1760789301, - "VideoTo": 1760789321 - }, - { - "OnlinePlayID": 112, - "GameID": 0, - "PlayID": 112, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2500, - "PlaySortOrder": 1, - "StartID": 9, - "ParentPlayID": 111, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:30", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 113, - "GameID": 0, - "PlayID": 113, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2500, - "PlaySortOrder": 2, - "StartID": 18, - "ParentPlayID": 111, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:30", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 114, - "GameID": 0, - "PlayID": 114, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2500, - "PlaySortOrder": 3, - "StartID": 31, - "ParentPlayID": 111, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:31", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 115, - "GameID": 0, - "PlayID": 115, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2580, - "PlaySortOrder": 0, - "StartID": 31, - "ParentPlayID": null, - "PlayTypeID": 5, - "PlayZone": 3, - "PlayX": -6, - "PlayY": 25, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:38", - "VideoFrom": 1760789309, - "VideoTo": 1760789329 - }, - { - "OnlinePlayID": 116, - "GameID": 0, - "PlayID": 116, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2580, - "PlaySortOrder": 1, - "StartID": 31, - "ParentPlayID": 115, - "PlayTypeID": 32, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:38", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 117, - "GameID": 0, - "PlayID": 117, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2580, - "PlaySortOrder": 2, - "StartID": 31, - "ParentPlayID": 115, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:39", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 118, - "GameID": 0, - "PlayID": 118, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2620, - "PlaySortOrder": 0, - "StartID": 31, - "ParentPlayID": null, - "PlayTypeID": 5, - "PlayZone": 3, - "PlayX": -6, - "PlayY": 32, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:43", - "VideoFrom": 1760789315, - "VideoTo": 1760789335 - }, - { - "OnlinePlayID": 119, - "GameID": 0, - "PlayID": 119, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2620, - "PlaySortOrder": 1, - "StartID": 31, - "ParentPlayID": 118, - "PlayTypeID": 33, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:43", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 120, - "GameID": 0, - "PlayID": 120, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2620, - "PlaySortOrder": 2, - "StartID": 32, - "ParentPlayID": 118, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:43", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 121, - "GameID": 0, - "PlayID": 121, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2640, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:44", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 122, - "GameID": 0, - "PlayID": 122, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2640, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 7, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:51", - "VideoFrom": 1760789322, - "VideoTo": 1760789342 - }, - { - "OnlinePlayID": 123, - "GameID": 0, - "PlayID": 123, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2640, - "PlaySortOrder": 1, - "StartID": 16, - "ParentPlayID": 122, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:51", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 124, - "GameID": 0, - "PlayID": 124, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2640, - "PlaySortOrder": 2, - "StartID": 14, - "ParentPlayID": 122, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:08:51", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 125, - "GameID": 0, - "PlayID": 125, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2640, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:09:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 126, - "GameID": 0, - "PlayID": 126, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2800, - "PlaySortOrder": 0, - "StartID": 33, - "ParentPlayID": null, - "PlayTypeID": 2, - "PlayZone": 5, - "PlayX": 10, - "PlayY": 61, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:09:37", - "VideoFrom": 1760789368, - "VideoTo": 1760789388 - }, - { - "OnlinePlayID": 127, - "GameID": 0, - "PlayID": 127, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2800, - "PlaySortOrder": 1, - "StartID": 33, - "ParentPlayID": 126, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:09:37", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 128, - "GameID": 0, - "PlayID": 128, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2800, - "PlaySortOrder": 2, - "StartID": 39, - "ParentPlayID": 126, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:09:37", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 129, - "GameID": 0, - "PlayID": 129, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2800, - "PlaySortOrder": 3, - "StartID": 1, - "ParentPlayID": 126, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:09:37", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 130, - "GameID": 0, - "PlayID": 130, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2900, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:09:47", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 131, - "GameID": 0, - "PlayID": 131, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2900, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:09:47", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 132, - "GameID": 0, - "PlayID": 132, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2900, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:09:48", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 133, - "GameID": 0, - "PlayID": 133, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2900, - "PlaySortOrder": 0, - "StartID": 31, - "ParentPlayID": null, - "PlayTypeID": 40, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:09:51", - "VideoFrom": 1760789364, - "VideoTo": 1760789394 - }, - { - "OnlinePlayID": 134, - "GameID": 0, - "PlayID": 134, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2900, - "PlaySortOrder": 1, - "StartID": 15, - "ParentPlayID": 133, - "PlayTypeID": 50, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:09:51", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 135, - "GameID": 0, - "PlayID": 135, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 2900, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:10:03", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 136, - "GameID": 0, - "PlayID": 136, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3010, - "PlaySortOrder": 0, - "StartID": 19, - "ParentPlayID": null, - "PlayTypeID": 2, - "PlayZone": 5, - "PlayX": 9, - "PlayY": 51, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:10:14", - "VideoFrom": 1760789407, - "VideoTo": 1760789427 - }, - { - "OnlinePlayID": 137, - "GameID": 0, - "PlayID": 137, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3010, - "PlaySortOrder": 1, - "StartID": 19, - "ParentPlayID": 136, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:10:14", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 138, - "GameID": 0, - "PlayID": 138, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3010, - "PlaySortOrder": 2, - "StartID": 18, - "ParentPlayID": 136, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:10:14", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 139, - "GameID": 0, - "PlayID": 139, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3010, - "PlaySortOrder": 3, - "StartID": 2, - "ParentPlayID": 136, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:10:14", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 140, - "GameID": 0, - "PlayID": 140, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3220, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:10:36", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 141, - "GameID": 0, - "PlayID": 141, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3220, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:10:36", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 142, - "GameID": 0, - "PlayID": 142, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3220, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:10:37", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 143, - "GameID": 0, - "PlayID": 143, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3220, - "PlaySortOrder": 0, - "StartID": 31, - "ParentPlayID": null, - "PlayTypeID": 12, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:10:38", - "VideoFrom": 1760789429, - "VideoTo": 1760789449 - }, - { - "OnlinePlayID": 144, - "GameID": 0, - "PlayID": 144, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3220, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:10:56", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 145, - "GameID": 0, - "PlayID": 145, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3380, - "PlaySortOrder": 0, - "StartID": 16, - "ParentPlayID": null, - "PlayTypeID": 20, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:12", - "VideoFrom": 1760789462, - "VideoTo": 1760789482 - }, - { - "OnlinePlayID": 146, - "GameID": 0, - "PlayID": 146, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3380, - "PlaySortOrder": 1, - "StartID": 39, - "ParentPlayID": 145, - "PlayTypeID": 26, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:12", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 147, - "GameID": 0, - "PlayID": 147, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3440, - "PlaySortOrder": 0, - "StartID": 33, - "ParentPlayID": null, - "PlayTypeID": 6, - "PlayZone": 8, - "PlayX": 49, - "PlayY": 52, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:19", - "VideoFrom": 1760789470, - "VideoTo": 1760789490 - }, - { - "OnlinePlayID": 148, - "GameID": 0, - "PlayID": 148, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3440, - "PlaySortOrder": 1, - "StartID": 33, - "ParentPlayID": 147, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:19", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 149, - "GameID": 0, - "PlayID": 149, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3440, - "PlaySortOrder": 2, - "StartID": 2, - "ParentPlayID": 147, - "PlayTypeID": 29, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:19", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 150, - "GameID": 0, - "PlayID": 150, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3440, - "PlaySortOrder": 3, - "StartID": 31, - "ParentPlayID": 147, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 151, - "GameID": 0, - "PlayID": 151, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3530, - "PlaySortOrder": 0, - "StartID": 33, - "ParentPlayID": null, - "PlayTypeID": 11, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:27", - "VideoFrom": 1760789478, - "VideoTo": 1760789498 - }, - { - "OnlinePlayID": 152, - "GameID": 0, - "PlayID": 152, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3530, - "PlaySortOrder": 1, - "StartID": 15, - "ParentPlayID": 151, - "PlayTypeID": 26, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 153, - "GameID": 0, - "PlayID": 153, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3580, - "PlaySortOrder": 0, - "StartID": 15, - "ParentPlayID": null, - "PlayTypeID": 2, - "PlayZone": 2, - "PlayX": -13, - "PlayY": 7, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:32", - "VideoFrom": 1760789483, - "VideoTo": 1760789503 - }, - { - "OnlinePlayID": 154, - "GameID": 0, - "PlayID": 154, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3580, - "PlaySortOrder": 1, - "StartID": 15, - "ParentPlayID": 153, - "PlayTypeID": 32, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:32", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 155, - "GameID": 0, - "PlayID": 155, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3580, - "PlaySortOrder": 2, - "StartID": 1, - "ParentPlayID": 153, - "PlayTypeID": 29, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:32", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 156, - "GameID": 0, - "PlayID": 156, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3580, - "PlaySortOrder": 3, - "StartID": 2, - "ParentPlayID": 153, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:32", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 157, - "GameID": 0, - "PlayID": 157, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3760, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:50", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 158, - "GameID": 0, - "PlayID": 158, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3760, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:51", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 159, - "GameID": 0, - "PlayID": 159, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3760, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:52", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 160, - "GameID": 0, - "PlayID": 160, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3760, - "PlaySortOrder": 0, - "StartID": 39, - "ParentPlayID": null, - "PlayTypeID": 11, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:11:52", - "VideoFrom": 1760789503, - "VideoTo": 1760789523 - }, - { - "OnlinePlayID": 161, - "GameID": 0, - "PlayID": 161, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3760, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 7, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:12:07", - "VideoFrom": 1760789519, - "VideoTo": 1760789539 - }, - { - "OnlinePlayID": 162, - "GameID": 0, - "PlayID": 162, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3760, - "PlaySortOrder": 1, - "StartID": 30, - "ParentPlayID": 161, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:12:07", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 163, - "GameID": 0, - "PlayID": 163, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3760, - "PlaySortOrder": 2, - "StartID": 32, - "ParentPlayID": 161, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:12:07", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 164, - "GameID": 0, - "PlayID": 164, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3760, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:12:14", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 165, - "GameID": 0, - "PlayID": 165, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3820, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:12:21", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 166, - "GameID": 0, - "PlayID": 166, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3820, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:12:21", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 167, - "GameID": 0, - "PlayID": 167, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3820, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:12:22", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 168, - "GameID": 0, - "PlayID": 168, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3820, - "PlaySortOrder": 0, - "StartID": 18, - "ParentPlayID": null, - "PlayTypeID": 20, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:12:24", - "VideoFrom": 1760789537, - "VideoTo": 1760789557 - }, - { - "OnlinePlayID": 169, - "GameID": 0, - "PlayID": 169, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3820, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:12:33", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 170, - "GameID": 0, - "PlayID": 170, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3980, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:12:49", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 171, - "GameID": 0, - "PlayID": 171, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3980, - "PlaySortOrder": 0, - "StartID": 2, - "ParentPlayID": null, - "PlayTypeID": 19, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:12:51", - "VideoFrom": 1760789562, - "VideoTo": 1760789582 - }, - { - "OnlinePlayID": 172, - "GameID": 0, - "PlayID": 172, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 3980, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:13:14", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 173, - "GameID": 0, - "PlayID": 173, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4000, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:13:16", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 174, - "GameID": 0, - "PlayID": 174, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4000, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:13:16", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 175, - "GameID": 0, - "PlayID": 175, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4120, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:13:30", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 176, - "GameID": 0, - "PlayID": 176, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4120, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:13:31", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 177, - "GameID": 0, - "PlayID": 177, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4120, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:13:31", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 178, - "GameID": 0, - "PlayID": 178, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4120, - "PlaySortOrder": 0, - "StartID": 30, - "ParentPlayID": null, - "PlayTypeID": 40, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:13:36", - "VideoFrom": 1760789588, - "VideoTo": 1760789618 - }, - { - "OnlinePlayID": 179, - "GameID": 0, - "PlayID": 179, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4120, - "PlaySortOrder": 1, - "StartID": 19, - "ParentPlayID": 178, - "PlayTypeID": 50, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:13:36", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 180, - "GameID": 0, - "PlayID": 180, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4120, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:13:51", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 181, - "GameID": 0, - "PlayID": 181, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4120, - "PlaySortOrder": 0, - "StartID": 18, - "ParentPlayID": null, - "PlayTypeID": 11, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:13:52", - "VideoFrom": 1760789624, - "VideoTo": 1760789644 - }, - { - "OnlinePlayID": 182, - "GameID": 0, - "PlayID": 182, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4130, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:13:52", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 183, - "GameID": 0, - "PlayID": 183, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4130, - "PlaySortOrder": 0, - "StartID": 1, - "ParentPlayID": null, - "PlayTypeID": 72, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:14:09", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 184, - "GameID": 0, - "PlayID": 184, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4130, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 7, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:15:15", - "VideoFrom": 1760789707, - "VideoTo": 1760789727 - }, - { - "OnlinePlayID": 185, - "GameID": 0, - "PlayID": 185, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4130, - "PlaySortOrder": 1, - "StartID": 12, - "ParentPlayID": 184, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:15:15", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 186, - "GameID": 0, - "PlayID": 186, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4130, - "PlaySortOrder": 2, - "StartID": 18, - "ParentPlayID": 184, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:15:15", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 187, - "GameID": 0, - "PlayID": 187, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4130, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:15:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 188, - "GameID": 0, - "PlayID": 188, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4230, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:15:30", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 189, - "GameID": 0, - "PlayID": 189, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4230, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:15:32", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 190, - "GameID": 0, - "PlayID": 190, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4230, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:15:33", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 191, - "GameID": 0, - "PlayID": 191, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4230, - "PlaySortOrder": 0, - "StartID": 12, - "ParentPlayID": null, - "PlayTypeID": 40, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:15:39", - "VideoFrom": 1760789710, - "VideoTo": 1760789740 - }, - { - "OnlinePlayID": 192, - "GameID": 0, - "PlayID": 192, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4230, - "PlaySortOrder": 1, - "StartID": 39, - "ParentPlayID": 191, - "PlayTypeID": 52, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:15:39", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 193, - "GameID": 0, - "PlayID": 193, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4230, - "PlaySortOrder": 0, - "StartID": 39, - "ParentPlayID": null, - "PlayTypeID": 1, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:15:50", - "VideoFrom": 1760789740, - "VideoTo": 1760789760 - }, - { - "OnlinePlayID": 194, - "GameID": 0, - "PlayID": 194, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4230, - "PlaySortOrder": 0, - "StartID": 39, - "ParentPlayID": null, - "PlayTypeID": 1, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:02", - "VideoFrom": 1760789753, - "VideoTo": 1760789773 - }, - { - "OnlinePlayID": 195, - "GameID": 0, - "PlayID": 195, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4230, - "PlaySortOrder": 1, - "StartID": 1, - "ParentPlayID": 194, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:02", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 196, - "GameID": 0, - "PlayID": 196, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4230, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:08", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 197, - "GameID": 0, - "PlayID": 197, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4410, - "PlaySortOrder": 0, - "StartID": 9, - "ParentPlayID": null, - "PlayTypeID": 5, - "PlayZone": 4, - "PlayX": 47, - "PlayY": 5, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:27", - "VideoFrom": 1760789778, - "VideoTo": 1760789798 - }, - { - "OnlinePlayID": 198, - "GameID": 0, - "PlayID": 198, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4410, - "PlaySortOrder": 1, - "StartID": 9, - "ParentPlayID": 197, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 199, - "GameID": 0, - "PlayID": 199, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4410, - "PlaySortOrder": 2, - "StartID": 12, - "ParentPlayID": 197, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 200, - "GameID": 0, - "PlayID": 200, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4410, - "PlaySortOrder": 3, - "StartID": 19, - "ParentPlayID": 197, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 201, - "GameID": 0, - "PlayID": 201, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4460, - "PlaySortOrder": 0, - "StartID": 9, - "ParentPlayID": null, - "PlayTypeID": 2, - "PlayZone": 2, - "PlayX": -14, - "PlayY": 7, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:32", - "VideoFrom": 1760789783, - "VideoTo": 1760789803 - }, - { - "OnlinePlayID": 202, - "GameID": 0, - "PlayID": 202, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4460, - "PlaySortOrder": 1, - "StartID": 9, - "ParentPlayID": 201, - "PlayTypeID": 32, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:32", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 203, - "GameID": 0, - "PlayID": 203, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4460, - "PlaySortOrder": 2, - "StartID": 19, - "ParentPlayID": 201, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:32", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 204, - "GameID": 0, - "PlayID": 204, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4460, - "PlaySortOrder": 3, - "StartID": 2, - "ParentPlayID": 201, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:32", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 205, - "GameID": 0, - "PlayID": 205, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4590, - "PlaySortOrder": 0, - "StartID": 30, - "ParentPlayID": null, - "PlayTypeID": 6, - "PlayZone": 8, - "PlayX": 44, - "PlayY": 59, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:45", - "VideoFrom": 1760789796, - "VideoTo": 1760789816 - }, - { - "OnlinePlayID": 206, - "GameID": 0, - "PlayID": 206, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4590, - "PlaySortOrder": 1, - "StartID": 30, - "ParentPlayID": 205, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:45", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 207, - "GameID": 0, - "PlayID": 207, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4590, - "PlaySortOrder": 2, - "StartID": 33, - "ParentPlayID": 205, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:45", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 208, - "GameID": 0, - "PlayID": 208, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4610, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:46", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 209, - "GameID": 0, - "PlayID": 209, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4590, - "PlaySortOrder": 3, - "StartID": 2, - "ParentPlayID": 205, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:48", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 210, - "GameID": 0, - "PlayID": 210, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4610, - "PlaySortOrder": 0, - "StartID": 2, - "ParentPlayID": null, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:16:49", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 211, - "GameID": 0, - "PlayID": 211, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4610, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 7, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:17:01", - "VideoFrom": 1760789812, - "VideoTo": 1760789832 - }, - { - "OnlinePlayID": 212, - "GameID": 0, - "PlayID": 212, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4610, - "PlaySortOrder": 1, - "StartID": 28, - "ParentPlayID": 211, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:17:01", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 213, - "GameID": 0, - "PlayID": 213, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4610, - "PlaySortOrder": 2, - "StartID": 33, - "ParentPlayID": 211, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:17:01", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 214, - "GameID": 0, - "PlayID": 214, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4610, - "PlaySortOrder": 3, - "StartID": 8, - "ParentPlayID": 211, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:17:05", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 215, - "GameID": 0, - "PlayID": 215, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4610, - "PlaySortOrder": 4, - "StartID": 9, - "ParentPlayID": 211, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:17:05", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 216, - "GameID": 0, - "PlayID": 216, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4610, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:17:14", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 217, - "GameID": 0, - "PlayID": 217, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4710, - "PlaySortOrder": 0, - "StartID": 39, - "ParentPlayID": null, - "PlayTypeID": 2, - "PlayZone": 1, - "PlayX": 17, - "PlayY": 7, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:17:24", - "VideoFrom": 1760789835, - "VideoTo": 1760789855 - }, - { - "OnlinePlayID": 218, - "GameID": 0, - "PlayID": 218, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4710, - "PlaySortOrder": 1, - "StartID": 39, - "ParentPlayID": 217, - "PlayTypeID": 32, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:17:24", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 219, - "GameID": 0, - "PlayID": 219, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4710, - "PlaySortOrder": 2, - "StartID": 1, - "ParentPlayID": 217, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:17:25", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 220, - "GameID": 0, - "PlayID": 220, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4890, - "PlaySortOrder": 0, - "StartID": 16, - "ParentPlayID": null, - "PlayTypeID": 3, - "PlayZone": 8, - "PlayX": 67, - "PlayY": 25, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:17:43", - "VideoFrom": 1760789855, - "VideoTo": 1760789875 - }, - { - "OnlinePlayID": 221, - "GameID": 0, - "PlayID": 221, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4890, - "PlaySortOrder": 1, - "StartID": 16, - "ParentPlayID": 220, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:17:43", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 222, - "GameID": 0, - "PlayID": 222, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 4890, - "PlaySortOrder": 2, - "StartID": 2, - "ParentPlayID": 220, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:17:43", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 223, - "GameID": 0, - "PlayID": 223, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5080, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:02", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 224, - "GameID": 0, - "PlayID": 224, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5080, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:04", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 225, - "GameID": 0, - "PlayID": 225, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5080, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:05", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 226, - "GameID": 0, - "PlayID": 226, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5080, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:12", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 227, - "GameID": 0, - "PlayID": 227, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5080, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:13", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 228, - "GameID": 0, - "PlayID": 228, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5080, - "PlaySortOrder": 0, - "StartID": 30, - "ParentPlayID": null, - "PlayTypeID": 40, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:14", - "VideoFrom": 1760789866, - "VideoTo": 1760789896 - }, - { - "OnlinePlayID": 229, - "GameID": 0, - "PlayID": 229, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5080, - "PlaySortOrder": 1, - "StartID": 30, - "ParentPlayID": 228, - "PlayTypeID": 47, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:14", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 230, - "GameID": 0, - "PlayID": 230, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5080, - "PlaySortOrder": 2, - "StartID": 15, - "ParentPlayID": 228, - "PlayTypeID": 50, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:14", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 231, - "GameID": 0, - "PlayID": 231, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5080, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 7, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:22", - "VideoFrom": 1760789894, - "VideoTo": 1760789914 - }, - { - "OnlinePlayID": 232, - "GameID": 0, - "PlayID": 232, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5080, - "PlaySortOrder": 1, - "StartID": 18, - "ParentPlayID": 231, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:22", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 233, - "GameID": 0, - "PlayID": 233, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5080, - "PlaySortOrder": 2, - "StartID": 14, - "ParentPlayID": 231, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:22", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 234, - "GameID": 0, - "PlayID": 234, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5080, - "PlaySortOrder": 3, - "StartID": 15, - "ParentPlayID": 231, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:22", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 235, - "GameID": 0, - "PlayID": 235, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5080, - "PlaySortOrder": 4, - "StartID": 12, - "ParentPlayID": 231, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:22", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 236, - "GameID": 0, - "PlayID": 236, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5080, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 237, - "GameID": 0, - "PlayID": 237, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5230, - "PlaySortOrder": 0, - "StartID": 19, - "ParentPlayID": null, - "PlayTypeID": 5, - "PlayZone": 2, - "PlayX": -19, - "PlayY": 10, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:42", - "VideoFrom": 1760789914, - "VideoTo": 1760789934 - }, - { - "OnlinePlayID": 238, - "GameID": 0, - "PlayID": 238, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5230, - "PlaySortOrder": 1, - "StartID": 19, - "ParentPlayID": 237, - "PlayTypeID": 32, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:42", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 239, - "GameID": 0, - "PlayID": 239, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5230, - "PlaySortOrder": 2, - "StartID": 18, - "ParentPlayID": 237, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:42", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 240, - "GameID": 0, - "PlayID": 240, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5230, - "PlaySortOrder": 3, - "StartID": 14, - "ParentPlayID": 237, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:43", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 241, - "GameID": 0, - "PlayID": 241, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5260, - "PlaySortOrder": 0, - "StartID": 14, - "ParentPlayID": null, - "PlayTypeID": 2, - "PlayZone": 1, - "PlayX": 13, - "PlayY": 6, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:45", - "VideoFrom": 1760789917, - "VideoTo": 1760789937 - }, - { - "OnlinePlayID": 242, - "GameID": 0, - "PlayID": 242, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5260, - "PlaySortOrder": 1, - "StartID": 14, - "ParentPlayID": 241, - "PlayTypeID": 33, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:45", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 243, - "GameID": 0, - "PlayID": 243, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5260, - "PlaySortOrder": 2, - "StartID": 14, - "ParentPlayID": 241, - "PlayTypeID": 30, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:45", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 244, - "GameID": 0, - "PlayID": 244, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5260, - "PlaySortOrder": 3, - "StartID": 2, - "ParentPlayID": 241, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:18:45", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 245, - "GameID": 0, - "PlayID": 245, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5460, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:19:05", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 246, - "GameID": 0, - "PlayID": 246, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5460, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:19:06", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 247, - "GameID": 0, - "PlayID": 247, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5460, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:19:07", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 248, - "GameID": 0, - "PlayID": 248, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5460, - "PlaySortOrder": 0, - "StartID": 19, - "ParentPlayID": null, - "PlayTypeID": 40, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:19:11", - "VideoFrom": 1760789922, - "VideoTo": 1760789952 - }, - { - "OnlinePlayID": 249, - "GameID": 0, - "PlayID": 249, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5460, - "PlaySortOrder": 1, - "StartID": 29, - "ParentPlayID": 248, - "PlayTypeID": 52, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:19:11", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 250, - "GameID": 0, - "PlayID": 250, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5460, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 7, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:19:16", - "VideoFrom": 1760789947, - "VideoTo": 1760789967 - }, - { - "OnlinePlayID": 251, - "GameID": 0, - "PlayID": 251, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5460, - "PlaySortOrder": 1, - "StartID": 32, - "ParentPlayID": 250, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:19:16", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 252, - "GameID": 0, - "PlayID": 252, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5460, - "PlaySortOrder": 2, - "StartID": 30, - "ParentPlayID": 250, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:19:16", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 253, - "GameID": 0, - "PlayID": 253, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5460, - "PlaySortOrder": 3, - "StartID": 10, - "ParentPlayID": 250, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:19:23", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 254, - "GameID": 0, - "PlayID": 254, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5460, - "PlaySortOrder": 4, - "StartID": 19, - "ParentPlayID": 250, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:19:23", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 255, - "GameID": 0, - "PlayID": 255, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5460, - "PlaySortOrder": 0, - "StartID": 29, - "ParentPlayID": null, - "PlayTypeID": 1, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:19:34", - "VideoFrom": 1760789965, - "VideoTo": 1760789985 - }, - { - "OnlinePlayID": 256, - "GameID": 0, - "PlayID": 256, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5460, - "PlaySortOrder": 0, - "StartID": 29, - "ParentPlayID": null, - "PlayTypeID": 1, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:19:47", - "VideoFrom": 1760789978, - "VideoTo": 1760789998 - }, - { - "OnlinePlayID": 257, - "GameID": 0, - "PlayID": 257, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5460, - "PlaySortOrder": 1, - "StartID": 1, - "ParentPlayID": 256, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:19:48", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 258, - "GameID": 0, - "PlayID": 258, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5460, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:19:52", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 259, - "GameID": 0, - "PlayID": 259, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5680, - "PlaySortOrder": 0, - "StartID": 18, - "ParentPlayID": null, - "PlayTypeID": 3, - "PlayZone": 7, - "PlayX": 70, - "PlayY": 4, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:20:14", - "VideoFrom": 1760790006, - "VideoTo": 1760790026 - }, - { - "OnlinePlayID": 260, - "GameID": 0, - "PlayID": 260, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5680, - "PlaySortOrder": 1, - "StartID": 18, - "ParentPlayID": 259, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:20:14", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 261, - "GameID": 0, - "PlayID": 261, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5680, - "PlaySortOrder": 2, - "StartID": 2, - "ParentPlayID": 259, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:20:14", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 262, - "GameID": 0, - "PlayID": 262, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5730, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:20:20", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 263, - "GameID": 0, - "PlayID": 263, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5730, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:20:28", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 264, - "GameID": 0, - "PlayID": 264, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5730, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:20:29", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 265, - "GameID": 0, - "PlayID": 265, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5730, - "PlaySortOrder": 0, - "StartID": 39, - "ParentPlayID": null, - "PlayTypeID": 2, - "PlayZone": 2, - "PlayX": -12, - "PlayY": 7, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:20:35", - "VideoFrom": 1760790027, - "VideoTo": 1760790047 - }, - { - "OnlinePlayID": 266, - "GameID": 0, - "PlayID": 266, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5730, - "PlaySortOrder": 1, - "StartID": 39, - "ParentPlayID": 265, - "PlayTypeID": 32, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:20:35", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 267, - "GameID": 0, - "PlayID": 267, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5730, - "PlaySortOrder": 0, - "StartID": 8, - "ParentPlayID": null, - "PlayTypeID": 40, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:20:35", - "VideoFrom": 1760790007, - "VideoTo": 1760790037 - }, - { - "OnlinePlayID": 268, - "GameID": 0, - "PlayID": 268, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5730, - "PlaySortOrder": 1, - "StartID": 39, - "ParentPlayID": 267, - "PlayTypeID": 51, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:20:35", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 269, - "GameID": 0, - "PlayID": 269, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5730, - "PlaySortOrder": 0, - "StartID": 39, - "ParentPlayID": null, - "PlayTypeID": 1, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:20:52", - "VideoFrom": 1760790044, - "VideoTo": 1760790064 - }, - { - "OnlinePlayID": 270, - "GameID": 0, - "PlayID": 270, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5730, - "PlaySortOrder": 1, - "StartID": 1, - "ParentPlayID": 269, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:20:52", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 271, - "GameID": 0, - "PlayID": 271, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5730, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 7, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:02", - "VideoFrom": 1760790055, - "VideoTo": 1760790075 - }, - { - "OnlinePlayID": 272, - "GameID": 0, - "PlayID": 272, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5730, - "PlaySortOrder": 1, - "StartID": 37, - "ParentPlayID": 271, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:02", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 273, - "GameID": 0, - "PlayID": 273, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5730, - "PlaySortOrder": 2, - "StartID": 33, - "ParentPlayID": 271, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:02", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 274, - "GameID": 0, - "PlayID": 274, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5730, - "PlaySortOrder": 3, - "StartID": 32, - "ParentPlayID": 271, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:02", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 275, - "GameID": 0, - "PlayID": 275, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5730, - "PlaySortOrder": 4, - "StartID": 39, - "ParentPlayID": 271, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:02", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 276, - "GameID": 0, - "PlayID": 276, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5730, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:12", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 277, - "GameID": 0, - "PlayID": 277, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5890, - "PlaySortOrder": 0, - "StartID": 10, - "ParentPlayID": null, - "PlayTypeID": 2, - "PlayZone": 3, - "PlayX": -12, - "PlayY": 25, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:28", - "VideoFrom": 1760790080, - "VideoTo": 1760790100 - }, - { - "OnlinePlayID": 278, - "GameID": 0, - "PlayID": 278, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5890, - "PlaySortOrder": 1, - "StartID": 10, - "ParentPlayID": 277, - "PlayTypeID": 32, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:28", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 279, - "GameID": 0, - "PlayID": 279, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5890, - "PlaySortOrder": 2, - "StartID": 16, - "ParentPlayID": 277, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:28", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 280, - "GameID": 0, - "PlayID": 280, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 5890, - "PlaySortOrder": 3, - "StartID": 2, - "ParentPlayID": 277, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:28", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 281, - "GameID": 0, - "PlayID": 281, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:39", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 282, - "GameID": 0, - "PlayID": 282, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 0, - "StartID": 29, - "ParentPlayID": null, - "PlayTypeID": 6, - "PlayZone": 9, - "PlayX": 5, - "PlayY": 76, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:40", - "VideoFrom": 1760790093, - "VideoTo": 1760790113 - }, - { - "OnlinePlayID": 283, - "GameID": 0, - "PlayID": 283, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 1, - "StartID": 29, - "ParentPlayID": 282, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:40", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 284, - "GameID": 0, - "PlayID": 284, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:40", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 285, - "GameID": 0, - "PlayID": 285, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 2, - "StartID": 33, - "ParentPlayID": 282, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:41", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 286, - "GameID": 0, - "PlayID": 286, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 0, - "StartID": 33, - "ParentPlayID": null, - "PlayTypeID": 5, - "PlayZone": 4, - "PlayX": 49, - "PlayY": 4, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:45", - "VideoFrom": 1760790098, - "VideoTo": 1760790118 - }, - { - "OnlinePlayID": 287, - "GameID": 0, - "PlayID": 287, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 1, - "StartID": 33, - "ParentPlayID": 286, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:45", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 288, - "GameID": 0, - "PlayID": 288, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 22, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:57", - "VideoFrom": 1760790109, - "VideoTo": 1760790129 - }, - { - "OnlinePlayID": 289, - "GameID": 0, - "PlayID": 289, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 1, - "StartID": 18, - "ParentPlayID": 288, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:57", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 290, - "GameID": 0, - "PlayID": 290, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 2, - "StartID": 14, - "ParentPlayID": 288, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:57", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 291, - "GameID": 0, - "PlayID": 291, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 3, - "StartID": 16, - "ParentPlayID": 288, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:57", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 292, - "GameID": 0, - "PlayID": 292, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 4, - "StartID": 8, - "ParentPlayID": 288, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:57", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 293, - "GameID": 0, - "PlayID": 293, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 5, - "StartID": 10, - "ParentPlayID": 288, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:57", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 294, - "GameID": 0, - "PlayID": 294, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 6, - "StartID": 28, - "ParentPlayID": 288, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:57", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 295, - "GameID": 0, - "PlayID": 295, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 7, - "StartID": 29, - "ParentPlayID": 288, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:57", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 296, - "GameID": 0, - "PlayID": 296, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 8, - "StartID": 37, - "ParentPlayID": 288, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:57", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 297, - "GameID": 0, - "PlayID": 297, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 9, - "StartID": 31, - "ParentPlayID": 288, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:57", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 298, - "GameID": 0, - "PlayID": 298, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 10, - "StartID": 33, - "ParentPlayID": 288, - "PlayTypeID": 9, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:57", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 299, - "GameID": 0, - "PlayID": 299, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:21:58", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 300, - "GameID": 0, - "PlayID": 300, - "PlayFlag": 0, - "PlayPeriod": 1, - "PlaySecond": 6000, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 69, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:22:56", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 301, - "GameID": 0, - "PlayID": 301, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 0, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 21, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:23:27", - "VideoFrom": 1760790199, - "VideoTo": 1760790219 - }, - { - "OnlinePlayID": 302, - "GameID": 0, - "PlayID": 302, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 0, - "PlaySortOrder": 1, - "StartID": 18, - "ParentPlayID": 301, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:23:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 303, - "GameID": 0, - "PlayID": 303, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 0, - "PlaySortOrder": 2, - "StartID": 14, - "ParentPlayID": 301, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:23:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 304, - "GameID": 0, - "PlayID": 304, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 0, - "PlaySortOrder": 3, - "StartID": 16, - "ParentPlayID": 301, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:23:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 305, - "GameID": 0, - "PlayID": 305, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 0, - "PlaySortOrder": 4, - "StartID": 8, - "ParentPlayID": 301, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:23:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 306, - "GameID": 0, - "PlayID": 306, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 0, - "PlaySortOrder": 5, - "StartID": 10, - "ParentPlayID": 301, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:23:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 307, - "GameID": 0, - "PlayID": 307, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 0, - "PlaySortOrder": 6, - "StartID": 28, - "ParentPlayID": 301, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:23:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 308, - "GameID": 0, - "PlayID": 308, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 0, - "PlaySortOrder": 7, - "StartID": 29, - "ParentPlayID": 301, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:23:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 309, - "GameID": 0, - "PlayID": 309, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 0, - "PlaySortOrder": 8, - "StartID": 31, - "ParentPlayID": 301, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:23:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 310, - "GameID": 0, - "PlayID": 310, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 0, - "PlaySortOrder": 9, - "StartID": 32, - "ParentPlayID": 301, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:23:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 311, - "GameID": 0, - "PlayID": 311, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 0, - "PlaySortOrder": 10, - "StartID": 33, - "ParentPlayID": 301, - "PlayTypeID": 8, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:23:27", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 312, - "GameID": 0, - "PlayID": 312, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 0, - "PlaySortOrder": 11, - "StartID": 2, - "ParentPlayID": 301, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:23:51", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 313, - "GameID": 0, - "PlayID": 313, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 0, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:23:52", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 314, - "GameID": 0, - "PlayID": 314, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 90, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:24:01", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 315, - "GameID": 0, - "PlayID": 315, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 90, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:24:10", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 316, - "GameID": 0, - "PlayID": 316, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 240, - "PlaySortOrder": 0, - "StartID": 29, - "ParentPlayID": null, - "PlayTypeID": 5, - "PlayZone": 1, - "PlayX": 19, - "PlayY": 8, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:24:25", - "VideoFrom": 1760790257, - "VideoTo": 1760790277 - }, - { - "OnlinePlayID": 317, - "GameID": 0, - "PlayID": 317, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 240, - "PlaySortOrder": 1, - "StartID": 14, - "ParentPlayID": 316, - "PlayTypeID": 27, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:24:25", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 318, - "GameID": 0, - "PlayID": 318, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 240, - "PlaySortOrder": 2, - "StartID": 29, - "ParentPlayID": 316, - "PlayTypeID": 32, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:24:25", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 319, - "GameID": 0, - "PlayID": 319, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 240, - "PlaySortOrder": 3, - "StartID": 14, - "ParentPlayID": 316, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:24:25", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 320, - "GameID": 0, - "PlayID": 320, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 310, - "PlaySortOrder": 0, - "StartID": 8, - "ParentPlayID": null, - "PlayTypeID": 6, - "PlayZone": 9, - "PlayX": 5, - "PlayY": 75, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:24:33", - "VideoFrom": 1760790265, - "VideoTo": 1760790285 - }, - { - "OnlinePlayID": 321, - "GameID": 0, - "PlayID": 321, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 310, - "PlaySortOrder": 1, - "StartID": 8, - "ParentPlayID": 320, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:24:33", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 322, - "GameID": 0, - "PlayID": 322, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 310, - "PlaySortOrder": 2, - "StartID": 16, - "ParentPlayID": 320, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:24:33", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 323, - "GameID": 0, - "PlayID": 323, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 310, - "PlaySortOrder": 3, - "StartID": 33, - "ParentPlayID": 320, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:24:33", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 324, - "GameID": 0, - "PlayID": 324, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 460, - "PlaySortOrder": 0, - "StartID": 33, - "ParentPlayID": null, - "PlayTypeID": 3, - "PlayZone": 10, - "PlayX": -64, - "PlayY": 30, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:24:47", - "VideoFrom": 1760790278, - "VideoTo": 1760790298 - }, - { - "OnlinePlayID": 325, - "GameID": 0, - "PlayID": 325, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 460, - "PlaySortOrder": 1, - "StartID": 33, - "ParentPlayID": 324, - "PlayTypeID": 31, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:24:47", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 326, - "GameID": 0, - "PlayID": 326, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 460, - "PlaySortOrder": 2, - "StartID": 28, - "ParentPlayID": 324, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:24:47", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 327, - "GameID": 0, - "PlayID": 327, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 460, - "PlaySortOrder": 3, - "StartID": 1, - "ParentPlayID": 324, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:24:47", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 328, - "GameID": 0, - "PlayID": 328, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 690, - "PlaySortOrder": 0, - "StartID": 14, - "ParentPlayID": null, - "PlayTypeID": 5, - "PlayZone": 1, - "PlayX": 12, - "PlayY": 3, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:25:11", - "VideoFrom": 1760790303, - "VideoTo": 1760790323 - }, - { - "OnlinePlayID": 329, - "GameID": 0, - "PlayID": 329, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 690, - "PlaySortOrder": 1, - "StartID": 14, - "ParentPlayID": 328, - "PlayTypeID": 32, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:25:11", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 330, - "GameID": 0, - "PlayID": 330, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 690, - "PlaySortOrder": 2, - "StartID": 10, - "ParentPlayID": 328, - "PlayTypeID": 25, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:25:11", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 331, - "GameID": 0, - "PlayID": 331, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 690, - "PlaySortOrder": 3, - "StartID": 2, - "ParentPlayID": 328, - "PlayTypeID": 28, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:25:12", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 332, - "GameID": 0, - "PlayID": 332, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 700, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:25:12", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 333, - "GameID": 0, - "PlayID": 333, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 700, - "PlaySortOrder": 0, - "StartID": 1, - "ParentPlayID": null, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:25:12", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 334, - "GameID": 0, - "PlayID": 334, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 700, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 69, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:25:22", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 335, - "GameID": 0, - "PlayID": 335, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 700, - "PlaySortOrder": 0, - "StartID": 2, - "ParentPlayID": null, - "PlayTypeID": 24, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:25:23", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 336, - "GameID": 0, - "PlayID": 336, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 700, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:25:25", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 337, - "GameID": 0, - "PlayID": 337, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 780, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:25:33", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 338, - "GameID": 0, - "PlayID": 338, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 780, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 71, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "1901-12-13T23:45:52", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:25:34", - "VideoFrom": 0, - "VideoTo": 0 - }, - { - "OnlinePlayID": 339, - "GameID": 0, - "PlayID": 339, - "PlayFlag": 0, - "PlayPeriod": 2, - "PlaySecond": 790, - "PlaySortOrder": 0, - "StartID": 0, - "ParentPlayID": null, - "PlayTypeID": 70, - "PlayZone": null, - "PlayX": null, - "PlayY": null, - "SysLastChanged": "0001-01-01T00:00:00", - "SysStatus": 1, - "SysClientLastChanged": "2025-10-18T15:25:35", - "VideoFrom": 0, - "VideoTo": 0 - } - ], - "OnlinePeriods": [ - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - }, - { - "Period": 1, - "Seconds": 600 - }, - { - "Period": 2, - "Seconds": 600 - }, - { - "Period": 3, - "Seconds": 600 - }, - { - "Period": 4, - "Seconds": 600 - } - ], - "GameTeams": [ - { - "TeamNumber": 1, - "TeamID": 3059, - "TeamName": { - "CompTeamNameID": 0, - "TeamID": 3059, - "TeamType": 0, - "CompTeamShortNameRu": "БЕТСИТИ ПАРМА", - "CompTeamShortNameEn": "BETCITY PARMA", - "CompTeamNameRu": "БЕТСИТИ ПАРМА", - "CompTeamNameEn": "BETCITY PARMA", - "CompTeamRegionNameRu": "Пермский край", - "CompTeamRegionNameEn": "Perm region", - "CompTeamAbcNameRu": "ПАРМА", - "CompTeamAbcNameEn": "PARMA", - "CompTeamNameChanged": null, - "CompTeamNameDefault": true, - "SysStatus": 1, - "SysLastChanged": "/Date(1760552611793)/", - "SysUser": "?", - "SysMyUser": null, - "CompTeams": [], - "Team": null, - "IsRealTeam": false - }, - "Score": 0, - "Points": 0, - "Shot1": 0, - "Goal1": 0, - "Shot2": 0, - "Goal2": 0, - "Shot3": 0, - "Goal3": 0, - "PaintShot": 0, - "PaintGoal": 0, - "Shots1": "0/0", - "Shot1Percent": "", - "Shots2": "0/0", - "Shot2Percent": "", - "Shots3": "0/0", - "Shot3Percent": "", - "PaintShots": "0/0", - "PaintShotPercent": "", - "Assist": 0, - "Blocks": 0, - "DefRebound": 0, - "OffRebound": 0, - "Rebound": 0, - "Steal": 0, - "Turnover": 0, - "TeamDefRebound": null, - "TeamOffRebound": null, - "TeamRebound": null, - "TeamSteal": null, - "TeamTurnover": null, - "Foul": 0, - "OpponentFoul": 0, - "Seconds": 0, - "PlayedTime": "0:00", - "PlusMinus": null, - "Coach": { - "PersonID": null, - "TeamNumber": 0, - "PlayerNumber": 0, - "DisplayNumber": "0", - "LastNameRu": null, - "LastNameEn": null, - "FirstNameRu": null, - "FirstNameEn": null, - "PersonNameRu": null, - "PersonNameEn": null, - "PersonBirth": null, - "PosID": null, - "CountryCodeIOC": null, - "CountryNameRu": null, - "CountryNameEn": null, - "RankRu": null, - "RankEn": null, - "FoulC": null, - "FoulB": null, - "FoulD": null, - "Foul": null - }, - "Players": [], - "Coaches": [ - { - "PersonID": null, - "TeamNumber": 0, - "PlayerNumber": 0, - "DisplayNumber": "0", - "LastNameRu": null, - "LastNameEn": null, - "FirstNameRu": null, - "FirstNameEn": null, - "PersonNameRu": null, - "PersonNameEn": null, - "PersonBirth": null, - "PosID": null, - "CountryCodeIOC": null, - "CountryNameRu": null, - "CountryNameEn": null, - "RankRu": null, - "RankEn": null, - "FoulC": null, - "FoulB": null, - "FoulD": null, - "Foul": null - }, - { - "PersonID": null, - "TeamNumber": 0, - "PlayerNumber": 0, - "DisplayNumber": "0", - "LastNameRu": null, - "LastNameEn": null, - "FirstNameRu": null, - "FirstNameEn": null, - "PersonNameRu": null, - "PersonNameEn": null, - "PersonBirth": null, - "PosID": null, - "CountryCodeIOC": null, - "CountryNameRu": null, - "CountryNameEn": null, - "RankRu": null, - "RankEn": null, - "FoulC": null, - "FoulB": null, - "FoulD": null, - "Foul": null - } - ] - }, - { - "TeamNumber": 2, - "TeamID": 682, - "TeamName": { - "CompTeamNameID": 0, - "TeamID": 682, - "TeamType": 0, - "CompTeamShortNameRu": "Автодор", - "CompTeamShortNameEn": "Avtodor", - "CompTeamNameRu": "Автодор", - "CompTeamNameEn": "Avtodor", - "CompTeamRegionNameRu": "Саратов", - "CompTeamRegionNameEn": "Saratov", - "CompTeamAbcNameRu": "Автодо", - "CompTeamAbcNameEn": "Avtodo", - "CompTeamNameChanged": null, - "CompTeamNameDefault": true, - "SysStatus": 1, - "SysLastChanged": "/Date(1760552611793)/", - "SysUser": "?", - "SysMyUser": null, - "CompTeams": [], - "Team": null, - "IsRealTeam": false - }, - "Score": 0, - "Points": 0, - "Shot1": 0, - "Goal1": 0, - "Shot2": 0, - "Goal2": 0, - "Shot3": 0, - "Goal3": 0, - "PaintShot": 0, - "PaintGoal": 0, - "Shots1": "0/0", - "Shot1Percent": "", - "Shots2": "0/0", - "Shot2Percent": "", - "Shots3": "0/0", - "Shot3Percent": "", - "PaintShots": "0/0", - "PaintShotPercent": "", - "Assist": 0, - "Blocks": 0, - "DefRebound": 0, - "OffRebound": 0, - "Rebound": 0, - "Steal": 0, - "Turnover": 0, - "TeamDefRebound": null, - "TeamOffRebound": null, - "TeamRebound": null, - "TeamSteal": null, - "TeamTurnover": null, - "Foul": 0, - "OpponentFoul": 0, - "Seconds": 0, - "PlayedTime": "0:00", - "PlusMinus": null, - "Coach": { - "PersonID": null, - "TeamNumber": 0, - "PlayerNumber": 0, - "DisplayNumber": "0", - "LastNameRu": null, - "LastNameEn": null, - "FirstNameRu": null, - "FirstNameEn": null, - "PersonNameRu": null, - "PersonNameEn": null, - "PersonBirth": null, - "PosID": null, - "CountryCodeIOC": null, - "CountryNameRu": null, - "CountryNameEn": null, - "RankRu": null, - "RankEn": null, - "FoulC": null, - "FoulB": null, - "FoulD": null, - "Foul": null - }, - "Players": [], - "Coaches": [ - { - "PersonID": null, - "TeamNumber": 0, - "PlayerNumber": 0, - "DisplayNumber": "0", - "LastNameRu": null, - "LastNameEn": null, - "FirstNameRu": null, - "FirstNameEn": null, - "PersonNameRu": null, - "PersonNameEn": null, - "PersonBirth": null, - "PosID": null, - "CountryCodeIOC": null, - "CountryNameRu": null, - "CountryNameEn": null, - "RankRu": null, - "RankEn": null, - "FoulC": null, - "FoulB": null, - "FoulD": null, - "Foul": null - }, - { - "PersonID": null, - "TeamNumber": 0, - "PlayerNumber": 0, - "DisplayNumber": "0", - "LastNameRu": null, - "LastNameEn": null, - "FirstNameRu": null, - "FirstNameEn": null, - "PersonNameRu": null, - "PersonNameEn": null, - "PersonBirth": null, - "PosID": null, - "CountryCodeIOC": null, - "CountryNameRu": null, - "CountryNameEn": null, - "RankRu": null, - "RankEn": null, - "FoulC": null, - "FoulB": null, - "FoulD": null, - "Foul": null - } - ] - } - ], - "CompNameRu": "Регулярный чемпионат", - "CompNameEn": "Regular Season", - "LeagueNameRu": "Единая лига ВТБ", - "LeagueNameEn": "VTB United League", - "LeagueShortNameRu": "ВТБ", - "LeagueShortNameEn": "VTB", - "Gender": 1, - "CompID": 50720, - "LeagueID": 50714, - "Is3x3": false -} diff --git a/visual.py b/visual.py new file mode 100644 index 0000000..9d363b7 --- /dev/null +++ b/visual.py @@ -0,0 +1,1984 @@ +import os +import json +import socket +import platform +import numpy as np +import pandas as pd +import streamlit as st +import sys +import requests +from streamlit_autorefresh import st_autorefresh +import errno +import time +import re +from datetime import datetime, timedelta, timezone + + +st.set_page_config( + page_title="Баскетбол", + page_icon="🏀", + layout="wide", + initial_sidebar_state="expanded", + menu_items={"About": "версия 2.0 от 08.10.2025"}, +) +REMOVE_PADDING_FROM_SIDES = """ + +""" + +st.markdown(REMOVE_PADDING_FROM_SIDES, unsafe_allow_html=True) +st_autorefresh() + + +def schedule_daily_restart(): + """Перезапуск get_season_and_schedule каждый день в 00:05 (только не на Windows).""" + if not sys.platform.startswith("win"): + while True: + now = datetime.now() + next_run = (now + timedelta(days=1)).replace( + hour=0, minute=5, second=0, microsecond=0 + ) + sleep_time = (next_run - now).total_seconds() + time.sleep(sleep_time) + + st.cache_data.clear() + + +# Функции для стилизации +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 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"]), + } + + career_avg = { + "name": "Career Average", + "game_count": "", + "start_count": "", + "pts": str(player_data["AvgCarPoints"]), + "pt-2": str(player_data["CareerTShot2Percent"]), + "pt-3": str(player_data["CareerTShot3Percent"]), + "pt-1": str(player_data["CareerTShot1Percent"]), + "fg": str(player_data["CareerTShot23Percent"]), + "ast": str(player_data["AvgCarAssist"]), + "stl": str(player_data["AvgCarSteal"]), + "blk": str(player_data["AvgCarBlocks"]), + "dreb": str(player_data["AvgCarDefRebound"]), + "oreb": str(player_data["AvgCarOffRebound"]), + "reb": str(player_data["AvgCarRebound"]), + # "to": str(player_data["AvgTurnover"]), + # "foul": str(player_data["AvgFoul"]), + "fouled": str(player_data["AvgCarOpponentFoul"]), + "dunk": str(player_data["AvgCarDunk"]), + "time": str(player_data["AvgCarPlayedTime"]), + } + + + + return [season_total, season_avg, career_total, career_avg], 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.TextColumn("PTS", width="content", help="⭐ = Career High"), + "pt-2": st.column_config.TextColumn("2-PT", width="content"), + "pt-3": st.column_config.TextColumn("3-PT", width="content"), + "pt-1": st.column_config.TextColumn("FT", width="content"), + "fg": st.column_config.TextColumn("FG", width="content"), + "ast": st.column_config.TextColumn("AS", width="content"), + "stl": st.column_config.TextColumn("ST", width="content"), + "blk": st.column_config.TextColumn("BL", width="content"), + "blkVic": st.column_config.TextColumn("BV", width="content"), + "dreb": st.column_config.TextColumn("DR", width="content"), + "oreb": st.column_config.TextColumn("OR", width="content"), + "reb": st.column_config.TextColumn("R", width="content"), + "to": st.column_config.TextColumn("TO", width="content"), + "foul": st.column_config.TextColumn("F", width="content"), + "fouled": st.column_config.TextColumn("Fed", width="content"), + "plusMinus": st.column_config.TextColumn("+/-", width="content"), + "dunk": st.column_config.TextColumn("DUNK", width="content"), + "kpi": st.column_config.TextColumn("KPI", width="content"), + "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() +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 _is_meaningful_payload(obj) -> bool: + # Нулевые/битые/пустые — не считаем осмысленными + if obj is None: + return False + # Пустая коллекция — не осмысленно + if isinstance(obj, (list, dict, set, tuple)): + return len(obj) > 0 + # Любой другой тип (str/числа) считаем осмысленным только если не пустая строка + if isinstance(obj, str): + return obj.strip() != "" + return True + + +def load_data_from_json(filepath): + """ + Читает JSON и обновляет session_state ТОЛЬКО если данные осмысленные. + Иначе оставляет предыдущий кэш нетронутым (stale-if-error/stale-if-empty). + """ + 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 "" + host = _ipcheck() + base = os.path.basename(filepath_full).replace(".json", "") + key = base.replace(f"{host}", "", 1) + new_payload = load_json_data(filepath_full) # может быть None/битое/пустое + # if "team1_" in filepath_full: + # print(filepath_full) + # print(new_payload) + + # Если новый payload осмысленный — обновляем кэш и "last_good_*" + if _is_meaningful_payload(new_payload): + st.session_state[key] = new_payload + st.session_state.setdefault("_last_good", {}) + st.session_state["_last_good"][key] = new_payload + return + + # Иначе: если раньше уже был хороший — восстанавливаем его и НЕ трогаем + if "_last_good" in st.session_state and key in st.session_state["_last_good"]: + # ничего не делаем — оставляем текущее значение как есть + return + + # Иначе (нет ни нового, ни прошлого хорошего) — вообще не создаём ключ + # чтобы ниже по коду .get(...) вернул None и UI ничего не нарисовал + # (при желании можно явно "очищать": st.session_state.pop(key, None)) + + +def _ipcheck() -> str: + """Возвращает префикс для имени файла по IP. + Если IP локальный или host не найден — возвращает пустую строку. + """ + try: + ip_str = get_ip_address() + except Exception: + ip_str = None + + ip_map = globals().get("ip_check") or {} + if ip_str and isinstance(ip_map, dict): + host = (ip_map.get(ip_str) or {}).get("host") + if host: + return f"{host}_" + return "" + + +def read_match_id_json(path="match_id.json", attempts=10, delay=0.2): + """Надёжное чтение match_id.json с ретраями при EBUSY/битом JSON.""" + d = delay + for i in range(attempts): + try: + if not os.path.isfile(path): + return {} + with open(path, "r", encoding="utf-8") as f: + return json.load(f) + except json.JSONDecodeError: + # файл переписывают — подождём и попробуем снова + time.sleep(d) + d = min(d * 1.6, 2.0) + except OSError as e: + # EBUSY (errno=16) — подождём и ещё раз + if getattr(e, "errno", None) == errno.EBUSY: + time.sleep(d) + d = min(d * 1.6, 2.0) + continue + # иные ошибки — пробрасываем дальше + raise + print("Не удалось прочитать match_id.json после нескольких попыток; возвращаю {}") + return {} + + +def rewrite_file(filename: str, data: dict, directory: str = "JSON") -> None: + """ + Перезаписывает JSON-файл с заданными данными. + Если запуск локальный (локальный IP), префикс host в имени файла не используется. + Если IP не локальный и есть словарь ip_check с хостами — добавим префикс host_. + """ + # Если глобальная константа задана — используем её + try: + directory = FOLDER_JSON # type: ignore[name-defined] + except NameError: + # иначе используем аргумент по умолчанию/переданный + pass + + os.makedirs(directory, exist_ok=True) + + host_prefix = _ipcheck() + + filepath = os.path.join(directory, f"{host_prefix}{filename}.json") + # print(filepath) # оставил как у тебя; можно заменить на logger.debug при желании + + try: + with open(filepath, "w", encoding="utf-8") as f: + json.dump(data, f, ensure_ascii=False, indent=2) + except Exception as e: + print(f"Ошибка при записи файла {filepath}: {e}") + + +ip_check = read_match_id_json("match_id.json") or {} + + +prefix = _ipcheck() + +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" + ) + comp_name = ( + ((cached_game_online.get("result") or {}).get("comp") or {}) + .get("name") + .replace(" ", "_") + ) +if league_tag: + load_data_from_json(f"{prefix}standings_{league_tag}_{comp_name}") +cached_standings = ( + st.session_state.get(f"standings_{league_tag}_{comp_name}") 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") + +load_data_from_json(f"{prefix}team_comparison") +cached_team_comparison = st.session_state.get("team_comparison") + + +def _is_empty_like(x) -> bool: + if x is None: + return True + if isinstance(x, pd.DataFrame): + return x.empty + try: + from pandas.io.formats.style import Styler + + if isinstance(x, Styler): + 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): + for a in args: + if _is_empty_like(a): + return None + for k, v in kwargs.items(): + 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 + 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 ======== +def ensure_state(key: str, default=None): + # Инициализирует ключ один раз и возвращает значение + return st.session_state.setdefault(key, default) + + +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 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, + ) + col2.markdown( + f"

{result['game']['localDate']} {result['game']['defaultZoneTime']}

", + 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 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, + tab_online, +) = 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", +] +if cached_team1 and cached_team2: + team1_data = process_team_data(cached_team1, columns_game) + team2_data = process_team_data(cached_team2, columns_game) + # Добавляем звездочку, если pts > PTS_Career_High + def _get_first_number(x): + """Безопасно вытащить число из строки/значения (например '12 (60%)' -> 12).""" + try: + if x is None: + return None + s = str(x) + # заберём ведущие число/знак (поддержим +/-) + import re + m = re.search(r"[-+]?\d+(\.\d+)?", s) + return float(m.group(0)) if m else None + except Exception: + return None + + CAREER_HIGH_KEYS = { + "pts": ["PTS_Career_High", "CareerHighPoints", "career_high_pts"], + "ast": ["AST_Career_High", "CareerHighAssist", "career_high_ast"], + "stl": ["STL_Career_High", "CareerHighSteal", "career_high_stl"], + "blk": ["BLK_Career_High", "CareerHighBlocks", "career_high_blk"], + "reb": ["REB_Career_High", "CareerHighRebound", "career_high_reb"], + # если нужно — добавь ещё пары "df_column": ["possible_key1","possible_key2"...] +} + def _build_career_high_map(cached_team_list): + """Вернёт словарь: player_id -> {stat_key: value} для всех доступных максимумов.""" + out = {} + if not isinstance(cached_team_list, list): + return out + for p in cached_team_list: + if not isinstance(p, dict): + continue + pid = p.get("id") + if pid is None: + continue + out[pid] = {} + for stat_col, aliases in CAREER_HIGH_KEYS.items(): + for k in aliases: + if k in p and p[k] not in (None, ""): + out[pid][stat_col] = _get_first_number(p[k]) + break + return out + + def _ensure_id_column(df, cached_team_list): + """Присвоить игрокам id в том же порядке, что и в списке cached_team.""" + try: + ids = [p.get("id") if isinstance(p, dict) else None for p in cached_team_list][:len(df)] + if "id" not in df.columns: + df["id"] = ids + else: + # не затираем, только заполняем пустые + df["id"] = df["id"].fillna(pd.Series(ids, index=df.index)) + except Exception: + pass + + def _mark_star_for_columns(df, cached_team_list, columns): + """ + Для каждого col в columns: если текущее значение > career high — добавляем ' ⭐️'. + Преобразуем колонки в текст (для отображения эмодзи). + """ + _ensure_id_column(df, cached_team_list) + ch_map = _build_career_high_map(cached_team_list) + + def format_with_star(val, career_max): + v = _get_first_number(val) + cm = _get_first_number(career_max) + if v is not None and cm is not None and v >= cm and val > 0: + # сохраняем исходное текстовое представление + ⭐️ + return f"{val} ⭐️" + return f"{val}" if val is not None else "" + + for col in columns: + if col not in df.columns: + continue + new_vals = [] + for idx, row in df.iterrows(): + pid = row.get("id") + career_max = (ch_map.get(pid, {}) or {}).get(col) + new_vals.append(format_with_star(row[col], career_max)) + df[col] = new_vals # теперь это текст для отображения + + STAR_COLUMNS = [ + "pts", "ast", "stl", "blk", "reb", +] + team1_data["_pts_num"] = pd.to_numeric(team1_data["pts"], errors="coerce") + team1_data["_kpi_num"] = pd.to_numeric(team1_data["kpi"], errors="coerce") + team2_data["_pts_num"] = pd.to_numeric(team2_data["pts"], errors="coerce") + team2_data["_kpi_num"] = pd.to_numeric(team2_data["kpi"], errors="coerce") + def highlight_max_by_refcol(df, view_col, ref_col): + ref = pd.to_numeric(df[ref_col], errors="coerce") + mx = ref.max() + return [("background-color: green" if (pd.notna(v) and v == mx and v > 0) else "") + for v in ref] + + _mark_star_for_columns(team1_data, cached_team1, STAR_COLUMNS) + _mark_star_for_columns(team2_data, cached_team2, STAR_COLUMNS) + + # Стилизация данных + # team1_styled = ( + # team1_data.style.apply(highlight_grey, axis=1) + # .apply(highlight_foul, subset="foul") + # .apply(highlight_max, subset="pts") + # .apply(highlight_max, subset="kpi") + # ) + # team2_styled = ( + # team2_data.style.apply(highlight_grey, axis=1) + # .apply(highlight_foul, subset="foul") + # .apply(highlight_max, subset="pts") + # .apply(highlight_max, subset="kpi") + # ) + team1_styled = ( + team1_data[columns_game].style + .apply(highlight_grey, axis=1) + .apply(highlight_foul, subset="foul") + .apply(lambda _: highlight_max_by_refcol(team1_data, "pts", "_pts_num"), axis=0, subset=["pts"]) + .apply(lambda _: highlight_max_by_refcol(team1_data, "kpi", "_kpi_num"), axis=0, subset=["kpi"]) + ) + team2_styled = ( + team2_data[columns_game].style + .apply(highlight_grey, axis=1) + .apply(highlight_foul, subset="foul") + .apply(lambda _: highlight_max_by_refcol(team2_data, "pts", "_pts_num"), axis=0, subset=["pts"]) + .apply(lambda _: highlight_max_by_refcol(team2_data, "kpi", "_kpi_num"), axis=0, subset=["kpi"]) + ) + + def get_player_all_game(player_data_1): + + try: + directory = FOLDER_JSON # type: ignore[name-defined] + except NameError: + # иначе используем аргумент по умолчанию/переданный + pass + + os.makedirs(directory, exist_ok=True) + + host_prefix = _ipcheck() + filename = player_data_1["id"] + filepath = os.path.join(directory, f"{host_prefix}{filename}.json") + # print(filepath) # оставил как у тебя; можно заменить на logger.debug при желании + + try: + with open(filepath, "r", encoding="utf-8") as f: + players_game = json.load(f) + except Exception: + pass + df_player_game = pd.json_normalize(players_game) + # Отфильтровать строки, где class == "Normal" + # print(player_data_1) + df_filtered = df_player_game[df_player_game["class"] == "Normal"].copy() + + # Преобразуем game.gameDate в datetime + df_filtered["game.gameDate"] = pd.to_datetime( + df_filtered["game.gameDate"], errors="coerce", dayfirst=True + ) + + # Удалим строки без корректной даты (если такие есть) + # df_filtered = df_filtered.dropna(subset=["game.gameDate"]) + + # Сортировка от последнего матча к первому + df_filtered = df_filtered.sort_values(by="game.gameDate", ascending=False) + # Указать нужные колонки для вывода + columns_to_show = [ + "Сезон", + "Дата", + "Команда 1", + "Команда 2", + "Счёт", + "PTS", + "2-PTS%", + "3-PTS%", + "FG%", + "FT%", + "AST", + "STL", + "BLK", + "DR", + "OR", + "REB", + "TO", + "F", + "TIME", + "+/-", + ] + numeric_cols = [ + "stats.points", + "stats.assist", + "stats.steal", + "stats.blockShot", + "stats.rebound", + ] + # df_filtered[numeric_cols] = df_filtered[numeric_cols].apply( + # pd.to_numeric, errors="coerce" + # ) + + # 🟢 Переименовываем колонки для отображения в Streamlit + rename_map = { + "season": "Сезон", + "game.gameDate": "Дата", + "game.team1Name": "Команда 1", + "game.team2Name": "Команда 2", + "game.score": "Счёт", + "stats.points": "PTS", + "stats.shot2Percent": "2-PTS%", + "stats.shot3Percent": "3-PTS%", + "stats.shot23Percent": "FG%", + "stats.shot1Percent": "FT%", + "stats.assist": "AST", + "stats.steal": "STL", + "stats.blockShot": "BLK", + "stats.defRebound": "DR", + "stats.offRebound": "OR", + "stats.rebound": "REB", + "stats.turnover": "TO", + "stats.foul": "F", + "stats.playedTime": "TIME", + "stats.plusMinus": "+/-", + } + df_filtered[numeric_cols] = df_filtered[numeric_cols].apply( + pd.to_numeric, errors="coerce" + ) + df_filtered[numeric_cols] = df_filtered[numeric_cols].round(0).astype("Int64") + df_filtered = df_filtered.rename(columns=rename_map) + df_filtered["Дата"] = df_filtered["Дата"].dt.strftime("%d.%m.%Y") + styled = ( + df_filtered[columns_to_show] + .style.apply(highlight_max, subset=["PTS"]) + .apply(highlight_max, subset=["AST"]) + .apply(highlight_max, subset=["STL"]) + .apply(highlight_max, subset=["BLK"]) + .apply(highlight_max, subset=["REB"]) + .format( + { + "Дата": lambda x: x, # уже строка, просто оставляем как есть + "PTS": "{:,.0f}".format, + "AST": "{:,.0f}".format, + "STL": "{:,.0f}".format, + "BLK": "{:,.0f}".format, + "REB": "{:,.0f}".format, + } + ) + ) + return styled + + # Вывод данных + col_player1, col_player2 = tab_temp_1.columns((5, 5)) + config_copy = config.copy() + + event1 = col_player1.dataframe( + team1_styled, + column_config=config_copy, + 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 and event1.selection.get("rows"): + selected_index1 = event1.selection["rows"][0] + st.session_state["player1"] = ( + selected_index1 # Сохранение состояния в session_state + ) + else: + st.session_state["player1"] = None + 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, q, b, c, d, e = col_player1.columns((1, 6, 1, 1, 1, 1, 1)) + z.metric("Номер", player_data_1["num"], border=False) + a.metric("Игрок", player_data_1["NameGFX"], border=False) + q.image(player_data_1["flag"]) + 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, + ) + + col_player1.title("Статистика каждой игры") + col_player1.dataframe(get_player_all_game(player_data_1), 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 + ) + else: + st.session_state["player2"] = None + 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, q, b, c, d, e = col_player2.columns((1, 6, 1, 1, 1, 1, 1)) + z.metric("Номер", player_data_2["num"], border=False) + a.metric("Игрок", player_data_2["NameGFX"], border=False) + q.image(player_data_2["flag"]) + 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, + ) + col_player2.title("Статистика каждой игры") + col_player2.dataframe(get_player_all_game(player_data_2), hide_index=True) + +team_col1, team_col2 = tab_temp_2.columns((5, 5)) +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], + ] + team_col1.title("Статистика за матч") + team_col1.dataframe(cached_team_stats_new, height=500) + +if isinstance(cached_team_comparison, list): + team_col2.title("Статистика за сезон") + + # задаём желаемый порядок ключей + order = [ + "points", + "points_1", + "points_2", + "points_3", + "points_23", + "assists", + "rebounds", + "steals", + "blocks", + "turnovers", + "fouls", + "games", + # "team", + ] + + # формируем результат с учётом порядка + result = [ + { + "name": key, + "val1": cached_team_comparison[0][key], + "val2": cached_team_comparison[1][key], + } + for key in order + if key in cached_team_comparison[0] + ] + team_col2.dataframe(result, width="stretch", height=500) + +if isinstance(cached_referee, (list, pd.DataFrame)): + tab_temp_3.dataframe( + cached_referee, + height=600, + width="content", + column_config={"flag": st.column_config.ImageColumn("flag")}, + ) + + +column_config_ref = { + "flag": st.column_config.ImageColumn( + "flag", + ), +} + + +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) + + 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[ + [ + "teamId", + "start", + "place", + "name", + "regionName", + "totalGames", + "totalWin", + "totalDefeat", + "totalPoints", + "totalGoalPlus", + "totalGoalMinus", + "logo", + "w_l", + "procent", + "plus_minus", + ] + ].style.apply(highlight_teams, axis=1) + tab_temp_4.dataframe( + styled, + column_config={"logo": st.column_config.ImageColumn("logo")}, + hide_index=True, + height=610, + width="content" + ) + + +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 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) + + +def _ensure_columns(df: pd.DataFrame, cols: list[str]) -> pd.DataFrame: + """Гарантирует наличие всех столбцов в df, отсутствующие заполняет NaN/0 по типу.""" + for c in cols: + if c not in df.columns: + # для числовых метрик по четверти логично ставить 0 + df[c] = 0 + # Переупорядочим столбцы + return df[cols] + + +def _safe_dataframe( + container, df: pd.DataFrame, cols_for_st: list[str], height_per_row: int = 38 +): + df = _ensure_columns(df, cols_for_st) + rows = len(df) + + # Стилизуем безопасно (если вдруг highlight_max упадёт — показываем без стиля) + try: + styled = ( + df.style.apply(highlight_max, subset="q_pts") if not df.empty else df.style + ) + except Exception: + styled = df.style + + kwargs = dict(column_config=config, hide_index=True) + + # height только если он действительно нужен + if rows > 10: + kwargs["height"] = height_per_row * rows + # или: kwargs["height"] = "stretch" # если хотите растягивать блок + + container.dataframe(styled, **kwargs) + + +# 1) Безопасная проверка наличия плей-данных +has_plays = bool( + cached_game_online and cached_game_online.get("result", {}).get("plays") +) +if has_plays: + + # 2) Готовим вкладки по количеству периодов + # Если у вас уже есть count_quarter — используйте его. Иначе берём из period_max. + + # === REPLACE: безопасное определение количества периодов и создание вкладок === + def _safe_int(x, default=None): + try: + v = int(x) + return v if v is not None else default + except Exception: + return default + + def _max_period_from_plays(cached_game_online) -> int: + plays = (cached_game_online or {}).get("result", {}).get("plays") or [] + periods = [] + for item in plays: + try: + v = int(item.get("period")) + periods.append(v) + except Exception: + # пропускаем пустые/неконвертируемые значения + continue + return max(periods) if periods else 0 + + count_quarter = _max_period_from_plays(cached_game_online) + + # 3) попытка по ключам team1_/team2_ в session_state (например, team1_1..team1_4) + if count_quarter is None or count_quarter <= 0: + import re + + mx = 0 + for k in st.session_state.keys(): + m1 = re.fullmatch(r"team1_(\d+)", k) + m2 = re.fullmatch(r"team2_(\d+)", k) + if m1: + mx = max(mx, int(m1.group(1))) + if m2: + mx = max(mx, int(m2.group(1))) + count_quarter = mx if mx > 0 else None + + # 4) дефолт, если ничего не получилось + if count_quarter is None or count_quarter <= 0: + # если совсем нет данных — не создаём вкладки и показываем инфо + tab_temp_7.info( + "Нет корректного числа периодов для отображения таблиц по четвертям." + ) + count_quarter = 0 + + # 5) создаём вкладки, только если их хотя бы одна + if count_quarter > 0: + tab_labels = [f"{i+1}Q" for i in range(count_quarter)] + columns_quarter = tab_temp_7.tabs(tab_labels) + else: + columns_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", + ] + + # 3) Рендер таблиц по четвертям + for i in range(count_quarter): + # Каждая вкладка -> 2 колонки + try: + col_quarter1, col_quarter2 = columns_quarter[i].columns((5, 5)) + except IndexError: + # На случай несоответствия размеров + st.warning(f"Недостаточно вкладок для периода #{i+1}. Пропуск.") + continue + + # --- Team 1 --- + key_team1 = f"team1_{i+1}" + try: + load_data_from_json(key_team1) + except Exception as e: + tab_temp_7.warning(f"Не удалось загрузить данные для {key_team1}: {e}") + continue + + data_team1 = st.session_state.get(key_team1, []) + # print(data_team1) + df_team1 = ( + pd.DataFrame(data_team1) + if isinstance(data_team1, (list, tuple, dict)) + else pd.DataFrame() + ) + + # _safe_dataframe(col_quarter1, df_team1, columns_quarter_for_st) + + # --- Team 2 --- + key_team2 = f"team2_{i+1}" + try: + load_data_from_json(key_team2) + except Exception as e: + tab_temp_7.warning(f"Не удалось загрузить данные для {key_team2}: {e}") + continue + + data_team2 = st.session_state.get(key_team2, []) + df_team2 = ( + pd.DataFrame(data_team2) + if isinstance(data_team2, (list, tuple, dict)) + else pd.DataFrame() + ) + # _safe_dataframe(col_quarter2, df_team2, columns_quarter_for_st) + tab_temp_7.warning("В процессе разработки!!!!!!") + + # 4) Блок с milestones по командам (если есть кэш) + if cached_team1 and cached_team2: + try: + data_team_season_1, data_team_career_1 = milestones(cached_team1) + data_team_season_2, data_team_career_2 = milestones(cached_team2) + except Exception as e: + st.warning(f"Не удалось получить milestones: {e}") + else: + # На случай, если функции вернули не DataFrame + if not isinstance(data_team_season_1, pd.DataFrame): + data_team_season_1 = pd.DataFrame(data_team_season_1 or {}) + if not isinstance(data_team_career_1, pd.DataFrame): + data_team_career_1 = pd.DataFrame(data_team_career_1 or {}) + if not isinstance(data_team_season_2, pd.DataFrame): + data_team_season_2 = pd.DataFrame(data_team_season_2 or {}) + if not isinstance(data_team_career_2, pd.DataFrame): + data_team_career_2 = pd.DataFrame(data_team_career_2 or {}) + + tab7_col1, tab7_col2 = tab_temp_8.columns((5, 5)) + + tab7_col1.title("Сезон") + tab7_col1.dataframe(data_team_season_1) + tab7_col2.title("Сезон") + tab7_col2.dataframe(data_team_season_2) + tab7_col1.title("Карьера") + tab7_col1.dataframe(data_team_career_1) + tab7_col2.title("Карьера") + tab7_col2.dataframe(data_team_career_2) +else: + tab_temp_7.info("Нет онлайн-плей-данных для отображения.") + + +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", + "team1.teamId", + "team2.teamId", + ] + 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]) + 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) + + game_online = st.session_state.get("game_online") + # print(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 + ) + # print(team1_data) + team2_data = schedule_selected_team( + team2_id, pd_schedule, game_id, selection2, team1_id + ) + + def highlight_two_teams(s): + # print(s) + try: + if s.loc["team1.teamId"] in ( + team1_id, + team2_id, + ) and s.loc["team2.teamId"] in ( + team1_id, + team2_id, + ): + 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( + "Счёт по четвертям", width="medium" + ), + "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 tab_online: + if isinstance(cached_schedule, list): + current_date = pd.to_datetime(datetime.now().date()) + df_online = pd.json_normalize(cached_schedule) + df_online["game.localDate"] = pd.to_datetime( + df_online["game.localDate"], format="%d.%m.%Y", errors="coerce" + ) + df_filtered = df_online[df_online["game.localDate"] == current_date].copy() + + names = { + "Avtodor": r"D:\Графика\БАСКЕТБОЛ\VTB League\TEAM LOGOS\LOGOS 2025-2026\AVTODOR.png", + "BETCITY PARMA": r"D:\Графика\БАСКЕТБОЛ\VTB League\TEAM LOGOS\LOGOS 2025-2026\BETCITY_PARMA_ENG.png", + "CSKA": r"D:\Графика\БАСКЕТБОЛ\VTB League\TEAM LOGOS\LOGOS 2025-2026\CSKA_BLACK_BACK_ENG.png", + "Enisey": r"D:\Графика\БАСКЕТБОЛ\VTB League\TEAM LOGOS\LOGOS 2025-2026\ENISEY_ENG.png", + "Lokomotiv Kuban": r"D:\Графика\БАСКЕТБОЛ\VTB League\TEAM LOGOS\LOGOS 2025-2026\LOKOMOTIV KUBAN.png", + "MBA-MAI": r"D:\Графика\БАСКЕТБОЛ\VTB League\TEAM LOGOS\LOGOS 2025-2026\MBA-MAI.png", + "Pari Nizhny Novgorod": r"D:\Графика\БАСКЕТБОЛ\VTB League\TEAM LOGOS\LOGOS 2025-2026\PARI_NN_ENG.png", + "Samara": r"D:\Графика\БАСКЕТБОЛ\VTB League\TEAM LOGOS\LOGOS 2025-2026\SAMARA_BLACK_BACK.png", + "UNICS": r"D:\Графика\БАСКЕТБОЛ\VTB League\TEAM LOGOS\LOGOS 2025-2026\UNICS_BLACK_BACK.png", + "Uralmash": r"D:\Графика\БАСКЕТБОЛ\VTB League\TEAM LOGOS\LOGOS 2025-2026\URALMASH_ENG.png", + "Zenit": r"D:\Графика\БАСКЕТБОЛ\VTB League\TEAM LOGOS\LOGOS 2025-2026\ZENIT.png", + } + + df_filtered["logo1"] = df_filtered["team1.name"].map(names) + df_filtered["logo2"] = df_filtered["team2.name"].map(names) + + # Словарь для быстрого поиска по gameId + live_data_map = {} + + # Собираем live-данные по каждому game.id + + for _, row in df_filtered.iterrows(): + game_id = row["game.id"] + try: + json_data = requests.get( + f"https://vtb-league.org/api/abc/games/live-status?Id={game_id}&Lang=en", + ).json() + except Exception as ex: + + print(ex) + + # Берём содержимое result (словарь с gameId и данными) + if json_data: + result = json_data.get("result", {}) + if result and "gameId" in result: + live_data_map[result["gameId"]] = result + + # Создаём колонки для live-данных + df_filtered["live_period"] = None + df_filtered["live_timeToGo"] = None + df_filtered["live_scoreA"] = None + df_filtered["live_scoreB"] = None + df_filtered["live_status"] = None + df_filtered["period"] = None + # Заполняем колонки, где game.id совпадает с gameId + for idx, row in df_filtered.iterrows(): + game_id = row["game.id"] + if game_id in live_data_map: + live_info = live_data_map[game_id] + df_filtered.at[idx, "live_period"] = live_info.get("period") + df_filtered.at[idx, "live_timeToGo"] = live_info.get("timeToGo") + df_filtered.at[idx, "live_scoreA"] = live_info.get("scoreA") + df_filtered.at[idx, "live_scoreB"] = live_info.get("scoreB") + df_filtered.at[idx, "live_status"] = live_info.get("gameStatus") + try: + if live_info.get("timeToGo") != "": + if float(live_info.get("timeToGo")) == 0.0: + if live_info.get("period") == 2: + df_filtered.at[idx, "period"] = "HT" + elif live_info.get("period") in [1, 3]: + df_filtered.at[idx, "period"] = ( + f"END {live_info.get('period')}Q" + ) + elif float(live_info.get("timeToGo")) > 0.0: + df_filtered.at[idx, "period"] = ( + f"{live_info.get('period')}Q" + ) + else: + df_filtered.at[idx, "period"] = "" + except Exception as ex: + df_filtered.at[idx, "period"] = "" + print(ex) + + df_filtered["live_scoreA"] = pd.to_numeric( + df_filtered["live_scoreA"], errors="coerce" + ).fillna(pd.to_numeric(df_filtered["game.score1"], errors="coerce")) + + df_filtered["live_scoreB"] = pd.to_numeric( + df_filtered["live_scoreB"], errors="coerce" + ).fillna(pd.to_numeric(df_filtered["game.score2"], errors="coerce")) + + # Вывод нужных колонок + columns = [ + "game.id", + "game.gameStatus", + "status.displayName", + "game.defaultZoneTime", + "team1.name", + "team2.name", + "game.score1", + "game.score2", + "live_scoreA", + "live_scoreB", + "live_period", + "live_timeToGo", + "live_status", + "period", + "team1.logo", + "team2.logo", + "logo1", + "logo2", + ] + + existing_columns = [c for c in columns if c in df_filtered.columns] + df_sel = df_filtered.loc[:, existing_columns].copy() + data = df_sel.to_dict(orient="records") # список словарей + rewrite_file("online", data) + + st.dataframe( + df_filtered[existing_columns], + column_config={ + "team1.logo": st.column_config.ImageColumn("team1.logo"), + "team2.logo": st.column_config.ImageColumn("team2.logo"), + }, + width="content", + ) + + +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 + + +# Безопасная загрузка 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 {} + +# Если teams_section — список (например, [{"starts": [...]}, {...}]) +if isinstance(teams_section, list): + if len(teams_section) >= 2: + starts1 = next( + (t.get("starts") for t in teams_section if t["teamNumber"] == 1), None + ) + starts2 = next( + (t.get("starts") for t in teams_section if t["teamNumber"] == 2), None + ) + 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 "auto"), + ) + else: + tab_pbp.info("Данных play-by-play нет.") diff --git a/visual_safe_show.patch b/visual_safe_show.patch deleted file mode 100644 index 51b7c76..0000000 --- a/visual_safe_show.patch +++ /dev/null @@ -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"

{team1_name} — {team2_name}

", -- 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"

{team1_name} — {team2_name}

", -+ 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 нет.")