from repositories.match_repository import ( get_match_by_external_id, mark_match_parsed, mark_match_parse_error, clear_match_squad_data, ) from repositories.player_repository import ( get_player_id_by_name_and_team, get_player_id_by_external_id, create_player_from_lineup, ) from repositories.coach_repository import ( get_coach_id_by_name_and_team, get_coach_id_by_external_id, create_coach_from_lineup, ) from repositories.referee_repository import get_referee_id_by_name, upsert_referee from repositories.match_lineup_repository import replace_match_lineups, save_match_lineup_for_editor from repositories.match_coach_repository import replace_match_coaches from repositories.match_referee_repository import replace_match_referees def sync_match_page( match_external_id: str, home_starting: list[dict], away_starting: list[dict], home_bench: list[dict], away_bench: list[dict], home_coaches: list[dict], away_coaches: list[dict], referees: list[dict], ) -> None: match_row = get_match_by_external_id(match_external_id) if not match_row: raise ValueError(f"Match not found by external_id: {match_external_id}") match_id, _, home_team_id, away_team_id = match_row clear_match_squad_data(match_id) created_players_count = 0 created_coaches_count = 0 def resolve_player(player: dict, team_id: int) -> tuple[int | None, str | None]: """Находит игрока из протокола или создаёт его в справочнике автоматически.""" nonlocal created_players_count player_name = str(player.get("player_name") or "").strip() player_external_id = str(player.get("player_external_id") or "").strip() number = str(player.get("number") or "").strip() position = str(player.get("position") or "").strip() player_id = None player_position = None if player_external_id: player_row = get_player_id_by_external_id(player_external_id) if player_row: player_id, player_position = player_row if player_id is None and player_name: player_id = get_player_id_by_name_and_team(player_name, team_id) if player_id is None and player_name: player_row = create_player_from_lineup( team_id=team_id, external_id=player_external_id, full_name=player_name, number=number, position=position, ) if player_row: player_id, player_position = player_row created_players_count += 1 return player_id, player_position or position def resolve_coach(coach: dict, team_id: int) -> int | None: """Находит тренера из протокола или создаёт его в справочнике автоматически.""" nonlocal created_coaches_count coach_name = str(coach.get("coach_name") or "").strip() coach_external_id = str(coach.get("coach_external_id") or "").strip() role = str(coach.get("role") or "").strip() coach_id = None if coach_external_id: coach_id = get_coach_id_by_external_id(coach_external_id) if coach_id is None and coach_name: coach_id = get_coach_id_by_name_and_team(coach_name, team_id) if coach_id is None and coach_name: coach_id = create_coach_from_lineup( team_id=team_id, external_id=coach_external_id, full_name=coach_name, role=role, ) if coach_id: created_coaches_count += 1 return coach_id lineup_rows = [] def append_players(players: list[dict], team_id: int, lineup_type: str) -> None: for player in players: player_id, player_position = resolve_player(player, team_id) lineup_rows.append( { "match_id": match_id, "team_id": team_id, "player_id": player_id, "player_name": player.get("player_name") or "", "number": player.get("number"), "position": player.get("position"), "position_full": player_position, "is_captain": bool(player.get("is_captain")), "lineup_type": lineup_type, "source": "parser", } ) append_players(home_starting, home_team_id, "starting") append_players(away_starting, away_team_id, "starting") append_players(home_bench, home_team_id, "bench") append_players(away_bench, away_team_id, "bench") coach_rows = [] def append_coaches(coaches: list[dict], team_id: int, side: str) -> None: for coach in coaches: coach_id = resolve_coach(coach, team_id) coach_rows.append( { "match_id": match_id, "team_id": team_id, "side": side, "coach_id": coach_id, "coach_name": coach.get("coach_name") or "", "role": coach.get("role"), "source": "parser", } ) append_coaches(home_coaches, home_team_id, "home") append_coaches(away_coaches, away_team_id, "away") referee_rows = [] for referee in referees: referee_name = referee["referee_name"].strip() referee_id = get_referee_id_by_name(referee_name) if referee_id is None: referee_id = upsert_referee(full_name=referee_name) referee_rows.append( { "match_id": match_id, "referee_id": referee_id, "referee_name": referee_name, "role": referee.get("role"), "source": "parser", } ) try: replace_match_lineups(match_id, lineup_rows) replace_match_coaches(match_id, coach_rows) replace_match_referees(match_id, referee_rows) mark_match_parsed(match_external_id) if created_players_count or created_coaches_count: print( f"[parser_game] auto-created for match={match_external_id}: " f"players={created_players_count}, coaches={created_coaches_count}" ) except Exception as e: mark_match_parse_error(match_external_id, str(e)) raise