paper-dynasty-gameplay-webapp/app/services
Cal Corum c09f9d1302 CLAUDE: Initialize Paper Dynasty web app with Model/Service Architecture
Establishes foundation for migrating baseball simulation from Discord bot to web application using service-oriented architecture pattern.

Key components:
- FastAPI application structure with dependency injection
- Service layer foundation with base classes and container
- Comprehensive directory documentation with README files
- PostgreSQL containerization with Docker Compose
- Testing structure for unit/integration/e2e tests
- Migration planning documentation
- Rotating log configuration per user requirements

Architecture follows Model/Service/Controller pattern to improve testability, maintainability, and scalability over original monolithic Discord app.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-27 21:44:12 -05:00
..
__init__.py CLAUDE: Initialize Paper Dynasty web app with Model/Service Architecture 2025-09-27 21:44:12 -05:00
base_service.py CLAUDE: Initialize Paper Dynasty web app with Model/Service Architecture 2025-09-27 21:44:12 -05:00
README.md CLAUDE: Initialize Paper Dynasty web app with Model/Service Architecture 2025-09-27 21:44:12 -05:00
service_container.py CLAUDE: Initialize Paper Dynasty web app with Model/Service Architecture 2025-09-27 21:44:12 -05:00

Services Directory

This directory contains the business logic layer of the Model/Service Architecture. Services are the core of the application architecture, containing all business rules and logic separated from HTTP concerns and database details.

Architecture Pattern

Service Responsibilities

  • Business Logic: Core application logic and rules
  • Data Validation: Input validation and business rule enforcement
  • Service Orchestration: Coordination between multiple services
  • Error Handling: Business-appropriate error handling and logging

Design Principles

  • Single Responsibility: Each service has one clear purpose
  • Dependency Injection: Services receive dependencies via constructor
  • Stateless: Services don't maintain instance state between calls
  • Testable: Services can be unit tested with mocked dependencies
  • Pure Business Logic: No HTTP, database, or UI concerns

Current Files

base_service.py

Abstract base class providing common functionality:

  • Standardized logging: self._log_operation() and self._log_error()
  • Session management: SQLModel database session handling
  • Validation helpers: Common validation patterns

service_container.py

Dependency injection container:

  • Database sessions: Session lifecycle management
  • Service dependencies: FastAPI Depends() integration
  • Type annotations: Service dependency type aliases

Planned Services

Core Game Services

  • GameService: Game creation, management, queries
  • GameplayService: Core gameplay simulation & flow
  • AIService: AI decision making and automation

Supporting Services

  • UserService: User sessions, preferences
  • AuthService: Discord OAuth, session management
  • NotificationService: Web notifications and real-time updates

Service Pattern Example

from app.services.base_service import BaseService
from app.services.service_container import SessionDep

class GameService(BaseService):
    def __init__(self, session: Session):
        super().__init__(session)

    async def create_game(self, away_team_id: int, home_team_id: int) -> Game:
        self._log_operation("create_game", f"Teams: {away_team_id} vs {home_team_id}")

        # Business logic here
        game = Game(away_team_id=away_team_id, home_team_id=home_team_id)

        # Database persistence
        self.session.add(game)
        self.session.commit()

        return game

Dependency Injection

Services are injected into routes using FastAPI's Depends():

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
    return await game_service.create_game(away_team_id=1, home_team_id=2)

Testing Services

Services should be unit tested independently:

@pytest.fixture
def mock_session():
    return Mock(spec=Session)

@pytest.fixture
def game_service(mock_session):
    return GameService(mock_session)

async def test_create_game(game_service):
    # Test business logic without database
    result = await game_service.create_game(1, 2)
    assert result.away_team_id == 1

Migration from Discord App

When migrating from ../discord-app/:

  1. Extract business logic from Discord command handlers
  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