AIdeaText commited on
Commit
0d5ba51
·
verified ·
1 Parent(s): 2b737a6

Update modules/studentact/student_activities_v2.py

Browse files
modules/studentact/student_activities_v2.py CHANGED
@@ -537,265 +537,68 @@ def display_semantic_activities(username: str, t: dict):
537
  ###################################################################################################
538
 
539
  def display_discourse_activities(username: str, t: dict):
540
- """
541
- Muestra actividades de análisis del discurso con visualizaciones gráficas
542
- en el mismo formato que la interfaz principal
543
- """
544
  try:
545
- # Importar directamente la colección
546
- from ..database.mongo_db import get_collection
547
-
548
- # Registrar información de inicio
549
- logger.info(f"Intentando obtener análisis de discurso para {username}")
550
-
551
- # Obtener colección directamente
552
- collection = get_collection('student_discourse_analysis')
553
-
554
- # Verificar correctamente si collection es None
555
- if collection is None:
556
- st.info(t.get('no_discourse_analyses', 'No hay análisis comparados de textos registrados'))
557
- return
558
 
559
- # Consulta simplificada: solo por username
560
- results = list(collection.find({"username": username}).sort("timestamp", -1))
561
- logger.info(f"Recuperados {len(results)} documentos para {username}")
562
-
563
- if not results:
564
  st.info(t.get('no_discourse_analyses', 'No hay análisis comparados de textos registrados'))
565
  return
566
-
567
- # Estilo CSS similar al de la interfaz principal
568
- st.markdown("""
569
- <style>
570
- .concepts-container {
571
- display: flex;
572
- flex-wrap: nowrap;
573
- gap: 8px;
574
- padding: 12px;
575
- background-color: #f8f9fa;
576
- border-radius: 8px;
577
- overflow-x: auto;
578
- margin-bottom: 15px;
579
- white-space: nowrap;
580
- }
581
- .concept-item {
582
- background-color: white;
583
- border-radius: 4px;
584
- padding: 6px 10px;
585
- display: inline-flex;
586
- align-items: center;
587
- gap: 4px;
588
- box-shadow: 0 1px 2px rgba(0,0,0,0.1);
589
- flex-shrink: 0;
590
- }
591
- .concept-name {
592
- font-weight: 500;
593
- color: #1f2937;
594
- font-size: 0.85em;
595
- }
596
- .concept-freq {
597
- color: #6b7280;
598
- font-size: 0.75em;
599
- }
600
- .graph-container {
601
- background-color: white;
602
- padding: 15px;
603
- border-radius: 8px;
604
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
605
- margin-top: 10px;
606
- }
607
- </style>
608
- """, unsafe_allow_html=True)
609
-
610
- # Mostrar cada resultado
611
- for i, doc in enumerate(results):
612
  try:
613
- # Crear ID único para este análisis
614
- doc_id = str(doc.get('_id', f"doc_{i}"))
615
-
616
- # Extraer y formatear fecha con manejo de errores
617
- timestamp_str = doc.get('timestamp', 'Fecha desconocida')
618
- try:
619
- if isinstance(timestamp_str, str):
620
- dt = datetime.fromisoformat(timestamp_str.replace('Z', '+00:00'))
621
- formatted_date = dt.strftime("%d/%m/%Y %H:%M:%S")
622
- else:
623
- formatted_date = str(timestamp_str)
624
- except:
625
- formatted_date = str(timestamp_str)
626
 
627
- # Crear expander
628
- expander_label = f"{t.get('analysis_date', 'Fecha')}: {formatted_date}"
629
- with st.expander(expander_label, expanded=False):
630
- # Crear columnas como en la interfaz principal
631
- col1, col2 = st.columns(2)
 
 
 
 
 
632
 
