AIdeaText commited on
Commit
262493d
·
verified ·
1 Parent(s): 99029e0

Upload 4 files

Browse files
modules/studentact/claude_recommendations.py CHANGED
@@ -29,6 +29,11 @@ TEXT_TYPES = {
29
  'academic_article': 'article académique',
30
  'university_work': 'travail universitaire',
31
  'general_communication': 'communication générale'
 
 
 
 
 
32
  }
33
  }
34
 
@@ -102,6 +107,51 @@ def generate_claude_recommendations(text, metrics, text_type, lang_code):
102
  4. Una sugerencia sobre qué herramienta de AIdeaText usar (Análisis Morfosintáctico, Análisis Semántico o Análisis del Discurso)
103
 
104
  Tu respuesta debe ser concisa y no exceder los 300 palabras."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  else:
106
  # Default to English
107
  system_prompt = """You are an assistant specialized in analyzing academic texts and written communication.
@@ -152,6 +202,8 @@ def generate_claude_recommendations(text, metrics, text_type, lang_code):
152
  logger.error(f"Error generating recommendations with Claude: {str(e)}")
153
  return get_fallback_recommendations(lang_code)
154
 
 
 
155
  def get_fallback_recommendations(lang_code):
156
  """
157
  Return fallback recommendations if Claude API fails
@@ -160,16 +212,45 @@ def get_fallback_recommendations(lang_code):
160
  return """
161
  **Análisis General**
162
  Tu texto presenta una estructura básica adecuada, pero hay áreas que pueden mejorarse para mayor claridad y cohesión.
163
-
164
  **Recomendaciones**:
165
  - Intenta variar tu vocabulario para evitar repeticiones innecesarias
166
  - Considera revisar la longitud de tus oraciones para mantener un mejor ritmo
167
  - Asegúrate de establecer conexiones claras entre las ideas principales
168
  - Revisa la consistencia en el uso de tiempos verbales
169
-
170
  **Herramienta recomendada**:
171
  Te sugerimos utilizar el Análisis Morfosintáctico para identificar patrones en tu estructura de oraciones.
172
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  else:
174
  return """
175
  **General Analysis**
@@ -187,7 +268,7 @@ def get_fallback_recommendations(lang_code):
187
 
188
 
189
  #######################################
190
-
191
  def store_recommendations(username, text, metrics, text_type, recommendations):
192
  """
193
  Store the recommendations in the database
 
29
  'academic_article': 'article académique',
30
  'university_work': 'travail universitaire',
31
  'general_communication': 'communication générale'
32
+ },
33
+ 'pt': {
34
+ 'academic_article': 'artigo acadêmico',
35
+ 'university_work': 'trabalho universitário',
36
+ 'general_communication': 'comunicação geral'
37
  }
38
  }
39
 
 
107
  4. Una sugerencia sobre qué herramienta de AIdeaText usar (Análisis Morfosintáctico, Análisis Semántico o Análisis del Discurso)
108
 
109
  Tu respuesta debe ser concisa y no exceder los 300 palabras."""
110
+
111
+ elif lang_code == 'fr':
112
+ system_prompt = """Vous êtes un assistant spécialisé dans l'analyse de textes académiques et de communication écrite.
113
+ Votre tâche est d'analyser le texte de l'utilisateur et de fournir des recommandations personnalisées.
114
+ Utilisez un ton constructif et spécifique. Soyez clair et direct dans vos suggestions.
115
+ """
116
+ user_prompt = f"""Veuillez analyser ce texte de type '{formatted_metrics['text_type']}'
117
+ et fournir des recommandations personnalisées pour l'améliorer.
118
+
119
+ MÉTRIQUES D'ANALYSE:
120
+ {json.dumps(formatted_metrics, indent=2, ensure_ascii=False)}
121
+
122
+ TEXTE À ANALYSER:
123
+ {text[:2000]}
124
+
125
+ Fournissez votre analyse avec le format suivant:
126
+ 1. Un résumé bref (2-3 phrases) de l'analyse générale
127
+ 2. 3-4 recommandations spécifiques et réalisables (chacune de 1-2 phrases)
128
+ 3. Un exemple concret d'amélioration tiré du texte même de l'utilisateur
129
+ 4. Une suggestion sur quel outil AIdeaText utiliser (Analyse Morphosyntaxique, Analyse Sémantique ou Analyse du Discours)
130
+
131
+ Votre réponse doit être concise et ne pas dépasser 300 mots."""
132
+
133
+ elif lang_code == 'pt':
134
+ system_prompt = """Você é um assistente especializado na análise de textos acadêmicos e comunicação escrita.
135
+ Sua tarefa é analisar o texto do usuário e fornecer recomendações personalizadas.
136
+ Use um tom construtivo e específico. Seja claro e direto com suas sugestões.
137
+ """
138
+ user_prompt = f"""Por favor, analise este texto do tipo '{formatted_metrics['text_type']}'
139
+ e forneça recomendações personalizadas para melhorá-lo.
140
+
141
+ MÉTRICAS DE ANÁLISE:
142
+ {json.dumps(formatted_metrics, indent=2, ensure_ascii=False)}
143
+
144
+ TEXTO PARA ANALISAR:
145
+ {text[:2000]}
146
+
147
+ Forneça sua análise com o seguinte formato:
148
+ 1. Um breve resumo (2-3 frases) da análise geral
149
+ 2. 3-4 recomendações específicas e acionáveis (cada uma com 1-2 frases)
150
+ 3. Um exemplo concreto de melhoria retirado do próprio texto do usuário
151
+ 4. Uma sugestão sobre qual ferramenta do AIdeaText usar (Análise Morfossintática, Análise Semântica ou Análise do Discurso)
152
+
153
+ Sua resposta deve ser concisa e não exceder 300 palavras."""
154
+
155
  else:
156
  # Default to English
157
  system_prompt = """You are an assistant specialized in analyzing academic texts and written communication.
 
202
  logger.error(f"Error generating recommendations with Claude: {str(e)}")
203
  return get_fallback_recommendations(lang_code)
204
 
205
+ ##################################################################################
206
+ ##################################################################################
207
  def get_fallback_recommendations(lang_code):
208
  """
209
  Return fallback recommendations if Claude API fails
 
