aimodelshare 0.3.94__py3-none-any.whl → 0.4.71__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -404,7 +404,7 @@ def _build_attempts_tracker_html(current_count, limit=10):
404
404
  border_color = "#bae6fd"
405
405
  text_color = "#0369a1"
406
406
  icon = "🛑"
407
- label = f"Última oportunitat (de moment) per pujar la teva puntuació!: {current_count}/{limit}"
407
+ label = f"Última oportunitat (per ara) per pujar la teva puntuació!: {current_count}/{limit}"
408
408
  else:
409
409
  # Normal - blue styling
410
410
  bg_color = "#f0f9ff"
@@ -784,7 +784,7 @@ def _background_initializer():
784
784
  INIT_FLAGS["competition"] = True
785
785
  except Exception as e:
786
786
  with INIT_LOCK:
787
- INIT_FLAGS["errors"].append(f"Competition connection failed: {str(e)}")
787
+ INIT_FLAGS["errors"].append(f"La connexió amb la competició ha fallat: {str(e)}")
788
788
 
789
789
  try:
790
790
  # Step 2: Load dataset core (train/test split)
@@ -793,7 +793,7 @@ def _background_initializer():
793
793
  INIT_FLAGS["dataset_core"] = True
794
794
  except Exception as e:
795
795
  with INIT_LOCK:
796
- INIT_FLAGS["errors"].append(f"Dataset loading failed: {str(e)}")
796
+ INIT_FLAGS["errors"].append(f"La càrrega del conjunt de dades ha fallat: {str(e)}")
797
797
  return # Cannot proceed without data
798
798
 
799
799
  try:
@@ -803,7 +803,7 @@ def _background_initializer():
803
803
  INIT_FLAGS["warm_mini"] = True
804
804
  except Exception as e:
805
805
  with INIT_LOCK:
806
- INIT_FLAGS["errors"].append(f"Warm mini dataset failed: {str(e)}")
806
+ INIT_FLAGS["errors"].append(f"El dataset mini de preescalfament ha fallat: {str(e)}")
807
807
 
808
808
  # Progressive sampling - samples are already created in load_and_prep_data
809
809
  # Just mark them as ready sequentially with delays to simulate progressive loading
@@ -815,7 +815,7 @@ def _background_initializer():
815
815
  INIT_FLAGS["pre_samples_small"] = True
816
816
  except Exception as e:
817
817
  with INIT_LOCK:
818
- INIT_FLAGS["errors"].append(f"Small sample failed: {str(e)}")
818
+ INIT_FLAGS["errors"].append(f"La mostra petita ha fallat: {str(e)}")
819
819
 
820
820
  try:
821
821
  # Step 4b: Medium sample (60%)
@@ -824,7 +824,7 @@ def _background_initializer():
824
824
  INIT_FLAGS["pre_samples_medium"] = True
825
825
  except Exception as e:
826
826
  with INIT_LOCK:
827
- INIT_FLAGS["errors"].append(f"Medium sample failed: {str(e)}")
827
+ INIT_FLAGS["errors"].append(f"La mostra mitjana ha fallat: {str(e)}")
828
828
 
829
829
  try:
830
830
  # Step 4c: Large sample (80%)
@@ -833,7 +833,7 @@ def _background_initializer():
833
833
  INIT_FLAGS["pre_samples_large"] = True
834
834
  except Exception as e:
835
835
  with INIT_LOCK:
836
- INIT_FLAGS["errors"].append(f"Large sample failed: {str(e)}")
836
+ INIT_FLAGS["errors"].append(f"La mostra gran ha fallat: {str(e)}")
837
837
  print(f"✗ Large sample failed: {e}")
838
838
 
839
839
  try:
@@ -844,7 +844,7 @@ def _background_initializer():
844
844
  INIT_FLAGS["pre_samples_full"] = True
845
845
  except Exception as e:
846
846
  with INIT_LOCK:
847
- INIT_FLAGS["errors"].append(f"Full sample failed: {str(e)}")
847
+ INIT_FLAGS["errors"].append(f"La mostra completa ha fallat: {str(e)}")
848
848
 
849
849
  try:
850
850
  # Step 5: Leaderboard prefetch (best-effort, unauthenticated)
@@ -856,7 +856,7 @@ def _background_initializer():
856
856
  INIT_FLAGS["leaderboard"] = True
857
857
  except Exception as e:
858
858
  with INIT_LOCK:
859
- INIT_FLAGS["errors"].append(f"Leaderboard prefetch failed: {str(e)}")
859
+ INIT_FLAGS["errors"].append(f"La pre-obtenció de la classificació ha fallat: {str(e)}")
860
860
 
861
861
  try:
862
862
  # Step 6: Default preprocessor on small sample
@@ -865,7 +865,7 @@ def _background_initializer():
865
865
  INIT_FLAGS["default_preprocessor"] = True
866
866
  except Exception as e:
867
867
  with INIT_LOCK:
868
- INIT_FLAGS["errors"].append(f"Default preprocessor failed: {str(e)}")
868
+ INIT_FLAGS["errors"].append(f"El preprocessador per defecte ha fallat: {str(e)}")
869
869
  print(f"✗ Default preprocessor failed: {e}")
870
870
 
871
871
 
