amendolajine commited on
Commit
414cb71
·
verified ·
1 Parent(s): 2089a47

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +70 -51
app.py CHANGED
@@ -13,8 +13,8 @@ def load_excel(file):
13
  """
14
  Reads the Excel file and normalizes header names.
15
  Expected headers (row 1): "Player", "Role 1", "Role 2", "Role 3", "xB90".
16
- Returns six Dropdown components (three for exchange roles and three for preferred proposal roles)
17
- populated with the union of roles from the three role columns (blank option prepended).
18
  """
19
  global df
20
  logging.debug("load_excel: Received file %s", file.name)
@@ -42,21 +42,20 @@ def load_excel(file):
42
  # Get union of roles from all three columns.
43
  roles = pd.concat([df["role1"], df["role2"], df["role3"]]).dropna().unique().tolist()
44
  roles = sorted(roles)
45
- roles = [""] + roles # Blank option.
46
  logging.debug("Roles found: %s", roles)
47
- # Return six dropdown components.
48
  return (
49
- gr.Dropdown(choices=roles, interactive=True), # role1 for exchange
50
- gr.Dropdown(choices=roles, interactive=True), # role2 for exchange
51
- gr.Dropdown(choices=roles, interactive=True), # role3 for exchange
52
- gr.Dropdown(choices=roles, interactive=True), # preferred role for player1
53
- gr.Dropdown(choices=roles, interactive=True), # preferred role for player2
54
- gr.Dropdown(choices=roles, interactive=True) # preferred role for player3
55
  )
56
 
57
  def update_players(selected_role):
58
  """
59
- Given a selected role, returns a new Dropdown with players whose name appears
60
  in any of the role columns.
61
  A blank option is added.
62
  """
@@ -65,8 +64,8 @@ def update_players(selected_role):
65
  if df is None or not selected_role:
66
  return gr.Dropdown(choices=[], interactive=True)
67
  players = df[
68
- (df["role1"] == selected_role) |
69
- (df["role2"] == selected_role) |
70
  (df["role3"] == selected_role)
71
  ]["player"].dropna().unique().tolist()
72
  players = sorted(players)
@@ -76,8 +75,8 @@ def update_players(selected_role):
76
 
77
  def get_xb90_value(role, player):
78
  """
79
- Returns the xB90 value for the given player and selected role.
80
- Searches rows where the player's name matches and the role appears in any role column.
81
  """
82
  global df
83
  logging.debug("get_xb90_value: role=%s, player=%s", role, player)
