Source code for vlrdevapi.events.match_summary

"""Event match summary functionality."""

from __future__ import annotations

import datetime
from bs4 import BeautifulSoup

from .models import MatchSummary, StageMatches
from ..config import get_config
from ..fetcher import fetch_html
from ..exceptions import NetworkError
from ..utils import extract_text, parse_date

_config = get_config()


[docs] def match_summary(event_id: int, timeout: float | None = None) -> MatchSummary | None: """ Get event match summary. Args: event_id: Event ID timeout: Request timeout in seconds Returns: Match summary or None if not found Example: >>> import vlrdevapi as vlr >>> summary = vlr.events.match_summary(event_id=123) >>> print(f"Total: {summary.total_matches}, Completed: {summary.completed}") """ url = f"{_config.vlr_base}/event/matches/{event_id}" effective_timeout = timeout if timeout is not None else _config.default_timeout try: html = fetch_html(url, effective_timeout) except NetworkError: return None soup = BeautifulSoup(html, "lxml") # Count matches and organize by stage total = 0 completed = 0 upcoming = 0 ongoing = 0 # Track stage-level statistics stage_stats: dict[str, dict] = {} for card in soup.select("a.match-item"): total += 1 # Parse status ml = card.select_one(".match-item-eta .ml") match_status = "upcoming" if ml: classes_raw = ml.get("class") classes: list[str] = [] if isinstance(classes_raw, list): classes = classes_raw elif isinstance(classes_raw, str): classes = [classes_raw] classes_list = classes if any("mod-completed" in str(c) for c in classes_list): completed += 1 match_status = "completed" elif any("mod-live" in str(c) or "mod-ongoing" in str(c) for c in classes_list): ongoing += 1 match_status = "ongoing" else: upcoming += 1 else: upcoming += 1 # Parse stage name event_el = card.select_one(".match-item-event") stage_name = extract_text(event_el) or "Unknown Stage" # Remove phase from stage name if present series_el = card.select_one(".match-item-event-series") phase = extract_text(series_el) or None if phase and stage_name: stage_name = stage_name.replace(phase, "").strip() # Parse date match_date: datetime.date | None = None label = card.find_previous("div", class_="wf-label mod-large") if label: texts = [frag.strip() for frag in label.find_all(string=True, recursive=False)] text = " ".join(t for t in texts if t) match_date = parse_date(text, ["%a, %B %d, %Y", "%A, %B %d, %Y", "%B %d, %Y"]) # Initialize stage stats if not exists if stage_name not in stage_stats: stage_stats[stage_name] = { "count": 0, "completed": 0, "upcoming": 0, "ongoing": 0, "dates": [] } # Update stage stats stage_stats[stage_name]["count"] += 1 if match_status == "completed": stage_stats[stage_name]["completed"] += 1 elif match_status == "ongoing": stage_stats[stage_name]["ongoing"] += 1 else: stage_stats[stage_name]["upcoming"] += 1 if match_date: stage_stats[stage_name]["dates"].append(match_date) # Build stage summaries stages: list[StageMatches] = [] for stage_name, stats in stage_stats.items(): dates = stats["dates"] start_date = min(dates) if dates else None end_date = max(dates) if dates else None stages.append(StageMatches( name=stage_name, match_count=stats["count"], completed=stats["completed"], upcoming=stats["upcoming"], ongoing=stats["ongoing"], start_date=start_date, end_date=end_date, )) return MatchSummary( event_id=event_id, total_matches=total, completed=completed, upcoming=upcoming, ongoing=ongoing, stages=stages, )