aimodelshare 0.3.7__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.
Files changed (36) hide show
  1. aimodelshare/moral_compass/__init__.py +51 -2
  2. aimodelshare/moral_compass/api_client.py +92 -4
  3. aimodelshare/moral_compass/apps/__init__.py +36 -16
  4. aimodelshare/moral_compass/apps/ai_consequences.py +98 -88
  5. aimodelshare/moral_compass/apps/bias_detective_ca.py +2722 -0
  6. aimodelshare/moral_compass/apps/bias_detective_en.py +2722 -0
  7. aimodelshare/moral_compass/apps/bias_detective_part1.py +2722 -0
  8. aimodelshare/moral_compass/apps/bias_detective_part2.py +2465 -0
  9. aimodelshare/moral_compass/apps/bias_detective_part_es.py +2722 -0
  10. aimodelshare/moral_compass/apps/ethical_revelation.py +237 -147
  11. aimodelshare/moral_compass/apps/fairness_fixer.py +1839 -859
  12. aimodelshare/moral_compass/apps/fairness_fixer_ca.py +1869 -0
  13. aimodelshare/moral_compass/apps/fairness_fixer_en.py +1869 -0
  14. aimodelshare/moral_compass/apps/fairness_fixer_es.py +1869 -0
  15. aimodelshare/moral_compass/apps/judge.py +130 -143
  16. aimodelshare/moral_compass/apps/justice_equity_upgrade.py +793 -831
  17. aimodelshare/moral_compass/apps/justice_equity_upgrade_ca.py +815 -0
  18. aimodelshare/moral_compass/apps/justice_equity_upgrade_en.py +815 -0
  19. aimodelshare/moral_compass/apps/justice_equity_upgrade_es.py +815 -0
  20. aimodelshare/moral_compass/apps/mc_integration_helpers.py +227 -745
  21. aimodelshare/moral_compass/apps/model_building_app_ca.py +4544 -0
  22. aimodelshare/moral_compass/apps/model_building_app_ca_final.py +3899 -0
  23. aimodelshare/moral_compass/apps/model_building_app_en.py +4290 -0
  24. aimodelshare/moral_compass/apps/model_building_app_en_final.py +3869 -0
  25. aimodelshare/moral_compass/apps/model_building_app_es.py +4362 -0
  26. aimodelshare/moral_compass/apps/model_building_app_es_final.py +3899 -0
  27. aimodelshare/moral_compass/apps/model_building_game.py +4211 -935
  28. aimodelshare/moral_compass/apps/moral_compass_challenge.py +195 -95
  29. aimodelshare/moral_compass/apps/what_is_ai.py +126 -117
  30. aimodelshare/moral_compass/challenge.py +98 -17
  31. {aimodelshare-0.3.7.dist-info → aimodelshare-0.4.71.dist-info}/METADATA +1 -1
  32. {aimodelshare-0.3.7.dist-info → aimodelshare-0.4.71.dist-info}/RECORD +35 -19
  33. aimodelshare/moral_compass/apps/bias_detective.py +0 -714
  34. {aimodelshare-0.3.7.dist-info → aimodelshare-0.4.71.dist-info}/WHEEL +0 -0
  35. {aimodelshare-0.3.7.dist-info → aimodelshare-0.4.71.dist-info}/licenses/LICENSE +0 -0
  36. {aimodelshare-0.3.7.dist-info → aimodelshare-0.4.71.dist-info}/top_level.txt +0 -0
@@ -8,7 +8,7 @@ import random
8
8
  import time
9
9
  import threading
10
10
  from typing import Optional, Dict, Any, Tuple
11
-
11
+ from functools import lru_cache
12
12
  import pandas as pd
13
13
  import gradio as gr
14
14
 
@@ -34,6 +34,35 @@ TEAM_NAMES = [
34
34
  "The Ethical Explorers", "The Fairness Finders", "The Accuracy Avengers"
35
35
  ]
36
36
 
37
+ # NEW: Team name translations for UI display only
38
+ # Internal logic (ranking, caching, grouping) always uses canonical English names
39
+ TEAM_NAME_TRANSLATIONS = {
40
+ "en": {
41
+ "The Justice League": "The Justice League",
42
+ "The Moral Champions": "The Moral Champions",
43
+ "The Data Detectives": "The Data Detectives",
44
+ "The Ethical Explorers": "The Ethical Explorers",
45
+ "The Fairness Finders": "The Fairness Finders",
46
+ "The Accuracy Avengers": "The Accuracy Avengers"
47
+ },
48
+ "es": {
49
+ "The Justice League": "La Liga de la Justicia",
50
+ "The Moral Champions": "Los Campeones Morales",
51
+ "The Data Detectives": "Los Detectives de Datos",
52
+ "The Ethical Explorers": "Los Exploradores Éticos",
53
+ "The Fairness Finders": "Los Buscadores de Equidad",
54
+ "The Accuracy Avengers": "Los Vengadores de Precisión"
55
+ },
56
+ "ca": {
57
+ "The Justice League": "La Lliga de la Justícia",
58
+ "The Moral Champions": "Els Campions Morals",
59
+ "The Data Detectives": "Els Detectives de Dades",
60
+ "The Ethical Explorers": "Els Exploradors Ètics",
61
+ "The Fairness Finders": "Els Cercadors d'Equitat",
62
+ "The Accuracy Avengers": "Els Venjadors de Precisió"
63
+ }
64
+ }
65
+
37
66
  _cache_lock = threading.Lock()
38
67
  _leaderboard_cache: Dict[str, Any] = {"data": None, "timestamp": 0.0}
39
68
  _user_stats_cache: Dict[str, Dict[str, Any]] = {}
