Add Player season hitting overview - #58
Conversation
Add GET /players/hitting?season=...&player_id=..., a DB-only season-level hitting overview for one Player. - Confirm Player-season membership from player_seasons via a focused get_player_catalog_entry repository read before loading hitting data. - Derive TB, AVG, OBP, SLG, OPS and the K%/BB%/HR% plate-appearance rate profile in app/analytics/player_hitting.py; undefined rates stay None. - Render summary cards and a single-colour PA rate profile chart with local Plotly; no MLB comparison, rankings, or team-stint claims. - Link the Player directory to the overview when hitting is stored, and show the real import command otherwise. - Introduce a tiny player_base.html for Player primary-nav state. Refs #57 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ording Validate that strikeouts, walks, and home runs do not exceed plate appearances, and that hits and strikeouts do not exceed at-bats, before building the plate-appearance rate profile. A corrupted stored row now raises PlayerHittingAnalysisError and renders the route's 409 state instead of escaping as a Pydantic ValidationError. The schema bounds remain as a second integrity boundary. Describe the overview as the stored season aggregate rather than a full season, since an in-progress season can be re-imported as its totals grow, and keep the separate multi-club caveat. Refs #57 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@claude please review |
|
Claude finished @Mattsface's task in 2m 55s —— View job Review: Add Player season hitting overview
This is a well-executed PR — I don't have any blocking findings. Highlights and verification notes below. What I checked closelyNumeric bounds are provably safe, not just tested. Migration-order concern I ruled out. Data-integrity and undefined-rate semantics match AGENTS.md's requirements precisely: zero-denominator rates are Architecture follows the repo's layering cleanly: analytics has zero FastAPI/SQLAlchemy/Plotly/MLB imports, the route ( Tests are strong: hand-worked formula values, zero-denominator branches, corrupted-row error messages (including which bound is reported first when multiple are violated), schema-validator drift rejection, and full web-layer coverage of every browser state ( Nitpicks (non-blocking, optional)
LimitationI was not able to run Branch: |
Summary
Adds the first real Player analytics page for issue #57.
GET /players/hitting?season=...&player_id=...player_seasonsData integrity
The analytics layer explicitly rejects impossible stored relationships such as:
These surface as the existing browser-facing 409 conflict state rather than escaping as schema/runtime errors.
Semantics
The page describes the Player season aggregate currently stored locally.
It does not imply:
Multi-club seasons remain one combined stored aggregate.
Preserved behavior
This PR does not add:
Existing Team navigation, Team analytics,
/players, and/healthremain intact.Testing
Coverage includes:
Closes #57.