DFS_Contest_Analyzer / global_func /optimize_lineup.py
James McCool
Add functionality for player name cleaning and CSV mismatch detection
d04558f
raw
history blame
3.19 kB
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]