AIdeaText commited on
Commit
c7a1b47
·
verified ·
1 Parent(s): 4479433

Update modules/studentact/student_activities_v2.py

Browse files
modules/studentact/student_activities_v2.py CHANGED
@@ -535,241 +535,114 @@ def display_semantic_activities(username: str, t: dict):
535
 
536
 
537
  ###################################################################################################
 
538
  def display_discourse_activities(username: str, t: dict):
539
  """
540
- Muestra actividades de análisis del discurso (mostrado como 'Análisis comparado de textos' en la UI)
541
  """
542
  try:
543
  logger.info(f"Recuperando análisis del discurso para {username}")
544
-
545
- # Obtener análisis del discurso con el tipo correcto
546
- from ..database.discourse_mongo_db import get_student_discourse_analysis
547
  analyses = get_student_discourse_analysis(username)
548
 
549
  if not analyses:
550
  logger.info("No se encontraron análisis del discurso")
551
- # Usamos el término "análisis comparado de textos" en la UI
552
  st.info(t.get('no_discourse_analyses', 'No hay análisis comparados de textos registrados'))
553
  return
554
 
555
  logger.info(f"Procesando {len(analyses)} análisis del discurso")
556
  for analysis in analyses:
557
  try:
558
- # Verificar campos mínimos necesarios
559
- if 'timestamp' not in analysis:
560
- logger.warning(f"Análisis sin timestamp: {analysis.keys()}")
561
- continue
562
-
563
  # Formatear fecha
564
- try:
565
- timestamp = datetime.fromisoformat(analysis['timestamp'].replace('Z', '+00:00'))
566
- formatted_date = timestamp.strftime("%d/%m/%Y %H:%M:%S")
567
- except Exception as e:
568
- logger.error(f"Error al formatear timestamp: {str(e)}")
569
- formatted_date = str(analysis.get('timestamp', 'Fecha desconocida'))
570
 
571
- # Crear el título del expander
572
  expander_title = f"{t.get('analysis_date', 'Fecha')}: {formatted_date}"
573
 
574
  with st.expander(expander_title, expanded=False):
575
- # Crear pestañas para los textos y la comparación
576
- tabs = st.tabs([
577
- t.get('text1_tab', 'Texto 1 (Patrón)'),
578
- t.get('text2_tab', 'Texto 2 (Comparación)'),
579
- t.get('comparison_tab', 'Análisis Comparativo')
580
- ])
 
 
 
 
 
 
 
 
 
581
 
582
- # Tab para Texto 1
583
- with tabs[0]:
584
- if 'text1' in analysis and analysis['text1']:
585
- st.text_area(
586
- "Texto 1",
587
- value=analysis['text1'],
588
- height=150,
589
- disabled=True,
590
- label_visibility="collapsed",
591
- key=f"text1_{str(analysis['_id'])}"
592
- )
593
-
594
- # Mostrar conceptos clave del texto 1
595
- if 'key_concepts1' in analysis and analysis['key_concepts1']:
596
- st.subheader(t.get('key_concepts1', 'Conceptos clave (Texto 1)'))
597
-
598
- # Crear una tabla/dataframe de conceptos
599
- concept_data = analysis['key_concepts1']
600
- if concept_data and len(concept_data) > 0:
601
- # Verificar formato de los datos
602
- if isinstance(concept_data[0], list) and len(concept_data[0]) == 2:
603
- # Formato esperado: [["concepto", valor], ...]
604
- df = pd.DataFrame(concept_data, columns=['Concepto', 'Relevancia'])
605
- st.dataframe(df, use_container_width=True)
606
- else:
607
- st.write(concept_data) # Mostrar como está si no tiene el formato esperado
608
- else:
609
- st.info(t.get('no_concepts1', 'No hay conceptos clave disponibles para el Texto 1'))
610
-
611
- # Mostrar gráfico si existe
612
- if 'graph1' in analysis and analysis['graph1']:
613
- st.subheader(t.get('graph1', 'Visualización del Texto 1'))
614
- try:
615
- if isinstance(analysis['graph1'], str) and analysis['graph1'].startswith('data:image'):
616
- # Manejo para string base64
617
- import base64
618
- image_bytes = base64.b64decode(analysis['graph1'].split(',')[1])
619
- st.image(image_bytes, use_column_width=True)
620
- elif isinstance(analysis['graph1'], bytes):
621
- # Manejo para bytes directos
622
- st.image(analysis['graph1'], use_column_width=True)
623
- else:
624
- # Otro tipo de gráfico (matplotlib, etc.)
625
- st.pyplot(analysis['graph1'])
626
- except Exception as e:
627
- logger.error(f"Error mostrando gráfico 1: {str(e)}")
628
- st.error(t.get('error_graph1', 'Error al mostrar el gráfico del Texto 1'))
629
- else:
630
- st.info(t.get('no_text1', 'Texto 1 no disponible'))
631
 