@@ -65,8 +94,8 @@ TRANSLATIONS = {
65
94
  "s2_title": "⚠️ But Wait...",
66
95
  "s2_intro": "Before we share the model, there's something you need to know...",
67
96
  "s2_box_title": "A Real-World Story",
68
- "s2_p1": "A model similar to yours was actually used in the real world. It was used by judges across the United States to help make decisions about defendants' futures.",
69
- "s2_p2": "Like yours, it had impressive accuracy scores. Like yours, it was built on data about past criminal cases. Like yours, it aimed to predict who would re-offend.",
97
+ "s2_p1": "A model similar to yours was actually used in the real world. It was used by judges across the United States to determine whether to grant parole to people in prison.",
98
+ "s2_p2": "Like yours, it had impressive accuracy scores. Like yours, it was built on data about past criminal cases. Like yours, it aimed to predict who might re-offend.",
70
99
  "s2_p3": "But something was terribly wrong...",
71
100
  "btn_back": "◀️ Back",
72
101
  "btn_reveal": "Reveal the Truth ▶️",
@@ -77,7 +106,7 @@ TRANSLATIONS = {
77
106
  "s3_box_title": "Their Shocking Findings:",
78
107
  "s3_alert": "⚠️ Black defendants were labeled \"high-risk\" at nearly <u>TWICE</u> the rate of white defendants.",
79
108
  "s3_spec": "<strong>Specifically:</strong>",
80
- "s3_li1_pre": "defendants who <em>did NOT re-offend</em> were incorrectly labeled as <strong>\"high-risk\"</strong> at a rate of",
109
+ "s3_li1_pre": "<strong>Black defendants</strong> who <em>did NOT re-offend</em>, were incorrectly labeled as <strong>\"high-risk\"</strong> at a rate of about <strong>45%</strong>",
81
110
  "s3_li2_pre": "<strong>White defendants</strong> who <em>did NOT re-offend</em> were incorrectly labeled as <strong>\"high-risk\"</strong> at a rate of only <strong>24%</strong>",
82
111
  "s3_li3": "Meanwhile, <strong>white defendants</strong> who <em>DID re-offend</em> were <strong>more likely to be labeled \"low-risk\"</strong> compared to Black defendants",
83
112
  "s3_box2_title": "What Does This Mean?",
@@ -87,8 +116,8 @@ TRANSLATIONS = {
87
116
  "lbl_black": "Black", # Used in dynamic construction if needed
88
117
  # Step 4 EU
89
118
  "s4eu_title": "🇪🇺 This Isn’t Just a US Problem",
90
- "s4eu_head": "AI for “Risky Offenders” Is Already in Europe",
91
- "s4eu_intro": "The COMPAS story is not just an American warning. Across Europe, public authorities have experimented with <strong>very similar tools</strong> that aim to predict who will reoffend or which areas are “high risk”.",
119
+ "s4eu_head": "Europe Is Already Using AI to Predict Reoffending Risk",
120
+ "s4eu_intro": "The COMPAS story is not just an American warning. Across Europe, public authorities have experimented with <strong>very similar tools</strong> designed to predict who might reoffend or which areas are considered “high risk”.",
92
121
  "s4eu_li1_title": "United Kingdom – HART (Harm Assessment Risk Tool)",
93
122
  "s4eu_li1_body": "A machine-learning model used by Durham Police to predict who will reoffend within two years. It uses variables like age, gender, <em>postcode</em>, housing and job instability – socio-economic proxies that can reproduce the same kinds of biased patterns exposed in COMPAS.",
94
123
  "s4eu_li2_title": "Spain – VioGén",
@@ -103,7 +132,7 @@ TRANSLATIONS = {
103
132
  # Step 4 Lesson
104
133
  "s4_title": "💡 The Critical Lesson",
105
134
  "s4_box_title": "Why This Matters:",
106
- "s4_li1_title": "Overall accuracy can hide group-specific harm",
135
+ "s4_li1_title": "A model’s overall accuracy can hide group-specific harm",
107
136
  "s4_li1_body": "A model might be 70% accurate overall — but the remaining 30% of errors can fall disproportionately on <span class='emph-harm'>specific groups</span>, resulting in real harm even when the total accuracy appears “good”.",
108
137
  "s4_li2_title": "Historical bias in training data gets amplified",
109
138
  "s4_li2_body": "If past policing or judicial decisions were biased, the AI system will <span class='emph-harm'>learn and reinforce</span> those inequities — often making them worse at scale.",
@@ -127,155 +156,155 @@ TRANSLATIONS = {
127
156
  "btn_review": "◀️ Review the Investigation"
128
157
  },
129
158
  "es": {
130
- "title": "🚀 La Revelación Ética: Impacto Real",
159
+ "title": "🚀 La revelación ética: impacto real",
131
160
  "loading_personal": "⏳ Cargando tu experiencia personalizada...",
132
- "stats_title": "🏆 ¡Gran Trabajo, Ingeniero! 🏆",
133
- "stats_subtitle": "Aquí está tu resumen de rendimiento.",
134
- "stats_heading": "Tus Estadísticas",
135
- "lbl_accuracy": "Mejor Precisión",
136
- "lbl_rank": "Tu Rango",
161
+ "stats_title": "🏆 ¡Gran trabajo, ingeniero/a! 🏆",
162
+ "stats_subtitle": "Aquí tienes el resumen de tu rendimiento.",
163
+ "stats_heading": "Tus estadísticas",
164
+ "lbl_accuracy": "Mejor precisión",
165
+ "lbl_rank": "Tu rango",
137
166
  "lbl_team": "Equipo",
138
167
  "stats_footer": "¿Listo para compartir tu modelo y explorar su impacto en el mundo real?",
139
- "btn_deploy": "🌍 Compartir tu Modelo de IA (Simulación)",
140
- "guest_title": "🚀 ¡Has Iniciado Sesión!",
168
+ "btn_deploy": "🌍 Compartir tu modelo de IA (simulación)",
169
+ "guest_title": "🚀 ¡Has iniciado sesión!",
141
170
  "guest_subtitle": "Aún no has enviado un modelo, pero estás listo para seguir aprendiendo.",
142
171
  "guest_body": "Una vez que envíes un modelo en el Juego de Construcción de Modelos, tu precisión y clasificación aparecerán aquí.",
143
172
  "guest_footer": "Continúa a la siguiente sección cuando estés listo.",
144
173
  "loading_session": "🔒 Cargando tu sesión...",
145
- "s2_title": "⚠️ Pero Espera...",
174
+ "s2_title": "⚠️ Pero espera...",
146
175
  "s2_intro": "Antes de compartir el modelo, hay algo que necesitas saber...",
147
- "s2_box_title": "Una Historia del Mundo Real",
148
- "s2_p1": "Un modelo similar al tuyo se utilizó realmente en el mundo real. Fue usado por jueces en todo Estados Unidos para ayudar a tomar decisiones sobre el futuro de los acusados.",
149
- "s2_p2": "Como el tuyo, tenía puntuaciones de precisión impresionantes. Como el tuyo, se construyó con datos de casos criminales pasados. Como el tuyo, su objetivo era predecir quién reincidiría.",
150
- "s2_p3": "Pero algo estaba terriblemente mal...",
176
+ "s2_box_title": "Una historia del mundo real",
177
+ "s2_p1": "Un modelo similar al tuyo se empleó en situaciones reales. Jueces de todo Estados Unidos lo usaron para determinar si conceder la libertad condicional a personas presas.",
178
+ "s2_p2": "Como el tuyo, tenía puntuaciones de precisión impresionantes. Como el tuyo, se construyó con datos de casos criminales pasados. Como el tuyo, su objetivo era predecir quíen podría volver a cometer un delito..",
179
+ "s2_p3": "Pero algo iba muy mal...",
151
180
  "btn_back": "◀️ Atrás",
152
- "btn_reveal": "Revelar la Verdad ▶️",
153
- "s3_title": "📰 La Investigación de ProPublica",
154
- "s3_head": "\"Sesgo de Máquina\" - Una Investigación Histórica",
181
+ "btn_reveal": "Revelar la verdad ▶️",
182
+ "s3_title": "📰 La investigación de ProPublica",
183
+ "s3_head": "\"Machine Bias\" - Una investigación de referencia sobre los sesgos algorítmicos",
155
184
  "s3_p1": "En 2016, periodistas de <strong>ProPublica</strong> investigaron un algoritmo de evaluación de riesgo criminal ampliamente utilizado llamado <strong>COMPAS</strong>. Analizaron más de <strong>7,000 casos reales</strong> para ver si las predicciones de la IA se cumplían.",
156
- "s3_box_title": "Sus Hallazgos Impactantes:",
157
- "s3_alert": "⚠️ Los acusados negros fueron etiquetados como \"alto riesgo\" casi el <u>DOBLE</u> que los acusados blancos.",
185
+ "s3_box_title": "Sus hallazgos impactantes:",
186
+ "s3_alert": "⚠️ Las personas negras presas fueron clasificadas como \"alto riesgo\" casi el <u>DOBLE</u> que las personas blancas presas.",
158
187
  "s3_spec": "<strong>Específicamente:</strong>",
159
- "s3_li1_pre": "Los <span class='emph-danger'>acusados negros</span> que <em>NO reincidieron</em> fueron etiquetados incorrectamente como <strong>\"alto riesgo\"</strong> a una tasa del",
160
- "s3_li2_pre": "Los <strong>acusados blancos</strong> que <em>NO reincidieron</em> fueron etiquetados incorrectamente como <strong>\"alto riesgo\"</strong> a una tasa de solo el <strong>24%</strong>",
161
- "s3_li3": "Mientras tanto, los <strong>acusados blancos</strong> que <em>SÍ reincidieron</em> tenían <strong>más probabilidades de ser etiquetados como \"bajo riesgo\"</strong> en comparación con los acusados negros",
162
- "s3_box2_title": "¿Qué Significa Esto?",
163
- "s3_mean_p1": "El sistema de IA estaba <strong class='emph-danger'>sistemáticamente sesgado</strong>. No solo cometía errores aleatorios, cometía <strong>diferentes tipos de errores para diferentes grupos de personas</strong>.",
164
- "s3_mean_p2": "Los acusados negros enfrentaban un riesgo mucho mayor de ser <strong class='emph-danger'>injustamente etiquetados como peligrosos</strong>, lo que potencialmente conducía a sentencias de prisión más largas o libertad condicional denegada, incluso cuando no habrían reincidido.",
165
- "btn_eu": "Ver Esto en Europa ▶️",
188
+ "s3_li1_pre": "Las <span class='emph-danger'>personas negras presas</span> que <em>NO volvieron a cometer un delito</em> fueron clasificadas incorrectamente como <strong>\"alto riesgo\"</strong> en aproximadamente un <strong>45%</strong> de los casos",
189
+ "s3_li2_pre": "Las <strong>personas blancas presas</strong> que <em>NO reincidieron</em> fueron clasificadas incorrectamente como <strong>\"alto riesgo\"</strong> solo en un <strong>24%</strong> de los casos",
190
+ "s3_li3": "En cambio, las <strong>personas blancas presas</strong> que <em>SÍ reincidieron</em> tenían <strong>más probabilidades de ser clasificadas como de \"bajo riesgo\"</strong> en comparación con las personas negras presas",
191
+ "s3_box2_title": "¿Qué significa esto?",
192
+ "s3_mean_p1": "El sistema de IA mostraba <strong class='emph-danger'>un sesgo sistemático</strong>. No solo cometía errores al azar; también hacía <strong>errores distintos según el grupo de personas</strong>.",
193
+ "s3_mean_p2": "Las personas negras presas enfrentaban un riesgo mucho mayor de ser <strong class='emph-danger'>injustamente classificadas como peligrosas</strong>, lo que potencialmente conducía a sentencias de prisión más largas o libertad condicional denegada, incluso cuando no habrían vuelto a cometer un delito.",
194
+ "btn_eu": "Ver esto en Europa ▶️",
166
195
  "lbl_black": "Negros",
167
- "s4eu_title": "🇪🇺 Esto No Es Solo un Problema de EE. UU.",
168
- "s4eu_head": "La IA para \"Delincuentes de Riesgo\" Ya Está en Europa",
196
+ "s4eu_title": "🇪🇺 Esto no es solo un problema de EE. UU.",
197
+ "s4eu_head": "Europa ya utiliza IA para evaluar el riesgo de reincidencia",
169
198
  "s4eu_intro": "La historia de COMPAS no es solo una advertencia estadounidense. En toda Europa, las autoridades públicas han experimentado con <strong>herramientas muy similares</strong> que pretenden predecir quién reincidirá o qué áreas son de \"alto riesgo\".",
170
199
  "s4eu_li1_title": "Reino Unido – HART (Harm Assessment Risk Tool)",
171
200
  "s4eu_li1_body": "Un modelo de aprendizaje automático utilizado por la Policía de Durham para predecir quién reincidirá en dos años. Utiliza variables como edad, género, <em>código postal</em>, vivienda e inestabilidad laboral: indicadores socioeconómicos que pueden reproducir los mismos tipos de patrones sesgados expuestos en COMPAS.",
172
201
  "s4eu_li2_title": "España – VioGén",
173
- "s4eu_li2_body": "Una herramienta de riesgo para casos de violencia de género cuyo funcionamiento interno es en gran medida una <em>\"caja negra\"</em>. Los oficiales dependen en gran medida de sus puntuaciones para decidir medidas de protección, aunque el algoritmo no puede ser auditado fácilmente en busca de sesgos o errores.",
202
+ "s4eu_li2_body": "Una herramienta de riesgo para casos de violencia de género cuyo funcionamiento interno es en gran medida una <em>\"caja negra\"</em>. Los oficiales dependen en gran medida de sus puntuaciones para decidir medidas de protección, aunque no se puede auditar fácilmente el algoritmo en busca de sesgos o errores.",
174
203
  "s4eu_li3_title": "Países Bajos y Dinamarca – Perfiles predictivos",
175
- "s4eu_li3_body": "Sistemas como el <em>Sistema de Anticipación del Crimen (CAS)</em> holandés y las clasificaciones algorítmicas de <em>\"guetos\"</em> de Dinamarca utilizan datos demográficos y socioeconómicos para dirigir la vigilancia y las sanciones, arriesgando bucles de retroalimentación que apuntan a ciertas comunidades una y otra vez.",
176
- "s4eu_box_title": "Debate Europeo en Curso",
204
+ "s4eu_li3_body": "Sistemas como el <em>Crime Anticipation System (CAS)</em> holandés y las clasificaciones algorítmicas de <em>\"guetos\"</em> de Dinamarca utilizan datos demográficos y socioeconómicos para orientar la vigilancia i las sanciones, con el riesgo de generar bucles de retroalimentación que señalen una y otra vez a las mismas comunidades.",
205
+ "s4eu_box_title": "Debate europeo en curso",
177
206
  "s4eu_box_body": "La Fiscalía de Barcelona ha propuesto una \"calculadora electrónica de reincidencia\". Tribunales, reguladores e investigadores están examinando activamente cómo estas herramientas afectan los derechos fundamentales como la no discriminación, el juicio justo y la protección de datos.",
178
- "s4eu_note": "<strong>Punto clave:</strong> Los riesgos que viste con COMPAS no están lejos en otro país. <strong class='emph-key'>Son preguntas vivas tanto en Europa como en los EE. UU. en este momento.</strong>",
179
- "btn_back_invest": "◀️ Volver a la Investigación",
180
- "btn_zoom": "Alejarse a la Lección ▶️",
181
- "s4_title": "💡 La Lección Crítica",
182
- "s4_box_title": "Por Qué Importa Esto:",
183
- "s4_li1_title": "La precisión general puede ocultar daños específicos a grupos",
184
- "s4_li1_body": "Un modelo puede tener un 70% de precisión general, pero el 30% restante de errores puede recaer desproporcionadamente en <span class='emph-harm'>grupos específicos</span>, resultando en un daño real incluso cuando la precisión total parece \"buena\".",
207
+ "s4eu_note": "<strong>Idea clave:</strong> Los riesgos que viste con COMPAS no están lejos ni son ajenos. <strong class='emph-key'>Son cuestiones pleanmente actuales tanto en Europa como en los EE. UU.</strong>",
208
+ "btn_back_invest": "◀️ Volver a la investigación",
209
+ "btn_zoom": "Vista general de la lección ▶️",
210
+ "s4_title": "💡 La lección fundamental",
211
+ "s4_box_title": "Por qué importa esto:",
212
+ "s4_li1_title": "La precisión global de un modelo puede ocultar daños específicos por grupo",
213
+ "s4_li1_body": "Un modelo puede tener un 70% de precisión global, pero el 30% restante de errores puede concentrarse de manera desproporcionada en <span class='emph-harm'>grupos concretos</span>, causando daños reales incluso cuando la precisión global parece \"buena\".",
185
214
  "s4_li2_title": "El sesgo histórico en los datos de entrenamiento se amplifica",
186
- "s4_li2_body": "Si las decisiones policiales o judiciales pasadas fueron sesgadas, el sistema de IA <span class='emph-harm'>aprenderá y reforzará</span> esas desigualdades, a menudo empeorándolas a escala.",
215
+ "s4_li2_body": "Si las decisiones policiales o judiciales pasadas fueron sesgadas, el sistema de IA <span class='emph-harm'>aprenderá y reforzará</span> esas desigualdades, y a menudo las amplificará a gran escala.",
187
216
  "s4_li3_title": "Las vidas de personas reales se ven afectadas",
188
- "s4_li3_body": "Cada <strong class='emph-harm'>\"falso positivo\"</strong> representa a una persona que puede perder años de libertad, empleo, vivienda o conexión familiar, todo debido a una sola <strong class='emph-harm'>predicción sesgada</strong>.",
217
+ "s4_li3_body": "Cada <strong class='emph-harm'>\"falso positivo\"</strong> representa a una persona que puede perder años de libertad, empleo, vivienda o conexión familiar, todo a causa de una sola <strong class='emph-harm'>predicción sesgada</strong>.",
189
218
  "btn_back_eu": "◀️ Atrás",
190
- "btn_what_do": "¿Qué Podemos Hacer? ▶️",
191
- "s5_title": "🛤️ El Camino a Seguir",
192
- "s5_head": "De la Precisión a la Ética",
193
- "s5_intro": "Ahora has visto ambos lados de la historia de la IA:",
194
- "s5_li1": "✅ Construiste modelos que lograron puntuaciones de precisión más altas",
195
- "s5_li2": "⚠️ Aprendiste cómo modelos similares causaron daño en el mundo real",
219
+ "btn_what_do": "¿Qué podemos hacer? ▶️",
220
+ "s5_title": "🛤️ El camino a seguir",
221
+ "s5_head": "De la precisión a la ética",
222
+ "s5_intro": "Ya has visto los dos lados de la IA:",
223
+ "s5_li1": "✅ Has construido modelos con altos niveles de precisión",
224
+ "s5_li2": "⚠️ Has aprendido cómo modelos similares han causado daños reales",
196
225
  "s5_li3": "🤔 Entiendes que la precisión por sí sola no es suficiente",
197
- "s5_box_title": "Lo Que Harás A Continuación:",
226
+ "s5_box_title": "Lo que harás a continuación:",
198
227
  "s5_p1": "En la siguiente sección, se te presentará una <strong class='emph-key'>nueva forma de medir el éxito</strong>, una que equilibra el rendimiento con la equidad y la ética.",
199
228
  "s5_p2": "Aprenderás técnicas para <strong class='emph-key'>detectar sesgos</strong> en tus modelos, <strong class='emph-key'>medir la equidad</strong> en diferentes grupos y <strong class='emph-key'>rediseñar tu IA</strong> para minimizar el daño.",
200
- "s5_mission": "🎯 Tu nueva misión: Construir IA que no solo sea precisa, sino también <strong class='emph-key'>justa, equitativa y éticamente sólida</strong>.",
229
+ "s5_mission": "🎯 Tu nueva misión: Construir una IA que no solo sea precisa, sino también <strong class='emph-key'>justa, equitativa y éticamente sólida</strong>.",
201
230
  "s5_scroll": "👇 DESPLÁZATE HACIA ABAJO 👇",
202
- "s5_continue": "Continúa en la siguiente sección abajo para comenzar tu viaje de IA ética.",
231
+ "s5_continue": "Continúa en la siguiente sección para comenzar tu viaje de IA ética.",
203
232
  "btn_review": "◀️ Revisar la Investigación"
204
233
  },
205
234
  "ca": {
206
- "title": "🚀 La Revelació Ètica: Impacte Real",
235
+ "title": "🚀 La revelació ètica: impacte real",
207
236
  "loading_personal": "⏳ Carregant la teva experiència personalitzada...",
208
- "stats_title": "🏆 Bona Feina, Enginyer! 🏆",
237
+ "stats_title": "🏆 Bona feina, enginyer/a! 🏆",
209
238
  "stats_subtitle": "Aquí tens el teu resum de rendiment.",
210
- "stats_heading": "Les Teves Estadístiques",
211
- "lbl_accuracy": "Millor Precisió",
212
- "lbl_rank": "El Teu Rang",
239
+ "stats_heading": "Les teves estadístiques",
240
+ "lbl_accuracy": "Millor precisió",
241
+ "lbl_rank": "El teu rang",
213
242
  "lbl_team": "Equip",
214
243
  "stats_footer": "A punt per compartir el teu model i explorar el seu impacte al món real?",
215
- "btn_deploy": "🌍 Compartir el Teu Model d'IA (Simulació)",
216
- "guest_title": "🚀 Has Iniciat Sessió!",
244
+ "btn_deploy": "🌍 Compartir el teu model d'IA (simulació)",
245
+ "guest_title": "🚀 Has iniciat sessió!",
217
246
  "guest_subtitle": "Encara no has enviat un model, però estàs a punt per continuar aprenent.",
218
247
  "guest_body": "Un cop enviïs un model al Joc de Construcció de Models, la teva precisió i classificació apareixeran aquí.",
219
248
  "guest_footer": "Continua a la següent secció quan estiguis a punt.",
220
249
  "loading_session": "🔒 Carregant la teva sessió...",
221
- "s2_title": "⚠️ Però Espera...",
222
- "s2_intro": "Abans de compartir el model, hi ha una cosa que necessites saber...",
223
- "s2_box_title": "Una Història del Món Real",
224
- "s2_p1": "Un model similar al teu es va utilitzar realment al món real. Va ser utilitzat per jutges a tot Estats Units per ajudar a prendre decisions sobre el futur dels acusats.",
225
- "s2_p2": "Com el teu, tenia puntuacions de precisió impressionants. Com el teu, es va construir amb dades de casos criminals passats. Com el teu, el seu objectiu era predir qui reincidiria.",
226
- "s2_p3": "Però alguna cosa estava terriblement malament...",
250
+ "s2_title": "⚠️ Però espera...",
251
+ "s2_intro": "Abans de compartir el model, hi ha una cosa que hauries de saber...",
252
+ "s2_box_title": "Una història del món real",
253
+ "s2_p1": "Un model similar al teu es va utilitzar en situacions reals. Jutges d’arreu dels Estats Units el van fer servir per determinar si concedir la llibertat condicional a persones preses.",
254
+ "s2_p2": "Com el teu, tenia puntuacions de precisió impressionants. Com el teu, es va construir amb dades de casos criminals passats. Com el teu, el seu objectiu era predir qui podria tornar a cometre un delicte.",
255
+ "s2_p3": "Però alguna cosa no anava bé...",
227
256
  "btn_back": "◀️ Enrere",
228
- "btn_reveal": "Revelar la Veritat ▶️",
229
- "s3_title": "📰 La Investigació de ProPublica",
230
- "s3_head": "\"Biaix de Màquina\" - Una Investigació Històrica",
231
- "s3_p1": "El 2016, periodistes de <strong>ProPublica</strong> van investigar un algorisme d'avaluació de risc criminal àmpliament utilitzat anomenat <strong>COMPAS</strong>. Van analitzar més de <strong>7.000 casos reals</strong> per veure si les prediccions de la IA es complien.",
232
- "s3_box_title": "Les Seves Troballes Impactants:",
233
- "s3_alert": "⚠️ Els acusats negres van ser etiquetats com a \"alt risc\" gairebé el <u>DOBLE</u> que els acusats blancs.",
234
- "s3_spec": "<strong>Específicament:</strong>",
235
- "s3_li1_pre": "Els <span class='emph-danger'>acusats negres</span> que <em>NO van reincidir</em> van ser etiquetats incorrectament com a <strong>\"alt risc\"</strong> a una taxa del",
236
- "s3_li2_pre": "Els <strong>acusats blancs</strong> que <em>NO van reincidir</em> van ser etiquetats incorrectament com a <strong>\"alt risc\"</strong> a una taxa de només el <strong>24%</strong>",
237
- "s3_li3": "Mentrestant, els <strong>acusats blancs</strong> que <em>SÍ van reincidir</em> tenien <strong>més probabilitats de ser etiquetats com a \"baix risc\"</strong> en comparació amb els acusats negres",
238
- "s3_box2_title": "Què Significa Això?",
239
- "s3_mean_p1": "El sistema d'IA estava <strong class='emph-danger'>sistemàticament esbiaixat</strong>. No només cometia errors aleatoris, cometia <strong>diferents tipus d'errors per a diferents grups de persones</strong>.",
240
- "s3_mean_p2": "Els acusats negres s'enfrontaven a un risc molt més gran de ser <strong class='emph-danger'>injustament etiquetats com a perillosos</strong>, la qual cosa potencialment conduïa a sentències de presó més llargues o llibertat condicional denegada, fins i tot quan no haurien reincidit.",
241
- "btn_eu": "Veure Això a Europa ▶️",
257
+ "btn_reveal": "Revelar la veritat ▶️",
258
+ "s3_title": "📰 La investigació de ProPublica",
259
+ "s3_head": "\"Machine Bias\" - Una investigació de referència sobre els biaixos algorítmics",
260
+ "s3_p1": "El 2016, periodistes de <strong>ProPublica</strong> van analitzar un algoritme davaluació del risc penal molt estès anomenat <strong>COMPAS</strong>. Van estudiar més de <strong>7.000 casos reals</strong> per veure si les prediccions de la IA es complien.",
261
+ "s3_box_title": "Les seves troballes més impactants:",
262
+ "s3_alert": "⚠️ Les persones negres preses eren classificades com a \"alt risc\" gairebé el <u>DOBLE</u> que les persones blanques preses.",
263
+ "s3_spec": "<strong>En concret:</strong>",
264
+ "s3_li1_pre": "Les <span class='emph-danger'>persones negres preses</span> que <em>NO van tornar a cometre un delicte</em> van ser classificades incorrectament com a <strong>\"alt risc\"</strong> en aproximadament el <strong>45%</strong> dels casos.",
265
+ "s3_li2_pre": "Les <strong>persones blanques preses</strong> que <em>NO van reincidir</em> van ser classificades incorrectament com a <strong>\"alt risc\"</strong> en només el <strong>24%</strong> dels casos.",
266
+ "s3_li3": "En canvi, les <strong>persones blanques preses</strong> que <em>SÍ van reincidir</em> tenien <strong>més probabilitats de ser classificades com a \"baix risc\"</strong> en comparació amb les persones negres preses.",
267
+ "s3_box2_title": "Què significa això?",
268
+ "s3_mean_p1": "El sistema d'IA estava <strong class='emph-danger'>sistemàticament esbiaixat</strong>. No només cometia errors aleatoris, cometia <strong>diferents tipus d'errors segons el grup de persones</strong>.",
269
+ "s3_mean_p2": "Les persones negres preses s'enfrontaven a un risc molt més gran de ser <strong class='emph-danger'>injustament classificats com a perillosos</strong>, la qual cosa que podia comportar penes de presó més llargues o que se’ls denegués la llibertat condicional, fins i tot quan no haurien tornat a cometre un delicte.",
270
+ "btn_eu": "Veure això a Europa ▶️",
242
271
  "lbl_black": "Negres",
243
- "s4eu_title": "🇪🇺 Això No És Només un Problema dels EUA",
244
- "s4eu_head": "La IA per a \"Delinqüents de Risc\" Ja És a Europa",
272
+ "s4eu_title": "🇪🇺 Això no és només un problema dels EUA",
273
+ "s4eu_head": "Europa ja utilitza IA per avaluar el risc de reincidència",
245
274
  "s4eu_intro": "La història de COMPAS no és només una advertència nord-americana. A tota Europa, les autoritats públiques han experimentat amb <strong>eines molt similars</strong> que pretenen predir qui reincidirà o quines àrees són d'\"alt risc\".",
246
275
  "s4eu_li1_title": "Regne Unit – HART (Harm Assessment Risk Tool)",
247
276
  "s4eu_li1_body": "Un model d'aprenentatge automàtic utilitzat per la Policia de Durham per predir qui reincidirà en dos anys. Utilitza variables com edat, gènere, <em>codi postal</em>, habitatge i inestabilitat laboral: indicadors socioeconòmics que poden reproduir els mateixos tipus de patrons esbiaixats exposats a COMPAS.",
248
277
  "s4eu_li2_title": "Espanya – VioGén",
249
- "s4eu_li2_body": "Una eina de risc per a casos de violència de gènere el funcionament intern de la qual és en gran part una <em>\"caixa negra\"</em>. Els oficials depenen en gran mesura de les seves puntuacions per decidir mesures de protecció, tot i que l'algorisme no pot ser auditat fàcilment a la recerca de biaixos o errors.",
278
+ "s4eu_li2_body": "Una eina de risc per a casos de violència de gènere, amb processos interns que són, en gran part, una <em>\"caixa negra\"</em>. Les autoritats depenen àmpliament de les seves puntuacions per decidir mesures de protecció, tot i que l’algoritme no es pot auditar fàcilment per detectar biaixos o errors.",
250
279
  "s4eu_li3_title": "Països Baixos i Dinamarca – Perfils predictius",
251
- "s4eu_li3_body": "Sistemes com el <em>Sistema d'Anticipació del Crim (CAS)</em> holandès i les classificacions algorísmiques de <em>\"guetos\"</em> de Dinamarca utilitzen dades demogràfiques i socioeconòmiques per dirigir la vigilància i les sancions, arriscant bucles de retroalimentació que apunten a certes comunitats una i altra vegada.",
252
- "s4eu_box_title": "Debat Europeu en Curs",
280
+ "s4eu_li3_body": "Sistemes com el <em>Crime Anticipation System (CAS)</em> holandès i les classificacions algorítmiques de <em>\"guetos\"</em> de Dinamarca utilitzen dades demogràfiques i socioeconòmiques per orientar la vigilància i les sancions, amb el risc de generar bucles de retroalimentació que assenyalen una i altra vegada les mateixes comunitats.",
281
+ "s4eu_box_title": "Debat europeu en curs",
253
282
  "s4eu_box_body": "La Fiscalia de Barcelona ha proposat una \"calculadora electrònica de reincidència\". Tribunals, reguladors i investigadors estan examinant activament com aquestes eines afecten els drets fonamentals com la no discriminació, el judici just i la protecció de dades.",
254
- "s4eu_note": "<strong>Punt clau:</strong> Els riscos que vas veure amb COMPAS no són lluny en un altre país. <strong class='emph-key'>Són preguntes vives tant a Europa com als EUA en aquest moment.</strong>",
255
- "btn_back_invest": "◀️ Tornar a la Investigació",
256
- "btn_zoom": "Allunyar-se a la Lliçó ▶️",
257
- "s4_title": "💡 La Lliçó Crítica",
258
- "s4_box_title": "Per Què Importa Això:",
259
- "s4_li1_title": "La precisió general pot amagar danys específics a grups",
260
- "s4_li1_body": "Un model pot tenir un 70% de precisió general, però el 30% restant d'errors pot recaure desproporcionadament en <span class='emph-harm'>grups específics</span>, resultant en un dany real fins i tot quan la precisió total sembla \"bona\".",
283
+ "s4eu_note": "<strong>Punt clau:</strong> Els riscos que vas veure amb COMPAS no són lluny ni aliens. <strong class='emph-key'>Són qüestions plenament actuals tant a Europa com als EUA.</strong>",
284
+ "btn_back_invest": "◀️ Tornar a la investigació",
285
+ "btn_zoom": "Vista general de la Lliçó ▶️",
286
+ "s4_title": "💡 La lliçó crítica",
287
+ "s4_box_title": "Per què és important això:",
288
+ "s4_li1_title": "La precisió global d'un model pot amagar danys específics a grups concrets",
289
+ "s4_li1_body": "Un model pot tenir un 70% de precisió global, però el 30% restant d'errors pot recaure desproporcionadament en <span class='emph-harm'>determinats grups</span>, provocant danys reals fins i tot quan la precisió global sembla \"bona\".",
261
290
  "s4_li2_title": "El biaix històric en les dades d'entrenament s'amplifica",
262
- "s4_li2_body": "Si les decisions policials o judicials passades van ser esbiaixades, el sistema d'IA <span class='emph-harm'>aprendrà i reforçarà</span> aquestes desigualtats, sovint empitjorant-les a escala.",
291
+ "s4_li2_body": "Si les decisions policials o judicials passades van ser esbiaixades, el sistema d'IA <span class='emph-harm'>aprendrà i reforçarà</span> aquestes desigualtats, i sovint les amplificarà.",
263
292
  "s4_li3_title": "Les vides de persones reals es veuen afectades",
264
- "s4_li3_body": "Cada <strong class='emph-harm'>\"fals positiu\"</strong> representa una persona que pot perdre anys de llibertat, feina, habitatge o connexió familiar, tot a causa d'una sola <strong class='emph-harm'>predicció esbiaixada</strong>.",
293
+ "s4_li3_body": "Cada <strong class='emph-harm'>\"fals positiu\"</strong> representa una persona que pot perdre anys de llibertat, feina, habitatge o connexió familiar, tot per una única <strong class='emph-harm'>predicció esbiaixada</strong>.",
265
294
  "btn_back_eu": "◀️ Enrere",
266
- "btn_what_do": "Què Podem Fer? ▶️",
267
- "s5_title": "🛤️ El Camí a Seguir",
268
- "s5_head": "De la Precisió a l'Ètica",
269
- "s5_intro": "Ara has vist els dos costats de la història de la IA:",
270
- "s5_li1": "✅ Vas construir models que van aconseguir puntuacions de precisió més altes",
271
- "s5_li2": "⚠️ Vas aprendre com models similars van causar dany al món real",
295
+ "btn_what_do": "Què podem fer? ▶️",
296
+ "s5_title": "🛤️ El camí a seguir",
297
+ "s5_head": "De la precisió a l'ètica",
298
+ "s5_intro": "Ara ja has vist els dos costats de la IA:",
299
+ "s5_li1": "✅ Has construït models amb alts nivells de precisió",
300
+ "s5_li2": "⚠️ Has après com models similars han causat danys reals",
272
301
  "s5_li3": "🤔 Entens que la precisió per si sola no és suficient",
273
- "s5_box_title": "El Que Faràs A Continuació:",
302
+ "s5_box_title": "Què faràs a continuació:",
274
303
  "s5_p1": "En la següent secció, se't presentarà una <strong class='emph-key'>nova manera de mesurar l'èxit</strong>, una que equilibra el rendiment amb l'equitat i l'ètica.",
275
304
  "s5_p2": "Aprendràs tècniques per <strong class='emph-key'>detectar biaixos</strong> en els teus models, <strong class='emph-key'>mesurar l'equitat</strong> en diferents grups i <strong class='emph-key'>redissenyar la teva IA</strong> per minimitzar el dany.",
276
- "s5_mission": "🎯 La teva nova missió: Construir IA que no només sigui precisa, sinó també <strong class='emph-key'>justa, equitativa i èticament sòlida</strong>.",
305
+ "s5_mission": "🎯 La teva nova missió: Construir una IA que no només sigui precisa, sinó també <strong class='emph-key'>justa, equitativa i èticament sòlida</strong>.",
277
306
  "s5_scroll": "👇 DESPLAÇA'T CAP AVALL 👇",
278
- "s5_continue": "Continua a la següent secció a sota per començar el teu viatge d'IA ètica.",
307
+ "s5_continue": "Continua amb la següent secció per iniciar el teu recorregut cap a una IA ètica.",
279
308
  "btn_review": "◀️ Revisar la Investigació"
280
309
  }
281
310
  }
@@ -293,6 +322,48 @@ def _normalize_team_name(name: str) -> str:
293
322
  return ""
294
323
  return " ".join(str(name).strip().split())
295
324
 
325
+ # NEW: Team name translation helpers for UI display
326
+ def translate_team_name_for_display(team_en: str, lang: str = "en") -> str:
327
+ """
328
+ Translate a canonical English team name to the specified language for UI display.
329
+ Fallback to English if translation not found.
330
+ """
331
+ if lang not in TEAM_NAME_TRANSLATIONS:
332
+ lang = "en"
333
+ return TEAM_NAME_TRANSLATIONS[lang].get(team_en, team_en)
334
+
335
+ # NEW: Reverse lookup for future use (e.g., if user input needs to be normalized back to English)
336
+ def translate_team_name_to_english(display_name: str, lang: str = "en") -> str:
337
+ """
338
+ Reverse lookup: given a localized team name, return the canonical English name.
339
+ Returns the original display_name if not found.
340
+ """
341
+ if lang not in TEAM_NAME_TRANSLATIONS:
342
+ return display_name # Already English or unknown
343
+
344
+ translations = TEAM_NAME_TRANSLATIONS[lang]
345
+ for english_name, localized_name in translations.items():
346
+ if localized_name == display_name:
347
+ return english_name
348
+ return display_name # UPDATED: Return display_name instead of None for consistency
349
+
350
+ # NEW: Format leaderboard DataFrame with localized team names (non-destructive copy)
351
+ def _format_leaderboard_for_display(df: Optional[pd.DataFrame], lang: str = "en") -> Optional[pd.DataFrame]:
352
+ """
353
+ Create a copy of the leaderboard DataFrame with team names translated for display.
354
+ Does not mutate the original DataFrame.
355
+ For potential future use when displaying full leaderboard.
356
+ """
357
+ if df is None:
358
+ return None # UPDATED: Handle None explicitly
359
+
360
+ if df.empty or "Team" not in df.columns:
361
+ return df.copy() # UPDATED: Return copy for empty or missing Team column
362
+
363
+ df_display = df.copy()
364
+ df_display["Team"] = df_display["Team"].apply(lambda t: translate_team_name_for_display(t, lang))
365
+ return df_display
366
+
296
367
  def _fetch_leaderboard(token: str) -> Optional[pd.DataFrame]:
297
368
  now = time.time()
298
369
  with _cache_lock:
@@ -423,7 +494,8 @@ def build_stats_html(user_stats: Dict[str, Any], lang="en") -> str:
423
494
  if user_stats.get("best_score") is not None:
424
495
  best_score_pct = f"{(user_stats['best_score'] * 100):.1f}%"
425
496
  rank_text = f"#{user_stats['rank']}" if user_stats['rank'] else "N/A"
426
- team_text = user_stats['team_name'] if user_stats['team_name'] else "N/A"
497
+ # UPDATED: Translate team name for display based on selected language
498
+ team_text = translate_team_name_for_display(user_stats['team_name'], lang) if user_stats['team_name'] else "N/A"
427
499
  return f"""
428
500
  <div class='slide-shell slide-shell--primary'>
429
501
  <div style='text-align:center;'>
@@ -536,7 +608,6 @@ def _get_step3_html(lang):
536
608
  <ul style='font-size:1.05rem; line-height:1.8;'>
537
609
  <li>
538
610
  {t(lang, 's3_li1_pre')}
539
- <span class='emph-danger'> 45%</span>
540
611
  </li>
541
612
  <li>
542
613
  {t(lang, 's3_li2_pre')}
@@ -773,74 +844,93 @@ def create_ethical_revelation_app(theme_primary_hue: str = "indigo") -> "gr.Bloc
773
844
  loading_screen = gr.Column(visible=False)
774
845
  all_steps = [step_1, step_2, step_3, step_4_eu, step_4, step_5, loading_screen, initial_loading]
775
846
 
776
- # --- Initial Load with Language & Auth ---
777
- def initial_load(request: gr.Request):
778
- params = request.query_params
779
- lang = params.get("lang", "en")
780
- if lang not in TRANSLATIONS: lang = "en"
781
-
782
- # Try auth
783
- success, username, token = _try_session_based_auth(request)
784
-
785
- # Build Stats HTML (Translating inside)
786
- stats_html = ""
787
- if success and username:
788
- stats = _compute_user_stats(username, token)
789
- stats_html = build_stats_html(stats, lang)
790
- else:
791
- stats_html = f"""
792
- <div class='slide-shell slide-shell--primary' style='text-align:center;'>
793
- <h2 class='slide-shell__title'>{t(lang, 'loading_session')}</h2>
794
- </div>
795
- """
796
-
797
- # Return all UI updates
847
+ # -------------------------------------------------------------------------
848
+ # HYBRID CACHING LOGIC
849
+ # -------------------------------------------------------------------------
850
+
851
+ # 1. Define all targets that need updating
852
+ update_targets = [
853
+ initial_loading, step_1, stats_display, c_title, c_loading_text,
854
+ deploy_button,
855
+ c_s2_title, c_s2_html, step_2_back, step_2_next,
856
+ c_s3_title, c_s3_html, step_3_back, step_3_next,
857
+ c_s4eu_title, c_s4eu_html, step_4_eu_back, step_4_eu_next,
858
+ c_s4_title, c_s4_html, step_4_back, step_4_next,
859
+ c_s5_title, c_s5_html, back_to_lesson_btn
860
+ ]
861
+
862
+ # 2. Cached Generator for Static Content (Steps 2-5)
863
+ @lru_cache(maxsize=16)
864
+ def get_cached_static_content(lang):
865
+ """
866
+ Generates the heavy HTML for Steps 2, 3, 4, and 5 once per language.
867
+ """
798
868
  return [
799
- gr.update(visible=False), # initial_loading
800
- gr.update(visible=True), # step_1
801
- gr.update(value=stats_html), # stats_display
802
- # Title
803
- f"<h1 style='text-align:center;'>{t(lang, 'title')}</h1>",
804
- # Loading Text
805
- f"<div style='text-align:center; padding:80px 0;'><h2>{t(lang, 'loading_personal')}</h2></div>",
806
- # Step 1 Button
869
+ # Step 1 Button (Static Text)
807
870
  gr.Button(value=t(lang, 'btn_deploy')),
871
+
808
872
  # Step 2
809
873
  f"<h2 style='text-align:center;'>{t(lang, 's2_title')}</h2>",
810
874
  _get_step2_html(lang),
811
875
  gr.Button(value=t(lang, 'btn_back')),
812
876
  gr.Button(value=t(lang, 'btn_reveal')),
877
+
813
878
  # Step 3
814
879
  f"<h2 style='text-align:center;'>{t(lang, 's3_title')}</h2>",
815
880
  _get_step3_html(lang),
816
881
  gr.Button(value=t(lang, 'btn_back')),
817
882
  gr.Button(value=t(lang, 'btn_eu')),
883
+
818
884
  # Step 4 EU
819
885
  f"<h2 style='text-align:center;'>{t(lang, 's4eu_title')}</h2>",
820
886
  _get_step4_eu_html(lang),
821
887
  gr.Button(value=t(lang, 'btn_back_invest')),
822
888
  gr.Button(value=t(lang, 'btn_zoom')),
889
+
823
890
  # Step 4 Lesson
824
891
  f"<h2 style='text-align:center;'>{t(lang, 's4_title')}</h2>",
825
892
  _get_step4_lesson_html(lang),
826
893
  gr.Button(value=t(lang, 'btn_back_eu')),
827
894
  gr.Button(value=t(lang, 'btn_what_do')),
895
+
828
896
  # Step 5
829
897
  f"<h2 style='text-align:center;'>{t(lang, 's5_title')}</h2>",
830
898
  _get_step5_html(lang),
831
899
  gr.Button(value=t(lang, 'btn_review'))
832
900
  ]
833
901
 
834
- # Load trigger
835
- update_targets = [
836
- initial_loading, step_1, stats_display, c_title, c_loading_text,
837
- deploy_button,
838
- c_s2_title, c_s2_html, step_2_back, step_2_next,
839
- c_s3_title, c_s3_html, step_3_back, step_3_next,
840
- c_s4eu_title, c_s4eu_html, step_4_eu_back, step_4_eu_next,
841
- c_s4_title, c_s4_html, step_4_back, step_4_next,
842
- c_s5_title, c_s5_html, back_to_lesson_btn
843
- ]
902
+ # 3. Hybrid Load Function
903
+ def initial_load(request: gr.Request):
904
+ params = request.query_params
905
+ lang = params.get("lang", "en")
906
+ if lang not in TRANSLATIONS: lang = "en"
907
+
908
+ # --- DYNAMIC PART (Runs every time) ---
909
+ success, username, token = _try_session_based_auth(request)
910
+
911
+ stats_html = ""
912
+ if success and username:
913
+ stats = _compute_user_stats(username, token)
914
+ stats_html = build_stats_html(stats, lang)
915
+ else:
916
+ stats_html = f"""
917
+ <div class='slide-shell slide-shell--primary' style='text-align:center;'>
918
+ <h2 class='slide-shell__title'>{t(lang, 'loading_session')}</h2>
919
+ </div>
920
+ """
921
+
922
+ # --- STATIC PART (Fetched from Cache) ---
923
+ static_updates = get_cached_static_content(lang)
924
+
925
+ # Combine: Dynamic + Static
926
+ return [
927
+ gr.update(visible=False), # initial_loading
928
+ gr.update(visible=True), # step_1
929
+ gr.update(value=stats_html), # stats_display (DYNAMIC)
930
+ f"<h1 style='text-align:center;'>{t(lang, 'title')}</h1>", # Title
931
+ f"<div style='text-align:center; padding:80px 0;'><h2>{t(lang, 'loading_personal')}</h2></div>", # Loading Text
932
+ ] + static_updates
933
+
844
934
  demo.load(fn=initial_load, inputs=None, outputs=update_targets)
845
935
 
846
936
  # --- Navigation Logic ---