From a9e749640dd86d9eb91d170b2d3c5dc2e1d73378 Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Fri, 17 Oct 2025 16:37:01 -0500 Subject: [PATCH] Added /search endpoint to /players --- app/routers_v3/players.py | 53 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/app/routers_v3/players.py b/app/routers_v3/players.py index bf7c2f5..9930cb7 100644 --- a/app/routers_v3/players.py +++ b/app/routers_v3/players.py @@ -124,6 +124,57 @@ async def get_players( return return_players +@router.get('/search') +@handle_db_errors +@add_cache_headers(max_age=5*60) +async def search_players( + q: str = Query(..., description="Search query for player name"), + season: Optional[int] = Query(default=None, description="Season to search in (defaults to current)"), + limit: int = Query(default=10, ge=1, le=50, description="Maximum number of results to return"), + short_output: bool = False): + """ + Real-time fuzzy search for players by name. + + Returns players matching the query with exact matches prioritized over partial matches. + """ + if season is None: + # Get current season from the database - using a simple approach + from ..db_engine import Current + current = Current.select().first() + season = current.season if current else 12 # fallback to season 12 + + # Get all players matching the name pattern (partial match supported by existing logic) + all_players = Player.select_season(season).where( + fn.lower(Player.name).contains(q.lower()) + ) + + # Convert to list for sorting + players_list = list(all_players) + + # Sort by relevance (exact matches first, then partial) + query_lower = q.lower() + exact_matches = [] + partial_matches = [] + + for player in players_list: + name_lower = player.name.lower() + if name_lower == query_lower: + exact_matches.append(player) + elif query_lower in name_lower: + partial_matches.append(player) + + # Combine and limit results + results = exact_matches + partial_matches + limited_results = results[:limit] + + db.close() + return { + 'count': len(limited_results), + 'total_matches': len(results), + 'players': [model_to_dict(x, recurse=not short_output) for x in limited_results] + } + + @router.get('/{player_id}') @handle_db_errors @add_cache_headers(max_age=10*60) @@ -217,7 +268,7 @@ async def patch_player( this_player.headshot = headshot if il_return is not None: - this_player.il_return = il_return + this_player.il_return = None if il_return == '' else il_return if demotion_week is not None: this_player.demotion_week = demotion_week if strat_code is not None: