Spaces:
Runtime error
Runtime error
| from __future__ import annotations | |
| from ingest.sofascore.fept_mapper import ( | |
| map_lineups_to_fept, | |
| pick_player_rating_from_statistics, | |
| ) | |
| from ingest.sofascore.fept_ingest import build_fept_payload | |
| from ingest.sofascore.kxl_sofascore_ingest import KxlSofascoreIngestResult | |
| from ingest.sofascore.kxl_merge import merge_sofascore_fept | |
| from ingest.sofascore.teams import sides_for_event | |
| from schemas.wc_kxl_dynamic import ( | |
| FedeElenco, | |
| FeptEscalacao, | |
| FeptTitularesEstruturados, | |
| WcKxlMatchInput, | |
| ) | |
| class FakeSofascoreClient: | |
| def __init__(self, event: dict, lineups: dict, player_stats: dict[int, list]): | |
| self._event = event | |
| self._lineups = lineups | |
| self._player_stats = player_stats | |
| def event(self, event_id: int) -> dict: | |
| return self._event | |
| def event_lineups(self, event_id: int) -> dict: | |
| return self._lineups | |
| def player_statistics(self, player_id: int) -> list[dict]: | |
| return self._player_stats.get(player_id, []) | |
| def test_pick_player_rating_prefers_world_cup(): | |
| seasons = [ | |
| { | |
| "uniqueTournament": {"slug": "laliga"}, | |
| "statistics": {"rating": 7.9, "countRating": 20}, | |
| }, | |
| { | |
| "uniqueTournament": {"slug": "world-championship"}, | |
| "statistics": {"rating": 7.2, "countRating": 6}, | |
| }, | |
| ] | |
| assert pick_player_rating_from_statistics(seasons) == 7.2 | |
| def test_map_lineups_to_fept_structured(): | |
| lineups = { | |
| "home": { | |
| "formation": "4-3-3", | |
| "players": [ | |
| { | |
| "substitute": False, | |
| "position": "G", | |
| "player": {"id": 1, "name": "GK"}, | |
| "statistics": {"rating": 7.0}, | |
| }, | |
| { | |
| "substitute": False, | |
| "position": "D", | |
| "player": {"id": 2, "name": "CB"}, | |
| "statistics": {"rating": 6.8}, | |
| }, | |
| { | |
| "substitute": False, | |
| "position": "M", | |
| "player": {"id": 3, "name": "CM"}, | |
| "statistics": {"rating": 7.1}, | |
| }, | |
| { | |
| "substitute": False, | |
| "position": "F", | |
| "player": {"id": 4, "name": "ST"}, | |
| "statistics": {"rating": 7.5}, | |
| }, | |
| { | |
| "substitute": True, | |
| "position": "F", | |
| "player": {"id": 5, "name": "Bench"}, | |
| "statistics": {"rating": 6.0}, | |
| }, | |
| ], | |
| }, | |
| "away": { | |
| "formation": "4-4-2", | |
| "players": [ | |
| { | |
| "substitute": False, | |
| "position": "G", | |
| "player": {"id": 6, "name": "GK2"}, | |
| "statistics": {"rating": 6.9}, | |
| }, | |
| ], | |
| }, | |
| } | |
| fept = map_lineups_to_fept( | |
| lineups, | |
| home_is_event_home=True, | |
| fetch_statistics=lambda _pid: [], | |
| rating_cache={}, | |
| ) | |
| assert fept.esquema_mandante == "4-3-3" | |
| assert fept.esquema_visitante == "4-4-2" | |
| assert fept.mandante_titulares_notas is not None | |
| assert fept.mandante_titulares_notas.goleiro["nome"] == "GK" | |
| assert len(fept.mandante_titulares_notas.atacantes) == 1 | |
| def test_build_fept_payload_with_event_id(): | |
| team_map = { | |
| "Brasil": {"sofascore_id": 4748}, | |
| "Argentina": {"sofascore_id": 4819}, | |
| } | |
| event = { | |
| "id": 99, | |
| "homeTeam": {"id": 4748, "name": "Brazil"}, | |
| "awayTeam": {"id": 4819, "name": "Argentina"}, | |
| } | |
| lineups = { | |
| "home": { | |
| "formation": "4-2-3-1", | |
| "players": [ | |
| { | |
| "substitute": False, | |
| "position": "G", | |
| "player": {"id": 10, "name": "Alisson"}, | |
| "statistics": {"rating": 6.4}, | |
| }, | |
| ], | |
| }, | |
| "away": { | |
| "formation": "4-4-2", | |
| "players": [ | |
| { | |
| "substitute": False, | |
| "position": "G", | |
| "player": {"id": 11, "name": "Martinez"}, | |
| "statistics": {"rating": 7.0}, | |
| }, | |
| ], | |
| }, | |
| } | |
| client = FakeSofascoreClient(event, lineups, {}) | |
| result = build_fept_payload( | |
| event_id=99, | |
| client=client, | |
| team_map=team_map, | |
| ) | |
| assert result.home_team == "Brasil" | |
| assert result.away_team == "Argentina" | |
| assert result.fept.esquema_mandante == "4-2-3-1" | |
| assert result.ratings_found == 2 | |
| def test_merge_sofascore_fept_creates_kxl_match(monkeypatch): | |
| fept = FeptEscalacao( | |
| esquema_mandante="4-2-3-1", | |
| mandante_titulares_notas=FeptTitularesEstruturados( | |
| goleiro={"nome": "Alisson", "nota_sofascore": 7.0}, | |
| ), | |
| ) | |
| def fake_build(**_kwargs): | |
| return KxlSofascoreIngestResult( | |
| home_team="Brasil", | |
| away_team="Argentina", | |
| event_id=99, | |
| match_date=None, | |
| fept=fept, | |
| fede=FedeElenco(), | |
| feju=None, | |
| ratings_found=1, | |
| ratings_missing=0, | |
| absences_home=0, | |
| absences_away=0, | |
| ) | |
| monkeypatch.setattr( | |
| "ingest.sofascore.kxl_merge.build_kxl_sofascore_payload", | |
| fake_build, | |
| ) | |
| kxl, meta = merge_sofascore_fept( | |
| kxl_match=None, | |
| sofascore_event_id=99, | |
| home_team="Brasil", | |
| away_team="Argentina", | |
| ) | |
| assert kxl is not None | |
| assert kxl.fept is not None | |
| assert meta is not None | |
| assert meta["auto_merged"] is True | |
| def test_merge_sofascore_fept_preserves_manual_fept(monkeypatch): | |
| from schemas.wc_kxl_dynamic import FejuArbitro, FedeDesfalque | |
| manual = WcKxlMatchInput( | |
| fept=FeptEscalacao(esquema_mandante="3-5-2"), | |
| ) | |
| def fake_build(**_kwargs): | |
| return KxlSofascoreIngestResult( | |
| home_team="Brasil", | |
| away_team="Argentina", | |
| event_id=99, | |
| match_date=None, | |
| fept=FeptEscalacao(esquema_mandante="4-3-3"), | |
| fede=FedeElenco( | |
| desfalques_mandante=[FedeDesfalque(jogador="Casemiro", posicao="Meio")], | |
| ), | |
| feju=FejuArbitro(nome_arbitro="Piero Maza", perfil="punitivista"), | |
| ratings_found=1, | |
| ratings_missing=0, | |
| absences_home=1, | |
| absences_away=0, | |
| ) | |
| monkeypatch.setattr( | |
| "ingest.sofascore.kxl_merge.build_kxl_sofascore_payload", | |
| fake_build, | |
| ) | |
| kxl, meta = merge_sofascore_fept( | |
| kxl_match=manual, | |
| sofascore_event_id=99, | |
| home_team="Brasil", | |
| away_team="Argentina", | |
| ) | |
| assert kxl.fept.esquema_mandante == "3-5-2" | |
| assert kxl.fede is not None | |
| assert kxl.feju is not None | |
| assert meta["auto_merged"] is False | |
| def test_sides_for_event_swapped(): | |
| event = { | |
| "id": 1, | |
| "homeTeam": {"id": 4819, "name": "Argentina"}, | |
| "awayTeam": {"id": 4748, "name": "Brazil"}, | |
| } | |
| team_map = { | |
| "Brasil": {"sofascore_id": 4748}, | |
| "Argentina": {"sofascore_id": 4819}, | |
| } | |
| home_is_event_home, home_id, away_id = sides_for_event( | |
| event, | |
| home_team="Brasil", | |
| away_team="Argentina", | |
| team_map=team_map, | |
| ) | |
| assert home_is_event_home is False | |
| assert home_id == 4748 | |
| assert away_id == 4819 | |