Consolidate shared helpers (format_rating, format_swar, tier_style,
format_relative_time) into widgets/mod.rs and screens/mod.rs. Replace
heap allocations with stack arrays and HashSets, parallelize DB queries
with tokio::try_join, wrap schema init in transactions, use OnceLock for
invariant hashes, and fix clippy warnings. Auto-sync on dashboard mount
when last sync >24h ago. All 105 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add league standings with Division and Wild Card tabs, fetched from API
with SQLite cache for instant display on screen open. Document 11 new
future features in project plan and add cargo check post-edit hook.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Roster: sWAR only sums majors, stateful table rendering for j/k scroll,
rows sorted batters-first for correct selection mapping.
Matchup: initial focus highlight, descriptive sort key hints, state
cached on nav-away to preserve opponent/pitcher selections.
Lineup: load/delete/clear promoted to work from any focus, load selector
popup anchored correctly, delete confirmation prompt.
Settings: API key toggle changed to Ctrl+T so t can be typed, per-field
yellow change markers, sWAR/cap formatting to two decimal places.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace all four stub screens with full implementations. Wire up nav bar
with [r/m/l/S] keys and Box<State> ActiveScreen variants. Roster shows
tabbed batter/pitcher tables with card ratings. Matchup adds standalone
analysis with sort modes. Lineup provides two-panel builder with
save/load/delete. Settings offers form-based TOML config editing with
live team validation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copies BatterCalcs.csv and PitcherCalcs.csv into rust/docs/sheets_export/
so the Rust CSV importer can find them at the default path. Verified
import produces identical results to Python DB (490 batters, 502 pitchers).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously only counted pos_1; now uses Player::positions() to tally
all position fields (pos_1-pos_8) so multi-position players are counted
at each eligible position.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add position coverage, IL players, missing card warnings, and detailed
sync status sections to the dashboard
- Fix team sync to include IL/MiL teams (active_only=false), matching
Python behavior so get_my_roster() finds WVIL/WVMiL teams
- Re-fetch all dashboard data after successful sync so changes reflect
immediately without navigating away
- Add sWAR budget bar (90-100% range) with color thresholds from
Team.salary_cap
- Add team-scoped missing card queries and bulk sync status query
- Mark Phase 2 and Phase 3 project plans as complete
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
API returns move_id as string ("Season-013-Week-11-1772073335"), not
i64. Also disable foreign_keys at pool level via SqliteConnectOptions
since transactions reference players/teams that may not exist locally.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The API returns gmid/gmid2 as quoted strings ("258104532423147520")
to avoid JavaScript precision loss. Changed types to Option<String>.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Errors were only visible in the truncated status bar notification.
Add tracing-appender to write to data/sba-scout.log with env-filter
support (RUST_LOG), and add tracing::error! calls alongside all
notification-only error paths for full diagnostic visibility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace blocking event loop with tokio::select! over EventStream, mpsc
channel, and tick interval. Add message bus architecture with AppMessage
enum for background task results. Implement Dashboard with roster summary
cards and API sync, and Gameday with cascading team/pitcher selectors,
matchup table, and 9-slot lineup management with save/load.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Port the Python calc layer to Rust: league stat distributions (avg excludes zeros,
stdev N-1 includes zeros), weighted standardized matchup scoring with switch-hitter
resolution and pitcher inversion, and SHA-256-validated score cache with automatic
rebuild after card imports. 105 tests passing (76 unit + 5 integration + 24 DB).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Port the full data ingestion layer from Python to Rust:
- Typed API client with 10 endpoints, serde response types, and error handling
- Team/player/transaction sync with proper upsert semantics (preserves hand field)
- Batter and pitcher CSV importers with 40+ column mappings each
- Parse helpers for float/int/endurance with 21 unit tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Set up lib.rs for integration test access, add 50 tests covering
calc engine (weights, standardization), model helpers (Player positions,
Lineup JSON roundtrips), and full query layer (in-memory SQLite).
Update PHASE1_PROJECT_PLAN.json to reflect all 12 tasks completed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wire up the full data pipeline for the Rust TUI rewrite:
- SQL schema creation for all 9 tables with correct types, FKs, and constraints
- 20 async query functions (teams, players, cards, lineups, sync status, cache)
- Config loading via figment integrated into main.rs startup flow
- App struct now holds SqlitePool and Settings for screen access
- Roster aggregate query and Lineup JSON helper methods
- Added csv, sha2, regex crates for upcoming phases
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Initialize rust/ subdirectory with ratatui + tokio + sqlx stack,
mirroring the Python module structure. Includes all DB models,
config loader, matchup scoring logic, and screen stubs that
compile cleanly with cargo check.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Redirect all logging to data/logs/sba_scout.log instead of stderr
- Prevents log output from corrupting the Textual TUI display
- Add loading spinner for sync operations to show progress
- Improve error messages for Cloudflare/API errors
- Add TROUBLESHOOTING.md guide for common sync issues
- Exclude data/ directory from git
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix bug where clicking to select a player in the middle of the lineup
would operate on the last added player instead of the clicked row
- Deselect now requires clicking the same row twice (for screenshots)
- Clicking the table after deselect re-enables selection mode
- Fix main.py to actually launch the TUI app
- Add CLAUDE.md with codebase documentation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- New Settings screen (press 'x') for configuring app settings
- Settings stored in data/settings.yaml (user-editable)
- Editable fields: team abbrev, season, API URL, API key (masked), theme
- Team validation against database before saving
- Read-only team info display from database (name, sWAR cap, ID)
- Load order: defaults -> .env -> settings.yaml
- Added pyyaml dependency
Features:
- Lineup Builder screen: set batting order, assign positions, save/load lineups
- Gameday screen: integrated matchup scout + lineup builder side-by-side
- Matchup Scout: analyze batters vs opposing pitchers with standardized scoring
- Standardized scoring system with league AVG/STDEV calculations
- Score caching for fast matchup lookups
Lineup Builder (press 'l'):
- Dual-panel UI with available batters and 9-slot lineup
- Keyboard controls: a=add, r=remove, k/j=reorder, p=change position
- Save/load named lineups, delete saved lineups with 'd'
Gameday screen (press 'g'):
- Left panel: team/pitcher selection with matchup ratings
- Right panel: lineup builder with live matchup ratings per batter
- Players in lineup marked with * in matchup list
- Click highlighted row to toggle selection for screenshots
Other changes:
- Dynamic season configuration (removed hardcoded season=13)
- Added delete_lineup query function
- StandardizedScoreCache model for pre-computed scores
- Auto-rebuild score cache after card imports