# Week 6: Player Models & League Integration - Overview

**Created**: 2025-10-25
**Status**: Planning Complete, Ready for Implementation
**Prerequisites**: Week 5 Complete (Game engine working)
**Focus**: League-specific player models and API integration

---

## Quick Summary

Implement two-layer player model system:
1. **API Models** - Exact match to external league APIs (PD & SBA)
2. **Game Models** - Optimized for gameplay with only essential fields

This allows us to:
- Deserialize API responses with full type safety
- Work with clean, minimal data in game engine
- Support both leagues with different data structures

---

## Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                   External League APIs                       │
│   ┌──────────────────────┐  ┌──────────────────────┐       │
│   │  PD API              │  │  SBA API             │       │
│   │  - Player            │  │  - Player            │       │
│   │  - Batting Ratings   │  │                      │       │
│   │  - Pitching Ratings  │  │                      │       │
│   └──────────────────────┘  └──────────────────────┘       │
└────────────────┬──────────────────────┬─────────────────────┘
                 │                      │
                 ↓                      ↓
┌─────────────────────────────────────────────────────────────┐
│              API Response Models (api_models.py)             │
│   ┌──────────────────────┐  ┌──────────────────────┐       │
│   │  PdPlayerApi         │  │  SbaPlayerApi        │       │
│   │  PdBattingRatingsApi │  │  (with nested Team,  │       │
│   │  PdPitchingRatingsApi│  │   Manager, Division) │       │
│   └──────────────────────┘  └──────────────────────┘       │
└────────────────┬──────────────────────┬─────────────────────┘
                 │                      │
                 ↓                      ↓
┌─────────────────────────────────────────────────────────────┐
│          Mapper Layer (PlayerMapper class)                   │
│              Transforms: API → Game Models                   │
│   - Extracts essential fields                               │
│   - Flattens nested structures                              │
│   - Normalizes position data (pos_1-8 → List[str])         │
└────────────────┬──────────────────────┬─────────────────────┘
                 │                      │
                 ↓                      ↓
┌─────────────────────────────────────────────────────────────┐
│           Game Models (player_models.py)                     │
│   ┌──────────────────────┐  ┌──────────────────────┐       │
│   │  PdPlayer            │  │  SbaPlayer           │       │
│   │  - Basic fields      │  │  - Basic fields      │       │
│   │  - Batting ratings   │  │  - Simplified data   │       │
│   │  - Pitching ratings  │  │                      │       │
│   └──────────────────────┘  └──────────────────────┘       │
└────────────────┬──────────────────────┬─────────────────────┘
                 │                      │
                 ↓                      ↓
┌─────────────────────────────────────────────────────────────┐
│                  Game Engine & Play Resolver                 │
│   - Uses game models during play resolution                 │
│   - PD: Uses outcome probabilities from ratings             │
│   - SBA: Uses simplified result charts                      │
└─────────────────────────────────────────────────────────────┘
```

---

## Why Two Layers?

### Problem
- External APIs return **massive** nested JSON (team, division, cardset, rarity, etc.)
- Game engine only needs **minimal** data (name, positions, ratings)
- PD needs 3 API calls per player (player + batting ratings + pitching ratings)

### Solution
**Layer 1: API Models** - Match external structure exactly
- Full type safety when deserializing
- All nested objects as Pydantic models
- Easy to maintain when API changes

**Layer 2: Game Models** - Only what's needed for gameplay
- Clean, minimal data
- Fast serialization for WebSocket
- Easy to work with in game logic

**Mapper Layer** - Transform between them
- Extract essential fields
- Combine multiple API calls (PD: player + ratings)
- Normalize differences between leagues

---

## Detailed Documentation

This plan is split across multiple focused files:

### Core Specifications

1. **[API Models - PD](./player-model-specs/api-models-pd.md)**
   - All PD API response models
   - JSON examples
   - Nested structures (Cardset, Rarity, MlbPlayer)
   - Batting & pitching ratings

2. **[API Models - SBA](./player-model-specs/api-models-sba.md)**
   - SBA API response models
   - JSON examples
   - Nested structures (Team, Manager, Division)

3. **[Game Models](./player-model-specs/game-models.md)**
   - BasePlayer abstract class
   - SbaPlayer (game-optimized)
   - PdPlayer (game-optimized with ratings)
   - Field selection rationale

4. **[Mappers & Factories](./player-model-specs/mappers-and-factories.md)**
   - PlayerMapper (API → Game)
   - PlayerFactory (create by league)
   - Transformation logic
   - Position normalization

5. **[API Client](./player-model-specs/api-client.md)**
   - LeagueApiClient HTTP client
   - Methods for each endpoint
   - Error handling
   - Usage examples

6. **[Testing Strategy](./player-model-specs/testing-strategy.md)**
   - Unit test specifications
   - Integration test plans
   - Mock data strategy

---

## Implementation Order

### Phase 1: API Models (Day 1)
1. Create `api_models.py`
2. Define all PD API models
3. Define all SBA API models
4. Unit tests with real JSON samples

### Phase 2: Game Models (Day 1-2)
1. Create `player_models.py`
2. Define BasePlayer abstract
3. Define SbaPlayer
4. Define PdPlayer with ratings
5. Unit tests

### Phase 3: Mappers (Day 2)
1. Create PlayerMapper class
2. Implement PD mapping (combine 3 API calls)
3. Implement SBA mapping
4. Unit tests with transformation examples

### Phase 4: API Client (Day 2-3)
1. Create `api_client.py`
2. Implement LeagueApiClient with httpx
3. Implement PD endpoints
4. Implement SBA endpoints
5. Integration tests with mocked responses

### Phase 5: Integration (Day 3)
1. Update `league_configs.py` with API base URLs
2. Update PlayResolver to use PD ratings
3. End-to-end integration tests
4. Performance testing

---

## Key Design Decisions

### Decision 1: Two-Layer Approach
**Chosen**: API models + Game models (with mapper)

**Alternatives Considered**:
- Single model matching API (❌ too much unnecessary data in game engine)
- Single game model with manual dict parsing (❌ no type safety on API responses)

**Rationale**: Separation of concerns, type safety, performance

### Decision 2: Nested Pydantic Models
**Chosen**: Full Pydantic models for all nested objects (Team, Cardset, etc.)

**Alternatives Considered**:
- Dict[str, Any] for nested data (❌ loses type safety)
- Flatten everything to top level (❌ complex mapping logic)

**Rationale**: Type safety, IDE autocomplete, validation

### Decision 3: Position Handling
**Chosen**: Extract `pos_1` through `pos_8` → `positions: List[str]`

**Rationale**: Cleaner interface, easier to work with in game logic

### Decision 4: PD Ratings Storage
**Chosen**: Store ratings as part of PdPlayer model (vs L and vs R)

**Rationale**: Always needed for play resolution, keep together

### Decision 5: API Base URLs
**Actual URLs** (from your data):
- PD: `https://pd.manticorum.com/`
- SBA: `https://api.sba.manticorum.com/`

