DFS_Contest_Analyzer / global_func /load_contest_file.py
James McCool
Enhance player lineup processing in load_contest_file function
a266f29
raw
history blame
7.56 kB
import streamlit as st
import pandas as pd
def load_contest_file(upload, sport):
pos_values = ['P', 'C', '1B', '2B', '3B', 'SS', 'OF']
if upload is not None:
try:
try:
if upload.name.endswith('.csv'):
raw_df = pd.read_csv(upload)
elif upload.name.endswith(('.xls', '.xlsx')):
raw_df = pd.read_excel(upload)
else:
st.error('Please upload either a CSV or Excel file')
return None
except:
raw_df = upload
df = raw_df[['EntryId', 'EntryName', 'TimeRemaining', 'Points', 'Lineup', 'Player', 'Roster Position', '%Drafted', 'FPTS', 'Salary', 'Team']]
df = df.rename(columns={'Roster Position': 'Pos', '%Drafted': 'Own'})
# Split EntryName into base name and entry count
df['BaseName'] = df['EntryName'].str.replace(r'\s*\(\d+/\d+\)$', '', regex=True)
df['EntryCount'] = df['EntryName'].str.extract(r'\((\d+/\d+)\)')
df['EntryCount'] = df['EntryCount'].fillna('1/1') # Default to 1/1 if no entry count
# Split the lineup string by replacing position indicators with commas
# We need to ensure we only replace position indicators that are at the start of a player entry
# and not those that might appear within player names
df['Lineup'] = df['Lineup'].str.replace(r'\b(' + '|'.join(pos_values) + r')\b', r'\1,', regex=True)
# Split into individual columns and remove position indicators
# First, determine the maximum number of players in any lineup
max_players = int(df['Lineup'].str.split(',').str.len().max())
if max_players <= 0:
st.error('No valid lineups found in the uploaded file')
return None
# Create columns for each player
for i in range(1, max_players):
df[i] = df['Lineup'].str.split(',').str[i].str.strip()
# Remove position indicators from the end of each entry
df[i] = df[i].str.replace(r'\s+(' + '|'.join(pos_values) + r')$', '', regex=True)
# Replace None with -1
df[i] = df[i].fillna('-1')
if sport == 'MLB':
df = df.rename(columns={1: '1B', 2: '2B', 3: '3B', 4: 'C', 5: 'OF1', 6: 'OF2', 7: 'OF3', 8: 'SP1', 9: 'SP2', 10: 'SS'})
try:
df['Own'] = df['Own'].str.replace('%', '').astype(float)
except:
df['Own'] = df['Own'].astype(float)
ownership_df = df[['Player', 'Own']]
fpts_df = df[['Player', 'FPTS']]
salary_df = df[['Player', 'Salary']]
team_df = df[['Player', 'Team']]
pos_df = df[['Player', 'Pos']]
# Create position mapping dictionary
pos_dict = dict(zip(pos_df['Player'], pos_df['Pos']))
# Debug prints
print("\nPosition Dictionary:")
print(pos_dict)
print("\nSample Lineup String:")
print(df['Lineup'].iloc[0]) # Print first lineup
# Function to check if player is eligible for position
def is_eligible_for_position(player, target_pos):
if player not in pos_dict:
print(f"Player not found in pos_dict: {player}")
return False
player_positions = pos_dict[player].split('/')
print(f"Checking {player} for {target_pos}. Player positions: {player_positions}")
# Handle special cases
if target_pos.startswith('SP') and 'P' in player_positions:
return True
if target_pos.startswith('OF') and 'OF' in player_positions:
return True
return target_pos in player_positions
# Process each lineup
for idx, row in df.iterrows():
# Get all players in the lineup and clean up the strings
players = row['Lineup'].split(',')
cleaned_players = []
current_position = None
for item in players:
item = item.strip()
# If the item is just a position indicator, store it
if item in pos_values:
current_position = item
continue
# If we have a position and a player name
if current_position:
# Remove any trailing position indicators
for pos in pos_values:
if item.endswith(pos):
item = item[:-len(pos)].strip()
cleaned_players.append(item)
current_position = None
else:
# If we somehow got a player without a position, try to clean it
for pos in pos_values:
if item.endswith(pos):
item = item[:-len(pos)].strip()
break
cleaned_players.append(item)
print(f"\nProcessing lineup {idx}:")
print(f"Original lineup: {row['Lineup']}")
print(f"Cleaned players: {cleaned_players}")
# First pass: fill required positions (excluding OF)
required_positions = ['SP1', 'SP2', 'C', '1B', '2B', '3B', 'SS']
for pos in required_positions:
for player in cleaned_players:
if is_eligible_for_position(player, pos):
print(f"Assigning {player} to {pos}")
df.at[idx, pos] = player
cleaned_players.remove(player)
break
else:
print(f"No player found for {pos}")
# Second pass: fill OF positions with remaining players
of_positions = ['OF1', 'OF2', 'OF3']
for pos in of_positions:
for player in cleaned_players:
if 'OF' in pos_dict.get(player, '').split('/'):
print(f"Assigning {player} to {pos}")
df.at[idx, pos] = player
cleaned_players.remove(player)
break
else:
print(f"No player found for {pos}, using -1")
df.at[idx, pos] = '-1'
cleaned_df = df.drop(columns=['EntryId', 'EntryName', 'TimeRemaining', 'Points', 'Lineup', 'Player', 'Pos', 'Own', 'FPTS', 'Salary', 'Team'])
cleaned_df = cleaned_df[['BaseName', 'EntryCount', 'SP1', 'SP2', 'C', '1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3']]
entry_list = list(set(df['BaseName']))
entry_list.sort()
return cleaned_df, ownership_df, fpts_df, salary_df, team_df, pos_df, entry_list
except Exception as e:
st.error(f'Error loading file: {str(e)}')
return None
return None