212
  return """
213
  **Análisis General**
214
  Tu texto presenta una estructura básica adecuada, pero hay áreas que pueden mejorarse para mayor claridad y cohesión.
 
215
  **Recomendaciones**:
216
  - Intenta variar tu vocabulario para evitar repeticiones innecesarias
217
  - Considera revisar la longitud de tus oraciones para mantener un mejor ritmo
218
  - Asegúrate de establecer conexiones claras entre las ideas principales
219
  - Revisa la consistencia en el uso de tiempos verbales
 
220
  **Herramienta recomendada**:
221
  Te sugerimos utilizar el Análisis Morfosintáctico para identificar patrones en tu estructura de oraciones.
222
  """
223
+
224
+ elif lang_code == 'fr':
225
+ return """
226
+ **Analyse Générale**
227
+ Votre texte présente une structure de base adéquate, mais certains aspects pourraient être améliorés pour plus de clarté et de cohésion.
228
+
229
+ **Recommandations**:
230
+ - Essayez de varier votre vocabulaire pour éviter les répétitions inutiles
231
+ - Envisagez de revoir la longueur de vos phrases pour maintenir un meilleur rythme
232
+ - Assurez-vous d'établir des liens clairs entre les idées principales
233
+ - Vérifiez la cohérence dans l'utilisation des temps verbaux
234
+
235
+ **Outil recommandé**:
236
+ Nous vous suggérons d'utiliser l'Analyse Morphosyntaxique pour identifier les modèles dans la structure de vos phrases.
237
+ """
238
+
239
+ elif lang_code == 'pt':
240
+ return """
241
+ **Análise Geral**
242
+ Seu texto apresenta uma estrutura básica adequada, mas há áreas que podem ser melhoradas para maior clareza e coesão.
243
+
244
+ **Recomendações**:
245
+ - Tente variar seu vocabulário para evitar repetições desnecessárias
246
+ - Considere revisar o comprimento de suas frases para manter um melhor ritmo
247
+ - Certifique-se de estabelecer conexões claras entre as ideias principais
248
+ - Revise a consistência no uso dos tempos verbais
249
+
250
+ **Ferramenta recomendada**:
251
+ Sugerimos utilizar a Análise Morfossintática para identificar padrões na sua estrutura de frases.
252
+ """
253
+
254
  else:
255
  return """
256
  **General Analysis**
 
268
 
269
 
270
  #######################################
271
+ #######################################
272
  def store_recommendations(username, text, metrics, text_type, recommendations):
273
  """
274
  Store the recommendations in the database
modules/studentact/current_situation_analysis.py CHANGED
@@ -10,7 +10,6 @@ import numpy as np
10
  import matplotlib.patches as patches
11
  import logging
12
 
13
- from translations.recommendations import RECOMMENDATIONS
14
 
15
  # 2. Configuración básica del logging
