File size: 20,213 Bytes
44d2f4e
7d2b8ec
43b44fb
7d2b8ec
 
43b44fb
 
e19483a
43b44fb
7d2b8ec
44d2f4e
 
 
1e95929
8f792a0
44d2f4e
cec31c3
9f78896
90e40b9
2f0c295
cec31c3
7d2b8ec
26486d0
 
 
3ece79a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60e4a0a
3ece79a
39800a0
c0718a1
60e4a0a
 
 
 
39800a0
3ece79a
 
39800a0
 
 
290f988
39800a0
 
 
 
 
 
 
 
 
 
 
290f988
39800a0
3ece79a
 
 
25af5c0
3ece79a
 
 
 
26486d0
 
7d2b8ec
8d6379a
e5d0ce8
7d2b8ec
 
e5d0ce8
 
 
 
 
 
7d2b8ec
e5d0ce8
 
 
 
 
 
 
 
 
 
5a27028
6f9a88d
5a27028
e5d0ce8
 
5a27028
 
26486d0
8d6379a
 
7d2b8ec
8d6379a
 
 
 
 
 
 
7d2b8ec
8d6379a
7d2b8ec
8d6379a
 
 
 
 
 
 
26486d0
7d2b8ec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26486d0
7d2b8ec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26486d0
ee5cd97
6d01086
7d2b8ec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5f1328a
 
ee5cd97
 
 
7d2b8ec
5f1328a
 
 
 
7d2b8ec
 
 
 
ee5cd97
 
5f1328a
7d2b8ec
 
 
ee5cd97
 
 
4a52be9
 
 
7d2b8ec
 
 
4a52be9
7d2b8ec
 
 
ee5cd97
 
7d2b8ec
 
4a52be9
7d2b8ec
 
 
 
 
 
 
 
 
 
 
4a52be9
a972c69
7d2b8ec
ee5cd97
7d2b8ec
 
 
 
 
 
4f8d08e
 
7d2b8ec
c810a25
 
 
 
 
8b900da
c810a25
9addec4
c810a25
 
 
8b900da
c810a25
9addec4
c810a25
 
 
8b900da
c810a25
9addec4
c810a25
 
 
 
 
8b900da
c810a25
8b900da
 
 
 
c810a25
8b900da
8189f16
9addec4
7236d98
 
8b900da
31d258b
 
 
 
 
 
 
 
 
e442b89
31d258b
 
 
 
 
 
e442b89
31d258b
 
 
 
 
 
e442b89
31d258b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55ec21b
31d258b
e442b89
 
 
 
 
55ec21b
e442b89
 
55ec21b
31d258b
26486d0
7e9e1b6
cec31c3
 
 
e19483a
cec31c3
e19483a
cec31c3
 
e19483a
cec31c3
e19483a
cec31c3
 
e19483a
cec31c3
e19483a
cec31c3
 
 
e19483a
098b351
cec31c3
 
 
16dcc0e
098b351
c4ed35f
e19483a
098b351
c4ed35f
8a2688a
3fdaa70
 
c4ed35f
8a2688a
c4ed35f
3fdaa70
098b351
e68d122
3fdaa70
e68d122
c4ed35f
 
 
 
 
3fdaa70
c4ed35f
 
bd565ef
c4ed35f
bd565ef
c4ed35f
 
bd565ef
 
 
c4ed35f
3fdaa70
c4ed35f
8576dc4
e68d122
 
3fdaa70
 
8d6379a
5a27028
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
#Importaciones generales
import streamlit as st
import re
import io
import base64
import matplotlib.pyplot as plt
import pandas as pd
import time
from streamlit_player import st_player  # Necesitarás instalar esta librería: pip install streamlit-player
from spacy import displacy

#Importaciones locales
#Importaciones locales de autenticación y base de datos 
from .auth import authenticate_user, register_user
from .database import get_student_data, store_morphosyntax_result, store_semantic_result, store_chat_history

#Importaciones locales funciones de análisis
from .morpho_analysis import generate_arc_diagram, get_repeated_words_colors, highlight_repeated_words, POS_COLORS, POS_TRANSLATIONS
from .semantic_analysis import visualize_semantic_relations, perform_semantic_analysis
from .discourse_analysis import compare_semantic_analysis, perform_discourse_analysis
from .chatbot import initialize_chatbot, get_chatbot_response

