major-domo-v2/commands/injuries/CLAUDE.md
Cal Corum ca325142d8 CLAUDE: Add comprehensive CLAUDE.md documentation files for AI agent guidance
Adding 17 CLAUDE.md files across the project to provide detailed context
and implementation guidelines for AI development agents:

Root Documentation:
- CLAUDE.md - Main project guide with Git workflow requirements

Component Documentation:
- commands/CLAUDE.md - Command architecture and patterns
- models/CLAUDE.md - Pydantic models and validation
- services/CLAUDE.md - Service layer and API interactions
- tasks/CLAUDE.md - Background tasks and automation
- tests/CLAUDE.md - Testing strategies and patterns
- utils/CLAUDE.md - Utility functions and decorators
- views/CLAUDE.md - Discord UI components and embeds

Command Package Documentation:
- commands/help/CLAUDE.md - Help system implementation
- commands/injuries/CLAUDE.md - Injury management commands
- commands/league/CLAUDE.md - League-wide commands
- commands/players/CLAUDE.md - Player information commands
- commands/profile/CLAUDE.md - User profile commands
- commands/teams/CLAUDE.md - Team information commands
- commands/transactions/CLAUDE.md - Transaction management
- commands/utilities/CLAUDE.md - Utility commands
- commands/voice/CLAUDE.md - Voice channel management

Key Updates:
- Updated .gitignore to track CLAUDE.md files in version control
- Added Git Workflow section requiring branch-based development
- Documented all architectural patterns and best practices
- Included comprehensive command/service implementation guides

These files provide essential context for AI agents working on the codebase,
ensuring consistent patterns, proper error handling, and maintainable code.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-20 20:30:07 -05:00

14 KiB

Injury Commands

Command Group: /injury Permission Required: SBA Players role (for set-new and clear) Subcommands: roll, set-new, clear

Overview

The injury command family provides comprehensive player injury management for the SBA league. Team managers can roll for injuries using official Strat-o-Matic injury tables, record confirmed injuries, and clear injuries when players return.

Commands

/injury roll

Roll for injury based on a player's injury rating using 3d6 dice and official injury tables.

Usage:

/injury roll <player_name>

Parameters:

  • player_name (required, autocomplete): Name of the player - uses smart autocomplete prioritizing your team's players

Injury Rating Format: The player's injury_rating field contains both the games played and rating in format #p##:

  • Format: 1p70, 4p50, 2p65, etc.
  • First character: Games played in current series (1-6)
  • Remaining characters: Injury rating (p70, p65, p60, p50, p40, p30, p20)

Examples:

  • 1p70 = 1 game played, p70 rating
  • 4p50 = 4 games played, p50 rating
  • 2p65 = 2 games played, p65 rating

Dice Roll:

  • Rolls 3d6 (3-18 range)
  • Automatically extracts games played and rating from player's injury_rating field
  • Looks up result in official Strat-o-Matic injury tables
  • Returns injury duration based on rating and games played

Possible Results:

  • OK: No injury
  • REM: Remainder of game (batters) or Fatigued (pitchers)
  • Number: Games player will miss (1-24 games)

Example:

/injury roll Mike Trout

Response Fields:

  • Roll: Total rolled and individual dice (e.g., "15 (3d6: 5 + 5 + 5)")
  • Player: Player name and position
  • Injury Rating: Full rating with parsed details (e.g., "4p50 (p50, 4 games)")
  • Result: Injury outcome (OK, REM, or number of games)
  • Team: Player's current team

Response Colors:

  • Green: OK (no injury)
  • Gold: REM (remainder of game/fatigued)
  • Orange: Number of games (injury occurred)

Error Handling: If a player's injury_rating is not in the correct format, an error message will be displayed:

Invalid Injury Rating Format
{Player} has an invalid injury rating: `{rating}`

Expected format: #p## (e.g., 1p70, 4p50)

/injury set-new

Record a new injury for a player on your team.

Usage:

/injury set-new <player_name> <this_week> <this_game> <injury_games>

Parameters:

  • player_name (required): Name of the player to injure
  • this_week (required): Current week number
  • this_game (required): Current game number (1-4)
  • injury_games (required): Total number of games player will be out

Validation:

  • Player must exist in current season
  • Player cannot already have an active injury
  • Game number must be between 1 and 4
  • Injury duration must be at least 1 game

Automatic Calculations: The command automatically calculates:

  1. Injury start date (adjusts for game 4 edge case)
  2. Return date based on injury duration
  3. Week rollover when games exceed 4 per week

Example:

/injury set-new Mike Trout 5 2 4

This records an injury occurring in week 5, game 2, with player out for 4 games (returns week 6, game 2).

Response:

  • Confirmation embed with injury details
  • Player's name, position, and team
  • Total games missed
  • Calculated return date

/injury clear

Clear a player's active injury and mark them as eligible to play.

Usage:

/injury clear <player_name>

Parameters:

  • player_name (required, autocomplete): Name of the player whose injury to clear - uses smart autocomplete prioritizing your team's players

