| | import streamlit as st |
| | import matplotlib.pyplot as plt |
| | import pandas as pd |
| | import io |
| | import base64 |
| | from spacy import displacy |
| | import re |
| | from .morpho_analysis import POS_COLORS, POS_TRANSLATIONS |
| | from .auth import authenticate_user, register_user, get_user_role |
| | from .database import get_student_data, store_analysis_result |
| | from .morpho_analysis import get_repeated_words_colors, highlight_repeated_words |
| | from .syntax_analysis import visualize_syntax |
| |
|
| | |
| | def login_register_page(): |
| | st.title("AIdeaText") |
| | |
| | tab1, tab2 = st.tabs(["Iniciar Sesión", "Registrarse"]) |
| | |
| | with tab1: |
| | login_form() |
| | |
| | with tab2: |
| | register_form() |
| |
|
| | |
| | def login_form(): |
| | username = st.text_input("Usuario") |
| | password = st.text_input("Contraseña", type='password') |
| | captcha_answer = st.text_input("Captcha: ¿Cuánto es 2 + 3?") |
| | |
| | if st.button("Iniciar Sesión"): |
| | if captcha_answer == "5": |
| | if authenticate_user(username, password): |
| | st.success(f"Bienvenido, {username}!") |
| | st.session_state.logged_in = True |
| | st.session_state.username = username |
| | st.session_state.role = get_user_role(username) |
| | st.experimental_rerun() |
| | else: |
| | st.error("Usuario o contraseña incorrectos") |
| | else: |
| | st.error("Captcha incorrecto") |
| |
|
| | |
| | def register_form(): |
| | new_username = st.text_input("Nuevo Usuario") |
| | new_password = st.text_input("Nueva Contraseña", type='password') |
| | carrera = st.text_input("Carrera") |
| | captcha_answer = st.text_input("Captcha: ¿Cuánto es 3 + 4?") |
| | |
| | if st.button("Registrarse"): |
| | if captcha_answer == "7": |
| | additional_info = {'carrera': carrera} |
| | if register_user(new_username, new_password, additional_info): |
| | st.success("Registro exitoso. Por favor, inicia sesión.") |
| | else: |
| | st.error("El usuario ya existe o ocurrió un error durante el registro") |
| | else: |
| | st.error("Captcha incorrecto") |
| |
|
| | |
| | def display_chat_interface(): |
| | st.markdown("### Chat con AIdeaText") |
| |
|
| | if 'chat_history' not in st.session_state: |
| | st.session_state.chat_history = [] |
| |
|
| | for i, (role, text) in enumerate(st.session_state.chat_history): |
| | if role == "user": |
| | st.text_area(f"Tú:", value=text, height=50, key=f"user_message_{i}", disabled=True) |
| | else: |
| | st.text_area(f"AIdeaText:", value=text, height=50, key=f"bot_message_{i}", disabled=True) |
| |
|
| | user_input = st.text_input("Escribe tu mensaje aquí:") |
| |
|
| | if st.button("Enviar"): |
| | if user_input: |
| | st.session_state.chat_history.append(("user", user_input)) |
| | response = get_chatbot_response(user_input) |
| | st.session_state.chat_history.append(("bot", response)) |
| | st.experimental_rerun() |
| |
|
| | |
| | def display_student_progress(username, lang_code='es'): |
| | student_data = get_student_data(username) |
| | |
| | if student_data is None: |
| | st.warning("No se encontraron datos para este estudiante.") |
| | st.info("Intenta realizar algunos análisis de texto primero.") |
| | return |
| |
|
| | st.title(f"Progreso de {username}") |
| |
|
| | if student_data['entries_count'] > 0: |
| | if 'word_count' in student_data and student_data['word_count']: |
| | st.subheader("Total de palabras por categoría gramatical") |
| | |
| | df = pd.DataFrame(list(student_data['word_count'].items()), columns=['category', 'count']) |
| | df['label'] = df.apply(lambda x: f"{POS_TRANSLATIONS[lang_code].get(x['category'], x['category'])}", axis=1) |
| | |
| | df = df.sort_values('count', ascending=False) |
| | |
| | fig, ax = plt.subplots(figsize=(12, 6)) |
| | bars = ax.bar(df['label'], df['count'], color=[POS_COLORS.get(cat, '#CCCCCC') for cat in df['category']]) |
| | |
| | ax.set_xlabel('Categoría Gramatical') |
| | ax.set_ylabel('Cantidad de Palabras') |
| | ax.set_title('Total de palabras por categoría gramatical') |
| | plt.xticks(rotation=45, ha='right') |
| | |
| | for bar in bars: |
| | height = bar.get_height() |
| | ax.text(bar.get_x() + bar.get_width()/2., height, |
| | f'{height}', |
| | ha='center', va='bottom') |
| | |
| | plt.tight_layout() |
| | |
| | buf = io.BytesIO() |
| | fig.savefig(buf, format='png') |
| | buf.seek(0) |
| | st.image(buf, use_column_width=True) |
| | else: |
| | st.info("No hay datos de conteo de palabras disponibles.") |
| | |
| | st.header("Diagramas de Arco") |
| | with st.expander("Ver todos los Diagramas de Arco"): |
| | for i, entry in enumerate(student_data['entries']): |
| | if 'arc_diagrams' in entry and entry['arc_diagrams']: |
| | st.subheader(f"Entrada {i+1} - {entry['timestamp']}") |
| | st.write(entry['arc_diagrams'][0], unsafe_allow_html=True) |
| | |
| | st.header("Diagramas de Red") |
| | with st.expander("Ver todos los Diagramas de Red"): |
| | for i, entry in enumerate(student_data['entries']): |
| | if 'network_diagram' in entry and entry['network_diagram']: |
| | st.subheader(f"Entrada {i+1} - {entry['timestamp']}") |
| | try: |
| | image_bytes = base64.b64decode(entry['network_diagram']) |
| | st.image(image_bytes) |
| | except Exception as e: |
| | st.error(f"Error al mostrar el diagrama de red: {str(e)}") |
| | else: |
| | st.warning("No se encontraron entradas para este estudiante.") |
| | st.info("Intenta realizar algunos análisis de texto primero.") |
| |
|
| | |
| | def display_text_analysis_interface(nlp_models, lang_code): |
| | translations = { |
| | 'es': { |
| | 'title': "AIdeaText - Análisis morfológico y sintáctico", |
| | 'input_label': "Ingrese un texto para analizar (máx. 5,000 palabras):", |
| | 'input_placeholder': "El objetivo de esta aplicación es que mejore sus habilidades de redacción...", |
| | 'analyze_button': "Analizar texto", |
| | 'repeated_words': "Palabras repetidas", |
| | 'legend': "Leyenda: Categorías gramaticales", |
| | 'arc_diagram': "Análisis sintáctico: Diagrama de arco", |
| | 'network_diagram': "Análisis sintáctico: Diagrama de red", |
| | 'sentence': "Oración" |
| | }, |
| | 'en': { |
| | 'title': "AIdeaText - Morphological and Syntactic Analysis", |
| | 'input_label': "Enter a text to analyze (max 5,000 words):", |
| | 'input_placeholder': "The goal of this app is for you to improve your writing skills...", |
| | 'analyze_button': "Analyze text", |
| | 'repeated_words': "Repeated words", |
| | 'legend': "Legend: Grammatical categories", |
| | 'arc_diagram': "Syntactic analysis: Arc diagram", |
| | 'network_diagram': "Syntactic analysis: Network diagram", |
| | 'sentence': "Sentence" |
| | }, |
| | 'fr': { |
| | 'title': "AIdeaText - Analyse morphologique et syntaxique", |
| | 'input_label': "Entrez un texte à analyser (max 5 000 mots) :", |
| | 'input_placeholder': "Le but de cette application est d'améliorer vos compétences en rédaction...", |
| | 'analyze_button': "Analyser le texte", |
| | 'repeated_words': "Mots répétés", |
| | 'legend': "Légende : Catégories grammaticales", |
| | 'arc_diagram': "Analyse syntaxique : Diagramme en arc", |
| | 'network_diagram': "Analyse syntaxique : Diagramme de réseau", |
| | 'sentence': "Phrase" |
| | } |
| | } |
| |
|
| | t = translations[lang_code] |
| |
|
| | if 'input_text' not in st.session_state: |
| | st.session_state.input_text = "" |
| |
|
| | sentence_input = st.text_area( |
| | t['input_label'], |
| | height=150, |
| | placeholder=t['input_placeholder'], |
| | value=st.session_state.input_text, |
| | key=f"text_input_{lang_code}" |
| | ) |
| | st.session_state.input_text = sentence_input |
| |
|
| | if st.button(t['analyze_button'], key=f"analyze_button_{lang_code}"): |
| | if sentence_input: |
| | doc = nlp_models[lang_code](sentence_input) |
| |
|
| | with st.expander(t['repeated_words'], expanded=True): |
| | word_colors = get_repeated_words_colors(doc) |
| | highlighted_text = highlight_repeated_words(doc, word_colors) |
| | st.markdown(highlighted_text, unsafe_allow_html=True) |
| |
|
| | st.markdown(f"##### {t['legend']}") |
| | legend_html = "<div style='display: flex; flex-wrap: wrap;'>" |
| | for pos, color in POS_COLORS.items(): |
| | if pos in POS_TRANSLATIONS: |
| | legend_html += f"<div style='margin-right: 10px;'><span style='background-color: {color}; padding: 2px 5px;'>{POS_TRANSLATIONS[pos]}</span></div>" |
| | legend_html += "</div>" |
| | st.markdown(legend_html, unsafe_allow_html=True) |
| |
|
| | with st.expander(t['arc_diagram'], expanded=True): |
| | sentences = list(doc.sents) |
| | arc_diagrams = [] |
| | for i, sent in enumerate(sentences): |
| | st.subheader(f"{t['sentence']} {i+1}") |
| | html = displacy.render(sent, style="dep", options={"distance": 100}) |
| | html = html.replace('height="375"', 'height="200"') |
| | html = re.sub(r'<svg[^>]*>', lambda m: m.group(0).replace('height="450"', 'height="300"'), html) |
| | html = re.sub(r'<g [^>]*transform="translate\((\d+),(\d+)\)"', lambda m: f'<g transform="translate({m.group(1)},50)"', html) |
| | st.write(html, unsafe_allow_html=True) |
| | arc_diagrams.append(html) |
| |
|
| | with st.expander(t['network_diagram'], expanded=True): |
| | fig = visualize_syntax(sentence_input, nlp_models[lang_code], lang_code) |
| | st.pyplot(fig) |
| |
|
| | if store_analysis_result( |
| | st.session_state.username, |
| | sentence_input, |
| | word_colors, |
| | arc_diagrams, |
| | fig |
| | ): |
| | st.success("Análisis guardado correctamente.") |
| | else: |
| | st.error("Hubo un problema al guardar el análisis. Por favor, inténtelo de nuevo.") |
| | st.error(f"Falló el guardado del análisis. Username: {st.session_state.username}") |
| |
|
| | |
| | def get_chatbot_response(input_text): |
| | |
| | |
| | return "Lo siento, el chatbot no está disponible en este momento." |