major-domo-v2/utils/autocomplete.py
Cal Corum 758be0f166 CLAUDE: Fix trade system issues and enhance documentation
Major fixes and improvements:

Trade System Fixes:
- Fix duplicate player moves in trade embed Player Exchanges section
- Resolve "WVMiL not participating" error for Minor League destinations
- Implement organizational authority model for ML/MiL/IL team relationships
- Update Trade.cross_team_moves to deduplicate using moves_giving only

Team Model Enhancements:
- Rewrite roster_type() method using sname as definitive source per spec
- Fix edge cases like "BHMIL" (Birmingham IL) vs "BHMMIL"
- Update _get_base_abbrev() to use consistent sname-based logic
- Add organizational lookup support in trade participation

Autocomplete System:
- Fix major_league_team_autocomplete invalid roster_type parameter
- Implement client-side filtering using Team.roster_type() method
- Add comprehensive test coverage for all autocomplete functions
- Centralize autocomplete logic to shared utils functions

Test Infrastructure:
- Add 25 new tests for trade models and trade builder
- Add 13 autocomplete function tests with error handling
- Fix existing test failures with proper mocking patterns
- Update dropadd tests to use shared autocomplete functions

Documentation Updates:
- Document trade model enhancements and deduplication fix
- Add autocomplete function documentation with usage examples
- Document organizational authority model and edge case handling
- Update README files with recent fixes and implementation notes

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-06 16:10:13 -05:00

173 lines
5.4 KiB
Python

"""
Autocomplete Utilities
Shared autocomplete functions for Discord slash commands.
"""
from typing import List, Optional
import discord
from discord import app_commands
from services.player_service import player_service
from services.team_service import team_service
from utils.team_utils import get_user_major_league_team
from constants import SBA_CURRENT_SEASON
async def player_autocomplete(
interaction: discord.Interaction,
current: str
) -> List[app_commands.Choice[str]]:
"""
Autocomplete for player names with team context prioritization.
Prioritizes players from the user's team first, then shows other players.
Args:
interaction: Discord interaction object
current: Current input from user
Returns:
List of player name choices (user's team players first)
"""
if len(current) < 2:
return []
try:
# Get user's team for prioritization
user_team = await get_user_major_league_team(interaction.user.id)
# Search for players using the search endpoint
players = await player_service.search_players(current, limit=50, season=SBA_CURRENT_SEASON)
# Separate players by team (user's team vs others)
user_team_players = []
other_players = []
for player in players:
# Check if player belongs to user's team (any roster section)
is_users_player = False
if user_team and hasattr(player, 'team') and player.team:
# Check if player is from user's major league team or has same base team
if (player.team.id == user_team.id or
(hasattr(player, 'team_id') and player.team_id == user_team.id)):
is_users_player = True
if is_users_player:
user_team_players.append(player)
else:
other_players.append(player)
# Format choices with team context
choices = []
# Add user's team players first (prioritized)
for player in user_team_players[:15]: # Limit user team players
team_info = f"{player.primary_position}"
if hasattr(player, 'team') and player.team:
team_info += f" - {player.team.abbrev}"
choice_name = f"{player.name} ({team_info})"
choices.append(app_commands.Choice(name=choice_name, value=player.name))
# Add other players (remaining slots)
remaining_slots = 25 - len(choices)
for player in other_players[:remaining_slots]:
team_info = f"{player.primary_position}"
if hasattr(player, 'team') and player.team:
team_info += f" - {player.team.abbrev}"
choice_name = f"{player.name} ({team_info})"
choices.append(app_commands.Choice(name=choice_name, value=player.name))
return choices
except Exception:
# Silently fail on autocomplete errors to avoid disrupting user experience
return []
async def team_autocomplete(
interaction: discord.Interaction,
current: str
) -> List[app_commands.Choice[str]]:
"""
Autocomplete for team abbreviations.
Args:
interaction: Discord interaction object
current: Current input from user
Returns:
List of team abbreviation choices
"""
if len(current) < 1:
return []
try:
# Get all teams for current season
teams = await team_service.get_teams_by_season(SBA_CURRENT_SEASON)
# Filter teams by current input and limit to 25
matching_teams = [
team for team in teams
if current.lower() in team.abbrev.lower() or current.lower() in team.sname.lower()
][:25]
choices = []
for team in matching_teams:
choice_name = f"{team.abbrev} - {team.sname}"
choices.append(app_commands.Choice(name=choice_name, value=team.abbrev))
return choices
except Exception:
# Silently fail on autocomplete errors
return []
async def major_league_team_autocomplete(
interaction: discord.Interaction,
current: str
) -> List[app_commands.Choice[str]]:
"""
Autocomplete for Major League team abbreviations only.
Used for trade commands where only ML team owners should be able to initiate trades.
Args:
interaction: Discord interaction object
current: Current input from user
Returns:
List of Major League team abbreviation choices
"""
if len(current) < 1:
return []
try:
# Get all teams for current season
all_teams = await team_service.get_teams_by_season(SBA_CURRENT_SEASON)
# Filter to only Major League teams using the model's helper method
from models.team import RosterType
ml_teams = [
team for team in all_teams
if team.roster_type() == RosterType.MAJOR_LEAGUE
]
# Filter teams by current input and limit to 25
matching_teams = [
team for team in ml_teams
if current.lower() in team.abbrev.lower() or current.lower() in team.sname.lower()
][:25]
choices = []
for team in matching_teams:
choice_name = f"{team.abbrev} - {team.sname}"
choices.append(app_commands.Choice(name=choice_name, value=team.abbrev))
return choices
except Exception:
# Silently fail on autocomplete errors
return []