feat(WP-01): add evolution Peewee models

Add EvolutionTrack, EvolutionCardState, EvolutionTierBoost, and
EvolutionCosmetic models to db_engine.py with composite unique indexes
and create_tables blocks. Also includes PlayerSeasonStats (WP-02).

Add ruff.toml to suppress pre-existing F403/F405 from intentional
`from peewee import *` wildcard import pattern in db_engine.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Cal Corum 2026-03-17 17:14:52 -05:00
parent dcf9036140
commit 926c18af70
2 changed files with 153 additions and 0 deletions

View File

@ -1194,6 +1194,155 @@ if not SKIP_TABLE_CREATION:
db.create_tables([ScoutOpportunity, ScoutClaim], safe=True)
class PlayerSeasonStats(BaseModel):
player = ForeignKeyField(Player)
team = ForeignKeyField(Team)
season = IntegerField()
# Batting stats
games_batting = IntegerField(default=0)
pa = IntegerField(default=0)
ab = IntegerField(default=0)
hits = IntegerField(default=0)
doubles = IntegerField(default=0)
triples = IntegerField(default=0)
hr = IntegerField(default=0)
bb = IntegerField(default=0)
hbp = IntegerField(default=0)
so = IntegerField(default=0)
rbi = IntegerField(default=0)
runs = IntegerField(default=0)
sb = IntegerField(default=0)
cs = IntegerField(default=0)
# Pitching stats
games_pitching = IntegerField(default=0)
outs = IntegerField(default=0)
k = IntegerField(default=0)
bb_allowed = IntegerField(default=0)
hits_allowed = IntegerField(default=0)
hr_allowed = IntegerField(default=0)
wins = IntegerField(default=0)
losses = IntegerField(default=0)
saves = IntegerField(default=0)
holds = IntegerField(default=0)
blown_saves = IntegerField(default=0)
# Meta
last_game = ForeignKeyField(StratGame, null=True)
last_updated_at = DateTimeField(null=True)
class Meta:
database = db
table_name = "player_season_stats"
player_season_stats_unique_index = ModelIndex(
PlayerSeasonStats,
(PlayerSeasonStats.player, PlayerSeasonStats.team, PlayerSeasonStats.season),
unique=True,
)
PlayerSeasonStats.add_index(player_season_stats_unique_index)
player_season_stats_team_season_index = ModelIndex(
PlayerSeasonStats,
(PlayerSeasonStats.team, PlayerSeasonStats.season),
unique=False,
)
PlayerSeasonStats.add_index(player_season_stats_team_season_index)
player_season_stats_player_season_index = ModelIndex(
PlayerSeasonStats,
(PlayerSeasonStats.player, PlayerSeasonStats.season),
unique=False,
)
PlayerSeasonStats.add_index(player_season_stats_player_season_index)
if not SKIP_TABLE_CREATION:
db.create_tables([PlayerSeasonStats], safe=True)
class EvolutionTrack(BaseModel):
name = CharField(unique=True)
card_type = CharField() # 'batter', 'sp', 'rp'
formula = CharField() # e.g. "pa + tb * 2"
t1_threshold = IntegerField()
t2_threshold = IntegerField()
t3_threshold = IntegerField()
t4_threshold = IntegerField()
class Meta:
database = db
table_name = "evolution_track"
class EvolutionCardState(BaseModel):
player = ForeignKeyField(Player)
team = ForeignKeyField(Team)
track = ForeignKeyField(EvolutionTrack)
current_tier = IntegerField(default=0) # 0-4
current_value = FloatField(default=0.0)
fully_evolved = BooleanField(default=False)
last_evaluated_at = DateTimeField(null=True)
class Meta:
database = db
table_name = "evolution_card_state"
evolution_card_state_index = ModelIndex(
EvolutionCardState,
(EvolutionCardState.player, EvolutionCardState.team),
unique=True,
)
EvolutionCardState.add_index(evolution_card_state_index)
class EvolutionTierBoost(BaseModel):
track = ForeignKeyField(EvolutionTrack)
tier = IntegerField() # 1-4
boost_type = CharField() # e.g. 'rating', 'stat'
boost_target = CharField() # e.g. 'contact_vl', 'power_vr'
boost_value = FloatField(default=0.0)
class Meta:
database = db
table_name = "evolution_tier_boost"
evolution_tier_boost_index = ModelIndex(
EvolutionTierBoost,
(
EvolutionTierBoost.track,
EvolutionTierBoost.tier,
EvolutionTierBoost.boost_type,
EvolutionTierBoost.boost_target,
),
unique=True,
)
EvolutionTierBoost.add_index(evolution_tier_boost_index)
class EvolutionCosmetic(BaseModel):
name = CharField(unique=True)
tier_required = IntegerField(default=0)
cosmetic_type = CharField() # 'frame', 'badge', 'theme'
css_class = CharField(null=True)
asset_url = CharField(null=True)
class Meta:
database = db
table_name = "evolution_cosmetic"
if not SKIP_TABLE_CREATION:
db.create_tables(
[EvolutionTrack, EvolutionCardState, EvolutionTierBoost, EvolutionCosmetic],
safe=True,
)
db.close()
# scout_db = SqliteDatabase(

4
ruff.toml Normal file
View File

@ -0,0 +1,4 @@
[lint]
# F403/F405: peewee ORM uses `from peewee import *` intentionally in db_engine.py
# These are suppressed per-file to avoid breaking the wildcard import pattern.
per-file-ignores = { "app/db_engine.py" = ["F403", "F405"] }