632
- # Tab para Texto 2
633
- with tabs[1]:
634
- if 'text2' in analysis and analysis['text2']:
635
- st.text_area(
636
- "Texto 2",
637
- value=analysis['text2'],
638
- height=150,
639
- disabled=True,
640
- label_visibility="collapsed",
641
- key=f"text2_{str(analysis['_id'])}"
642
- )
643
-
644
- # Mostrar conceptos clave del texto 2
645
- if 'key_concepts2' in analysis and analysis['key_concepts2']:
646
- st.subheader(t.get('key_concepts2', 'Conceptos clave (Texto 2)'))
647
-
648
- # Crear una tabla/dataframe de conceptos
649
- concept_data = analysis['key_concepts2']
650
- if concept_data and len(concept_data) > 0:
651
- # Verificar formato de los datos
652
- if isinstance(concept_data[0], list) and len(concept_data[0]) == 2:
653
- # Formato esperado: [["concepto", valor], ...]
654
- df = pd.DataFrame(concept_data, columns=['Concepto', 'Relevancia'])
655
- st.dataframe(df, use_container_width=True)
656
- else:
657
- st.write(concept_data) # Mostrar como está si no tiene el formato esperado
658
- else:
659
- st.info(t.get('no_concepts2', 'No hay conceptos clave disponibles para el Texto 2'))
660
-
661
- # Mostrar gráfico si existe
662
- if 'graph2' in analysis and analysis['graph2']:
663
- st.subheader(t.get('graph2', 'Visualización del Texto 2'))
664
- try:
665
- if isinstance(analysis['graph2'], str) and analysis['graph2'].startswith('data:image'):
666
- # Manejo para string base64
667
- import base64
668
- image_bytes = base64.b64decode(analysis['graph2'].split(',')[1])
669
- st.image(image_bytes, use_column_width=True)
670
- elif isinstance(analysis['graph2'], bytes):
671
- # Manejo para bytes directos
672
- st.image(analysis['graph2'], use_column_width=True)
673
- else:
674
- # Otro tipo de gráfico (matplotlib, etc.)
675
- st.pyplot(analysis['graph2'])
676
- except Exception as e:
677
- logger.error(f"Error mostrando gráfico 2: {str(e)}")
678
- st.error(t.get('error_graph2', 'Error al mostrar el gráfico del Texto 2'))
679
- else:
680
- # Caso especial: si text2 está ausente pero text1 está presente
681
- # mostrar text1 aquí también (para documentos de un solo texto)
682
- if 'text1' in analysis and analysis['text1']:
683
- st.info(t.get('using_text1', 'Usando el mismo texto como referencia.'))
684
- st.text_area(
685
- "Texto 1 como referencia",
686
- value=analysis['text1'],
687
- height=150,
688
- disabled=True,
689
- label_visibility="collapsed",
690
- key=f"text1_ref_{str(analysis['_id'])}"
691
- )
692
- else:
693
- st.info(t.get('no_text2', 'Texto 2 no disponible'))
694
 
695
- # Tab para Comparación
696
- with tabs[2]:
697
- # Mostrar gráfico combinado si existe
698
- if 'combined_graph' in analysis and analysis['combined_graph']:
699
- st.subheader(t.get('combined_visualization', 'Visualización comparativa'))
700
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
701
  if isinstance(analysis['combined_graph'], str):
702
- # Si es string base64
703
- if analysis['combined_graph'].startswith('data:image'):
704
  import base64
705
- image_bytes = base64.b64decode(analysis['combined_graph'].split(',')[1])
706
- else:
707
- # Podría ser base64 sin prefijo
708
- try:
709
- import base64
710
  image_bytes = base64.b64decode(analysis['combined_graph'])
711
- except:
712
- st.text(analysis['combined_graph'][:100] + "...") # Mostrar parte como texto
713
- raise ValueError("Formato de gráfico combinado no reconocido")
714
-
715
- st.image(image_bytes, use_column_width=True)
716
  elif isinstance(analysis['combined_graph'], bytes):
717
- # Si son bytes directos
718
  st.image(analysis['combined_graph'], use_column_width=True)
719
- else:
720
- # Otro tipo de gráfico
721
  st.pyplot(analysis['combined_graph'])
722
  except Exception as e:
723
  logger.error(f"Error mostrando gráfico combinado: {str(e)}")
