AIdeaText commited on
Commit
c58df45
1 Parent(s): f0f8520

Upload 216 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. app.py +150 -0
  2. assets/img/AIdeaTextCard.jpg +0 -0
  3. assets/img/Mesa de trabajo 1png 0.3.png +0 -0
  4. assets/img/logo_92x92.jpg +0 -0
  5. assets/img/logo_92x92.png +0 -0
  6. assets/img/text.txt +0 -0
  7. modules/23-7-2024_auth.py +135 -0
  8. modules/23-7-2024_ui.py +344 -0
  9. modules/__init__.py +112 -0
  10. modules/__init__Old-V3.py +180 -0
  11. modules/__pycache__/__init__.cpython-311.pyc +0 -0
  12. modules/admin/__init__.py +0 -0
  13. modules/admin/__pycache__/__init__.cpython-311.pyc +0 -0
  14. modules/admin/__pycache__/admin_ui.cpython-311.pyc +0 -0
  15. modules/admin/admin_ui.py +49 -0
  16. modules/admin/txt.txt +0 -0
  17. modules/auth/__init__.py +0 -0
  18. modules/auth/__pycache__/__init__.cpython-311.pyc +0 -0
  19. modules/auth/__pycache__/auth.cpython-311.pyc +0 -0
  20. modules/auth/auth.py +119 -0
  21. modules/auth/txt.txt +0 -0
  22. modules/chatbot/__init__.py +0 -0
  23. modules/chatbot/__pycache__/__init__.cpython-311.pyc +0 -0
  24. modules/chatbot/__pycache__/chatbot.cpython-311.pyc +0 -0
  25. modules/chatbot/chatbot.py +46 -0
  26. modules/chatbot/chatbot_open_Source_Model-test.py +124 -0
  27. modules/chatbot/txt.txt +0 -0
  28. modules/database/__init__.py +0 -0
  29. modules/database/__pycache__/__init__.cpython-311.pyc +0 -0
  30. modules/database/__pycache__/chat_db.cpython-311.pyc +0 -0
  31. modules/database/__pycache__/database.cpython-311.pyc +0 -0
  32. modules/database/__pycache__/database_init.cpython-311.pyc +0 -0
  33. modules/database/__pycache__/database_oldFromV2.cpython-311.pyc +0 -0
  34. modules/database/__pycache__/mongo_db.cpython-311.pyc +0 -0
  35. modules/database/__pycache__/morphosintax_db.cpython-311.pyc +0 -0
  36. modules/database/__pycache__/morphosintax_mongo_db.cpython-311.pyc +0 -0
  37. modules/database/__pycache__/morphosintaxis_export.cpython-311.pyc +0 -0
  38. modules/database/__pycache__/sql_db.cpython-311.pyc +0 -0
  39. modules/database/backUp/database.py +216 -0
  40. modules/database/backUp/databaseBackUp23-9-24.py +581 -0
  41. modules/database/backUp/database_oldFromV2.py +473 -0
  42. modules/database/backUp/database_v3-2ok.py +629 -0
  43. modules/database/chat_db.py +45 -0
  44. modules/database/database_init.py +80 -0
  45. modules/database/mongo_db.py +51 -0
  46. modules/database/morphosintax_mongo_db.py +49 -0
  47. modules/database/morphosintaxis_export.py +78 -0
  48. modules/database/morphosintaxis_export_v1.py +97 -0
  49. modules/database/sql_db.py +129 -0
  50. modules/database/txt.txt +0 -0
