This commit is contained in:
2026-08-19 15:08:39 +03:00
parent 478557f3ad
commit a03c54dbe8
5148 changed files with 31553313 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
from __future__ import annotations
from typing import Any
from xml.etree import ElementTree as ET
from .match_parser import local_name, safe_int
def _text(value: Any) -> str:
return str(value or "").strip()
def _team_payload(node: ET.Element, language: str) -> dict[str, Any]:
attrs = {str(key): _text(value) for key, value in node.attrib.items()}
name_ru = attrs.get("name", "")
name_en = attrs.get("nameen", "")
return {
"id": attrs.get("id", ""),
"entry_id": attrs.get("id", ""),
"club_id": attrs.get("clubid", ""),
"name": name_en if language == "en" and name_en else name_ru or name_en,
"names": {"ru": name_ru, "en": name_en},
"rank": safe_int(attrs.get("rank")),
"games": safe_int(attrs.get("gp")),
"wins": safe_int(attrs.get("w")),
"overtime_wins": safe_int(attrs.get("otw")),
"shootout_wins": safe_int(attrs.get("sow")),
"shootout_losses": safe_int(attrs.get("sol")),
"overtime_losses": safe_int(attrs.get("otl")),
"losses": safe_int(attrs.get("l")),
"points": safe_int(attrs.get("pts")),
"points_pct": attrs.get("pts_pct", ""),
"goals_for": safe_int(attrs.get("gf")),
"goals_against": safe_int(attrs.get("ga")),
"penalty_minutes": safe_int(attrs.get("pim")),
"opponent_penalty_minutes": safe_int(attrs.get("pima")),
"playoffs_in": attrs.get("playoffs_in", "").upper() == "Y",
"playoffs_out": attrs.get("playoffs_out", "").upper() == "Y",
"highlighted": False,
"side": "",
}
def _group_payload(
node: ET.Element,
*,
language: str,
fallback_id: str,
) -> dict[str, Any]:
attrs = {str(key): _text(value) for key, value in node.attrib.items()}
name_ru = attrs.get("name", "")
name_en = attrs.get("name_en", "")
teams = [
_team_payload(child, language)
for child in list(node)
if local_name(child.tag).lower() == "team"
]
return {
"id": attrs.get("item") or attrs.get("id") or fallback_id,
"name": name_en if language == "en" and name_en else name_ru or name_en,
"names": {"ru": name_ru, "en": name_en},
"standings_type": attrs.get("standings_type", ""),
"conference": attrs.get("conference", ""),
"playoff_places": safe_int(attrs.get("in_playoff")),
"teams": teams,
}
def parse_standings_xml(
content: bytes | str,
*,
language: str = "ru",
) -> dict[str, Any]:
raw = content.encode("utf-8") if isinstance(content, str) else content
root = ET.fromstring(raw)
if local_name(root.tag).lower() != "standings":
raise ValueError("Stat2TV вернул неизвестный формат турнирной таблицы")
league_groups: list[dict[str, Any]] = []
conference_groups: list[dict[str, Any]] = []
division_groups: list[dict[str, Any]] = []
for child in list(root):
child_tag = local_name(child.tag).lower()
if child_tag == "league":
league_groups.append(
_group_payload(child, language=language, fallback_id="league")
)
elif child_tag == "conferences":
conference_groups.extend(
_group_payload(
group,
language=language,
fallback_id=f"conference-{index}",
)
for index, group in enumerate(list(child), start=1)
if local_name(group.tag).lower() == "conference"
)
elif child_tag == "divisions":
division_groups.extend(
_group_payload(
group,
language=language,
fallback_id=f"division-{index}",
)
for index, group in enumerate(list(child), start=1)
if local_name(group.tag).lower() == "division"
)
variants = [
{
"id": "league",
"label": "League" if language == "en" else "Общая",
"groups": league_groups,
},
{
"id": "conferences",
"label": "Conferences" if language == "en" else "Конференции",
"groups": conference_groups,
},
{
"id": "divisions",
"label": "Divisions" if language == "en" else "Дивизионы",
"groups": division_groups,
},
]
variants = [variant for variant in variants if variant["groups"]]
return {
"tournament_id": _text(root.attrib.get("idtournament")),
"generated_at": _text(root.attrib.get("genDate")),
"order": _text(root.attrib.get("order")),
"available": bool(variants),
"variants": variants,
}