##################################################################################################
def login_register_page():
    st.title("AIdeaText")

    # Dividir la pantalla en dos columnas
    left_column, right_column = st.columns([1, 3])  # 25% izquierda, 75% derecha

    # Sección izquierda para login y registro
    with left_column:
        tab1, tab2 = st.tabs(["Iniciar Sesión", "Registrarse"])
        
        with tab1:
            login_form()
        
        with tab2:
            register_form()

    # Sección derecha para videos de YouTube
    with right_column:
        st.header("Videos: pitch, demos, entrevistas, otros")
        
        # Diccionario de videos de YouTube con títulos amigables
        videos = {
            "Intro AideaText": "https://www.youtube.com/watch?v=UA-md1VxaRc",
            "Pitch que facilitó acceder a la segunda fase de IFE Explora del TEC de Monterrey": "https://www.youtube.com/watch?v=Fqi4Di_Rj_s",
            "Entrevista con el doctor Guillermo Ruíz, EduMate Lima Perú" : "https://www.youtube.com/watch?v=_ch8cRja3oc",
            "Demo versión desktop de AIdeaText": "https://www.youtube.com/watch?v=nP6eXbog-ZY"
        }
        
        # Selector de video
        video_titles = list(videos.keys())
        if video_titles:
            selected_title = st.selectbox("Selecciona un video tutorial:", video_titles)
            
            # Obtener la URL correspondiente al título seleccionado
            if selected_title in videos:
                selected_video = videos[selected_title]
                
                # Reproductor de YouTube
                try:
                    st_player(selected_video)
                except Exception as e:
                    st.error(f"Error al cargar el video: {str(e)}")
            else:
                st.warning("El video seleccionado no está disponible.")
        else:
            st.warning("No hay videos disponibles para mostrar.")

        # Información adicional
        st.markdown("""
        ## Novedades de la versión actual
        - Nueva función de análisis semántico
        - Soporte para múltiples idiomas
        - Interfaz mejorada para una mejor experiencia de usuario
        """)

##################################################################################################
def login_form():
    username = st.text_input("Correo electrónico")
    password = st.text_input("Contraseña", type="password")
    
    if st.button("Iniciar Sesión"):
        success, role = authenticate_user(username, password)
        if success:
            st.session_state.logged_in = True
            st.session_state.username = username
            st.session_state.role = role
            st.experimental_rerun()
        else:
            st.error("Credenciales incorrectas")

##################################################################################################
def main():
    if 'logged_in' not in st.session_state:
        st.session_state.logged_in = False

    if not st.session_state.logged_in:
        login_register_page()
    else:
        print(f"Rol del usuario: {st.session_state.role}")  # Depuración
        if st.session_state.role == 'Administrador':
            print("Redirigiendo a la página de administrador")  # Depuración
            admin_page()
        else:
            print("Redirigiendo a la página de usuario normal")  # Depuración
            user_page()
##################################################################################################
def admin_page():
    st.title("Panel de Administración")
    
    # Crear nuevo usuario
    st.header("Crear Nuevo Usuario")
    new_username = st.text_input("Correo electrónico del nuevo usuario")
    new_password = st.text_input("Contraseña", type="password")
    if st.button("Crear Usuario"):
        if create_invited_user(new_username, new_password):
            st.success(f"Usuario {new_username} creado exitosamente")
        else:
            st.error("Error al crear el usuario")

    # Aquí puedes añadir más funcionalidades CRUD en el futuro

##################################################################################################
def register_form():
    ##
    ##
    pass
##################################################################################################
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_morphosyntax_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",
            '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",
            '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",
            'sentence': "Phrase"
        }
    }

    t = translations[lang_code]

    input_key = f"morphosyntax_input_{lang_code}"

    # Inicializar la clave en session_state si no existe
    if input_key not in st.session_state:
        st.session_state[input_key] = ""

    # Función para actualizar el estado del input
    def update_input():
        st.session_state[input_key] = st.session_state[f"text_area_{lang_code}"]

    sentence_input = st.text_area(
        t['input_label'],
        height=150,
        placeholder=t['input_placeholder'],
        value=st.session_state[input_key],
        key=f"text_area_{lang_code}",
        on_change=update_input
    )

    if st.button(t['analyze_button'], key=f"analyze_button_{lang_code}"):
        current_input = st.session_state[input_key]
        if current_input:
            doc = nlp_models[lang_code](current_input)
            
            word_colors = get_repeated_words_colors(doc)
            
            with st.expander(t['repeated_words'], expanded=True):
                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[lang_code]:
                    legend_html += f"<div style='margin-right: 10px;'><span style='background-color: {color}; padding: 2px 5px;'>{POS_TRANSLATIONS[lang_code][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)
            
            if store_morphosyntax_result(
                st.session_state.username,
                current_input,
                word_colors,
                arc_diagrams,
            ):
                st.success("Análisis guardado correctamente.")
            else:
                st.error("Hubo un problema al guardar el análisis. Por favor, inténtelo de nuevo.")
        else:
            st.warning("Por favor, ingrese un texto para analizar.")

