Spaces:
Sleeping
Sleeping
James McCool
commited on
Commit
·
ffe9064
1
Parent(s):
40f41b3
Enhance player swapping logic to maintain team diversity by implementing constraints that ensure at least three teams are represented in the lineup, while also considering the current player's team during replacements.
Browse files- src/sports/nhl_functions.py +38 -4
src/sports/nhl_functions.py
CHANGED
|
@@ -429,7 +429,6 @@ def init_team_results(model_source: DataFrame, position_reqs: dict, salary_cap:
|
|
| 429 |
# Add the position to our swapped tracking list
|
| 430 |
swapped_positions.append(pos_to_swap)
|
| 431 |
|
| 432 |
-
# ... existing code for finding replacement player ...
|
| 433 |
# Find the assigned position (e.g., 'OF', 'SP', etc.)
|
| 434 |
match = re.match(r'[A-Z]+', pos_to_swap.strip())
|
| 435 |
if match:
|
|
@@ -437,6 +436,20 @@ def init_team_results(model_source: DataFrame, position_reqs: dict, salary_cap:
|
|
| 437 |
else:
|
| 438 |
continue
|
| 439 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 440 |
# Handle special positions
|
| 441 |
if assigned_pos == 'FLEX' or assigned_pos == 'FLEX1' or assigned_pos == 'FLEX2':
|
| 442 |
util_positions = ['C', 'W', 'D']
|
|
@@ -461,6 +474,30 @@ def init_team_results(model_source: DataFrame, position_reqs: dict, salary_cap:
|
|
| 461 |
|
| 462 |
if eligible.empty:
|
| 463 |
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 464 |
# Randomly select a replacement
|
| 465 |
replacement = eligible.sample(1).iloc[0]
|
| 466 |
new_row[pos_to_swap] = replacement['Name']
|
|
@@ -479,9 +516,6 @@ def init_team_results(model_source: DataFrame, position_reqs: dict, salary_cap:
|
|
| 479 |
# Get all position columns (exclude totals)
|
| 480 |
pos_labels = [col for col in final_df.columns if col not in ['Total_Salary', 'Total_Median', 'Target_Team', 'Own']]
|
| 481 |
|
| 482 |
-
# Create a mapping from player name to team for fast lookup
|
| 483 |
-
player_team_map = filtered_df.set_index('Name')['Team'].to_dict()
|
| 484 |
-
|
| 485 |
# Count target team players in each row
|
| 486 |
def count_target_team(row):
|
| 487 |
return sum(1 for pos in pos_labels if player_team_map.get(row[pos], None) == target_team)
|
|
|
|
| 429 |
# Add the position to our swapped tracking list
|
| 430 |
swapped_positions.append(pos_to_swap)
|
| 431 |
|
|
|
|
| 432 |
# Find the assigned position (e.g., 'OF', 'SP', etc.)
|
| 433 |
match = re.match(r'[A-Z]+', pos_to_swap.strip())
|
| 434 |
if match:
|
|
|
|
| 436 |
else:
|
| 437 |
continue
|
| 438 |
|
| 439 |
+
# Get current player being swapped and their team
|
| 440 |
+
current_player = new_row[pos_to_swap]
|
| 441 |
+
current_player_team = player_team_map.get(current_player)
|
| 442 |
+
|
| 443 |
+
# Count teams in current lineup (before swap)
|
| 444 |
+
current_lineup_players = [new_row[pos] for pos in pos_labels]
|
| 445 |
+
current_teams = set(player_team_map.get(p) for p in current_lineup_players if player_team_map.get(p))
|
| 446 |
+
|
| 447 |
+
# Count how many players from the current player's team are in the lineup
|
| 448 |
+
players_from_same_team = sum(1 for p in current_lineup_players if player_team_map.get(p) == current_player_team)
|
| 449 |
+
|
| 450 |
+
# If this player is the only one from their team, we need to be careful
|
| 451 |
+
must_maintain_team = players_from_same_team == 1 and len(current_teams) <= 3
|
| 452 |
+
|
| 453 |
# Handle special positions
|
| 454 |
if assigned_pos == 'FLEX' or assigned_pos == 'FLEX1' or assigned_pos == 'FLEX2':
|
| 455 |
util_positions = ['C', 'W', 'D']
|
|
|
|
| 474 |
|
| 475 |
if eligible.empty:
|
| 476 |
continue
|
| 477 |
+
|
| 478 |
+
# Filter eligible players to maintain 3-team constraint
|
| 479 |
+
if must_maintain_team:
|
| 480 |
+
# Must pick from same team OR ensure 3 teams remain
|
| 481 |
+
# Get teams that would remain after removing current player
|
| 482 |
+
remaining_teams = set(player_team_map.get(p) for p in current_lineup_players if p != current_player and player_team_map.get(p))
|
| 483 |
+
|
| 484 |
+
# Filter to players whose team either:
|
| 485 |
+
# 1. Is the same as current player (maintains that team)
|
| 486 |
+
# 2. Is already in remaining_teams AND remaining_teams has at least 2 other teams
|
| 487 |
+
def maintains_3_teams(player_team):
|
| 488 |
+
if player_team == current_player_team:
|
| 489 |
+
return True # Same team, maintains the team
|
| 490 |
+
if player_team in remaining_teams and len(remaining_teams) >= 3:
|
| 491 |
+
return True # Team already represented and we have enough teams
|
| 492 |
+
if player_team not in remaining_teams and len(remaining_teams) >= 2:
|
| 493 |
+
return True # New team, but we still have 2 other teams + this one = 3
|
| 494 |
+
return False
|
| 495 |
+
|
| 496 |
+
eligible = eligible[eligible['Team'].apply(maintains_3_teams)]
|
| 497 |
+
|
| 498 |
+
if eligible.empty:
|
| 499 |
+
continue
|
| 500 |
+
|
| 501 |
# Randomly select a replacement
|
| 502 |
replacement = eligible.sample(1).iloc[0]
|
| 503 |
new_row[pos_to_swap] = replacement['Name']
|
|
|
|
| 516 |
# Get all position columns (exclude totals)
|
| 517 |
pos_labels = [col for col in final_df.columns if col not in ['Total_Salary', 'Total_Median', 'Target_Team', 'Own']]
|
| 518 |
|
|
|
|
|
|
|
|
|
|
| 519 |
# Count target team players in each row
|
| 520 |
def count_target_team(row):
|
| 521 |
return sum(1 for pos in pos_labels if player_team_map.get(row[pos], None) == target_team)
|