724
- st.error(t.get('error_combined_graph', 'Error al mostrar la visualización comparativa'))
725
- else:
726
- # Mostrar comparación de conceptos lado a lado
727
- if ('key_concepts1' in analysis and analysis['key_concepts1'] and
728
- 'key_concepts2' in analysis and analysis['key_concepts2']):
729
-
730
- st.subheader(t.get('concept_comparison', 'Comparación de conceptos clave'))
731
- col1, col2 = st.columns(2)
732
-
733
- with col1:
734
- st.markdown(f"**{t.get('text1_concepts', 'Conceptos del Texto 1')}**")
735
- concept_data1 = analysis['key_concepts1']
736
- if concept_data1 and len(concept_data1) > 0:
737
- if isinstance(concept_data1[0], list) and len(concept_data1[0]) == 2:
738
- df1 = pd.DataFrame(concept_data1, columns=['Concepto', 'Relevancia'])
739
- st.dataframe(df1, use_container_width=True)
740
- else:
741
- st.write(concept_data1)
742
-
743
- with col2:
744
- st.markdown(f"**{t.get('text2_concepts', 'Conceptos del Texto 2')}**")
745
- concept_data2 = analysis['key_concepts2']
746
- if concept_data2 and len(concept_data2) > 0:
747
- if isinstance(concept_data2[0], list) and len(concept_data2[0]) == 2:
748
- df2 = pd.DataFrame(concept_data2, columns=['Concepto', 'Relevancia'])
749
- st.dataframe(df2, use_container_width=True)
750
- else:
751
- st.write(concept_data2)
752
-
753
- # Mostrar conceptos en común (intersección)
754
- if (isinstance(analysis['key_concepts1'], list) and
755
- isinstance(analysis['key_concepts2'], list)):
756
-
757
- concepts1 = [item[0] for item in analysis['key_concepts1'] if isinstance(item, list) and len(item) == 2]
758
- concepts2 = [item[0] for item in analysis['key_concepts2'] if isinstance(item, list) and len(item) == 2]
759
-
760
- common_concepts = set(concepts1).intersection(set(concepts2))
761
-
762
- if common_concepts:
763
- st.subheader(t.get('common_concepts', 'Conceptos en común'))
764
- st.write(", ".join(common_concepts))
765
- else:
766
- st.info(t.get('no_common_concepts', 'No se encontraron conceptos en común entre los textos'))
767
- else:
768
- st.info(t.get('no_comparison_data', 'No hay datos suficientes para la comparación'))
769
-
770
- # Nota sobre la comparación
771
- st.info(t.get('comparison_note',
772
- 'La funcionalidad de comparación avanzada estará disponible en una próxima actualización.'))
773
 
774
  except Exception as e:
775
  logger.error(f"Error procesando análisis individual: {str(e)}")
@@ -777,9 +650,9 @@ def display_discourse_activities(username: str, t: dict):
777
 
778
  except Exception as e:
779
  logger.error(f"Error mostrando análisis del discurso: {str(e)}")
780
- # Usamos el término "análisis comparado de textos" en la UI
781
  st.error(t.get('error_discourse', 'Error al mostrar análisis comparado de textos'))
782
 
 
783
  #################################################################################
784
  def display_chat_activities(username: str, t: dict):
785
  """
 
535
 
536
 
537
  ###################################################################################################
538
+
539
  def display_discourse_activities(username: str, t: dict):
540
  """
