Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -370,6 +370,7 @@ def parse_zebris_pdf(uploaded_pdf):
|
|
| 370 |
data = {
|
| 371 |
"athlete_name": extract_name_from_filename(source_pdf),
|
| 372 |
"source_pdf": source_pdf,
|
|
|
|
| 373 |
"transition_g": np.nan,
|
| 374 |
"transition_d": np.nan,
|
| 375 |
"heel_force_g": np.nan,
|
|
@@ -406,6 +407,14 @@ def parse_zebris_pdf(uploaded_pdf):
|
|
| 406 |
|
| 407 |
full_text = " ".join(page_texts)
|
| 408 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 409 |
# fallback si nom non récupéré via fichier
|
| 410 |
if not data["athlete_name"]:
|
| 411 |
data["athlete_name"] = extract_pdf_name(full_text, source_pdf=source_pdf)
|
|
@@ -509,12 +518,12 @@ def estimate_attack_from_pdf(pdf_data: dict):
|
|
| 509 |
return "indéterminée"
|
| 510 |
|
| 511 |
|
| 512 |
-
def
|
| 513 |
target = normalize_name(athlete_name)
|
| 514 |
target_parts = set(target.split())
|
| 515 |
|
| 516 |
best_pdf = None
|
| 517 |
-
best_score =
|
| 518 |
|
| 519 |
for pdf in pdfs_data:
|
| 520 |
pdf_name = normalize_name(pdf.get("athlete_name"))
|
|
@@ -523,22 +532,30 @@ def match_pdf_to_athlete(pdfs_data, athlete_name):
|
|
| 523 |
if not pdf_name:
|
| 524 |
continue
|
| 525 |
|
| 526 |
-
#
|
| 527 |
-
|
| 528 |
-
return pdf
|
| 529 |
|
| 530 |
-
#
|
| 531 |
-
|
|
|
|
|
|
|
|
|
|
| 532 |
|
| 533 |
-
|
| 534 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 535 |
best_pdf = pdf
|
| 536 |
|
| 537 |
-
# on
|
| 538 |
-
if best_score >=
|
| 539 |
return best_pdf
|
| 540 |
|
| 541 |
-
# si un seul PDF
|
| 542 |
if len(pdfs_data) == 1:
|
| 543 |
return pdfs_data[0]
|
| 544 |
|
|
@@ -1271,8 +1288,6 @@ if uploaded_pdfs:
|
|
| 1271 |
all_athletes = sorted(df_std["Nom"].dropna().unique().tolist())
|
| 1272 |
selected_athlete = st.selectbox("Athlète", all_athletes)
|
| 1273 |
|
| 1274 |
-
matched_pdf = match_pdf_to_athlete(pdfs_data, selected_athlete)
|
| 1275 |
-
|
| 1276 |
sub_df = df_std[df_std["Nom"] == selected_athlete].copy()
|
| 1277 |
if sub_df.empty:
|
| 1278 |
st.error("Aucune donnée trouvée pour cet athlète.")
|
|
@@ -1286,6 +1301,9 @@ if len(sources) > 1:
|
|
| 1286 |
sub_df = sub_df.sort_values("Vitesse (km/h)")
|
| 1287 |
speeds = sub_df["Vitesse (km/h)"].dropna().tolist()
|
| 1288 |
selected_speed = st.selectbox("Allure analysée (km/h)", speeds)
|
|
|
|
|
|
|
|
|
|
| 1289 |
row = sub_df[sub_df["Vitesse (km/h)"] == selected_speed].iloc[0]
|
| 1290 |
|
| 1291 |
poids_csv = row["Poids (kg)"] if pd.notna(row["Poids (kg)"]) else np.nan
|
|
|
|
| 370 |
data = {
|
| 371 |
"athlete_name": extract_name_from_filename(source_pdf),
|
| 372 |
"source_pdf": source_pdf,
|
| 373 |
+
"speed_kmh": np.nan,
|
| 374 |
"transition_g": np.nan,
|
| 375 |
"transition_d": np.nan,
|
| 376 |
"heel_force_g": np.nan,
|
|
|
|
| 407 |
|
| 408 |
full_text = " ".join(page_texts)
|
| 409 |
|
| 410 |
+
# Extraction de l'allure du PDF (ex: "VMA 14kmh" ou "14,0 km/h")
|
| 411 |
+
speed_match = re.search(r"(\d+(?:[.,]\d+)?)\s*km\s*/?\s*h", full_text, flags=re.I)
|
| 412 |
+
if not speed_match:
|
| 413 |
+
speed_match = re.search(r"(\d+(?:[.,]\d+)?)\s*kmh", full_text, flags=re.I)
|
| 414 |
+
|
| 415 |
+
if speed_match:
|
| 416 |
+
data["speed_kmh"] = float(speed_match.group(1).replace(",", "."))
|
| 417 |
+
|
| 418 |
# fallback si nom non récupéré via fichier
|
| 419 |
if not data["athlete_name"]:
|
| 420 |
data["athlete_name"] = extract_pdf_name(full_text, source_pdf=source_pdf)
|
|
|
|
| 518 |
return "indéterminée"
|
| 519 |
|
| 520 |
|
| 521 |
+
def match_pdf_to_athlete_and_speed(pdfs_data, athlete_name, selected_speed, tolerance=0.3):
|
| 522 |
target = normalize_name(athlete_name)
|
| 523 |
target_parts = set(target.split())
|
| 524 |
|
| 525 |
best_pdf = None
|
| 526 |
+
best_score = -1
|
| 527 |
|
| 528 |
for pdf in pdfs_data:
|
| 529 |
pdf_name = normalize_name(pdf.get("athlete_name"))
|
|
|
|
| 532 |
if not pdf_name:
|
| 533 |
continue
|
| 534 |
|
| 535 |
+
# score nom
|
| 536 |
+
name_score = len(target_parts.intersection(pdf_parts))
|
|
|
|
| 537 |
|
| 538 |
+
# bonus si allure du PDF = allure sélectionnée
|
| 539 |
+
pdf_speed = pdf.get("speed_kmh")
|
| 540 |
+
speed_score = 0
|
| 541 |
+
if pd.notna(pdf_speed) and abs(float(pdf_speed) - float(selected_speed)) <= tolerance:
|
| 542 |
+
speed_score = 10
|
| 543 |
|
| 544 |
+
total_score = name_score + speed_score
|
| 545 |
+
|
| 546 |
+
# priorité absolue si nom exact + bonne allure
|
| 547 |
+
if pdf_name == target and speed_score == 10:
|
| 548 |
+
return pdf
|
| 549 |
+
|
| 550 |
+
if total_score > best_score:
|
| 551 |
+
best_score = total_score
|
| 552 |
best_pdf = pdf
|
| 553 |
|
| 554 |
+
# on accepte si on a au moins un vrai match de nom
|
| 555 |
+
if best_score >= 1:
|
| 556 |
return best_pdf
|
| 557 |
|
| 558 |
+
# fallback seulement si un seul PDF
|
| 559 |
if len(pdfs_data) == 1:
|
| 560 |
return pdfs_data[0]
|
| 561 |
|
|
|
|
| 1288 |
all_athletes = sorted(df_std["Nom"].dropna().unique().tolist())
|
| 1289 |
selected_athlete = st.selectbox("Athlète", all_athletes)
|
| 1290 |
|
|
|
|
|
|
|
| 1291 |
sub_df = df_std[df_std["Nom"] == selected_athlete].copy()
|
| 1292 |
if sub_df.empty:
|
| 1293 |
st.error("Aucune donnée trouvée pour cet athlète.")
|
|
|
|
| 1301 |
sub_df = sub_df.sort_values("Vitesse (km/h)")
|
| 1302 |
speeds = sub_df["Vitesse (km/h)"].dropna().tolist()
|
| 1303 |
selected_speed = st.selectbox("Allure analysée (km/h)", speeds)
|
| 1304 |
+
|
| 1305 |
+
matched_pdf = match_pdf_to_athlete_and_speed(pdfs_data, selected_athlete, selected_speed)
|
| 1306 |
+
|
| 1307 |
row = sub_df[sub_df["Vitesse (km/h)"] == selected_speed].iloc[0]
|
| 1308 |
|
| 1309 |
poids_csv = row["Poids (kg)"] if pd.notna(row["Poids (kg)"]) else np.nan
|