Spaces:
Running
Running
James McCool
commited on
Commit
·
78ac3ba
1
Parent(s):
5bb8e91
Refactor UI layout and add custom tab styling in app.py
Browse filesSimplified the tab layout by removing unnecessary column divisions and introducing an expandable section for filters. Added custom CSS styling for tabs to improve visual appearance and user experience.
app.py
CHANGED
@@ -26,6 +26,37 @@ db = init_conn()
|
|
26 |
player_roo_format = {'Top_finish': '{:.2%}','Top_5_finish': '{:.2%}', 'Top_10_finish': '{:.2%}', '20+%': '{:.2%}', '2x%': '{:.2%}', '3x%': '{:.2%}',
|
27 |
'4x%': '{:.2%}'}
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
@st.cache_resource(ttl=200)
|
30 |
def player_stat_table():
|
31 |
collection = db["Player_Level_ROO"]
|
@@ -58,13 +89,12 @@ t_stamp = f"Last Update: " + str(timestamp) + f" CST"
|
|
58 |
tab1, tab2, tab3 = st.tabs(["Player Range of Outcomes", "Line Combo Range of Outcomes", "Power Play Range of Outcomes"])
|
59 |
|
60 |
with tab1:
|
61 |
-
|
62 |
-
with col1:
|
63 |
st.info(t_stamp)
|
64 |
if st.button("Load/Reset Data", key='reset1'):
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
site_var1 = st.radio("What table would you like to display?", ('Draftkings', 'Fanduel'), key='site_var1')
|
69 |
main_var1 = st.radio("Main slate or secondary slate?", ('Main Slate', 'Secondary Slate'), key='main_var1')
|
70 |
split_var1 = st.radio("Would you like to view the whole slate or just specific games?", ('Full Slate Run', 'Specific Games'), key='split_var1')
|
@@ -78,30 +108,28 @@ with tab1:
|
|
78 |
elif pos_split1 == 'All Positions':
|
79 |
pos_var1 = 'All'
|
80 |
sal_var1 = st.slider("Is there a certain price range you want to view?", 2000, 10000, (2000, 20000), key='sal_var1')
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
)
|
101 |
|
102 |
with tab2:
|
103 |
-
|
104 |
-
with col1:
|
105 |
st.info(t_stamp)
|
106 |
if st.button("Load/Reset Data", key='reset2'):
|
107 |
st.cache_data.clear()
|
@@ -110,26 +138,24 @@ with tab2:
|
|
110 |
site_var2 = st.radio("What table would you like to display?", ('Draftkings', 'Fanduel'), key='site_var2')
|
111 |
main_var2 = st.radio("Main slate or secondary slate?", ('Main Slate', 'Secondary Slate'), key='main_var2')
|
112 |
sal_var2 = st.slider("Is there a certain price range you want to view?", 5000, 40000, (5000, 40000), key='sal_var2')
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
)
|
129 |
|
130 |
with tab3:
|
131 |
-
|
132 |
-
with col1:
|
133 |
st.info(t_stamp)
|
134 |
if st.button("Load/Reset Data", key='reset3'):
|
135 |
st.cache_data.clear()
|
@@ -139,18 +165,17 @@ with tab3:
|
|
139 |
main_var3 = st.radio("Main slate or secondary slate?", ('Main Slate', 'Secondary Slate'), key='main_var3')
|
140 |
sal_var3 = st.slider("Is there a certain price range you want to view?", 5000, 40000, (5000, 40000), key='sal_var3')
|
141 |
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
)
|
|
|
26 |
player_roo_format = {'Top_finish': '{:.2%}','Top_5_finish': '{:.2%}', 'Top_10_finish': '{:.2%}', '20+%': '{:.2%}', '2x%': '{:.2%}', '3x%': '{:.2%}',
|
27 |
'4x%': '{:.2%}'}
|
28 |
|
29 |
+
st.markdown("""
|
30 |
+
<style>
|
31 |
+
/* Tab styling */
|
32 |
+
.stTabs [data-baseweb="tab-list"] {
|
33 |
+
gap: 8px;
|
34 |
+
padding: 4px;
|
35 |
+
}
|
36 |
+
|
37 |
+
.stTabs [data-baseweb="tab"] {
|
38 |
+
height: 50px;
|
39 |
+
white-space: pre-wrap;
|
40 |
+
background-color: #FFD700;
|
41 |
+
color: white;
|
42 |
+
border-radius: 10px;
|
43 |
+
gap: 1px;
|
44 |
+
padding: 10px 20px;
|
45 |
+
font-weight: bold;
|
46 |
+
transition: all 0.3s ease;
|
47 |
+
}
|
48 |
+
|
49 |
+
.stTabs [aria-selected="true"] {
|
50 |
+
background-color: #DAA520;
|
51 |
+
color: white;
|
52 |
+
}
|
53 |
+
|
54 |
+
.stTabs [data-baseweb="tab"]:hover {
|
55 |
+
background-color: #DAA520;
|
56 |
+
cursor: pointer;
|
57 |
+
}
|
58 |
+
</style>""", unsafe_allow_html=True)
|
59 |
+
|
60 |
@st.cache_resource(ttl=200)
|
61 |
def player_stat_table():
|
62 |
collection = db["Player_Level_ROO"]
|
|
|
89 |
tab1, tab2, tab3 = st.tabs(["Player Range of Outcomes", "Line Combo Range of Outcomes", "Power Play Range of Outcomes"])
|
90 |
|
91 |
with tab1:
|
92 |
+
with st.expander("Info and Filters"):
|
|
|
93 |
st.info(t_stamp)
|
94 |
if st.button("Load/Reset Data", key='reset1'):
|
95 |
+
st.cache_data.clear()
|
96 |
+
player_frame, line_frame, pp_frame, timestamp = player_stat_table()
|
97 |
+
t_stamp = f"Last Update: " + str(timestamp) + f" CST"
|
98 |
site_var1 = st.radio("What table would you like to display?", ('Draftkings', 'Fanduel'), key='site_var1')
|
99 |
main_var1 = st.radio("Main slate or secondary slate?", ('Main Slate', 'Secondary Slate'), key='main_var1')
|
100 |
split_var1 = st.radio("Would you like to view the whole slate or just specific games?", ('Full Slate Run', 'Specific Games'), key='split_var1')
|
|
|
108 |
elif pos_split1 == 'All Positions':
|
109 |
pos_var1 = 'All'
|
110 |
sal_var1 = st.slider("Is there a certain price range you want to view?", 2000, 10000, (2000, 20000), key='sal_var1')
|
111 |
+
|
112 |
+
final_Proj = player_frame[player_frame['Site'] == str(site_var1)]
|
113 |
+
final_Proj = final_Proj[final_Proj['Type'] == 'Basic']
|
114 |
+
final_Proj = final_Proj[final_Proj['Slate'] == main_var1]
|
115 |
+
final_Proj = final_Proj[player_frame['Team'].isin(team_var1)]
|
116 |
+
final_Proj = final_Proj[final_Proj['Salary'] >= sal_var1[0]]
|
117 |
+
final_Proj = final_Proj[final_Proj['Salary'] <= sal_var1[1]]
|
118 |
+
if pos_var1 != 'All':
|
119 |
+
final_Proj = final_Proj[final_Proj['Position'].str.contains('|'.join(pos_var1))]
|
120 |
+
final_Proj = final_Proj.sort_values(by='Median', ascending=False)
|
121 |
+
if pos_var1 == 'All':
|
122 |
+
final_Proj = final_Proj.sort_values(by='Median', ascending=False)
|
123 |
+
st.dataframe(final_Proj.iloc[:, :-3].style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), use_container_width = True)
|
124 |
+
st.download_button(
|
125 |
+
label="Export Tables",
|
126 |
+
data=convert_df_to_csv(final_Proj),
|
127 |
+
file_name='NHL_player_export.csv',
|
128 |
+
mime='text/csv',
|
129 |
+
)
|
|
|
130 |
|
131 |
with tab2:
|
132 |
+
with st.expander("Info and Filters"):
|
|
|
133 |
st.info(t_stamp)
|
134 |
if st.button("Load/Reset Data", key='reset2'):
|
135 |
st.cache_data.clear()
|
|
|
138 |
site_var2 = st.radio("What table would you like to display?", ('Draftkings', 'Fanduel'), key='site_var2')
|
139 |
main_var2 = st.radio("Main slate or secondary slate?", ('Main Slate', 'Secondary Slate'), key='main_var2')
|
140 |
sal_var2 = st.slider("Is there a certain price range you want to view?", 5000, 40000, (5000, 40000), key='sal_var2')
|
141 |
+
|
142 |
+
final_line_combos = line_frame[line_frame['Site'] == str(site_var2)]
|
143 |
+
final_line_combos = final_line_combos[final_line_combos['Type'] == 'Basic']
|
144 |
+
final_line_combos = final_line_combos[final_line_combos['Slate'] == main_var2]
|
145 |
+
final_line_combos = final_line_combos[final_line_combos['Salary'] >= sal_var2[0]]
|
146 |
+
final_line_combos = final_line_combos[final_line_combos['Salary'] <= sal_var2[1]]
|
147 |
+
final_line_combos = final_line_combos.drop_duplicates(subset=['Player'])
|
148 |
+
final_line_combos = final_line_combos.sort_values(by='Median', ascending=False)
|
149 |
+
st.dataframe(final_line_combos.iloc[:, :-3].style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
|
150 |
+
st.download_button(
|
151 |
+
label="Export Tables",
|
152 |
+
data=convert_df_to_csv(final_line_combos),
|
153 |
+
file_name='NHL_linecombos_export.csv',
|
154 |
+
mime='text/csv',
|
155 |
+
)
|
|
|
156 |
|
157 |
with tab3:
|
158 |
+
with st.expander("Info and Filters"):
|
|
|
159 |
st.info(t_stamp)
|
160 |
if st.button("Load/Reset Data", key='reset3'):
|
161 |
st.cache_data.clear()
|
|
|
165 |
main_var3 = st.radio("Main slate or secondary slate?", ('Main Slate', 'Secondary Slate'), key='main_var3')
|
166 |
sal_var3 = st.slider("Is there a certain price range you want to view?", 5000, 40000, (5000, 40000), key='sal_var3')
|
167 |
|
168 |
+
final_pp_combos = pp_frame[pp_frame['Site'] == str(site_var3)]
|
169 |
+
final_pp_combos = final_pp_combos[final_pp_combos['Type'] == 'Basic']
|
170 |
+
final_pp_combos = final_pp_combos[final_pp_combos['Slate'] == main_var3]
|
171 |
+
final_pp_combos = final_pp_combos[final_pp_combos['Salary'] >= sal_var3[0]]
|
172 |
+
final_pp_combos = final_pp_combos[final_pp_combos['Salary'] <= sal_var3[1]]
|
173 |
+
final_pp_combos = final_pp_combos.drop_duplicates(subset=['Player'])
|
174 |
+
final_pp_combos = final_pp_combos.sort_values(by='Median', ascending=False)
|
175 |
+
st.dataframe(final_pp_combos.iloc[:, :-3].style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
|
176 |
+
st.download_button(
|
177 |
+
label="Export Tables",
|
178 |
+
data=convert_df_to_csv(final_pp_combos),
|
179 |
+
file_name='NHL_powerplay_export.csv',
|
180 |
+
mime='text/csv',
|
181 |
+
)
|
|