# 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 **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()` | 📋 TODO | | `tag_from_second()` | AIService | `check_tag_from_second()` | 📋 TODO | | `tag_from_third()` | AIService | `check_tag_from_third()` | 📋 TODO | | `throw_at_uncapped()` | AIService | `decide_throw_target()` | 📋 TODO | | `uncapped_advance()` | AIService | `decide_runner_advance()` | 📋 TODO | | `defense_alignment()` | AIService | `set_defensive_alignment()` | 📋 TODO | | `gb_decide_run()` | AIService | `decide_groundball_running()` | 📋 TODO | | `gb_decide_throw()` | AIService | `decide_groundball_throw()` | 📋 TODO | | `replace_pitcher()` | AIService | `should_replace_pitcher()` | 📋 TODO | ### 2. `Cardset` - Card Set Metadata **Model Migration**: - ✅ Keep: Basic metadata (id, name, ranked_legal) - ✅ Keep: Relationships to games/players **Business Logic to Extract**: None (pure data model) ### 3. `Team` - Team Identity Data **Model Migration**: - ✅ Keep: Team data fields (abbrev, names, wallet, etc.) - ✅ Keep: Simple `description` property - ❌ Remove: `embed` property (Discord UI) **Business Logic to Extract**: | Original Method/Property | Target Service | New Method | Status | |-------------------------|---------------|------------|---------| | `embed` property | UIService | `format_team_display()` | 📋 TODO | --- ## Phase 2: Player and Card Data ### 4. `Player` - Player Metadata **Model Migration**: - ✅ Keep: Player metadata (name, cost, positions, etc.) - ✅ Keep: Simple `name_with_desc` property - ❌ 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_ascii` creates 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 logic - [ ] `check_tag_from_second()` - Tag-up decisions from 2nd - [ ] `check_tag_from_third()` - Tag-up decisions from 3rd - [ ] `decide_throw_target()` - Uncapped runner throw decisions - [ ] `decide_runner_advance()` - Uncapped advance decisions - [ ] `set_defensive_alignment()` - Defensive positioning - [ ] `decide_groundball_running()` - Groundball running decisions - [ ] `decide_groundball_throw()` - Groundball throw decisions - [ ] `should_replace_pitcher()` - Pitcher replacement logic ### GameService - Game Management - [ ] `initialize_game()` - Game setup and first play creation - [ ] `get_current_play()` - Current play retrieval - [ ] `format_team_lineup()` - Lineup display formatting - [ ] `build_cardset_params()` - Cardset parameter building - [ ] `get_human_team()` - Human team identification - [ ] `get_league_name()` - League name formatting ### GameplayService - Live Game Logic - [ ] `initialize_play_ai()` - AI setup for plays - [ ] `calculate_run_differential()` - Score differential calculation - [ ] `is_ai_batting()` - AI batting turn detection - [ ] `check_walkoff_situation()` - Walkoff scenario detection ### UIService - User Interface Formatting - [ ] `format_team_display()` - Team display for web UI - [ ] `format_player_link()` - Player links for web - [ ] `get_batter_card_image()` - Batter card image URLs - [ ] `get_pitcher_card_image()` - Pitcher card image URLs - [ ] `format_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: 1. **AI Logic Location**: All AI decision-making moves to AIService to enable easy testing and modification 2. **UI Separation**: All formatting logic moves to UIService to support multiple interfaces 3. **Game State Management**: Core game logic moves to GameService/GameplayService for business rule centralization ### Risk Areas: 1. **Game.initialize_play()**: Complex method with lineup validation and AI setup 2. **Play model**: Heavily used throughout gameplay with many computed properties 3. **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