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

Update modules/studentact/student_activities_v2.py

Browse files
modules/studentact/student_activities_v2.py CHANGED
@@ -536,9 +536,14 @@ def display_semantic_activities(username: str, t: dict):
536
 
537
  ###################################################################################################
538
  def display_discourse_activities(username: str, t: dict):
539
- """Muestra actividades de análisis del discurso (mostrado como 'Análisis comparado de textos' en la UI)"""
 
 
540
  try:
541
  logger.info(f"Recuperando análisis del discurso para {username}")
 
 
 
542
  analyses = get_student_discourse_analysis(username)
543
 
544
  if not analyses:
@@ -551,26 +556,220 @@ def display_discourse_activities(username: str, t: dict):
551
  for analysis in analyses:
552
  try:
553
  # Verificar campos mínimos necesarios
554
- if not all(key in analysis for key in ['timestamp', 'combined_graph']):
555
- logger.warning(f"Análisis incompleto: {analysis.keys()}")
556
  continue
557
 
558
  # Formatear fecha
559
- timestamp = datetime.fromisoformat(analysis['timestamp'].replace('Z', '+00:00'))
560
- formatted_date = timestamp.strftime("%d/%m/%Y %H:%M:%S")
 
 
 
 
561
 
562
- with st.expander(f"{t.get('analysis_date', 'Fecha')}: {formatted_date}", expanded=False):
563
- if analysis['combined_graph']:
564
- logger.debug("Decodificando gráfico combinado")
565
- try:
566
- image_bytes = base64.b64decode(analysis['combined_graph'])
567
- st.image(image_bytes, use_container_width=True)
568
- logger.debug("Gráfico mostrado exitosamente")
569
- except Exception as img_error:
570
- logger.error(f"Error decodificando imagen: {str(img_error)}")
571
- st.error(t.get('error_loading_graph', 'Error al cargar el gráfico'))
572
- else:
573
- st.info(t.get('no_visualization', 'No hay visualización comparativa disponible'))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
574
 
575
  except Exception as e:
576
  logger.error(f"Error procesando análisis individual: {str(e)}")
 
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:
 
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)}")