TrainerRunning / app.py
rogarces85's picture
Upload 5 files
fa1a61c verified
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 = "<h1>Error: index.html no encontrado</h1>"
print("❌ Error: index.html no encontrado")
# Crear interfaz Gradio
with gr.Blocks(
title="Osorno Runners",
theme=gr.themes.Soft(),
css="""
.gradio-container {padding: 0 !important;}
.contain {max-width: 100% !important;}
"""
) as app:
gr.HTML(html_content)
# Configuración del servidor
if __name__ == "__main__":
print("🌐 Iniciando servidor en puerto 7860")
app.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
show_error=True
)