import gradio as gr import json import sqlite3 from datetime import datetime from pathlib import Path import os # Configuración de la base de datos DB_FILE = 'osorno_runners.db' def init_db(): """Inicializar base de datos SQLite""" conn = sqlite3.connect(DB_FILE) cursor = conn.cursor() # Tabla de planes cursor.execute(''' CREATE TABLE IF NOT EXISTS planes ( id INTEGER PRIMARY KEY AUTOINCREMENT, plan_data TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_by TEXT NOT NULL, athlete_name TEXT NOT NULL, distance TEXT NOT NULL, race_date TEXT NOT NULL ) ''') # Tabla de usuarios cursor.execute(''' CREATE TABLE IF NOT EXISTS users ( username TEXT PRIMARY KEY, password TEXT NOT NULL, role TEXT NOT NULL, name TEXT NOT NULL ) ''') # Insertar usuarios por defecto si no existen cursor.execute('SELECT COUNT(*) FROM users') if cursor.fetchone()[0] == 0: cursor.execute("INSERT INTO users VALUES ('USER', '123', 'user', 'Usuario')") cursor.execute("INSERT INTO users VALUES ('ADMIN', '123', 'admin', 'Administrador')") print("✅ Usuarios por defecto creados: USER/123 y ADMIN/123") conn.commit() conn.close() print("✅ Base de datos inicializada correctamente") def save_plan_to_db(plan_data, username): """Guardar plan en la base de datos""" try: conn = sqlite3.connect(DB_FILE) cursor = conn.cursor() cursor.execute(''' INSERT INTO planes (plan_data, created_by, athlete_name, distance, race_date) VALUES (?, ?, ?, ?, ?) ''', ( json.dumps(plan_data), username, plan_data['userData']['name'], plan_data['userData']['distance'], plan_data['userData']['raceDate'] )) conn.commit() plan_id = cursor.lastrowid conn.close() print(f"✅ Plan guardado con ID: {plan_id}") return plan_id except Exception as e: print(f"❌ Error al guardar plan: {e}") return None def get_all_plans(username=None, role='user'): """Obtener todos los planes según permisos""" try: conn = sqlite3.connect(DB_FILE) cursor = conn.cursor() if role == 'admin': cursor.execute('SELECT id, plan_data, created_at, created_by FROM planes ORDER BY created_at DESC') else: cursor.execute('SELECT id, plan_data, created_at, created_by FROM planes WHERE created_by = ? ORDER BY created_at DESC', (username,)) plans = [] for row in cursor.fetchall(): plan_data = json.loads(row[1]) plan_data['id'] = row[0] plan_data['createdAt'] = row[2] plan_data['createdBy'] = row[3] plans.append(plan_data) conn.close() print(f"✅ Cargados {len(plans)} planes para {username} ({role})") return plans except Exception as e: print(f"❌ Error al cargar planes: {e}") return [] def delete_plan_from_db(plan_id): """Eliminar plan de la base de datos""" try: conn = sqlite3.connect(DB_FILE) cursor = conn.cursor() cursor.execute('DELETE FROM planes WHERE id = ?', (plan_id,)) conn.commit() conn.close() print(f"✅ Plan {plan_id} eliminado") return True except Exception as e: print(f"❌ Error al eliminar plan: {e}") return False def authenticate_user(username, password): """Autenticar usuario""" try: conn = sqlite3.connect(DB_FILE) cursor = conn.cursor() cursor.execute('SELECT role, name FROM users WHERE username = ? AND password = ?', (username.upper(), password)) result = cursor.fetchone() conn.close() if result: user_data = { 'username': username.upper(), 'role': result[0], 'name': result[1] } print(f"✅ Login exitoso: {username} ({result[0]})") return user_data else: print(f"❌ Login fallido: {username}") return None except Exception as e: print(f"❌ Error en autenticación: {e}") return None # APIs para el frontend def api_login(request: gr.Request): """API de login""" try: data = json.loads(request.query_params.get('data', '{}')) username = data.get('username', '') password = data.get('password', '') user = authenticate_user(username, password) if user: return json.dumps({'success': True, 'user': user}) return json.dumps({'success': False, 'error': 'Credenciales inválidas'}) except Exception as e: return json.dumps({'success': False, 'error': str(e)}) def api_save_plan(request: gr.Request): """API para guardar plan""" try: data = json.loads(request.query_params.get('data', '{}')) plan_json = data.get('plan', '{}') username = data.get('username', '') plan_data = json.loads(plan_json) plan_id = save_plan_to_db(plan_data, username) if plan_id: return json.dumps({'success': True, 'id': plan_id}) return json.dumps({'success': False, 'error': 'Error al guardar'}) except Exception as e: return json.dumps({'success': False, 'error': str(e)}) def api_get_plans(request: gr.Request): """API para obtener planes""" try: data = json.loads(request.query_params.get('data', '{}')) username = data.get('username', '') role = data.get('role', 'user') plans = get_all_plans(username, role) return json.dumps({'success': True, 'plans': plans}) except Exception as e: return json.dumps({'success': False, 'error': str(e)}) def api_delete_plan(request: gr.Request): """API para eliminar plan""" try: data = json.loads(request.query_params.get('data', '{}')) plan_id = data.get('plan_id', 0) success = delete_plan_from_db(plan_id) if success: return json.dumps({'success': True}) return json.dumps({'success': False, 'error': 'Error al eliminar'}) except Exception as e: return json.dumps({'success': False, 'error': str(e)}) # Inicializar BD al arrancar print("🚀 Iniciando Osorno Runners - Sistema de Entrenamiento") init_db() # Leer HTML html_path = Path("index.html") if html_path.exists(): html_content = html_path.read_text(encoding='utf-8') print("✅ HTML cargado correctamente") else: html_content = "