|
|
|
|
|
|
|
import streamlit as st |
|
import re |
|
import io |
|
from io import BytesIO |
|
import pandas as pd |
|
import numpy as np |
|
import time |
|
import matplotlib.pyplot as plt |
|
from datetime import datetime |
|
from spacy import displacy |
|
import random |
|
import base64 |
|
import seaborn as sns |
|
import logging |
|
|
|
|
|
from ..database.morphosintax_mongo_db import get_student_morphosyntax_analysis |
|
from ..database.semantic_mongo_db import get_student_semantic_analysis |
|
from ..database.discourse_mongo_db import get_student_discourse_analysis |
|
from ..database.chat_mongo_db import get_chat_history |
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
|
|
def display_student_activities(username: str, lang_code: str, t: dict): |
|
""" |
|
Muestra todas las actividades del estudiante |
|
Args: |
|
username: Nombre del estudiante |
|
lang_code: Código del idioma |
|
t: Diccionario de traducciones |
|
""" |
|
try: |
|
st.header(t.get('activities_title', 'Mis Actividades')) |
|
|
|
|
|
tabs = st.tabs([ |
|
t.get('morpho_activities', 'Análisis Morfosintáctico'), |
|
t.get('semantic_activities', 'Análisis Semántico'), |
|
t.get('discourse_activities', 'Análisis del Discurso'), |
|
t.get('chat_activities', 'Conversaciones con el Asistente') |
|
]) |
|
|
|
|
|
with tabs[0]: |
|
display_morphosyntax_activities(username, t) |
|
|
|
|
|
with tabs[1]: |
|
display_semantic_activities(username, t) |
|
|
|
|
|
with tabs[2]: |
|
display_discourse_activities(username, t) |
|
|
|
|
|
with tabs[3]: |
|
display_chat_activities(username, t) |
|
|
|
except Exception as e: |
|
logger.error(f"Error mostrando actividades: {str(e)}") |
|
st.error(t.get('error_loading_activities', 'Error al cargar las actividades')) |
|
|
|
|
|
|
|
def display_morphosyntax_activities(username: str, t: dict): |
|
"""Muestra actividades de análisis morfosintáctico""" |
|
try: |
|
analyses = get_student_morphosyntax_analysis(username) |
|
if not analyses: |
|
st.info(t.get('no_morpho_analyses', 'No hay análisis morfosintácticos registrados')) |
|
return |
|
|
|
for analysis in analyses: |
|
with st.expander( |
|
f"{t.get('analysis_date', 'Fecha')}: {analysis['timestamp']}", |
|
expanded=False |
|
): |
|
st.text(f"{t.get('analyzed_text', 'Texto analizado')}:") |
|
st.write(analysis['text']) |
|
|
|
if 'arc_diagrams' in analysis: |
|
st.subheader(t.get('syntactic_diagrams', 'Diagramas sintácticos')) |
|
for diagram in analysis['arc_diagrams']: |
|
st.write(diagram, unsafe_allow_html=True) |
|
|
|
except Exception as e: |
|
logger.error(f"Error mostrando análisis morfosintáctico: {str(e)}") |
|
st.error(t.get('error_morpho', 'Error al mostrar análisis morfosintáctico')) |
|
|
|
|
|
|
|
|
|
def display_semantic_activities(username: str, t: dict): |
|
"""Muestra actividades de análisis semántico""" |
|
try: |
|
logger.info(f"Recuperando análisis semántico para {username}") |
|
analyses = get_student_semantic_analysis(username) |
|
|
|
if not analyses: |
|
logger.info("No se encontraron análisis semánticos") |
|
st.info(t.get('no_semantic_analyses', 'No hay análisis semánticos registrados')) |
|
return |
|
|
|
logger.info(f"Procesando {len(analyses)} análisis semánticos") |
|
|
|
for analysis in analyses: |
|
try: |
|
|
|
if not all(key in analysis for key in ['timestamp', 'concept_graph']): |
|
logger.warning(f"Análisis incompleto: {analysis.keys()}") |
|
continue |
|
|
|
|
|
timestamp = datetime.fromisoformat(analysis['timestamp'].replace('Z', '+00:00')) |
|
formatted_date = timestamp.strftime("%d/%m/%Y %H:%M:%S") |
|
|
|
|
|
with st.expander(f"{t.get('analysis_date', 'Fecha')}: {formatted_date}", expanded=False): |
|
|
|
if analysis.get('concept_graph'): |
|
try: |
|
|
|
logger.debug("Decodificando gráfico de conceptos") |
|
image_data = analysis['concept_graph'] |
|
|
|
|
|
if isinstance(image_data, bytes): |
|
image_bytes = image_data |
|
else: |
|
|
|
image_bytes = base64.b64decode(image_data) |
|
|
|
logger.debug(f"Longitud de bytes de imagen: {len(image_bytes)}") |
|
|
|
|
|
st.image( |
|
image_bytes, |
|
caption=t.get('concept_network', 'Red de Conceptos'), |
|
use_column_width=True |
|
) |
|
logger.debug("Gráfico mostrado exitosamente") |
|
|
|
except Exception as img_error: |
|
logger.error(f"Error procesando gráfico: {str(img_error)}") |
|
st.error(t.get('error_loading_graph', 'Error al cargar el gráfico')) |
|
else: |
|
st.info(t.get('no_graph', 'No hay visualización disponible')) |
|
|
|
except Exception as e: |
|
logger.error(f"Error procesando análisis individual: {str(e)}") |
|
continue |
|
|
|
except Exception as e: |
|
logger.error(f"Error mostrando análisis semántico: {str(e)}") |
|
st.error(t.get('error_semantic', 'Error al mostrar análisis semántico')) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def display_discourse_activities(username: str, t: dict): |
|
"""Muestra actividades de análisis del discurso""" |
|
try: |
|
logger.info(f"Recuperando análisis del discurso para {username}") |
|
analyses = get_student_discourse_analysis(username) |
|
|
|
if not analyses: |
|
logger.info("No se encontraron análisis del discurso") |
|
st.info(t.get('no_discourse_analyses', 'No hay análisis del discurso registrados')) |
|
return |
|
|
|
logger.info(f"Procesando {len(analyses)} análisis del discurso") |
|
for analysis in analyses: |
|
try: |
|
|
|
if not all(key in analysis for key in ['timestamp', 'combined_graph']): |
|
logger.warning(f"Análisis incompleto: {analysis.keys()}") |
|
continue |
|
|
|
|
|
timestamp = datetime.fromisoformat(analysis['timestamp'].replace('Z', '+00:00')) |
|
formatted_date = timestamp.strftime("%d/%m/%Y %H:%M:%S") |
|
|
|
with st.expander(f"{t.get('analysis_date', 'Fecha')}: {formatted_date}", expanded=False): |
|
if analysis['combined_graph']: |
|
logger.debug("Decodificando gráfico combinado") |
|
try: |
|
image_bytes = base64.b64decode(analysis['combined_graph']) |
|
st.image(image_bytes, use_column_width=True) |
|
logger.debug("Gráfico mostrado exitosamente") |
|
except Exception as img_error: |
|
logger.error(f"Error decodificando imagen: {str(img_error)}") |
|
st.error(t.get('error_loading_graph', 'Error al cargar el gráfico')) |
|
else: |
|
st.info(t.get('no_visualization', 'No hay visualización comparativa disponible')) |
|
|
|
except Exception as e: |
|
logger.error(f"Error procesando análisis individual: {str(e)}") |
|
continue |
|
|
|
except Exception as e: |
|
logger.error(f"Error mostrando análisis del discurso: {str(e)}") |
|
st.error(t.get('error_discourse', 'Error al mostrar análisis del discurso')) |
|
|
|
|
|
def display_discourse_comparison(analysis: dict, t: dict): |
|
"""Muestra la comparación de análisis del discurso""" |
|
st.subheader(t.get('comparison_results', 'Resultados de la comparación')) |
|
|
|
col1, col2 = st.columns(2) |
|
with col1: |
|
st.markdown(f"**{t.get('concepts_text_1', 'Conceptos Texto 1')}**") |
|
df1 = pd.DataFrame(analysis['key_concepts1']) |
|
st.dataframe(df1) |
|
|
|
with col2: |
|
st.markdown(f"**{t.get('concepts_text_2', 'Conceptos Texto 2')}**") |
|
df2 = pd.DataFrame(analysis['key_concepts2']) |
|
st.dataframe(df2) |
|
|
|
|
|
def display_chat_activities(username: str, t: dict): |
|
""" |
|
Muestra historial de conversaciones del chat |
|
""" |
|
try: |
|
|
|
chat_history = get_chat_history( |
|
username=username, |
|
analysis_type='sidebar', |
|
limit=50 |
|
) |
|
|
|
if not chat_history: |
|
st.info(t.get('no_chat_history', 'No hay conversaciones registradas')) |
|
return |
|
|
|
for chat in reversed(chat_history): |
|
try: |
|
|
|
timestamp = datetime.fromisoformat(chat['timestamp'].replace('Z', '+00:00')) |
|
formatted_date = timestamp.strftime("%d/%m/%Y %H:%M:%S") |
|
|
|
with st.expander( |
|
f"{t.get('chat_date', 'Fecha de conversación')}: {formatted_date}", |
|
expanded=False |
|
): |
|
if 'messages' in chat and chat['messages']: |
|
|
|
for message in chat['messages']: |
|
role = message.get('role', 'unknown') |
|
content = message.get('content', '') |
|
|
|
|
|
with st.chat_message(role): |
|
st.markdown(content) |
|
|
|
|
|
st.divider() |
|
else: |
|
st.warning(t.get('invalid_chat_format', 'Formato de chat no válido')) |
|
|
|
except Exception as e: |
|
logger.error(f"Error mostrando conversación: {str(e)}") |
|
continue |
|
|
|
except Exception as e: |
|
logger.error(f"Error mostrando historial del chat: {str(e)}") |
|
st.error(t.get('error_chat', 'Error al mostrar historial del chat')) |
|
|