Validation:

  • Player must exist in current season
  • Player must have an active injury

User Flow:

  1. Command issued with player name
  2. Confirmation embed displayed showing:
    • Player name and position
    • Team name and abbreviation
    • Expected return date
    • Total games missed
    • Team thumbnail (if available)
  3. User prompted: "Is {Player Name} cleared to return?"
  4. Two buttons presented:
    • "Clear Injury" → Proceeds with clearing the injury
    • "Cancel" → Cancels the operation
  5. After confirmation, injury is cleared and success message displayed

Example:

/injury clear Mike Trout

Confirmation Embed:

  • Title: Player name
  • Description: "Is {Player Name} cleared to return?"
  • Fields: Player info, team, expected return date, games missed
  • Buttons: "Clear Injury" / "Cancel"
  • Timeout: 3 minutes

Success Response (after confirmation):

  • Confirmation that injury was cleared
  • Shows previous return date
  • Shows total games that were missed
  • Player's team information

Responders:

  • Command issuer
  • Team GM(s) - can also confirm/cancel on behalf of team

Date Format

All injury dates use the format w##g#:

  • w## = Week number (zero-padded to 2 digits)
  • g# = Game number (1-4)

Examples:

  • w05g2 = Week 5, Game 2
  • w12g4 = Week 12, Game 4
  • w01g1 = Week 1, Game 1

Injury Calculation Logic

Basic Calculation

For an injury of N games starting at week W, game G:

  1. Calculate weeks and remaining games:

    out_weeks = floor(N / 4)
    out_games = N % 4
    
  2. Calculate return date:

    return_week = W + out_weeks
    return_game = G + 1 + out_games
    
  3. Handle week rollover:

    if return_game > 4:
        return_week += 1
        return_game -= 4
    

Special Cases

Game 4 Edge Case

If injury occurs during game 4, the start date is adjusted:

start_week = W + 1
start_game = 1

Examples

Example 1: Simple injury (same week)

  • Current: Week 5, Game 1
  • Injury: 2 games
  • Return: Week 5, Game 4

Example 2: Week rollover

  • Current: Week 5, Game 3
  • Injury: 3 games
  • Return: Week 6, Game 3

Example 3: Multi-week injury

  • Current: Week 5, Game 2
  • Injury: 8 games
  • Return: Week 7, Game 3

Example 4: Game 4 start

  • Current: Week 5, Game 4
  • Injury: 2 games
  • Start: Week 6, Game 1
  • Return: Week 6, Game 3

Database Schema

Injury Model

class Injury(SBABaseModel):
    id: int                 # Injury ID
    season: int            # Season number
    player_id: int         # Player ID
    total_games: int       # Total games player will be out
    start_week: int        # Week injury started
    start_game: int        # Game number injury started (1-4)
    end_week: int          # Week player returns
    end_game: int          # Game number player returns (1-4)
    is_active: bool        # Whether injury is currently active

API Integration

The commands interact with the following API endpoints:

  • GET /api/v3/injuries - Query injuries with filters
  • POST /api/v3/injuries - Create new injury record
  • PATCH /api/v3/injuries/{id} - Update injury (clear active status)
  • PATCH /api/v3/players/{id} - Update player's il_return field

Service Layer

InjuryService

Location: services/injury_service.py

Key Methods:

  • get_active_injury(player_id, season) - Get active injury for player
  • get_injuries_by_player(player_id, season, active_only) - Get all injuries for player
  • get_injuries_by_team(team_id, season, active_only) - Get team injuries
  • create_injury(...) - Create new injury record
  • clear_injury(injury_id) - Deactivate injury

Permissions

Required Roles

For /injury check:

  • No role required (available to all users)

For /injury set-new and /injury clear:

  • SBA Players role required
  • Configured via SBA_PLAYERS_ROLE_NAME environment variable

Permission Checks

The commands use has_player_role() method to verify user has appropriate role:

def has_player_role(self, interaction: discord.Interaction) -> bool:
    """Check if user has the SBA Players role."""
    player_role = discord.utils.get(
        interaction.guild.roles,
        name=get_config().sba_players_role_name
    )
    return player_role in interaction.user.roles if player_role else False

Error Handling

Common Errors

Player Not Found:

❌ Player Not Found
I did not find anybody named **{player_name}**.

Already Injured:

❌ Already Injured
Hm. It looks like {player_name} is already hurt.

Not Injured:

❌ No Active Injury
{player_name} isn't injured.

Invalid Input:

❌ Invalid Input
Game number must be between 1 and 4.

Permission Denied:

❌ Permission Denied
This command requires the **SBA Players** role.

Logging

All injury commands use the @logged_command decorator for automatic logging:

@app_commands.command(name="check")
@logged_command("/injury check")
async def injury_check(self, interaction, player_name: str):
    # Command implementation

Log Context:

  • Command name
  • User ID and username
  • Player name
  • Season
  • Injury details (duration, dates)
  • Success/failure status

Example Log:

