|
|
|
import logging |
|
from datetime import datetime, timezone |
|
import base64 |
|
from bson import Binary |
|
from pymongo.errors import PyMongoError |
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
COLLECTION_NAME = 'student_semantic_live_analysis' |
|
|
|
def store_student_semantic_live_result(username, text, analysis_result, lang_code='en'): |
|
""" |
|
Guarda el resultado del análisis semántico en vivo en MongoDB. |
|
Versión mejorada con manejo robusto de errores y verificación de datos. |
|
""" |
|
try: |
|
|
|
if not username or not isinstance(username, str): |
|
logger.error("Nombre de usuario inválido o vacío") |
|
return False |
|
|
|
if not text or not isinstance(text, str): |
|
logger.error("Texto de análisis inválido o vacío") |
|
return False |
|
|
|
if not analysis_result or not isinstance(analysis_result, dict): |
|
logger.error("Resultado de análisis inválido o vacío") |
|
return False |
|
|
|
|
|
concept_graph_data = None |
|
if 'concept_graph' in analysis_result and analysis_result['concept_graph'] is not None: |
|
try: |
|
graph_data = analysis_result['concept_graph'] |
|
|
|
if isinstance(graph_data, bytes): |
|
|
|
concept_graph_data = base64.b64encode(graph_data).decode('utf-8') |
|
elif isinstance(graph_data, str): |
|
|
|
concept_graph_data = graph_data |
|
elif isinstance(graph_data, Binary): |
|
|
|
concept_graph_data = base64.b64encode(graph_data).decode('utf-8') |
|
else: |
|
logger.warning(f"Formato de gráfico no soportado: {type(graph_data)}") |
|
except Exception as e: |
|
logger.error(f"Error al procesar gráfico conceptual: {str(e)}", exc_info=True) |
|
|
|
|
|
|
|
analysis_document = { |
|
'username': username, |
|
'timestamp': datetime.now(timezone.utc), |
|
'text': text[:10000], |
|
'analysis_type': 'semantic_live', |
|
'language': lang_code, |
|
'metadata': { |
|
'version': '1.0', |
|
'source': 'live_interface' |
|
} |
|
} |
|
|
|
|
|
if 'key_concepts' in analysis_result and isinstance(analysis_result['key_concepts'], list): |
|
analysis_document['key_concepts'] = analysis_result['key_concepts'][:50] |
|
|
|
if 'concept_centrality' in analysis_result and isinstance(analysis_result['concept_centrality'], dict): |
|
analysis_document['concept_centrality'] = analysis_result['concept_centrality'] |
|
|
|
if concept_graph_data: |
|
analysis_document['concept_graph'] = concept_graph_data |
|
|
|
|
|
try: |
|
collection = get_collection(COLLECTION_NAME) |
|
if not collection: |
|
logger.error("No se pudo obtener la colección MongoDB") |
|
return False |
|
|
|
result = collection.insert_one(analysis_document) |
|
|
|
if result.inserted_id: |
|
logger.info(f"Análisis guardado exitosamente para {username}. ID: {result.inserted_id}") |
|
return True |
|
|
|
logger.error("La operación de inserción no devolvió un ID") |
|
return False |
|
|
|
except PyMongoError as mongo_error: |
|
logger.error(f"Error de MongoDB al guardar análisis: {str(mongo_error)}", exc_info=True) |
|
return False |
|
|
|
except Exception as e: |
|
logger.error(f"Error inesperado al guardar análisis: {str(e)}", exc_info=True) |
|
return False |
|
|
|
def get_student_semantic_live_analysis(username, limit=10): |
|
""" |
|
Recupera los análisis semánticos en vivo de un estudiante. |
|
Versión mejorada con paginación y manejo de errores. |
|
""" |
|
try: |
|
|
|
if not username or not isinstance(username, str): |
|
logger.error("Nombre de usuario inválido para recuperación") |
|
return [] |
|
|
|
if not isinstance(limit, int) or limit <= 0: |
|
limit = 10 |
|
|
|
|
|
query = { |
|
"username": username, |
|
"analysis_type": "semantic_live" |
|
} |
|
|
|
projection = { |
|
"timestamp": 1, |
|
"text": {"$substr": ["$text", 0, 200]}, |
|
"key_concepts": {"$slice": ["$key_concepts", 10]}, |
|
"concept_graph": 1, |
|
"_id": 1, |
|
"metadata": 1 |
|
} |
|
|
|
|
|
try: |
|
collection = get_collection(COLLECTION_NAME) |
|
if not collection: |
|
logger.error("No se pudo obtener la colección MongoDB") |
|
return [] |
|
|
|
cursor = collection.find(query, projection).sort("timestamp", -1).limit(limit) |
|
results = list(cursor) |
|
|
|
|
|
for doc in results: |
|
if 'concept_graph' in doc and isinstance(doc['concept_graph'], str): |
|
try: |
|
|
|
doc['concept_graph'] = base64.b64decode(doc['concept_graph']) |
|
except Exception as e: |
|
logger.warning(f"Error al decodificar gráfico: {str(e)}") |
|
doc.pop('concept_graph', None) |
|
|
|
logger.info(f"Recuperados {len(results)} análisis para {username}") |
|
return results |
|
|
|
except PyMongoError as mongo_error: |
|
logger.error(f"Error de MongoDB al recuperar análisis: {str(mongo_error)}") |
|
return [] |
|
|
|
except Exception as e: |
|
logger.error(f"Error inesperado al recuperar análisis: {str(e)}", exc_info=True) |
|
return [] |
|
|
|
__all__ = [ |
|
'store_student_semantic_live_result', |
|
'get_student_semantic_live_analysis' |
|
] |