File size: 8,776 Bytes
d5aed59
65f66ec
9b4705e
8b671c6
4c938b0
9b4705e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65f66ec
9b4705e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65f66ec
9b4705e
 
 
65f66ec
9b4705e
 
65f66ec
9b4705e
 
 
 
 
 
 
 
 
 
 
 
 
 
65f66ec
9b4705e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44d5540
9b4705e
44d5540
8b671c6
 
 
 
 
 
 
 
9b4705e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44d5540
9b4705e
8b671c6
9b4705e
 
 
 
 
 
 
 
 
 
 
 
 
 
44d5540
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import streamlit as st
import requests
import pandas as pd
st.set_page_config(layout="wide")

# Define API URLs and headers
slate_url = "https://www.rotowire.com/daily/wnba/api/slate-list.php?siteID=1"
player_url_base = "https://www.rotowire.com/daily/wnba/api/players.php?slateID="

headers = {
    "Accept": "application/json, text/plain, */*",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Accept-Language": "en-US,en;q=0.9",
    "Cookie": "PHPSESSID=b340dce31e2fe6b24ba4dcc921561b50; _fbp=fb.1.1753692771687.711224744180466095; _gcl_au=1.1.1672675840.1753692772; _ga=GA1.1.661634385.1753692772; intercom-id-bfhjit7z=85529c35-cb6c-4007-9335-0687d15c18a1; intercom-session-bfhjit7z=; intercom-device-id-bfhjit7z=83ce3491-d957-4599-89eb-2dbfcfffed54; cookieyes-consent=consentid:NHZGWmhCeURaeGUySlh5cTJaTEJOcWdPU2lZT1pCd3Y,consent:yes,action:no,necessary:yes,functional:yes,analytics:yes,performance:yes,advertisement:yes,other:yes; sharedid=b24bed8b-091f-4e7e-add8-96cd466790e7; sharedid_cst=kSylLAssaw%3D%3D; _lr_retry_request=true; _lr_env_src_ats=false; hb_insticator_uid=54225407-2db3-40d3-af18-f82167168130; pbjs-unifiedid=%7B%22TDID%22%3A%2273bf1881-4f9b-4c6f-9bb0-100d21c50499%22%2C%22TDID_LOOKUP%22%3A%22TRUE%22%2C%22TDID_CREATED_AT%22%3A%222025-06-28T08%3A52%3A51%22%7D; pbjs-unifiedid_cst=kSylLAssaw%3D%3D; _cc_id=de8e1434a7144b27260fdc79a8c30409; panoramaId=c4024b79a49a7f854a05b3190db54945a7025ae2ab983e5c2283ff0dc2cd405a; panoramaId_expiry=1754297572016; panoramaIdType=panoIndiv; connectId=%7B%22ttl%22%3A86400000%2C%22lastUsed%22%3A1753692774128%2C%22lastSynced%22%3A1753692774128%7D; cto_bidid=wNpa_V95NWJWZkFCV004YXNKdHFBZFBpaURJYXpVcCUyQjFPSmZCOEtyZnR1blJja25WM0Q1SHNIMm01bVZVZEpwdVJoQ2w4U0M5U0U2eVBEckxEZ09yODBrVDdzTGxMd0NpSzYxZm5xd0p4WTBINWFrJTNE; __gads=ID=62cdc6dbf3fa4d4e:T=1753692773:RT=1753692773:S=ALNI_MZcj2DhLz4YVMYbd_CLQ7dQMzbI5g; __gpi=UID=000011702b223793:T=1753692773:RT=1753692773:S=ALNI_Mb3F1y3HUi-GqjxvM-KBF1M3-5QHg; __eoi=ID=86abfa80c7e66266:T=1753692773:RT=1753692773:S=AA-AfjbkQxgd9_sZXLVHRz2hGqh4; idw-fe-id=8027215f-1b18-4092-9444-efece70b61b2; _lr_sampling_rate=100; cto_bundle=SiXMDV9LeGhTdEZUbkkyNlM2Mk1pdFI4WmslMkJLbzJqZ2h5b0F1eSUyQkRSdlI5dWFZbXVtQlA2VURSOUZwTDllR1NrV3ZNNVh6dEQzSzMwMlY0WW95VjFaSndNWFViYXMyRmolMkJOVlFsWUpFd0lhTTVwaTJpSldEOFFTVDZDdjZ6R01qT2FWUmUzSmdmTldzWVdiSUluVzMlMkY3Vm9oJTJGNXZRblIxOUJKSTRTc1ZWOFdGb2lwYnZ3TW1JZ2lyOFYlMkZ2YVVYNHdNczdmdVZsMFB3djhQYk03eThvREFia2VnTm9JT09lNzZURGtkY2xSbjRxSjVHYXpBOTV0Y0NjU0Z3bWlDSCUyQlg3dkk; rwlanding=%252Fdaily%252Fwnba%252Foptimizer.php; rw_tsd=1753692771__(direct)__(none)__(not set)__web__desktop; _rdt_uuid=1753692771432.f1d64ec6-1ed1-4659-b976-692ca175ebc1; _uetsid=3e8225106b9011f08382991a4653144e; _uetvid=3e823a306b9011f0bf4075c7ff02c82e; _ga_DJZM5GNYZ8=GS2.1.s1753692771$o1$g1$t1753693293$j27$l0$h1870534944",
    "Referer": "https://www.rotowire.com/daily/wnba/optimizer.php",
    "Sec-Ch-Ua": "\"Not)A;Brand\";v=\"8\", \"Chromium\";v=\"138\", \"Google Chrome\";v=\"138\"",
    "Sec-Ch-Ua-Mobile": "?0",
    "Sec-Ch-Ua-Platform": "\"Windows\"",
    "Sec-Fetch-Dest": "empty",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Site": "same-origin",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"
}