{
  "level": "INFO",
  "command": "/injury set-new",
  "user_id": "123456789",
  "player_name": "Mike Trout",
  "season": 12,
  "injury_games": 4,
  "return_date": "w06g2",
  "message": "Injury set for Mike Trout"
}

Testing

Test Coverage

Location: tests/test_services_injury.py

Test Categories:

  1. Model Tests (5 tests) - Injury model creation and properties
  2. Service Tests (8 tests) - InjuryService CRUD operations with API mocking
  3. Roll Logic Tests (8 tests) - Injury rating parsing, table lookup, and dice roll logic
  4. Calculation Tests (5 tests) - Date calculation logic for injury duration

Total: 26 comprehensive tests

Running Tests:

# Run all injury tests
python -m pytest tests/test_services_injury.py -v

# Run specific test class
python -m pytest tests/test_services_injury.py::TestInjuryService -v
python -m pytest tests/test_services_injury.py::TestInjuryRollLogic -v

# Run with coverage
python -m pytest tests/test_services_injury.py --cov=services.injury_service --cov=commands.injuries

Injury Roll Tables

Table Structure

The injury tables are based on official Strat-o-Matic rules with the following structure:

Ratings: p70, p65, p60, p50, p40, p30, p20 (higher is better) Games Played: 1-6 games in current series Roll: 3d6 (results from 3-18)

Rating Availability by Games Played

Not all ratings are available for all games played combinations:

  • 1 game: All ratings (p70-p20)
  • 2 games: All ratings (p70-p20)
  • 3 games: p65-p20 (p70 exempt)
  • 4 games: p60-p20 (p70, p65 exempt)
  • 5 games: p60-p20 (p70, p65 exempt)
  • 6 games: p40-p20 (p70, p65, p60, p50 exempt)

When a rating/games combination has no table, the result is automatically "OK" (no injury).

Example Table (p65, 1 game):

Roll Result
3 2
4 2
5 OK
6 REM
7 1
... ...
18 12

UI/UX Design

Embed Colors

  • Roll (OK): Green - No injury
  • Roll (REM): Gold - Remainder of game/Fatigued
  • Roll (Injury): Orange - Number of games
  • Set New: Success (green) - EmbedTemplate.success()
  • Clear: Success (green) - EmbedTemplate.success()
  • Errors: Error (red) - EmbedTemplate.error()

Response Format

All successful responses use Discord embeds with:

  • Clear title indicating action/status
  • Well-organized field layout
  • Team information when applicable
  • Consistent formatting for dates

Integration with Player Model

The Player model includes injury-related fields:

class Player(SBABaseModel):
    # ... other fields ...
    pitcher_injury: Optional[int]      # Pitcher injury rating
    injury_rating: Optional[str]       # General injury rating
    il_return: Optional[str]           # Injured list return date (w##g#)

When an injury is set or cleared, the player's il_return field is automatically updated via PlayerService.

Future Enhancements

Possible improvements for future versions:

  1. Injury History - View player's injury history for a season
  2. Team Injury Report - List all injuries for a team
  3. Injury Notifications - Automatic notifications when players return from injury
  4. Injury Statistics - Track injury trends and statistics
  5. Injury Chart Image - Display the official injury chart as an embed image

Migration from Legacy

Legacy Commands

The legacy injury commands were located in:

  • discord-app/cogs/players.py - set_injury_slash() and clear_injury_slash()
  • discord-app/cogs/players.py - injury_roll_slash() with manual rating/games input

Key Improvements

  1. Cleaner Command Structure: Using GroupCog for organized subcommands (/injury roll, /injury set-new, /injury clear)
  2. Simplified Interface: Single parameter for injury roll - games played automatically extracted from player data
  3. Smart Injury Ratings: Automatically reads and parses player's injury rating from database
  4. Player Autocomplete: Modern autocomplete with team prioritization for better UX
  5. Better Error Handling: User-friendly error messages via EmbedTemplate with format validation
  6. Improved Logging: Automatic logging via @logged_command decorator
  7. Service Layer: Separated business logic from command handlers
  8. Type Safety: Full type hints and Pydantic models
  9. Testability: Comprehensive unit tests (26 tests) with mocked API calls
  10. Modern UI: Consistent embed-based responses with color coding
  11. Official Tables: Complete Strat-o-Matic injury tables built into the command

Migration Details

Old: /injuryroll <rating> <games> - Manual rating and games selection New: /injury roll <player> - Single parameter, automatic rating and games extraction from player's injury_rating field

Old: /setinjury <player> <week> <game> <duration> New: /injury set-new <player> <week> <game> <duration> - Same functionality, better naming

Old: /clearinjury <player> New: /injury clear <player> - Same functionality, better naming

Database Field Update

The injury_rating field format has changed to include games played:

  • Old Format: p65, p70, etc. (rating only)
  • New Format: 1p70, 4p50, 2p65, etc. (games + rating)

Players must have their injury_rating field updated to the new format for the /injury roll command to work.


Last Updated: January 2025 Version: 2.0 Status: Active