paper-dynasty-gameplay-webapp/CLAUDE.md
Cal Corum 6ad18e5314 CLAUDE: Update documentation to reflect current project status
Updated CLAUDE.md with accurate current state information:

Migration Status:
- Phase 2: Core Game Services marked as  COMPLETE
- Phase 3: Game Engine & Routes marked as 🚧 NEXT
- Updated service implementation status

Service Documentation:
- AIService: Complete (369 lines, 72% coverage, 51 tests)
- PlayerService: Complete (53 lines, 100% coverage)
- UIService: Complete (18 lines, 83% coverage)
- BaseService: Complete (19 lines, 84% coverage)
- Added detailed capability descriptions

Model Documentation:
- Updated implemented models list
- Added AI response model descriptions
- Documented relationships and functionality

Testing Documentation:
- Current coverage: 65% overall, 206 total tests
- AIService: 51 tests (22 unit + 29 integration)
- Detailed integration testing approach
- Updated test distribution across suites

Documentation now accurately reflects substantial progress made in
service implementation, model development, and comprehensive testing
infrastructure.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-29 21:35:14 -05:00

13 KiB

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

# 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

# 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

# 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:

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:

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):

@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