633
- # Columna 1: Documento 1
634
- with col1:
635
- st.subheader(t.get('doc1_title', 'Documento 1'))
636
- st.markdown(t.get('key_concepts', 'Conceptos Clave'))
637
-
638
- if 'key_concepts1' in doc and doc['key_concepts1']:
639
- try:
640
- # Usar el mismo formato visual de conceptos que en la interfaz principal
641
- concepts_html = f"""
642
- <div class="concepts-container">
643
- {''.join([
644
- f'<div class="concept-item"><span class="concept-name">{concept}</span>'
645
- f'<span class="concept-freq">({freq})</span></div>'
646
- for concept, freq in doc['key_concepts1']
647
- ])}
648
- </div>
649
- """
650
- st.markdown(concepts_html, unsafe_allow_html=True)
651
-
652
- # Mostrar gráfico si existe
653
- if 'graph1' in doc and doc['graph1']:
654
- try:
655
- st.markdown('<div class="graph-container">', unsafe_allow_html=True)
656
-
657
- # Manejar diferentes formatos de gráfico
658
- if isinstance(doc['graph1'], bytes):
659
- st.image(doc['graph1'], caption=t.get('graph1_caption', 'Grafo del Texto 1'), use_column_width=True)
660
- elif isinstance(doc['graph1'], str):
661
- try:
662
- import base64
663
- # Intentar diferentes formatos de base64
664
- try:
665
- if doc['graph1'].startswith('data:image'):
666
- image_bytes = base64.b64decode(doc['graph1'].split(',')[1])
667
- else:
668
- image_bytes = base64.b64decode(doc['graph1'])
669
- st.image(image_bytes, caption=t.get('graph1_caption', 'Grafo del Texto 1'), use_column_width=True)
670
- except:
671
- st.warning(t.get('graph_decode_error', 'Error al decodificar el gráfico'))
672
- except:
673
- st.warning(t.get('graph_format_error', 'Formato de gráfico no soportado'))
674
-
675
- # Interpretación como texto normal
676
- st.markdown("**📊 Interpretación del grafo:**")
677
- st.markdown("""
678
- - 🔀 Las flechas indican la dirección de la relación entre conceptos
679
- - 🎨 Los colores más intensos indican conceptos más centrales en el texto
680
- - ⭕ El tamaño de los nodos representa la frecuencia del concepto
681
- - ↔️ El grosor de las líneas indica la fuerza de la conexión
682
- """)
683
-
684
- st.markdown('</div>', unsafe_allow_html=True)
685
- except Exception as graph_err:
686
- logger.error(f"Error mostrando gráfico 1: {str(graph_err)}")
687
- st.warning(t.get('graph_not_available', 'Gráfico no disponible'))
688
- else:
689
- st.warning(t.get('graph_not_available', 'Gráfico no disponible'))
690
- except Exception as e:
691
- logger.error(f"Error mostrando conceptos 1: {str(e)}")
692
- st.error("Error mostrando conceptos")
693
- else:
694
- st.warning(t.get('concepts_not_available', 'Conceptos no disponibles'))
695
 
696
- # Columna 2: Documento 2
697
- with col2:
698
- st.subheader(t.get('doc2_title', 'Documento 2'))
699
- st.markdown(t.get('key_concepts', 'Conceptos Clave'))
700
-
701
- if 'key_concepts2' in doc and doc['key_concepts2']:
702
  try:
703
- # Usar el mismo formato visual de conceptos que en la interfaz principal
704
- concepts_html = f"""
705
- <div class="concepts-container">
706
- {''.join([
707
- f'<div class="concept-item"><span class="concept-name">{concept}</span>'
708
- f'<span class="concept-freq">({freq})</span></div>'
709
- for concept, freq in doc['key_concepts2']
710
- ])}
711
- </div>
712
- """
713
- st.markdown(concepts_html, unsafe_allow_html=True)
714
-
715
- # Mostrar gráfico si existe
716
- if 'graph2' in doc and doc['graph2']:
717
- try:
718
- st.markdown('<div class="graph-container">', unsafe_allow_html=True)
719
-
720
- # Manejar diferentes formatos de gráfico
721
- if isinstance(doc['graph2'], bytes):
722
- st.image(doc['graph2'], caption=t.get('graph2_caption', 'Grafo del Texto 2'), use_column_width=True)
723
- elif isinstance(doc['graph2'], str):
724
- try:
725
- import base64
726
- # Intentar diferentes formatos de base64
727
- try:
728
- if doc['graph2'].startswith('data:image'):
729
- image_bytes = base64.b64decode(doc['graph2'].split(',')[1])
730
- else:
731
- image_bytes = base64.b64decode(doc['graph2'])
732
- st.image(image_bytes, caption=t.get('graph2_caption', 'Grafo del Texto 2'), use_column_width=True)
733
- except:
734
- st.warning(t.get('graph_decode_error', 'Error al decodificar el gráfico'))
735
- except:
736
- st.warning(t.get('graph_format_error', 'Formato de gráfico no soportado'))
737
-
738
- # Interpretación como texto normal
739
- st.markdown("**📊 Interpretación del grafo:**")
740
- st.markdown("""
741
- - 🔀 Las flechas indican la dirección de la relación entre conceptos
742
- - 🎨 Los colores más intensos indican conceptos más centrales en el texto
743
- - ⭕ El tamaño de los nodos representa la frecuencia del concepto
744
- - ↔️ El grosor de las líneas indica la fuerza de la conexión
745
- """)
746
-
747
- st.markdown('</div>', unsafe_allow_html=True)
748
- except Exception as graph_err:
749
- logger.error(f"Error mostrando gráfico 2: {str(graph_err)}")
750
- st.warning(t.get('graph_not_available', 'Gráfico no disponible'))
751
  else:
752
- st.warning(t.get('graph_not_available', 'Gráfico no disponible'))
753
- except Exception as e:
754
- logger.error(f"Error mostrando conceptos 2: {str(e)}")
755
- st.error("Error mostrando conceptos")
756
- else:
757
- st.warning(t.get('concepts_not_available', 'Conceptos no disponibles'))
758
 