app.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #app.py de v3
2
+ #app.py
3
+ import logging
4
+ import streamlit as st
5
+ import sys
6
+ import os
7
+ from dotenv import load_dotenv
8
+ from datetime import datetime
9
+
10
+ def setup_logging():
11
+ log_dir = 'logs'
12
+ if not os.path.exists(log_dir):
13
+ os.makedirs(log_dir)
14
+ current_time = datetime.now().strftime("%Y%m%d_%H%M%S")
15
+ log_filename = f'{log_dir}/app_log_{current_time}.txt'
16
+ logging.basicConfig(
17
+ level=logging.DEBUG,
18
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
19
+ filename=log_filename,
20
+ filemode='w'
21
+ )
22
+ console = logging.StreamHandler()
23
+ console.setLevel(logging.INFO)
24
+ formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
25
+ console.setFormatter(formatter)
26
+ logging.getLogger('').addHandler(console)
27
+ logging.info(f"Logging iniciado. Archivo de log: {log_filename}")
28
+
29
+ setup_logging()
30
+ load_dotenv()
31
+
32
+ st.set_page_config(page_title="AIdeaText", layout="wide", page_icon="random")
33
+
34
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
35
+
36
+ #########IMPORTACIONES LOCALES#######################################
37
+ from translations import get_translations
38
+
39
+ from session_state import initialize_session_state
40
+
41
+ from modules.ui.ui import main as ui_main
42
+
43
+ from modules.utils.spacy_utils import load_spacy_models
44
+
45
+ from modules.morphosyntax.morphosyntax_interface import (
46
+ display_morphosyntax_interface
47
+ )
48
+
49
+ ###Importaciones de la base de datos###
50
+ from modules.database.database_init import (
51
+ initialize_database_connections
52
+ )
53
+
54
+ from modules.database.sql_db import (
55
+ create_student_user,
56
+ get_student_user,
57
+ update_student_user,
58
+ delete_student_user,
59
+ store_application_request,
60
+ store_student_feedback
61
+ )
62
+
63
+
64
+ from modules.database.mongo_db import (
65
+ get_collection,
66
+ insert_document,
67
+ find_documents,
68
+ update_document,
69
+ delete_document
70
+ )
71
+
72
+ from modules.database.morphosintax_mongo_db import (
73
+ store_student_morphosyntax_result,
74
+ get_student_morphosyntax_analysis
75
+ )
76
+
77
+ from modules.database.chat_db import (
78
+ store_chat_history,
79
+ get_chat_history
80
+ )
81
+
82
+ from modules.studentact.student_activities_v2 import (
83
+ display_student_progress
84
+ )
85
+
86
+ from modules.auth.auth import (
87
+ authenticate_student,
88
+ register_student,
89
+ update_student_info,
90
+ delete_student
91
+ )
92
+
93
+ from modules.admin.admin_ui import admin_page
94
+
95
+ from modules.chatbot.chatbot import (
96
+ initialize_chatbot,
97
+ process_chat_input
98
+ )
99
+
100
+ print("Configurando página")
101
+ st.cache_data.clear()
102
+ st.cache_resource.clear()
103
+
104
+ logging.basicConfig(level=logging.INFO)
105
+ logger = logging.getLogger(__name__)
106
+
107
+ @st.cache_resource
108
+ def initialize_nlp_models():
109
+ logger.info("Cargando modelos de spaCy")
110
+ models = load_spacy_models()
111
+ logger.info("Modelos de spaCy cargados exitosamente")
112
+ return models
113
+
114
+ def app_main():
115
+ try:
116
+ logger.info("Entrando en app_main()")
117
+
118
+ # Inicializar el estado de la sesión
119
+ initialize_session_state()
120
+
121
+ # Inicializar conexiones a bases de datos si no se ha hecho
122
+ if 'db_initialized' not in st.session_state:
123
+ st.session_state.db_initialized = initialize_database_connections()
124
+
125
+ # Cargar modelos NLP si no se ha hecho
126
+ if 'nlp_models' not in st.session_state:
127
+ logger.info("Inicializando modelos NLP en la sesión")
128
+ st.session_state.nlp_models = initialize_nlp_models()
129
+ logger.info("Modelos NLP inicializados y almacenados en la sesión")
130
+
131
+ # Configurar la página inicial si no está configurada
132
+ if 'page' not in st.session_state:
133
+ st.session_state.page = 'login'
134
+
135
+ logger.info(f"Página actual: {st.session_state.page}")
136
+ logger.info(f"Rol del usuario: {st.session_state.role}")
137
+
138
+ # Dirigir el flujo a la interfaz de usuario principal
139
+ logger.info(f"Llamando a ui_main() desde app_main()")
140
+ ui_main()
141
+
142
+ except Exception as e:
143
+ logger.error(f"Error en app_main: {str(e)}", exc_info=True)
144
+ st.error("Se ha producido un error en la aplicación. Por favor, inténtelo de nuevo más tarde.")
145
+ if st.button("Reiniciar aplicación"):
146
+ st.rerun()
147
+
148
+ if __name__ == "__main__":
149
+ print("Llamando a app_main()")
150
+ app_main()
assets/img/AIdeaTextCard.jpg ADDED
assets/img/Mesa de trabajo 1png 0.3.png ADDED
assets/img/logo_92x92.jpg ADDED
assets/img/logo_92x92.png ADDED
assets/img/text.txt ADDED
File without changes
modules/23-7-2024_auth.py ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### auth.py
2
+ import os
3
+ from azure.cosmos import CosmosClient, exceptions
4
+ import bcrypt
5
+ import base64
6
+
7
+ ################################################################################################################
8
+ def clean_and_validate_key(key):
9
+ key = key.strip()
10
+ while len(key) % 4 != 0:
11
+ key += '='
12
+ try:
13
+ base64.b64decode(key)
14
+ return key
15
+ except:
16
+ raise ValueError("La clave proporcionada no es válida")
17
+
18
+ # Azure Cosmos DB configuration
19
+ endpoint = os.environ.get("COSMOS_ENDPOINT")
20
+ key = os.environ.get("COSMOS_KEY")
21
+
22
+ if not endpoint or not key:
23
+ raise ValueError("Las variables de entorno COSMOS_ENDPOINT y COSMOS_KEY deben estar configuradas")
24
+
25
+ key = clean_and_validate_key(key)
26
+
27
+ try:
28
+ client = CosmosClient(endpoint, key)
29
+ database = client.get_database_client("user_database")
30
+ container = database.get_container_client("users")
31
+ # Prueba de conexión
32
+ database_list = list(client.list_databases())
33
+ print(f"Conexión exitosa. Bases de datos encontradas: {len(database_list)}")
34
+ except Exception as e:
35
+ print(f"Error al conectar con Cosmos DB: {str(e)}")
36
+ raise
37
+
38
+ #############################################################################################################3
39
+ def hash_password(password):
40
+ """Hash a password for storing."""
41
+ return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
42
+
43
+ ################################################################################################################
44
+ def verify_password(stored_password, provided_password):
45
+ """Verify a stored password against one provided by user"""
46
+ return bcrypt.checkpw(provided_password.encode('utf-8'), stored_password.encode('utf-8'))
47
+
48
+ ################################################################################################################
49
+ def register_user(username, password, additional_info=None):
50
+ try:
51
+ query = f"SELECT * FROM c WHERE c.id = '{username}'"
52
+ existing_user = list(container.query_items(query=query, enable_cross_partition_query=True))
53
+
54
+ if existing_user:
55
+ return False # User already exists
56
+
57
+ new_user = {
58
+ 'id': username,
59
+ 'password': hash_password(password),
60
+ 'role': 'Estudiante',
61
+ 'additional_info': additional_info or {}
62
+ }
63
+
64
+ new_user['partitionKey'] = username
65
+
66
+ container.create_item(body=new_user)
67
+ return True
68
+ except exceptions.CosmosHttpResponseError as e:
69
+ print(f"Error al registrar usuario: {str(e)}")
70
+ return False
71
+
72
+
73
+ ################################################################################################################
74
+ def authenticate_user(username, password):
75
+ """Authenticate a user."""
76
+ try:
77
+ query = f"SELECT * FROM c WHERE c.id = '{username}'"
78
+ results = list(container.query_items(query=query, partition_key=username))
79
+
80
+ if results:
81
+ stored_user = results[0]
82
+ if verify_password(stored_user['password'], password):
83
+ return True
84
+ except exceptions.CosmosHttpResponseError:
85
+ pass
86
+
87
+ return False
88
+
89
+
90
+ ################################################################################################################
91
+ def get_user_role(username):
92
+ """Get the role of a user."""
93
+ try:
94
+ query = f"SELECT c.role FROM c WHERE c.id = '{username}'"
95
+ results = list(container.query_items(query=query, partition_key=username))
96
+
97
+ if results:
98
+ return results[0]['role']
99
+ except exceptions.CosmosHttpResponseError:
100
+ pass
101
+
102
+ return None
103
+
104
+ ################################################################################################################
105
+ def update_user_info(username, new_info):
106
+ """Update user information."""
107
+ try:
108
+ query = f"SELECT * FROM c WHERE c.id = '{username}'"
109
+ results = list(container.query_items(query=query, partition_key=username))
110
+
111
+ if results:
112
+ user = results[0]
113
+ user['additional_info'].update(new_info)
114
+ container.upsert_item(user, partition_key=username)
115
+ return True
116
+ except exceptions.CosmosHttpResponseError:
117
+ pass
118
+
119
+ return False
120
+
121
+ ################################################################################################################
122
+ def delete_user(username):
123
+ """Delete a user."""
124
+ try:
125
+ query = f"SELECT * FROM c WHERE c.id = '{username}'"
126
+ results = list(container.query_items(query=query, partition_key=username))
127
+
128
+ if results:
129
+ user = results[0]
130
+ container.delete_item(item=user['id'], partition_key=username)
131
+ return True
132
+ except exceptions.CosmosHttpResponseError:
133
+ pass
134
+
135
+ return False
modules/23-7-2024_ui.py ADDED
@@ -0,0 +1,344 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # modules/ui.py
2
+ # Importaciones estandar de python
3
+ import io
4
+ import streamlit as st
5
+ import matplotlib
6
+ matplotlib.use('Agg')
7
+ import matplotlib.pyplot as plt
8
+ import squarify
9
+ import pandas as pd
10
+ from datetime import datetime
11
+ import base64
12
+ from spacy import displacy
13
+ import re
14
+ from .morpho_analysis import POS_COLORS, POS_TRANSLATIONS # Asegúrate de que esta importación esté presente
15
+ print("POS_COLORS:", POS_COLORS)
16
+ print("POS_TRANSLATIONS:", POS_TRANSLATIONS)
17
+
18
+ # Importaciones locales
19
+ from .auth import authenticate_user, register_user, get_user_role
20
+ from .database import get_student_data, store_analysis_result
21
+ from .morpho_analysis import get_repeated_words_colors, highlight_repeated_words, POS_COLORS, POS_TRANSLATIONS
22
+ from .syntax_analysis import visualize_syntax
23
+
24
+ #########################################################################
25
+ # Define colors for grammatical categories
26
+ POS_COLORS = {
27
+ 'ADJ': '#FFA07A', # Light Salmon
28
+ 'ADP': '#98FB98', # Pale Green
29
+ 'ADV': '#87CEFA', # Light Sky Blue
30
+ 'AUX': '#DDA0DD', # Plum
31
+ 'CCONJ': '#F0E68C', # Khaki
32
+ 'DET': '#FFB6C1', # Light Pink
33
+ 'INTJ': '#FF6347', # Tomato
34
+ 'NOUN': '#90EE90', # Light Green
35
+ 'NUM': '#FAFAD2', # Light Goldenrod Yellow
36
+ 'PART': '#D3D3D3', # Light Gray
37
+ 'PRON': '#FFA500', # Orange
38
+ 'PROPN': '#20B2AA', # Light Sea Green
39
+ 'SCONJ': '#DEB887', # Burlywood
40
+ 'SYM': '#7B68EE', # Medium Slate Blue
41
+ 'VERB': '#FF69B4', # Hot Pink
42
+ 'X': '#A9A9A9', # Dark Gray
43
+ }
44
+
45
+ POS_TRANSLATIONS = {
46
+ 'es': {
47
+ 'ADJ': 'Adjetivo',
48
+ 'ADP': 'Adposición',
49
+ 'ADV': 'Adverbio',
50
+ 'AUX': 'Auxiliar',
51
+ 'CCONJ': 'Conjunción Coordinante',
52
+ 'DET': 'Determinante',
53
+ 'INTJ': 'Interjección',
54
+ 'NOUN': 'Sustantivo',
55
+ 'NUM': 'Número',
56
+ 'PART': 'Partícula',
57
+ 'PRON': 'Pronombre',
58
+ 'PROPN': 'Nombre Propio',
59
+ 'SCONJ': 'Conjunción Subordinante',
60
+ 'SYM': 'Símbolo',
61
+ 'VERB': 'Verbo',
62
+ 'X': 'Otro',
63
+ },
64
+ 'en': {
65
+ 'ADJ': 'Adjective',
66
+ 'ADP': 'Adposition',
67
+ 'ADV': 'Adverb',
68
+ 'AUX': 'Auxiliary',
69
+ 'CCONJ': 'Coordinating Conjunction',
70
+ 'DET': 'Determiner',
71
+ 'INTJ': 'Interjection',
72
+ 'NOUN': 'Noun',
73
+ 'NUM': 'Number',
74
+ 'PART': 'Particle',
75
+ 'PRON': 'Pronoun',
76
+ 'PROPN': 'Proper Noun',
77
+ 'SCONJ': 'Subordinating Conjunction',
78
+ 'SYM': 'Symbol',
79
+ 'VERB': 'Verb',
80
+ 'X': 'Other',
81
+ },
82
+ 'fr': {
83
+ 'ADJ': 'Adjectif',
84
+ 'ADP': 'Adposition',
85
+ 'ADV': 'Adverbe',
86
+ 'AUX': 'Auxiliaire',
87
+ 'CCONJ': 'Conjonction de Coordination',
88
+ 'DET': 'Déterminant',
89
+ 'INTJ': 'Interjection',
90
+ 'NOUN': 'Nom',
91
+ 'NUM': 'Nombre',
92
+ 'PART': 'Particule',
93
+ 'PRON': 'Pronom',
94
+ 'PROPN': 'Nom Propre',
95
+ 'SCONJ': 'Conjonction de Subordination',
96
+ 'SYM': 'Symbole',
97
+ 'VERB': 'Verbe',
98
+ 'X': 'Autre',
99
+ }
100
+ }
101
+
102
+ ##########################################################################
103
+ def login_page():
104
+ st.title("Iniciar Sesión")
105
+ username = st.text_input("Usuario")
106
+ password = st.text_input("Contraseña", type='password')
107
+ if st.button("Iniciar Sesión"):
108
+ if authenticate_user(username, password):
109
+ st.success(f"Bienvenido, {username}!")
110
+ st.session_state.logged_in = True
111
+ st.session_state.username = username
112
+ st.session_state.role = get_user_role(username)
113
+ st.experimental_rerun()
114
+ else:
115
+ st.error("Usuario o contraseña incorrectos")
116
+
117
+ ##########################################################################
118
+ def register_page():
119
+ st.title("Registrarse")
120
+ new_username = st.text_input("Nuevo Usuario")
121
+ new_password = st.text_input("Nueva Contraseña", type='password')
122
+
123
+ additional_info = {}
124
+ additional_info['carrera'] = st.text_input("Carrera")
125
+
126
+ if st.button("Registrarse"):
127
+ if register_user(new_username, new_password, additional_info):
128
+ st.success("Registro exitoso. Por favor, inicia sesión.")
129
+ else:
130
+ st.error("El usuario ya existe o ocurrió un error durante el registro")
131
+
132
+ ##########################################################################
133
+ def get_chatbot_response(input_text):
134
+ # Esta función debe ser implementada o importada de otro módulo
135
+ # Por ahora, retornamos un mensaje genérico
136
+ return "Lo siento, el chatbot no está disponible en este momento."
137
+
138
+ ##########################################################################
139
+ def display_chat_interface():
140
+ st.markdown("### Chat con AIdeaText")
141
+
142
+ if 'chat_history' not in st.session_state:
143
+ st.session_state.chat_history = []
144
+
145
+ for i, (role, text) in enumerate(st.session_state.chat_history):
146
+ if role == "user":
147
+ st.text_area(f"Tú:", value=text, height=50, key=f"user_message_{i}", disabled=True)
148
+ else:
149
+ st.text_area(f"AIdeaText:", value=text, height=50, key=f"bot_message_{i}", disabled=True)
150
+
151
+ user_input = st.text_input("Escribe tu mensaje aquí:")
152
+
153
+ if st.button("Enviar"):
154
+ if user_input:
155
+ st.session_state.chat_history.append(("user", user_input))
156
+ response = get_chatbot_response(user_input)
157
+ st.session_state.chat_history.append(("bot", response))
158
+ st.experimental_rerun()
159
+
160
+ ##########################################################################
161
+
162
+ def display_student_progress(username, lang_code='es'):
163
+ print("lang_code:", lang_code)
164
+ student_data = get_student_data(username)
165
+
166
+ if student_data is None:
167
+ st.warning("No se encontraron datos para este estudiante.")
168
+ st.info("Intenta realizar algunos análisis de texto primero.")
169
+ return
170
+
171
+ st.title(f"Progreso de {username}")
172
+
173
+ if student_data['entries_count'] > 0:
174
+ if 'word_count' in student_data and student_data['word_count']:
175
+ st.subheader("Total de palabras por categoría gramatical")
176
+
177
+ df = pd.DataFrame(list(student_data['word_count'].items()), columns=['category', 'count'])
178
+ df['label'] = df.apply(lambda x: f"{POS_TRANSLATIONS[lang_code].get(x['category'], x['category'])}", axis=1)
179
+
180
+ # Ordenar el DataFrame por conteo de palabras, de mayor a menor
181
+ df = df.sort_values('count', ascending=False)
182
+
183
+ fig, ax = plt.subplots(figsize=(12, 6))
184
+ bars = ax.bar(df['label'], df['count'], color=[POS_COLORS.get(cat, '#CCCCCC') for cat in df['category']])
185
+
186
+ ax.set_xlabel('Categoría Gramatical')
187
+ ax.set_ylabel('Cantidad de Palabras')
188
+ ax.set_title('Total de palabras por categoría gramatical')
189
+ plt.xticks(rotation=45, ha='right')
190
+
191
+ # Añadir etiquetas de valor en las barras
192
+ for bar in bars:
193
+ height = bar.get_height()
194
+ ax.text(bar.get_x() + bar.get_width()/2., height,
195
+ f'{height}',
196
+ ha='center', va='bottom')
197
+
198
+ plt.tight_layout()
199
+
200
+ buf = io.BytesIO()
201
+ fig.savefig(buf, format='png')
202
+ buf.seek(0)
203
+ st.image(buf, use_column_width=True)
204
+ else:
205
+ st.info("No hay datos de conteo de palabras disponibles.")
206
+
207
+ # Diagramas de Arco (consolidados)
208
+ st.header("Diagramas de Arco")
209
+ with st.expander("Ver todos los Diagramas de Arco"):
210
+ for i, entry in enumerate(student_data['entries']):
211
+ if 'arc_diagrams' in entry and entry['arc_diagrams']:
212
+ st.subheader(f"Entrada {i+1} - {entry['timestamp']}")
213
+ st.write(entry['arc_diagrams'][0], unsafe_allow_html=True)
214
+
215
+ # Diagramas de Red (consolidados)
216
+ st.header("Diagramas de Red")
217
+ with st.expander("Ver todos los Diagramas de Red"):
218
+ for i, entry in enumerate(student_data['entries']):
219
+ if 'network_diagram' in entry and entry['network_diagram']:
220
+ st.subheader(f"Entrada {i+1} - {entry['timestamp']}")
221
+ try:
222
+ # Decodificar la imagen base64
223
+ image_bytes = base64.b64decode(entry['network_diagram'])
224
+ st.image(image_bytes)
225
+ except Exception as e:
226
+ st.error(f"Error al mostrar el diagrama de red: {str(e)}")
227
+ else:
228
+ st.warning("No se encontraron entradas para este estudiante.")
229
+ st.info("Intenta realizar algunos análisis de texto primero.")
230
+
231
+ ##############################################################Mostrar entradas recientes######################################################################
232
+ #st.header("Entradas Recientes")
233
+ #for i, entry in enumerate(student_data['entries'][:5]): # Mostrar las 5 entradas más recientes
234
+ #with st.expander(f"Entrada {i+1} - {entry['timestamp']}"):
235
+ #st.write(entry['text'])
236
+ #else:
237
+ #st.warning("No se encontraron entradas para este estudiante.")
238
+ #st.info("Intenta realizar algunos análisis de texto primero.")
239
+
240
+ ##########################################################################
241
+ def display_text_analysis_interface(nlp_models, lang_code):
242
+ translations = {
243
+ 'es': {
244
+ 'title': "AIdeaText - Análisis morfológico y sintáctico",
245
+ 'input_label': "Ingrese un texto para analizar (máx. 5,000 palabras):",
246
+ 'input_placeholder': "El objetivo de esta aplicación es que mejore sus habilidades de redacción. Para ello, después de ingresar su texto y presionar el botón obtendrá tres vistas horizontales. La primera, le indicará las palabras que se repiten por categoría gramátical; la segunda, un diagrama de arco le indicara las conexiones sintácticas en cada oración; y la tercera, es un grafo en el cual visualizara la configuración de su texto.",
247
+ 'analyze_button': "Analizar texto",
248
+ 'repeated_words': "Palabras repetidas",
249
+ 'legend': "Leyenda: Categorías gramaticales",
250
+ 'arc_diagram': "Análisis sintáctico: Diagrama de arco",
251
+ 'network_diagram': "Análisis sintáctico: Diagrama de red",
252
+ 'sentence': "Oración"
253
+ },
254
+ 'en': {
255
+ 'title': "AIdeaText - Morphological and Syntactic Analysis",
256
+ 'input_label': "Enter a text to analyze (max 5,000 words):",
257
+ 'input_placeholder': "The goal of this app is for you to improve your writing skills. To do this, after entering your text and pressing the button you will get three horizontal views. The first will indicate the words that are repeated by grammatical category; second, an arc diagram will indicate the syntactic connections in each sentence; and the third is a graph in which you will visualize the configuration of your text.",
258
+ 'analyze_button': "Analyze text",
259
+ 'repeated_words': "Repeated words",
260
+ 'legend': "Legend: Grammatical categories",
261
+ 'arc_diagram': "Syntactic analysis: Arc diagram",
262
+ 'network_diagram': "Syntactic analysis: Network diagram",
263
+ 'sentence': "Sentence"
264
+ },
265
+ 'fr': {
266
+ 'title': "AIdeaText - Analyse morphologique et syntaxique",
267
+ 'input_label': "Entrez un texte à analyser (max 5 000 mots) :",
268
+ 'input_placeholder': "Le but de cette application est d'améliorer vos compétences en rédaction. Pour ce faire, après avoir saisi votre texte et appuyé sur le bouton vous obtiendrez trois vues horizontales. Le premier indiquera les mots répétés par catégorie grammaticale; deuxièmement, un diagramme en arcs indiquera les connexions syntaxiques dans chaque phrase; et le troisième est un graphique dans lequel vous visualiserez la configuration de votre texte.",
269
+ 'analyze_button': "Analyser le texte",
270
+ 'repeated_words': "Mots répétés",
271
+ 'legend': "Légende : Catégories grammaticales",
272
+ 'arc_diagram': "Analyse syntaxique : Diagramme en arc",
273
+ 'network_diagram': "Analyse syntaxique : Diagramme de réseau",
274
+ 'sentence': "Phrase"
275
+ }
276
+ }
277
+
278
+ t = translations[lang_code]
279
+
280
+ if 'input_text' not in st.session_state:
281
+ st.session_state.input_text = ""
282
+
283
+ # Añadimos una clave única basada en el idioma seleccionado
284
+ sentence_input = st.text_area(
285
+ t['input_label'],
286
+ height=150,
287
+ placeholder=t['input_placeholder'],
288
+ value=st.session_state.input_text,
289
+ key=f"text_input_{lang_code}" # Clave única basada en el idioma
290
+ )
291
+ st.session_state.input_text = sentence_input
292
+
293
+ # sentence_input = st.text_area(t['input_label'], height=150, placeholder=t['input_placeholder'], value=st.session_state.input_text)
294
+ # st.session_state.input_text = sentence_input
295
+
296
+ if st.button(t['analyze_button'], key=f"analyze_button_{lang_code}"):
297
+ if sentence_input:
298
+ doc = nlp_models[lang_code](sentence_input)
299
+
300
+ with st.expander(t['repeated_words'], expanded=True):
301
+ word_colors = get_repeated_words_colors(doc)
302
+ highlighted_text = highlight_repeated_words(doc, word_colors)
303
+ st.markdown(highlighted_text, unsafe_allow_html=True)
304
+
305
+ st.markdown(f"##### {t['legend']}")
306
+ legend_html = "<div style='display: flex; flex-wrap: wrap;'>"
307
+ for pos, color in POS_COLORS.items():
308
+ if pos in POS_TRANSLATIONS:
309
+ legend_html += f"<div style='margin-right: 10px;'><span style='background-color: {color}; padding: 2px 5px;'>{POS_TRANSLATIONS[pos]}</span></div>"
310
+ legend_html += "</div>"
311
+ st.markdown(legend_html, unsafe_allow_html=True)
312
+
313
+ with st.expander(t['arc_diagram'], expanded=True):
314
+ sentences = list(doc.sents)
315
+ arc_diagrams = []
316
+ for i, sent in enumerate(sentences):
317
+ st.subheader(f"{t['sentence']} {i+1}")
318
+ html = displacy.render(sent, style="dep", options={"distance": 100})
319
+ html = html.replace('height="375"', 'height="200"')
320
+ html = re.sub(r'<svg[^>]*>', lambda m: m.group(0).replace('height="450"', 'height="300"'), html)
321
+ html = re.sub(r'<g [^>]*transform="translate\((\d+),(\d+)\)"', lambda m: f'<g transform="translate({m.group(1)},50)"', html)
322
+ st.write(html, unsafe_allow_html=True)
323
+ arc_diagrams.append(html)
324
+
325
+ with st.expander(t['network_diagram'], expanded=True):
326
+ fig = visualize_syntax(sentence_input, nlp_models[lang_code], lang_code)
327
+ st.pyplot(fig)
328
+
329
+ if store_analysis_result(
330
+ st.session_state.username,
331
+ sentence_input,
332
+ word_colors,
333
+ arc_diagrams,
334
+ fig
335
+ ):
336
+ st.success("Análisis guardado correctamente.")
337
+ else:
338
+ st.error("Hubo un problema al guardar el análisis. Por favor, inténtelo de nuevo.")
339
+ st.error(f"Falló el guardado del análisis. Username: {st.session_state.username}")
340
+
341
+ ##########################################################################
342
+ def display_teacher_interface():
343
+ st.write("Bienvenido, profesor. Aquí podrás ver el progreso de tus estudiantes.")
344
+ # Aquí puedes agregar la lógica para mostrar el progreso de los estudiantes
modules/__init__.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # modules/__init__.py
2
+
3
+ def load_auth_functions():
4
+ from .auth.auth import authenticate_student, register_student, update_student_info, delete_student
5
+ return {
6
+ 'authenticate_student': authenticate_student,
7
+ 'register_student': register_student,
8
+ 'update_student_info': update_student_info,
9
+ 'delete_student': delete_student
10
+ }
11
+
12
+ def load_database_functions():
13
+
14
+ from .database.database_init import (
15
+ initialize_database_connections
16
+ )
17
+
18
+ from .database.sql_db import (
19
+ create_student_user,
20
+ get_student_user,
21
+ update_student_user,
22
+ delete_student_user,
23
+ store_application_request,
24
+ store_student_feedback
25
+ )
26
+ from .database.mongo_db import (
27
+ get_collection,
28
+ insert_document,
29
+ find_documents,
30
+ update_document,
31
+ delete_document,
32
+ )
33
+ from .database.morphosintax_mongo_db import (
34
+ store_student_morphosyntax_result,
35
+ get_student_morphosyntax_analysis,
36
+ update_student_morphosyntax_analysis,
37
+ delete_student_morphosyntax_analysis,
38
+ get_student_morphosyntax_data
39
+ )
40
+ from .database.chat_db import store_chat_history, get_chat_history
41
+
42
+ return {
43
+ 'initialize_database_connections': initialize_database_connections,
44
+ 'create_student_user': create_student_user,
45
+ 'get_student_user': get_student_user,
46
+ 'update_student_user': update_student_user,
47
+ 'delete_student_user': delete_student_user,
48
+ 'store_application_request': store_application_request,
49
+ 'store_student_feedback': store_student_feedback,
50
+ 'get_collection': get_collection,
51
+ 'insert_document': insert_document,
52
+ 'find_documents': find_documents,
53
+ 'update_document': update_document,
54
+ 'delete_document': delete_document,
55
+ 'store_student_morphosyntax_result': store_student_morphosyntax_result,
56
+ 'get_student_morphosyntax_analysis': get_student_morphosyntax_analysis,
57
+ 'update_student_morphosyntax_analysis': update_student_morphosyntax_analysis,
58
+ 'delete_student_morphosyntax_analysis': delete_student_morphosyntax_analysis,
59
+ 'get_student_morphosyntax_data': get_student_morphosyntax_data,
60
+ 'store_chat_history': store_chat_history,
61
+ 'get_chat_history': get_chat_history
62
+ }
63
+
64
+ def load_ui_functions():
65
+ # No importamos nada de ui.py aquí
66
+ return {} # Retornamos un diccionario vacío
67
+
68
+ def load_student_activities_functions():
69
+ from .studentact.student_activities import display_student_progress
70
+ return {
71
+ 'display_student_progress': display_student_progress
72
+ }
73
+
74
+ def load_morphosyntax_functions():
75
+ from .morphosyntax.morphosyntax_interface import display_morphosyntax_interface
76
+ from .morphosyntax.morphosyntax_process import process_morphosyntactic_input
77
+ return {
78
+ 'display_morphosyntax_interface': display_morphosyntax_interface,
79
+ 'process_morphosyntactic_input': process_morphosyntactic_input
80
+ }
81
+
82
+ def load_admin_functions():
83
+ from .admin.admin_ui import admin_page
84
+ return {
85
+ 'admin_page': admin_page
86
+ }
87
+
88
+ def load_utils_functions():
89
+ from .utils.spacy_utils import load_spacy_models
90
+ return {
91
+ 'load_spacy_models': load_spacy_models
92
+ }
93
+
94
+ def load_chatbot_functions():
95
+ from .chatbot.chatbot import initialize_chatbot, process_chat_input
96
+ return {
97
+ 'initialize_chatbot': initialize_chatbot,
98
+ 'process_chat_input': process_chat_input
99
+ }
100
+
101
+ # Función para cargar todas las funciones
102
+ def load_all_functions():
103
+ return {
104
+ **load_auth_functions(),
105
+ **load_database_functions(),
106
+ # **load_ui_functions(),
107
+ **load_admin_functions(),
108
+ **load_morphosyntax_functions(),
109
+ **load_utils_functions(),
110
+ **load_chatbot_functions(),
111
+ **load_student_activities_functions()
112
+ }
modules/__init__Old-V3.py ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # modules/__init__.py
2
+
3
+ def load_auth_functions():
4
+ from .auth.auth import authenticate_user, register_user
5
+ return {
6
+ 'authenticate_user': authenticate_user,
7
+ 'register_user': register_user
8
+ }
9
+
10
+ def load_database_function():
11
+ from .database.database_oldFromV2 import (
12
+ initialize_mongodb_connection,
13
+ initialize_database_connections,
14
+ create_admin_user,
15
+ create_student_user,
16
+ get_user,
17
+ get_student_data,
18
+ get_user_files,
19
+ delete_file,
20
+ store_application_request,
21
+ store_user_feedback,
22
+ store_morphosyntax_result,
23
+ store_semantic_result,
24
+ store_discourse_analysis_result,
25
+ store_chat_history,
26
+ export_analysis_and_chat,
27
+ manage_file_contents
28
+ )
29
+ return {
30
+ 'initialize_mongodb_connection': initialize_mongodb_connection,
31
+ 'initialize_database_connections': initialize_database_connections,
32
+ 'create_admin_user': create_admin_user,
33
+ 'create_student_user': create_student_user,
34
+ 'get_user': get_user,
35
+ 'get_student_data': get_student_data,
36
+ 'get_user_files': get_user_files,
37
+ 'delete_file': delete_file,
38
+ 'store_application_request': store_application_request,
39
+ 'store_user_feedback': store_user_feedback,
40
+ 'store_morphosyntax_result': store_morphosyntax_result,
41
+ 'store_semantic_result': store_semantic_result,
42
+ 'store_discourse_analysis_result': store_discourse_analysis_result,
43
+ 'store_chat_history': store_chat_history,
44
+ 'export_analysis_and_chat': export_analysis_and_chat,
45
+ 'manage_file_contents': manage_file_contents
46
+ }
47
+
48
+ def load_ui_functions():
49
+ # No importamos nada de ui.py aquí
50
+ return {} # Retornamos un diccionario vacío
51
+
52
+
53
+ def load_student_activities_functions():
54
+ from .studentact.student_activities_v2 import display_student_progress
55
+ return {
56
+ 'display_student_progress': display_student_progress
57
+ }
58
+
59
+ def load_morphosyntax_functions():
60
+ from .morphosyntax.morphosyntax_interface import display_morphosyntax_interface
61
+ from .morphosyntax.morphosyntax_process import process_morphosyntactic_input
62
+ return {
63
+ 'display_morphosyntax_interface': display_morphosyntax_interface,
64
+ 'process_morphosyntactic_input': process_morphosyntactic_input
65
+ }
66
+
67
+ def load_semantic_functions():
68
+ from .semantic.semantic_interface_68ok import display_semantic_interface
69
+ from .semantic.semantic_process import process_semantic_input
70
+ return {
71
+ 'display_semantic_interface': display_semantic_interface,
72
+ 'process_semantic_input': process_semantic_input
73
+ }
74
+
75
+ def load_discourse_functions():
76
+ from .discourse.discourse_interface import display_discourse_interface
77
+ from .discourse.discourse_process import process_discourse_input
78
+ return {
79
+ 'display_discourse_interface': display_discourse_interface,
80
+ 'process_discourse_input': process_discourse_input
81
+ }
82
+
83
+ def load_email_functions():
84
+ from .email.email import send_email_notification
85
+ return {
86
+ 'send_email_notification': send_email_notification
87
+ }
88
+
89
+ def load_admin_functions():
90
+ from .admin.admin_ui import admin_page
91
+ return {
92
+ 'admin_page': admin_page
93
+ }
94
+
95
+ def load_text_analysis_functions():
96
+ from .text_analysis.morpho_analysis import (
97
+ generate_arc_diagram,
98
+ perform_advanced_morphosyntactic_analysis,
99
+ perform_pos_analysis,
100
+ perform_morphological_analysis,
101
+ analyze_sentence_structure,
102
+ get_repeated_words_colors,
103
+ highlight_repeated_words,
104
+ )
105
+ from .text_analysis.semantic_analysis import (
106
+ perform_semantic_analysis,
107
+ generate_summary,
108
+ extract_entities,
109
+ analyze_sentiment,
110
+ create_topic_graph,
111
+ visualize_topic_graph,
112
+ ENTITY_LABELS
113
+ )
114
+ from .text_analysis.discourse_analysis import (
115
+ perform_discourse_analysis,
116
+ compare_semantic_analysis
117
+ )
118
+ return {
119
+ 'generate_arc_diagram': generate_arc_diagram,
120
+ 'perform_advanced_morphosyntactic_analysis': perform_advanced_morphosyntactic_analysis,
121
+ 'perform_pos_analysis': perform_pos_analysis,
122
+ 'perform_morphological_analysis': perform_morphological_analysis,
123
+ 'analyze_sentence_structure': analyze_sentence_structure,
124
+ 'get_repeated_words_colors': get_repeated_words_colors,
125
+ 'highlight_repeated_words': highlight_repeated_words,
126
+ 'perform_semantic_analysis': perform_semantic_analysis,
127
+ 'generate_summary': generate_summary,
128
+ 'extract_entities': extract_entities,
129
+ 'analyze_sentiment': analyze_sentiment,
130
+ 'create_topic_graph': create_topic_graph,
131
+ 'visualize_topic_graph': visualize_topic_graph,
132
+ 'ENTITY_LABELS': ENTITY_LABELS,
133
+ 'perform_discourse_analysis': perform_discourse_analysis,
134
+ 'compare_semantic_analysis': compare_semantic_analysis
135
+ }
136
+
137
+ def load_utils_functions():
138
+ from .utils.spacy_utils import load_spacy_models
139
+ return {
140
+ 'load_spacy_models': load_spacy_models
141
+ }
142
+
143
+ def load_chatbot_functions():
144
+ from .chatbot.chatbot import (
145
+ ClaudeAPIChat,
146
+ initialize_chatbot,
147
+ process_chat_input,
148
+ get_connectors,
149
+ handle_semantic_commands,
150
+ generate_topics_visualization,
151
+ extract_topics,
152
+ get_semantic_chatbot_response
153
+ )
154
+ return {
155
+ 'ClaudeAPIChat': ClaudeAPIChat,
156
+ 'initialize_chatbot': initialize_chatbot,
157
+ 'process_chat_input': process_chat_input,
158
+ 'get_connectors': get_connectors,
159
+ 'handle_semantic_commands': handle_semantic_commands,
160
+ 'generate_topics_visualization': generate_topics_visualization,
161
+ 'extract_topics': extract_topics,
162
+ 'get_semantic_chatbot_response': get_semantic_chatbot_response
163
+ }
164
+
165
+ # Función para cargar todas las funciones
166
+ def load_all_functions():
167
+ return {
168
+ **load_auth_functions(),
169
+ **load_database_function(),
170
+ # **load_ui_functions(),
171
+ **load_admin_functions(),
172
+ **load_morphosyntax_functions(),
173
+ **load_semantic_functions(),
174
+ **load_discourse_functions(),
175
+ **load_text_analysis_functions(),
176
+ **load_utils_functions(),
177
+ **load_chatbot_functions(),
178
+ **load_email_functions()
179
+ **load_student_activities_functions() # Añadimos las nuevas funciones de actividades del estudiante
180
+ }
modules/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (4.19 kB). View file
 