@@ -1291,7 +1291,7 @@ def _build_kpi_card_html(new_score, last_score, new_rank, last_rank, submission_
1291
1291
 
1292
1292
  # Handle pending state - show processing message with provisional diff
1293
1293
  if is_pending:
1294
- title = "⏳ Submission Processing"
1294
+ title = "⏳ Processant l'enviament"
1295
1295
  acc_color = "#3b82f6" # Blue
1296
1296
  acc_text = f"{(local_test_accuracy * 100):.2f}%" if local_test_accuracy is not None else "N/A"
1297
1297
 
@@ -1299,60 +1299,60 @@ def _build_kpi_card_html(new_score, last_score, new_rank, last_rank, submission_
1299
1299
  if local_test_accuracy is not None and last_score is not None and last_score > 0:
1300
1300
  score_diff = local_test_accuracy - last_score
1301
1301
  if abs(score_diff) < 0.0001:
1302
- acc_diff_html = "<p style='font-size: 1.5rem; font-weight: 600; color: #6b7280; margin:0;'>No Change (↔) <span style='font-size: 0.9rem; color: #9ca3af;'>(Provisional)</span></p><p style='font-size: 1.2rem; font-weight: 500; color: #6b7280; margin:0; padding-top: 8px;'>Pending leaderboard update...</p>"
1302
+ acc_diff_html = "<p style='font-size: 1.5rem; font-weight: 600; color: #6b7280; margin:0;'>Sense canvis (↔) <span style='font-size: 0.9rem; color: #9ca3af;'>(Provisional)</span></p><p style='font-size: 1.2rem; font-weight: 500; color: #6b7280; margin:0; padding-top: 8px;'>Actualització de la classificació pendent...</p>"
1303
1303
  elif score_diff > 0:
1304
- acc_diff_html = f"<p style='font-size: 1.5rem; font-weight: 600; color: #16a34a; margin:0;'>+{(score_diff * 100):.2f} (⬆️) <span style='font-size: 0.9rem; color: #9ca3af;'>(Provisional)</span></p><p style='font-size: 1.2rem; font-weight: 500; color: #6b7280; margin:0; padding-top: 8px;'>Pending leaderboard update...</p>"
1304
+ acc_diff_html = f"<p style='font-size: 1.5rem; font-weight: 600; color: #16a34a; margin:0;'>+{(score_diff * 100):.2f} (⬆️) <span style='font-size: 0.9rem; color: #9ca3af;'>(Provisional)</span></p><p style='font-size: 1.2rem; font-weight: 500; color: #6b7280; margin:0; padding-top: 8px;'>Actualització de la classificació pendent...</p>"
1305
1305
  else:
1306
- acc_diff_html = f"<p style='font-size: 1.5rem; font-weight: 600; color: #ef4444; margin:0;'>{(score_diff * 100):.2f} (⬇️) <span style='font-size: 0.9rem; color: #9ca3af;'>(Provisional)</span></p><p style='font-size: 1.2rem; font-weight: 500; color: #6b7280; margin:0; padding-top: 8px;'>Pending leaderboard update...</p>"
1306
+ acc_diff_html = f"<p style='font-size: 1.5rem; font-weight: 600; color: #ef4444; margin:0;'>{(score_diff * 100):.2f} (⬇️) <span style='font-size: 0.9rem; color: #9ca3af;'>(Provisional)</span></p><p style='font-size: 1.2rem; font-weight: 500; color: #6b7280; margin:0; padding-top: 8px;'>Actualització de la classificació pendent...</p>"
1307
1307
  else:
1308
1308
  # No last score available - just show pending message
1309
1309
  acc_diff_html = "<p style='font-size: 1.2rem; font-weight: 500; color: #6b7280; margin:0; padding-top: 8px;'>Pending leaderboard update...</p>"
1310
1310
 
1311
1311
  border_color = acc_color
1312
1312
  rank_color = "#6b7280" # Gray
1313
- rank_text = "Pending"
1314
- rank_diff_html = "<p style='font-size: 1.2rem; font-weight: 500; color: #6b7280; margin:0;'>Calculating rank...</p>"
1313
+ rank_text = "Pendent"
1314
+ rank_diff_html = "<p style='font-size: 1.2rem; font-weight: 500; color: #6b7280; margin:0;'>Calculant la posició...</p>"
1315
1315
 
1316
1316
  # Handle preview mode - Styled to match "success" card
1317
1317
  elif is_preview:
1318
- title = "🔬 Successful Preview Run!"
1318
+ title = "🔬 Prova de vista prèvia finalitzada!"
1319
1319
  acc_color = "#16a34a" # Green (like success)
1320
1320
  acc_text = f"{(new_score * 100):.2f}%" if new_score > 0 else "N/A"
1321
- acc_diff_html = "<p style='font-size: 1.2rem; font-weight: 500; color: #6b7280; margin:0; padding-top: 8px;'>(Preview only - not submitted)</p>" # Neutral color
1321
+ acc_diff_html = "<p style='font-size: 1.2rem; font-weight: 500; color: #6b7280; margin:0; padding-top: 8px;'>(Només vista prèvia - no s'ha enviat)</p>" # Neutral color
1322
1322
  border_color = acc_color # Green border
1323
1323
  rank_color = "#3b82f6" # Blue (like rank)
1324
1324
  rank_text = "N/A" # Placeholder
1325
- rank_diff_html = "<p style='font-size: 1.2rem; font-weight: 500; color: #6b7280; margin:0;'>Not ranked (preview)</p>" # Neutral color
1325
+ rank_diff_html = "<p style='font-size: 1.2rem; font-weight: 500; color: #6b7280; margin:0;'>Sense posició (vista prèvia)</p>" # Neutral color
1326
1326
 
1327
1327
  # 1. Handle First Submission
1328
1328
  elif submission_count == 0:
1329
- title = "🎉 First Model Submitted!"
1329
+ title = "🎉 Primer model enviat!"
1330
1330
  acc_color = "#16a34a" # green
1331
1331
  acc_text = f"{(new_score * 100):.2f}%"
1332
- acc_diff_html = "<p style='font-size: 1.2rem; font-weight: 500; color: #6b7280; margin:0; padding-top: 8px;'>(Your first score!)</p>"
1332
+ acc_diff_html = "<p style='font-size: 1.2rem; font-weight: 500; color: #6b7280; margin:0; padding-top: 8px;'>(La teva primera puntuació!)</p>"
1333
1333
 
1334
1334
  rank_color = "#3b82f6" # blue
1335
1335
  rank_text = f"#{new_rank}"
1336
- rank_diff_html = "<p style='font-size: 1.5rem; font-weight: 600; color: #3b82f6; margin:0;'>You're on the board!</p>"
1336
+ rank_diff_html = "<p style='font-size: 1.5rem; font-weight: 600; color: #3b82f6; margin:0;'>¡Ja ets a la taula!</p>"
1337
1337
  border_color = acc_color
1338
1338
 
1339
1339
  else:
1340
1340
  # 2. Handle Score Changes
1341
1341
  score_diff = new_score - last_score
1342
1342
  if abs(score_diff) < 0.0001:
1343
- title = "✅ Submission Successful"
1343
+ title = "✅ Enviament completat!"
1344
1344
  acc_color = "#6b7280" # gray
1345
1345
  acc_text = f"{(new_score * 100):.2f}%"
1346
- acc_diff_html = f"<p style='font-size: 1.5rem; font-weight: 600; color: {acc_color}; margin:0;'>No Change (↔)</p>"
1346
+ acc_diff_html = f"<p style='font-size: 1.5rem; font-weight: 600; color: {acc_color}; margin:0;'>Sense canvis (↔)</p>"
1347
1347
  border_color = acc_color
1348
1348
  elif score_diff > 0:
1349
- title = "✅ Submission Successful!"
1349
+ title = "✅ Enviament completat!"
1350
1350
  acc_color = "#16a34a" # green
1351
1351
  acc_text = f"{(new_score * 100):.2f}%"
1352
1352
  acc_diff_html = f"<p style='font-size: 1.5rem; font-weight: 600; color: {acc_color}; margin:0;'>+{(score_diff * 100):.2f} (⬆️)</p>"
1353
1353
  border_color = acc_color
1354
1354
  else:
1355
- title = "📉 Score Dropped"
1355
+ title = "📉 La puntuació ha baixat"
1356
1356
  acc_color = "#ef4444" # red
1357
1357
  acc_text = f"{(new_score * 100):.2f}%"
1358
1358
  acc_diff_html = f"<p style='font-size: 1.5rem; font-weight: 600; color: {acc_color}; margin:0;'>{(score_diff * 100):.2f} (⬇️)</p>"
@@ -1363,25 +1363,25 @@ def _build_kpi_card_html(new_score, last_score, new_rank, last_rank, submission_
1363
1363
  rank_color = "#3b82f6" # blue
1364
1364
  rank_text = f"#{new_rank}"
1365
1365
  if last_rank == 0: # Handle first rank
1366
- rank_diff_html = "<p style='font-size: 1.5rem; font-weight: 600; color: #3b82f6; margin:0;'>You're on the board!</p>"
1366
+ rank_diff_html = "<p style='font-size: 1.5rem; font-weight: 600; color: #3b82f6; margin:0;'>¡Ja ets a la taula!</p>"
1367
1367
  elif rank_diff > 0:
1368
- rank_diff_html = f"<p style='font-size: 1.5rem; font-weight: 600; color: #16a34a; margin:0;'>🚀 Moved up {rank_diff} spot{'s' if rank_diff > 1 else ''}!</p>"
1368
+ rank_diff_html = f"<p style='font-size: 1.5rem; font-weight: 600; color: #16a34a; margin:0;'>🚀 ¡Has pujat {rank_diff} posició/ons!</p>"
1369
1369
  elif rank_diff < 0:
1370
- rank_diff_html = f"<p style='font-size: 1.5rem; font-weight: 600; color: #ef4444; margin:0;'>🔻 Dropped {abs(rank_diff)} spot{'s' if abs(rank_diff) > 1 else ''}</p>"
1370
+ rank_diff_html = f"<p style='font-size: 1.5rem; font-weight: 600; color: #ef4444; margin:0;'>🔻 Has baixat {abs(rank_diff)} posició/ons!</p>"
1371
1371
  else:
1372
- rank_diff_html = f"<p style='font-size: 1.5rem; font-weight: 600; color: {rank_color}; margin:0;'>No Change (↔)</p>"
1372
+ rank_diff_html = f"<p style='font-size: 1.5rem; font-weight: 600; color: {rank_color}; margin:0;'>Mantens la teva posició (↔)</p>"
1373
1373
 
1374
1374
  return f"""
1375
1375
  <div class='kpi-card' style='border-color: {border_color};'>
1376
1376
  <h2 style='color: #111827; margin-top:0;'>{title}</h2>
1377
1377
  <div class='kpi-card-body'>
1378
1378
  <div class='kpi-metric-box'>
1379
- <p class='kpi-label'>New Accuracy</p>
1379
+ <p class='kpi-label'>Nova precisió</p>
1380
1380
  <p class='kpi-score' style='color: {acc_color};'>{acc_text}</p>
1381
1381
  {acc_diff_html}
1382
1382
  </div>
1383
1383
  <div class='kpi-metric-box'>
1384
- <p class='kpi-label'>Your Rank</p>
1384
+ <p class='kpi-label'>La teva posició</p>
1385
1385
  <p class='kpi-score' style='color: {rank_color};'>{rank_text}</p>
1386
1386
  {rank_diff_html}
1387
1387
  </div>
@@ -1400,7 +1400,7 @@ def _build_team_html(team_summary_df, team_name):
1400
1400
  use the unmodified English team names from the DataFrame.
1401
1401
  """
1402
1402
  if team_summary_df is None or team_summary_df.empty:
1403
- return "<p style='text-align:center; color:#6b7280; padding-top:20px;'>No team submissions yet.</p>"
1403
+ return "<p style='text-align:center; color:#6b7280; padding-top:20px;'>Encara no hi ha enviaments per equips.</p>"
1404
1404
 
1405
1405
  # Normalize the current user's team name for comparison (using English names)
1406
1406
  normalized_user_team = _normalize_team_name(team_name).lower()
@@ -1409,11 +1409,11 @@ def _build_team_html(team_summary_df, team_name):
1409
1409
  <table class='leaderboard-html-table'>
1410
1410
  <thead>
1411
1411
  <tr>
1412
- <th>Rank</th>
1413
- <th>Team</th>
1414
- <th>Best_Score</th>
1415
- <th>Avg_Score</th>
1416
- <th>Submissions</th>
1412
+ <th>Posició</th>
1413
+ <th>Equip</th>
1414
+ <th>Millor Puntuació</th>
1415
+ <th>Mitjana</th>
1416
+ <th>Enviaments</th>
1417
1417
  </tr>
1418
1418
  </thead>
1419
1419
  <tbody>
@@ -1445,16 +1445,16 @@ def _build_team_html(team_summary_df, team_name):
1445
1445
  def _build_individual_html(individual_summary_df, username):
1446
1446
  """Generates the HTML for the individual leaderboard."""
1447
1447
  if individual_summary_df is None or individual_summary_df.empty:
1448
- return "<p style='text-align:center; color:#6b7280; padding-top:20px;'>No individual submissions yet.</p>"
1448
+ return "<p style='text-align:center; color:#6b7280; padding-top:20px;'>Encara no hi ha enviaments individuals.</p>"
1449
1449
 
1450
1450
  header = """
1451
1451
  <table class='leaderboard-html-table'>
1452
1452
  <thead>
1453
1453
  <tr>
1454
- <th>Rank</th>
1455
- <th>Engineer</th>
1456
- <th>Best_Score</th>
1457
- <th>Submissions</th>
1454
+ <th>Posició</th>
1455
+ <th>Enginyer/a</th>
1456
+ <th>Millor Puntuació</th>
1457
+ <th>Enviaments</th>
1458
1458
  </tr>
1459
1459
  </thead>
1460
1460
  <tbody>
@@ -1496,8 +1496,8 @@ def generate_competitive_summary(leaderboard_df, team_name, username, last_submi
1496
1496
 
1497
1497
  if leaderboard_df is None or leaderboard_df.empty or "accuracy" not in leaderboard_df.columns:
1498
1498
  return (
1499
- "<p style='text-align:center; color:#6b7280; padding-top:20px;'>Leaderboard empty.</p>",
1500
- "<p style='text-align:center; color:#6b7280; padding-top:20px;'>Leaderboard empty.</p>",
1499
+ "<p style='text-align:center; color:#6b7280; padding-top:20px;'>La classificació està buida.</p>",
1500
+ "<p style='text-align:center; color:#6b7280; padding-top:20px;'>La classificació està buida.</p>",
1501
1501
  _build_kpi_card_html(0, 0, 0, 0, 0, is_preview=False, is_pending=False, local_test_accuracy=None),
1502
1502
  0.0, 0, 0.0
1503
1503
  )
@@ -1867,9 +1867,9 @@ def perform_inline_login(username_input, password_input):
1867
1867
 
1868
1868
  # Build success message based on whether team is new or existing
1869
1869
  if is_new_team:
1870
- team_message = f"You have been assigned to a new team: <b>{display_team_name}</b> 🎉"
1870
+ team_message = f"T'hem assignat a un nou equip: <b>{display_team_name}</b> 🎉"
1871
1871
  else:
1872
- team_message = f"Welcome back! You remain on team: <b>{display_team_name}</b> ✅"
1872
+ team_message = f"Hola de nou! Continues a l'equip: <b>{display_team_name}</b> ✅"
1873
1873
 
1874
1874
  # Success: hide login form, show success message with team info, enable submit button
1875
1875
  success_html = f"""
@@ -2010,11 +2010,11 @@ def run_experiment(
2010
2010
  """
2011
2011
 
2012
2012
  # --- Stage 1: Lock UI and give initial feedback ---
2013
- progress(0.1, desc="Starting Experiment...")
2013
+ progress(0.1, desc="Iniciant l'experiment...")
2014
2014
  initial_updates = {
2015
- submit_button: gr.update(value="⏳ Experiment Running...", interactive=False),
2016
- submission_feedback_display: gr.update(value=get_status_html(1, "Initializing", "Preparing your data ingredients..."), visible=True),
2017
- login_error: gr.update(visible=False),
2015
+ submit_button: gr.update(value="⏳ Experiment en curs...", interactive=False),
2016
+ submission_feedback_display: gr.update(value=get_status_html(1, "Iniciant", "Preparant les variables de dades..."), visible=True), # Make sure it's visible
2017
+ login_error: gr.update(visible=False), # Hide login success/error message
2018
2018
  attempts_tracker_display: gr.update(value=_build_attempts_tracker_html(submission_count))
2019
2019
  }
2020
2020
  yield initial_updates
@@ -2028,10 +2028,155 @@ def run_experiment(
2028
2028
  log_output = f"▶ New Experiment\nModel: {model_name_key}\n..."
2029
2029
 
2030
2030
  # Check readiness
2031
- if playground is None or not ready:
2032
- # ... (Error handling code remains the same) ...
2033
- # (For brevity, I'm assuming you keep the existing error handling block here)
2034
- pass
2031
+ with INIT_LOCK:
2032
+ flags = INIT_FLAGS.copy()
2033
+
2034
+ # Normalize variable name for consistency
2035
+ ready_for_submission = ready
2036
+
2037
+ # If not ready but warm mini available, run preview
2038
+ if not ready_for_submission and flags["warm_mini"] and X_TRAIN_WARM is not None:
2039
+ _log("Running warm mini preview (not ready yet)")
2040
+ progress(0.5, desc="Executant la vista prèvia...")
2041
+ yield {
2042
+ submission_feedback_display: gr.update(value=get_status_html("Vista prèvia", "Prova d'escalfament", "Provant amb un conjunt de dades reduït..."), visible=True),
2043
+ login_error: gr.update(visible=False)
2044
+ }
2045
+
2046
+ try:
2047
+ # Run preview on warm mini dataset
2048
+ numeric_cols = [f for f in feature_set if f in ALL_NUMERIC_COLS]
2049
+ categorical_cols = [f for f in feature_set if f in ALL_CATEGORICAL_COLS]
2050
+
2051
+ if not numeric_cols and not categorical_cols:
2052
+ raise ValueError("No features selected for modeling.")
2053
+
2054
+ # Quick preprocessing and training on warm mini (uses memoized preprocessor)
2055
+ preprocessor, selected_cols = build_preprocessor(numeric_cols, categorical_cols)
2056
+
2057
+ X_warm_processed = preprocessor.fit_transform(X_TRAIN_WARM[selected_cols])
2058
+ X_test_processed = preprocessor.transform(X_TEST_RAW[selected_cols])
2059
+
2060
+ base_model = MODEL_TYPES[model_name_key]["model_builder"]()
2061
+ tuned_model = tune_model_complexity(base_model, complexity_level)
2062
+
2063
+ # Handle sparse arrays for models that require dense input
2064
+ if isinstance(tuned_model, (DecisionTreeClassifier, RandomForestClassifier)):
2065
+ X_warm_for_fit = _ensure_dense(X_warm_processed)
2066
+ X_test_for_predict = _ensure_dense(X_test_processed)
2067
+ else:
2068
+ X_warm_for_fit = X_warm_processed
2069
+ X_test_for_predict = X_test_processed
2070
+
2071
+ tuned_model.fit(X_warm_for_fit, Y_TRAIN_WARM)
2072
+
2073
+ # Get preview score
2074
+ from sklearn.metrics import accuracy_score
2075
+ predictions = tuned_model.predict(X_test_for_predict)
2076
+ preview_score = accuracy_score(Y_TEST, predictions)
2077
+
2078
+ # Update metadata state
2079
+ new_kpi_meta = {
2080
+ "was_preview": True,
2081
+ "preview_score": preview_score,
2082
+ "ready_at_run_start": False,
2083
+ "poll_iterations": 0,
2084
+ "local_test_accuracy": preview_score,
2085
+ "this_submission_score": None,
2086
+ "new_best_accuracy": None,
2087
+ "rank": None
2088
+ }
2089
+
2090
+ # Show preview card
2091
+ preview_html = _build_kpi_card_html(
2092
+ preview_score, 0, 0, 0, -1,
2093
+ is_preview=True, is_pending=False, local_test_accuracy=None
2094
+ )
2095
+
2096
+ settings = compute_rank_settings(
2097
+ submission_count, model_name_key, complexity_level, feature_set, data_size_str
2098
+ )
2099
+
2100
+ final_updates = {
2101
+ submission_feedback_display: gr.update(value=preview_html, visible=True),
2102
+ team_leaderboard_display: _build_skeleton_leaderboard(rows=6, is_team=True),
2103
+ individual_leaderboard_display: _build_skeleton_leaderboard(rows=6, is_team=False),
2104
+ last_submission_score_state: last_submission_score,
2105
+ last_rank_state: last_rank,
2106
+ best_score_state: best_score,
2107
+ submission_count_state: submission_count,
2108
+ first_submission_score_state: first_submission_score,
2109
+ rank_message_display: settings["rank_message"],
2110
+ model_type_radio: gr.update(choices=settings["model_choices"], value=settings["model_value"], interactive=settings["model_interactive"]),
2111
+ complexity_slider: gr.update(minimum=1, maximum=settings["complexity_max"], value=settings["complexity_value"]),
2112
+ feature_set_checkbox: gr.update(choices=settings["feature_set_choices"], value=settings["feature_set_value"], interactive=settings["feature_set_interactive"]),
2113
+ data_size_radio: gr.update(choices=settings["data_size_choices"], value=settings["data_size_value"], interactive=settings["data_size_interactive"]),
2114
+ submit_button: gr.update(value="🔬 Build & Submit Model", interactive=True),
2115
+ login_username: gr.update(visible=False),
2116
+ login_password: gr.update(visible=False),
2117
+ login_submit: gr.update(visible=False),
2118
+ login_error: gr.update(visible=False),
2119
+ attempts_tracker_display: gr.update(value=_build_attempts_tracker_html(submission_count)),
2120
+ was_preview_state: True,
2121
+ kpi_meta_state: new_kpi_meta,
2122
+ last_seen_ts_state: None # No timestamp for preview
2123
+ }
2124
+ yield final_updates
2125
+ return
2126
+
2127
+ except Exception as e:
2128
+ _log(f"Preview failed: {e}")
2129
+ # Fall through to error handling
2130
+
2131
+ if playground is None or not ready_for_submission:
2132
+ settings = compute_rank_settings(
2133
+ submission_count, model_name_key, complexity_level, feature_set, data_size_str
2134
+ )
2135
+
2136
+ error_msg = "<p style='text-align:center; color:red; padding:20px 0;'>"
2137
+ if playground is None:
2138
+ error_msg += "Playground not connected. Please try again later."
2139
+ else:
2140
+ error_msg += "Data still initializing. Please wait a moment and try again."
2141
+ error_msg += "</p>"
2142
+
2143
+ error_kpi_meta = {
2144
+ "was_preview": False,
2145
+ "preview_score": None,
2146
+ "ready_at_run_start": False,
2147
+ "poll_iterations": 0,
2148
+ "local_test_accuracy": None,
2149
+ "this_submission_score": None,
2150
+ "new_best_accuracy": None,
2151
+ "rank": None
2152
+ }
2153
+
2154
+ error_updates = {
2155
+ submission_feedback_display: gr.update(value=error_msg, visible=True),
2156
+ submit_button: gr.update(value="🔬 Build & Submit Model", interactive=True),
2157
+ team_leaderboard_display: _build_skeleton_leaderboard(rows=6, is_team=True),
2158
+ individual_leaderboard_display: _build_skeleton_leaderboard(rows=6, is_team=False),
2159
+ last_submission_score_state: last_submission_score,
2160
+ last_rank_state: last_rank,
2161
+ best_score_state: best_score,
2162
+ submission_count_state: submission_count,
2163
+ first_submission_score_state: first_submission_score,
2164
+ rank_message_display: settings["rank_message"],
2165
+ model_type_radio: gr.update(choices=settings["model_choices"], value=settings["model_value"], interactive=settings["model_interactive"]),
2166
+ complexity_slider: gr.update(minimum=1, maximum=settings["complexity_max"], value=settings["complexity_value"]),
2167
+ feature_set_checkbox: gr.update(choices=settings["feature_set_choices"], value=settings["feature_set_value"], interactive=settings["feature_set_interactive"]),
2168
+ data_size_radio: gr.update(choices=settings["data_size_choices"], value=settings["data_size_value"], interactive=settings["data_size_interactive"]),
2169
+ login_username: gr.update(visible=False),
2170
+ login_password: gr.update(visible=False),
2171
+ login_submit: gr.update(visible=False),
2172
+ login_error: gr.update(visible=False),
2173
+ attempts_tracker_display: gr.update(value=_build_attempts_tracker_html(submission_count)),
2174
+ was_preview_state: False,
2175
+ kpi_meta_state: error_kpi_meta,
2176
+ last_seen_ts_state: None
2177
+ }
2178
+ yield error_updates
2179
+ return
2035
2180
 
2036
2181
  try:
2037
2182
  # --- Stage 2: Smart Build (Cache vs Train) ---
@@ -2160,7 +2305,7 @@ def run_experiment(
2160
2305
  if submission_count >= ATTEMPT_LIMIT:
2161
2306
  limit_warning_html = f"""
2162
2307
  <div class='kpi-card' style='border-color: #ef4444;'>
2163
- <h2 style='color: #111827; margin-top:0;'>🛑 Submission Limit Reached</h2>
2308
+ <h2 style='color: #111827; margin-top:0;'>🛑 Límit d'enviaments assolit</h2>
2164
2309
  <div class='kpi-card-body'>
2165
2310
  <div class='kpi-metric-box'>
2166
2311
  <p class='kpi-label'>Attempts Used</p>
@@ -2174,10 +2319,10 @@ def run_experiment(
2174
2319
  settings = compute_rank_settings(submission_count, model_name_key, complexity_level, feature_set, data_size_str)
2175
2320
  limit_reached_updates = {
2176
2321
  submission_feedback_display: gr.update(value=limit_warning_html, visible=True),
2177
- submit_button: gr.update(value="🛑 Submission Limit Reached", interactive=False),
2322
+ submit_button: gr.update(value="🛑 Límit d'enviaments assolit", interactive=False),
2178
2323
  model_type_radio: gr.update(interactive=False), complexity_slider: gr.update(interactive=False),
2179
2324
  feature_set_checkbox: gr.update(interactive=False), data_size_radio: gr.update(interactive=False),
2180
- attempts_tracker_display: gr.update(value=f"<div style='text-align:center; padding:8px; margin:8px 0; background:#fef2f2; border-radius:8px; border:1px solid #ef4444;'><p style='margin:0; color:#991b1b; font-weight:600;'>🛑 Attempts used: {ATTEMPT_LIMIT}/{ATTEMPT_LIMIT}</p></div>"),
2325
+ attempts_tracker_display: gr.update(value=f"<div style='text-align:center; padding:8px; margin:8px 0; background:#fef2f2; border-radius:8px; border:1px solid #ef4444;'><p style='margin:0; color:#991b1b; font-weight:600;'>🛑 Intents utilitzats: {ATTEMPT_LIMIT}/{ATTEMPT_LIMIT}</p></div>"),
2181
2326
  team_leaderboard_display: team_leaderboard_display, individual_leaderboard_display: individual_leaderboard_display,
2182
2327
  last_submission_score_state: last_submission_score, last_rank_state: last_rank,
2183
2328
  best_score_state: best_score, submission_count_state: submission_count,
@@ -2189,9 +2334,9 @@ def run_experiment(
2189
2334
  yield limit_reached_updates
2190
2335
  return
2191
2336
 
2192
- progress(0.5, desc="Submitting to Cloud...")
2337
+ progress(0.5, desc="S'està enviant al núvol...")
2193
2338
  yield {
2194
- submission_feedback_display: gr.update(value=get_status_html(3, "Submitting", "Sending model to the competition server..."), visible=True),
2339
+ submission_feedback_display: gr.update(value=get_status_html(3, "Enviament en curs", "S'està enviant el model al servidor de la competició..."), visible=True),
2195
2340
  login_error: gr.update(visible=False)
2196
2341
  }
2197
2342
 
@@ -2312,24 +2457,24 @@ def run_experiment(
2312
2457
  # 1. Append the Limit Warning HTML *below* the Result Card
2313
2458
  limit_html = f"""
2314
2459
  <div style='margin-top: 16px; border: 2px solid #ef4444; background:#fef2f2; padding:16px; border-radius:12px; text-align:left;'>
2315
- <h3 style='margin:0 0 8px 0; color:#991b1b;'>🛑 Submission Limit Reached ({ATTEMPT_LIMIT}/{ATTEMPT_LIMIT})</h3>
2460
+ <h3 style='margin:0 0 8px 0; color:#991b1b;'>🛑 Límit d'enviaments assolit ({ATTEMPT_LIMIT}/{ATTEMPT_LIMIT})</h3>
2316
2461
  <p style='margin:0; color:#7f1d1d; line-height:1.4;'>
2317
2462
  <b>You have used all your attempts for this session.</b><br>
2318
- Review your final results above, then scroll down to "Finish and Reflect" to continue.
2463
+ Revisa els teus resultats finals a dalt i després baixa fins a "Finalitzar i reflexionar" per continuar.
2319
2464
  </p>
2320
2465
  </div>
2321
2466
  """
2322
2467
  final_html_display = kpi_card_html + limit_html
2323
2468
 
2324
2469
  # 2. Disable all controls
2325
- button_update = gr.update(value="🛑 Limit Reached", interactive=False)
2470
+ button_update = gr.update(value="🛑 Límit assolit", interactive=False)
2326
2471
  interactive_state = False
2327
- tracker_html = f"<div style='text-align:center; padding:8px; margin:8px 0; background:#fef2f2; border-radius:8px; border:1px solid #ef4444;'><p style='margin:0; color:#991b1b; font-weight:600;'>🛑 Attempts used: {ATTEMPT_LIMIT}/{ATTEMPT_LIMIT} (Max)</p></div>"
2472
+ tracker_html = f"<div style='text-align:center; padding:8px; margin:8px 0; background:#fef2f2; border-radius:8px; border:1px solid #ef4444;'><p style='margin:0; color:#991b1b; font-weight:600;'>🛑 Intents utilitzats: {ATTEMPT_LIMIT}/{ATTEMPT_LIMIT} (Max)</p></div>"
2328
2473
 
2329
2474
  else:
2330
2475
  # Normal State: Show just the result card and keep controls active
2331
2476
  final_html_display = kpi_card_html
2332
- button_update = gr.update(value="🔬 Build & Submit Model", interactive=True)
2477
+ button_update = gr.update(value="🔬 Construir i enviar model", interactive=True)
2333
2478
  interactive_state = True
2334
2479
  tracker_html = _build_attempts_tracker_html(new_submission_count)
2335
2480
 
@@ -2427,14 +2572,14 @@ def on_initial_load(username, token=None, team_name=""):
2427
2572
  welcome_html = f"""
2428
2573
  <div style='text-align:center; padding: 30px 20px;'>
2429
2574
  <div style='font-size: 3rem; margin-bottom: 10px;'>👋</div>
2430
- <h3 style='margin: 0 0 8px 0; color: #111827; font-size: 1.5rem;'>Benvingut a <b>{display_team}</b>!</h3>
2575
+ <h3 style='margin: 0 0 8px 0; color: #111827; font-size: 1.5rem;'>Ja formes part de l'equip: <b>{display_team}</b>!</h3>
2431
2576
  <p style='font-size: 1.1rem; color: #4b5563; margin: 0 0 20px 0;'>
2432
- El teu equip espera la teva ajuda per millorar la IA.
2577
+ El teu equip necessita la teva ajuda per millorar la IA.
2433
2578
  </p>
2434
2579
 
2435
2580
  <div style='background:#eff6ff; padding:16px; border-radius:12px; border:2px solid #bfdbfe; display:inline-block;'>
2436
2581
  <p style='margin:0; color:#1e40af; font-weight:bold; font-size:1.1rem;'>
2437
- 👈 Fes clic a "Build & Submit Model" per començar a jugar!
2582
+ 👈 Fes clic a 'Construir i enviar model' per començar a jugar!
2438
2583
  </p>
2439
2584
  </div>
2440
2585
  </div>
@@ -2469,7 +2614,7 @@ def on_initial_load(username, token=None, team_name=""):
2469
2614
  # CASE 1: New User (or first time loading session) -> FORCE WELCOME
2470
2615
  # regardless of whether the leaderboard has other people's data.
2471
2616
  team_html = welcome_html
2472
- individual_html = "<p style='text-align:center; color:#6b7280; padding-top:40px;'>Submit your model to see where you rank!</p>"
2617
+ individual_html = "<p style='text-align:center; color:#6b7280; padding-top:40px;'>Envia el teu model per veure la teva posició a la classificació!</p>"
2473
2618
 
2474
2619
  elif full_leaderboard_df is None or full_leaderboard_df.empty:
2475
2620
  # CASE 2: Returning user, but data fetch failed -> Show Skeleton
@@ -2487,8 +2632,8 @@ def on_initial_load(username, token=None, team_name=""):
2487
2632
  )
2488
2633
  except Exception as e:
2489
2634
  print(f"Error generating summary HTML: {e}")
2490
- team_html = "<p style='text-align:center; color:red; padding-top:20px;'>Error rendering leaderboard.</p>"
2491
- individual_html = "<p style='text-align:center; color:red; padding-top:20px;'>Error rendering leaderboard.</p>"
2635
+ team_html = "<p style='text-align:center; color:red; padding-top:20px;'>S'ha produït un error en carregar la classificació.</p>"
2636
+ individual_html = "<p style='text-align:center; color:red; padding-top:20px;'>S'ha produït un error en mostrar la classificació.</p>"
2492
2637
 
2493
2638
  return (
2494
2639
  get_model_card(DEFAULT_MODEL),
@@ -2511,7 +2656,7 @@ def build_final_conclusion_html(best_score, submissions, rank, first_score, feat
2511
2656
  Colors are handled via CSS classes so that light/dark mode work correctly.
2512
2657
  """
2513
2658
  unlocked_tiers = min(3, max(0, submissions - 1)) # 0..3
2514
- tier_names = ["Trainee", "Junior", "Senior", "Lead"]
2659
+ tier_names = ["En pràctiques", "Júnior", "Sènior", "Principal"]
2515
2660
  reached = tier_names[: unlocked_tiers + 1]
2516
2661
  tier_line = " → ".join([f"{t}{' ✅' if t in reached else ''}" for t in tier_names])
2517
2662
 
@@ -2520,8 +2665,8 @@ def build_final_conclusion_html(best_score, submissions, rank, first_score, feat
2520
2665
  strong_used = [f for f in feature_set if f in strong_predictors]
2521
2666
 
2522
2667
  ethical_note = (
2523
- "You unlocked powerful predictors. Consider: Would removing demographic fields change fairness? "
2524
- "In the next section we will begin to investigate this question further."
2668
+ "Has desbloquejat predictors molt potents. Reflexiona: eliminant els camps demogràfics canviaria la justícia del model?"
2669
+ "En la següent secció començarem a investigar aquesta qüestió a fons."
2525
2670
  )
2526
2671
 
2527
2672
  # Tailor message for very few submissions
@@ -2529,7 +2674,7 @@ def build_final_conclusion_html(best_score, submissions, rank, first_score, feat
2529
2674
  if submissions < 2:
2530
2675
  tip_html = """
2531
2676
  <div class="final-conclusion-tip">
2532
- <b>Tip:</b> Try at least 23 submissions changing ONE setting at a time to see clear cause/effect.
2677
+ <b>Tip:</b> Prova de fer almenys 2 o 3 enviaments canviant NOMÉS un paràmetre cada vegada per veure clarament la relació causa-efecte.
2533
2678
  </div>
2534
2679
  """
2535
2680
 
@@ -3438,7 +3583,7 @@ def create_model_building_game_ca_app(theme_primary_hue: str = "indigo") -> "gr.
3438
3583
  gr.Markdown(
3439
3584
  """
3440
3585
  <div style='text-align:center; padding:100px 0;'>
3441
- <h2 style='font-size:2rem; color:#6b7280;'>⏳ Loading...</h2>
3586
+ <h2 style='font-size:2rem; color:#6b7280;'>⏳ Carregant...</h2>
3442
3587
  </div>
3443
3588
  """
3444
3589
  )