import logging from typing import Optional, Literal from fastapi import APIRouter, Query from ...db_engine import ( db, StratPlay, StratGame, Team, Player, model_to_dict, fn, ) from ...dependencies import ( handle_db_errors, add_cache_headers, cache_result, ) logger = logging.getLogger("discord_app") router = APIRouter() @router.get("/") @handle_db_errors @add_cache_headers(max_age=10 * 60) @cache_result(ttl=5 * 60, key_prefix="plays") async def get_plays( game_id: list = Query(default=None), batter_id: list = Query(default=None), season: list = Query(default=None), week: list = Query(default=None), has_defender: Optional[bool] = None, has_catcher: Optional[bool] = None, has_defender_or_catcher: Optional[bool] = None, is_scoring_play: Optional[bool] = None, pitcher_id: list = Query(default=None), obc: list = Query(default=None), inning: list = Query(default=None), batting_order: list = Query(default=None), starting_outs: list = Query(default=None), batter_pos: list = Query(default=None), catcher_id: list = Query(default=None), defender_id: list = Query(default=None), runner_id: list = Query(default=None), offense_team_id: list = Query(default=None), defense_team_id: list = Query(default=None), hit: Optional[int] = None, double: Optional[int] = None, triple: Optional[int] = None, homerun: Optional[int] = None, play_num: list = Query(default=None), error: list = Query(default=None), sb: Optional[int] = None, cs: Optional[int] = None, manager_id: list = Query(default=None), run: Optional[int] = None, e_run: Optional[int] = None, rbi: list = Query(default=None), outs: list = Query(default=None), wild_pitch: Optional[int] = None, is_final_out: Optional[bool] = None, is_go_ahead: Optional[bool] = None, is_tied: Optional[bool] = None, is_new_inning: Optional[bool] = None, min_wpa: Optional[float] = None, max_wpa: Optional[float] = None, pitcher_team_id: list = Query(default=None), short_output: Optional[bool] = False, sort: Optional[str] = None, limit: Optional[int] = 200, page_num: Optional[int] = 1, s_type: Literal["regular", "post", "total", None] = None, ): all_plays = StratPlay.select() if season is not None: s_games = StratGame.select().where(StratGame.season << season) all_plays = all_plays.where(StratPlay.game << s_games) if week is not None: w_games = StratGame.select().where(StratGame.week << week) all_plays = all_plays.where(StratPlay.game << w_games) if has_defender is not None: all_plays = all_plays.where(StratPlay.defender.is_null(False)) if has_catcher is not None: all_plays = all_plays.where(StratPlay.catcher.is_null(False)) if has_defender_or_catcher is not None: all_plays = all_plays.where( (StratPlay.catcher.is_null(False)) | (StratPlay.defender.is_null(False)) ) if game_id is not None: all_plays = all_plays.where(StratPlay.game_id << game_id) if batter_id is not None: all_plays = all_plays.where(StratPlay.batter_id << batter_id) if pitcher_id is not None: all_plays = all_plays.where(StratPlay.pitcher_id << pitcher_id) if obc is not None: all_plays = all_plays.where(StratPlay.on_base_code << obc) if inning is not None: all_plays = all_plays.where(StratPlay.inning_num << inning) if batting_order is not None: all_plays = all_plays.where(StratPlay.batting_order << batting_order) if starting_outs is not None: all_plays = all_plays.where(StratPlay.starting_outs << starting_outs) if batter_pos is not None: all_plays = all_plays.where(StratPlay.batter_pos << batter_pos) if catcher_id is not None: all_plays = all_plays.where(StratPlay.catcher_id << catcher_id) if defender_id is not None: all_plays = all_plays.where(StratPlay.defender_id << defender_id) if runner_id is not None: all_plays = all_plays.where(StratPlay.runner_id << runner_id) if pitcher_team_id is not None: all_teams = Team.select().where(Team.id << pitcher_team_id) all_plays = all_plays.where((StratPlay.pitcher_team << all_teams)) if offense_team_id is not None: all_teams = Team.select().where(Team.id << offense_team_id) all_plays = all_plays.where( (StratPlay.batter_team << all_teams) | (StratPlay.runner_team << all_teams) ) if defense_team_id is not None: all_teams = Team.select().where(Team.id << defense_team_id) all_plays = all_plays.where( (StratPlay.catcher_team << all_teams) | (StratPlay.defender_team << all_teams) ) if hit is not None: all_plays = all_plays.where(StratPlay.hit == hit) if double is not None: all_plays = all_plays.where(StratPlay.double == double) if triple is not None: all_plays = all_plays.where(StratPlay.triple == triple) if homerun is not None: all_plays = all_plays.where(StratPlay.homerun == homerun) if sb is not None: all_plays = all_plays.where(StratPlay.sb == sb) if cs is not None: all_plays = all_plays.where(StratPlay.cs == cs) if wild_pitch is not None: all_plays = all_plays.where(StratPlay.wild_pitch == wild_pitch) if run is not None: all_plays = all_plays.where(StratPlay.run == run) if e_run is not None: all_plays = all_plays.where(StratPlay.e_run == e_run) if rbi is not None: all_plays = all_plays.where(StratPlay.rbi << rbi) if outs is not None: all_plays = all_plays.where(StratPlay.outs << outs) if error is not None: all_plays = all_plays.where(StratPlay.error << error) if manager_id is not None: all_games = StratGame.select().where( (StratGame.away_manager_id << manager_id) | (StratGame.home_manager_id << manager_id) ) all_plays = all_plays.where(StratPlay.game << all_games) if is_final_out is not None: all_plays = all_plays.where(StratPlay.starting_outs + StratPlay.outs == 3) if is_go_ahead is not None: all_plays = all_plays.where(StratPlay.is_go_ahead == is_go_ahead) if is_tied is not None: all_plays = all_plays.where(StratPlay.is_tied == is_tied) if is_new_inning is not None: all_plays = all_plays.where(StratPlay.is_new_inning == is_new_inning) if is_scoring_play is not None: all_plays = all_plays.where( (StratPlay.on_first_final == 4) | (StratPlay.on_second_final == 4) | (StratPlay.on_third_final == 4) | (StratPlay.batter_final == 4) ) if min_wpa is not None: all_plays = all_plays.where(StratPlay.wpa >= min_wpa) if max_wpa is not None: all_plays = all_plays.where(StratPlay.wpa <= max_wpa) if play_num is not None: all_plays = all_plays.where(StratPlay.play_num << play_num) if s_type is not None: season_games = StratGame.select() if s_type == "regular": season_games = season_games.where(StratGame.week <= 18) elif s_type == "post": season_games = season_games.where(StratGame.week > 18) all_plays = all_plays.where(StratPlay.game << season_games) if limit < 1: limit = 1 bat_plays = all_plays.paginate(page_num, limit) if sort == "wpa-desc": all_plays = all_plays.order_by(-fn.ABS(StratPlay.wpa)) elif sort == "wpa-asc": all_plays = all_plays.order_by(fn.ABS(StratPlay.wpa)) elif sort == "re24-desc": all_plays = all_plays.order_by(-fn.ABS(StratPlay.re24_primary)) elif sort == "re24-asc": all_plays = all_plays.order_by(fn.ABS(StratPlay.re24_primary)) elif sort == "newest": all_plays = all_plays.order_by( StratPlay.game_id.desc(), StratPlay.play_num.desc() ) elif sort == "oldest": all_plays = all_plays.order_by(StratPlay.game_id, StratPlay.play_num) all_plays = all_plays.limit(limit) return_plays = { "count": all_plays.count(), "plays": [model_to_dict(x, recurse=not short_output) for x in all_plays], } db.close() return return_plays