# modules/studentact/current_situation_interface.py import streamlit as st import logging from ..utils.widget_utils import generate_unique_key from .current_situation_analysis import ( analyze_text_dimensions, create_vocabulary_network, create_syntax_complexity_graph, create_cohesion_heatmap ) logger = logging.getLogger(__name__) def display_current_situation_interface(lang_code, nlp_models, t): """ Interfaz modular para el análisis de la situación actual del estudiante. Esta función maneja la presentación y la interacción con el usuario. Args: lang_code: Código del idioma actual nlp_models: Diccionario de modelos de spaCy cargados t: Diccionario de traducciones """ st.markdown("## Mi Situación Actual de Escritura") # Container principal para mejor organización visual with st.container(): # Columnas para entrada y visualización text_col, visual_col = st.columns([1,2]) with text_col: # Área de entrada de texto text_input = st.text_area( t.get('current_situation_input', "Ingresa tu texto para analizar:"), height=400, key=generate_unique_key("current_situation", "input") ) # Botón de análisis if st.button( t.get('analyze_button', "Explorar mi escritura"), type="primary", disabled=not text_input, key=generate_unique_key("current_situation", "analyze") ): try: with st.spinner(t.get('processing', "Analizando texto...")): # 1. Procesar el texto doc = nlp_models[lang_code](text_input) metrics = analyze_text_dimensions(doc) # 2. Mostrar visualizaciones en la columna derecha with visual_col: display_current_situation_visual(doc, metrics) # 3. Obtener retroalimentación de Claude feedback = get_claude_feedback(metrics, text_input) # 4. Guardar los resultados from ..database.current_situation_mongo_db import store_current_situation_result if st.button(t.get('analyze_button', "Explorar mi escritura")): with st.spinner(t.get('processing', "Analizando texto...")): # Procesar y analizar doc = nlp_models[lang_code](text_input) # Obtener métricas con manejo de errores try: metrics = analyze_text_dimensions(doc) except Exception as e: logger.error(f"Error en análisis: {str(e)}") st.error("Error en el análisis de dimensiones") return # Obtener feedback try: feedback = get_claude_feedback(metrics, text_input) except Exception as e: logger.error(f"Error obteniendo feedback: {str(e)}") st.error("Error obteniendo retroalimentación") return # Guardar resultados con verificación if store_current_situation_result( st.session_state.username, text_input, metrics, feedback ): st.success(t.get('save_success', "Análisis guardado")) # Mostrar visualizaciones y recomendaciones display_current_situation_visual(doc, metrics) show_recommendations(feedback, t) else: st.error("Error al guardar el análisis") except Exception as e: logger.error(f"Error en interfaz: {str(e)}") st.error("Error general en la interfaz") ################################################################ def display_current_situation_visual(doc, metrics): """Visualización mejorada de resultados con interpretaciones""" try: with st.container(): # Estilos CSS mejorados para los contenedores st.markdown(""" """, unsafe_allow_html=True) # 1. Riqueza de Vocabulario with st.expander("📚 Riqueza de Vocabulario", expanded=True): st.markdown('
', unsafe_allow_html=True) vocabulary_graph = create_vocabulary_network(doc) if vocabulary_graph: # Mostrar gráfico st.pyplot(vocabulary_graph) plt.close(vocabulary_graph) # Interpretación st.markdown('
', unsafe_allow_html=True) st.markdown("**¿Qué significa este gráfico?**") st.markdown(""" - 🔵 Los nodos azules representan palabras clave en tu texto - 📏 El tamaño de cada nodo indica su frecuencia de uso - 🔗 Las líneas conectan palabras que aparecen juntas frecuentemente - 🎨 Los colores más intensos indican palabras más centrales """) st.markdown("
", unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) # 2. Estructura de Oraciones with st.expander("🏗️ Complejidad Estructural", expanded=True): st.markdown('
', unsafe_allow_html=True) syntax_graph = create_syntax_complexity_graph(doc) if syntax_graph: st.pyplot(syntax_graph) plt.close(syntax_graph) st.markdown('
', unsafe_allow_html=True) st.markdown("**Análisis de la estructura:**") st.markdown(""" - 📊 Las barras muestran la complejidad de cada oración - 📈 Mayor altura indica estructuras más elaboradas - 🎯 La línea punteada indica el nivel óptimo de complejidad - 🔄 Variación en las alturas sugiere dinamismo en la escritura """) st.markdown("
", unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) # 3. Cohesión Textual with st.expander("🔄 Cohesión del Texto", expanded=True): st.markdown('
', unsafe_allow_html=True) cohesion_map = create_cohesion_heatmap(doc) if cohesion_map: st.pyplot(cohesion_map) plt.close(cohesion_map) st.markdown('
', unsafe_allow_html=True) st.markdown("**¿Cómo leer el mapa de calor?**") st.markdown(""" - 🌈 Colores más intensos indican mayor conexión entre oraciones - 📝 La diagonal muestra la coherencia interna de cada oración - 🔗 Las zonas claras sugieren oportunidades de mejorar conexiones - 🎯 Un buen texto muestra patrones de color consistentes """) st.markdown("
", unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) # 4. Métricas Generales with st.expander("📊 Resumen de Métricas", expanded=True): col1, col2, col3 = st.columns(3) with col1: st.metric( "Diversidad Léxica", f"{metrics['vocabulary_richness']:.2f}/1.0", help="Mide la variedad de palabras diferentes utilizadas" ) with col2: st.metric( "Complejidad Estructural", f"{metrics['structural_complexity']:.2f}/1.0", help="Indica qué tan elaboradas son las estructuras de las oraciones" ) with col3: st.metric( "Cohesión Textual", f"{metrics['cohesion_score']:.2f}/1.0", help="Evalúa qué tan bien conectadas están las ideas entre sí" ) except Exception as e: logger.error(f"Error en visualización: {str(e)}") st.error("Error al generar las visualizaciones") ################################################################ def show_recommendations(feedback, t): """ Muestra las recomendaciones y ejercicios personalizados para el estudiante, permitiendo el seguimiento de su progreso. Args: feedback: Diccionario con retroalimentación y ejercicios recomendados t: Diccionario de traducciones """ st.markdown("### " + t.get('recommendations_title', "Recomendaciones para mejorar")) for area, exercises in feedback['recommendations'].items(): with st.expander(f"💡 {area}"): try: # Descripción del área de mejora st.markdown(exercises['description']) # Obtener el historial de ejercicios del estudiante from ..database.current_situation_mongo_db import get_student_exercises_history exercises_history = get_student_exercises_history(st.session_state.username) # Separar ejercicios en completados y pendientes completed = exercises_history.get(area, []) # Mostrar estado actual progress_col1, progress_col2 = st.columns([3,1]) with progress_col1: st.markdown("**Ejercicio sugerido:**") st.markdown(exercises['activity']) with progress_col2: # Verificar si el ejercicio ya está completado exercise_key = f"{area}_{exercises['activity']}" is_completed = exercise_key in completed if is_completed: st.success("✅ Completado") else: # Botón para marcar ejercicio como completado if st.button( t.get('mark_complete', "Marcar como completado"), key=generate_unique_key("exercise", area), type="primary" ): try: from ..database.current_situation_mongo_db import update_exercise_status # Actualizar estado del ejercicio success = update_exercise_status( username=st.session_state.username, area=area, exercise=exercises['activity'], completed=True ) if success: st.success(t.get( 'exercise_completed', "¡Ejercicio marcado como completado!" )) st.rerun() else: st.error(t.get( 'exercise_error', "Error al actualizar el estado del ejercicio" )) except Exception as e: logger.error(f"Error actualizando estado del ejercicio: {str(e)}") st.error(t.get('update_error', "Error al actualizar el ejercicio")) # Mostrar recursos adicionales si existen if 'resources' in exercises: st.markdown("**Recursos adicionales:**") for resource in exercises['resources']: st.markdown(f"- {resource}") # Mostrar fecha de finalización si está completado if is_completed: completion_date = exercises_history[exercise_key].get('completion_date') if completion_date: st.caption( t.get('completed_on', "Completado el") + f": {completion_date.strftime('%d/%m/%Y %H:%M')}" ) except Exception as e: logger.error(f"Error mostrando recomendaciones para {area}: {str(e)}") st.error(t.get( 'recommendations_error', f"Error al mostrar las recomendaciones para {area}" ))