nesticot commited on
Commit
25249d0
·
verified ·
1 Parent(s): 9f32875

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -86
app.py CHANGED
@@ -31,7 +31,7 @@ colour_palette = ['#FFB000','#648FFF','#785EF0',
31
  '#DC267F','#FE6100','#3D1EB2','#894D80','#16AA02','#B5592B','#A3C1ED']
32
  cmap_sum = mcolors.LinearSegmentedColormap.from_list("", ['#648FFF', '#FFFFFF', '#FFB000'])
33
 
34
- year_list = [2025,2024,2023,2022,2021,2020,2019,2018,2017]
35
 
36
 
37
  type_dict = {'R':'Regular',
@@ -157,73 +157,11 @@ dict_pitch_alpha = dict(sorted(dict_pitch.items(), key=lambda item: item[1]))
157
 
158
  import requests
159
 
160
- import os
161
- CAMPAIGN_ID = os.getenv("CAMPAIGN_ID")
162
- ACCESS_TOKEN = os.getenv("ACCESS_TOKEN")
163
- BACKUP_PW = os.getenv("BACKUP_PW")
164
- ADMIN_PW = os.getenv("ADMIN_PW")
165
-
166
- url = f"https://www.patreon.com/api/oauth2/v2/campaigns/{CAMPAIGN_ID}/members"
167
-
168
- headers = {
169
- "Authorization": f"Bearer {ACCESS_TOKEN}"
170
- }
171
-
172
- # Simple parameters, requesting the member's email and currently entitled tiers
173
- params = {
174
- "fields[member]": "full_name,email", # Request the member's email
175
- "include": "currently_entitled_tiers", # Include the currently entitled tiers
176
- "page[size]": 10000 # Fetch up to 1000 patrons per request
177
- }
178
-
179
- response = requests.get(url, headers=headers, params=params)
180
-
181
-
182
- VALID_PASSWORDS = []
183
- if response.status_code == 200:
184
- data = response.json()
185
- for patron in data['data']:
186
- try:
187
- tiers = patron['relationships']['currently_entitled_tiers']['data']
188
- if any(tier['id'] == '9078921' for tier in tiers):
189
- full_name = patron['attributes']['email']
190
- VALID_PASSWORDS.append(full_name)
191
- except KeyError:
192
- continue
193
- VALID_PASSWORDS.append(BACKUP_PW)
194
- VALID_PASSWORDS.append(ADMIN_PW)
195
-
196
 
197
  from shiny import App, reactive, ui, render
198
  from shiny.ui import h2, tags
199
 
200
 
201
-
202
- # Define the login UI
203
- login_ui = ui.page_fluid(
204
- ui.card(
205
- ui.h2([
206
- "TJStats Daily Pitching Summary App ",
207
- ui.tags.a("(@TJStats)", href="https://twitter.com/TJStats", target="_blank")
208
- ]),
209
- ui.p(
210
- "This App is available to Superstar Patrons. Please enter your Patreon email address in the box below. If you're having trouble, please refer to the ",
211
- ui.tags.a("Patreon post", href="https://www.patreon.com/posts/122860440", target="_blank"),
212
- "."
213
- ),
214
- ui.input_password("password", "Enter Patreon Email (or Password from Link):", width="25%"),
215
- ui.tags.input(
216
- type="checkbox",
217
- id="authenticated",
218
- value=False,
219
- disabled=True
220
- ),
221
- ui.input_action_button("login", "Login", class_="btn-primary"),
222
- ui.output_text("login_message"),
223
- )
224
- )
225
-
226
-
227
  # Define the UI layout for the app
228
  main_ui = ui.page_fluid(
229
  ui.layout_sidebar(
@@ -249,7 +187,7 @@ main_ui = ui.page_fluid(
249
  target="_blank"
250
  )))),
