Update app.py
Browse files
app.py
CHANGED
|
@@ -583,7 +583,7 @@ sequence_generators = {
|
|
| 583 |
"Flexibilidad": generate_flexibility_sequence,
|
| 584 |
}
|
| 585 |
|
| 586 |
-
# --- Data Handling (Unchanged) ---
|
| 587 |
def guardar_resultado(alias, level, scores, test_order):
|
| 588 |
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 589 |
avg = sum(scores.values()) / len(scores) if scores else 0.0
|
|
@@ -601,37 +601,102 @@ def guardar_resultado(alias, level, scores, test_order):
|
|
| 601 |
except Exception as e: print(f"ERROR inesperado al guardar resultado: {e}"); traceback.print_exc(); return False
|
| 602 |
|
| 603 |
def leer_historial_df():
|
| 604 |
-
results = []
|
| 605 |
-
if not os.path.isfile(ARCHIVO_RESULTADOS):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 606 |
with csv_lock:
|
| 607 |
try:
|
| 608 |
with open(ARCHIVO_RESULTADOS, 'r', newline='', encoding='utf-8') as f:
|
| 609 |
-
|
| 610 |
-
if not
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 611 |
for i, row in enumerate(reader):
|
| 612 |
try:
|
| 613 |
-
|
| 614 |
-
|
| 615 |
-
|
| 616 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 617 |
processed_rows.append(proc_row)
|
| 618 |
-
except
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 619 |
results = processed_rows
|
| 620 |
-
except FileNotFoundError:
|
| 621 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 622 |
if not results: return None
|
| 623 |
-
|
| 624 |
-
|
|
|
|
|
|
|
|
|
|
| 625 |
if PANDAS_AVAILABLE:
|
| 626 |
try:
|
| 627 |
-
df = pd.DataFrame(results)
|
| 628 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 629 |
if cols_to_rename: df_display = df_display.rename(columns=cols_to_rename)
|
|
|
|
|
|
|
| 630 |
if 'Lvl' in df_display.columns: df_display['Lvl'] = pd.to_numeric(df_display['Lvl'], errors='coerce').fillna(0).astype(int)
|
| 631 |
if 'Prec%' in df_display.columns: df_display['Prec%'] = pd.to_numeric(df_display['Prec%'], errors='coerce').fillna(0.0).round(1)
|
|
|
|
| 632 |
return df_display.head(25)
|
| 633 |
-
except Exception as e:
|
| 634 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 635 |
|
| 636 |
# --- Core Trial Logic ---
|
| 637 |
# --- Modified process_response (v8.2 - Inhibition logic) ---
|
|
|
|
| 583 |
"Flexibilidad": generate_flexibility_sequence,
|
| 584 |
}
|
| 585 |
|
| 586 |
+
# --- Data Handling (Unchanged structure, FIX SyntaxError) ---
|
| 587 |
def guardar_resultado(alias, level, scores, test_order):
|
| 588 |
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 589 |
avg = sum(scores.values()) / len(scores) if scores else 0.0
|
|
|
|
| 601 |
except Exception as e: print(f"ERROR inesperado al guardar resultado: {e}"); traceback.print_exc(); return False
|
| 602 |
|
| 603 |
def leer_historial_df():
|
| 604 |
+
results = []
|
| 605 |
+
if not os.path.isfile(ARCHIVO_RESULTADOS):
|
| 606 |
+
return None
|
| 607 |
+
|
| 608 |
+
expected_base_cols = ['Alias', 'Timestamp', 'Level', 'AvgPrec']
|
| 609 |
+
expected_test_cols = AVAILABLE_TESTS
|
| 610 |
+
processed_rows = []
|
| 611 |
+
|
| 612 |
with csv_lock:
|
| 613 |
try:
|
| 614 |
with open(ARCHIVO_RESULTADOS, 'r', newline='', encoding='utf-8') as f:
|
| 615 |
+
first_char = f.read(1)
|
| 616 |
+
if not first_char: return None # Empty file
|
| 617 |
+
f.seek(0)
|
| 618 |
+
reader = csv.DictReader(f)
|
| 619 |
+
# Tolerate missing/bad header or missing columns slightly more robustly
|
| 620 |
+
if not reader.fieldnames:
|
| 621 |
+
print("WARN: No header found in results CSV.")
|
| 622 |
+
# Attempt to read assuming standard order if needed, or just return None
|
| 623 |
+
return None # Simplest fallback
|
| 624 |
+
|
| 625 |
for i, row in enumerate(reader):
|
| 626 |
try:
|
| 627 |
+
# Basic data extraction with defaults
|
| 628 |
+
proc_row = {
|
| 629 |
+
'Alias': str(row.get('Alias', f'Fila_{i+1}_NA'))[:25],
|
| 630 |
+
'Timestamp': str(row.get('Timestamp', 'NA'))[:15],
|
| 631 |
+
'Level': 0, # Default
|
| 632 |
+
'AvgPrec': 0.0 # Default
|
| 633 |
+
}
|
| 634 |
+
# Safely parse Level and AvgPrec
|
| 635 |
+
try: proc_row['Level'] = int(float(row.get('Level', 0)))
|
| 636 |
+
except (ValueError, TypeError): pass # Keep default 0
|
| 637 |
+
try: proc_row['AvgPrec'] = float(row.get('AvgPrec', 0.0))
|
| 638 |
+
except (ValueError, TypeError): pass # Keep default 0.0
|
| 639 |
+
|
| 640 |
+
# Process test scores safely
|
| 641 |
+
for test in expected_test_cols:
|
| 642 |
+
raw_val = row.get(test) # Use .get() for safety if column missing
|
| 643 |
+
# --- START FIX for SyntaxError ---
|
| 644 |
+
try:
|
| 645 |
+
# Attempt conversion only if raw_val is not None
|
| 646 |
+
proc_row[test] = float(raw_val) if raw_val is not None else 0.0
|
| 647 |
+
except (ValueError, TypeError):
|
| 648 |
+
# If conversion fails or raw_val was None/invalid, assign 0.0
|
| 649 |
+
proc_row[test] = 0.0
|
| 650 |
+
# --- END FIX for SyntaxError ---
|
| 651 |
processed_rows.append(proc_row)
|
| 652 |
+
except KeyError as e:
|
| 653 |
+
# Log if a critical expected column is missing, but try to continue
|
| 654 |
+
print(f"WARN: Missing expected key {e} in CSV row {i+1}. Skipping row or using defaults.")
|
| 655 |
+
continue
|
| 656 |
+
except Exception as inner_e:
|
| 657 |
+
# Catch other unexpected errors processing a row
|
| 658 |
+
print(f"ERROR processing CSV row {i+1}: {inner_e}. Skipping row.")
|
| 659 |
+
traceback.print_exc()
|
| 660 |
+
continue # Skip malformed row
|
| 661 |
+
|
| 662 |
results = processed_rows
|
| 663 |
+
except FileNotFoundError:
|
| 664 |
+
return None
|
| 665 |
+
except Exception as e:
|
| 666 |
+
print(f"ERROR Crítico al leer historial CSV: {e}")
|
| 667 |
+
traceback.print_exc()
|
| 668 |
+
return None # Critical error reading the file
|
| 669 |
+
|
| 670 |
if not results: return None
|
| 671 |
+
|
| 672 |
+
try: # Sort best level/score first
|
| 673 |
+
results.sort(key=lambda x: (x.get('Level', 0), x.get('AvgPrec', 0.0)), reverse=True)
|
| 674 |
+
except Exception: pass # Ignore sorting errors if data is inconsistent
|
| 675 |
+
|
| 676 |
if PANDAS_AVAILABLE:
|
| 677 |
try:
|
| 678 |
+
df = pd.DataFrame(results)
|
| 679 |
+
# Ensure essential columns exist before proceeding
|
| 680 |
+
cols_to_display = ['Alias', 'Level', 'AvgPrec', 'Timestamp']
|
| 681 |
+
existing_cols = [col for col in cols_to_display if col in df.columns]
|
| 682 |
+
if not existing_cols: return results[:25] # Fallback if essential columns missing
|
| 683 |
+
|
| 684 |
+
df_display = df[existing_cols]
|
| 685 |
+
rename_map = {'Level': 'Lvl', 'AvgPrec': 'Prec%', 'Timestamp': 'Fecha'}
|
| 686 |
+
cols_to_rename = {k: v for k, v in rename_map.items() if k in df_display.columns}
|
| 687 |
if cols_to_rename: df_display = df_display.rename(columns=cols_to_rename)
|
| 688 |
+
|
| 689 |
+
# Safely convert types after renaming
|
| 690 |
if 'Lvl' in df_display.columns: df_display['Lvl'] = pd.to_numeric(df_display['Lvl'], errors='coerce').fillna(0).astype(int)
|
| 691 |
if 'Prec%' in df_display.columns: df_display['Prec%'] = pd.to_numeric(df_display['Prec%'], errors='coerce').fillna(0.0).round(1)
|
| 692 |
+
|
| 693 |
return df_display.head(25)
|
| 694 |
+
except Exception as e:
|
| 695 |
+
print(f"ERROR creando DataFrame con Pandas (usando lista básica): {e}")
|
| 696 |
+
traceback.print_exc()
|
| 697 |
+
return results[:25] # Fallback to list
|
| 698 |
+
else:
|
| 699 |
+
return results[:25] # Return raw list if pandas not available
|
| 700 |
|
| 701 |
# --- Core Trial Logic ---
|
| 702 |
# --- Modified process_response (v8.2 - Inhibition logic) ---
|