from __future__ import annotations from dataclasses import dataclass, field from datetime import datetime from typing import Protocol @dataclass(frozen=True) class ExternalMatch: external_id: str competition_code: str home_team_external_id: str | None away_team_external_id: str | None kickoff_at: datetime | None stadium_external_id: str | None stage: str group_name: str | None = None metadata: dict[str, object] = field(default_factory=dict) @dataclass(frozen=True) class ExternalMatchResult: external_match_id: str status: str home_score: int | None away_score: int | None winner_external_team_id: str | None = None is_giant_killing: bool = False metadata: dict[str, object] = field(default_factory=dict) class MatchDataProvider(Protocol): """Adapter contract for FIFA, Opta, Stats Perform, Sportradar, or internal feeds.""" provider_name: str def fetch_matches(self, *, competition_code: str) -> list[ExternalMatch]: """Return the provider's latest match schedule.""" def fetch_results(self, *, competition_code: str) -> list[ExternalMatchResult]: """Return final/live result updates from the provider.""" class NoopMatchDataProvider: provider_name = "noop" def fetch_matches(self, *, competition_code: str) -> list[ExternalMatch]: return [] def fetch_results(self, *, competition_code: str) -> list[ExternalMatchResult]: return [] class MatchDataProviderRegistry: def __init__(self) -> None: self._providers: dict[str, MatchDataProvider] = {} def register(self, provider: MatchDataProvider) -> None: self._providers[provider.provider_name] = provider def get(self, provider_name: str) -> MatchDataProvider: return self._providers.get(provider_name, NoopMatchDataProvider()) def names(self) -> list[str]: return sorted(self._providers)