# Streamlit app title
st.title("WNBA Player Data")

# Fetch slate ID list
st.write("### Slate ID List")
try:
    slate_response = requests.get(slate_url, headers=headers)
    
    if slate_response.status_code == 200:
        slate_data = slate_response.json()
        
        # Handle slate data (list or nested 'slates')
        if isinstance(slate_data, list):
            slate_ids = [str(item.get('slateID')) for item in slate_data if 'slateID' in item]
        elif isinstance(slate_data, dict) and 'slates' in slate_data:
            slate_ids = [str(item.get('slateID')) for item in slate_data['slates'] if 'slateID' in item]
        else:
            st.error("Unexpected slate JSON structure. Please share the slate JSON response.")
            slate_ids = []
        
        if slate_ids:
            st.write("Available Slate IDs:", ", ".join(slate_ids))
        else:
            st.error("No slate IDs found in the response.")
    else:
        st.error(f"Failed to fetch slate IDs: Status code {slate_response.status_code}")
except Exception as e:
    st.error(f"An error occurred while fetching slate IDs: {str(e)}")

# Input for manual slate ID
slate_id = st.text_input("Enter Slate ID", value="512")

# Fetch player data for the entered slate ID
if slate_id:
    player_url = f"{player_url_base}{slate_id}"
    try:
        response = requests.get(player_url, headers=headers)
        
        if response.status_code == 200:
            data = response.json()
            
            # Convert JSON to DataFrame
            if isinstance(data, list):
                df = pd.DataFrame(data)
            elif isinstance(data, dict) and 'players' in data:
                df = pd.DataFrame(data['players'])
            else:
                st.error("Unexpected player JSON structure. Please share the player JSON response.")
                st.stop()
            
            # Combine firstName and lastName into Player
            if 'firstName' in df.columns and 'lastName' in df.columns:
                df['Player'] = df['firstName'] + ' ' + df['lastName']
            
            # Extract nested fields
            if 'team' in df.columns:
                df['Team'] = df['team'].apply(lambda x: x.get('abbr') if isinstance(x, dict) else x)
            if 'opponent' in df.columns:
                df['Opp'] = df['opponent'].apply(lambda x: x.get('team') if isinstance(x, dict) else x)
            if 'lineup' in df.columns:
                df['Lineup'] = df['lineup'].apply(lambda x: x.get('slot') if isinstance(x, dict) else x)
            
            # Flatten only stats.avgFpts
            if 'stats' in df.columns:
                stats_df = pd.json_normalize(df['stats'].apply(lambda x: x.get('avgFpts', {})))
                # Rename columns to match desired names
                stats_df = stats_df.rename(columns={
                    'last14': 'L14 FPTS',
                    'last3': 'L3 FPTS',
                    'last5': 'L5 FPTS',
                    'last7': 'L7 FPTS',
                    'season': 'AVG FPTS'
                })
                df = pd.concat([df.drop(columns=['stats']), stats_df], axis=1)
            
            # Rename columns
            column_mapping = {
                'Player': 'Player',
                'rotoPos': 'Position',
                'injuryStatus': 'InjuryStatus',
                'Team': 'Team',
                'salary': 'Salary',
                'minutes': 'Minutes',
                'Lineup': 'Lineup',
                'pts': 'FP',
                'Opp': 'Opp'
            }
            df = df.rename(columns=column_mapping)
            
            # Convert Lineup to 'Yes'/'No'
            if 'Lineup' in df.columns:
                df['Lineup'] = df['Lineup'].map({True: 'Yes', False: 'No', 'Yes': 'Yes', 'No': 'No', 1: 'Yes', 0: 'No', 'OUT': 'No'})
            
            # Format Salary column to include '$'
            if 'Salary' in df.columns:
                df['Salary'] = df['Salary'].apply(lambda x: f"$ {x}" if pd.notnull(x) and isinstance(x, (int, float)) else x)
            
            # Get unique teams for dropdown
            if 'Team' in df.columns:
                team_list = sorted(df['Team'].dropna().unique())
                selected_teams = st.multiselect("Select Team(s)", team_list, default=team_list)
                
                # Filter DataFrame by selected teams
                if selected_teams:
                    df = df[df['Team'].isin(selected_teams)]
            
            # Select desired columns
            base_columns = ['Player', 'Position', 'InjuryStatus', 'Team', 'Salary', 'Minutes', 'Lineup', 'FP', 'Opp']
            stats_columns = ['L14 FPTS', 'L3 FPTS', 'L5 FPTS', 'L7 FPTS', 'AVG FPTS']
            desired_columns = base_columns + stats_columns
            available_columns = [col for col in desired_columns if col in df.columns]
            
            if available_columns:
                df = df[available_columns]
                st.write("### Player Data")
                st.dataframe(df)  # Display the DataFrame
            else:
                st.error("None of the desired columns were found. Displaying all columns instead.")
                st.dataframe(df)  # Fallback to all columns
        
        else:
            st.error(f"Failed to fetch player data: Status code {response.status_code}")
    except Exception as e:
        st.error(f"An error occurred while fetching player data: {str(e)}")