---

## File Structure

After implementation, project structure will be:

```
backend/app/
├── models/
│   ├── api_models.py          # NEW - External API response models
│   ├── player_models.py       # NEW - Game-optimized player models
│   ├── game_models.py         # Existing - Game state models
│   └── db_models.py           # Existing - Database ORM models
│
├── data/
│   ├── __init__.py
│   └── api_client.py          # NEW - HTTP client for league APIs
│
├── config/
│   ├── __init__.py
│   ├── base_config.py         # To create
│   ├── league_configs.py      # To create (with API URLs)
│   └── result_charts.py       # To create
│
└── core/
    ├── play_resolver.py       # UPDATE - Use PD ratings for resolution
    └── ...                    # Existing files

tests/
├── unit/
│   ├── models/
│   │   ├── test_api_models.py      # NEW
│   │   └── test_player_models.py   # NEW
│   └── data/
│       └── test_mappers.py         # NEW
│
└── integration/
    └── data/
        └── test_api_client.py      # NEW
```

---

## Success Criteria

### Functional Requirements
- ✅ Can fetch PD player from API and deserialize to PdPlayerApi
- ✅ Can fetch PD batting ratings and deserialize
- ✅ Can fetch PD pitching ratings and deserialize
- ✅ Can fetch SBA player from API and deserialize to SbaPlayerApi
- ✅ Can map PD API models → PdPlayer game model
- ✅ Can map SBA API models → SbaPlayer game model
- ✅ PlayerFactory creates correct player type by league_id
- ✅ Positions correctly extracted from pos_1-8 fields
- ✅ PD ratings correctly attached to PdPlayer

### Non-Functional Requirements
- ✅ All API models pass Pydantic validation with real JSON
- ✅ Unit test coverage > 90%
- ✅ API client handles errors gracefully
- ✅ Serialization/deserialization < 10ms per player
- ✅ Type hints validated by mypy

---

## Timeline & Effort

**Estimated Total**: 2-3 days (16-24 hours)

**Breakdown**:
- API Models: 4-6 hours
- Game Models: 3-4 hours
- Mappers: 2-3 hours
- API Client: 4-6 hours
- Testing: 3-5 hours

**Dependencies**:
- httpx library (already in requirements.txt ✅)
- Access to PD and SBA APIs (have URLs ✅)
- Real JSON samples (provided by user ✅)

---

## Next Steps

1. Read detailed specifications in `player-model-specs/` directory
2. Start with API models (PD first, then SBA)
3. Implement game models
4. Create mapper layer
5. Build API client
6. Write comprehensive tests
7. Update PlayResolver to use ratings

---

**Current Status**: 📝 Planning Complete - Ready to start implementation
**Last Updated**: 2025-10-25
**Week**: 6 of Phase 2
