refactor: deduplicate pitcher formula and test constants
All checks were successful
Build Docker Image / build (push) Successful in 8m46s
All checks were successful
Build Docker Image / build (push) Successful in 8m46s
Extract shared pitcher value computation into _pitcher_value() helper. Consolidate duplicated column lists and index helper in season stats tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bd8e4578cc
commit
6580c1b431
@ -37,14 +37,18 @@ def compute_batter_value(stats) -> float:
|
|||||||
return float(stats.pa + tb * 2)
|
return float(stats.pa + tb * 2)
|
||||||
|
|
||||||
|
|
||||||
|
def _pitcher_value(stats) -> float:
|
||||||
|
return stats.outs / 3 + stats.strikeouts
|
||||||
|
|
||||||
|
|
||||||
def compute_sp_value(stats) -> float:
|
def compute_sp_value(stats) -> float:
|
||||||
"""IP + K where IP = outs / 3."""
|
"""IP + K where IP = outs / 3."""
|
||||||
return stats.outs / 3 + stats.strikeouts
|
return _pitcher_value(stats)
|
||||||
|
|
||||||
|
|
||||||
def compute_rp_value(stats) -> float:
|
def compute_rp_value(stats) -> float:
|
||||||
"""IP + K (same formula as SP; thresholds differ)."""
|
"""IP + K (same formula as SP; thresholds differ)."""
|
||||||
return stats.outs / 3 + stats.strikeouts
|
return _pitcher_value(stats)
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@ -97,33 +97,75 @@ def make_pitching_stats(player, team, season=10, **kwargs):
|
|||||||
return PitchingSeasonStats.create(player=player, team=team, season=season, **kwargs)
|
return PitchingSeasonStats.create(player=player, team=team, season=season, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
# ── Shared column-list constants ─────────────────────────────────────────────
|
||||||
|
|
||||||
|
_BATTING_STAT_COLS = [
|
||||||
|
"games",
|
||||||
|
"pa",
|
||||||
|
"ab",
|
||||||
|
"hits",
|
||||||
|
"doubles",
|
||||||
|
"triples",
|
||||||
|
"hr",
|
||||||
|
"rbi",
|
||||||
|
"runs",
|
||||||
|
"bb",
|
||||||
|
"strikeouts",
|
||||||
|
"hbp",
|
||||||
|
"sac",
|
||||||
|
"ibb",
|
||||||
|
"gidp",
|
||||||
|
"sb",
|
||||||
|
"cs",
|
||||||
|
]
|
||||||
|
|
||||||
|
_PITCHING_STAT_COLS = [
|
||||||
|
"games",
|
||||||
|
"games_started",
|
||||||
|
"outs",
|
||||||
|
"strikeouts",
|
||||||
|
"bb",
|
||||||
|
"hits_allowed",
|
||||||
|
"runs_allowed",
|
||||||
|
"earned_runs",
|
||||||
|
"hr_allowed",
|
||||||
|
"hbp",
|
||||||
|
"wild_pitches",
|
||||||
|
"balks",
|
||||||
|
"wins",
|
||||||
|
"losses",
|
||||||
|
"holds",
|
||||||
|
"saves",
|
||||||
|
"blown_saves",
|
||||||
|
]
|
||||||
|
|
||||||
|
_KEY_COLS = ["player", "team", "season"]
|
||||||
|
_META_COLS = ["last_game", "last_updated_at"]
|
||||||
|
|
||||||
|
|
||||||
|
# ── Shared index helper ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
|
def _get_index_columns(db_conn, table: str) -> set:
|
||||||
|
"""Return a set of frozensets, each being the column set of one index."""
|
||||||
|
indexes = db_conn.execute_sql(f"PRAGMA index_list({table})").fetchall()
|
||||||
|
result = set()
|
||||||
|
for idx in indexes:
|
||||||
|
idx_name = idx[1]
|
||||||
|
cols = db_conn.execute_sql(f"PRAGMA index_info({idx_name})").fetchall()
|
||||||
|
result.add(frozenset(col[2] for col in cols))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
# ── Unit: column completeness ────────────────────────────────────────────────
|
# ── Unit: column completeness ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
class TestBattingColumnCompleteness:
|
class TestBattingColumnCompleteness:
|
||||||
"""All required columns are present in BattingSeasonStats."""
|
"""All required columns are present in BattingSeasonStats."""
|
||||||
|
|
||||||
EXPECTED_COLS = [
|
EXPECTED_COLS = _BATTING_STAT_COLS
|
||||||
"games",
|
KEY_COLS = _KEY_COLS
|
||||||
"pa",
|
META_COLS = _META_COLS
|
||||||
"ab",
|
|
||||||
"hits",
|
|
||||||
"doubles",
|
|
||||||
"triples",
|
|
||||||
"hr",
|
|
||||||
"rbi",
|
|
||||||
"runs",
|
|
||||||
"bb",
|
|
||||||
"strikeouts",
|
|
||||||
"hbp",
|
|
||||||
"sac",
|
|
||||||
"ibb",
|
|
||||||
"gidp",
|
|
||||||
"sb",
|
|
||||||
"cs",
|
|
||||||
]
|
|
||||||
KEY_COLS = ["player", "team", "season"]
|
|
||||||
META_COLS = ["last_game", "last_updated_at"]
|
|
||||||
|
|
||||||
def test_stat_columns_present(self):
|
def test_stat_columns_present(self):
|
||||||
"""All batting aggregate columns are present."""
|
"""All batting aggregate columns are present."""
|
||||||
@ -147,27 +189,9 @@ class TestBattingColumnCompleteness:
|
|||||||
class TestPitchingColumnCompleteness:
|
class TestPitchingColumnCompleteness:
|
||||||
"""All required columns are present in PitchingSeasonStats."""
|
"""All required columns are present in PitchingSeasonStats."""
|
||||||
|
|
||||||
EXPECTED_COLS = [
|
EXPECTED_COLS = _PITCHING_STAT_COLS
|
||||||
"games",
|
KEY_COLS = _KEY_COLS
|
||||||
"games_started",
|
META_COLS = _META_COLS
|
||||||
"outs",
|
|
||||||
"strikeouts",
|
|
||||||
"bb",
|
|
||||||
"hits_allowed",
|
|
||||||
"runs_allowed",
|
|
||||||
"earned_runs",
|
|
||||||
"hr_allowed",
|
|
||||||
"hbp",
|
|
||||||
"wild_pitches",
|
|
||||||
"balks",
|
|
||||||
"wins",
|
|
||||||
"losses",
|
|
||||||
"holds",
|
|
||||||
"saves",
|
|
||||||
"blown_saves",
|
|
||||||
]
|
|
||||||
KEY_COLS = ["player", "team", "season"]
|
|
||||||
META_COLS = ["last_game", "last_updated_at"]
|
|
||||||
|
|
||||||
def test_stat_columns_present(self):
|
def test_stat_columns_present(self):
|
||||||
"""All pitching aggregate columns are present."""
|
"""All pitching aggregate columns are present."""
|
||||||
@ -194,25 +218,7 @@ class TestPitchingColumnCompleteness:
|
|||||||
class TestBattingDefaultValues:
|
class TestBattingDefaultValues:
|
||||||
"""All integer stat columns default to 0; nullable meta fields default to None."""
|
"""All integer stat columns default to 0; nullable meta fields default to None."""
|
||||||
|
|
||||||
INT_STAT_COLS = [
|
INT_STAT_COLS = _BATTING_STAT_COLS
|
||||||
"games",
|
|
||||||
"pa",
|
|
||||||
"ab",
|
|
||||||
"hits",
|
|
||||||
"doubles",
|
|
||||||
"triples",
|
|
||||||
"hr",
|
|
||||||
"rbi",
|
|
||||||
"runs",
|
|
||||||
"bb",
|
|
||||||
"strikeouts",
|
|
||||||
"hbp",
|
|
||||||
"sac",
|
|
||||||
"ibb",
|
|
||||||
"gidp",
|
|
||||||
"sb",
|
|
||||||
"cs",
|
|
||||||
]
|
|
||||||
|
|
||||||
def test_all_int_columns_default_to_zero(self):
|
def test_all_int_columns_default_to_zero(self):
|
||||||
"""Every integer stat column defaults to 0 on an unsaved instance."""
|
"""Every integer stat column defaults to 0 on an unsaved instance."""
|
||||||
@ -235,25 +241,7 @@ class TestBattingDefaultValues:
|
|||||||
class TestPitchingDefaultValues:
|
class TestPitchingDefaultValues:
|
||||||
"""All integer stat columns default to 0; nullable meta fields default to None."""
|
"""All integer stat columns default to 0; nullable meta fields default to None."""
|
||||||
|
|
||||||
INT_STAT_COLS = [
|
INT_STAT_COLS = _PITCHING_STAT_COLS
|
||||||
"games",
|
|
||||||
"games_started",
|
|
||||||
"outs",
|
|
||||||
"strikeouts",
|
|
||||||
"bb",
|
|
||||||
"hits_allowed",
|
|
||||||
"runs_allowed",
|
|
||||||
"earned_runs",
|
|
||||||
"hr_allowed",
|
|
||||||
"hbp",
|
|
||||||
"wild_pitches",
|
|
||||||
"balks",
|
|
||||||
"wins",
|
|
||||||
"losses",
|
|
||||||
"holds",
|
|
||||||
"saves",
|
|
||||||
"blown_saves",
|
|
||||||
]
|
|
||||||
|
|
||||||
def test_all_int_columns_default_to_zero(self):
|
def test_all_int_columns_default_to_zero(self):
|
||||||
"""Every integer stat column defaults to 0 on an unsaved instance."""
|
"""Every integer stat column defaults to 0 on an unsaved instance."""
|
||||||
@ -428,56 +416,36 @@ class TestPitchingDeltaUpdate:
|
|||||||
class TestBattingIndexExistence:
|
class TestBattingIndexExistence:
|
||||||
"""Required indexes exist on batting_season_stats."""
|
"""Required indexes exist on batting_season_stats."""
|
||||||
|
|
||||||
def _get_index_columns(self, db_conn, table):
|
|
||||||
"""Return a set of frozensets, each being the column set of one index."""
|
|
||||||
indexes = db_conn.execute_sql(f"PRAGMA index_list({table})").fetchall()
|
|
||||||
result = set()
|
|
||||||
for idx in indexes:
|
|
||||||
idx_name = idx[1]
|
|
||||||
cols = db_conn.execute_sql(f"PRAGMA index_info({idx_name})").fetchall()
|
|
||||||
result.add(frozenset(col[2] for col in cols))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def test_unique_index_on_player_team_season(self, setup_test_db):
|
def test_unique_index_on_player_team_season(self, setup_test_db):
|
||||||
"""A unique index covering (player_id, team_id, season) exists."""
|
"""A unique index covering (player_id, team_id, season) exists."""
|
||||||
index_sets = self._get_index_columns(setup_test_db, "batting_season_stats")
|
index_sets = _get_index_columns(setup_test_db, "batting_season_stats")
|
||||||
assert frozenset({"player_id", "team_id", "season"}) in index_sets
|
assert frozenset({"player_id", "team_id", "season"}) in index_sets
|
||||||
|
|
||||||
def test_index_on_team_season(self, setup_test_db):
|
def test_index_on_team_season(self, setup_test_db):
|
||||||
"""An index covering (team_id, season) exists."""
|
"""An index covering (team_id, season) exists."""
|
||||||
index_sets = self._get_index_columns(setup_test_db, "batting_season_stats")
|
index_sets = _get_index_columns(setup_test_db, "batting_season_stats")
|
||||||
assert frozenset({"team_id", "season"}) in index_sets
|
assert frozenset({"team_id", "season"}) in index_sets
|
||||||
|
|
||||||
def test_index_on_player_season(self, setup_test_db):
|
def test_index_on_player_season(self, setup_test_db):
|
||||||
"""An index covering (player_id, season) exists."""
|
"""An index covering (player_id, season) exists."""
|
||||||
index_sets = self._get_index_columns(setup_test_db, "batting_season_stats")
|
index_sets = _get_index_columns(setup_test_db, "batting_season_stats")
|
||||||
assert frozenset({"player_id", "season"}) in index_sets
|
assert frozenset({"player_id", "season"}) in index_sets
|
||||||
|
|
||||||
|
|
||||||
class TestPitchingIndexExistence:
|
class TestPitchingIndexExistence:
|
||||||
"""Required indexes exist on pitching_season_stats."""
|
"""Required indexes exist on pitching_season_stats."""
|
||||||
|
|
||||||
def _get_index_columns(self, db_conn, table):
|
|
||||||
"""Return a set of frozensets, each being the column set of one index."""
|
|
||||||
indexes = db_conn.execute_sql(f"PRAGMA index_list({table})").fetchall()
|
|
||||||
result = set()
|
|
||||||
for idx in indexes:
|
|
||||||
idx_name = idx[1]
|
|
||||||
cols = db_conn.execute_sql(f"PRAGMA index_info({idx_name})").fetchall()
|
|
||||||
result.add(frozenset(col[2] for col in cols))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def test_unique_index_on_player_team_season(self, setup_test_db):
|
def test_unique_index_on_player_team_season(self, setup_test_db):
|
||||||
"""A unique index covering (player_id, team_id, season) exists."""
|
"""A unique index covering (player_id, team_id, season) exists."""
|
||||||
index_sets = self._get_index_columns(setup_test_db, "pitching_season_stats")
|
index_sets = _get_index_columns(setup_test_db, "pitching_season_stats")
|
||||||
assert frozenset({"player_id", "team_id", "season"}) in index_sets
|
assert frozenset({"player_id", "team_id", "season"}) in index_sets
|
||||||
|
|
||||||
def test_index_on_team_season(self, setup_test_db):
|
def test_index_on_team_season(self, setup_test_db):
|
||||||
"""An index covering (team_id, season) exists."""
|
"""An index covering (team_id, season) exists."""
|
||||||
index_sets = self._get_index_columns(setup_test_db, "pitching_season_stats")
|
index_sets = _get_index_columns(setup_test_db, "pitching_season_stats")
|
||||||
assert frozenset({"team_id", "season"}) in index_sets
|
assert frozenset({"team_id", "season"}) in index_sets
|
||||||
|
|
||||||
def test_index_on_player_season(self, setup_test_db):
|
def test_index_on_player_season(self, setup_test_db):
|
||||||
"""An index covering (player_id, season) exists."""
|
"""An index covering (player_id, season) exists."""
|
||||||
index_sets = self._get_index_columns(setup_test_db, "pitching_season_stats")
|
index_sets = _get_index_columns(setup_test_db, "pitching_season_stats")
|
||||||
assert frozenset({"player_id", "season"}) in index_sets
|
assert frozenset({"player_id", "season"}) in index_sets
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user