import streamlit as st import numpy as np import pandas as pd import time from fuzzywuzzy import process def optimize_lineup(row): current_lineup = [] total_salary = 0 salary_cap = 50000 used_players = set() # Convert row to dictionary with roster positions roster = {} for col, player in zip(row.index, row): if col not in ['salary', 'median', 'Own', 'Finish_percentile', 'Dupes', 'Lineup Edge']: roster[col] = { 'name': player, 'position': map_dict['pos_map'].get(player, '').split('/'), 'team': map_dict['team_map'].get(player, ''), 'salary': map_dict['salary_map'].get(player, 0), 'median': map_dict['proj_map'].get(player, 0), 'ownership': map_dict['own_map'].get(player, 0) } total_salary += roster[col]['salary'] used_players.add(player) # Optimize each roster position in random order roster_positions = list(roster.items()) random.shuffle(roster_positions) for roster_pos, current in roster_positions: # Skip optimization for players from removed teams if current['team'] in remove_teams_var: continue valid_positions = position_rules[roster_pos] better_options = [] # Find valid replacements for this roster position for pos in valid_positions: if pos in position_groups: pos_options = [ p for p in position_groups[pos] if p['median'] > current['median'] and (total_salary - current['salary'] + p['salary']) <= salary_cap and p['player_names'] not in used_players and any(valid_pos in p['positions'] for valid_pos in valid_positions) and map_dict['team_map'].get(p['player_names']) not in remove_teams_var # Check team restriction ] better_options.extend(pos_options) if better_options: # Remove duplicates better_options = {opt['player_names']: opt for opt in better_options}.values() # Sort by median projection and take the best one best_replacement = max(better_options, key=lambda x: x['median']) # Update the lineup and tracking variables used_players.remove(current['name']) used_players.add(best_replacement['player_names']) total_salary = total_salary - current['salary'] + best_replacement['salary'] roster[roster_pos] = { 'name': best_replacement['player_names'], 'position': map_dict['pos_map'][best_replacement['player_names']].split('/'), 'team': map_dict['team_map'][best_replacement['player_names']], 'salary': best_replacement['salary'], 'median': best_replacement['median'], 'ownership': best_replacement['ownership'] } # Return optimized lineup maintaining original column order return [roster[pos]['name'] for pos in row.index if pos in roster]