###############################################################################################################
def display_semantic_analysis_interface(nlp_models, lang_code):
    translations = {
        'es': {
            'title': "AIdeaText - Análisis semántico",
            'file_uploader': "Cargar archivo de texto",
            'analyze_button': "Analizar texto",
            'semantic_relations': "Relaciones Semánticas Relevantes",
        },
        'en': {
            'title': "AIdeaText - Semantic Analysis",
            'file_uploader': "Upload text file",
            'analyze_button': "Analyze text",
            'semantic_relations': "Relevant Semantic Relations",
        },
        'fr': {
            'title': "AIdeaText - Analyse sémantique",
            'file_uploader': "Télécharger le fichier texte",
            'analyze_button': "Analyser le texte",
            'semantic_relations': "Relations Sémantiques Pertinentes",
        }
    }

    t = translations[lang_code]

    st.header(t['title'])

    uploaded_file = st.file_uploader(t['file_uploader'], type=['txt'])

    if uploaded_file is not None:
        text_content = uploaded_file.getvalue().decode('utf-8')

        if st.button(t['analyze_button']):
            relations_graph = perform_semantic_analysis(text_content, nlp_models[lang_code], lang_code)

            with st.expander(t['semantic_relations'], expanded=True):
                st.pyplot(relations_graph)

##################################################################################################

def display_discourse_analysis_interface(nlp_models, lang_code):
    translations = {
        'es': {
            'title': "AIdeaText - Análisis del discurso",
            'file_uploader1': "Cargar archivo de texto 1 (Patrón)",
            'file_uploader2': "Cargar archivo de texto 2 (Comparación)",
            'analyze_button': "Analizar textos",
            'comparison': "Comparación de Relaciones Semánticas",
        },
        'en': {
            'title': "AIdeaText - Discourse Analysis",
            'file_uploader1': "Upload text file 1 (Pattern)",
            'file_uploader2': "Upload text file 2 (Comparison)",
            'analyze_button': "Analyze texts",
            'comparison': "Comparison of Semantic Relations",
        },
        'fr': {
            'title': "AIdeaText - Analyse du discours",
            'file_uploader1': "Télécharger le fichier texte 1 (Modèle)",
            'file_uploader2': "Télécharger le fichier texte 2 (Comparaison)",
            'analyze_button': "Analyser les textes",
            'comparison': "Comparaison des Relations Sémantiques",
        }
    }

    t = translations[lang_code]

    st.header(t['title'])

    col1, col2 = st.columns(2)

    with col1:
        uploaded_file1 = st.file_uploader(t['file_uploader1'], type=['txt'])

    with col2:
        uploaded_file2 = st.file_uploader(t['file_uploader2'], type=['txt'])

    if uploaded_file1 is not None and uploaded_file2 is not None:
        text_content1 = uploaded_file1.getvalue().decode('utf-8')
        text_content2 = uploaded_file2.getvalue().decode('utf-8')

        if st.button(t['analyze_button']):
            graph1, graph2 = perform_discourse_analysis(text_content1, text_content2, nlp_models[lang_code], lang_code)

            st.subheader(t['comparison'])
            
            col1, col2 = st.columns(2)
            
            with col1:
                st.pyplot(graph1)
            
            with col2:
                st.pyplot(graph2)

##################################################################################################

def display_chatbot_interface(lang_code):
    translations = {
        'es': {
            'title': "Expertos en Vacaciones",
            'input_placeholder': "Escribe tu mensaje aquí...",
            'initial_message': "¡Hola! ¿Cómo podemos ayudarte?"
        },
        'en': {
            'title': "Vacation Experts",
            'input_placeholder': "Type your message here...",
            'initial_message': "Hi! How can we help you?"
        },
        'fr': {
            'title': "Experts en Vacances",
            'input_placeholder': "Écrivez votre message ici...",
            'initial_message': "Bonjour! Comment pouvons-nous vous aider?"
        }
    }
    t = translations[lang_code]
    st.title(t['title'])

    if 'chatbot' not in st.session_state:
        st.session_state.chatbot = initialize_chatbot()
    if 'messages' not in st.session_state:
        st.session_state.messages = [{"role": "assistant", "content": t['initial_message']}]

    # Contenedor principal para el chat
    chat_container = st.container()

    # Mostrar mensajes existentes
    with chat_container:
        for message in st.session_state.messages:
            with st.chat_message(message["role"]):
                st.markdown(message["content"])

    # Área de entrada del usuario
    user_input = st.chat_input(t['input_placeholder'])

    if user_input:
        # Agregar mensaje del usuario
        st.session_state.messages.append({"role": "user", "content": user_input})
        
        # Mostrar mensaje del usuario
        with chat_container:
            with st.chat_message("user"):
                st.markdown(user_input)

        # Generar respuesta del chatbot
        with chat_container:
            with st.chat_message("assistant"):
                message_placeholder = st.empty()
                full_response = ""
                
                for chunk in get_chatbot_response(st.session_state.chatbot, user_input, lang_code):
                    full_response += chunk
                    message_placeholder.markdown(full_response + "▌")
                message_placeholder.markdown(full_response)

        # Agregar respuesta del asistente a los mensajes
        st.session_state.messages.append({"role": "assistant", "content": full_response})
        
        # Guardar la conversación en la base de datos
        store_chat_history(st.session_state.username, st.session_state.messages)

    # Scroll al final del chat
    st.markdown('<script>window.scrollTo(0,document.body.scrollHeight);</script>', unsafe_allow_html=True)

######################################################
if __name__ == "__main__":
    main()