Update app.py
Browse files
app.py
CHANGED
|
@@ -100,14 +100,13 @@ def positions_list():
|
|
| 100 |
return sorted(vals)
|
| 101 |
|
| 102 |
def nations_list():
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
vals = []
|
| 106 |
for c in pycountry.countries:
|
| 107 |
nm = c.name
|
| 108 |
if re.sub(r"\s+"," ", nm).upper() not in EXCLUDED_NATIONS:
|
| 109 |
-
|
| 110 |
-
return sorted(set(
|
| 111 |
|
| 112 |
def clubs_list():
|
| 113 |
if "Club" not in DF.columns: return []
|
|
@@ -144,7 +143,7 @@ def to_csv_bytes(df):
|
|
| 144 |
df.to_csv(buf, index=False, encoding="utf-8")
|
| 145 |
return buf.getvalue().encode("utf-8")
|
| 146 |
|
| 147 |
-
# === UI
|
| 148 |
THEME = gr.themes.Soft(primary_hue="blue")
|
| 149 |
CSS = """
|
| 150 |
#title { text-align:center; }
|
|
@@ -155,14 +154,14 @@ CSS = """
|
|
| 155 |
with gr.Blocks(theme=THEME, css=CSS) as demo:
|
| 156 |
gr.Markdown("<h1 id='title'>ProScout — Player Finder</h1>")
|
| 157 |
|
| 158 |
-
#
|
| 159 |
with gr.Row():
|
| 160 |
-
# Column 1:
|
| 161 |
with gr.Column(scale=1, elem_classes="card"):
|
| 162 |
pos = gr.CheckboxGroup(positions_list(), label="Positions", value=[], info="Pick one or more")
|
| 163 |
nat = gr.Dropdown(nations_list(), multiselect=True, label="Nations", value=[], filterable=True)
|
| 164 |
clu = gr.Dropdown(clubs_list(), multiselect=True, label="Clubs", value=[], filterable=True)
|
| 165 |
-
query = gr.Textbox(label="Search
|
| 166 |
|
| 167 |
# Column 2: ratings & age
|
| 168 |
with gr.Column(scale=1, elem_classes="card"):
|
|
@@ -170,9 +169,6 @@ with gr.Blocks(theme=THEME, css=CSS) as demo:
|
|
| 170 |
min_pot = gr.Slider(0, 99, value=0, step=1, label="Min Potential")
|
| 171 |
max_age = gr.Slider(15, 45, value=45, step=1, label="Max Age")
|
| 172 |
|
| 173 |
-
gr.Markdown("") # spacer
|
| 174 |
-
btn = gr.Button("Search", variant="primary")
|
| 175 |
-
|
| 176 |
# Column 3: physical & financial
|
| 177 |
with gr.Column(scale=1, elem_classes="card"):
|
| 178 |
min_h = gr.Slider(140, 210, value=140, step=1, label="Min Height (cm)")
|
|
@@ -182,7 +178,7 @@ with gr.Blocks(theme=THEME, css=CSS) as demo:
|
|
| 182 |
max_val = gr.Number(value=np.nan, label="Max Value (EUR)")
|
| 183 |
max_wage = gr.Number(value=np.nan, label="Max Wage (EUR)")
|
| 184 |
|
| 185 |
-
# Results panel
|
| 186 |
with gr.Column(scale=2, elem_classes="card"):
|
| 187 |
results = gr.Dataframe(row_count=(12,"dynamic"), wrap=True, interactive=False, label="Results")
|
| 188 |
with gr.Row():
|
|
@@ -191,6 +187,12 @@ with gr.Blocks(theme=THEME, css=CSS) as demo:
|
|
| 191 |
avg_age_box = gr.Markdown("", elem_classes="stat")
|
| 192 |
dl = gr.DownloadButton("Download CSV")
|
| 193 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
def _run(positions, nations, clubs, min_overall, min_potential,
|
| 195 |
max_age, min_h, max_h, min_w, max_w, max_val, max_wage, query):
|
| 196 |
df = filter_players(positions, nations, clubs, min_overall, min_potential,
|
|
@@ -201,7 +203,7 @@ with gr.Blocks(theme=THEME, css=CSS) as demo:
|
|
| 201 |
csv_bytes = to_csv_bytes(df)
|
| 202 |
return df, f"**Players:** {count}", f"**Avg OVR:** {avg_ovr}", f"**Avg Age:** {avg_age}", csv_bytes
|
| 203 |
|
| 204 |
-
#
|
| 205 |
demo.load(
|
| 206 |
_run,
|
| 207 |
inputs=[pos,nat,clu,min_ovr,min_pot,max_age,min_h,max_h,min_w,max_w,max_val,max_wage,query],
|
|
|
|
| 100 |
return sorted(vals)
|
| 101 |
|
| 102 |
def nations_list():
|
| 103 |
+
# Always list all countries (minus exclusions), not just those in the dataset
|
| 104 |
+
all_names = []
|
|
|
|
| 105 |
for c in pycountry.countries:
|
| 106 |
nm = c.name
|
| 107 |
if re.sub(r"\s+"," ", nm).upper() not in EXCLUDED_NATIONS:
|
| 108 |
+
all_names.append(nm)
|
| 109 |
+
return sorted(set(all_names))
|
| 110 |
|
| 111 |
def clubs_list():
|
| 112 |
if "Club" not in DF.columns: return []
|
|
|
|
| 143 |
df.to_csv(buf, index=False, encoding="utf-8")
|
| 144 |
return buf.getvalue().encode("utf-8")
|
| 145 |
|
| 146 |
+
# === UI ===
|
| 147 |
THEME = gr.themes.Soft(primary_hue="blue")
|
| 148 |
CSS = """
|
| 149 |
#title { text-align:center; }
|
|
|
|
| 154 |
with gr.Blocks(theme=THEME, css=CSS) as demo:
|
| 155 |
gr.Markdown("<h1 id='title'>ProScout — Player Finder</h1>")
|
| 156 |
|
| 157 |
+
# Filters in three columns, results wide on the right
|
| 158 |
with gr.Row():
|
| 159 |
+
# Column 1: positions + nations/clubs + free-text search at the end
|
| 160 |
with gr.Column(scale=1, elem_classes="card"):
|
| 161 |
pos = gr.CheckboxGroup(positions_list(), label="Positions", value=[], info="Pick one or more")
|
| 162 |
nat = gr.Dropdown(nations_list(), multiselect=True, label="Nations", value=[], filterable=True)
|
| 163 |
clu = gr.Dropdown(clubs_list(), multiselect=True, label="Clubs", value=[], filterable=True)
|
| 164 |
+
query = gr.Textbox(label="Search", placeholder="e.g., Maccabi, Brazil, CAM")
|
| 165 |
|
| 166 |
# Column 2: ratings & age
|
| 167 |
with gr.Column(scale=1, elem_classes="card"):
|
|
|
|
| 169 |
min_pot = gr.Slider(0, 99, value=0, step=1, label="Min Potential")
|
| 170 |
max_age = gr.Slider(15, 45, value=45, step=1, label="Max Age")
|
| 171 |
|
|
|
|
|
|
|
|
|
|
| 172 |
# Column 3: physical & financial
|
| 173 |
with gr.Column(scale=1, elem_classes="card"):
|
| 174 |
min_h = gr.Slider(140, 210, value=140, step=1, label="Min Height (cm)")
|
|
|
|
| 178 |
max_val = gr.Number(value=np.nan, label="Max Value (EUR)")
|
| 179 |
max_wage = gr.Number(value=np.nan, label="Max Wage (EUR)")
|
| 180 |
|
| 181 |
+
# Results panel (wide)
|
| 182 |
with gr.Column(scale=2, elem_classes="card"):
|
| 183 |
results = gr.Dataframe(row_count=(12,"dynamic"), wrap=True, interactive=False, label="Results")
|
| 184 |
with gr.Row():
|
|
|
|
| 187 |
avg_age_box = gr.Markdown("", elem_classes="stat")
|
| 188 |
dl = gr.DownloadButton("Download CSV")
|
| 189 |
|
| 190 |
+
# Button full-width under filters/results
|
| 191 |
+
with gr.Row():
|
| 192 |
+
gr.Markdown("") # left spacer
|
| 193 |
+
btn = gr.Button("Search", variant="primary")
|
| 194 |
+
gr.Markdown("") # right spacer
|
| 195 |
+
|
| 196 |
def _run(positions, nations, clubs, min_overall, min_potential,
|
| 197 |
max_age, min_h, max_h, min_w, max_w, max_val, max_wage, query):
|
| 198 |
df = filter_players(positions, nations, clubs, min_overall, min_potential,
|
|
|
|
| 203 |
csv_bytes = to_csv_bytes(df)
|
| 204 |
return df, f"**Players:** {count}", f"**Avg OVR:** {avg_ovr}", f"**Avg Age:** {avg_age}", csv_bytes
|
| 205 |
|
| 206 |
+
# Load initial data automatically
|
| 207 |
demo.load(
|
| 208 |
_run,
|
| 209 |
inputs=[pos,nat,clu,min_ovr,min_pot,max_age,min_h,max_h,min_w,max_w,max_val,max_wage,query],
|