paper-dynasty-gameplay-webapp/CLAUDE.md
Cal Corum 1c24161e76 CLAUDE: Achieve 100% test pass rate with comprehensive AI service testing
- 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>
2025-09-28 17:55:34 -05:00

8.3 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 🚧 NEXT

  • Extract business logic from ../discord-app/command_logic/logic_gameplay.py
  • Implement GameService, GameplayService, AIService
  • Migrate core gameplay models from Discord app
  • Add comprehensive service unit tests

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

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

Unit Tests (tests/unit/)

  • Services: Test business logic with mocked database sessions
  • Engine: Test stateless game simulation functions
  • Models: Test data validation and relationships using db_session + factories

Integration Tests (tests/integration/)

  • Service interactions with real database (isolated transactions)
  • Authentication flows and session management
  • Must use db_session fixture and factory classes

End-to-End Tests (tests/e2e/)

  • 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