feat: formula engine for evolution value computation (WP-09) (#74) #85
No reviewers
Labels
No Label
ai-changes-requested
ai-failed
ai-merged
ai-pr-opened
ai-reviewed
ai-reviewing
ai-reviewing
ai-working
bug
enhancement
evolution
performance
phase-0
phase-1a
phase-1b
phase-1c
phase-1d
security
tech-debt
todo
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: cal/paper-dynasty-database#85
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "ai/paper-dynasty-database#74"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #74
Summary
app/services/formula_engine.pywith three pure formula functions, a dispatch helper, and a tier classifiertests/test_formula_engine.py— 19 unit tests, all pass (no database required)What was implemented
compute_batter_value(stats)—PA + TB×2whereTB = 1B + 2×2B + 3×3B + 4×HRcompute_sp_value(stats)—outs/3 + kcompute_rp_value(stats)—outs/3 + k(same formula, different thresholds)compute_value_for_track(card_type, stats)— dispatches to the correct formula bycard_type('batter'/'sp'/'rp'); raisesValueErroron unknown typetier_from_value(value, track)— classifies T0–T4 against track thresholds; accepts both dict (seed fixture) and attribute-style (Peewee model) track objectsNotes
stats.k(notstats.so) to match thePlayerSeasonStatsmodel introduced in WP-02, wherekis the pitcher strikeouts fieldFiles changed
app/services/__init__.py(new, empty)app/services/formula_engine.py(new, 105 lines)tests/test_formula_engine.py(new, 188 lines)AI Code Review
Files Reviewed
app/services/__init__.py(new, empty)app/services/formula_engine.py(new, 105 lines)tests/test_formula_engine.py(new, 188 lines)Findings
Correctness
compute_batter_value: Singles derivation (hits - doubles - triples - hr) is correct. TB formula (singles + 2×2B + 3×3B + 4×HR) is correct. Returns float. ✓compute_sp_value/compute_rp_value:outs / 3 + k— Python true division returns float correctly. Intentional shared formula acknowledged in PR body. ✓compute_value_for_track: Dict dispatch withNonecheck andValueErroron unknown type is clean and correct. ✓tier_from_value: Cascade-if from T4 down is the correct pattern for inclusive-lower boundaries. Dict/attribute dual access is correct. ✓Security
Style & Conventions
BatterStatsandPitcherStatsProtocol classes are defined but not used as type annotations in the function signatures (functions are typedstatswithout annotation). They serve as inline documentation, which is fine, but the protocols don't enforce anything as written. Minor nit, not a blocker.Suggestions
tier_from_valueis exercised againsttrack_dict("batter")only. The SP (t1=10, t2=40, t3=120, t4=240) and RP (t1=3, t2=12, t3=35, t4=70) threshold sets have no tier boundary tests. The logic is identical so the risk is low, but a single SP and RP boundary test each would complete coverage.doubles + triples + hr > hits,singlesgoes negative and TB is undervalued silently. Upstream data should be clean, but amax(0, singles)or an assertion would make the function more defensive. Suggestion only.Verdict: APPROVED
Clean, focused implementation. All three formula functions are correct, the dispatch and tier helpers work as documented, and the 19-unit test suite covers the key boundaries. No security issues, no scope creep, no modifications to existing files.
Automated review by Claude PR Reviewer