Spaces:
Sleeping
Sleeping
JonSolow
commited on
Draft page (#19)
Browse files* Add blank draft page
* Fix uneeded f-string
* Load yahoo_con into session
* Enable draft view with 2023 and 2024 for testing
* Apply black
* Load league settings
* Implement selection of year and refresh button
* Implement view of roster positions with caching of league settings
* Move ECR to another file to share
* Add export of fp tiers csv
* Get ecr data loaded and merged withd draft results
* Sort into columns by pos
* Remove unused fp ecr
* Split into tiers
* Filter out some positions
* Put filters in expander
* Format red if drafted
- src/config.py +1 -0
- src/ecr.py +67 -0
- src/login_component.py +2 -0
- src/pages/3_Draft_View.py +160 -0
- src/pages/3_ECR.py +2 -70
- src/yahoo_client.py +38 -3
src/config.py
CHANGED
@@ -3,3 +3,4 @@ DEFAULT_ICON = "🏉"
|
|
3 |
LEAGUE_NUMBER_TEAMS = 12
|
4 |
|
5 |
KEEPER_DATA_URL = "../../tests/mocks/2024_keepers.csv"
|
|
|
|
3 |
LEAGUE_NUMBER_TEAMS = 12
|
4 |
|
5 |
KEEPER_DATA_URL = "../../tests/mocks/2024_keepers.csv"
|
6 |
+
SEASON = 2024
|
src/ecr.py
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import pandas as pd
|
3 |
+
import streamlit as st
|
4 |
+
|
5 |
+
from streamlit_filter import filter_dataframe
|
6 |
+
|
7 |
+
|
8 |
+
def load_adp() -> pd.DataFrame:
|
9 |
+
df = pd.read_csv(r"https://raw.githubusercontent.com/dynastyprocess/data/master/files/db_fpecr_latest.csv")
|
10 |
+
df["ranking_type"] = df["fp_page"].apply(lambda x: os.path.split(x)[-1].replace(".php", ""))
|
11 |
+
return df
|
12 |
+
|
13 |
+
|
14 |
+
@st.cache_data(ttl=60 * 60 * 24)
|
15 |
+
def load_adp_data():
|
16 |
+
# Merge ADP
|
17 |
+
data = load_adp()
|
18 |
+
ranking_type_list = sorted(list(data.ranking_type.unique()))
|
19 |
+
return data, ranking_type_list
|
20 |
+
|
21 |
+
|
22 |
+
def filtered_ecr_dataframe(data: pd.DataFrame, ranking_type_list: list[str]):
|
23 |
+
default_ix = ranking_type_list.index("ppr-superflex-cheatsheets")
|
24 |
+
ranking_type_selected = st.selectbox("ECR Format:", ranking_type_list, index=default_ix)
|
25 |
+
ranking_type_filter = data["ranking_type"] == ranking_type_selected
|
26 |
+
|
27 |
+
is_advanced = st.checkbox("Show Advanced View")
|
28 |
+
|
29 |
+
id_cols = [
|
30 |
+
# "player_square_image_url",
|
31 |
+
"player",
|
32 |
+
"pos",
|
33 |
+
"team",
|
34 |
+
]
|
35 |
+
|
36 |
+
id_cols_advanced = [
|
37 |
+
"bye",
|
38 |
+
"player_owned_yahoo",
|
39 |
+
]
|
40 |
+
|
41 |
+
adp_cols: list[str] = [
|
42 |
+
"ecr",
|
43 |
+
]
|
44 |
+
|
45 |
+
adp_cols_advanced = ["sd", "best", "worst"]
|
46 |
+
|
47 |
+
if is_advanced:
|
48 |
+
show_columns = id_cols + id_cols_advanced + adp_cols + adp_cols_advanced
|
49 |
+
else:
|
50 |
+
show_columns = id_cols + adp_cols
|
51 |
+
|
52 |
+
data_filtered_by_ranking_type = data.loc[ranking_type_filter]
|
53 |
+
latest_scrape_date = data_filtered_by_ranking_type.scrape_date.max()
|
54 |
+
st.write(f"Scraped data as of: {latest_scrape_date}")
|
55 |
+
|
56 |
+
filtered_data = filter_dataframe(data.loc[ranking_type_filter, show_columns])
|
57 |
+
st.dataframe(
|
58 |
+
filtered_data,
|
59 |
+
hide_index=True,
|
60 |
+
height=35 * (len(filtered_data) + 1) + 12,
|
61 |
+
use_container_width=True,
|
62 |
+
column_config={
|
63 |
+
# "player_square_image_url": st.column_config.ImageColumn(label="", help="Player image"),
|
64 |
+
},
|
65 |
+
)
|
66 |
+
|
67 |
+
st.write("Source: https://github.com/dynastyprocess/data")
|
src/login_component.py
CHANGED
@@ -41,6 +41,7 @@ def get_authorization_button():
|
|
41 |
st.session_state.token = result.get("token")
|
42 |
yahoo_con = YahooFantasyClient(oauth2, st.session_state.token)
|
43 |
st.session_state.logged_in_guid = yahoo_con.get_guid_for_logged_in_user()
|
|
|
44 |
st.rerun()
|
45 |
else:
|
46 |
# # If token exists in session state, allow logout
|
@@ -48,6 +49,7 @@ def get_authorization_button():
|
|
48 |
if st.button("Logout"):
|
49 |
del st.session_state.token
|
50 |
del st.session_state.logged_in_guid
|
|
|
51 |
st.rerun()
|
52 |
# # If token exists in session state, show the token
|
53 |
# token = st.session_state["token"]
|
|
|
41 |
st.session_state.token = result.get("token")
|
42 |
yahoo_con = YahooFantasyClient(oauth2, st.session_state.token)
|
43 |
st.session_state.logged_in_guid = yahoo_con.get_guid_for_logged_in_user()
|
44 |
+
st.session_state.yahoo_client = yahoo_con
|
45 |
st.rerun()
|
46 |
else:
|
47 |
# # If token exists in session state, allow logout
|
|
|
49 |
if st.button("Logout"):
|
50 |
del st.session_state.token
|
51 |
del st.session_state.logged_in_guid
|
52 |
+
del st.session_state.yahoo_client
|
53 |
st.rerun()
|
54 |
# # If token exists in session state, show the token
|
55 |
# token = st.session_state["token"]
|
src/pages/3_Draft_View.py
ADDED
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
import pandas as pd
|
3 |
+
import requests
|
4 |
+
import streamlit as st
|
5 |
+
|
6 |
+
from config import DEFAULT_ICON, SEASON
|
7 |
+
from login_component import is_token_in_session
|
8 |
+
from shared_page import common_page_config
|
9 |
+
from streamlit_filter import filter_dataframe
|
10 |
+
|
11 |
+
|
12 |
+
@st.cache_data(ttl=60 * 60 * 24)
|
13 |
+
def load_yahoo_to_fp_id_map() -> dict[str, str]:
|
14 |
+
df = pd.read_csv(r"https://raw.githubusercontent.com/dynastyprocess/data/master/files/db_playerids.csv")
|
15 |
+
for id_col in ["yahoo_id", "fantasypros_id"]:
|
16 |
+
df[id_col] = df[id_col].fillna(-9999).apply(lambda x: str(int(x)))
|
17 |
+
return df.set_index("yahoo_id")["fantasypros_id"].to_dict()
|
18 |
+
|
19 |
+
|
20 |
+
def extract_ecr_var_data(request_text_str, var_name: str):
|
21 |
+
start_str = f"""var {var_name} = """
|
22 |
+
end_str = """};"""
|
23 |
+
end_offset = 1 # include closing bracket
|
24 |
+
|
25 |
+
start_slice_pos = request_text_str.find(start_str) + len(start_str)
|
26 |
+
first_slice = request_text_str[start_slice_pos:]
|
27 |
+
end_slice_pos = first_slice.find(end_str) + end_offset
|
28 |
+
dom_str = first_slice[:end_slice_pos]
|
29 |
+
var_json = json.loads(dom_str)
|
30 |
+
return var_json
|
31 |
+
|
32 |
+
|
33 |
+
@st.cache_data(ttl=60 * 60 * 24)
|
34 |
+
def load_ecr_data():
|
35 |
+
request_text = get_ecr_request_text()
|
36 |
+
ecr_data = extract_ecr_var_data(request_text, "ecrData")
|
37 |
+
ecr_columns = [
|
38 |
+
"player_id",
|
39 |
+
"player_name",
|
40 |
+
"player_position_id",
|
41 |
+
"player_bye_week",
|
42 |
+
"rank_ecr",
|
43 |
+
"pos_rank",
|
44 |
+
"tier",
|
45 |
+
]
|
46 |
+
df_ecr = pd.DataFrame(ecr_data["players"])[ecr_columns]
|
47 |
+
df_ecr["player_id"] = df_ecr["player_id"].apply(lambda x: str(int(x)))
|
48 |
+
|
49 |
+
# sos_data = extract_ecr_var_data(request_text, "sosData")
|
50 |
+
# adp_data = extract_ecr_var_data(request_text, "adpData")
|
51 |
+
return df_ecr
|
52 |
+
|
53 |
+
|
54 |
+
@st.cache_data(ttl=60 * 60 * 24)
|
55 |
+
def get_ecr_request_text():
|
56 |
+
r = requests.get("https://www.fantasypros.com/nfl/rankings/half-point-ppr-cheatsheets.php")
|
57 |
+
return r.text
|
58 |
+
|
59 |
+
|
60 |
+
@st.cache_resource(ttl=60 * 60 * 24)
|
61 |
+
def get_league_settings_with_cache(selected_league):
|
62 |
+
return st.session_state.yahoo_client.parse_league_settings(selected_league)
|
63 |
+
|
64 |
+
|
65 |
+
def highlight_drafted(data_row_series):
|
66 |
+
return ["background-color: red" if data_row_series.is_drafted else "" for _ in range(len(data_row_series))]
|
67 |
+
|
68 |
+
|
69 |
+
def display_formatted_tiers(df):
|
70 |
+
st.dataframe(
|
71 |
+
df.style.apply(highlight_drafted, axis=1),
|
72 |
+
hide_index=True,
|
73 |
+
height=35 * (len(df) + 1) + 5,
|
74 |
+
column_order=[
|
75 |
+
"rank_ecr",
|
76 |
+
"player_name",
|
77 |
+
# "player_position_id",
|
78 |
+
"player_bye_week",
|
79 |
+
# "tier",
|
80 |
+
# "is_drafted",
|
81 |
+
],
|
82 |
+
column_config={
|
83 |
+
"player_name": st.column_config.TextColumn(label="Name", help="Player's name"),
|
84 |
+
"player_position_id": st.column_config.TextColumn(label="Position", help="Player's position"),
|
85 |
+
"player_bye_week": st.column_config.NumberColumn(label="Bye", help="Player's Bye Week"),
|
86 |
+
"rank_ecr": st.column_config.NumberColumn(label="Rank", help="Player ECR Rank"),
|
87 |
+
"tier": st.column_config.NumberColumn(label="Tier", help="Player Tier"),
|
88 |
+
"is_drafted": st.column_config.CheckboxColumn(label="Drafted", help="Has been drafted"),
|
89 |
+
},
|
90 |
+
)
|
91 |
+
|
92 |
+
|
93 |
+
def get_page():
|
94 |
+
page_title = "Yahoo Draft Live Summary"
|
95 |
+
st.set_page_config(page_title=page_title, page_icon=DEFAULT_ICON, layout="wide")
|
96 |
+
common_page_config()
|
97 |
+
st.title(page_title)
|
98 |
+
|
99 |
+
if not is_token_in_session():
|
100 |
+
st.write(
|
101 |
+
"You must authorize the application to access your account in order to use this feature."
|
102 |
+
" Please click Login button above."
|
103 |
+
)
|
104 |
+
|
105 |
+
else:
|
106 |
+
selected_season = st.selectbox("Select Season", list(range(SEASON, 2012, -1)))
|
107 |
+
user_leagues = st.session_state.yahoo_client.find_all_leagues_for_logged_in_user(season=selected_season)
|
108 |
+
selected_league = st.selectbox("Select league", user_leagues)
|
109 |
+
league_settings = get_league_settings_with_cache(selected_league)
|
110 |
+
st.header(f"{league_settings.name} - {league_settings.season}")
|
111 |
+
with st.expander("Show Positions"):
|
112 |
+
st.dataframe(
|
113 |
+
pd.DataFrame(league_settings.roster_positions).set_index("position")["count"],
|
114 |
+
)
|
115 |
+
|
116 |
+
draft_result = pd.DataFrame(st.session_state.yahoo_client.get_draft(selected_league))
|
117 |
+
if st.button("Load / Refresh"):
|
118 |
+
draft_result = pd.DataFrame(st.session_state.yahoo_client.get_draft(selected_league))
|
119 |
+
if "player_key" in draft_result:
|
120 |
+
draft_result["player_id"] = draft_result["player_key"].apply(lambda x: x.rsplit(".", 1)[-1] if x else x)
|
121 |
+
else:
|
122 |
+
draft_result["player_id"] = ""
|
123 |
+
draft_result["fp_id"] = draft_result["player_id"].apply(lambda x: load_yahoo_to_fp_id_map().get(x))
|
124 |
+
|
125 |
+
if "team_key" not in draft_result:
|
126 |
+
draft_result["team_key"] = ""
|
127 |
+
|
128 |
+
with st.expander("Show Draft Results"):
|
129 |
+
st.dataframe(draft_result)
|
130 |
+
|
131 |
+
st.header("ECR Tiers")
|
132 |
+
ecr_data = load_ecr_data()
|
133 |
+
draft_result_merge_cols = [
|
134 |
+
"fp_id",
|
135 |
+
"team_key",
|
136 |
+
]
|
137 |
+
ecr_with_draft = ecr_data.merge(
|
138 |
+
draft_result[draft_result_merge_cols], how="left", left_on="player_id", right_on="fp_id"
|
139 |
+
)
|
140 |
+
ecr_with_draft["is_drafted"] = ecr_with_draft["fp_id"].notna()
|
141 |
+
with st.expander("Filters"):
|
142 |
+
filtered_data = filter_dataframe(
|
143 |
+
ecr_with_draft, force_on=True, force_on_columns=["is_drafted", "player_position_id"]
|
144 |
+
)
|
145 |
+
|
146 |
+
position_list = [
|
147 |
+
x for x in ["QB", "RB", "WR", "TE", "DST", "K"] if x in filtered_data.player_position_id.unique()
|
148 |
+
]
|
149 |
+
columns_list = st.columns(len(position_list))
|
150 |
+
for pos, col in zip(position_list, columns_list):
|
151 |
+
with col:
|
152 |
+
st.header(pos)
|
153 |
+
df_pos = filtered_data[filtered_data.player_position_id == pos]
|
154 |
+
for tier, df_tier in df_pos.groupby("tier"):
|
155 |
+
st.header(f"Tier {tier}")
|
156 |
+
display_formatted_tiers(df_tier)
|
157 |
+
|
158 |
+
|
159 |
+
if __name__ == "__main__":
|
160 |
+
get_page()
|
src/pages/3_ECR.py
CHANGED
@@ -1,76 +1,8 @@
|
|
1 |
-
import os
|
2 |
-
import pandas as pd
|
3 |
import streamlit as st
|
4 |
|
5 |
from config import DEFAULT_ICON
|
6 |
from shared_page import common_page_config
|
7 |
-
from
|
8 |
-
|
9 |
-
|
10 |
-
KEEPER_DATA_URL = "../../tests/mocks/2023_keepers.csv"
|
11 |
-
HEADSHOT_DATA_URL = "../../tests/mocks/2023_player_headshots.csv"
|
12 |
-
|
13 |
-
|
14 |
-
def load_adp() -> pd.DataFrame:
|
15 |
-
df = pd.read_csv(r"https://raw.githubusercontent.com/dynastyprocess/data/master/files/db_fpecr_latest.csv")
|
16 |
-
df["ranking_type"] = df["fp_page"].apply(lambda x: os.path.split(x)[-1].replace(".php", ""))
|
17 |
-
return df
|
18 |
-
|
19 |
-
|
20 |
-
@st.cache_data(ttl=60 * 60 * 24)
|
21 |
-
def load_data():
|
22 |
-
# Merge ADP
|
23 |
-
data = load_adp()
|
24 |
-
ranking_type_list = sorted(list(data.ranking_type.unique()))
|
25 |
-
return data, ranking_type_list
|
26 |
-
|
27 |
-
|
28 |
-
def filtered_ecr_dataframe(data: pd.DataFrame, ranking_type_list: list[str]):
|
29 |
-
default_ix = ranking_type_list.index("ppr-superflex-cheatsheets")
|
30 |
-
ranking_type_selected = st.selectbox("ECR Format:", ranking_type_list, index=default_ix)
|
31 |
-
ranking_type_filter = data["ranking_type"] == ranking_type_selected
|
32 |
-
|
33 |
-
is_advanced = st.checkbox("Show Advanced View")
|
34 |
-
|
35 |
-
id_cols = [
|
36 |
-
# "player_square_image_url",
|
37 |
-
"player",
|
38 |
-
"pos",
|
39 |
-
"team",
|
40 |
-
]
|
41 |
-
|
42 |
-
id_cols_advanced = [
|
43 |
-
"bye",
|
44 |
-
"player_owned_yahoo",
|
45 |
-
]
|
46 |
-
|
47 |
-
adp_cols: list[str] = [
|
48 |
-
"ecr",
|
49 |
-
]
|
50 |
-
|
51 |
-
adp_cols_advanced = ["sd", "best", "worst"]
|
52 |
-
|
53 |
-
if is_advanced:
|
54 |
-
show_columns = id_cols + id_cols_advanced + adp_cols + adp_cols_advanced
|
55 |
-
else:
|
56 |
-
show_columns = id_cols + adp_cols
|
57 |
-
|
58 |
-
data_filtered_by_ranking_type = data.loc[ranking_type_filter]
|
59 |
-
latest_scrape_date = data_filtered_by_ranking_type.scrape_date.max()
|
60 |
-
st.write(f"Scraped data as of: {latest_scrape_date}")
|
61 |
-
|
62 |
-
filtered_data = filter_dataframe(data.loc[ranking_type_filter, show_columns])
|
63 |
-
st.dataframe(
|
64 |
-
filtered_data,
|
65 |
-
hide_index=True,
|
66 |
-
height=35 * (len(filtered_data) + 1) + 12,
|
67 |
-
use_container_width=True,
|
68 |
-
column_config={
|
69 |
-
# "player_square_image_url": st.column_config.ImageColumn(label="", help="Player image"),
|
70 |
-
},
|
71 |
-
)
|
72 |
-
|
73 |
-
st.write("Source: https://github.com/dynastyprocess/data")
|
74 |
|
75 |
|
76 |
def get_keeper_app():
|
@@ -78,7 +10,7 @@ def get_keeper_app():
|
|
78 |
st.set_page_config(page_title=keeper_title, page_icon=DEFAULT_ICON, layout="wide")
|
79 |
common_page_config()
|
80 |
st.title(keeper_title)
|
81 |
-
data, ecr_type_list =
|
82 |
|
83 |
with st.container():
|
84 |
filtered_ecr_dataframe(data, ecr_type_list)
|
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
|
3 |
from config import DEFAULT_ICON
|
4 |
from shared_page import common_page_config
|
5 |
+
from ecr import load_adp_data, filtered_ecr_dataframe
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
7 |
|
8 |
def get_keeper_app():
|
|
|
10 |
st.set_page_config(page_title=keeper_title, page_icon=DEFAULT_ICON, layout="wide")
|
11 |
common_page_config()
|
12 |
st.title(keeper_title)
|
13 |
+
data, ecr_type_list = load_adp_data()
|
14 |
|
15 |
with st.container():
|
16 |
filtered_ecr_dataframe(data, ecr_type_list)
|
src/yahoo_client.py
CHANGED
@@ -2,7 +2,7 @@ import asyncio
|
|
2 |
import pandas as pd
|
3 |
from pydantic import BaseModel
|
4 |
import re
|
5 |
-
from typing import List, Mapping, Tuple, Union
|
6 |
import xml.etree.ElementTree as ET
|
7 |
from streamlit_oauth import OAuth2Component
|
8 |
|
@@ -17,6 +17,7 @@ class LeagueSettings(BaseModel):
|
|
17 |
playoff_start_week: int
|
18 |
num_playoff_teams: int
|
19 |
num_playoff_consolation_teams: int
|
|
|
20 |
|
21 |
@classmethod
|
22 |
def from_xml(cls, xml_settings: ET.Element) -> "LeagueSettings":
|
@@ -37,6 +38,19 @@ class LeagueSettings(BaseModel):
|
|
37 |
]
|
38 |
settings_fields_dict = {f: xml_settings.findtext(f"./league/settings/{f}") for f in settings_fields_list}
|
39 |
league_settings_dict = {**base_fields_dict, **settings_fields_dict}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
return cls(
|
41 |
league_key=league_settings_dict["league_key"] or "",
|
42 |
league_id=league_settings_dict["league_id"] or "",
|
@@ -47,6 +61,7 @@ class LeagueSettings(BaseModel):
|
|
47 |
playoff_start_week=int(league_settings_dict["playoff_start_week"] or 0),
|
48 |
num_playoff_teams=int(league_settings_dict["num_playoff_teams"] or 0),
|
49 |
num_playoff_consolation_teams=int(league_settings_dict["num_playoff_consolation_teams"] or 0),
|
|
|
50 |
)
|
51 |
|
52 |
|
@@ -73,8 +88,14 @@ class YahooFantasyClient:
|
|
73 |
root = ET.fromstring(xmlstring)
|
74 |
return root, xmlstring
|
75 |
|
76 |
-
def find_all_leagues_for_logged_in_user(self) -> List[str]:
|
77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
root, _ = self.yahoo_request_to_xml(url)
|
79 |
league_keys = list(
|
80 |
filter(None, [x.text for x in root.findall("./users/user/games/game/leagues/league/league_key")])
|
@@ -97,6 +118,20 @@ class YahooFantasyClient:
|
|
97 |
parsed_league_settings = LeagueSettings.from_xml(league_settings)
|
98 |
return parsed_league_settings
|
99 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
def parse_weeks_matchups(self, week: str, league_key: str) -> List[Mapping[str, Union[str, float]]]:
|
101 |
url = f"https://fantasysports.yahooapis.com/fantasy/v2/leagues;league_keys={league_key}/scoreboard;week={week}"
|
102 |
week_scoreboard, _ = self.yahoo_request_to_xml(url)
|
|
|
2 |
import pandas as pd
|
3 |
from pydantic import BaseModel
|
4 |
import re
|
5 |
+
from typing import List, Mapping, Tuple, Union, Optional
|
6 |
import xml.etree.ElementTree as ET
|
7 |
from streamlit_oauth import OAuth2Component
|
8 |
|
|
|
17 |
playoff_start_week: int
|
18 |
num_playoff_teams: int
|
19 |
num_playoff_consolation_teams: int
|
20 |
+
roster_positions: list[dict]
|
21 |
|
22 |
@classmethod
|
23 |
def from_xml(cls, xml_settings: ET.Element) -> "LeagueSettings":
|
|
|
38 |
]
|
39 |
settings_fields_dict = {f: xml_settings.findtext(f"./league/settings/{f}") for f in settings_fields_list}
|
40 |
league_settings_dict = {**base_fields_dict, **settings_fields_dict}
|
41 |
+
|
42 |
+
roster_fields_list = [
|
43 |
+
"position",
|
44 |
+
"position_type",
|
45 |
+
"count",
|
46 |
+
"is_starting_position",
|
47 |
+
]
|
48 |
+
|
49 |
+
roster_positions = [
|
50 |
+
{f: x.findtext(f"./{f}") for f in roster_fields_list}
|
51 |
+
for x in xml_settings.findall("./league/settings/roster_positions/*")
|
52 |
+
]
|
53 |
+
|
54 |
return cls(
|
55 |
league_key=league_settings_dict["league_key"] or "",
|
56 |
league_id=league_settings_dict["league_id"] or "",
|
|
|
61 |
playoff_start_week=int(league_settings_dict["playoff_start_week"] or 0),
|
62 |
num_playoff_teams=int(league_settings_dict["num_playoff_teams"] or 0),
|
63 |
num_playoff_consolation_teams=int(league_settings_dict["num_playoff_consolation_teams"] or 0),
|
64 |
+
roster_positions=roster_positions,
|
65 |
)
|
66 |
|
67 |
|
|
|
88 |
root = ET.fromstring(xmlstring)
|
89 |
return root, xmlstring
|
90 |
|
91 |
+
def find_all_leagues_for_logged_in_user(self, season: Optional[str]) -> List[str]:
|
92 |
+
if season:
|
93 |
+
season_str = f";seasons={season}"
|
94 |
+
else:
|
95 |
+
season_str = ""
|
96 |
+
url = (
|
97 |
+
f"https://fantasysports.yahooapis.com/fantasy/v2/users;use_login=1/games{season_str};game_codes=nfl/leagues"
|
98 |
+
)
|
99 |
root, _ = self.yahoo_request_to_xml(url)
|
100 |
league_keys = list(
|
101 |
filter(None, [x.text for x in root.findall("./users/user/games/game/leagues/league/league_key")])
|
|
|
118 |
parsed_league_settings = LeagueSettings.from_xml(league_settings)
|
119 |
return parsed_league_settings
|
120 |
|
121 |
+
def get_draft(self, league_key: str):
|
122 |
+
url = f"https://fantasysports.yahooapis.com/fantasy/v2/league/{league_key}/draftresults"
|
123 |
+
draft_results_xml, _ = self.yahoo_request_to_xml(url)
|
124 |
+
parsed_draft = [
|
125 |
+
{
|
126 |
+
"pick": x.findtext("./pick"),
|
127 |
+
"round": x.findtext("./round"),
|
128 |
+
"team_key": x.findtext("./team_key"),
|
129 |
+
"player_key": x.findtext("./player_key"),
|
130 |
+
}
|
131 |
+
for x in draft_results_xml.findall("./league/draft_results/*")
|
132 |
+
]
|
133 |
+
return parsed_draft
|
134 |
+
|
135 |
def parse_weeks_matchups(self, week: str, league_key: str) -> List[Mapping[str, Union[str, float]]]:
|
136 |
url = f"https://fantasysports.yahooapis.com/fantasy/v2/leagues;league_keys={league_key}/scoreboard;week={week}"
|
137 |
week_scoreboard, _ = self.yahoo_request_to_xml(url)
|