modules/admin/__init__.py ADDED
File without changes
modules/admin/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (147 Bytes). View file
 
modules/admin/__pycache__/admin_ui.cpython-311.pyc ADDED
Binary file (3.07 kB). View file
 
modules/admin/admin_ui.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from ..database.sql_db import (
3
+ get_user,
4
+ get_student_user,
5
+ get_admin_user,
6
+ get_teacher_user,
7
+ create_student_user,
8
+ update_student_user,
9
+ delete_student_user
10
+ )
11
+
12
+ from ..database.morphosintax_mongo_db import get_student_morphosyntax_analysis
13
+
14
+ def admin_page():
15
+ st.title("Panel de Administración")
16
+ st.write(f"Bienvenido, {st.session_state.username}")
17
+
18
+ # Sección para crear nuevos usuarios estudiantes
19
+ st.header("Crear Nuevo Usuario Estudiante")
20
+ new_username = st.text_input("Correo electrónico del nuevo usuario", key="admin_new_username")
21
+ new_password = st.text_input("Contraseña", type="password", key="admin_new_password")
22
+ if st.button("Crear Usuario", key="admin_create_user"):
23
+ if create_student_user(new_username, new_password):
24
+ st.success(f"Usuario estudiante {new_username} creado exitosamente")
25
+ else:
26
+ st.error("Error al crear el usuario estudiante")
27
+
28
+ # Sección para ver datos de estudiantes
29
+ st.header("Ver Datos de Estudiantes")
30
+ student_username = st.text_input("Nombre de usuario del estudiante", key="admin_view_student")
31
+ if st.button("Ver Datos", key="admin_view_student_data"):
32
+ student = get_student_user(student_username)
33
+ if student:
34
+ st.write(f"Información del estudiante {student_username}:")
35
+ st.json(student)
36
+
37
+ student_data = get_student_morphosyntax_analysis(student_username)
38
+ if student_data:
39
+ st.write("Datos de análisis del estudiante:")
40
+ st.json(student_data)
41
+ else:
42
+ st.info("No hay datos de análisis para este estudiante.")
43
+ else:
44
+ st.error("Estudiante no encontrado")
45
+
46
+ # Botón para cerrar sesión
47
+ if st.button("Cerrar Sesión", key="admin_logout"):
48
+ st.session_state.clear()
49
+ st.experimental_rerun()
modules/admin/txt.txt ADDED
File without changes
modules/auth/__init__.py ADDED
File without changes
modules/auth/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (146 Bytes). View file
 
modules/auth/__pycache__/auth.cpython-311.pyc ADDED
Binary file (6.44 kB). View file
 
modules/auth/auth.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from azure.cosmos import CosmosClient, exceptions
3
+ from azure.cosmos.exceptions import CosmosHttpResponseError
4
+ import bcrypt
5
+ import base64
6
+ from ..database.sql_db import (
7
+ get_user,
8
+ get_student_user,
9
+ get_admin_user,
10
+ get_teacher_user,
11
+ create_student_user,
12
+ update_student_user,
13
+ delete_student_user
14
+ )
15
+
16
+ import logging
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ # ... (código de inicialización)
21
+ def clean_and_validate_key(key):
22
+ key = key.strip()
23
+ while len(key) % 4 != 0:
24
+ key += '='
25
+ try:
26
+ base64.b64decode(key)
27
+ return key
28
+ except:
29
+ raise ValueError("La clave proporcionada no es válida")
30
+
31
+ # Verificar las variables de entorno
32
+ endpoint = os.getenv("COSMOS_ENDPOINT")
33
+ key = os.getenv("COSMOS_KEY")
34
+
35
+ if not endpoint or not key:
36
+ raise ValueError("Las variables de entorno COSMOS_ENDPOINT y COSMOS_KEY deben estar configuradas")
37
+
38
+ key = clean_and_validate_key(key)
39
+ ####################################################
40
+
41
+
42
+ def authenticate_user(username, password):
43
+ try:
44
+ user_item = get_user(username)
45
+ if user_item and verify_password(user_item['password'], password):
46
+ logger.info(f"Usuario autenticado: {username}, Rol: {user_item['role']}")
47
+ return True, user_item['role']
48
+ logger.warning(f"Autenticación fallida para el usuario: {username}")
49
+ return False, None
50
+ except Exception as e:
51
+ logger.error(f"Error durante la autenticación del usuario: {str(e)}")
52
+ return False, None
53
+
54
+ def authenticate_admin(username, password):
55
+ return authenticate_user(username, password)
56
+
57
+ def authenticate_student(username, password):
58
+ return authenticate_user(username, password)
59
+
60
+ def authenticate_teacher(username, password):
61
+ return authenticate_user(username, password)
62
+
63
+ ############################
64
+ def register_student(username, password, additional_info=None):
65
+ try:
66
+ if get_student_user(username):
67
+ logger.warning(f"Intento de registro de estudiante existente: {username}")
68
+ return False # El estudiante ya existe
69
+
70
+ success = create_student_user(username, password, additional_info)
71
+ if success:
72
+ logger.info(f"Nuevo estudiante registrado: {username}")
73
+ return True
74
+ else:
75
+ logger.error(f"Error al registrar nuevo estudiante: {username}")
76
+ return False
77
+ except Exception as e:
78
+ logger.error(f"Error al registrar estudiante: {str(e)}")
79
+ return False
80
+
81
+ def update_student_info(username, new_info):
82
+ try:
83
+ success = update_student_user(username, new_info)
84
+ if success:
85
+ logger.info(f"Información del estudiante actualizada: {username}")
86
+ return True
87
+ else:
88
+ logger.error(f"Error al actualizar información del estudiante: {username}")
89
+ return False
90
+ except Exception as e:
91
+ logger.error(f"Error al actualizar información del estudiante: {str(e)}")
92
+ return False
93
+
94
+ def delete_student(username):
95
+ try:
96
+ success = delete_student_user(username)
97
+ if success:
98
+ logger.info(f"Estudiante eliminado: {username}")
99
+ return True
100
+ else:
101
+ logger.error(f"Error al eliminar estudiante: {username}")
102
+ return False
103
+ except Exception as e:
104
+ logger.error(f"Error al eliminar estudiante: {str(e)}")
105
+ return False
106
+
107
+
108
+ # ... (funciones de hash y verificación de contraseña)
109
+
110
+ def hash_password(password):
111
+ """Hash a password for storing."""
112
+ return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
113
+
114
+ ##################################################################################33
115
+
116
+ def verify_password(stored_password, provided_password):
117
+ """Verify a stored password against one provided by user"""
118
+ return bcrypt.checkpw(provided_password.encode('utf-8'), stored_password.encode('utf-8'))
119
+ ######################################################################################################
modules/auth/txt.txt ADDED
File without changes
modules/chatbot/__init__.py ADDED
File without changes
modules/chatbot/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (149 Bytes). View file
 
modules/chatbot/__pycache__/chatbot.cpython-311.pyc ADDED
Binary file (3.3 kB). View file
 
modules/chatbot/chatbot.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from ..text_analysis.morpho_analysis import perform_advanced_morphosyntactic_analysis
3
+ from ..text_analysis.semantic_analysis import perform_semantic_analysis
4
+ from ..text_analysis.discourse_analysis import perform_discourse_analysis
5
+
6
+ class AIdeaTextChatbot:
7
+ def __init__(self):
8
+ self.conversation_history = []
9
+
10
+ def handle_morphosyntactic_input(self, user_input, lang_code, nlp_models, t):
11
+ if user_input.startswith('/analisis_morfosintactico'):
12
+ text_to_analyze = user_input.split('[', 1)[1].rsplit(']', 1)[0]
13
+ result = perform_advanced_morphosyntactic_analysis(text_to_analyze, nlp_models[lang_code])
14
+ if result is None or 'arc_diagrams' not in result:
15
+ return t.get('morphosyntactic_analysis_error', 'Error en el análisis morfosintáctico'), None, None
16
+ return t.get('morphosyntactic_analysis_completed', 'Análisis morfosintáctico completado'), result['arc_diagrams'], result
17
+ else:
18
+ # Aquí puedes manejar otras interacciones relacionadas con el análisis morfosintáctico
19
+ return self.generate_response(user_input, lang_code), None, None
20
+
21
+
22
+ def handle_semantic_input(self, user_input, lang_code, nlp_models, t):
23
+ # Implementar lógica para análisis semántico
24
+ pass
25
+
26
+ def handle_discourse_input(self, user_input, lang_code, nlp_models, t):
27
+ # Implementar lógica para análisis de discurso
28
+ pass
29
+
30
+ def handle_generate_response(self, prompt, lang_code):
31
+ # Aquí iría la lógica para generar respuestas generales del chatbot
32
+ # Puedes usar la API de Claude aquí si lo deseas
33
+ pass
34
+
35
+ def initialize_chatbot():
36
+ return AIdeaTextChatbot()
37
+
38
+ def process_chat_input(user_input, lang_code, nlp_models, analysis_type, t, file_contents=None):
39
+ chatbot = st.session_state.get('aideatext_chatbot')
40
+ if not chatbot:
41
+ chatbot = initialize_chatbot()
42
+ st.session_state.aideatext_chatbot = chatbot
43
+
44
+ if analysis_type == 'morphosyntactic':
45
+ return chatbot.handle_morphosyntactic_input(user_input, lang_code, nlp_models, t)
46
+ # ... manejar otros tipos de análisis ...
modules/chatbot/chatbot_open_Source_Model-test.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import GPT2LMHeadModel, GPT2Tokenizer
2
+ import torch
3
+ from torch.optim import Adam
4
+ from torch.utils.data import DataLoader, Dataset
5
+ import json
6
+ import tqdm
7
+
8
+ tokenizer = GPT2Tokenizer.from_pretrained("openai-community/gpt2")
9
+ model = GPT2LMHeadModel.from_pretrained("openai-community/gpt2")
10
+
11
+ class MultilingualChatData(Dataset):
12
+ def __init__(self, file_path, tokenizer, max_length=512):
13
+ with open(file_path, 'r', encoding='utf-8') as f:
14
+ self.data = json.load(f)
15
+ self.tokenizer = tokenizer
16
+ self.max_length = max_length
17
+
18
+ def __len__(self):
19
+ return len(self.data)
20
+
21
+ def __getitem__(self, idx):
22
+ item = self.data[idx]
23
+ input_text = f"<startofstring> {item['input']} <bot>: {item['output']} <endofstring>"
24
+ encoding = self.tokenizer(input_text, truncation=True, padding='max_length', max_length=self.max_length, return_tensors="pt")
25
+ return encoding['input_ids'].squeeze(), encoding['attention_mask'].squeeze()
26
+
27
+ class MultilingualChatbot:
28
+ def __init__(self):
29
+ self.models = {
30
+ 'en': GPT2LMHeadModel.from_pretrained("microsoft/DialoGPT-medium"),
31
+ 'es': GPT2LMHeadModel.from_pretrained("DeepESP/gpt2-spanish"),
32
+ 'fr': GPT2LMHeadModel.from_pretrained("asi/gpt-fr-cased-small")
33
+ }
34
+ self.tokenizers = {
35
+ 'en': GPT2Tokenizer.from_pretrained("microsoft/DialoGPT-medium"),
36
+ 'es': GPT2Tokenizer.from_pretrained("DeepESP/gpt2-spanish"),
37
+ 'fr': GPT2Tokenizer.from_pretrained("asi/gpt-fr-cased-small")
38
+ }
39
+ for tokenizer in self.tokenizers.values():
40
+ tokenizer.pad_token = tokenizer.eos_token
41
+ tokenizer.add_special_tokens({
42
+ "bos_token": "<startofstring>",
43
+ "eos_token": "<endofstring>"
44
+ })
45
+ tokenizer.add_tokens(["<bot>:"])
46
+
47
+ for model in self.models.values():
48
+ model.resize_token_embeddings(len(self.tokenizers['en'])) # Assuming all tokenizers have the same vocabulary size
49
+
50
+ self.device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
51
+ for model in self.models.values():
52
+ model.to(self.device)
53
+
54
+ def train(self, lang, data_file, epochs=5, batch_size=32, learning_rate=1e-4):
55
+ model = self.models[lang]
56
+ tokenizer = self.tokenizers[lang]
57
+
58
+ chat_data = MultilingualChatData(data_file, tokenizer)
59
+ data_loader = DataLoader(chat_data, batch_size=batch_size, shuffle=True)
60
+
61
+ optimizer = Adam(model.parameters(), lr=learning_rate)
62
+
63
+ model.train()
64
+ for epoch in range(epochs):
65
+ total_loss = 0
66
+ for batch in tqdm.tqdm(data_loader, desc=f"Epoch {epoch+1}/{epochs}"):
67
+ input_ids, attention_mask = [b.to(self.device) for b in batch]
68
+
69
+ optimizer.zero_grad()
70
+ outputs = model(input_ids, attention_mask=attention_mask, labels=input_ids)
71
+ loss = outputs.loss
72
+ loss.backward()
73
+ optimizer.step()
74
+
75
+ total_loss += loss.item()
76
+
77
+ print(f"Epoch {epoch+1}/{epochs}, Loss: {total_loss/len(data_loader):.4f}")
78
+
79
+ torch.save(model.state_dict(), f"model_state_{lang}.pt")
80
+
81
+ def generate_response(self, prompt, src_lang):
82
+ model = self.models.get(src_lang, self.models['en'])
83
+ tokenizer = self.tokenizers.get(src_lang, self.tokenizers['en'])
84
+
85
+ input_text = f"<startofstring> {prompt} <bot>: "
86
+ input_ids = tokenizer.encode(input_text, return_tensors='pt').to(self.device)
87
+
88
+ attention_mask = torch.ones(input_ids.shape, dtype=torch.long, device=self.device)
89
+
90
+ output = model.generate(
91
+ input_ids,
92
+ attention_mask=attention_mask,
93
+ max_length=1000,
94
+ pad_token_id=tokenizer.eos_token_id,
95
+ no_repeat_ngram_size=3,
96
+ do_sample=True,
97
+ top_k=50,
98
+ top_p=0.95,
99
+ temperature=0.7,
100
+ num_return_sequences=1,
101
+ length_penalty=1.0,
102
+ repetition_penalty=1.2
103
+ )
104
+
105
+ decoded_output = tokenizer.decode(output[0], skip_special_tokens=True)
106
+ return decoded_output.split("<bot>:")[-1].strip()
107
+
108
+ def initialize_chatbot():
109
+ return MultilingualChatbot()
110
+
111
+ def get_chatbot_response(chatbot, prompt, src_lang):
112
+ return chatbot.generate_response(prompt, src_lang)
113
+
114
+ # Ejemplo de uso
115
+ if __name__ == "__main__":
116
+ chatbot = initialize_chatbot()
117
+
118
+ # Entrenar el modelo en español (asumiendo que tienes un archivo de datos en español)
119
+ chatbot.train('es', './spanish_chat_data.json', epochs=3)
120
+
121
+ # Generar respuestas
122
+ print(get_chatbot_response(chatbot, "Hola, ¿cómo estás?", 'es'))
123
+ print(get_chatbot_response(chatbot, "Hello, how are you?", 'en'))
124
+ print(get_chatbot_response(chatbot, "Bonjour, comment allez-vous?", 'fr'))
modules/chatbot/txt.txt ADDED
File without changes
modules/database/__init__.py ADDED
File without changes
modules/database/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (150 Bytes). View file
 
modules/database/__pycache__/chat_db.cpython-311.pyc ADDED
Binary file (1.78 kB). View file
 
modules/database/__pycache__/database.cpython-311.pyc ADDED
Binary file (25.1 kB). View file
 
modules/database/__pycache__/database_init.cpython-311.pyc ADDED
Binary file (4.18 kB). View file
 
modules/database/__pycache__/database_oldFromV2.cpython-311.pyc ADDED
Binary file (25.2 kB). View file
 
modules/database/__pycache__/mongo_db.cpython-311.pyc ADDED
Binary file (3.7 kB). View file
 
modules/database/__pycache__/morphosintax_db.cpython-311.pyc ADDED
Binary file (1.79 kB). View file
 
modules/database/__pycache__/morphosintax_mongo_db.cpython-311.pyc ADDED
Binary file (2.72 kB). View file
 
modules/database/__pycache__/morphosintaxis_export.cpython-311.pyc ADDED
Binary file (4.2 kB). View file
 
modules/database/__pycache__/sql_db.cpython-311.pyc ADDED
Binary file (8.24 kB). View file
 
