Documents current branch state, what's built, what's left, known bugs, and decision points so the next session can pick up without re-investigating. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
90 lines
5.2 KiB
Markdown
90 lines
5.2 KiB
Markdown
# FullCard Migration Status
|
||
|
||
**Branch:** `feature/fullcard-migration` (5 commits ahead of main)
|
||
**Last Updated:** 2026-02-26
|
||
|
||
## What This Branch Does
|
||
|
||
Moves card-building logic (fitting continuous chances to discrete 2d6×d20 card mechanics) from the database to Python. Previously, Python sent raw continuous values and the database fitted them — meaning what you sent ≠ what got stored. Now Python builds the complete discrete card structure before POSTing.
|
||
|
||
### New Files
|
||
|
||
| File | Purpose |
|
||
|------|---------|
|
||
| `card_layout.py` | Core card models: PlayResult, CardResult, CardColumn, FullCard, FullBattingCard, FullPitchingCard. Ported from database's `card_creation.py`. Uses `col_*` key names. |
|
||
| `batters/card_builder.py` | `build_batter_full_cards()` — takes vL/vR ratings, returns two FullBattingCard objects |
|
||
| `pitchers/card_builder.py` | `build_pitcher_full_cards()` — same for pitchers |
|
||
| `batters/models.py` | Extracted `BattingCardRatingsModel` from `calcs_batter.py` |
|
||
| `pitchers/models.py` | Extracted `PitchingCardRatingsModel` from `calcs_pitcher.py` |
|
||
| `offense_col_resolver.py` | Maps player→offense_col for retrosheet pipeline (fixed 883 silent KeyErrors) |
|
||
| `tests/test_rate_stats_formulas.py` | Tests for extracted rating model formulas |
|
||
|
||
### Integration Path
|
||
|
||
```
|
||
retrosheet_data.py → calcs_batter.py → build_batter_full_cards() → card_output() → vl_dict.update()
|
||
→ calcs_pitcher.py → build_pitcher_full_cards() → card_output() → vr_dict.update()
|
||
```
|
||
|
||
Card builders are called inside a `try/except` in `calcs_batter.py:339` and `calcs_pitcher.py:134`. On failure, logs a warning and the card still posts without col_* layout data (backwards compatible).
|
||
|
||
## Commits on Branch
|
||
|
||
1. `a72abc0` — Add FullCard/CardColumn/CardResult models and card builder pipeline
|
||
2. `39c652e` — Extract BattingCardRatingsModel and PitchingCardRatingsModel into models.py files
|
||
3. `2bf3a6c` — Fix SLG formula drift in extracted rating models
|
||
4. `32cadb1` — Fix two bugs in pitcher card builder dispatch logic
|
||
5. `db38225` — Add offense_col resolver for retrosheet pipeline to fix 883 silent KeyErrors
|
||
|
||
## What's Left Before Merge
|
||
|
||
### 1. Database Migration (BLOCKING if you want col_* data persisted)
|
||
|
||
The database repo (`paper-dynasty-database`) has a parallel `feature/fullcard-migration` branch with:
|
||
- 9 new nullable TextFields on `BattingCardRatings` and `PitchingCardRatings` tables
|
||
- Pydantic model updates in `routers_v2/battingcardratings.py` and `pitchingcardratings.py`
|
||
- Migration SQL documented but **intentionally not run**
|
||
|
||
Without this migration, the col_* fields in `card_output()` are computed but silently ignored by the API. The card-creation side works either way — it's a no-op until the DB accepts those fields.
|
||
|
||
### 2. `live_series_update.py` Not Integrated
|
||
|
||
This file has its own inline card generation — does NOT use `calcs_batter`/`calcs_pitcher`. Only the retrosheet pipeline benefits from the new card builders. Live series integration is a separate effort.
|
||
|
||
### 3. No Tests for Core New Code
|
||
|
||
`card_layout.py` (1015 lines), `batters/card_builder.py` (802 lines), `pitchers/card_builder.py` (776 lines) have zero test coverage. Priority targets:
|
||
- `get_chances()` — maps continuous values to discrete EXACT_CHANCES
|
||
- `CardColumn.add_result()` / `FullCard.card_fill()` — the filling algorithm
|
||
- `card_output()` — serialization to col_* dict format
|
||
- End-to-end: feed known ratings → assert expected card structure
|
||
|
||
### 4. Test Failures (Pre-existing, Not From This Branch)
|
||
|
||
- `test_wh_singles` — `wh_singles(12, .45)` returns `8.0` vs expected `Decimal('7.95')`. Fails on main too. The test file has a 1-line diff on this branch (import change).
|
||
- 11 failures in `test_automated_data_fetcher.py` — mock setup issues, no diff on this branch.
|
||
|
||
## Key Bugs Fixed During Development
|
||
|
||
1. **Float/Decimal mismatch** — card_layout uses Decimal internally, models use float. Fix: wrap `card_fill()` outputs with `float()` in `assign_bchances()`/`assign_pchances()`.
|
||
2. **PitchingCardRatingsModel xcheck defaults** — Non-zero defaults (xcheck_ss=7.0, etc.) corrupted accumulation. Fix: explicitly zero all xcheck fields in `new_ratings` constructor.
|
||
3. **Pitcher dispatch logic** — Two bugs in how pitcher card builder routed plays to columns.
|
||
4. **offense_col KeyError** — Retrosheet pipeline had no offense_col resolver, causing 883 silent failures.
|
||
|
||
## Architecture Reference
|
||
|
||
Full design doc: `docs/architecture/CARD_BUILDER_REDESIGN.md`
|
||
|
||
Migration phases:
|
||
- **Phase 1 (Extract & Validate)** — Done
|
||
- **Phase 2 (Python Adoption)** — In progress (retrosheet pipeline wired up)
|
||
- **Phase 3 (Database Simplification)** — Pending DB migration + removing fitting logic from DB
|
||
- **Phase 4 (Enhancements)** — Future (contracts/card personalities, preview endpoint)
|
||
|
||
## Decision Points for Next Session
|
||
|
||
1. **Merge as-is?** Branch is safe to merge — col_* fields are computed but harmlessly ignored until DB migrates. Card generation behavior is unchanged.
|
||
2. **Add tests first?** Recommended but not strictly required since card builders are behind try/except.
|
||
3. **Run DB migration?** Enables end-to-end persistence. Requires deploying database branch too.
|
||
4. **Wire up live series?** Separate PR recommended — different pipeline, different concerns.
|