251
  ui.row(
252
- ui.column(4, ui.input_select('year_input', 'Select Season', year_list, selected=2025)),
253
  ui.column(4, ui.input_select('level_input', 'Select Level', level_dict)),
254
  ui.column(4, ui.input_select('type_input', 'Select Type', type_dict,selected='R'))
255
  ),
@@ -263,6 +201,22 @@ main_ui = ui.page_fluid(
263
  ui.row(
264
  ui.column(6, ui.input_select('split_id', 'Select Split', split_dict, multiple=False)),
265
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
  ui.row( ui.column(6,ui.input_select(
267
  "new_pitch_type",
268
  "Update Pitch Type",
@@ -439,14 +393,8 @@ app_ui = ui.page_fluid(
439
  ui.tags.script(src="script.js")
440
  ),
441
 
442
- ui.panel_conditional(
443
- "!input.authenticated",
444
- login_ui
445
- ),
446
- ui.panel_conditional(
447
- "input.authenticated",
448
  main_ui
449
- )
450
  )
451
 
452
 
@@ -454,20 +402,6 @@ app_ui = ui.page_fluid(
454
  def server(input, output, session):
455
  # This code should be inserted in your server function
456
 
457
- @reactive.Effect
458
- @reactive.event(input.login)
459
- def check_password():
460
- if input.password() in VALID_PASSWORDS:
461
- ui.update_checkbox("authenticated", value=True)
462
- ui.update_text("login_message", value="")
463
- else:
464
- ui.update_text("login_message", value="Invalid password!")
465
- ui.update_text("password", value="")
466
-
467
- @output
468
- @render.text
469
- def login_message():
470
- return ""
471
 
472
 
473
 
@@ -669,6 +603,19 @@ def server(input, output, session):
669
  end=f"{int(input.year_input())}-12-31",
670
  min=f"{int(input.year_input())}-01-01",
671
  max=f"{int(input.year_input())}-12-31")
 
 
 
 
 
 
 
 
 
 
 
 
 
672
  @output
673
  @render.text
674
  def status():
@@ -954,6 +901,50 @@ def server(input, output, session):
954
  return fig
955
 
956
  df = df.clone()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
957
 
958
  # Create plot
959
  p.set(0.6, "Creating plot...")
@@ -962,7 +953,8 @@ def server(input, output, session):
962
  pitcher_id=player_input,
963
  plot_picker='short_form_movement',
964
  sport_id=sport_id,
965
- game_type=[input.type_input()]
 
966
  )
967
 
968
 
 
31
  '#DC267F','#FE6100','#3D1EB2','#894D80','#16AA02','#B5592B','#A3C1ED']
32
  cmap_sum = mcolors.LinearSegmentedColormap.from_list("", ['#648FFF', '#FFFFFF', '#FFB000'])
33
 
34
+ year_list = [2026,2025,2024,2023,2022,2021,2020,2019,2018,2017]
35
 
36
 
37
  type_dict = {'R':'Regular',
 
157
 
158
  import requests
159
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
  from shiny import App, reactive, ui, render
162
  from shiny.ui import h2, tags
163
 
164
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  # Define the UI layout for the app
166
  main_ui = ui.page_fluid(
167
  ui.layout_sidebar(
 
187
  target="_blank"
188
  )))),
189
  ui.row(
190
+ ui.column(4, ui.input_select('year_input', 'Select Season', year_list, selected=2026)),
191
  ui.column(4, ui.input_select('level_input', 'Select Level', level_dict)),
192
  ui.column(4, ui.input_select('type_input', 'Select Type', type_dict,selected='R'))
193
  ),
 
201
  ui.row(
202
  ui.column(6, ui.input_select('split_id', 'Select Split', split_dict, multiple=False)),
203
  ),
204
+
205
+ # Comparison mode toggle and options
206
+ ui.hr(),
207
+ ui.row(
208
+ ui.column(12, ui.input_switch("compare_mode", "Compare to Another Year", value=False)),
209
+ ),
210
+ ui.panel_conditional(
211
+ "input.compare_mode",
212
+ ui.row(
213
+ ui.column(6, ui.input_select('compare_year', 'Compare Year', year_list, selected=2024)),
214
+ ui.column(6, ui.input_select('compare_type', 'Compare Type', type_dict, selected='R')),
215
+ ),
216
+ ui.row(ui.column(12, ui.output_ui('compare_date_id', 'Compare Date Range'))),
217
+ ),
218
+ ui.hr(),
219
+
220
  ui.row( ui.column(6,ui.input_select(
221
  "new_pitch_type",
222
  "Update Pitch Type",
 
393
  ui.tags.script(src="script.js")
394
  ),
395
 
 
 
 
 
 
 
396
  main_ui
397
+
398
  )
399
 
400
 
 
402
  def server(input, output, session):
403
  # This code should be inserted in your server function
404
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
 
406
 
407
 
 
603
  end=f"{int(input.year_input())}-12-31",
604
  min=f"{int(input.year_input())}-01-01",
605
  max=f"{int(input.year_input())}-12-31")
606
+
607
+ @render.ui
608
+ @reactive.event(input.compare_year, input.compare_mode, ignore_none=False)
609
+ def compare_date_id():
610
+ # Create a date range input for the comparison year
611
+ if not input.compare_mode():
612
+ return None
613
+ return ui.input_date_range("compare_date_id", "Compare Date Range",
614
+ start=f"{int(input.compare_year())}-01-01",
615
+ end=f"{int(input.compare_year())}-12-31",
616
+ min=f"{int(input.compare_year())}-01-01",
617
+ max=f"{int(input.compare_year())}-12-31")
618
+
619
  @output
620
  @render.text
621
  def status():
 
901
  return fig
902
 
903
  df = df.clone()
904
+
905
+ # Fetch comparison data if compare_mode is enabled
906
+ compare_df = None
907
+ if input.compare_mode():
908
+ try:
909
+ p.set(0.5, "Fetching comparison data...")
910
+ compare_year = int(input.compare_year())
911
+ compare_game_type = [input.compare_type()]
912
+ compare_start = str(input.compare_date_id()[0])
913
+ compare_end = str(input.compare_date_id()[1])
914
+
915
+ compare_game_list = scrape.get_player_games_list(
916
+ sport_id=sport_id,
917
+ season=compare_year,
918
+ player_id=player_input,
919
+ start_date=compare_start,
920
+ end_date=compare_end,
921
+ game_type=compare_game_type
922
+ )
923
+
924
+ compare_data_list = scrape.get_data(game_list_input=compare_game_list[:])
925
+
926
+ compare_df = (stuff_apply.stuff_apply(
927
+ fe.feature_engineering(
928
+ update.update(
929
+ scrape.get_data_df(data_list=compare_data_list).filter(
930
+ (pl.col("pitcher_id") == player_input) &
931
+ (pl.col("is_pitch") == True) &
932
+ (pl.col("start_speed") >= 50) &
933
+ (pl.col('batter_hand').is_in(split_dict_hand[input.split_id()]))
934
+ )[:]
935
+ )
936
+ )
937
+ )).with_columns(
938
+ pl.col('pitch_type').count().over('pitch_type').alias('pitch_count')
939
+ )
940
+
941
+ compare_df = compare_df.with_columns(
942
+ prop_percent=(pl.col('is_pitch') / pl.col('is_pitch').sum()).over("pitch_type"),
943
+ prop=pl.col('is_pitch').sum().over("pitch_type")
944
+ )
945
+ except Exception as e:
946
+ print(f"Error fetching comparison data: {e}")
947
+ compare_df = None
948
 
949
  # Create plot
950
  p.set(0.6, "Creating plot...")
 
953
  pitcher_id=player_input,
954
  plot_picker='short_form_movement',
955
  sport_id=sport_id,
956
+ game_type=[input.type_input()],
957
+ compare_df=compare_df
958
  )
959
 
960