# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is the **Paper Dynasty Web App**, a baseball simulation game migrated from a Discord bot (`../discord-app/`) to a standalone web application using **FastAPI + Model/Service Architecture**. The migration follows a service-oriented approach that prioritizes testability, maintainability, and scalability. ## Development Commands ### Environment Setup ```bash # Start PostgreSQL database container docker compose up -d postgres # Activate virtual environment source venv/bin/activate # Install dependencies (including PostgreSQL driver) pip install -r requirements.txt # Copy environment configuration cp .env.example .env # Edit .env file if needed # Run development server python -m app.main # Server runs on http://localhost:8001 ``` ### Testing ```bash # Run all tests pytest # Run tests with coverage pytest --cov=app # Run specific test module pytest tests/unit/services/test_game_service.py # Run specific test pytest tests/unit/services/test_game_service.py::test_create_game_success ``` ### Database ```bash # Start/stop PostgreSQL container docker compose up -d postgres # Start pddev-postgres container docker compose stop postgres # Stop container docker compose down -v # Stop and remove data (fresh start) # Create database tables (once models are implemented) python -c "from app.services.service_container import create_db_and_tables; create_db_and_tables()" # Generate migration (once Alembic is configured) alembic revision --autogenerate -m "Description" # Apply migrations alembic upgrade head # Connect to database directly docker compose exec postgres psql -U paper_dynasty_user -d paper_dynasty ``` ## Architecture Overview ### Model/Service Architecture Pattern This project implements a **service-oriented architecture** with clear separation of concerns: - **Models** (`app/models/`): Pure data models using SQLModel - **Services** (`app/services/`): Business logic layer with dependency injection - **Controllers** (`app/routers/`): Thin FastAPI route handlers that delegate to services - **Engine** (`app/engine/`): Stateless game simulation functions - **Repositories** (`app/repositories/`): Optional data access layer for complex queries ### Service Layer Design All services inherit from `BaseService` and follow these patterns: - Constructor dependency injection via SQLModel Session - Standardized logging with `f'{__name__}.{self.__class__.__name__}'` format - Business logic separated from HTTP concerns - Unit testable with mocked dependencies ### Dependency Injection Services are injected into routes using FastAPI's `Depends()` system via `service_container.py`: ```python from app.services.service_container import GameServiceDep @router.post("/games/start") async def start_game(game_service: GameServiceDep): # Service contains business logic, route handles HTTP concerns ``` ### Migration from Discord App When migrating code from `../discord-app/`: 1. **Extract business logic** from Discord command handlers into services 2. **Remove Discord dependencies** (discord.py, interaction objects) 3. **Create service methods** with pure business logic 4. **Add comprehensive unit tests** for service methods 5. **Create thin route handlers** that delegate to services ## Current Migration Status **Phase 1: Service Foundation** ✅ COMPLETE - FastAPI project structure established - Base service classes and dependency injection configured - Logging with rotating handlers implemented - Virtual environment and core dependencies installed **Phase 2: Core Game Services** ✅ COMPLETE - ✅ AIService fully implemented (369 lines, 72% test coverage) - Complete steal opportunity decision logic - Defensive alignment and positioning - Tag-up and runner advance decisions - Pitcher replacement logic - ✅ PlayerService fully implemented (53 lines, 100% test coverage) - Player data management and formatting - Name handling with descriptions - ✅ UIService implemented (18 lines, 83% test coverage) - User interface helper functions - ✅ Core gameplay models migrated: Player, Team, Cardset, ManagerAi, PositionRating - ✅ Comprehensive test suite: 206 tests (65% overall coverage) - 51 AI Service tests (unit + integration) - Robust integration testing with real database queries **Phase 3: Game Engine & Routes** 🚧 NEXT - Implement game simulation engine and gameplay mechanics - Create FastAPI routes and controllers for web interface - Add authentication and session management - Integrate services with HTTP endpoints ## Key Files and Patterns ### Service Container (`app/services/service_container.py`) - Manages database sessions and service lifecycles - Provides dependency injection for FastAPI routes - Configure SQLModel engine for PostgreSQL/SQLite ### Base Service (`app/services/base_service.py`) - Abstract base class for all services - Standardized logging and validation patterns - Session management and error handling ### Constants (`app/config/constants.py`) - Migrated constants from Discord app (not assumed values) - Environment-based configuration via Settings class - Game constants, MLB teams, rarity values from original source ### Logging Configuration (`app/config/logging_config.py`) - Rotating file handlers per user requirements - Console and file output with structured formatting - Service-specific logger naming patterns ## Implemented Services ### AIService (`app/services/ai_service.py`) **Status**: ✅ Complete (369 lines, 72% test coverage, 51 tests) Core AI decision-making for baseball gameplay mechanics: - **Steal Opportunities**: `check_steal_opportunity()` - Complex conditional logic for steal decisions to 2nd, 3rd, and home - **Defensive Alignment**: `set_defensive_alignment()` - Hold runners, infield positioning based on game state - **Tag Decisions**: `check_tag_from_second()`, `check_tag_from_third()` - Fly ball tag-up logic - **Runner Advances**: `decide_runner_advance()` - Uncapped situation running decisions - **Pitcher Management**: `should_replace_pitcher()` - Fatigue and situational pitcher replacement - **Groundball Decisions**: `decide_groundball_running()`, `decide_groundball_throw()` - Fielding choices **Key Features**: - Real database queries for defensive ratings - Complex aggression calculations based on game state - Comprehensive bounds checking and error handling - Migrated from Discord app with full business logic preservation ### PlayerService (`app/services/player_service.py`) **Status**: ✅ Complete (53 lines, 100% test coverage) Player data management and formatting: - **Player Creation**: Database-backed player instantiation - **Name Formatting**: `get_formatted_name_with_description()` - Consistent player name display - **Data Validation**: Proper player attribute handling ### UIService (`app/services/ui_service.py`) **Status**: ✅ Complete (18 lines, 83% test coverage) User interface helper functions: - **Formatting Utilities**: Display helpers for web interface - **Data Presentation**: Consistent UI data formatting ### Base Service (`app/services/base_service.py`) **Status**: ✅ Complete (19 lines, 84% test coverage) Abstract foundation for all services: - **Session Management**: SQLModel database session handling - **Logging**: Standardized `f'{__name__}.{self.__class__.__name__}'` format - **Operation Tracking**: `_log_operation()` and `_log_error()` methods - **Dependency Injection**: Constructor-based session injection ## Implemented Models ### Core Models (`app/models/`) - **Player** (`player.py`): Complete player data model with positions relationship - **Team** (`team.py`): Team management with MLB club associations - **Cardset** (`cardset.py`): Card set definitions and metadata - **ManagerAi** (`manager_ai.py`): AI personality and aggression settings - **PositionRating** (`position_rating.py`): Defensive ratings by position and variant ### AI Response Models (`app/models/ai_responses.py`) Structured response objects for AI decisions: - `JumpResponse`: Steal opportunity decisions with safety thresholds - `TagResponse`: Tag-up decisions with minimum safe values - `ThrowResponse`: Fielding throw target decisions - `UncappedRunResponse`: Advanced base running decisions - `DefenseResponse`: Defensive alignment and hold decisions - `RunResponse`: Basic running decisions ## Testing Strategy **🚨 CRITICAL: All tests must follow test isolation guidelines to prevent data persistence issues.** ### Test Isolation Requirements (MANDATORY) **For ALL tests that interact with the database:** 1. **Use centralized `db_session` fixture** from `conftest.py` - never create custom session fixtures 2. **Use factory classes** for all test data - never hardcode IDs or use static values 3. **Import factories** from `tests.factories` package 4. **Ensure test independence** - each test must work in isolation and repeatedly **Example of CORRECT test pattern:** ```python from tests.factories.team_factory import TeamFactory def test_create_team(db_session): # ✅ Use db_session fixture team = TeamFactory.create(db_session, abbrev="LAD") # ✅ Use factory assert team.id is not None ``` **NEVER do this (causes data persistence issues):** ```python @pytest.fixture def session(): # ❌ Custom fixture pass def test_create_team(session): team = Team(id=1, abbrev="LAD") # ❌ Hardcoded ID ``` **📖 See detailed documentation:** - `tests/README.md` - Complete testing guidelines - `tests/factories/README.md` - Factory pattern documentation - `tests/TEST_ISOLATION_GUIDE.md` - Comprehensive isolation best practices ### Current Test Coverage Status - **Total Tests**: 206 tests across all suites - **Overall Coverage**: 65% (804 statements, 285 missed) - **Service Coverage**: - AIService: 72% (369 lines, 51 tests - unit + integration) - PlayerService: 100% (53 lines, comprehensive coverage) - UIService: 83% (18 lines) - BaseService: 84% (19 lines) ### Unit Tests (`tests/unit/`) - **Services**: Test business logic with mocked dependencies - AIService: 22 unit tests covering core decision logic - PlayerService: Comprehensive unit test coverage - UIService: Basic functionality testing - **Models**: Test data validation and relationships using `db_session` + factories - Player, Team, Cardset, ManagerAi, PositionRating models - **Engine**: Reserved for stateless game simulation functions ### Integration Tests (`tests/integration/`) - **AIService Integration**: 29 focused integration tests - Real database queries for defensive ratings - Complex conditional branch coverage - Error handling with actual data constraints - Cross-service interaction testing - Service interactions with real database (isolated transactions) - Must use `db_session` fixture and factory classes ### End-to-End Tests (`tests/e2e/`) - **Status**: 🚧 Reserved for future web interface testing - Complete user journeys through web interface - Game creation and gameplay flows - Use factory classes for any test data setup ## Development Guidelines ### Service Development - All services extend `BaseService` - Use dependency injection for service-to-service communication - Log operations with `self._log_operation()` and `self._log_error()` - Follow "Raise or Return" pattern (no optional return values) ### Documentation Maintenance - **Update README.md files** when making substantial changes to any directory - Each directory with significant content has a README.md explaining its purpose and patterns - Keep documentation current with architecture decisions and new patterns - Update relevant README when adding new services, routes, or changing patterns - **Reference per-directory README.md files** - Future AI agents should read the README in each directory to understand its purpose, patterns, and responsibilities before making changes ### File Size Management - **Keep all files as small as feasibly possible** for maximum maintainability - Break large files into smaller, focused modules - Single responsibility principle applies to files as well as classes - Prefer multiple small service files over monolithic service classes - Split complex models into separate files when they serve different domains ### Code Migration - Always check `../discord-app/` for actual implementation before assuming logic - Extract Discord command handlers into service methods - Test service logic independently of web framework - Keep routes thin - delegate business logic to services ### Database - Currently configured for SQLite development - PostgreSQL driver (`psycopg2-binary`) commented out until proper DB setup - Use SQLModel for all data models ### Logging - Use rotating file handlers as per user requirements - Format: `f'{__name__}.{className or functionName}'` - Log service operations and errors consistently