modules/database/backUp/database.py ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # database.py
2
+ # Versión 3 actualizada para manejar chat_history_v3
3
+
4
+ import streamlit as st
5
+ import logging
6
+ import os
7
+ from pymongo import MongoClient
8
+ import certifi
9
+ from datetime import datetime, timezone
10
+ import uuid
11
+
12
+ logging.basicConfig(level=logging.DEBUG)
13
+ logger = logging.getLogger(__name__)
14
+
15
+ # Variables globales para Cosmos DB MongoDB API
16
+ mongo_client = None
17
+ mongo_db = None
18
+ analysis_collection = None
19
+ chat_collection_v3 = None # Nueva variable global para chat_history_v3
20
+
21
+ def initialize_mongodb_connection():
22
+ global mongo_client, mongo_db, analysis_collection, chat_collection_v3
23
+ try:
24
+ cosmos_mongodb_connection_string = os.getenv("MONGODB_CONNECTION_STRING")
25
+ if not cosmos_mongodb_connection_string:
26
+ logger.error("La variable de entorno MONGODB_CONNECTION_STRING no está configurada")
27
+ return False
28
+
29
+ mongo_client = MongoClient(cosmos_mongodb_connection_string,
30
+ tls=True,
31
+ tlsCAFile=certifi.where(),
32
+ retryWrites=False,
33
+ serverSelectionTimeoutMS=5000,
34
+ connectTimeoutMS=10000,
35
+ socketTimeoutMS=10000)
36
+
37
+ mongo_client.admin.command('ping')
38
+
39
+ mongo_db = mongo_client['aideatext_db']
40
+ analysis_collection = mongo_db['text_analysis']
41
+ chat_collection_v3 = mongo_db['chat_history_v3'] # Inicializar la nueva colección
42
+
43
+ # Crear índices para chat_history_v3
44
+ chat_collection_v3.create_index([("username", 1), ("timestamp", -1)])
45
+ chat_collection_v3.create_index([("username", 1), ("analysis_type", 1), ("timestamp", -1)])
46
+
47
+ logger.info("Conexión a Cosmos DB MongoDB API exitosa")
48
+ return True
49
+ except Exception as e:
50
+ logger.error(f"Error al conectar con Cosmos DB MongoDB API: {str(e)}", exc_info=True)
51
+ return False
52
+
53
+ def store_chat_history_v3(username, messages, analysis_type):
54
+ try:
55
+ logger.info(f"Guardando historial de chat para el usuario: {username}, tipo de análisis: {analysis_type}")
56
+ logger.debug(f"Mensajes a guardar: {messages}")
57
+
58
+ chat_document = {
59
+ 'username': username,
60
+ 'timestamp': datetime.now(timezone.utc).isoformat(),
61
+ 'analysis_type': analysis_type,
62
+ 'messages': messages
63
+ }
64
+ result = chat_collection_v3.insert_one(chat_document)
65
+ logger.info(f"Historial de chat guardado con ID: {result.inserted_id} para el usuario: {username}")
66
+ return True
67
+ except Exception as e:
68
+ logger.error(f"Error al guardar el historial de chat para el usuario {username}: {str(e)}")
69
+ return False
70
+
71
+ def get_chat_history_v3(username, analysis_type=None, limit=10):
72
+ try:
73
+ logger.info(f"Obteniendo historial de chat para el usuario: {username}, tipo de análisis: {analysis_type}")
74
+
75
+ query = {"username": username}
76
+ if analysis_type:
77
+ query["analysis_type"] = analysis_type
78
+
79
+ cursor = chat_collection_v3.find(query).sort("timestamp", -1).limit(limit)
80
+
81
+ chat_history = []
82
+ for chat in cursor:
83
+ chat_history.append({
84
+ "timestamp": chat["timestamp"],
85
+ "analysis_type": chat["analysis_type"],
86
+ "messages": chat["messages"]
87
+ })
88
+
89
+ logger.info(f"Se obtuvieron {len(chat_history)} entradas de chat para el usuario: {username}")
90
+ return chat_history
91
+ except Exception as e:
92
+ logger.error(f"Error al obtener el historial de chat para el usuario {username}: {str(e)}")
93
+ return []
94
+
95
+ def delete_chat_history_v3(username, analysis_type=None):
96
+ try:
97
+ logger.info(f"Eliminando historial de chat para el usuario: {username}, tipo de análisis: {analysis_type}")
98
+
99
+ query = {"username": username}
100
+ if analysis_type:
101
+ query["analysis_type"] = analysis_type
102
+
103
+ result = chat_collection_v3.delete_many(query)
104
+
105
+ logger.info(f"Se eliminaron {result.deleted_count} entradas de chat para el usuario: {username}")
106
+ return True
107
+ except Exception as e:
108
+ logger.error(f"Error al eliminar el historial de chat para el usuario {username}: {str(e)}")
109
+ return False
110
+
111
+ def export_chat_history_v3(username, analysis_type=None):
112
+ try:
113
+ logger.info(f"Exportando historial de chat para el usuario: {username}, tipo de análisis: {analysis_type}")
114
+
115
+ query = {"username": username}
116
+ if analysis_type:
117
+ query["analysis_type"] = analysis_type
118
+
119
+ cursor = chat_collection_v3.find(query).sort("timestamp", -1)
120
+
121
+ export_data = list(cursor)
122
+
123
+ logger.info(f"Se exportaron {len(export_data)} entradas de chat para el usuario: {username}")
124
+ return export_data
125
+ except Exception as e:
126
+ logger.error(f"Error al exportar el historial de chat para el usuario {username}: {str(e)}")
127
+ return []
128
+
129
+ # Funciones específicas para cada tipo de análisis
130
+
131
+ def store_morphosyntax_result(username, text, repeated_words, arc_diagrams, pos_analysis, morphological_analysis, sentence_structure):
132
+ if analysis_collection is None:
133
+ logger.error("La conexión a MongoDB no está inicializada")
134
+ return False
135
+
136
+ try:
137
+ word_count = {}
138
+ for word, color in repeated_words.items():
139
+ category = color # Asumiendo que 'color' es la categoría gramatical
140
+ word_count[category] = word_count.get(category, 0) + 1
141
+
142
+ analysis_document = {
143
+ 'username': username,
144
+ 'timestamp': datetime.now(timezone.utc).isoformat(),
145
+ 'text': text,
146
+ 'repeated_words': repeated_words,
147
+ 'word_count': word_count,
148
+ 'arc_diagrams': arc_diagrams,
149
+ 'pos_analysis': pos_analysis,
150
+ 'morphological_analysis': morphological_analysis,
151
+ 'sentence_structure': sentence_structure,
152
+ 'analysis_type': 'morphosyntax'
153
+ }
154
+
155
+ result = analysis_collection.insert_one(analysis_document)
156
+ logger.info(f"Análisis morfosintáctico guardado con ID: {result.inserted_id} para el usuario: {username}")
157
+ return True
158
+ except Exception as e:
159
+ logger.error(f"Error al guardar el análisis morfosintáctico para el usuario {username}: {str(e)}")
160
+ return False
161
+
162
+ # Aquí puedes agregar funciones similares para análisis semántico y de discurso
163
+
164
+ def get_student_data(username):
165
+ if analysis_collection is None or chat_collection_v3 is None:
166
+ logger.error("La conexión a MongoDB no está inicializada")
167
+ return None
168
+
169
+ formatted_data = {
170
+ "username": username,
171
+ "entries": [],
172
+ "entries_count": 0,
173
+ "word_count": {},
174
+ "chat_history": {
175
+ "morphosyntax": [],
176
+ "semantic": [],
177
+ "discourse": []
178
+ }
179
+ }
180
+
181
+ try:
182
+ logger.info(f"Buscando datos de análisis para el usuario: {username}")
183
+ cursor = analysis_collection.find({"username": username})
184
+
185
+ for entry in cursor:
186
+ formatted_entry = {
187
+ 'timestamp': entry.get("timestamp"),
188
+ "analysis_type": entry.get("analysis_type", "morphosyntax")
189
+ }
190
+
191
+ if formatted_entry["analysis_type"] == "morphosyntax":
192
+ formatted_entry.update({
193
+ "text": entry.get("text", ""),
194
+ "word_count": entry.get("word_count", {}),
195
+ "arc_diagrams": entry.get("arc_diagrams", [])
196
+ })
197
+ for category, count in formatted_entry["word_count"].items():
198
+ formatted_data["word_count"][category] = formatted_data["word_count"].get(category, 0) + count
199
+
200
+ formatted_data["entries"].append(formatted_entry)
201
+
202
+ formatted_data["entries_count"] = len(formatted_data["entries"])
203
+ formatted_data["entries"].sort(key=lambda x: x["timestamp"], reverse=True)
204
+
205
+ # Obtener historial de chat para cada tipo de análisis
206
+ for analysis_type in ["morphosyntax", "semantic", "discourse"]:
207
+ chat_history = get_chat_history_v3(username, analysis_type)
208
+ formatted_data["chat_history"][analysis_type] = chat_history
209
+
210
+ except Exception as e:
211
+ logger.error(f"Error al obtener datos del estudiante {username}: {str(e)}")
212
+
213
+ logger.info(f"Datos formateados para {username}: {formatted_data}")
214
+ return formatted_data
215
+
216
+ # Puedes agregar más funciones según sea necesario para manejar otros tipos de datos o análisis
modules/database/backUp/databaseBackUp23-9-24.py ADDED
@@ -0,0 +1,581 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # database.py
2
+ import logging
3
+ import os
4
+ from azure.cosmos import CosmosClient
5
+ from azure.cosmos.exceptions import CosmosHttpResponseError
6
+ from pymongo import MongoClient
7
+ import certifi
8
+ from datetime import datetime
9
+ import io
10
+ from io import BytesIO
11
+ import base64
12
+ import matplotlib.pyplot as plt
13
+ from matplotlib.figure import Figure
14
+ import bcrypt
15
+ print(f"Bcrypt version: {bcrypt.__version__}")
16
+ import uuid
17
+ import plotly.graph_objects as go # Para manejar el diagrama de Sankey
18
+ import numpy as np # Puede ser necesario para algunas operaciones
19
+ logging.basicConfig(level=logging.DEBUG)
20
+ logger = logging.getLogger(__name__)
21
+
22
+ # Variables globales para Cosmos DB SQL API
23
+ application_requests_container = None
24
+ cosmos_client = None
25
+ user_database = None
26
+ user_container = None
27
+ user_feedback_container = None
28
+
29
+ # Variables globales para Cosmos DB MongoDB API
30
+ mongo_client = None
31
+ mongo_db = None
32
+ analysis_collection = None
33
+ chat_collection = None # Nueva variable global
34
+
35
+
36
+ ##############################################################################--- INICIO DE LAS BASES DE DATOS --- ###############################
37
+ def initialize_database_connections():
38
+ try:
39
+ print("Iniciando conexión a MongoDB")
40
+ mongodb_success = initialize_mongodb_connection()
41
+ print(f"Conexión a MongoDB: {'exitosa' if mongodb_success else 'fallida'}")
42
+ except Exception as e:
43
+ print(f"Error al conectar con MongoDB: {str(e)}")
44
+ mongodb_success = False
45
+
46
+ try:
47
+ print("Iniciando conexión a Cosmos DB SQL API")
48
+ sql_success = initialize_cosmos_sql_connection()
49
+ print(f"Conexión a Cosmos DB SQL API: {'exitosa' if sql_success else 'fallida'}")
50
+ except Exception as e:
51
+ print(f"Error al conectar con Cosmos DB SQL API: {str(e)}")
52
+ sql_success = False
53
+
54
+ return {
55
+ "mongodb": mongodb_success,
56
+ "cosmos_sql": sql_success
57
+ }
58
+
59
+ #####################################################################################33
60
+ def initialize_cosmos_sql_connection():
61
+ global cosmos_client, user_database, user_container, application_requests_container, user_feedback_container
62
+ logger.info("Initializing Cosmos DB SQL API connection")
63
+ try:
64
+ cosmos_endpoint = os.environ.get("COSMOS_ENDPOINT")
65
+ cosmos_key = os.environ.get("COSMOS_KEY")
66
+ logger.info(f"Cosmos Endpoint: {cosmos_endpoint}")
67
+ logger.info(f"Cosmos Key: {'*' * len(cosmos_key) if cosmos_key else 'Not set'}")
68
+
69
+ if not cosmos_endpoint or not cosmos_key:
70
+ logger.error("COSMOS_ENDPOINT or COSMOS_KEY environment variables are not set")
71
+ raise ValueError("Las variables de entorno COSMOS_ENDPOINT y COSMOS_KEY deben estar configuradas")
72
+
73
+ cosmos_client = CosmosClient(cosmos_endpoint, cosmos_key)
74
+ user_database = cosmos_client.get_database_client("user_database")
75
+ user_container = user_database.get_container_client("users")
76
+ application_requests_container = user_database.get_container_client("application_requests")
77
+ user_feedback_container = user_database.get_container_client("user_feedback")
78
+
79
+ logger.info(f"user_container initialized: {user_container is not None}")
80
+ logger.info(f"application_requests_container initialized: {application_requests_container is not None}")
81
+ logger.info(f"user_feedback_container initialized: {user_feedback_container is not None}")
82
+
83
+ logger.info("Conexión a Cosmos DB SQL API exitosa")
84
+ return True
85
+ except Exception as e:
86
+ logger.error(f"Error al conectar con Cosmos DB SQL API: {str(e)}", exc_info=True)
87
+ return False
88
+
89
+ ############################################################################################3
90
+ def initialize_mongodb_connection():
91
+ global mongo_client, mongo_db, analysis_collection, chat_collection
92
+ try:
93
+ cosmos_mongodb_connection_string = os.getenv("MONGODB_CONNECTION_STRING")
94
+ if not cosmos_mongodb_connection_string:
95
+ logger.error("La variable de entorno MONGODB_CONNECTION_STRING no está configurada")
96
+ return False
97
+
98
+ mongo_client = MongoClient(cosmos_mongodb_connection_string,
99
+ tls=True,
100
+ tlsCAFile=certifi.where(),
101
+ retryWrites=False,
102
+ serverSelectionTimeoutMS=5000,
103
+ connectTimeoutMS=10000,
104
+ socketTimeoutMS=10000)
105
+
106
+ mongo_client.admin.command('ping')
107
+
108
+ mongo_db = mongo_client['aideatext_db']
109
+ analysis_collection = mongo_db['text_analysis']
110
+ chat_collection = mongo_db['chat_history'] # Inicializar la nueva colección
111
+
112
+ # Verificar la conexión
113
+ mongo_client.admin.command('ping')
114
+
115
+ logger.info("Conexión a Cosmos DB MongoDB API exitosa")
116
+ return True
117
+ except Exception as e:
118
+ logger.error(f"Error al conectar con Cosmos DB MongoDB API: {str(e)}", exc_info=True)
119
+ return False
120
+
121
+ ##############################################################################--- FIN DEL INICIO DE LAS BASES DE DATOS --- ################################################################################################################################
122
+ ########################################################## -- INICIO DE GESTION DE USUARIOS ---##########################################################
123
+ def create_user(username, password, role):
124
+ global user_container
125
+ try:
126
+ print(f"Attempting to create user: {username} with role: {role}")
127
+ if user_container is None:
128
+ print("Error: user_container is None. Attempting to reinitialize connection.")
129
+ if not initialize_cosmos_sql_connection():
130
+ raise Exception("Failed to initialize SQL connection")
131
+
132
+ hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
133
+ print(f"Password hashed successfully for user: {username}")
134
+ user_data = {
135
+ 'id': username,
136
+ 'password': hashed_password,
137
+ 'role': role,
138
+ 'created_at': datetime.utcnow().isoformat()
139
+ }
140
+ user_container.create_item(body=user_data)
141
+ print(f"Usuario {role} creado: {username}") # Log para depuración
142
+ return True
143
+ except Exception as e:
144
+ print(f"Detailed error in create_user: {str(e)}")
145
+ return False
146
+
147
+ #######################################################################################################
148
+ def create_admin_user(username, password):
149
+ return create_user(username, password, 'Administrador')
150
+
151
+ #######################################################################################################
152
+ def create_student_user(username, password):
153
+ return create_user(username, password, 'Estudiante')
154
+
155
+ #######################################################################################################
156
+ # Funciones para Cosmos DB SQL API (manejo de usuarios)
157
+ def get_user(username):
158
+ try:
159
+ query = f"SELECT * FROM c WHERE c.id = '{username}'"
160
+ items = list(user_container.query_items(query=query, enable_cross_partition_query=True))
161
+ user = items[0] if items else None
162
+ if user:
163
+ print(f"Usuario encontrado: {username}, Rol: {user.get('role')}") # Log añadido
164
+ else:
165
+ print(f"Usuario no encontrado: {username}") # Log añadido
166
+ return user
167
+ except Exception as e:
168
+ print(f"Error al obtener usuario {username}: {str(e)}")
169
+ return None
170
+
171
+ ########################################################## -- FIN DE GESTION DE USUARIOS ---##########################################################
172
+
173
+ ########################################################## -- INICIO GESTION DE ARCHIVOS ---##########################################################
174
+
175
+ def store_file_contents(username, file_name, file_contents, analysis_type):
176
+ if user_container is None:
177
+ logger.error("La conexión a Cosmos DB SQL API no está inicializada")
178
+ return False
179
+ try:
180
+ document = {
181
+ 'id': f"{username}_{analysis_type}_{file_name}",
182
+ 'username': username,
183
+ 'file_name': file_name,
184
+ 'analysis_type': analysis_type,
185
+ 'file_contents': file_contents,
186
+ 'timestamp': datetime.utcnow().isoformat()
187
+ }
188
+ user_container.upsert_item(body=document)
189
+ logger.info(f"Contenido del archivo guardado para el usuario: {username}, tipo de análisis: {analysis_type}")
190
+ return True
191
+ except Exception as e:
192
+ logger.error(f"Error al guardar el contenido del archivo para el usuario {username}: {str(e)}")
193
+ return False
194
+
195
+ def retrieve_file_contents(username, file_name, analysis_type):
196
+ print(f"Attempting to retrieve file: {file_name} for user: {username}")
197
+ if user_container is None:
198
+ logger.error("La conexión a Cosmos DB SQL API no está inicializada")
199
+ return None
200
+ try:
201
+ query = f"SELECT * FROM c WHERE c.id = '{username}_{analysis_type}_{file_name}'"
202
+ items = list(user_container.query_items(query=query, enable_cross_partition_query=True))
203
+ if items:
204
+ return items[0]['file_contents']
205
+ else:
206
+ logger.info(f"No se encontró contenido de archivo para el usuario: {username}, tipo de análisis: {analysis_type}")
207
+ return None
208
+ except Exception as e:
209
+ logger.error(f"Error al recuperar el contenido del archivo para el usuario {username}: {str(e)}")
210
+ return None
211
+
212
+ def get_user_files(username, analysis_type=None):
213
+ if user_container is None:
214
+ logger.error("La conexión a Cosmos DB SQL API no está inicializada")
215
+ return []
216
+ try:
217
+ if analysis_type:
218
+ query = f"SELECT c.file_name, c.analysis_type, c.timestamp FROM c WHERE c.username = '{username}' AND c.analysis_type = '{analysis_type}'"
219
+ else:
220
+ query = f"SELECT c.file_name, c.analysis_type, c.timestamp FROM c WHERE c.username = '{username}'"
221
+
222
+ items = list(user_container.query_items(query=query, enable_cross_partition_query=True))
223
+ return items
224
+ except Exception as e:
225
+ logger.error(f"Error al obtener la lista de archivos del usuario {username}: {str(e)}")
226
+ return []
227
+
228
+ def delete_file(username, file_name, analysis_type):
229
+ if user_container is None:
230
+ logger.error("La conexión a Cosmos DB SQL API no está inicializada")
231
+ return False
232
+ try:
233
+ user_container.delete_item(item=f"{username}_{analysis_type}_{file_name}", partition_key=username)
234
+ logger.info(f"Archivo eliminado para el usuario: {username}, tipo de análisis: {analysis_type}")
235
+ return True
236
+ except Exception as e:
237
+ logger.error(f"Error al eliminar el archivo para el usuario {username}: {str(e)}")
238
+ return False
239
+
240
+ ########################################################## -- FIN GESTION DE ARCHIVOS ---##########################################################
241
+
242
+ ########################################################## -- INICIO GESTION DE FORMULARIOS ---##########################################################
243
+ def store_application_request(name, email, institution, role, reason):
244
+ global application_requests_container
245
+ logger.info("Entering store_application_request function")
246
+ try:
247
+ logger.info("Checking application_requests_container")
248
+ if application_requests_container is None:
249
+ logger.error("application_requests_container is not initialized")
250
+ return False
251
+
252
+ logger.info("Creating application request document")
253
+ application_request = {
254
+ "id": str(uuid.uuid4()),
255
+ "name": name,
256
+ "email": email,
257
+ "institution": institution,
258
+ "role": role,
259
+ "reason": reason,
260
+ "requestDate": datetime.utcnow().isoformat()
261
+ }
262
+
263
+ logger.info(f"Attempting to store document: {application_request}")
264
+ application_requests_container.create_item(body=application_request)
265
+ logger.info(f"Application request stored for email: {email}")
266
+ return True
267
+ except Exception as e:
268
+ logger.error(f"Error storing application request: {str(e)}")
269
+ return False
270
+
271
+ #######################################################################################################
272
+ def store_user_feedback(username, name, email, feedback):
273
+ global user_feedback_container
274
+ logger.info(f"Attempting to store user feedback for user: {username}")
275
+ try:
276
+ if user_feedback_container is None:
277
+ logger.error("user_feedback_container is not initialized")
278
+ return False
279
+
280
+ feedback_item = {
281
+ "id": str(uuid.uuid4()),
282
+ "username": username,
283
+ "name": name,
284
+ "email": email,
285
+ "feedback": feedback,
286
+ "timestamp": datetime.utcnow().isoformat()
287
+ }
288
+
289
+ result = user_feedback_container.create_item(body=feedback_item)
290
+ logger.info(f"User feedback stored with ID: {result['id']} for user: {username}")
291
+ return True
292
+ except Exception as e:
293
+ logger.error(f"Error storing user feedback for user {username}: {str(e)}")
294
+ return False
295
+
296
+
297
+ ########################################################## -- FIN GESTION DE FORMULARIOS ---##########################################################
298
+
299
+ ########################################################## -- INICIO ALMACENAMIENTO ANÁLISIS MORFOSINTÁCTICO ---##########################################################
300
+
301
+ def store_morphosyntax_result(username, text, repeated_words, arc_diagrams, pos_analysis, morphological_analysis, sentence_structure):
302
+ if analysis_collection is None:
303
+ logger.error("La conexión a MongoDB no está inicializada")
304
+ return False
305
+
306
+ try:
307
+ word_count = {}
308
+ for word, color in repeated_words.items():
309
+ category = color # Asumiendo que 'color' es la categoría gramatical
310
+ word_count[category] = word_count.get(category, 0) + 1
311
+
312
+ analysis_document = {
313
+ 'username': username,
314
+ 'timestamp': datetime.utcnow(),
315
+ 'text': text,
316
+ 'word_count': word_count,
317
+ 'arc_diagrams': arc_diagrams,
318
+ 'pos_analysis': pos_analysis,
319
+ 'morphological_analysis': morphological_analysis,
320
+ 'sentence_structure': sentence_structure
321
+ }
322
+
323
+ result = analysis_collection.insert_one(analysis_document)
324
+ logger.info(f"Análisis guardado con ID: {result.inserted_id} para el usuario: {username}")
325
+ return True
326
+ except Exception as e:
327
+ logger.error(f"Error al guardar el análisis para el usuario {username}: {str(e)}")
328
+ return False
329
+
330
+ ########################################################## -- FIN ALMACENAMIENTO ANÁLISIS MORFOSINTÁCTICO ---##########################################################
331
+
332
+
333
+ ##########################################--- INICIO SECCIÓN DEL ANÁLISIS SEMÁNTICO ---###############################################
334
+
335
+ def store_file_semantic_contents(username, file_name, file_contents):
336
+ if user_container is None:
337
+ logger.error("La conexión a Cosmos DB SQL API no está inicializada")
338
+ return False
339
+ try:
340
+ document = {
341
+ 'id': f"{username}_semantic_{file_name}",
342
+ 'username': username,
343
+ 'file_name': file_name,
344
+ 'file_contents': file_contents,
345
+ 'analysis_type': 'semantic',
346
+ 'timestamp': datetime.utcnow().isoformat()
347
+ }
348
+ user_container.upsert_item(body=document)
349
+ logger.info(f"Contenido del archivo semántico guardado para el usuario: {username}")
350
+ return True
351
+ except Exception as e:
352
+ logger.error(f"Error al guardar el contenido del archivo semántico para el usuario {username}: {str(e)}")
353
+ return False
354
+
355
+ def store_semantic_result(username, text, analysis_result):
356
+ if analysis_collection is None:
357
+ print("La conexión a MongoDB no está inicializada")
358
+ return False
359
+ try:
360
+ # Convertir los conceptos clave a una lista de tuplas
361
+ key_concepts = [(concept, float(frequency)) for concept, frequency in analysis_result['key_concepts']]
362
+
363
+ # Convertir los gráficos a imágenes base64
364
+ graphs = {}
365
+ for graph_name in ['relations_graph', 'entity_graph', 'topic_graph']:
366
+ if graph_name in analysis_result:
367
+ buf = BytesIO()
368
+ analysis_result[graph_name].savefig(buf, format='png')
369
+ buf.seek(0)
370
+ graphs[graph_name] = base64.b64encode(buf.getvalue()).decode('utf-8')
371
+
372
+ analysis_document = {
373
+ 'username': username,
374
+ 'timestamp': datetime.utcnow(),
375
+ 'text': text,
376
+ 'key_concepts': key_concepts,
377
+ 'graphs': graphs,
378
+ 'summary': analysis_result.get('summary', ''),
379
+ 'entities': analysis_result.get('entities', {}),
380
+ 'sentiment': analysis_result.get('sentiment', ''),
381
+ 'topics': analysis_result.get('topics', []),
382
+ 'analysis_type': 'semantic'
383
+ }
384
+
385
+ result = analysis_collection.insert_one(analysis_document)
386
+ print(f"Análisis semántico guardado con ID: {result.inserted_id} para el usuario: {username}")
387
+ return True
388
+ except Exception as e:
389
+ print(f"Error al guardar el análisis semántico para el usuario {username}: {str(e)}")
390
+ return False
391
+
392
+ ##########################################--- FIN DE LA SECCIÓN DEL ANÁLISIS SEMÁNTICO ---###############################################
393
+
394
+ ############################################--- INICIO DE LA SECCIÓN DEL ANÁLISIS DEL DISCURSO ###################################################################
395
+
396
+ def store_discourse_analysis_result(username, text1, text2, analysis_result):
397
+ if analysis_collection is None:
398
+ print("La conexión a MongoDB no está inicializada")
399
+ return False
400
+
401
+ try:
402
+ # Convertir los grafos individuales a imágenes base64
403
+ buf1 = BytesIO()
404
+ analysis_result['graph1'].savefig(buf1, format='png')
405
+ buf1.seek(0)
406
+ img_str1 = base64.b64encode(buf1.getvalue()).decode('utf-8')
407
+
408
+ buf2 = BytesIO()
409
+ analysis_result['graph2'].savefig(buf2, format='png')
410
+ buf2.seek(0)
411
+ img_str2 = base64.b64encode(buf2.getvalue()).decode('utf-8')
412
+
413
+ # Crear una imagen combinada
414
+ fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(20, 10))
415
+ ax1.imshow(plt.imread(BytesIO(base64.b64decode(img_str1))))
416
+ ax1.axis('off')
417
+ ax1.set_title("Documento 1: Relaciones Conceptuales")
418
+ ax2.imshow(plt.imread(BytesIO(base64.b64decode(img_str2))))
419
+ ax2.axis('off')
420
+ ax2.set_title("Documento 2: Relaciones Conceptuales")
421
+
422
+ buf_combined = BytesIO()
423
+ fig.savefig(buf_combined, format='png')
424
+ buf_combined.seek(0)
425
+ img_str_combined = base64.b64encode(buf_combined.getvalue()).decode('utf-8')
426
+ plt.close(fig)
427
+
428
+ # Convertir los conceptos clave a listas de tuplas
429
+ key_concepts1 = [(concept, float(frequency)) for concept, frequency in analysis_result['key_concepts1']]
430
+ key_concepts2 = [(concept, float(frequency)) for concept, frequency in analysis_result['key_concepts2']]
431
+
432
+ # Crear el documento para guardar
433
+ analysis_document = {
434
+ 'username': username,
435
+ 'timestamp': datetime.utcnow(),
436
+ #'text1': text1,
437
+ #'text2': text2,
438
+ 'graph1': img_str1,
439
+ 'graph2': img_str2,
440
+ 'combined_graph': img_str_combined,
441
+ 'key_concepts1': key_concepts1,
442
+ 'key_concepts2': key_concepts2,
443
+ 'analysis_type': 'discourse'
444
+ }
445
+
446
+ # Insertar el documento en la base de datos
447
+ result = analysis_collection.insert_one(analysis_document)
448
+ print(f"Análisis discursivo guardado con ID: {result.inserted_id} para el usuario: {username}")
449
+ return True
450
+ except Exception as e:
451
+ print(f"Error al guardar el análisis discursivo para el usuario {username}: {str(e)}")
452
+ print(f"Tipo de excepción: {type(e).__name__}")
453
+ print(f"Detalles de la excepción: {e.args}")
454
+ return False
455
+
456
+ ############################################--- FIN DE LA SECCIÓN DEL ANÁLISIS DEL DISCURSO ###################################################################
457
+
458
+
459
+ ################################################-- INICIO DE LA SECCIÓN DEL CHATBOT --- ###############################################################
460
+ def store_chat_history(username, messages):
461
+ try:
462
+ logger.info(f"Attempting to save chat history for user: {username}")
463
+ logger.debug(f"Messages to save: {messages}")
464
+
465
+ chat_document = {
466
+ 'username': username,
467
+ 'timestamp': datetime.utcnow(),
468
+ 'messages': messages
469
+ }
470
+ result = chat_collection.insert_one(chat_document)
471
+ logger.info(f"Chat history saved with ID: {result.inserted_id} for user: {username}")
472
+ logger.debug(f"Chat content: {messages}")
473
+ return True
474
+ except Exception as e:
475
+ logger.error(f"Error saving chat history for user {username}: {str(e)}")
476
+ return False
477
+
478
+ #######################################################################################################
479
+ def export_analysis_and_chat(username, analysis_data, chat_data):
480
+ try:
481
+ export_data = {
482
+ "username": username,
483
+ "timestamp": datetime.utcnow(),
484
+ "analysis": analysis_data,
485
+ "chat": chat_data
486
+ }
487
+
488
+ # Aquí puedes decidir cómo quieres exportar los datos
489
+ # Por ejemplo, podrías guardarlos en una nueva colección en MongoDB
490
+ export_collection = mongo_db['exports']
491
+ result = export_collection.insert_one(export_data)
492
+
493
+ # También podrías generar un archivo JSON o CSV y guardarlo en Azure Blob Storage
494
+
495
+ return True
496
+ except Exception as e:
497
+ logger.error(f"Error al exportar análisis y chat para {username}: {str(e)}")
498
+ return False
499
+
500
+ ################################################-- FIN DE LA SECCIÓN DEL CHATBOT --- ###############################################################
501
+
502
+ #######################################################################################################################################################
503
+
504
+ def get_student_data(username):
505
+ if analysis_collection is None or chat_collection is None:
506
+ logger.error("La conexión a MongoDB no está inicializada")
507
+ return None
508
+ formatted_data = {
509
+ "username": username,
510
+ "entries": [],
511
+ "entries_count": 0,
512
+ "word_count": {},
513
+ "semantic_analyses": [],
514
+ "discourse_analyses": [],
515
+ "chat_history": []
516
+ }
517
+ try:
518
+ logger.info(f"Buscando datos de análisis para el usuario: {username}")
519
+ cursor = analysis_collection.find({"username": username})
520
+
521
+ for entry in cursor:
522
+ formatted_entry = {
523
+ "timestamp": entry.get("timestamp", datetime.utcnow()),
524
+ "analysis_type": entry.get("analysis_type", "morphosyntax")
525
+ }
526
+
527
+ if formatted_entry["analysis_type"] == "morphosyntax":
528
+ formatted_entry.update({
529
+ "text": entry.get("text", ""),
530
+ "word_count": entry.get("word_count", {}),
531
+ "arc_diagrams": entry.get("arc_diagrams", [])
532
+ })
533
+ for category, count in formatted_entry["word_count"].items():
534
+ formatted_data["word_count"][category] = formatted_data["word_count"].get(category, 0) + count
535
+
536
+ elif formatted_entry["analysis_type"] == "semantic":
537
+ formatted_entry.update({
538
+ "key_concepts": entry.get("key_concepts", []),
539
+ "graph": entry.get("graph", "")
540
+ })
541
+ formatted_data["semantic_analyses"].append(formatted_entry)
542
+
543
+ elif formatted_entry["analysis_type"] == "discourse":
544
+ formatted_entry.update({
545
+ "text1": entry.get("text1", ""),
546
+ "text2": entry.get("text2", ""),
547
+ "key_concepts1": entry.get("key_concepts1", []),
548
+ "key_concepts2": entry.get("key_concepts2", []),
549
+ "graph1": entry.get("graph1", ""),
550
+ "graph2": entry.get("graph2", ""),
551
+ "combined_graph": entry.get("combined_graph", "")
552
+ })
553
+ formatted_data["discourse_analyses"].append(formatted_entry)
554
+
555
+ formatted_data["entries"].append(formatted_entry)
556
+
557
+ formatted_data["entries_count"] = len(formatted_data["entries"])
558
+ formatted_data["entries"].sort(key=lambda x: x["timestamp"], reverse=True)
559
+
560
+ for entry in formatted_data["entries"]:
561
+ entry["timestamp"] = entry["timestamp"].isoformat()
562
+
563
+ except Exception as e:
564
+ logger.error(f"Error al obtener datos de análisis del estudiante {username}: {str(e)}")
565
+
566
+ try:
567
+ logger.info(f"Buscando historial de chat para el usuario: {username}")
568
+ chat_cursor = chat_collection.find({"username": username})
569
+ for chat in chat_cursor:
570
+ formatted_chat = {
571
+ "timestamp": chat["timestamp"].isoformat(),
572
+ "messages": chat["messages"]
573
+ }
574
+ formatted_data["chat_history"].append(formatted_chat)
575
+
576
+ formatted_data["chat_history"].sort(key=lambda x: x["timestamp"], reverse=True)
577
+
578
+ except Exception as e:
579
+ logger.error(f"Error al obtener historial de chat del estudiante {username}: {str(e)}")
580
+ logger.info(f"Datos formateados para {username}: {formatted_data}")
581
+ return formatted_data
modules/database/backUp/database_oldFromV2.py ADDED
@@ -0,0 +1,473 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # database.py
2
+ # database.py de la versión 3 al 26-9-2024
3
+ import streamlit as st
4
+ import logging
5
+ import os
6
+ import pandas as pd
7
+ from azure.cosmos import CosmosClient
8
+ from azure.cosmos.exceptions import CosmosHttpResponseError
9
+ from pymongo import MongoClient
10
+ import certifi
11
+ from datetime import datetime, timezone
12
+ from io import BytesIO
13
+ import base64
14
+ import matplotlib.pyplot as plt
15
+ from matplotlib.figure import Figure
16
+ import bcrypt
17
+ print(f"Bcrypt version: {bcrypt.__version__}")
18
+ import uuid
19
+ import plotly.graph_objects as go # Para manejar el diagrama de Sankey
20
+ import numpy as np # Puede ser necesario para algunas operaciones
21
+ logging.basicConfig(level=logging.DEBUG)
22
+ logger = logging.getLogger(__name__)
23
+
24
+ # Variables globales para Cosmos DB SQL API
25
+ application_requests_container = None
26
+ cosmos_client = None
27
+ user_database = None
28
+ user_container = None
29
+ user_feedback_container = None
30
+
31
+ # Variables globales para Cosmos DB MongoDB API
32
+ mongo_client = None
33
+ mongo_db = None
34
+ analysis_collection = None
35
+ chat_collection = None # Nueva variable global
36
+
37
+
38
+ ##############################################################################--- INICIO DE LAS BASES DE DATOS --- ###############################
39
+ def initialize_database_connections():
40
+ try:
41
+ print("Iniciando conexión a MongoDB")
42
+ mongodb_success = initialize_mongodb_connection()
43
+ print(f"Conexión a MongoDB: {'exitosa' if mongodb_success else 'fallida'}")
44
+ except Exception as e:
45
+ print(f"Error al conectar con MongoDB: {str(e)}")
46
+ mongodb_success = False
47
+
48
+ try:
49
+ print("Iniciando conexión a Cosmos DB SQL API")
50
+ sql_success = initialize_cosmos_sql_connection()
51
+ print(f"Conexión a Cosmos DB SQL API: {'exitosa' if sql_success else 'fallida'}")
52
+ except Exception as e:
53
+ print(f"Error al conectar con Cosmos DB SQL API: {str(e)}")
54
+ sql_success = False
55
+
56
+ return {
57
+ "mongodb": mongodb_success,
58
+ "cosmos_sql": sql_success
59
+ }
60
+
61
+ #####################################################################################33
62
+ def initialize_cosmos_sql_connection():
63
+ global cosmos_client, user_database, user_container, application_requests_container, user_feedback_container
64
+ logger.info("Initializing Cosmos DB SQL API connection")
65
+ try:
66
+ cosmos_endpoint = os.environ.get("COSMOS_ENDPOINT")
67
+ cosmos_key = os.environ.get("COSMOS_KEY")
68
+ logger.info(f"Cosmos Endpoint: {cosmos_endpoint}")
69
+ logger.info(f"Cosmos Key: {'*' * len(cosmos_key) if cosmos_key else 'Not set'}")
70
+
71
+ if not cosmos_endpoint or not cosmos_key:
72
+ logger.error("COSMOS_ENDPOINT or COSMOS_KEY environment variables are not set")
73
+ raise ValueError("Las variables de entorno COSMOS_ENDPOINT y COSMOS_KEY deben estar configuradas")
74
+
75
+ cosmos_client = CosmosClient(cosmos_endpoint, cosmos_key)
76
+ user_database = cosmos_client.get_database_client("user_database")
77
+ user_container = user_database.get_container_client("users")
78
+ application_requests_container = user_database.get_container_client("application_requests")
79
+ user_feedback_container = user_database.get_container_client("user_feedback")
80
+
81
+ logger.info(f"user_container initialized: {user_container is not None}")
82
+ logger.info(f"application_requests_container initialized: {application_requests_container is not None}")
83
+ logger.info(f"user_feedback_container initialized: {user_feedback_container is not None}")
84
+
85
+ logger.info("Conexión a Cosmos DB SQL API exitosa")
86
+ return True
87
+ except Exception as e:
88
+ logger.error(f"Error al conectar con Cosmos DB SQL API: {str(e)}", exc_info=True)
89
+ return False
90
+
91
+ ############################################################################################3
92
+ def initialize_mongodb_connection():
93
+ global mongo_client, mongo_db, analysis_collection, chat_collection
94
+ try:
95
+ cosmos_mongodb_connection_string = os.getenv("MONGODB_CONNECTION_STRING")
96
+ if not cosmos_mongodb_connection_string:
97
+ logger.error("La variable de entorno MONGODB_CONNECTION_STRING no está configurada")
98
+ return False
99
+
100
+ mongo_client = MongoClient(cosmos_mongodb_connection_string,
101
+ tls=True,
102
+ tlsCAFile=certifi.where(),
103
+ retryWrites=False,
104
+ serverSelectionTimeoutMS=5000,
105
+ connectTimeoutMS=10000,
106
+ socketTimeoutMS=10000)
107
+
108
+ mongo_client.admin.command('ping')
109
+
110
+ mongo_db = mongo_client['aideatext_db']
111
+ # export = mongo_db['export']
112
+ analysis_collection = mongo_db['text_analysis']
113
+ chat_collection = mongo_db['chat_history'] # Inicializar la nueva colección
114
+
115
+ # Verificar la conexión
116
+ mongo_client.admin.command('ping')
117
+
118
+ logger.info("Conexión a Cosmos DB MongoDB API exitosa")
119
+ return True
120
+ except Exception as e:
121
+ logger.error(f"Error al conectar con Cosmos DB MongoDB API: {str(e)}", exc_info=True)
122
+ return False
123
+
124
+ ##############################################################################--- FIN DEL INICIO DE LAS BASES DE DATOS --- ################################################################################################################################
125
+ ########################################################## -- INICIO DE GESTION DE USUARIOS ---##########################################################
126
+ def create_user(username, password, role):
127
+ global user_container
128
+ try:
129
+ print(f"Attempting to create user: {username} with role: {role}")
130
+ if user_container is None:
131
+ print("Error: user_container is None. Attempting to reinitialize connection.")
132
+ if not initialize_cosmos_sql_connection():
133
+ raise Exception("Failed to initialize SQL connection")
134
+
135
+ hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
136
+ print(f"Password hashed successfully for user: {username}")
137
+ user_data = {
138
+ 'id': username,
139
+ 'password': hashed_password,
140
+ 'role': role,
141
+ 'timestamp':datetime.now(timezone.utc).isoformat(),
142
+ }
143
+ user_container.create_item(body=user_data)
144
+ print(f"Usuario {role} creado: {username}") # Log para depuración
145
+ return True
146
+ except Exception as e:
147
+ print(f"Detailed error in create_user: {str(e)}")
148
+ return False
149
+
150
+ #######################################################################################################
151
+ def create_admin_user(username, password):
152
+ return create_user(username, password, 'Administrador')
153
+
154
+ #######################################################################################################
155
+ def create_student_user(username, password):
156
+ return create_user(username, password, 'Estudiante')
157
+
158
+ #######################################################################################################
159
+ # Funciones para Cosmos DB SQL API (manejo de usuarios)
160
+ def get_user(username):
161
+ try:
162
+ query = f"SELECT * FROM c WHERE c.id = '{username}'"
163
+ items = list(user_container.query_items(query=query, enable_cross_partition_query=True))
164
+ user = items[0] if items else None
165
+ if user:
166
+ print(f"Usuario encontrado: {username}, Rol: {user.get('role')}") # Log añadido
167
+ else:
168
+ print(f"Usuario no encontrado: {username}") # Log añadido
169
+ return user
170
+ except Exception as e:
171
+ print(f"Error al obtener usuario {username}: {str(e)}")
172
+ return None
173
+
174
+ ########################################################## -- FIN DE GESTION DE USUARIOS ---##########################################################
175
+
176
+ ########################################################## -- INICIO GESTION DE ARCHIVOS ---##########################################################
177
+
178
+ def manage_file_contents(username, file_name, analysis_type, file_contents=None):
179
+ if user_container is None:
180
+ logger.error("La conexión a Cosmos DB SQL API no está inicializada")
181
+ return None
182
+
183
+ item_id = f"{analysis_type}_{file_name}"
184
+
185
+ try:
186
+ if file_contents is not None:
187
+ # Storing or updating file
188
+ document = {
189
+ 'id': item_id,
190
+ 'username': username,
191
+ 'file_name': file_name,
192
+ 'analysis_type': analysis_type,
193
+ 'file_contents': file_contents,
194
+ 'timestamp': datetime.now(timezone.utc).isoformat()
195
+ }
196
+ user_container.upsert_item(body=document, partition_key=username)
197
+ logger.info(f"Contenido del archivo guardado/actualizado para el usuario: {username}, tipo de análisis: {analysis_type}")
198
+ return True
199
+ else:
200
+ # Retrieving file
201
+ item = user_container.read_item(item=item_id, partition_key=username)
202
+ return item['file_contents']
203
+ except CosmosHttpResponseError as e:
204
+ if e.status_code == 404:
205
+ logger.info(f"No se encontró el archivo para el usuario: {username}, tipo de análisis: {analysis_type}")
206
+ return None
207
+ else:
208
+ logger.error(f"Error de Cosmos DB al manejar el archivo para el usuario {username}: {str(e)}")
209
+ return None
210
+ except Exception as e:
211
+ logger.error(f"Error al manejar el archivo para el usuario {username}: {str(e)}")
212
+ return None
213
+
214
+
215
+ def get_user_files(username, analysis_type=None):
216
+ if user_container is None:
217
+ logger.error("La conexión a Cosmos DB SQL API no está inicializada")
218
+ return []
219
+ try:
220
+ if analysis_type:
221
+ query = f"SELECT c.file_name, c.analysis_type, c.timestamp FROM c WHERE c.username = '{username}' AND c.analysis_type = '{analysis_type}'"
222
+ else:
223
+ query = f"SELECT c.file_name, c.analysis_type, c.timestamp FROM c WHERE c.username = '{username}'"
224
+
225
+ items = list(user_container.query_items(query=query, enable_cross_partition_query=True))
226
+ return items
227
+ except Exception as e:
228
+ logger.error(f"Error al obtener la lista de archivos del usuario {username}: {str(e)}")
229
+ return []
230
+
231
+
232
+
233
+ def delete_file(username, file_name, analysis_type):
234
+ if user_container is None:
235
+ logger.error("La conexión a Cosmos DB SQL API no está inicializada")
236
+ return False
237
+
238
+ try:
239
+ item_id = f"{analysis_type}_{file_name}"
240
+ user_container.delete_item(item=item_id, partition_key=username)
241
+ logger.info(f"Archivo eliminado para el usuario: {username}, tipo de análisis: {analysis_type}, nombre: {file_name}")
242
+ return True
243
+
244
+ if success:
245
+ # Invalidar caché
246
+ cache_key = f"student_data_{username}"
247
+ if cache_key in st.session_state:
248
+ del st.session_state[cache_key]
249
+
250
+
251
+
252
+ except CosmosHttpResponseError as e:
253
+ logger.error(f"Cosmos DB error al eliminar el archivo para el usuario {username}: {str(e)}")
254
+ return False
255
+
256
+ except Exception as e:
257
+ logger.error(f"Error al eliminar el archivo para el usuario {username}: {str(e)}")
258
+ return False
259
+
260
+ ########################################################## -- FIN GESTION DE ARCHIVOS ---##########################################################
261
+
262
+ ########################################################## -- INICIO GESTION DE FORMULARIOS ---##########################################################
263
+ def store_application_request(name, email, institution, role, reason):
264
+ global application_requests_container
265
+ logger.info("Entering store_application_request function")
266
+ try:
267
+ logger.info("Checking application_requests_container")
268
+ if application_requests_container is None:
269
+ logger.error("application_requests_container is not initialized")
270
+ return False
271
+
272
+ logger.info("Creating application request document")
273
+ application_request = {
274
+ "id": str(uuid.uuid4()),
275
+ "name": name,
276
+ "email": email,
277
+ "institution": institution,
278
+ "role": role,
279
+ "reason": reason,
280
+ "requestDate": datetime.utcnow().isoformat()
281
+ }
282
+
283
+ logger.info(f"Attempting to store document: {application_request}")
284
+ application_requests_container.create_item(body=application_request)
285
+ logger.info(f"Application request stored for email: {email}")
286
+ return True
287
+ except Exception as e:
288
+ logger.error(f"Error storing application request: {str(e)}")
289
+ return False
290
+
291
+ #######################################################################################################
292
+ def store_user_feedback(username, name, email, feedback):
293
+ global user_feedback_container
294
+ logger.info(f"Attempting to store user feedback for user: {username}")
295
+ try:
296
+ if user_feedback_container is None:
297
+ logger.error("user_feedback_container is not initialized")
298
+ return False
299
+
300
+ feedback_item = {
301
+ "id": str(uuid.uuid4()),
302
+ "username": username,
303
+ "name": name,
304
+ "email": email,
305
+ "feedback": feedback,
306
+ 'timestamp':datetime.now(timezone.utc).isoformat(),
307
+ }
308
+
309
+ result = user_feedback_container.create_item(body=feedback_item)
310
+ logger.info(f"User feedback stored with ID: {result['id']} for user: {username}")
311
+ return True
312
+ except Exception as e:
313
+ logger.error(f"Error storing user feedback for user {username}: {str(e)}")
314
+ return False
315
+
316
+ ########################################################## -- FIN GESTION DE FORMULARIOS ---##########################################################
317
+
318
+ ########################################################## -- INICIO ALMACENAMIENTO ANÁLISIS MORFOSINTÁCTICO ---##########################################################
319
+
320
+ def store_morphosyntax_result(username, text, repeated_words, arc_diagrams, pos_analysis, morphological_analysis, sentence_structure):
321
+ if analysis_collection is None:
322
+ logger.error("La conexión a MongoDB no está inicializada")
323
+ return False
324
+
325
+ try:
326
+ word_count = {}
327
+ for word, color in repeated_words.items():
328
+ category = color # Asumiendo que 'color' es la categoría gramatical
329
+ word_count[category] = word_count.get(category, 0) + 1
330
+
331
+ analysis_document = {
332
+ 'username': username,
333
+ 'timestamp':datetime.now(timezone.utc).isoformat(),
334
+ 'text': text,
335
+ 'repeated_words': repeated_words,
336
+ 'word_count': word_count,
337
+ 'arc_diagrams': arc_diagrams,
338
+ 'pos_analysis': pos_analysis,
339
+ 'morphological_analysis': morphological_analysis,
340
+ 'sentence_structure': sentence_structure,
341
+ 'analysis_type': 'morphosyntax'
342
+ }
343
+
344
+ result = analysis_collection.insert_one(analysis_document)
345
+ logger.info(f"Análisis guardado con ID: {result.inserted_id} para el usuario: {username}")
346
+ return True
347
+ except Exception as e:
348
+ logger.error(f"Error al guardar el análisis para el usuario {username}: {str(e)}")
349
+ return False
350
+
351
+
352
+ ################################################-- INICIO DE LA SECCIÓN DEL CHATBOT --- ###############################################################
353
+ def store_chat_history(username, messages):
354
+ try:
355
+ logger.info(f"Attempting to save chat history for user: {username}")
356
+ logger.debug(f"Messages to save: {messages}")
357
+
358
+ chat_document = {
359
+ 'username': username,
360
+ 'timestamp':datetime.now(timezone.utc).isoformat(),
361
+ 'messages': messages
362
+ }
363
+ result = chat_collection.insert_one(chat_document)
364
+ logger.info(f"Chat history saved with ID: {result.inserted_id} for user: {username}")
365
+ logger.debug(f"Chat content: {messages}")
366
+ return True
367
+ except Exception as e:
368
+ logger.error(f"Error saving chat history for user {username}: {str(e)}")
369
+ return False
370
+
371
+ #######################################################################################################
372
+ def export_analysis_and_chat(username, analysis_data, chat_data):
373
+ try:
374
+ export_data = {
375
+ "username": username,
376
+ 'timestamp':datetime.now(timezone.utc).isoformat(),
377
+ "analysis": analysis_data,
378
+ "chat": chat_data
379
+ }
380
+
381
+ # Aquí puedes decidir cómo quieres exportar los datos
382
+ # Por ejemplo, podrías guardarlos en una nueva colección en MongoDB
383
+ export_collection = mongo_db['exports']
384
+ result = export_collection.insert_one(export_data)
385
+
386
+ # También podrías generar un archivo JSON o CSV y guardarlo en Azure Blob Storage
387
+
388
+ return True
389
+ except Exception as e:
390
+ logger.error(f"Error al exportar análisis y chat para {username}: {str(e)}")
391
+ return False
392
+
393
+ ################################################-- FIN DE LA SECCIÓN DEL CHATBOT --- ###############################################################
394
+ ########--- STUDENT DATA -------
395
+
396
+ def get_student_data(username):
397
+ if analysis_collection is None or chat_collection is None:
398
+ logger.error("La conexión a MongoDB no está inicializada")
399
+ return None
400
+ formatted_data = {
401
+ "username": username,
402
+ "entries": [],
403
+ "entries_count": 0,
404
+ "word_count": {},
405
+ "semantic_analyses": [],
406
+ "discourse_analyses": [],
407
+ "chat_history": []
408
+ }
409
+ try:
410
+ logger.info(f"Buscando datos de análisis para el usuario: {username}")
411
+ cursor = analysis_collection.find({"username": username})
412
+
413
+ for entry in cursor:
414
+ formatted_entry = {
415
+ 'timestamp':datetime.now(timezone.utc).isoformat(),
416
+ "analysis_type": entry.get("analysis_type", "morphosyntax")
417
+ }
418
+
419
+ if formatted_entry["analysis_type"] == "morphosyntax":
420
+ formatted_entry.update({
421
+ "text": entry.get("text", ""),
422
+ "word_count": entry.get("word_count", {}),
423
+ "arc_diagrams": entry.get("arc_diagrams", [])
424
+ })
425
+ for category, count in formatted_entry["word_count"].items():
426
+ formatted_data["word_count"][category] = formatted_data["word_count"].get(category, 0) + count
427
+
428
+ elif formatted_entry["analysis_type"] == "semantic":
429
+ formatted_entry.update({
430
+ "key_concepts": entry.get("key_concepts", []),
431
+ "graph": entry.get("graph", "")
432
+ })
433
+ formatted_data["semantic_analyses"].append(formatted_entry)
434
+
435
+ elif formatted_entry["analysis_type"] == "discourse":
436
+ formatted_entry.update({
437
+ "text1": entry.get("text1", ""),
438
+ "text2": entry.get("text2", ""),
439
+ "key_concepts1": entry.get("key_concepts1", []),
440
+ "key_concepts2": entry.get("key_concepts2", []),
441
+ "graph1": entry.get("graph1", ""),
442
+ "graph2": entry.get("graph2", ""),
443
+ "combined_graph": entry.get("combined_graph", "")
444
+ })
445
+ formatted_data["discourse_analyses"].append(formatted_entry)
446
+
447
+ formatted_data["entries"].append(formatted_entry)
448
+
449
+ formatted_data["entries_count"] = len(formatted_data["entries"])
450
+ formatted_data["entries"].sort(key=lambda x: x["timestamp"], reverse=True)
451
+
452
+ for entry in formatted_data["entries"]:
453
+ entry["timestamp"] = entry["timestamp"].isoformat()
454
+
455
+ except Exception as e:
456
+ logger.error(f"Error al obtener datos de análisis del estudiante {username}: {str(e)}")
457
+
458
+ try:
459
+ logger.info(f"Buscando historial de chat para el usuario: {username}")
460
+ chat_cursor = chat_collection.find({"username": username})
461
+ for chat in chat_cursor:
462
+ formatted_chat = {
463
+ "timestamp": chat["timestamp"].isoformat(),
464
+ "messages": chat["messages"]
465
+ }
466
+ formatted_data["chat_history"].append(formatted_chat)
467
+
468
+ formatted_data["chat_history"].sort(key=lambda x: x["timestamp"], reverse=True)
469
+
470
+ except Exception as e:
471
+ logger.error(f"Error al obtener historial de chat del estudiante {username}: {str(e)}")
472
+ logger.info(f"Datos formateados para {username}: {formatted_data}")
473
+ return formatted_data
modules/database/backUp/database_v3-2ok.py ADDED
@@ -0,0 +1,629 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # database.py
2
+ import logging
3
+ import os
4
+ from azure.cosmos import CosmosClient
5
+ from azure.cosmos.exceptions import CosmosHttpResponseError
6
+ from pymongo import MongoClient
7
+ import certifi
8
+ from datetime import datetime, timezone
9
+ import io
10
+ from io import BytesIO
11
+ import base64
12
+ import matplotlib.pyplot as plt
13
+ from matplotlib.figure import Figure
14
+ import bcrypt
15
+ print(f"Bcrypt version: {bcrypt.__version__}")
16
+ import uuid
17
+ import plotly.graph_objects as go # Para manejar el diagrama de Sankey
18
+ import numpy as np # Puede ser necesario para algunas operaciones
19
+ logging.basicConfig(level=logging.DEBUG)
20
+ logger = logging.getLogger(__name__)
21
+
22
+ # Variables globales para Cosmos DB SQL API
23
+ application_requests_container = None
24
+ cosmos_client = None
25
+ user_database = None
26
+ user_container = None
27
+ user_feedback_container = None
28
+
29
+ # Variables globales para Cosmos DB MongoDB API
30
+ mongo_client = None
31
+ mongo_db = None
32
+ analysis_collection = None
33
+ chat_collection = None # Nueva variable global
34
+
35
+
36
+ ##############################################################################--- INICIO DE LAS BASES DE DATOS --- ###############################
37
+ def initialize_database_connections():
38
+ try:
39
+ print("Iniciando conexión a MongoDB")
40
+ mongodb_success = initialize_mongodb_connection()
41
+ print(f"Conexión a MongoDB: {'exitosa' if mongodb_success else 'fallida'}")
42
+ except Exception as e:
43
+ print(f"Error al conectar con MongoDB: {str(e)}")
44
+ mongodb_success = False
45
+
46
+ try:
47
+ print("Iniciando conexión a Cosmos DB SQL API")
48
+ sql_success = initialize_cosmos_sql_connection()
49
+ print(f"Conexión a Cosmos DB SQL API: {'exitosa' if sql_success else 'fallida'}")
50
+ except Exception as e:
51
+ print(f"Error al conectar con Cosmos DB SQL API: {str(e)}")
52
+ sql_success = False
53
+
54
+ return {
55
+ "mongodb": mongodb_success,
56
+ "cosmos_sql": sql_success
57
+ }
58
+
59
+ #####################################################################################33
60
+ def initialize_cosmos_sql_connection():
61
+ global cosmos_client, user_database, user_container, application_requests_container, user_feedback_container
62
+ logger.info("Initializing Cosmos DB SQL API connection")
63
+ try:
64
+ cosmos_endpoint = os.environ.get("COSMOS_ENDPOINT")
65
+ cosmos_key = os.environ.get("COSMOS_KEY")
66
+ logger.info(f"Cosmos Endpoint: {cosmos_endpoint}")
67
+ logger.info(f"Cosmos Key: {'*' * len(cosmos_key) if cosmos_key else 'Not set'}")
68
+
69
+ if not cosmos_endpoint or not cosmos_key:
70
+ logger.error("COSMOS_ENDPOINT or COSMOS_KEY environment variables are not set")
71
+ raise ValueError("Las variables de entorno COSMOS_ENDPOINT y COSMOS_KEY deben estar configuradas")
72
+
73
+ cosmos_client = CosmosClient(cosmos_endpoint, cosmos_key)
74
+ user_database = cosmos_client.get_database_client("user_database")
75
+ user_container = user_database.get_container_client("users")
76
+ application_requests_container = user_database.get_container_client("application_requests")
77
+ user_feedback_container = user_database.get_container_client("user_feedback")
78
+
79
+ logger.info(f"user_container initialized: {user_container is not None}")
80
+ logger.info(f"application_requests_container initialized: {application_requests_container is not None}")
81
+ logger.info(f"user_feedback_container initialized: {user_feedback_container is not None}")
82
+
83
+ logger.info("Conexión a Cosmos DB SQL API exitosa")
84
+ return True
85
+ except Exception as e:
86
+ logger.error(f"Error al conectar con Cosmos DB SQL API: {str(e)}", exc_info=True)
87
+ return False
88
+
89
+ ############################################################################################3
90
+ def initialize_mongodb_connection():
91
+ global mongo_client, mongo_db, analysis_collection, chat_collection
92
+ try:
93
+ cosmos_mongodb_connection_string = os.getenv("MONGODB_CONNECTION_STRING")
94
+ if not cosmos_mongodb_connection_string:
95
+ logger.error("La variable de entorno MONGODB_CONNECTION_STRING no está configurada")
96
+ return False
97
+
98
+ mongo_client = MongoClient(cosmos_mongodb_connection_string,
99
+ tls=True,
100
+ tlsCAFile=certifi.where(),
101
+ retryWrites=False,
102
+ serverSelectionTimeoutMS=5000,
103
+ connectTimeoutMS=10000,
104
+ socketTimeoutMS=10000)
105
+
106
+ mongo_client.admin.command('ping')
107
+
108
+ mongo_db = mongo_client['aideatext_db']
109
+ analysis_collection = mongo_db['text_analysis']
110
+ chat_collection = mongo_db['chat_history'] # Inicializar la nueva colección
111
+
112
+ # Verificar la conexión
113
+ mongo_client.admin.command('ping')
114
+
115
+ logger.info("Conexión a Cosmos DB MongoDB API exitosa")
116
+ return True
117
+ except Exception as e:
118
+ logger.error(f"Error al conectar con Cosmos DB MongoDB API: {str(e)}", exc_info=True)
119
+ return False
120
+
121
+ ##############################################################################--- FIN DEL INICIO DE LAS BASES DE DATOS --- ################################################################################################################################
122
+ ########################################################## -- INICIO DE GESTION DE USUARIOS ---##########################################################
123
+ def create_user(username, password, role):
124
+ global user_container
125
+ try:
126
+ print(f"Attempting to create user: {username} with role: {role}")
127
+ if user_container is None:
128
+ print("Error: user_container is None. Attempting to reinitialize connection.")
129
+ if not initialize_cosmos_sql_connection():
130
+ raise Exception("Failed to initialize SQL connection")
131
+
132
+ hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
133
+ print(f"Password hashed successfully for user: {username}")
134
+ user_data = {
135
+ 'id': username,
136
+ 'password': hashed_password,
137
+ 'role': role,
138
+ 'created_at': datetime.utcnow().isoformat()
139
+ }
140
+ user_container.create_item(body=user_data)
141
+ print(f"Usuario {role} creado: {username}") # Log para depuración
142
+ return True
143
+ except Exception as e:
144
+ print(f"Detailed error in create_user: {str(e)}")
145
+ return False
146
+
147
+ #######################################################################################################
148
+ def create_admin_user(username, password):
149
+ return create_user(username, password, 'Administrador')
150
+
151
+ #######################################################################################################
152
+ def create_student_user(username, password):
153
+ return create_user(username, password, 'Estudiante')
154
+
155
+ #######################################################################################################
156
+ # Funciones para Cosmos DB SQL API (manejo de usuarios)
157
+ def get_user(username):
158
+ try:
159
+ query = f"SELECT * FROM c WHERE c.id = '{username}'"
160
+ items = list(user_container.query_items(query=query, enable_cross_partition_query=True))
161
+ user = items[0] if items else None
162
+ if user:
163
+ print(f"Usuario encontrado: {username}, Rol: {user.get('role')}") # Log añadido
164
+ else:
165
+ print(f"Usuario no encontrado: {username}") # Log añadido
166
+ return user
167
+ except Exception as e:
168
+ print(f"Error al obtener usuario {username}: {str(e)}")
169
+ return None
170
+
171
+ ########################################################## -- FIN DE GESTION DE USUARIOS ---##########################################################
172
+
173
+ ########################################################## -- INICIO GESTION DE ARCHIVOS ---##########################################################
174
+
175
+ def store_file_contents(username, file_name, file_contents, analysis_type):
176
+ if user_container is None:
177
+ logger.error("La conexión a Cosmos DB SQL API no está inicializada")
178
+ return False
179
+ try:
180
+ document = {
181
+ 'id': f"{username}_{analysis_type}_{file_name}",
182
+ 'username': username,
183
+ 'file_name': file_name,
184
+ 'analysis_type': analysis_type,
185
+ 'file_contents': file_contents,
186
+ 'timestamp':datetime.now(timezone.utc).isoformat(),
187
+ }
188
+ user_container.upsert_item(body=document)
189
+ logger.info(f"Contenido del archivo guardado para el usuario: {username}, tipo de análisis: {analysis_type}")
190
+ return True
191
+ except Exception as e:
192
+ logger.error(f"Error al guardar el contenido del archivo para el usuario {username}: {str(e)}")
193
+ return False
194
+
195
+ def retrieve_file_contents(username, file_name, analysis_type):
196
+ print(f"Attempting to retrieve file: {file_name} for user: {username}")
197
+ if user_container is None:
198
+ logger.error("La conexión a Cosmos DB SQL API no está inicializada")
199
+ return None
200
+ try:
201
+ query = f"SELECT * FROM c WHERE c.id = '{username}_{analysis_type}_{file_name}'"
202
+ items = list(user_container.query_items(query=query, enable_cross_partition_query=True))
203
+ if items:
204
+ return items[0]['file_contents']
205
+ else:
206
+ logger.info(f"No se encontró contenido de archivo para el usuario: {username}, tipo de análisis: {analysis_type}")
207
+ return None
208
+ except Exception as e:
209
+ logger.error(f"Error al recuperar el contenido del archivo para el usuario {username}: {str(e)}")
210
+ return None
211
+
212
+ def get_user_files(username, analysis_type=None):
213
+ if user_container is None:
214
+ logger.error("La conexión a Cosmos DB SQL API no está inicializada")
215
+ return []
216
+ try:
217
+ if analysis_type:
218
+ query = f"SELECT c.file_name, c.analysis_type, c.timestamp FROM c WHERE c.username = '{username}' AND c.analysis_type = '{analysis_type}'"
219
+ else:
220
+ query = f"SELECT c.file_name, c.analysis_type, c.timestamp FROM c WHERE c.username = '{username}'"
221
+
222
+ items = list(user_container.query_items(query=query, enable_cross_partition_query=True))
223
+ return items
224
+ except Exception as e:
225
+ logger.error(f"Error al obtener la lista de archivos del usuario {username}: {str(e)}")
226
+ return []
227
+
228
+ def delete_file(username, file_name, analysis_type):
229
+ if user_container is None:
230
+ logger.error("La conexión a Cosmos DB SQL API no está inicializada")
231
+ return False
232
+ try:
233
+ user_container.delete_item(item=f"{username}_{analysis_type}_{file_name}", partition_key=username)
234
+ logger.info(f"Archivo eliminado para el usuario: {username}, tipo de análisis: {analysis_type}")
235
+ return True
236
+ except Exception as e:
237
+ logger.error(f"Error al eliminar el archivo para el usuario {username}: {str(e)}")
238
+ return False
239
+
240
+ ########################################################## -- FIN GESTION DE ARCHIVOS ---##########################################################
241
+
242
+ ########################################################## -- INICIO GESTION DE FORMULARIOS ---##########################################################
243
+ def store_application_request(name, email, institution, role, reason):
244
+ global application_requests_container
245
+ logger.info("Entering store_application_request function")
246
+ try:
247
+ logger.info("Checking application_requests_container")
248
+ if application_requests_container is None:
249
+ logger.error("application_requests_container is not initialized")
250
+ return False
251
+
252
+ logger.info("Creating application request document")
253
+ application_request = {
254
+ "id": str(uuid.uuid4()),
255
+ "name": name,
256
+ "email": email,
257
+ "institution": institution,
258
+ "role": role,
259
+ "reason": reason,
260
+ "requestDate": datetime.utcnow().isoformat()
261
+ }
262
+
263
+ logger.info(f"Attempting to store document: {application_request}")
264
+ application_requests_container.create_item(body=application_request)
265
+ logger.info(f"Application request stored for email: {email}")
266
+ return True
267
+ except Exception as e:
268
+ logger.error(f"Error storing application request: {str(e)}")
269
+ return False
270
+
271
+ #######################################################################################################
272
+ def store_user_feedback(username, name, email, feedback):
273
+ global user_feedback_container
274
+ logger.info(f"Attempting to store user feedback for user: {username}")
275
+ try:
276
+ if user_feedback_container is None:
277
+ logger.error("user_feedback_container is not initialized")
278
+ return False
279
+
280
+ feedback_item = {
281
+ "id": str(uuid.uuid4()),
282
+ "username": username,
283
+ "name": name,
284
+ "email": email,
285
+ "feedback": feedback,
286
+ "timestamp":datetime.now(timezone.utc).isoformat(),
287
+ }
288
+
289
+ result = user_feedback_container.create_item(body=feedback_item)
290
+ logger.info(f"User feedback stored with ID: {result['id']} for user: {username}")
291
+ return True
292
+ except Exception as e:
293
+ logger.error(f"Error storing user feedback for user {username}: {str(e)}")
294
+ return False
295
+
296
+
297
+ ########################################################## -- FIN GESTION DE FORMULARIOS ---##########################################################
298
+
299
+ ########################################################## -- INICIO ALMACENAMIENTO ANÁLISIS MORFOSINTÁCTICO ---##########################################################
300
+
301
+ def store_morphosyntax_result(username, text, repeated_words, arc_diagrams, pos_analysis, morphological_analysis, sentence_structure):
302
+ if analysis_collection is None:
303
+ logger.error("La conexión a MongoDB no está inicializada")
304
+ return False
305
+
306
+ try:
307
+ word_count = {}
308
+ for word, color in repeated_words.items():
309
+ category = color # Asumiendo que 'color' es la categoría gramatical
310
+ word_count[category] = word_count.get(category, 0) + 1
311
+
312
+ analysis_document = {
313
+ 'username': username,
314
+ 'timestamp':datetime.now(timezone.utc).isoformat(),
315
+ 'text': text,
316
+ 'word_count': word_count,
317
+ 'arc_diagrams': arc_diagrams,
318
+ 'pos_analysis': pos_analysis,
319
+ 'morphological_analysis': morphological_analysis,
320
+ 'sentence_structure': sentence_structure
321
+ }
322
+
323
+ result = analysis_collection.insert_one(analysis_document)
324
+ logger.info(f"Análisis guardado con ID: {result.inserted_id} para el usuario: {username}")
325
+ return True
326
+ except Exception as e:
327
+ logger.error(f"Error al guardar el análisis para el usuario {username}: {str(e)}")
328
+ return False
329
+
330
+ ########################################################## -- FIN ALMACENAMIENTO ANÁLISIS MORFOSINTÁCTICO ---##########################################################
331
+
332
+
333
+ ##########################################--- INICIO SECCIÓN DEL ANÁLISIS SEMÁNTICO ---###############################################
334
+
335
+ def store_file_semantic_contents(username, file_name, file_contents):
336
+ if user_container is None:
337
+ logger.error("La conexión a Cosmos DB SQL API no está inicializada")
338
+ return False
339
+ try:
340
+ document = {
341
+ 'id': f"{username}_semantic_{file_name}",
342
+ 'username': username,
343
+ 'file_name': file_name,
344
+ 'file_contents': file_contents,
345
+ 'analysis_type': 'semantic',
346
+ 'timestamp':datetime.now(timezone.utc).isoformat(),
347
+ }
348
+ user_container.upsert_item(body=document)
349
+ logger.info(f"Contenido del archivo semántico guardado para el usuario: {username}")
350
+ return True
351
+ except Exception as e:
352
+ logger.error(f"Error al guardar el contenido del archivo semántico para el usuario {username}: {str(e)}")
353
+ return False
354
+
355
+ def store_semantic_result(username, text, analysis_result):
356
+ if analysis_collection is None:
357
+ print("La conexión a MongoDB no está inicializada")
358
+ return False
359
+ try:
360
+ # Convertir los conceptos clave a una lista de tuplas
361
+ key_concepts = [(concept, float(frequency)) for concept, frequency in analysis_result['key_concepts']]
362
+
363
+ # Convertir los gráficos a imágenes base64
364
+ graphs = {}
365
+ for graph_name in ['relations_graph', 'entity_graph', 'topic_graph']:
366
+ if graph_name in analysis_result:
367
+ buf = BytesIO()
368
+ analysis_result[graph_name].savefig(buf, format='png')
369
+ buf.seek(0)
370
+ graphs[graph_name] = base64.b64encode(buf.getvalue()).decode('utf-8')
371
+
372
+ analysis_document = {
373
+ 'username': username,
374
+ 'timestamp':datetime.now(timezone.utc).isoformat(),
375
+ 'text': text,
376
+ 'key_concepts': key_concepts,
377
+ 'graphs': graphs,
378
+ 'summary': analysis_result.get('summary', ''),
379
+ 'entities': analysis_result.get('entities', {}),
380
+ 'sentiment': analysis_result.get('sentiment', ''),
381
+ 'topics': analysis_result.get('topics', []),
382
+ 'analysis_type': 'semantic'
383
+ }
384
+
385
+ result = analysis_collection.insert_one(analysis_document)
386
+ print(f"Análisis semántico guardado con ID: {result.inserted_id} para el usuario: {username}")
387
+ return True
388
+ except Exception as e:
389
+ print(f"Error al guardar el análisis semántico para el usuario {username}: {str(e)}")
390
+ return False
391
+
392
+ ##########################################--- FIN DE LA SECCIÓN DEL ANÁLISIS SEMÁNTICO ---###############################################
393
+
394
+ ############################################--- INICIO DE LA SECCIÓN DEL ANÁLISIS DEL DISCURSO ###################################################################
395
+
396
+ def store_discourse_analysis_result(username, text1, text2, analysis_result):
397
+ if analysis_collection is None:
398
+ print("La conexión a MongoDB no está inicializada")
399
+ return False
400
+
401
+ try:
402
+ # Convertir los grafos individuales a imágenes base64
403
+ buf1 = BytesIO()
404
+ analysis_result['graph1'].savefig(buf1, format='png')
405
+ buf1.seek(0)
406
+ img_str1 = base64.b64encode(buf1.getvalue()).decode('utf-8')
407
+
408
+ buf2 = BytesIO()
409
+ analysis_result['graph2'].savefig(buf2, format='png')
410
+ buf2.seek(0)
411
+ img_str2 = base64.b64encode(buf2.getvalue()).decode('utf-8')
412
+
413
+ # Crear una imagen combinada
414
+ fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(20, 10))
415
+ ax1.imshow(plt.imread(BytesIO(base64.b64decode(img_str1))))
416
+ ax1.axis('off')
417
+ ax1.set_title("Documento 1: Relaciones Conceptuales")
418
+ ax2.imshow(plt.imread(BytesIO(base64.b64decode(img_str2))))
419
+ ax2.axis('off')
420
+ ax2.set_title("Documento 2: Relaciones Conceptuales")
421
+
422
+ buf_combined = BytesIO()
423
+ fig.savefig(buf_combined, format='png')
424
+ buf_combined.seek(0)
425
+ img_str_combined = base64.b64encode(buf_combined.getvalue()).decode('utf-8')
426
+ plt.close(fig)
427
+
428
+ # Convertir los conceptos clave a listas de tuplas
429
+ key_concepts1 = [(concept, float(frequency)) for concept, frequency in analysis_result['key_concepts1']]
430
+ key_concepts2 = [(concept, float(frequency)) for concept, frequency in analysis_result['key_concepts2']]
431
+
432
+ # Crear el documento para guardar
433
+ analysis_document = {
434
+ 'username': username,
435
+ 'timestamp':datetime.now(timezone.utc).isoformat(),
436
+ #'text1': text1,
437
+ #'text2': text2,
438
+ 'graph1': img_str1,
439
+ 'graph2': img_str2,
440
+ 'combined_graph': img_str_combined,
441
+ 'key_concepts1': key_concepts1,
442
+ 'key_concepts2': key_concepts2,
443
+ 'analysis_type': 'discourse'
444
+ }
445
+
446
+ # Insertar el documento en la base de datos
447
+ result = analysis_collection.insert_one(analysis_document)
448
+ print(f"Análisis discursivo guardado con ID: {result.inserted_id} para el usuario: {username}")
449
+ return True
450
+ except Exception as e:
451
+ print(f"Error al guardar el análisis discursivo para el usuario {username}: {str(e)}")
452
+ print(f"Tipo de excepción: {type(e).__name__}")
453
+ print(f"Detalles de la excepción: {e.args}")
454
+ return False
455
+
456
+ ############################################--- FIN DE LA SECCIÓN DEL ANÁLISIS DEL DISCURSO ###################################################################
457
+
458
+
459
+ ################################################-- INICIO DE LA SECCIÓN DEL CHATBOT --- ###############################################################
460
+ def store_chat_history(username, messages):
461
+ try:
462
+ logger.info(f"Attempting to save chat history for user: {username}")
463
+ logger.debug(f"Messages to save: {messages}")
464
+
465
+ chat_document = {
466
+ 'username': username,
467
+ 'timestamp':datetime.now(timezone.utc).isoformat(),
468
+ 'messages': messages
469
+ }
470
+ result = chat_collection.insert_one(chat_document)
471
+ logger.info(f"Chat history saved with ID: {result.inserted_id} for user: {username}")
472
+ logger.debug(f"Chat content: {messages}")
473
+ return True
474
+ except Exception as e:
475
+ logger.error(f"Error saving chat history for user {username}: {str(e)}")
476
+ return False
477
+
478
+ #######################################################################################################
479
+ def export_analysis_and_chat(username, analysis_data, chat_data):
480
+ try:
481
+ export_data = {
482
+ "username": username,
483
+ 'timestamp':datetime.now(timezone.utc).isoformat(),
484
+ "analysis": analysis_data,
485
+ "chat": chat_data
486
+ }
487
+
488
+ # Aquí puedes decidir cómo quieres exportar los datos
489
+ # Por ejemplo, podrías guardarlos en una nueva colección en MongoDB
490
+ export_collection = mongo_db['exports']
491
+ result = export_collection.insert_one(export_data)
492
+
493
+ # También podrías generar un archivo JSON o CSV y guardarlo en Azure Blob Storage
494
+
495
+ return True
496
+ except Exception as e:
497
+ logger.error(f"Error al exportar análisis y chat para {username}: {str(e)}")
498
+ return False
499
+
500
+ ################################################-- FIN DE LA SECCIÓN DEL CHATBOT --- ###############################################################
501
+
502
+ #######################################################################################################################################################
503
+
504
+ def get_student_data(username):
505
+ if analysis_collection is None or chat_collection is None:
506
+ logger.error("La conexión a MongoDB no está inicializada")
507
+ return None
508
+ formatted_data = {
509
+ "username": username,
510
+ "entries": [],
511
+ "entries_count": 0,
512
+ "word_count": {},
513
+ "semantic_analyses": [],
514
+ "discourse_analyses": [],
515
+ "chat_history": []
516
+ }
517
+ try:
518
+ logger.info(f"Buscando datos de análisis para el usuario: {username}")
519
+ cursor = analysis_collection.find({"username": username})
520
+
521
+ for entry in cursor:
522
+ formatted_entry = {
523
+ "timestamp": entry.get("timestamp", datetime.now(timezone.utc).isoformat()),
524
+ "analysis_type": entry.get("analysis_type", "morphosyntax")
525
+ }
526
+
527
+ if formatted_entry["analysis_type"] == "morphosyntax":
528
+ formatted_entry.update({
529
+ "text": entry.get("text", ""),
530
+ "word_count": entry.get("word_count", {}),
531
+ "arc_diagrams": entry.get("arc_diagrams", [])
532
+ })
533
+ for category, count in formatted_entry["word_count"].items():
534
+ formatted_data["word_count"][category] = formatted_data["word_count"].get(category, 0) + count
535
+
536
+ elif formatted_entry["analysis_type"] == "semantic":
537
+ formatted_entry.update({
538
+ "key_concepts": entry.get("key_concepts", []),
539
+ "graph": entry.get("graph", "")
540
+ })
541
+ formatted_data["semantic_analyses"].append(formatted_entry)
542
+
543
+ elif formatted_entry["analysis_type"] == "discourse":
544
+ formatted_entry.update({
545
+ "text1": entry.get("text1", ""),
546
+ "text2": entry.get("text2", ""),
547
+ "key_concepts1": entry.get("key_concepts1", []),
548
+ "key_concepts2": entry.get("key_concepts2", []),
549
+ "graph1": entry.get("graph1", ""),
550
+ "graph2": entry.get("graph2", ""),
551
+ "combined_graph": entry.get("combined_graph", "")
552
+ })
553
+ formatted_data["discourse_analyses"].append(formatted_entry)
554
+
555
+ formatted_data["entries"].append(formatted_entry)
556
+
557
+ formatted_data["entries_count"] = len(formatted_data["entries"])
558
+ formatted_data["entries"].sort(key=lambda x: x["timestamp"], reverse=True)
559
+
560
+ for entry in formatted_data["entries"]:
561
+ entry["timestamp"] = entry["timestamp"].isoformat()
562
+
563
+ except Exception as e:
564
+ logger.error(f"Error al obtener datos de análisis del estudiante {username}: {str(e)}")
565
+
566
+ try:
567
+ logger.info(f"Buscando historial de chat para el usuario: {username}")
568
+ chat_cursor = chat_collection.find({"username": username})
569
+ for chat in chat_cursor:
570
+ formatted_chat = {
571
+ "timestamp": chat["timestamp"].isoformat(),
572
+ "messages": chat["messages"]
573
+ }
574
+ formatted_data["chat_history"].append(formatted_chat)
575
+
576
+ formatted_data["chat_history"].sort(key=lambda x: x["timestamp"], reverse=True)
577
+
578
+ except Exception as e:
579
+ logger.error(f"Error al obtener historial de chat del estudiante {username}: {str(e)}")
580
+ logger.info(f"Datos formateados para {username}: {formatted_data}")
581
+ return formatted_data
582
+
583
+ ################################################################
584
+ def get_user_analysis_summary(username):
585
+ if analysis_collection is None:
586
+ logger.error("La conexión a MongoDB no está inicializada")
587
+ return []
588
+ try:
589
+ summary = analysis_collection.aggregate([
590
+ {"$match": {"username": username}},
591
+ {"$group": {
592
+ "_id": "$analysis_type",
593
+ "count": {"$sum": 1},
594
+ "last_analysis": {"$max": "$timestamp"}
595
+ }}
596
+ ])
597
+ return list(summary)
598
+ except Exception as e:
599
+ logger.error(f"Error al obtener el resumen de análisis para el usuario {username}: {str(e)}")
600
+ return []
601
+
602
+ #######################################################################
603
+ def get_user_recent_chats(username, limit=5):
604
+ if chat_collection is None:
605
+ logger.error("La conexión a MongoDB no está inicializada")
606
+ return []
607
+ try:
608
+ recent_chats = chat_collection.find(
609
+ {"username": username},
610
+ {"messages": {"$slice": -5}}
611
+ ).sort("timestamp", -1).limit(limit)
612
+ return list(recent_chats)
613
+ except Exception as e:
614
+ logger.error(f"Error al obtener chats recientes para el usuario {username}: {str(e)}")
615
+ return []
616
+
617
+ #################################################
618
+ def get_user_analysis_details(username, analysis_type, skip=0, limit=10):
619
+ if analysis_collection is None:
620
+ logger.error("La conexión a MongoDB no está inicializada")
621
+ return []
622
+ try:
623
+ details = analysis_collection.find(
624
+ {"username": username, "analysis_type": analysis_type}
625
+ ).sort("timestamp", -1).skip(skip).limit(limit)
626
+ return list(details)
627
+ except Exception as e:
628
+ logger.error(f"Error al obtener detalles de análisis para el usuario {username}: {str(e)}")
629
+ return []
modules/database/chat_db.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #/modules/database/chat_db.py
2
+ from .mongo_db import insert_document, find_documents
3
+ from datetime import datetime, timezone
4
+ import logging
5
+ from .database_init import get_mongodb # Asegúrate de que esta importación esté al principio del archivo
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ COLLECTION_NAME = 'chat_history-v3'
10
+
11
+ def store_chat_history(username, messages, analysis_type):
12
+ chat_document = {
13
+ 'username': username,
14
+ 'timestamp': datetime.now(timezone.utc).isoformat(),
15
+ 'messages': messages,
16
+ 'analysis_type': analysis_type
17
+ }
18
+
19
+ result = insert_document(COLLECTION_NAME, chat_document)
20
+ if result:
21
+ logger.info(f"Historial de chat guardado con ID: {result} para el usuario: {username}")
22
+ return True
23
+ return False
24
+
25
+ def get_chat_history(username, analysis_type, limit=None):
26
+ query = {"username": username}
27
+ if analysis_type:
28
+ query["analysis_type"] = analysis_type
29
+
30
+ db = get_mongodb()
31
+ collection = db['chat_history-v3']
32
+ cursor = collection.find(query).sort("timestamp", -1)
33
+ if limit:
34
+ cursor = cursor.limit(limit)
35
+
36
+ return list(cursor)
37
+
38
+ #def get_chat_history(username, analysis_type=None, limit=10):
39
+ # query = {"username": username}
40
+ # if analysis_type:
41
+ # query["analysis_type"] = analysis_type
42
+
43
+ # return find_documents(COLLECTION_NAME, query, sort=[("timestamp", -1)], limit=limit)
44
+
45
+ # Agregar funciones para actualizar y eliminar chat si es necesario
modules/database/database_init.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import logging
3
+ from azure.cosmos import CosmosClient
4
+ from pymongo import MongoClient
5
+ import certifi
6
+
7
+ logging.basicConfig(level=logging.DEBUG)
8
+ logger = logging.getLogger(__name__)
9
+
10
+ # Variables globales para Cosmos DB SQL API
11
+ cosmos_client = None
12
+ user_database = None
13
+ user_container = None
14
+ application_requests_container = None
15
+ user_feedback_container = None
16
+
17
+ # Variables globales para Cosmos DB MongoDB API
18
+ mongo_client = None
19
+ mongo_db = None
20
+
21
+ def initialize_cosmos_sql_connection():
22
+ global cosmos_client, user_database, user_container, application_requests_container, user_feedback_container
23
+ try:
24
+ cosmos_endpoint = os.environ.get("COSMOS_ENDPOINT")
25
+ cosmos_key = os.environ.get("COSMOS_KEY")
26
+
27
+ if not cosmos_endpoint or not cosmos_key:
28
+ raise ValueError("COSMOS_ENDPOINT and COSMOS_KEY environment variables must be set")
29
+
30
+ cosmos_client = CosmosClient(cosmos_endpoint, cosmos_key)
31
+ user_database = cosmos_client.get_database_client("user_database")
32
+ user_container = user_database.get_container_client("users")
33
+ application_requests_container = user_database.get_container_client("application_requests")
34
+ user_feedback_container = user_database.get_container_client("user_feedback")
35
+
36
+ logger.info("Conexión a Cosmos DB SQL API exitosa")
37
+ return True
38
+ except Exception as e:
39
+ logger.error(f"Error al conectar con Cosmos DB SQL API: {str(e)}", exc_info=True)
40
+ return False
41
+
42
+ def initialize_mongodb_connection():
43
+ global mongo_client, mongo_db
44
+ try:
45
+ cosmos_mongodb_connection_string = os.getenv("MONGODB_CONNECTION_STRING")
46
+ if not cosmos_mongodb_connection_string:
47
+ raise ValueError("MONGODB_CONNECTION_STRING environment variable is not set")
48
+
49
+ mongo_client = MongoClient(cosmos_mongodb_connection_string,
50
+ tls=True,
51
+ tlsCAFile=certifi.where(),
52
+ retryWrites=False,
53
+ serverSelectionTimeoutMS=5000,
54
+ connectTimeoutMS=10000,
55
+ socketTimeoutMS=10000)
56
+
57
+ mongo_client.admin.command('ping')
58
+
59
+ mongo_db = mongo_client['aideatext_db']
60
+
61
+ logger.info("Conexión a Cosmos DB MongoDB API exitosa")
62
+ return True
63
+ except Exception as e:
64
+ logger.error(f"Error al conectar con Cosmos DB MongoDB API: {str(e)}", exc_info=True)
65
+ return False
66
+
67
+ def initialize_database_connections():
68
+ sql_success = initialize_cosmos_sql_connection()
69
+ mongodb_success = initialize_mongodb_connection()
70
+ return sql_success and mongodb_success
71
+
72
+ def get_sql_containers():
73
+ if user_container is None or application_requests_container is None or user_feedback_container is None:
74
+ initialize_cosmos_sql_connection()
75
+ return user_container, application_requests_container, user_feedback_container
76
+
77
+ def get_mongodb():
78
+ if mongo_db is None:
79
+ initialize_mongodb_connection()
80
+ return mongo_db
modules/database/mongo_db.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .database_init import get_mongodb
2
+ import logging
3
+
4
+ logger = logging.getLogger(__name__)
5
+
6
+ def get_collection(collection_name):
7
+ db = get_mongodb()
8
+ return db[collection_name]
9
+
10
+ def insert_document(collection_name, document):
11
+ collection = get_collection(collection_name)
12
+ try:
13
+ result = collection.insert_one(document)
14
+ logger.info(f"Documento insertado en {collection_name} con ID: {result.inserted_id}")
15
+ return result.inserted_id
16
+ except Exception as e:
17
+ logger.error(f"Error al insertar documento en {collection_name}: {str(e)}")
18
+ return None
19
+
20
+ def find_documents(collection_name, query, sort=None, limit=None):
21
+ collection = get_collection(collection_name)
22
+ try:
23
+ cursor = collection.find(query)
24
+ if sort:
25
+ cursor = cursor.sort(sort)
26
+ if limit:
27
+ cursor = cursor.limit(limit)
28
+ return list(cursor)
29
+ except Exception as e:
30
+ logger.error(f"Error al buscar documentos en {collection_name}: {str(e)}")
31
+ return []
32
+
33
+ def update_document(collection_name, query, update):
34
+ collection = get_collection(collection_name)
35
+ try:
36
+ result = collection.update_one(query, update)
37
+ logger.info(f"Documento actualizado en {collection_name}: {result.modified_count} modificado(s)")
38
+ return result.modified_count
39
+ except Exception as e:
40
+ logger.error(f"Error al actualizar documento en {collection_name}: {str(e)}")
41
+ return 0
42
+
43
+ def delete_document(collection_name, query):
44
+ collection = get_collection(collection_name)
45
+ try:
46
+ result = collection.delete_one(query)
47
+ logger.info(f"Documento eliminado de {collection_name}: {result.deleted_count} eliminado(s)")
48
+ return result.deleted_count
49
+ except Exception as e:
50
+ logger.error(f"Error al eliminar documento de {collection_name}: {str(e)}")
51
+ return 0
modules/database/morphosintax_mongo_db.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #/modules/database/morphosintax_mongo_db.py
2
+ from .mongo_db import insert_document, find_documents, update_document, delete_document
3
+ from ..utils.svg_to_png_converter import process_and_save_svg_diagrams
4
+ from datetime import datetime, timezone
5
+ import logging
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ COLLECTION_NAME = 'student_morphosyntax_analysis'
10
+
11
+ def store_student_morphosyntax_result(username, text, arc_diagrams):
12
+ analysis_document = {
13
+ 'username': username,
14
+ 'timestamp': datetime.now(timezone.utc).isoformat(),
15
+ 'text': text,
16
+ 'arc_diagrams': arc_diagrams,
17
+ 'analysis_type': 'morphosyntax'
18
+ }
19
+
20
+ result = insert_document(COLLECTION_NAME, analysis_document)
21
+ if result:
22
+ # Procesar y guardar los diagramas SVG como PNG
23
+ png_ids = process_and_save_svg_diagrams(username, str(result), arc_diagrams)
24
+
25
+ # Actualizar el documento con los IDs de los PNGs
26
+ update_document(COLLECTION_NAME, {'_id': result}, {'$set': {'png_diagram_ids': png_ids}})
27
+
28
+ logger.info(f"Análisis morfosintáctico del estudiante guardado con ID: {result} para el usuario: {username}")
29
+ return True
30
+ return False
31
+
32
+ def get_student_morphosyntax_analysis(username, limit=10):
33
+ query = {"username": username, "analysis_type": "morphosyntax"}
34
+ return find_documents(COLLECTION_NAME, query, sort=[("timestamp", -1)], limit=limit)
35
+
36
+ def update_student_morphosyntax_analysis(analysis_id, update_data):
37
+ query = {"_id": analysis_id}
38
+ update = {"$set": update_data}
39
+ return update_document(COLLECTION_NAME, query, update)
40
+
41
+ def delete_student_morphosyntax_analysis(analysis_id):
42
+ query = {"_id": analysis_id}
43
+ return delete_document(COLLECTION_NAME, query)
44
+
45
+ def get_student_morphosyntax_data(username):
46
+ analyses = get_student_morphosyntax_analysis(username, limit=None) # Obtener todos los análisis
47
+ return {
48
+ 'entries': analyses
49
+ }
modules/database/morphosintaxis_export.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from io import BytesIO
2
+ from reportlab.lib import colors
3
+ from reportlab.lib.pagesizes import letter
4
+ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image, PageBreak
5
+ from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
6
+ from reportlab.lib.units import cm
7
+ from svglib.svglib import svg2rlg
8
+ from reportlab.graphics import renderPM
9
+ import base64
10
+ import cairosvg
11
+ from reportlab.graphics import renderPDF
12
+ from reportlab.lib.utils import ImageReader
13
+
14
+ #importaciones locales
15
+ from .morphosintax_mongo_db import get_student_morphosyntax_data
16
+ from .chat_db import get_chat_history
17
+
18
+ # Placeholder para el logo
19
+ LOGO_PATH = "assets\img\logo_92x92.png" # Reemplaza esto con la ruta real de tu logo
20
+
21
+ # Definir el tamaño de página carta manualmente (612 x 792 puntos)
22
+ LETTER_SIZE = (612, 792)
23
+
24
+ def add_logo(canvas, doc):
25
+ logo = Image(LOGO_PATH, width=2*cm, height=2*cm)
26
+ logo.drawOn(canvas, doc.leftMargin, doc.height + doc.topMargin - 0.5*cm)
27
+
28
+ def export_user_interactions(username, analysis_type):
29
+ # Obtener historial de chat (que ahora incluye los análisis morfosintácticos)
30
+ chat_history = get_chat_history(username, analysis_type)
31
+
32
+ # Crear un PDF
33
+ buffer = BytesIO()
34
+ doc = SimpleDocTemplate(
35
+ buffer,
36
+ pagesize=letter,
37
+ rightMargin=2*cm,
38
+ leftMargin=2*cm,
39
+ topMargin=2*cm,
40
+ bottomMargin=2*cm
41
+ )
42
+
43
+ story = []
44
+ styles = getSampleStyleSheet()
45
+
46
+ # Título
47
+ story.append(Paragraph(f"Interacciones de {username} - Análisis {analysis_type}", styles['Title']))
48
+ story.append(Spacer(1, 0.5*cm))
49
+
50
+ # Historial del chat y análisis
51
+ for entry in chat_history:
52
+ for message in entry['messages']:
53
+ role = message['role']
54
+ content = message['content']
55
+ story.append(Paragraph(f"<b>{role.capitalize()}:</b> {content}", styles['BodyText']))
56
+ story.append(Spacer(1, 0.25*cm))
57
+
58
+ # Si hay visualizaciones (diagramas SVG), convertirlas a imagen y añadirlas
59
+ if 'visualizations' in message and message['visualizations']:
60
+ for svg in message['visualizations']:
61
+ drawing = svg2rlg(BytesIO(svg.encode('utf-8')))
62
+ img_data = BytesIO()
63
+ renderPM.drawToFile(drawing, img_data, fmt="PNG")
64
+ img_data.seek(0)
65
+ img = Image(img_data, width=15*cm, height=7.5*cm)
66
+ story.append(img)
67
+ story.append(Spacer(1, 0.5*cm))
68
+
69
+ story.append(PageBreak())
70
+
71
+ # Construir el PDF
72
+ doc.build(story)
73
+ buffer.seek(0)
74
+ return buffer
75
+
76
+ # Uso en Streamlit:
77
+ # pdf_buffer = export_user_interactions(username, 'morphosyntax')
78
+ # st.download_button(label="Descargar PDF", data=pdf_buffer, file_name="interacciones.pdf", mime="application/pdf")
modules/database/morphosintaxis_export_v1.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # database_export.py
2
+
3
+ import pandas as pd
4
+ import matplotlib.pyplot as plt
5
+ from io import BytesIO
6
+ #importaciones locales
7
+ from .morphosintax_mongo_db import get_student_morphosyntax_analysis
8
+ from .chat_db import get_chat_history
9
+
10
+
11
+ def export_user_interactions(username, analysis_type):
12
+ # Obtener historial de chat (que ahora incluye los análisis morfosintácticos)
13
+ chat_history = get_chat_history(username, analysis_type)
14
+
15
+ # Crear un PDF
16
+ buffer = BytesIO()
17
+ doc = SimpleDocTemplate(
18
+ buffer,
19
+ pagesize=letter,
20
+ rightMargin=2*cm,
21
+ leftMargin=2*cm,
22
+ topMargin=2*cm,
23
+ bottomMargin=2*cm
24
+ )
25
+
26
+ story = []
27
+ styles = getSampleStyleSheet()
28
+
29
+ # Título
30
+ story.append(Paragraph(f"Interacciones de {username} - Análisis {analysis_type}", styles['Title']))
31
+ story.append(Spacer(1, 0.5*cm))
32
+
33
+ # Historial del chat y análisis
34
+ for entry in chat_history:
35
+ for message in entry['messages']:
36
+ role = message['role']
37
+ content = message['content']
38
+ story.append(Paragraph(f"<b>{role.capitalize()}:</b> {content}", styles['BodyText']))
39
+ story.append(Spacer(1, 0.25*cm))
40
+
41
+ # Si hay visualizaciones (diagramas SVG), convertirlas a imagen y añadirlas
42
+ if 'visualizations' in message and message['visualizations']:
43
+ for svg in message['visualizations']:
44
+ drawing = svg2rlg(BytesIO(svg.encode('utf-8')))
45
+ img_data = BytesIO()
46
+ renderPM.drawToFile(drawing, img_data, fmt="PNG")
47
+ img_data.seek(0)
48
+ img = Image(img_data, width=15*cm, height=7.5*cm)
49
+ story.append(img)
50
+ story.append(Spacer(1, 0.5*cm))
51
+
52
+ story.append(PageBreak())
53
+
54
+ # Construir el PDF
55
+ doc.build(story)
56
+ buffer.seek(0)
57
+ return buffer
58
+
59
+ #def export_user_interactions(username, analysis_type):
60
+ # Obtener análisis morfosintáctico
61
+ #morphosyntax_data = get_student_morphosyntax_analysis(username)
62
+
63
+ # Obtener historial de chat
64
+ #chat_history = get_chat_history(username, analysis_type)
65
+
66
+ # Crear un DataFrame con los datos
67
+ #df = pd.DataFrame({
68
+ # 'Timestamp': [entry['timestamp'] for entry in chat_history],
69
+ # 'Role': [msg['role'] for entry in chat_history for msg in entry['messages']],
70
+ # 'Content': [msg['content'] for entry in chat_history for msg in entry['messages']]
71
+ #})
72
+
73
+ # Crear un PDF
74
+ #buffer = BytesIO()
75
+ #plt.figure(figsize=(12, 6))
76
+ #plt.axis('off')
77
+ #plt.text(0.5, 0.98, f"Interacciones de {username} - Análisis {analysis_type}", ha='center', va='top', fontsize=16)
78
+ #plt.text(0.5, 0.95, f"Total de interacciones: {len(df)}", ha='center', va='top', fontsize=12)
79
+
80
+ # Añadir tabla con las interacciones
81
+ #plt.table(cellText=df.values, colLabels=df.columns, cellLoc='center', loc='center')
82
+
83
+ # Añadir diagramas de arco si es análisis morfosintáctico
84
+ #if analysis_type == 'morphosyntax' and morphosyntax_data:
85
+ # for i, analysis in enumerate(morphosyntax_data):
86
+ # plt.figure(figsize=(12, 6))
87
+ # plt.axis('off')
88
+ # plt.text(0.5, 0.98, f"Diagrama de Arco {i+1}", ha='center', va='top', fontsize=16)
89
+ # plt.imshow(analysis['arc_diagrams'][0]) # Asumiendo que arc_diagrams es una lista de imágenes
90
+
91
+ #plt.savefig(buffer, format='pdf', bbox_inches='tight')
92
+ #buffer.seek(0)
93
+ #return buffer
94
+
95
+ # Uso:
96
+ # pdf_buffer = export_user_interactions(username, 'morphosyntax')
97
+ # st.download_button(label="Descargar PDF", data=pdf_buffer, file_name="interacciones.pdf", mime="application/pdf")
modules/database/sql_db.py ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .database_init import get_sql_containers
2
+ from datetime import datetime, timezone
3
+ import logging
4
+ import bcrypt
5
+ import uuid
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ def get_user(username, role=None):
10
+ user_container, _, _ = get_sql_containers()
11
+ try:
12
+ query = f"SELECT * FROM c WHERE c.id = '{username}'"
13
+ if role:
14
+ query += f" AND c.role = '{role}'"
15
+ items = list(user_container.query_items(query=query, enable_cross_partition_query=True))
16
+ return items[0] if items else None
17
+ except Exception as e:
18
+ logger.error(f"Error al obtener usuario {username}: {str(e)}")
19
+ return None
20
+
21
+ def get_admin_user(username):
22
+ return get_user(username, role='Administrador')
23
+
24
+ def get_student_user(username):
25
+ return get_user(username, role='Estudiante')
26
+
27
+ def get_teacher_user(username):
28
+ return get_user(username, role='Profesor')
29
+
30
+ def create_user(username, password, role, additional_info=None):
31
+ user_container, _, _ = get_sql_containers()
32
+ try:
33
+ hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
34
+ user_data = {
35
+ 'id': username,
36
+ 'password': hashed_password,
37
+ 'role': role,
38
+ 'timestamp': datetime.now(timezone.utc).isoformat(),
39
+ 'additional_info': additional_info or {}
40
+ }
41
+ user_container.create_item(body=user_data)
42
+ logger.info(f"Usuario {role} creado: {username}")
43
+ return True
44
+ except Exception as e:
45
+ logger.error(f"Error al crear usuario {role}: {str(e)}")
46
+ return False
47
+
48
+ def create_student_user(username, password, additional_info=None):
49
+ return create_user(username, password, 'Estudiante', additional_info)
50
+
51
+ def create_teacher_user(username, password, additional_info=None):
52
+ return create_user(username, password, 'Profesor', additional_info)
53
+
54
+ def create_admin_user(username, password, additional_info=None):
55
+ return create_user(username, password, 'Administrador', additional_info)
56
+
57
+
58
+ ###########################################################
59
+ def update_student_user(username, new_info):
60
+ user_container, _, _ = get_sql_containers()
61
+ try:
62
+ user = get_student_user(username)
63
+ if user:
64
+ user['additional_info'].update(new_info)
65
+ user_container.upsert_item(body=user)
66
+ logger.info(f"Información del estudiante actualizada: {username}")
67
+ return True
68
+ else:
69
+ logger.warning(f"Intento de actualizar estudiante no existente: {username}")
70
+ return False
71
+ except Exception as e:
72
+ logger.error(f"Error al actualizar información del estudiante {username}: {str(e)}")
73
+ return False
74
+
75
+
76
+ def delete_student_user(username):
77
+ user_container, _, _ = get_sql_containers()
78
+ try:
79
+ user = get_student_user(username)
80
+ if user:
81
+ user_container.delete_item(item=user['id'], partition_key=username)
82
+ logger.info(f"Estudiante eliminado: {username}")
83
+ return True
84
+ else:
85
+ logger.warning(f"Intento de eliminar estudiante no existente: {username}")
86
+ return False
87
+ except Exception as e:
88
+ logger.error(f"Error al eliminar estudiante {username}: {str(e)}")
89
+ return False
90
+
91
+ def store_application_request(name, lastname, email, institution, current_role, desired_role, reason):
92
+ _, application_requests_container, _ = get_sql_containers()
93
+ try:
94
+ application_request = {
95
+ "id": str(uuid.uuid4()),
96
+ "name": name,
97
+ "lastname": lastname,
98
+ "email": email,
99
+ "institution": institution,
100
+ "current_role": current_role,
101
+ "desired_role": desired_role,
102
+ "reason": reason,
103
+ "requestDate": datetime.utcnow().isoformat()
104
+ }
105
+ application_requests_container.create_item(body=application_request)
106
+ logger.info(f"Solicitud de aplicación almacenada para el email: {email}")
107
+ return True
108
+ except Exception as e:
109
+ logger.error(f"Error al almacenar la solicitud de aplicación: {str(e)}")
110
+ return False
111
+
112
+ def store_student_feedback(username, name, email, feedback):
113
+ _, _, user_feedback_container = get_sql_containers()
114
+ try:
115
+ feedback_item = {
116
+ "id": str(uuid.uuid4()),
117
+ "username": username,
118
+ "name": name,
119
+ "email": email,
120
+ "feedback": feedback,
121
+ "role": "Estudiante",
122
+ 'timestamp': datetime.now(timezone.utc).isoformat(),
123
+ }
124
+ result = user_feedback_container.create_item(body=feedback_item)
125
+ logger.info(f"Feedback de estudiante almacenado con ID: {result['id']} para el usuario: {username}")
126
+ return True
127
+ except Exception as e:
128
+ logger.error(f"Error al almacenar el feedback del estudiante {username}: {str(e)}")
129
+ return False
modules/database/txt.txt ADDED
File without changes