- Fix TypeError in check_steal_opportunity by properly mocking catcher defense - Correct tag_from_third test calculation to account for all adjustment conditions - Fix pitcher replacement test by setting appropriate allowed runners threshold - Add comprehensive test coverage for AI service business logic - Implement VS Code testing panel configuration with pytest integration - Create pytest.ini for consistent test execution and warning management - Add test isolation guidelines and factory pattern implementation - Establish 102 passing tests with zero failures 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
9.7 KiB
Model Migration Plan: Data Models + Business Logic Extraction
Overview
This document tracks the migration of models from Discord app to web app, with careful separation of data models from business logic. All extracted business logic is tracked to ensure proper implementation in services.
Migration Principle
Models = Pure Data | Services = Business Logic
- Models: Field definitions, relationships, basic validators
- Services: Complex logic, UI formatting, game management, AI decisions
Phase 1: Foundation Data Models
1. ManagerAi - AI Configuration Data ✅ COMPLETE
Model Migration:
- ✅ Keep: AI parameter fields (steal, running, hold, etc.)
- ✅ Keep: Database relationships
- ✅ Remove: All decision methods
Business Logic to Extract:
| Original Method | Target Service | New Method | Status |
|---|---|---|---|
check_jump() |
AIService | check_steal_opportunity() |
✅ DONE |
tag_from_second() |
AIService | check_tag_from_second() |
✅ DONE |
tag_from_third() |
AIService | check_tag_from_third() |
✅ DONE |
throw_at_uncapped() |
AIService | decide_throw_target() |
✅ DONE |
uncapped_advance() |
AIService | decide_runner_advance() |
✅ DONE |
defense_alignment() |
AIService | set_defensive_alignment() |
✅ DONE |
gb_decide_run() |
AIService | decide_groundball_running() |
✅ DONE |
gb_decide_throw() |
AIService | decide_groundball_throw() |
✅ DONE |
replace_pitcher() |
AIService | should_replace_pitcher() |
✅ DONE |
Implementation Notes:
- ✅ Pure data model created in
app/models/manager_ai.py - ✅ All business logic extracted to
app/services/ai_service.py - ✅ AI response models created in
app/models/ai_responses.py - ✅ Comprehensive unit tests created and passing
- ✅ PostgreSQL integration working
2. Cardset - Card Set Metadata ✅ COMPLETE
Model Migration:
- ✅ Keep: Basic metadata (id, name, ranked_legal)
- ✅ Keep: Relationships to games/players
Business Logic to Extract: None (pure data model)
Implementation Notes:
- ✅ Pure data model created in
app/models/cardset.py - ✅ No business logic extraction needed (already pure data)
- ✅ Comprehensive unit tests created and passing (23 tests)
- ✅ Factory pattern implemented for test data generation
3. Team - Team Identity Data ✅ COMPLETE
Model Migration:
- ✅ Keep: Team data fields (abbrev, names, wallet, etc.)
- ✅ Keep: Simple
descriptionproperty - ✅ Remove:
embedproperty (Discord UI)
Business Logic to Extract:
| Original Method/Property | Target Service | New Method | Status |
|---|---|---|---|
embed property |
UIService | format_team_display() |
✅ DONE |
Implementation Notes:
- ✅ Pure data model created in
app/models/team.py - ✅ Discord
embedproperty extracted toapp/services/ui_service.py - ✅ UIService integrated with dependency injection in service container
- ✅ Comprehensive unit tests created and passing (25 tests)
- ✅ Team factory created for test data generation
- ✅ No business logic extraction needed beyond embed formatting
Phase 2: Player and Card Data
4. Player - Player Metadata
Model Migration:
- ✅ Keep: Player metadata (name, cost, positions, etc.)
- ✅ Keep: Simple
name_with_descproperty - ❌ Remove:
name_card_link()method (Discord markdown)
Business Logic to Extract:
| Original Method/Property | Target Service | New Method | Status |
|---|---|---|---|
name_card_link() |
UIService | format_player_link() |
📋 TODO |
batter_card_url |
UIService | get_batter_card_image() |
📋 TODO |
pitcher_card_url |
UIService | get_pitcher_card_image() |
📋 TODO |
5-8. Card and Rating Models
Models: BattingCard, PitchingCard, BattingRatings, PitchingRatings, BatterScouting, PitcherScouting, Card, PositionRating
Migration: Pure data models - no business logic extraction needed
Phase 3: Game Structure (Critical)
9. Game - Game State and Management ⭐
Model Migration:
- ✅ Keep: Game metadata (teams, season, settings)
- ✅ Keep: Database relationships
- ❌ Remove:
channel_id(Discord-specific) - ❌ Extract: All business logic methods
Business Logic to Extract:
| Original Method/Property | Target Service | New Method | Status |
|---|---|---|---|
initialize_play() |
GameService | initialize_game() |
📋 TODO |
current_play_or_none() |
GameService | get_current_play() |
📋 TODO |
team_lineup() |
GameService | format_team_lineup() |
📋 TODO |
cardset_param_string |
GameService | build_cardset_params() |
📋 TODO |
human_team property |
GameService | get_human_team() |
📋 TODO |
league_name property |
GameService | get_league_name() |
📋 TODO |
Critical Implementation Notes:
initialize_play()contains complex game setup logic (lines 171-230)team_lineup()handles lineup formatting with Discord links- Game state management methods are core to gameplay
10-11. Link Models
Models: GameCardsetLink, RosterLink, Lineup
Migration: Pure relationship models - no extraction needed
Phase 4: Gameplay State (Heaviest Extraction)
12. Play - Gameplay State and Statistics ⭐
Model Migration:
- ✅ Keep: Game state data (scores, outs, runners)
- ✅ Keep: Statistical tracking fields
- ✅ Keep: Relationships to lineups/game
- ❌ Extract: All computed properties and methods
Business Logic to Extract:
| Original Method/Property | Target Service | New Method | Status |
|---|---|---|---|
init_ai() |
GameplayService | initialize_play_ai() |
📋 TODO |
ai_run_diff property |
GameplayService | calculate_run_differential() |
📋 TODO |
ai_is_batting property |
GameplayService | is_ai_batting() |
📋 TODO |
could_walkoff property |
GameplayService | check_walkoff_situation() |
📋 TODO |
scorebug_ascii property |
UIService | format_scoreboard() |
📋 TODO |
Critical Implementation Notes:
scorebug_asciicreates ASCII scoreboard display (lines 1223-1243)- AI integration properties are used throughout gameplay
- Statistical calculations affect game flow
New Web-Specific Models to Add
Web Session and User Management
| Model | Purpose | Status |
|---|---|---|
WebSession |
User session management | 📋 TODO |
UserPreferences |
User settings and preferences | 📋 TODO |
GameViewState |
UI state for live game viewing | 📋 TODO |
Notification |
Web notification queue | 📋 TODO |
Service Implementation Tracker
AIService - AI Decision Making
check_steal_opportunity()- Complex steal decision logiccheck_tag_from_second()- Tag-up decisions from 2ndcheck_tag_from_third()- Tag-up decisions from 3rddecide_throw_target()- Uncapped runner throw decisionsdecide_runner_advance()- Uncapped advance decisionsset_defensive_alignment()- Defensive positioningdecide_groundball_running()- Groundball running decisionsdecide_groundball_throw()- Groundball throw decisionsshould_replace_pitcher()- Pitcher replacement logic
GameService - Game Management
initialize_game()- Game setup and first play creationget_current_play()- Current play retrievalformat_team_lineup()- Lineup display formattingbuild_cardset_params()- Cardset parameter buildingget_human_team()- Human team identificationget_league_name()- League name formatting
GameplayService - Live Game Logic
initialize_play_ai()- AI setup for playscalculate_run_differential()- Score differential calculationis_ai_batting()- AI batting turn detectioncheck_walkoff_situation()- Walkoff scenario detection
UIService - User Interface Formatting
format_team_display()- Team display for web UIformat_player_link()- Player links for webget_batter_card_image()- Batter card image URLsget_pitcher_card_image()- Pitcher card image URLsformat_scoreboard()- Live scoreboard display
Migration Validation Checklist
✅ Model Purity
- No business logic methods in models
- Only field definitions and relationships
- Basic validators for data integrity only
- No Discord dependencies
✅ Service Completeness
- All extracted methods implemented in services
- Services have comprehensive unit tests
- Service methods handle all edge cases from original
- Service integration tested
✅ Functionality Preservation
- All game mechanics preserved
- AI decision-making logic intact
- Statistical tracking complete
- UI formatting adapted for web
Notes and Decisions
Key Architectural Decisions:
- AI Logic Location: All AI decision-making moves to AIService to enable easy testing and modification
- UI Separation: All formatting logic moves to UIService to support multiple interfaces
- Game State Management: Core game logic moves to GameService/GameplayService for business rule centralization
Risk Areas:
- Game.initialize_play(): Complex method with lineup validation and AI setup
- Play model: Heavily used throughout gameplay with many computed properties
- AI integration: AI methods are called throughout game flow and must be properly service-integrated
Success Metrics:
- All models are pure data containers
- All business logic has corresponding service methods
- No functionality lost in migration
- Services are independently testable