@@ -95,18 +94,16 @@ def compute_exchange(role1, player1, pref1, role2, player2, pref2, role3, player
95
  Computes exchange proposals:
96
  - Actual value: sum of selected players’ xB90.
97
  - Target: actual * 1.05.
98
- - For each selected player, gather candidate replacements from rows where:
99
- (a) the candidate has the selected role (in any role column), and
100
- (b) if a preferred role is provided for that player, then candidate must have it in some role column.
101
- If no candidate meets the preferred criterion, the preference is relaxed.
102
  - Excludes any candidate that is among the selected players.
103
- - Generates candidate combinations (Cartesian product) and selects up to three proposals
104
- ensuring that no candidate appears in more than one proposal.
105
  """
106
  global df
107
  logging.debug("compute_exchange: Starting computation")
108
  selected = []
109
- # Collect selected players.
110
  for i, (r, p, pref) in enumerate([(role1, player1, pref1), (role2, player2, pref2), (role3, player3, pref3)], start=1):
111
  if r and p:
112
  xb90_val = get_xb90_value(r, p)
@@ -135,7 +132,6 @@ def compute_exchange(role1, player1, pref1, role2, player2, pref2, role3, player
135
  r = sel["role"]
136
  pref = sel["pref"]
137
  logging.debug("Gathering candidates for selected role %s with preference %s", r, pref)
138
- # First, try filtering by both role and preferred role if provided.
139
  if pref:
140
  candidates_df = df[
141
  (((df["role1"] == r) | (df["role2"] == r) | (df["role3"] == r))) &
@@ -145,7 +141,6 @@ def compute_exchange(role1, player1, pref1, role2, player2, pref2, role3, player
145
  candidates = candidates_df[["player", "xb90"]].dropna().to_dict(orient="records")
146
  if not candidates:
147
  logging.debug("No candidates found matching preference %s; relaxing preference", pref)
148
- # Relax the preference constraint.
149
  candidates_df = df[
150
  (((df["role1"] == r) | (df["role2"] == r) | (df["role3"] == r))) &
151
  (~df["player"].isin(selected_names))
@@ -157,7 +152,7 @@ def compute_exchange(role1, player1, pref1, role2, player2, pref2, role3, player
157
  (~df["player"].isin(selected_names))
158
  ]
159
  candidates = candidates_df[["player", "xb90"]].dropna().to_dict(orient="records")
160
- logging.debug("Candidates for %s: %s", r, candidates)
161
  if not candidates:
162
  return f"No alternative candidates found for role '{r}' (excluding selected players)."
163
  candidate_lists.append(candidates)
@@ -211,52 +206,76 @@ def compute_exchange(role1, player1, pref1, role2, player2, pref2, role3, player
211
  logging.debug("Exchange proposals computed successfully.")
212
  return output
213
 
214
- # Build the Gradio Blocks interface with Soft theme and custom CSS for mobile.
215
  with gr.Blocks(theme=gr.themes.Soft(), css="""
216
- .gradio-container { max-width: 800px; margin: auto; }
217
- .gradio-interface { padding: 20px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  @media (max-width: 600px) {
219
  .gradio-container { padding: 10px; }
220
  .gradio-interface { padding: 10px; }
221
  }
222
  """) as demo:
223
- gr.Markdown("<h2 style='text-align:center;'>Fantasy Football Player Exchange App</h2>")
224
- gr.Markdown("<p style='text-align:center;'>Upload an Excel file with player data. Row 1 must have headers: 'Player', 'Role 1', 'Role 2', 'Role 3', 'xB90'.</p>")
225
 
226
- file_input = gr.File(label="Upload Excel File (.xlsx)", file_types=[".xlsx"])
227
 
228
  with gr.Row():
229
  with gr.Column():
230
- role1 = gr.Dropdown(label="Role for Player 1", choices=[], interactive=True)
231
- player1 = gr.Dropdown(label="Player 1", choices=[], interactive=True)
232
- xb90_1 = gr.Textbox(label="xB90 for Player 1", interactive=False)
233
- pref1 = gr.Dropdown(label="Preferred Proposal Role for Player 1", choices=[], interactive=True)
234
  with gr.Column():
235
- role2 = gr.Dropdown(label="Role for Player 2 (Optional)", choices=[], interactive=True)
236
- player2 = gr.Dropdown(label="Player 2 (Optional)", choices=[], interactive=True)
237
- xb90_2 = gr.Textbox(label="xB90 for Player 2", interactive=False)
238
- pref2 = gr.Dropdown(label="Preferred Proposal Role for Player 2", choices=[], interactive=True)
239
  with gr.Column():
240
- role3 = gr.Dropdown(label="Role for Player 3 (Optional)", choices=[], interactive=True)
241
- player3 = gr.Dropdown(label="Player 3 (Optional)", choices=[], interactive=True)
242
- xb90_3 = gr.Textbox(label="xB90 for Player 3", interactive=False)
243
- pref3 = gr.Dropdown(label="Preferred Proposal Role for Player 3", choices=[], interactive=True)
244
 
245
- # When file is uploaded, update all six dropdowns with the union of roles.
246
  file_input.change(fn=load_excel, inputs=file_input, outputs=[role1, role2, role3, pref1, pref2, pref3])
247
-
248
- # When a role is selected, update the corresponding player dropdown.
249
  role1.change(fn=update_players, inputs=role1, outputs=player1)
250
  role2.change(fn=update_players, inputs=role2, outputs=player2)
251
  role3.change(fn=update_players, inputs=role3, outputs=player3)
252
-
253
- # When a player is selected, display the xB90 value.
254
  player1.change(fn=get_xb90_value, inputs=[role1, player1], outputs=xb90_1)
255
  player2.change(fn=get_xb90_value, inputs=[role2, player2], outputs=xb90_2)
256
  player3.change(fn=get_xb90_value, inputs=[role3, player3], outputs=xb90_3)
257
 
258
- exchange_button = gr.Button("Compute Exchange Proposals")
259
- output_box = gr.Textbox(label="Exchange Proposals", lines=12)
260
 
261
  exchange_button.click(
262
  fn=compute_exchange,
@@ -264,5 +283,5 @@ with gr.Blocks(theme=gr.themes.Soft(), css="""
264
  outputs=output_box,
265
  )
266
 
267
- # Launch the app with debug=True.
268
  demo.launch(debug=True)
 
13
  """
14
  Reads the Excel file and normalizes header names.
15
  Expected headers (row 1): "Player", "Role 1", "Role 2", "Role 3", "xB90".
16
+ Returns six Dropdown components: three for selected roles and three for preferred proposal roles,
17
+ populated from the union of roles in all role columns (with a blank option prepended).
18
  """
19
  global df
20
  logging.debug("load_excel: Received file %s", file.name)
 
42
  # Get union of roles from all three columns.
43
  roles = pd.concat([df["role1"], df["role2"], df["role3"]]).dropna().unique().tolist()
44
  roles = sorted(roles)
45
+ roles = [""] + roles # Prepend blank option.
46
  logging.debug("Roles found: %s", roles)
 
47
  return (
48
+ gr.Dropdown(choices=roles, interactive=True),
49
+ gr.Dropdown(choices=roles, interactive=True),
50
+ gr.Dropdown(choices=roles, interactive=True),
51
+ gr.Dropdown(choices=roles, interactive=True),
52
+ gr.Dropdown(choices=roles, interactive=True),
53
+ gr.Dropdown(choices=roles, interactive=True)
54
  )
55
 
56
  def update_players(selected_role):
57
  """
58
+ Given a selected role, returns a new Dropdown with players whose name appears
59
  in any of the role columns.
60
  A blank option is added.
61
  """
 
64
  if df is None or not selected_role:
65
  return gr.Dropdown(choices=[], interactive=True)
66
  players = df[
67
+ (df["role1"] == selected_role) |
68
+ (df["role2"] == selected_role) |
69
  (df["role3"] == selected_role)
70
  ]["player"].dropna().unique().tolist()
71
  players = sorted(players)
 
75
 
76
  def get_xb90_value(role, player):
77
  """
78
+ Returns the xB90 value (as a string) for the given player and selected role.
79
+ Searches rows where the player's name matches and the role appears in any column.
80
  """
81
  global df
82
  logging.debug("get_xb90_value: role=%s, player=%s", role, player)
 
94
  Computes exchange proposals:
95
  - Actual value: sum of selected players’ xB90.
96
  - Target: actual * 1.05.
97
+ - For each selected player, gather candidate replacements from rows where the candidate
98
+ has the selected role (in any column) and, if a preferred proposal role is provided,
99
+ it must match. If no candidate meets the preferred criterion, the preference is relaxed.
 
100
  - Excludes any candidate that is among the selected players.
101
+ - Generates candidate combinations and selects up to three proposals ensuring that no candidate
102
+ appears in more than one proposal.
103
  """
104
  global df
105
  logging.debug("compute_exchange: Starting computation")
106
  selected = []
 
107
  for i, (r, p, pref) in enumerate([(role1, player1, pref1), (role2, player2, pref2), (role3, player3, pref3)], start=1):
108
  if r and p:
109
  xb90_val = get_xb90_value(r, p)
 
132
  r = sel["role"]
133
  pref = sel["pref"]
134
  logging.debug("Gathering candidates for selected role %s with preference %s", r, pref)
 
135
  if pref:
136
  candidates_df = df[
137
  (((df["role1"] == r) | (df["role2"] == r) | (df["role3"] == r))) &
 
141
  candidates = candidates_df[["player", "xb90"]].dropna().to_dict(orient="records")
142
  if not candidates:
143
  logging.debug("No candidates found matching preference %s; relaxing preference", pref)
 
144
  candidates_df = df[
145
  (((df["role1"] == r) | (df["role2"] == r) | (df["role3"] == r))) &
146
  (~df["player"].isin(selected_names))
 
152
  (~df["player"].isin(selected_names))
153
  ]
154
  candidates = candidates_df[["player", "xb90"]].dropna().to_dict(orient="records")
155
+ logging.debug("Candidates for role %s: %s", r, candidates)
156
  if not candidates:
157
  return f"No alternative candidates found for role '{r}' (excluding selected players)."
158
  candidate_lists.append(candidates)
 
206
  logging.debug("Exchange proposals computed successfully.")
207
  return output
208
 
209
+ # Build the Gradio Blocks interface with advanced custom CSS.
210
  with gr.Blocks(theme=gr.themes.Soft(), css="""
211
+ @import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap');
212
+ body, .gradio-container {
213
+ font-family: 'Montserrat', sans-serif;
214
+ }
215
+ .gradio-container {
216
+ background: linear-gradient(rgba(0,0,0,0.6), rgba(0,0,0,0.6)), url('https://source.unsplash.com/1600x900/?football') no-repeat center center fixed;
217
+ background-size: cover;
218
+ }
219
+ .gradio-interface {
220
+ background-color: rgba(255, 255, 255, 0.95) !important;
221
+ border-radius: 10px;
222
+ padding: 20px;
223
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
224
+ }
225
+ h2, h3, h4, p {
226
+ color: #FFD700;
227
+ text-shadow: 1px 1px 4px rgba(0,0,0,0.8);
228
+ }
229
+ .gr-button {
230
+ background-color: #006400 !important;
231
+ color: #FFF !important;
232
+ border: none !important;
233
+ border-radius: 5px !important;
234
+ padding: 10px 20px !important;
235
+ font-size: 1.1em !important;
236
+ cursor: pointer !important;
237
+ transition: background-color 0.3s ease !important;
238
+ }
239
+ .gr-button:hover {
240
+ background-color: #228B22 !important;
241
+ }
242
  @media (max-width: 600px) {
243
  .gradio-container { padding: 10px; }
244
  .gradio-interface { padding: 10px; }
245
  }
246
  """) as demo:
247
+ gr.Markdown("<h2 style='text-align:center;'>Fantastico Calcio Andria - il foglietto dell'uomo algoritmo</h2>")
248
+ gr.Markdown("<p style='text-align:center;'>Carica il file Excel con i dati dei giocatori. La prima riga deve contenere le intestazioni: 'Player', 'Role 1', 'Role 2', 'Role 3', 'xB90'.</p>")
249
 
250
+ file_input = gr.File(label="Carica file Excel (.xlsx)", file_types=[".xlsx"])
251
 
252
  with gr.Row():
253
  with gr.Column():
254
+ role1 = gr.Dropdown(label="Ruolo per Giocatore 1", choices=[], interactive=True)
255
+ player1 = gr.Dropdown(label="Giocatore 1", choices=[], interactive=True)
256
+ xb90_1 = gr.Textbox(label="xB90 per Giocatore 1", interactive=False)
257
+ pref1 = gr.Dropdown(label="Ruolo Preferito per Proposta (1)", choices=[], interactive=True)
258
  with gr.Column():
259
+ role2 = gr.Dropdown(label="Ruolo per Giocatore 2 (Opzionale)", choices=[], interactive=True)
260
+ player2 = gr.Dropdown(label="Giocatore 2 (Opzionale)", choices=[], interactive=True)
261
+ xb90_2 = gr.Textbox(label="xB90 per Giocatore 2", interactive=False)
262
+ pref2 = gr.Dropdown(label="Ruolo Preferito per Proposta (2)", choices=[], interactive=True)
263
  with gr.Column():
264
+ role3 = gr.Dropdown(label="Ruolo per Giocatore 3 (Opzionale)", choices=[], interactive=True)
265
+ player3 = gr.Dropdown(label="Giocatore 3 (Opzionale)", choices=[], interactive=True)
266
+ xb90_3 = gr.Textbox(label="xB90 per Giocatore 3", interactive=False)
267
+ pref3 = gr.Dropdown(label="Ruolo Preferito per Proposta (3)", choices=[], interactive=True)
268
 
 
269
  file_input.change(fn=load_excel, inputs=file_input, outputs=[role1, role2, role3, pref1, pref2, pref3])
 
 
270
  role1.change(fn=update_players, inputs=role1, outputs=player1)
271
  role2.change(fn=update_players, inputs=role2, outputs=player2)
272
  role3.change(fn=update_players, inputs=role3, outputs=player3)
 
 
273
  player1.change(fn=get_xb90_value, inputs=[role1, player1], outputs=xb90_1)
274
  player2.change(fn=get_xb90_value, inputs=[role2, player2], outputs=xb90_2)
275
  player3.change(fn=get_xb90_value, inputs=[role3, player3], outputs=xb90_3)
276
 
277
+ exchange_button = gr.Button("Calcola Proposte di Scambio")
278
+ output_box = gr.Textbox(label="Proposte di Scambio", lines=14)
279
 
280
  exchange_button.click(
281
  fn=compute_exchange,
 
283
  outputs=output_box,
284
  )
285
 
286
+ # Launch the app with debug enabled.
287
  demo.launch(debug=True)