16
  logging.basicConfig(
@@ -622,6 +621,7 @@ def normalize_score(value, metric_type,
622
 
623
  #########################################################################
624
  #########################################################################
 
625
  def generate_recommendations(metrics, text_type, lang_code='es'):
626
  """
627
  Genera recomendaciones personalizadas basadas en las métricas del texto y el tipo de texto.
@@ -629,12 +629,18 @@ def generate_recommendations(metrics, text_type, lang_code='es'):
629
  Args:
630
  metrics: Diccionario con las métricas analizadas
631
  text_type: Tipo de texto ('academic_article', 'student_essay', 'general_communication')
632
- lang_code: Código del idioma para las recomendaciones (es, en, fr, pt)
633
 
634
  Returns:
635
  dict: Recomendaciones organizadas por categoría en el idioma correspondiente
636
  """
637
  try:
 
 
 
 
 
 
638
  # Obtener umbrales según el tipo de texto
639
  thresholds = TEXT_TYPES[text_type]['thresholds']
640
 
@@ -701,17 +707,17 @@ def generate_recommendations(metrics, text_type, lang_code='es'):
701
 
702
  except Exception as e:
703
  logger.error(f"Error en generate_recommendations: {str(e)}")
704
- # Retornar mensajes genéricos en caso de error
705
- if lang_code == 'en':
706
- return {
707
- 'vocabulary': ["Try enriching your vocabulary"],
708
- 'structure': ["Work on the structure of your sentences"],
709
- 'cohesion': ["Improve the connection between your ideas"],
710
- 'clarity': ["Try to express your ideas more clearly"],
711
- 'specific': ["Adapt your text according to its purpose"],
712
- 'priority': {
713
- 'area': 'general',
714
- 'tips': ["Seek specific feedback from a tutor or teacher"]
715
  },
716
  'dimension_names': {
717
  'vocabulary': 'Vocabulary',
@@ -728,71 +734,38 @@ def generate_recommendations(metrics, text_type, lang_code='es'):
728
  'save_error': "Error saving analysis",
729
  'area_priority': "Priority area"
730
  }
731
- }
732
- elif lang_code == 'fr':
733
- return {
734
- 'vocabulary': ["Essayez d'enrichir votre vocabulaire"],
735
- 'structure': ["Travaillez sur la structure de vos phrases"],
736
- 'cohesion': ["Améliorez la connexion entre vos idées"],
737
- 'clarity': ["Essayez d'exprimer vos idées plus clairement"],
738
- 'specific': ["Adaptez votre texte en fonction de son objectif"],
739
- 'priority': {
740
- 'area': 'general',
741
- 'tips': ["Demandez des commentaires spécifiques à un tuteur ou un professeur"]
742
- },
743
- 'dimension_names': {
744
- 'vocabulary': 'Vocabulaire',
745
- 'structure': 'Structure',
746
- 'cohesion': 'Cohésion',
747
- 'clarity': 'Clarté',
748
- 'general': 'Général'
749
- },
750
- 'ui_text': {
751
- 'priority_intro': "C'est là que vous devriez concentrer vos efforts.",
752
- 'detailed_recommendations': "Recommandations détaillées",
753
- 'save_button': "Enregistrer l'analyse",
754
- 'save_success': "Analyse enregistrée avec succès",
755
- 'save_error': "Erreur lors de l'enregistrement de l'analyse",
756
- 'area_priority': "Domaine prioritaire"
757
- }
758
- }
759
- elif lang_code == 'pt':
760
- return {
761
- 'vocabulary': ["Tente enriquecer seu vocabulário"],
762
- 'structure': ["Trabalhe na estrutura de suas frases"],
763
- 'cohesion': ["Melhore a conexão entre suas ideias"],
764
- 'clarity': ["Tente expressar suas ideias com mais clareza"],
765
- 'specific': ["Adapte seu texto de acordo com seu propósito"],
766
- 'priority': {
767
- 'area': 'general',
768
- 'tips': ["Busque feedback específico de um tutor ou professor"]
769
  },
770
  'dimension_names': {
771
- 'vocabulary': 'Vocabulário',
772
- 'structure': 'Estrutura',
773
- 'cohesion': 'Coesão',
774
- 'clarity': 'Clareza',
775
- 'general': 'Geral'
776
  },
777
  'ui_text': {
778
- 'priority_intro': "É aqui que você deve concentrar seus esforços.",
779
- 'detailed_recommendations': "Recomendações detalhadas",
780
- 'save_button': "Salvar análise",
781
- 'save_success': "Análise salva com sucesso",
782
- 'save_error': "Erro ao salvar análise",
783
- 'area_priority': "Área prioritária"
784
  }
785
- }
786
- else: # Español por defecto
787
- return {
788
- 'vocabulary': ["Intenta enriquecer tu vocabulario"],
789
- 'structure': ["Trabaja en la estructura de tus oraciones"],
790
- 'cohesion': ["Mejora la conexión entre tus ideas"],
791
- 'clarity': ["Busca expresar tus ideas con mayor claridad"],
792
- 'specific': ["Adapta tu texto según su propósito"],
793
- 'priority': {
794
- 'area': 'general',
795
- 'tips': ["Busca retroalimentación específica de un tutor o profesor"]
796
  },
797
  'dimension_names': {
798
  'vocabulary': 'Vocabulario',
@@ -810,6 +783,30 @@ def generate_recommendations(metrics, text_type, lang_code='es'):
810
  'area_priority': "Área prioritaria"
811
  }
812
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
813
 
814
 
815
  #########################################################################
@@ -822,6 +819,7 @@ def generate_sentence_graphs(doc):
822
  plt.close()
823
  return fig
824
 
 
825
  def generate_word_connections(doc):
826
  """Genera red de conexiones de palabras"""
827
  fig, ax = plt.subplots(figsize=(10, 6))
@@ -829,6 +827,7 @@ def generate_word_connections(doc):
829
  plt.close()
830
  return fig
831
 
 
832
  def generate_connection_paths(doc):
833
  """Genera patrones de conexión"""
834
  fig, ax = plt.subplots(figsize=(10, 6))
@@ -836,6 +835,7 @@ def generate_connection_paths(doc):
836
  plt.close()
837
  return fig
838
 
 
839
  def create_vocabulary_network(doc):
840
  """
841
  Genera el grafo de red de vocabulario.
@@ -882,6 +882,7 @@ def create_vocabulary_network(doc):
882
  plt.axis('off')
883
  return fig
884
 
 
885
  def create_syntax_complexity_graph(doc):
886
  """
887
  Genera el diagrama de arco de complejidad sintáctica.
@@ -961,7 +962,7 @@ def create_syntax_complexity_graph(doc):
961
  logger.error(f"Error en create_syntax_complexity_graph: {str(e)}")
962
  return None
963
 
964
-
965
  def create_cohesion_heatmap(doc):
966
  """Genera un mapa de calor que muestra la cohesión entre párrafos/oraciones."""
967
  try:
@@ -1005,4 +1006,4 @@ def create_cohesion_heatmap(doc):
1005
 
1006
  except Exception as e:
1007
  logger.error(f"Error en create_cohesion_heatmap: {str(e)}")
1008
- return None
 
10
  import matplotlib.patches as patches
11
  import logging
12
 
 
13
 
14
  # 2. Configuración básica del logging
15
  logging.basicConfig(
 
621
 
622
  #########################################################################
623
  #########################################################################
624
+
625
  def generate_recommendations(metrics, text_type, lang_code='es'):
626
  """
627
  Genera recomendaciones personalizadas basadas en las métricas del texto y el tipo de texto.
 
629
  Args:
630
  metrics: Diccionario con las métricas analizadas
631
  text_type: Tipo de texto ('academic_article', 'student_essay', 'general_communication')
632
+ lang_code: Código del idioma para las recomendaciones (es, en, uk)
633
 
634
  Returns:
635
  dict: Recomendaciones organizadas por categoría en el idioma correspondiente
636
  """
637
  try:
638
+ # Añadir debug log para verificar el código de idioma recibido
639
+ logger.info(f"generate_recommendations llamado con idioma: {lang_code}")
640
+
641
+ # Comprobar que importamos RECOMMENDATIONS correctamente
642
+ logger.info(f"Idiomas disponibles en RECOMMENDATIONS: {list(RECOMMENDATIONS.keys())}")
643
+
644
  # Obtener umbrales según el tipo de texto
645
  thresholds = TEXT_TYPES[text_type]['thresholds']
646
 
 
707
 
708
  except Exception as e:
709
  logger.error(f"Error en generate_recommendations: {str(e)}")
710
+
711
+ # Utilizar un enfoque basado en el idioma actual en lugar de casos codificados
712
+ # Esto permite manejar ucraniano y cualquier otro idioma futuro
713
+ fallback_translations = {
714
+ 'en': {
715
+ 'basic_recommendations': {
716
+ 'vocabulary': ["Try enriching your vocabulary"],
717
+ 'structure': ["Work on the structure of your sentences"],
718
+ 'cohesion': ["Improve the connection between your ideas"],
719
+ 'clarity': ["Try to express your ideas more clearly"],
720
+ 'specific': ["Adapt your text according to its purpose"],
721
  },
722
  'dimension_names': {
723
  'vocabulary': 'Vocabulary',
 
734
  'save_error': "Error saving analysis",
735
  'area_priority': "Priority area"
736
  }
737
+ },
738
+ 'uk': {
739
+ 'basic_recommendations': {
740
+ 'vocabulary': ["Розширте свій словниковий запас"],
741
+ 'structure': ["Покращіть структуру ваших речень"],
742
+ 'cohesion': ["Покращіть зв'язок між вашими ідеями"],
743
+ 'clarity': ["Висловлюйте свої ідеї ясніше"],
744
+ 'specific': ["Адаптуйте свій текст відповідно до його мети"],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
745
  },
746
  'dimension_names': {
747
+ 'vocabulary': 'Словниковий запас',
748
+ 'structure': 'Структура',
749
+ 'cohesion': 'Зв\'язність',
750
+ 'clarity': 'Ясність',
751
+ 'general': 'Загальне'
752
  },
753
  'ui_text': {
754
+ 'priority_intro': "Це область, де ви повинні зосередити свої зусилля.",
755
+ 'detailed_recommendations': "Детальні рекомендації",
756
+ 'save_button': "Зберегти аналіз",
757
+ 'save_success': "Аналіз успішно збережено",
758
+ 'save_error': "Помилка при збереженні аналізу",
759
+ 'area_priority': "Пріоритетна область"
760
  }
761
+ },
762
+ 'es': {
763
+ 'basic_recommendations': {
764
+ 'vocabulary': ["Intenta enriquecer tu vocabulario"],
765
+ 'structure': ["Trabaja en la estructura de tus oraciones"],
766
+ 'cohesion': ["Mejora la conexión entre tus ideas"],
767
+ 'clarity': ["Busca expresar tus ideas con mayor claridad"],
768
+ 'specific': ["Adapta tu texto según su propósito"],
 
 
 
769
  },
770
  'dimension_names': {
771
  'vocabulary': 'Vocabulario',
 
783
  'area_priority': "Área prioritaria"
784
  }
785
  }
786
+ }
787
+
788
+ # Usar el idioma actual si está disponible, o inglés, o español como última opción
789
+ current_lang = fallback_translations.get(lang_code,
790
+ fallback_translations.get('en',
791
+ fallback_translations['es']))
792
+
793
+ basic_recommendations = current_lang['basic_recommendations']
794
+
795
+ return {
796
+ 'vocabulary': basic_recommendations['vocabulary'],
797
+ 'structure': basic_recommendations['structure'],
798
+ 'cohesion': basic_recommendations['cohesion'],
799
+ 'clarity': basic_recommendations['clarity'],
800
+ 'specific': basic_recommendations['specific'],
801
+ 'priority': {
802
+ 'area': 'general',
803
+ 'tips': ["Busca retroalimentación específica de un tutor o profesor"]
804
+ },
805
+ 'dimension_names': current_lang['dimension_names'],
806
+ 'ui_text': current_lang['ui_text']
807
+ }
808
+
809
+
810
 
811
 
812
  #########################################################################
 
819
  plt.close()
820
  return fig
821
 
822
+ ############################################################################
823
  def generate_word_connections(doc):
824
  """Genera red de conexiones de palabras"""
825
  fig, ax = plt.subplots(figsize=(10, 6))
 
827
  plt.close()
828
  return fig
829
 
830
+ ############################################################################
831
  def generate_connection_paths(doc):
832
  """Genera patrones de conexión"""
833
  fig, ax = plt.subplots(figsize=(10, 6))
 
835
  plt.close()
836
  return fig
837
 
838
+ ############################################################################
839
  def create_vocabulary_network(doc):
840
  """
841
  Genera el grafo de red de vocabulario.
 
882
  plt.axis('off')
883
  return fig
884
 
885
+ ############################################################################
886
  def create_syntax_complexity_graph(doc):
887
  """
888
  Genera el diagrama de arco de complejidad sintáctica.
 
962
  logger.error(f"Error en create_syntax_complexity_graph: {str(e)}")
963
  return None
964
 
965
+ ############################################################################
966
  def create_cohesion_heatmap(doc):
967
  """Genera un mapa de calor que muestra la cohesión entre párrafos/oraciones."""
968
  try:
 
1006
 
1007
  except Exception as e:
1008
  logger.error(f"Error en create_cohesion_heatmap: {str(e)}")
1009
+ return None
modules/studentact/current_situation_interface.py CHANGED
@@ -16,7 +16,9 @@ try:
16
  except ImportError:
17
  # Si no existe el módulo, definimos una función placeholder
18
  def display_personalized_recommendations(text, metrics, text_type, lang_code, t):
19
- st.warning("Módulo de recomendaciones personalizadas no disponible. Por favor, contacte al administrador.")
 
 
20
 
21
  from .current_situation_analysis import (
22
  analyze_text_dimensions,
@@ -42,11 +44,10 @@ plt.rcParams['axes.spines.right'] = False
42
 
43
  logger = logging.getLogger(__name__)
44
 
45
- ####################################
46
- # Definición global de los tipos de texto y sus umbrales
47
  TEXT_TYPES = {
48
  'academic_article': {
49
- 'name': 'Artículo Académico',
50
  'thresholds': {
51
  'vocabulary': {'min': 0.70, 'target': 0.85},
52
  'structure': {'min': 0.75, 'target': 0.90},
@@ -55,7 +56,6 @@ TEXT_TYPES = {
55
  }
56
  },
57
  'student_essay': {
58
- 'name': 'Trabajo Universitario',
59
  'thresholds': {
60
  'vocabulary': {'min': 0.60, 'target': 0.75},
61
  'structure': {'min': 0.65, 'target': 0.80},
@@ -64,7 +64,6 @@ TEXT_TYPES = {
64
  }
65
  },
66
  'general_communication': {
67
- 'name': 'Comunicación General',
68
  'thresholds': {
69
  'vocabulary': {'min': 0.50, 'target': 0.65},
70
  'structure': {'min': 0.55, 'target': 0.70},
@@ -73,16 +72,21 @@ TEXT_TYPES = {
73
  }
74
  }
75
  }
76
- ####################################
77
 
 
 
78
  def display_current_situation_interface(lang_code, nlp_models, t):
79
  """
80
  Interfaz simplificada con gráfico de radar para visualizar métricas.
81
  """
 
 
 
 
82
  # Inicializar estados si no existen
83
  if 'text_input' not in st.session_state:
84
  st.session_state.text_input = ""
85
- if 'text_area' not in st.session_state: # Añadir inicialización de text_area
86
  st.session_state.text_area = ""
87
  if 'show_results' not in st.session_state:
88
  st.session_state.show_results = False
@@ -97,30 +101,64 @@ def display_current_situation_interface(lang_code, nlp_models, t):
97
  # Container principal con dos columnas
98
  with st.container():
99
  input_col, results_col = st.columns([1,2])
100
-
101
- with input_col:
102
- # Text area con manejo de estado
103
- text_input = st.text_area(
104
- t.get('input_prompt', "Escribe o pega tu texto aquí:"),
105
- height=400,
106
- key="text_area",
107
- value=st.session_state.text_input,
108
- help="Este texto será analizado para darte recomendaciones personalizadas"
109
- )
 
 
 
 
 
 
 
110
 
111
- # Función para manejar cambios de texto
112
- if text_input != st.session_state.text_input:
113
- st.session_state.text_input = text_input
114
- st.session_state.show_results = False
 
 
115
 
116
- if st.button(
117
- t.get('analyze_button', "Analizar mi escritura"),
118
- type="primary",
119
- disabled=not text_input.strip(),
120
- use_container_width=True,
121
- ):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  try:
123
- with st.spinner(t.get('processing', "Analizando...")):
124
  doc = nlp_models[lang_code](text_input)
125
  metrics = analyze_text_dimensions(doc)
126
 
@@ -140,33 +178,50 @@ def display_current_situation_interface(lang_code, nlp_models, t):
140
 
141
  except Exception as e:
142
  logger.error(f"Error en análisis: {str(e)}")
143
- st.error(t.get('analysis_error', "Error al analizar el texto"))
144
 
145
  # Mostrar resultados en la columna derecha
146
  with results_col:
147
  if st.session_state.show_results and st.session_state.current_metrics is not None:
148
- # Primero los radio buttons para tipo de texto
149
- st.markdown("### Tipo de texto")
 
 
 
 
 
 
 
 
 
 
 
 
150
  text_type = st.radio(
151
- label="Tipo de texto",
152
  options=list(TEXT_TYPES.keys()),
153
- format_func=lambda x: TEXT_TYPES[x]['name'],
154
  horizontal=True,
155
  key="text_type_radio",
156
  label_visibility="collapsed",
157
- help="Selecciona el tipo de texto para ajustar los criterios de evaluación"
158
  )
159
 
160
  st.session_state.current_text_type = text_type
161
 
162
- # Crear subtabs
163
- subtab1, subtab2 = st.tabs(["Diagnóstico", "Recomendaciones"])
 
 
 
164
 
165
  # Mostrar resultados en el primer subtab
166
  with subtab1:
167
  display_diagnosis(
168
  metrics=st.session_state.current_metrics,
169
- text_type=text_type
 
 
170
  )
171
 
172
  # Mostrar recomendaciones en el segundo subtab
@@ -182,13 +237,59 @@ def display_current_situation_interface(lang_code, nlp_models, t):
182
 
183
  except Exception as e:
184
  logger.error(f"Error en interfaz principal: {str(e)}")
185
- st.error("Ocurrió un error al cargar la interfaz")
186
 
187
- def display_diagnosis(metrics, text_type=None):
 
 
188
  """
189
  Muestra los resultados del análisis: métricas verticalmente y gráfico radar.
190
  """
191
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  # Usar valor por defecto si no se especifica tipo
193
  text_type = text_type or 'student_essay'
194
 
@@ -202,52 +303,54 @@ def display_diagnosis(metrics, text_type=None):
202
  with metrics_col:
203
  metrics_config = [
204
  {
205
- 'label': "Vocabulario",
206
  'key': 'vocabulary',
207
  'value': metrics['vocabulary']['normalized_score'],
208
- 'help': "Riqueza y variedad del vocabulario",
209
  'thresholds': thresholds['vocabulary']
210
  },
211
  {
212
- 'label': "Estructura",
213
  'key': 'structure',
214
  'value': metrics['structure']['normalized_score'],
215
- 'help': "Organización y complejidad de oraciones",
216
  'thresholds': thresholds['structure']
217
  },
218
  {
219
- 'label': "Cohesión",
220
  'key': 'cohesion',
221
  'value': metrics['cohesion']['normalized_score'],
222
- 'help': "Conexión y fluidez entre ideas",
223
  'thresholds': thresholds['cohesion']
224
  },
225
  {
226
- 'label': "Claridad",
227
  'key': 'clarity',
228
  'value': metrics['clarity']['normalized_score'],
229
- 'help': "Facilidad de comprensión del texto",
230
  'thresholds': thresholds['clarity']
231
  }
232
  ]
233
 
234
- # Mostrar métricas
235
  for metric in metrics_config:
236
  value = metric['value']
237
  if value < metric['thresholds']['min']:
238
- status = "⚠️ Por mejorar"
239
  color = "inverse"
240
  elif value < metric['thresholds']['target']:
241
- status = "📈 Aceptable"
242
  color = "off"
243
  else:
244
- status = "✅ Óptimo"
245
  color = "normal"
246
 
 
 
247
  st.metric(
248
  metric['label'],
249
  f"{value:.2f}",
250
- f"{status} (Meta: {metric['thresholds']['target']:.2f})",
251
  delta_color=color,
252
  help=metric['help']
253
  )
@@ -255,17 +358,29 @@ def display_diagnosis(metrics, text_type=None):
255
 
256
  # Gráfico radar en la columna derecha
257
  with graph_col:
258
- display_radar_chart(metrics_config, thresholds)
259
 
260
  except Exception as e:
261
  logger.error(f"Error mostrando resultados: {str(e)}")
262
- st.error("Error al mostrar los resultados")
263
 
264
- def display_radar_chart(metrics_config, thresholds):
 
 
265
  """
266
  Muestra el gráfico radar con los resultados.
267
  """
268
  try:
 
 
 
 
 
 
 
 
 
 
269
  # Preparar datos para el gráfico
270
  categories = [m['label'] for m in metrics_config]
271
  values_user = [m['value'] for m in metrics_config]
@@ -291,14 +406,14 @@ def display_radar_chart(metrics_config, thresholds):
291
  ax.set_yticklabels([f'{tick:.1f}' for tick in circle_ticks], fontsize=8)
292
  ax.set_ylim(0, 1)
293
 
294
- # Dibujar áreas de umbrales
295
- ax.plot(angles, min_values, '#e74c3c', linestyle='--', linewidth=1, label='Mínimo', alpha=0.5)
296
- ax.plot(angles, target_values, '#2ecc71', linestyle='--', linewidth=1, label='Meta', alpha=0.5)
297
  ax.fill_between(angles, target_values, [1]*len(angles), color='#2ecc71', alpha=0.1)
298
  ax.fill_between(angles, [0]*len(angles), min_values, color='#e74c3c', alpha=0.1)
299
 
300
- # Dibujar valores del usuario
301
- ax.plot(angles, values_user, '#3498db', linewidth=2, label='Tu escritura')
302
  ax.fill(angles, values_user, '#3498db', alpha=0.2)
303
 
304
  # Ajustar leyenda
 
16
  except ImportError:
17
  # Si no existe el módulo, definimos una función placeholder
18
  def display_personalized_recommendations(text, metrics, text_type, lang_code, t):
19
+ # Obtener el mensaje de advertencia traducido si está disponible
20
+ warning = t.get('module_not_available', "Módulo de recomendaciones personalizadas no disponible. Por favor, contacte al administrador.")
21
+ st.warning(warning)
22
 
23
  from .current_situation_analysis import (
24
  analyze_text_dimensions,
 
44
 
45
  logger = logging.getLogger(__name__)
46
 
47
+ # Definición de tipos de texto con umbrales
 
48
  TEXT_TYPES = {
49
  'academic_article': {
50
+ # Los nombres se obtendrán de las traducciones
51
  'thresholds': {
52
  'vocabulary': {'min': 0.70, 'target': 0.85},
53
  'structure': {'min': 0.75, 'target': 0.90},
 
56
  }
57
  },
58
  'student_essay': {
 
59
  'thresholds': {
60
  'vocabulary': {'min': 0.60, 'target': 0.75},
61
  'structure': {'min': 0.65, 'target': 0.80},
 
64
  }
65
  },
66
  'general_communication': {
 
67
  'thresholds': {
68
  'vocabulary': {'min': 0.50, 'target': 0.65},
69
  'structure': {'min': 0.55, 'target': 0.70},
 
72
  }
73
  }
74
  }
 
75
 
76
+ ####################################################
77
+ ####################################################
78
  def display_current_situation_interface(lang_code, nlp_models, t):
79
  """
80
  Interfaz simplificada con gráfico de radar para visualizar métricas.
81
  """
82
+ # Agregar logs para depuración
83
+ logger.info(f"Idioma: {lang_code}")
84
+ logger.info(f"Claves en t: {list(t.keys())}")
85
+
86
  # Inicializar estados si no existen
87
  if 'text_input' not in st.session_state:
88
  st.session_state.text_input = ""
89
+ if 'text_area' not in st.session_state:
90
  st.session_state.text_area = ""
91
  if 'show_results' not in st.session_state:
92
  st.session_state.show_results = False
 
101
  # Container principal con dos columnas
102
  with st.container():
103
  input_col, results_col = st.columns([1,2])
104
+
105
+ ###############################################################################################
106
+ # CSS personalizado para que el formulario ocupe todo el alto disponible
107
+ st.markdown("""
108
+ <style>
109
+ /* Hacer que la columna tenga una altura definida */
110
+ [data-testid="column"] {
111
+ min-height: 900px;
112
+ height: 100vh; /* 100% del alto visible de la ventana */
113
+ }
114
+
115
+ /* Hacer que el formulario ocupe el espacio disponible en la columna */
116
+ .stForm {
117
+ height: calc(100% - 40px); /* Ajuste por márgenes y paddings */
118
+ display: flex;
119
+ flex-direction: column;
120
+ }
121
 
122
+ /* Hacer que el área de texto se expanda dentro del formulario */
123
+ .stForm .stTextArea {
124
+ flex: 1;
125
+ display: flex;
126
+ flex-direction: column;
127
+ }
128
 
129
+ /* El textarea en sí debe expandirse */
130
+ .stForm .stTextArea textarea {
131
+ flex: 1;
132
+ min-height: 750px !important;
133
+ }
134
+ </style>
135
+ """, unsafe_allow_html=True)
136
+
137
+ ###############################################################################################
138
+ with input_col:
139
+ with st.form(key=f"text_input_form_{lang_code}"):
140
+ text_input = st.text_area(
141
+ t.get('input_prompt', "Escribe o pega tu texto aquí:"),
142
+ height=800,
143
+ key=f"text_area_{lang_code}",
144
+ value=st.session_state.text_input,
145
+ help=t.get('help', "Este texto será analizado para darte recomendaciones personalizadas")
146
+ )
147
+
148
+ submit_button = st.form_submit_button(
149
+ t.get('analyze_button', "Analizar mi escritura"),
150
+ type="primary",
151
+ use_container_width=True
152
+ )
153
+
154
+ if submit_button:
155
+ if text_input.strip():
156
+ st.session_state.text_input = text_input
157
+
158
+ #######################################################################
159
+ # Código para análisis...
160
  try:
161
+ with st.spinner(t.get('processing', "Analizando...")): # Usando t.get directamente
162
  doc = nlp_models[lang_code](text_input)
163
  metrics = analyze_text_dimensions(doc)
164
 
 
178
 
179
  except Exception as e:
180
  logger.error(f"Error en análisis: {str(e)}")
181
+ st.error(t.get('analysis_error', "Error al analizar el texto")) # Usando t.get directamente
182
 
183
  # Mostrar resultados en la columna derecha
184
  with results_col:
185
  if st.session_state.show_results and st.session_state.current_metrics is not None:
186
+ # Primero los radio buttons para tipo de texto - usando t.get directamente
187
+ st.markdown(f"### {t.get('text_type_header', 'Tipo de texto')}")
188
+
189
+ # Preparar opciones de tipos de texto con nombres traducidos
190
+ text_type_options = {}
191
+ for text_type_key in TEXT_TYPES.keys():
192
+ # Fallback a nombres genéricos si no hay traducción
193
+ default_names = {
194
+ 'academic_article': 'Academic Article' if lang_code == 'en' else 'Артикул академічний' if lang_code == 'uk' else 'Artículo Académico',
195
+ 'student_essay': 'Student Essay' if lang_code == 'en' else 'Студентське есе' if lang_code == 'uk' else 'Trabajo Universitario',
196
+ 'general_communication': 'General Communication' if lang_code == 'en' else 'Загальна комунікація' if lang_code == 'uk' else 'Comunicación General'
197
+ }
198
+ text_type_options[text_type_key] = default_names.get(text_type_key, text_type_key)
199
+
200
  text_type = st.radio(
201
+ label=t.get('text_type_header', "Tipo de texto"), # Usando t.get directamente
202
  options=list(TEXT_TYPES.keys()),
203
+ format_func=lambda x: text_type_options.get(x, x),
204
  horizontal=True,
205
  key="text_type_radio",
206
  label_visibility="collapsed",
207
+ help=t.get('text_type_help', "Selecciona el tipo de texto para ajustar los criterios de evaluación") # Usando t.get directamente
208
  )
209
 
210
  st.session_state.current_text_type = text_type
211
 
212
+ # Crear subtabs con nombres traducidos
213
+ diagnosis_tab = "Diagnosis" if lang_code == 'en' else "Діагностика" if lang_code == 'uk' else "Diagnóstico"
214
+ recommendations_tab = "Recommendations" if lang_code == 'en' else "Рекомендації" if lang_code == 'uk' else "Recomendaciones"
215
+
216
+ subtab1, subtab2 = st.tabs([diagnosis_tab, recommendations_tab])
217
 
218
  # Mostrar resultados en el primer subtab
219
  with subtab1:
220
  display_diagnosis(
221
  metrics=st.session_state.current_metrics,
222
+ text_type=text_type,
223
+ lang_code=lang_code,
224
+ t=t # Pasar t directamente, no current_situation_t
225
  )
226
 
227
  # Mostrar recomendaciones en el segundo subtab
 
237
 
238
  except Exception as e:
239
  logger.error(f"Error en interfaz principal: {str(e)}")
240
+ st.error(t.get('error_interface', "Ocurrió un error al cargar la interfaz")) # Usando t.get directamente
241
 
242
+ #################################################################
243
+ #################################################################
244
+ def display_diagnosis(metrics, text_type=None, lang_code='es', t=None):
245
  """
246
  Muestra los resultados del análisis: métricas verticalmente y gráfico radar.
247
  """
248
  try:
249
+ # Asegurar que tenemos traducciones
250
+ if t is None:
251
+ t = {}
252
+
253
+ # Traducciones para títulos y etiquetas
254
+ dimension_labels = {
255
+ 'es': {
256
+ 'title': "Tipo de texto",
257
+ 'vocabulary': "Vocabulario",
258
+ 'structure': "Estructura",
259
+ 'cohesion': "Cohesión",
260
+ 'clarity': "Claridad",
261
+ 'improvement': "⚠️ Por mejorar",
262
+ 'acceptable': "📈 Aceptable",
263
+ 'optimal': "✅ Óptimo",
264
+ 'target': "Meta: {:.2f}"
265
+ },
266
+ 'en': {
267
+ 'title': "Text Type",
268
+ 'vocabulary': "Vocabulary",
269
+ 'structure': "Structure",
270
+ 'cohesion': "Cohesion",
271
+ 'clarity': "Clarity",
272
+ 'improvement': "⚠️ Needs improvement",
273
+ 'acceptable': "📈 Acceptable",
274
+ 'optimal': "✅ Optimal",
275
+ 'target': "Target: {:.2f}"
276
+ },
277
+ 'uk': {
278
+ 'title': "Тип тексту",
279
+ 'vocabulary': "Словниковий запас",
280
+ 'structure': "Структура",
281
+ 'cohesion': "Зв'язність",
282
+ 'clarity': "Ясність",
283
+ 'improvement': "⚠️ Потребує покращення",
284
+ 'acceptable': "📈 Прийнятно",
285
+ 'optimal': "✅ Оптимально",
286
+ 'target': "Ціль: {:.2f}"
287
+ }
288
+ }
289
+
290
+ # Obtener traducciones para el idioma actual, con fallback a español
291
+ labels = dimension_labels.get(lang_code, dimension_labels['es'])
292
+
293
  # Usar valor por defecto si no se especifica tipo
294
  text_type = text_type or 'student_essay'
295
 
 
303
  with metrics_col:
304
  metrics_config = [
305
  {
306
+ 'label': labels['vocabulary'],
307
  'key': 'vocabulary',
308
  'value': metrics['vocabulary']['normalized_score'],
309
+ 'help': t.get('vocabulary_help', "Riqueza y variedad del vocabulario"),
310
  'thresholds': thresholds['vocabulary']
311
  },
312
  {
313
+ 'label': labels['structure'],
314
  'key': 'structure',
315
  'value': metrics['structure']['normalized_score'],
316
+ 'help': t.get('structure_help', "Organización y complejidad de oraciones"),
317
  'thresholds': thresholds['structure']
318
  },
319
  {
320
+ 'label': labels['cohesion'],
321
  'key': 'cohesion',
322
  'value': metrics['cohesion']['normalized_score'],
323
+ 'help': t.get('cohesion_help', "Conexión y fluidez entre ideas"),
324
  'thresholds': thresholds['cohesion']
325
  },
326
  {
327
+ 'label': labels['clarity'],
328
  'key': 'clarity',
329
  'value': metrics['clarity']['normalized_score'],
330
+ 'help': t.get('clarity_help', "Facilidad de comprensión del texto"),
331
  'thresholds': thresholds['clarity']
332
  }
333
  ]
334
 
335
+ # Mostrar métricas con textos traducidos
336
  for metric in metrics_config:
337
  value = metric['value']
338
  if value < metric['thresholds']['min']:
339
+ status = labels['improvement']
340
  color = "inverse"
341
  elif value < metric['thresholds']['target']:
342
+ status = labels['acceptable']
343
  color = "off"
344
  else:
345
+ status = labels['optimal']
346
  color = "normal"
347
 
348
+ target_text = labels['target'].format(metric['thresholds']['target'])
349
+
350
  st.metric(
351
  metric['label'],
352
  f"{value:.2f}",
353
+ f"{status} ({target_text})",
354
  delta_color=color,
355
  help=metric['help']
356
  )
 
358
 
359
  # Gráfico radar en la columna derecha
360
  with graph_col:
361
+ display_radar_chart(metrics_config, thresholds, lang_code) # Pasar el parámetro lang_code
362
 
363
  except Exception as e:
364
  logger.error(f"Error mostrando resultados: {str(e)}")
365
+ st.error(t.get('error_results', "Error al mostrar los resultados"))
366
 
367
+ ##################################################################
368
+ ##################################################################
369
+ def display_radar_chart(metrics_config, thresholds, lang_code='es'):
370
  """
371
  Muestra el gráfico radar con los resultados.
372
  """
373
  try:
374
+ # Traducción de las etiquetas de leyenda según el idioma
375
+ legend_translations = {
376
+ 'es': {'min': 'Mínimo', 'target': 'Meta', 'user': 'Tu escritura'},
377
+ 'en': {'min': 'Minimum', 'target': 'Target', 'user': 'Your writing'},
378
+ 'uk': {'min': 'Мінімум', 'target': 'Ціль', 'user': 'Ваш текст'}
379
+ }
380
+
381
+ # Usar español por defecto si el idioma no está soportado
382
+ translations = legend_translations.get(lang_code, legend_translations['es'])
383
+
384
  # Preparar datos para el gráfico
385
  categories = [m['label'] for m in metrics_config]
386
  values_user = [m['value'] for m in metrics_config]
 
406
  ax.set_yticklabels([f'{tick:.1f}' for tick in circle_ticks], fontsize=8)
407
  ax.set_ylim(0, 1)
408
 
409
+ # Dibujar áreas de umbrales con etiquetas traducidas
410
+ ax.plot(angles, min_values, '#e74c3c', linestyle='--', linewidth=1, label=translations['min'], alpha=0.5)
411
+ ax.plot(angles, target_values, '#2ecc71', linestyle='--', linewidth=1, label=translations['target'], alpha=0.5)
412
  ax.fill_between(angles, target_values, [1]*len(angles), color='#2ecc71', alpha=0.1)
413
  ax.fill_between(angles, [0]*len(angles), min_values, color='#e74c3c', alpha=0.1)
414
 
415
+ # Dibujar valores del usuario con etiqueta traducida
416
+ ax.plot(angles, values_user, '#3498db', linewidth=2, label=translations['user'])
417
  ax.fill(angles, values_user, '#3498db', alpha=0.2)
418
 
419
  # Ajustar leyenda
modules/studentact/student_activities_v2.py CHANGED
@@ -1,4 +1,4 @@
1
- ##############
2
  ###modules/studentact/student_activities_v2.py
3
 
4
  import streamlit as st
@@ -40,15 +40,17 @@ def display_student_activities(username: str, lang_code: str, t: dict):
40
  t: Diccionario de traducciones
41
  """
42
  try:
43
- st.header(t.get('activities_title', 'Mis Actividades'))
 
44
 
45
  # Tabs para diferentes tipos de análisis
 
46
  tabs = st.tabs([
47
- t.get('current_situation_activities', 'Mi Situación Actual'),
48
- t.get('morpho_activities', 'Análisis Morfosintáctico'),
49
- t.get('semantic_activities', 'Análisis Semántico'),
50
- t.get('discourse_activities', 'Análisis del Discurso'),
51
- t.get('chat_activities', 'Conversaciones con el Asistente')
52
  ])
53
 
54
  # Tab de Situación Actual
@@ -63,7 +65,7 @@ def display_student_activities(username: str, lang_code: str, t: dict):
63
  with tabs[2]:
64
  display_semantic_activities(username, t)
65
 
66
- # Tab de Análisis del Discurso
67
  with tabs[3]:
68
  display_discourse_activities(username, t)
69
 
@@ -461,14 +463,15 @@ def display_semantic_activities(username: str, t: dict):
461
 
462
  ###################################################################################################
463
  def display_discourse_activities(username: str, t: dict):
464
- """Muestra actividades de análisis del discurso"""
465
  try:
466
  logger.info(f"Recuperando análisis del discurso para {username}")
467
  analyses = get_student_discourse_analysis(username)
468
 
469
  if not analyses:
470
  logger.info("No se encontraron análisis del discurso")
471
- st.info(t.get('no_discourse_analyses', 'No hay análisis del discurso registrados'))
 
472
  return
473
 
474
  logger.info(f"Procesando {len(analyses)} análisis del discurso")
@@ -502,7 +505,8 @@ def display_discourse_activities(username: str, t: dict):
502
 
503
  except Exception as e:
504
  logger.error(f"Error mostrando análisis del discurso: {str(e)}")
505
- st.error(t.get('error_discourse', 'Error al mostrar análisis del discurso'))
 
506
 
507
  #################################################################################
508
  def display_chat_activities(username: str, t: dict):
@@ -557,6 +561,7 @@ def display_chat_activities(username: str, t: dict):
557
  #################################################################################
558
  def display_discourse_comparison(analysis: dict, t: dict):
559
  """Muestra la comparación de análisis del discurso"""
 
560
  st.subheader(t.get('comparison_results', 'Resultados de la comparación'))
561
 
562
  col1, col2 = st.columns(2)
@@ -568,4 +573,4 @@ def display_discourse_comparison(analysis: dict, t: dict):
568
  with col2:
569
  st.markdown(f"**{t.get('concepts_text_2', 'Conceptos Texto 2')}**")
570
  df2 = pd.DataFrame(analysis['key_concepts2'])
571
- st.dataframe(df2)
 
1
+ ##############
2
  ###modules/studentact/student_activities_v2.py
3
 
4
  import streamlit as st
 
40
  t: Diccionario de traducciones
41
  """
42
  try:
43
+ # Cambiado de "Mis Actividades" a "Registro de mis actividades"
44
+ #st.header(t.get('activities_title', 'Registro de mis actividades'))
45
 
46
  # Tabs para diferentes tipos de análisis
47
+ # Cambiado "Análisis del Discurso" a "Análisis comparado de textos"
48
  tabs = st.tabs([
49
+ t.get('current_situation_activities', 'Registros de la función: Mi Situación Actual'),
50
+ t.get('morpho_activities', 'Registros de mis análisis morfosintácticos'),
51
+ t.get('semantic_activities', 'Registros de mis análisis semánticos'),
52
+ t.get('discourse_activities', 'Registros de mis análisis comparado de textos'),
53
+ t.get('chat_activities', 'Registros de mis conversaciones con el tutor virtual')
54
  ])
55
 
56
  # Tab de Situación Actual
 
65
  with tabs[2]:
66
  display_semantic_activities(username, t)
67
 
68
+ # Tab de Análisis del Discurso (mantiene nombre interno pero UI muestra "Análisis comparado de textos")
69
  with tabs[3]:
70
  display_discourse_activities(username, t)
71
 
 
463
 
464
  ###################################################################################################
465
  def display_discourse_activities(username: str, t: dict):
466
+ """Muestra actividades de análisis del discurso (mostrado como 'Análisis comparado de textos' en la UI)"""
467
  try:
468
  logger.info(f"Recuperando análisis del discurso para {username}")
469
  analyses = get_student_discourse_analysis(username)
470
 
471
  if not analyses:
472
  logger.info("No se encontraron análisis del discurso")
473
+ # Usamos el término "análisis comparado de textos" en la UI
474
+ st.info(t.get('no_discourse_analyses', 'No hay análisis comparados de textos registrados'))
475
  return
476
 
477
  logger.info(f"Procesando {len(analyses)} análisis del discurso")
 
505
 
506
  except Exception as e:
507
  logger.error(f"Error mostrando análisis del discurso: {str(e)}")
508
+ # Usamos el término "análisis comparado de textos" en la UI
509
+ st.error(t.get('error_discourse', 'Error al mostrar análisis comparado de textos'))
510
 
511
  #################################################################################
512
  def display_chat_activities(username: str, t: dict):
 
561
  #################################################################################
562
  def display_discourse_comparison(analysis: dict, t: dict):
563
  """Muestra la comparación de análisis del discurso"""
564
+ # Cambiado para usar "textos comparados" en la UI
565
  st.subheader(t.get('comparison_results', 'Resultados de la comparación'))
566
 
567
  col1, col2 = st.columns(2)
 
573
  with col2:
574
  st.markdown(f"**{t.get('concepts_text_2', 'Conceptos Texto 2')}**")
575
  df2 = pd.DataFrame(analysis['key_concepts2'])
576
+ st.dataframe(df2)