759
- # Gráfico combinado (abajo de las columnas)
760
- if 'combined_graph' in doc and doc['combined_graph']:
761
- try:
762
- st.subheader(t.get('combined_graph_title', 'Análisis Comparativo'))
763
-
764
- # Manejar diferentes formatos de gráfico
765
- if isinstance(doc['combined_graph'], bytes):
766
- st.image(doc['combined_graph'], caption=t.get('combined_graph_caption', 'Visualización Comparativa'), use_column_width=True)
767
- elif isinstance(doc['combined_graph'], str):
768
- try:
769
- import base64
770
- # Intentar diferentes formatos de base64
771
- try:
772
- if doc['combined_graph'].startswith('data:image'):
773
- image_bytes = base64.b64decode(doc['combined_graph'].split(',')[1])
774
- else:
775
- image_bytes = base64.b64decode(doc['combined_graph'])
776
- st.image(image_bytes, caption=t.get('combined_graph_caption', 'Visualización Comparativa'), use_column_width=True)
777
- except:
778
- st.warning(t.get('graph_decode_error', 'Error al decodificar el gráfico'))
779
- except:
780
- st.warning(t.get('graph_format_error', 'Formato de gráfico no soportado'))
781
- except Exception as graph_err:
782
- logger.error(f"Error mostrando gráfico combinado: {str(graph_err)}")
783
- st.warning(t.get('combined_graph_not_available', 'Gráfico combinado no disponible'))
784
-
785
- # Nota informativa sobre la comparación
786
- st.info(t.get('comparison_note',
787
- 'La funcionalidad de comparación detallada estará disponible en una próxima actualización.'))
788
-
789
- except Exception as doc_err:
790
- logger.error(f"Error procesando documento: {str(doc_err)}")
791
- st.error(f"Error procesando análisis: {str(doc_err)}")
792
-
793
- except Exception as e:
794
- logger.error(f"Error general: {str(e)}")
795
- st.error(f"Error recuperando análisis: {str(e)}")
796
- # Mostrar el error para depuración
797
- st.exception(e)
798
 
 
 
 
799
 
800
 
801
  #################################################################################
 
537
  ###################################################################################################
538
 
539
  def display_discourse_activities(username: str, t: dict):
540
+ """Muestra actividades de análisis del discurso"""
 
 
 
541
  try:
542
+ logger.info(f"Recuperando análisis del discurso para {username}")
543
+ analyses = get_student_discourse_analysis(username)
 
 
 
 
 
 
 
 
 
 
 
544
 
545
+ if not analyses:
546
+ logger.info("No se encontraron análisis del discurso")
 
 
 
547
  st.info(t.get('no_discourse_analyses', 'No hay análisis comparados de textos registrados'))
548
  return
549
+
550
+ logger.info(f"Procesando {len(analyses)} análisis del discurso")
551
+ for analysis in analyses:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
552
  try:
553
+ # Verificar campos mínimos necesarios
554
+ if 'timestamp' not in analysis:
555
+ logger.warning(f"Análisis sin timestamp: {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
+ # Mostrar textos analizados
564
+ if 'text1' in analysis and 'text2' in analysis:
565
+ col1, col2 = st.columns(2)
566
+ with col1:
567
+ st.markdown("**Texto 1:**")
568
+ st.text_area("", value=analysis['text1'], height=100, disabled=True)
569
+ with col2:
570
+ st.markdown("**Texto 2:**")
571
+ st.text_area("", value=analysis['text2'], height=100, disabled=True)
572
 
573
+ # Mostrar gráficos
574
+ st.markdown("### Visualización comparativa")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
575
 
576
+ # Verificar y mostrar gráficos si existen
577
+ has_graphs = False
578
+ for graph_key in ['graph1', 'graph2', 'combined_graph']:
579
+ if graph_key in analysis and analysis[graph_key]:
 
 
580
  try:
581
+ # Verificar que sea bytes
582
+ if isinstance(analysis[graph_key], bytes):
583
+ st.image(analysis[graph_key],
584
+ caption=f"Gráfico {graph_key.replace('graph', '')}",
585
+ use_column_width=True)
586
+ has_graphs = True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
587
  else:
588
+ logger.warning(f"{graph_key} no es bytes: {type(analysis[graph_key])}")
589
+ except Exception as img_error:
590
+ logger.error(f"Error mostrando {graph_key}: {str(img_error)}")
 
 
 
591
 
592
+ if not has_graphs:
593
+ st.info(t.get('no_visualization', 'No hay visualización comparativa disponible'))
594
+
595
+ except Exception as e:
596
+ logger.error(f"Error procesando análisis individual: {str(e)}")
597
+ continue
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
598
 
599
+ except Exception as e:
600
+ logger.error(f"Error mostrando análisis del discurso: {str(e)}")
601
+ st.error(t.get('error_discourse', 'Error al mostrar análisis comparado de textos'))
602
 
603
 
604
  #################################################################################