Added targeted integration tests to cover previously uncovered conditional branches and edge cases in AI decision-making logic: - test_ai_service_focused_coverage.py: 11 tests for key missing branches * Steal opportunity conditions (lines 91, 93, 98-99, 108) * Steal to third/home scenarios (lines 129, 157, 161) * Defensive alignment logic (lines 438, 480) * Tag decision branches (lines 204, 253) - test_ai_service_final_coverage.py: 10 tests for remaining gaps * Complex steal conditions (lines 95, 118-119, 132, 136-137, 141) * Late inning steal logic (lines 159, 163) * Uncapped advance bounds checking (lines 382-388) * Complex defensive scenarios (lines 440-449) - test_ai_service_coverage.py: Comprehensive coverage tests (unused due to complexity) Fixed: - Player model relationship syntax (removed unsupported cascade_delete parameter) - Existing test assertion in test_ai_service_simple.py for steal to home scenario Coverage improvement: 369 statements, 147→105 missed lines (60%→72% coverage) All 49 AI Service tests now pass with comprehensive integration testing. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| __init__.py | ||
| ai_responses.py | ||
| cardset.py | ||
| manager_ai.py | ||
| player.py | ||
| position_rating.py | ||
| README.md | ||
| team.py | ||
Models Directory
This directory contains pure data models for the Paper Dynasty web app, migrated from the Discord app following the Model/Service Architecture pattern.
Architecture Principle
Models = Pure Data | Services = Business Logic
- Models: Field definitions, relationships, basic validators only
- Services: Complex logic, UI formatting, game management, AI decisions
Migration Status
✅ Completed Models
| Model | Status | Description | Business Logic Extracted |
|---|---|---|---|
ManagerAi |
✅ Complete | AI configuration data | → AIService (9 methods) |
Cardset |
✅ Complete | Card set metadata | None (pure data) |
🚧 In Progress
| Model | Status | Description | Business Logic to Extract |
|---|---|---|---|
Team |
📋 Next | Team identity data | → UIService (embed property) |
Player |
📋 Planned | Player metadata | → UIService (Discord markdown) |
📋 Future Phases
- Phase 3: Game structure (Game, Play models)
- Phase 4: Card and rating models
- Phase 5: Web-specific models (sessions, preferences)
Model Patterns
Pure Data Model Structure
# Base model for validation and field definitions
class ModelBase(SQLModel):
id: int | None = Field(default=None, primary_key=True)
name: str = Field(index=True, description="Field description")
@field_validator('name')
@classmethod
def validate_name(cls, v: str) -> str:
# Basic validation only
if not v or not v.strip():
raise ValueError("Name cannot be empty")
return v
# Table model for database operations
class Model(ModelBase, table=True):
# relationships: List["RelatedModel"] = Relationship(...)
pass
What STAYS in Models
✅ Field definitions and types
name: str = Field(index=True)
ranked_legal: bool = Field(default=False)
✅ Database relationships
players: List["Player"] = Relationship(back_populates="cardset")
✅ Basic field validation
@field_validator('name')
def validate_name_not_empty(cls, v: str) -> str:
if not v.strip():
raise ValueError("Name cannot be empty")
return v
What MOVES to Services
❌ Complex business logic
# BEFORE (in model)
def check_steal_opportunity(self, game, to_base):
# Complex AI decision logic...
# AFTER (in service)
def check_steal_opportunity(self, manager_ai, game, to_base):
# Same logic but in AIService
❌ UI formatting
# BEFORE (in model)
@property
def embed(self) -> discord.Embed:
# Discord-specific formatting...
# AFTER (in service)
def format_team_display(self, team) -> dict:
# Platform-agnostic formatting
❌ Game mechanics
# BEFORE (in model)
def initialize_play(self, session):
# Complex game setup logic...
# AFTER (in service)
def initialize_game(self, game_id) -> Play:
# Same logic but in GameService
Testing Strategy
All models use the factory pattern with transaction rollback:
# test_model.py
def test_model_creation(db_session):
model = ModelFactory.create(db_session, field="value")
assert model.field == "value"
# Automatic rollback ensures isolation
See tests/README.md for complete testing documentation.
File Organization
models/
├── __init__.py # Export all models
├── manager_ai.py # ✅ AI configuration (complete)
├── cardset.py # ✅ Card set metadata (complete)
├── team.py # 🚧 Team identity (next)
├── player.py # 📋 Player metadata (planned)
├── game.py # 📋 Game structure (planned)
├── play.py # 📋 Gameplay state (planned)
└── ai_responses.py # AI decision response models
Migration Guidelines
When migrating a model from ../discord-app/:
1. Analyze Original Model
# Find the model in Discord app
grep -r "class ModelName" ../discord-app/
2. Separate Data from Logic
- Keep: Field definitions, relationships, basic validation
- Extract: Methods, computed properties, complex logic
3. Create Pure Data Model
class ModelBase(SQLModel):
# Only field definitions and basic validation
class Model(ModelBase, table=True):
# Only relationships
4. Extract Business Logic
class ModelService(BaseService):
def extracted_method(self, model_instance, params):
# Migrated business logic
5. Create Comprehensive Tests
# Validation tests (no database)
def test_model_validation():
model = ModelFactory.build(invalid_field="bad")
# Test validation
# Database tests (with rollback)
def test_model_persistence(db_session):
model = ModelFactory.create(db_session)
# Test database operations
6. Update Migration Plan
- Mark model as complete in
.claude/model-migration-plan.md - Update this README with new model status
Dependencies
Models depend on:
sqlmodel- Database ORM and validationpydantic- Field validation and serializationsqlalchemy- Advanced database features
Models should NOT depend on:
discord.py- Platform-specific libraryfastapi- Web framework- Service classes - Business logic layer
Best Practices
DO:
- ✅ Keep models as simple data containers
- ✅ Use descriptive field documentation
- ✅ Add basic validation for data integrity
- ✅ Follow naming conventions from original models
- ✅ Create comprehensive factory-based tests
DON'T:
- ❌ Add business logic methods to models
- ❌ Include platform-specific dependencies
- ❌ Create computed properties with complex logic
- ❌ Hard-code values that belong in services
- ❌ Skip validation or tests
Future Considerations
As we complete the migration:
- Web-specific models will be added for session management
- Performance optimization may require relationship tuning
- Database migrations will be managed via Alembic
- API serialization will use Pydantic's serialization features
The goal is to have a clean, testable, platform-agnostic data layer that can support web, mobile, and future interfaces.