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