from __future__ import annotations import os import sys import unittest import pandas as pd sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) from data.mlb_starters import ( build_oddsapi_starter_fallback_map, merge_probable_starters_with_odds_fallback, ) class TestMlbStarters(unittest.TestCase): def test_oddsapi_fallback_can_fill_tba_matchup_from_pitcher_team_inference(self) -> None: props_feed = pd.DataFrame( [ { "event_id": "event-1", "away_team": "New York Yankees", "home_team": "San Francisco Giants", "market_family": "k", "selection_scope": "pitcher", "player_name_raw": "Max Fried", }, { "event_id": "event-1", "away_team": "New York Yankees", "home_team": "San Francisco Giants", "market_family": "k", "selection_scope": "pitcher", "player_name_raw": "Logan Webb", }, ] ) pitcher_statcast_df = pd.DataFrame( [ { "player_name": "Max Fried", "inning_topbot": "Bottom", "away_team": "New York Yankees", "home_team": "San Francisco Giants", }, { "player_name": "Logan Webb", "inning_topbot": "Top", "away_team": "New York Yankees", "home_team": "San Francisco Giants", }, ] ) primary = { ("new york yankees", "san francisco giants"): { "away_team_raw": "New York Yankees", "home_team_raw": "San Francisco Giants", "away_pitcher": None, "home_pitcher": None, "away_pitcher_source": "unresolved", "home_pitcher_source": "unresolved", "starter_cache_source": "statsapi_probable_pitcher", "fallback_used": False, } } fallback = build_oddsapi_starter_fallback_map( props_feed=props_feed, primary_starters=primary, pitcher_statcast_df=pitcher_statcast_df, ) merged = merge_probable_starters_with_odds_fallback(primary, fallback) row = merged[("new york yankees", "san francisco giants")] self.assertEqual(row["away_pitcher"], "Max Fried") self.assertEqual(row["home_pitcher"], "Logan Webb") self.assertEqual(row["away_pitcher_source"], "oddsapi_pitcher_strikeouts_two_candidate_match") self.assertEqual(row["home_pitcher_source"], "oddsapi_pitcher_strikeouts_two_candidate_match") self.assertEqual(row["starter_cache_source"], "statsapi_plus_oddsapi_fallback") self.assertTrue(bool(row["fallback_used"])) def test_oddsapi_fallback_does_not_override_existing_mlb_side(self) -> None: props_feed = pd.DataFrame( [ { "event_id": "event-2", "away_team": "Cleveland Guardians", "home_team": "Detroit Tigers", "market_family": "k", "selection_scope": "pitcher", "player_name_raw": "Tanner Bibee", }, { "event_id": "event-2", "away_team": "Cleveland Guardians", "home_team": "Detroit Tigers", "market_family": "k", "selection_scope": "pitcher", "player_name_raw": "Tarik Skubal", }, ] ) primary = { ("cleveland guardians", "detroit tigers"): { "away_team_raw": "Cleveland Guardians", "home_team_raw": "Detroit Tigers", "away_pitcher": "Tanner Bibee", "home_pitcher": None, "away_pitcher_source": "statsapi_probable_pitcher", "home_pitcher_source": "unresolved", "starter_cache_source": "statsapi_probable_pitcher", "fallback_used": False, } } fallback = build_oddsapi_starter_fallback_map( props_feed=props_feed, primary_starters=primary, pitcher_statcast_df=None, ) merged = merge_probable_starters_with_odds_fallback(primary, fallback) row = merged[("cleveland guardians", "detroit tigers")] self.assertEqual(row["away_pitcher"], "Tanner Bibee") self.assertEqual(row["away_pitcher_source"], "statsapi_probable_pitcher") self.assertEqual(row["home_pitcher"], "Tarik Skubal") self.assertEqual(row["home_pitcher_source"], "oddsapi_pitcher_strikeouts_single_candidate_match") self.assertEqual(row["starter_cache_source"], "statsapi_plus_oddsapi_fallback") if __name__ == "__main__": unittest.main()