Spaces:
Running
Running
| # 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(""" | |
| <style> | |
| .graph-container { | |
| background-color: white; | |
| border-radius: 10px; | |
| padding: 20px; | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
| margin: 15px 0; | |
| } | |
| .interpretation-box { | |
| background-color: #f8f9fa; | |
| border-left: 4px solid #0d6efd; | |
| padding: 15px; | |
| margin: 10px 0; | |
| } | |
| .metric-indicator { | |
| font-size: 1.2em; | |
| font-weight: 500; | |
| color: #1f2937; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # 1. Riqueza de Vocabulario | |
| with st.expander("📚 Riqueza de Vocabulario", expanded=True): | |
| st.markdown('<div class="graph-container">', 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('<div class="interpretation-box">', 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("</div>", unsafe_allow_html=True) | |
| st.markdown("</div>", unsafe_allow_html=True) | |
| # 2. Estructura de Oraciones | |
| with st.expander("🏗️ Complejidad Estructural", expanded=True): | |
| st.markdown('<div class="graph-container">', unsafe_allow_html=True) | |
| syntax_graph = create_syntax_complexity_graph(doc) | |
| if syntax_graph: | |
| st.pyplot(syntax_graph) | |
| plt.close(syntax_graph) | |
| st.markdown('<div class="interpretation-box">', 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("</div>", unsafe_allow_html=True) | |
| st.markdown("</div>", unsafe_allow_html=True) | |
| # 3. Cohesión Textual | |
| with st.expander("🔄 Cohesión del Texto", expanded=True): | |
| st.markdown('<div class="graph-container">', unsafe_allow_html=True) | |
| cohesion_map = create_cohesion_heatmap(doc) | |
| if cohesion_map: | |
| st.pyplot(cohesion_map) | |
| plt.close(cohesion_map) | |
| st.markdown('<div class="interpretation-box">', 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("</div>", unsafe_allow_html=True) | |
| st.markdown("</div>", 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}" | |
| )) |