135 lines
4.7 KiB
Python
135 lines
4.7 KiB
Python
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,
|
|
}
|