541
+ Muestra actividades de análisis del discurso centradas en las visualizaciones comparativas
542
  """
543
  try:
544
  logger.info(f"Recuperando análisis del discurso para {username}")
 
 
 
545
  analyses = get_student_discourse_analysis(username)
546
 
547
  if not analyses:
548
  logger.info("No se encontraron análisis del discurso")
 
549
  st.info(t.get('no_discourse_analyses', 'No hay análisis comparados de textos registrados'))
550
  return
551
 
552
  logger.info(f"Procesando {len(analyses)} análisis del discurso")
553
  for analysis in analyses:
554
  try:
 
 
 
 
 
555
  # Formatear fecha
556
+ timestamp = datetime.fromisoformat(analysis['timestamp'].replace('Z', '+00:00'))
557
+ formatted_date = timestamp.strftime("%d/%m/%Y %H:%M:%S")
 
 
 
 
558
 
559
+ # Título del expander
560
  expander_title = f"{t.get('analysis_date', 'Fecha')}: {formatted_date}"
561
 
562
  with st.expander(expander_title, expanded=False):
563
+ # Mostrar conceptos clave en dos columnas
564
+ if 'key_concepts1' in analysis and 'key_concepts2' in analysis:
565
+ col1, col2 = st.columns(2)
566
+
567
+ with col1:
568
+ st.subheader(t.get('concepts_text_1', 'Conceptos Texto 1'))
569
+ if analysis['key_concepts1']:
570
+ df1 = pd.DataFrame(analysis['key_concepts1'], columns=['Concepto', 'Relevancia'])
571
+ st.dataframe(df1, use_container_width=True)
572
+
573
+ with col2:
574
+ st.subheader(t.get('concepts_text_2', 'Conceptos Texto 2'))
575
+ if analysis['key_concepts2']:
576
+ df2 = pd.DataFrame(analysis['key_concepts2'], columns=['Concepto', 'Relevancia'])
577
+ st.dataframe(df2, use_container_width=True)
578
 
579
+ # Mostrar visualizaciones semánticas
580
+ st.subheader(t.get('semantic_visualization', 'Visualización Semántica'))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
581
 
582
+ # Mostrar gráficos en fila
583
+ graph_cols = st.columns(3)
584
+
585
+ # Gráfico 1 (si existe)
586
+ with graph_cols[0]:
587
+ if analysis.get('graph1'):
588
+ try:
589
+ st.caption(t.get('graph1_caption', 'Grafo Texto 1'))
590
+ if isinstance(analysis['graph1'], str) and analysis['graph1'].startswith('data:image'):
591
+ import base64
592
+ image_bytes = base64.b64decode(analysis['graph1'].split(',')[1])
593
+ st.image(image_bytes, use_column_width=True)
594
+ elif isinstance(analysis['graph1'], bytes):
595
+ st.image(analysis['graph1'], use_column_width=True)
596
+ elif analysis['graph1'] is not None:
597
+ st.pyplot(analysis['graph1'])
598
+ except Exception as e:
599
+ logger.error(f"Error mostrando gráfico 1: {str(e)}")
600
+ st.error(t.get('error_graph1', 'Error mostrando gráfico 1'))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
601
 
602
+ # Gráfico 2 (si existe)
603
+ with graph_cols[1]:
604
+ if analysis.get('graph2'):
 
 
605
  try:
606
+ st.caption(t.get('graph2_caption', 'Grafo Texto 2'))
607
+ if isinstance(analysis['graph2'], str) and analysis['graph2'].startswith('data:image'):
608
+ import base64
609
+ image_bytes = base64.b64decode(analysis['graph2'].split(',')[1])
610
+ st.image(image_bytes, use_column_width=True)
611
+ elif isinstance(analysis['graph2'], bytes):
612
+ st.image(analysis['graph2'], use_column_width=True)
613
+ elif analysis['graph2'] is not None:
614
+ st.pyplot(analysis['graph2'])
615
+ except Exception as e:
616
+ logger.error(f"Error mostrando gráfico 2: {str(e)}")
617
+ st.error(t.get('error_graph2', 'Error mostrando gráfico 2'))
618
+
619
+ # Gráfico combinado (si existe) - en la última columna
620
+ with graph_cols[2]:
621
+ if analysis.get('combined_graph'):
622
+ try:
623
+ st.caption(t.get('combined_graph_caption', 'Grafo Comparativo'))
624
  if isinstance(analysis['combined_graph'], str):
625
+ try:
 
626
  import base64
627
+ # Intentar diferentes formatos de base64
628
+ if analysis['combined_graph'].startswith('data:image'):
629
+ image_bytes = base64.b64decode(analysis['combined_graph'].split(',')[1])
630
+ else:
 
631
  image_bytes = base64.b64decode(analysis['combined_graph'])
632
+ st.image(image_bytes, use_column_width=True)
633
+ except:
634
+ logger.error("Error decodificando imagen combinada")
 
 
635
  elif isinstance(analysis['combined_graph'], bytes):
 
636
  st.image(analysis['combined_graph'], use_column_width=True)
637
+ elif analysis['combined_graph'] is not None:
 
638
  st.pyplot(analysis['combined_graph'])
639
  except Exception as e:
640
  logger.error(f"Error mostrando gráfico combinado: {str(e)}")
641
+ st.error(t.get('error_combined_graph', 'Error mostrando gráfico combinado'))
642
+
643
+ # Si no hay ningún gráfico disponible
644
+ if all(analysis.get(k) is None for k in ['graph1', 'graph2', 'combined_graph']):
645
+ st.info(t.get('no_visualizations', 'No hay visualizaciones disponibles para este análisis'))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
646
 
647
  except Exception as e:
648
  logger.error(f"Error procesando análisis individual: {str(e)}")
 
650
 
651
  except Exception as e:
652
  logger.error(f"Error mostrando análisis del discurso: {str(e)}")
 
653
  st.error(t.get('error_discourse', 'Error al mostrar análisis comparado de textos'))
654
 
655
+
656
  #################################################################################
657
  def display_chat_activities(username: str, t: dict):
658
  """