Closes#12
- tweak_archetype(): prompts user for updated archetype stats (avg/obp/slg/bb%/k% vs L and R, power and batted-ball profile, baserunning for batters), then recalculates D20 card ratings via the existing calculator
- manual_adjustments(): prompts user to choose a split (vs L or vs R), displays all 22 D20 chance fields with running total, accepts field-number + value edits, and warns if total deviates from 108
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#11
`starter_rating`, `relief_rating`, and `closer_rating` were hardcoded
stubs (5/5/None) in `create_pitching_card`. The chosen `PitcherArchetype`
already carries these values; now they are propagated through `card_data`
when the pitcher workflow builds its initial dict and consumed correctly
when writing the pitching card record to the database.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#9
Previously SEASON_PCT was hardcoded to 81/162 (~0.5) while END_DATE was
set to 20050731 (~65% through the season). Running retrosheet_data.py
directly (without the CLI which overrides SEASON_PCT at runtime) would
silently generate cards using half-season normalizations on stats covering
a larger portion of the season.
Fix: move START_DATE/END_DATE before SEASON_PCT and derive SEASON_PCT
from the date range using SEASON_END_DATE (2005 regular season end).
Now changing END_DATE automatically produces the correct SEASON_PCT.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#14
Five globals (MIN_PA_VL, MIN_PA_VR, MIN_TBF_VL, MIN_TBF_VR, CARDSET_ID)
were derived from PLAYER_DESCRIPTION at module load time, creating a
hidden ordering dependency: any value baked in before the CLI overrides
PLAYER_DESCRIPTION would be silently wrong if a caller relied on the
derived relationship. The CLI explicitly sets all of them anyway, so
replacing with scalar defaults makes the module self-contained and safe.
Also collapses LAST_WEEK_RATIO dead ternary (both branches were 0.0).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#13
Replace `from db_calls_card_creation import *` with an explicit
`from db_calls_card_creation import PitcherData`. Only PitcherData
is referenced in creation_helpers.py; the wildcard was also
pulling in all Peewee ORM internals via a transitive
`from peewee import *`, polluting the namespace.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces logger.error() with logger.exception() so the full stack trace
is captured when a pitcher card fails to generate, making it possible to
diagnose the root cause rather than just seeing the error message.
Closes#17
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#19
The conditional `0.0 if PLAYER_DESCRIPTION == 'Live' else 0.0` is dead
code: both branches evaluate to the same value. Simplified to a direct
assignment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#16
Deleted test_positions_df which called an async function synchronously
(returning a coroutine, not a DataFrame) and asserted True == True.
Zero coverage. Also removed the now-unused pd_positions_df import.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Switch hitters batting vs LHP hit right-handed (pull=lf, oppo=rf).
Switch hitters batting vs RHP hit left-handed (pull=rf, oppo=lf).
Copy-paste error had both pull_side branches returning the same value.
Closes#5
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The second `elif "DO*" in data_string` was dead code — the first always
matched, so `spaces -= 2` for the DO** variant was silently skipped.
Fix: check "DO**" first (spaces -= 2), then "DO*" (spaces -= 1).
Closes#6
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#7
The fallback branch of create_pit_position() used `int(df_data["key_bbref"])`
which always raises ValueError for string IDs like 'verlaju01'. The exception
was silently swallowed, causing pitchers without defensive stats to receive no
position record at all.
Fix: use `int(float(df_data["player_id"]))` to match the pattern used in
create_pitching_card() on the same file.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#10
Replace `except Exception: pass` with `except KeyError: pass` so only
the expected missing-attribute case (`cell["data-append-csv"]` not
present) is silently skipped. Network errors, encoding issues, and
other unexpected exceptions will now propagate instead of being hidden.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#24
Pins the two unpinned dependencies in requirements.txt:
- peewee (unversioned → 3.19.0)
- polars (unversioned → 1.36.1)
All other dependencies were already pinned with ==.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#15
`any` (lowercase) refers to the builtin function, not `typing.Any`.
Added `Any` to the `typing` imports in both files and updated the
`cardset` parameter annotation accordingly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#21
All 14 async test methods in tests/test_automated_data_fetcher.py were
missing @pytest.mark.asyncio. Without it, pytest collects them and
silently passes without executing the coroutine body, providing no
coverage.
Added explicit @pytest.mark.asyncio to each async def test_* method.
This makes the async intent unambiguous and is robust against any
future asyncio_mode configuration changes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>