rogarces85 commited on
Commit
3bcd6b5
·
verified ·
1 Parent(s): fc5b9e3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +91 -229
app.py CHANGED
@@ -1,231 +1,93 @@
1
- import gradio as gr
2
- import json
3
- import sqlite3
4
- from datetime import datetime
5
- from pathlib import Path
6
- import os
7
-
8
- # Configuración de la base de datos
9
- DB_FILE = 'osorno_runners.db'
10
-
11
- def init_db():
12
- """Inicializar base de datos SQLite"""
13
- conn = sqlite3.connect(DB_FILE)
14
- cursor = conn.cursor()
15
-
16
- # Tabla de planes
17
- cursor.execute('''
18
- CREATE TABLE IF NOT EXISTS planes (
19
- id INTEGER PRIMARY KEY AUTOINCREMENT,
20
- plan_data TEXT NOT NULL,
21
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
22
- created_by TEXT NOT NULL,
23
- athlete_name TEXT NOT NULL,
24
- distance TEXT NOT NULL,
25
- race_date TEXT NOT NULL
26
- )
27
- ''')
28
-
29
- # Tabla de usuarios
30
- cursor.execute('''
31
- CREATE TABLE IF NOT EXISTS users (
32
- username TEXT PRIMARY KEY,
33
- password TEXT NOT NULL,
34
- role TEXT NOT NULL,
35
- name TEXT NOT NULL
36
- )
37
- ''')
38
-
39
- # Insertar usuarios por defecto si no existen
40
- cursor.execute('SELECT COUNT(*) FROM users')
41
- if cursor.fetchone()[0] == 0:
42
- cursor.execute("INSERT INTO users VALUES ('USER', '123', 'user', 'Usuario')")
43
- cursor.execute("INSERT INTO users VALUES ('ADMIN', '123', 'admin', 'Administrador')")
44
- print("✅ Usuarios por defecto creados: USER/123 y ADMIN/123")
45
-
46
- conn.commit()
47
- conn.close()
48
- print("✅ Base de datos inicializada correctamente")
49
-
50
- def save_plan_to_db(plan_data, username):
51
- """Guardar plan en la base de datos"""
52
- try:
53
- conn = sqlite3.connect(DB_FILE)
54
- cursor = conn.cursor()
55
-
56
- cursor.execute('''
57
- INSERT INTO planes (plan_data, created_by, athlete_name, distance, race_date)
58
- VALUES (?, ?, ?, ?, ?)
59
- ''', (
60
- json.dumps(plan_data),
61
- username,
62
- plan_data['userData']['name'],
63
- plan_data['userData']['distance'],
64
- plan_data['userData']['raceDate']
65
- ))
66
-
67
- conn.commit()
68
- plan_id = cursor.lastrowid
69
- conn.close()
70
-
71
- print(f"✅ Plan guardado con ID: {plan_id}")
72
- return plan_id
73
- except Exception as e:
74
- print(f" Error al guardar plan: {e}")
75
- return None
76
-
77
- def get_all_plans(username=None, role='user'):
78
- """Obtener todos los planes según permisos"""
79
- try:
80
- conn = sqlite3.connect(DB_FILE)
81
- cursor = conn.cursor()
82
-
83
- if role == 'admin':
84
- cursor.execute('SELECT id, plan_data, created_at, created_by FROM planes ORDER BY created_at DESC')
85
- else:
86
- cursor.execute('SELECT id, plan_data, created_at, created_by FROM planes WHERE created_by = ? ORDER BY created_at DESC', (username,))
87
-
88
- plans = []
89
- for row in cursor.fetchall():
90
- plan_data = json.loads(row[1])
91
- plan_data['id'] = row[0]
92
- plan_data['createdAt'] = row[2]
93
- plan_data['createdBy'] = row[3]
94
- plans.append(plan_data)
95
-
96
- conn.close()
97
- print(f"✅ Cargados {len(plans)} planes para {username} ({role})")
98
- return plans
99
- except Exception as e:
100
- print(f"❌ Error al cargar planes: {e}")
101
- return []
102
-
103
- def delete_plan_from_db(plan_id):
104
- """Eliminar plan de la base de datos"""
105
- try:
106
- conn = sqlite3.connect(DB_FILE)
107
- cursor = conn.cursor()
108
- cursor.execute('DELETE FROM planes WHERE id = ?', (plan_id,))
109
- conn.commit()
110
- conn.close()
111
- print(f"✅ Plan {plan_id} eliminado")
112
- return True
113
- except Exception as e:
114
- print(f"❌ Error al eliminar plan: {e}")
115
- return False
116
-
117
- def authenticate_user(username, password):
118
- """Autenticar usuario"""
119
- try:
120
- conn = sqlite3.connect(DB_FILE)
121
- cursor = conn.cursor()
122
- cursor.execute('SELECT role, name FROM users WHERE username = ? AND password = ?',
123
- (username.upper(), password))
124
- result = cursor.fetchone()
125
- conn.close()
126
-
127
- if result:
128
- user_data = {
129
- 'username': username.upper(),
130
- 'role': result[0],
131
- 'name': result[1]
132
- }
133
- print(f"✅ Login exitoso: {username} ({result[0]})")
134
- return user_data
135
- else:
136
- print(f"❌ Login fallido: {username}")
137
- return None
138
- except Exception as e:
139
- print(f"❌ Error en autenticación: {e}")
140
- return None
141
-
142
- # APIs para el frontend
143
- def api_login(request: gr.Request):
144
- """API de login"""
145
- try:
146
- data = json.loads(request.query_params.get('data', '{}'))
147
- username = data.get('username', '')
148
- password = data.get('password', '')
149
-
150
- user = authenticate_user(username, password)
151
- if user:
152
- return json.dumps({'success': True, 'user': user})
153
- return json.dumps({'success': False, 'error': 'Credenciales inválidas'})
154
- except Exception as e:
155
- return json.dumps({'success': False, 'error': str(e)})
156
-
157
- def api_save_plan(request: gr.Request):
158
- """API para guardar plan"""
159
- try:
160
- data = json.loads(request.query_params.get('data', '{}'))
161
- plan_json = data.get('plan', '{}')
162
- username = data.get('username', '')
163
-
164
- plan_data = json.loads(plan_json)
165
- plan_id = save_plan_to_db(plan_data, username)
166
-
167
- if plan_id:
168
- return json.dumps({'success': True, 'id': plan_id})
169
- return json.dumps({'success': False, 'error': 'Error al guardar'})
170
- except Exception as e:
171
- return json.dumps({'success': False, 'error': str(e)})
172
-
173
- def api_get_plans(request: gr.Request):
174
- """API para obtener planes"""
175
- try:
176
- data = json.loads(request.query_params.get('data', '{}'))
177
- username = data.get('username', '')
178
- role = data.get('role', 'user')
179
-
180
- plans = get_all_plans(username, role)
181
- return json.dumps({'success': True, 'plans': plans})
182
- except Exception as e:
183
- return json.dumps({'success': False, 'error': str(e)})
184
-
185
- def api_delete_plan(request: gr.Request):
186
- """API para eliminar plan"""
187
- try:
188
- data = json.loads(request.query_params.get('data', '{}'))
189
- plan_id = data.get('plan_id', 0)
190
-
191
- success = delete_plan_from_db(plan_id)
192
- if success:
193
- return json.dumps({'success': True})
194
- return json.dumps({'success': False, 'error': 'Error al eliminar'})
195
- except Exception as e:
196
- return json.dumps({'success': False, 'error': str(e)})
197
-
198
- # Inicializar BD al arrancar
199
- print("🚀 Iniciando Osorno Runners - Sistema de Entrenamiento")
200
- init_db()
201
-
202
- # Leer HTML
203
- html_path = Path("index.html")
204
- if html_path.exists():
205
- html_content = html_path.read_text(encoding='utf-8')
206
- print("✅ HTML cargado correctamente")
207
- else:
208
- html_content = "<h1>Error: index.html no encontrado</h1>"
209
- print("❌ Error: index.html no encontrado")
210
-
211
- # Crear interfaz Gradio
212
- with gr.Blocks(
213
- title="Osorno Runners",
214
- theme=gr.themes.Soft(),
215
- css="""
216
- .gradio-container {padding: 0 !important;}
217
- .contain {max-width: 100% !important;}
218
- """
219
- ) as app:
220
- gr.HTML(html_content)
221
-
222
- # Configuración del servidor
223
  if __name__ == "__main__":
224
- print("🌐 Iniciando servidor en puerto 7860")
225
- app.launch(
226
- server_name="0.0.0.0",
227
- server_port=7860,
228
- share=False,
229
- show_error=True
230
- )
231
 
 
1
+ import os, json, io
2
+ lines = []
3
+ try:
4
+ path = hf_hub_download(repo_id=OUT_DATASET, repo_type="dataset", filename=OUT_FILE, token=HF_TOKEN)
5
+ with open(path, "r", encoding="utf-8") as f:
6
+ lines = f.read().splitlines()
7
+ except Exception:
8
+ lines = []
9
+
10
+
11
+ lines.append(json.dumps(record, ensure_ascii=False))
12
+ content = "\n".join(lines).encode("utf-8")
13
+
14
+
15
+ upload_file(
16
+ path_or_fileobj=io.BytesIO(content),
17
+ path_in_repo=OUT_FILE,
18
+ repo_id=OUT_DATASET,
19
+ repo_type="dataset",
20
+ token=HF_TOKEN
21
+ )
22
+ return f"Guardado en {OUT_DATASET}/{OUT_FILE}"
23
+
24
+
25
+ # --- Callback principal ---
26
+
27
+
28
+ def on_generate(name, age, sex, distance, target_date,
29
+ days_per_week, long_run_day, current_5k_pace, long_run_km, experience,
30
+ keywords, topk):
31
+ # 1) búsqueda en el dataset
32
+ table = search_papers(keywords, topk)
33
+ # 2) generar plan
34
+ plan = build_plan(distance, target_date, int(days_per_week), long_run_day,
35
+ float(current_5k_pace), float(long_run_km), experience)
36
+ # 3) guardar
37
+ record = {
38
+ "ts": datetime.utcnow().isoformat()+"Z",
39
+ "user": {"name": name, "age": age, "sex": sex},
40
+ "goal": {"distance": distance, "target_date": target_date},
41
+ "prefs": {"days_per_week": days_per_week, "long_run_day": long_run_day, "experience": experience},
42
+ "benchmarks": {"current_5k_pace_min_per_km": current_5k_pace, "long_run_km": long_run_km},
43
+ "keywords": keywords,
44
+ "plan": plan
45
+ }
46
+ saved = ensure_repo_and_push(record)
47
+ return table, json.dumps(plan, ensure_ascii=False, indent=2), saved
48
+
49
+
50
+ # --- UI ---
51
+ with gr.Blocks(title="OR_Training Running Plan Builder") as demo:
52
+ gr.Markdown("""
53
+ # 🏃 OR_Training — Running Plan Builder
54
+ Este Space busca en literatura (dataset NCBI extraído) y genera un **plan básico** personalizado.
55
+ - Dataset: `florentgbelidji/ncbi_extracted_running` (recomendado **duplicarlo** a `rogarces85/ncbi_extracted_running`).
56
+ - Cada envío puede guardarse como una línea en `dataset` propio (`OR_Training_submissions`).
57
+ """)
58
+
59
+
60
+ with gr.Row():
61
+ with gr.Column():
62
+ gr.Markdown("### 🔎 Búsqueda en el dataset")
63
+ keywords = gr.Textbox(label="Palabras clave (ej: injury, marathon, VO2max)")
64
+ topk = gr.Slider(1, 20, value=5, step=1, label="Resultados (top-k)")
65
+ table_out = gr.Dataframe(label="Artículos coincidentes (id, title, date, authors, language, snippet)", wrap=True, height=300)
66
+
67
+
68
+ with gr.Column():
69
+ gr.Markdown("### 📝 Formulario del atleta")
70
+ name = gr.Textbox(label="Nombre", value="")
71
+ age = gr.Number(label="Edad", value=30)
72
+ sex = gr.Radio(["F","M","Otro"], label="Sexo", value="F")
73
+ distance = gr.Dropdown(["5K","10K","21K","42K"], value="21K", label="Objetivo")
74
+ target_date = gr.Textbox(label="Fecha objetivo (YYYY-MM-DD)", value="2026-03-01")
75
+ days_per_week = gr.Slider(3,6,value=4,step=1,label="Días/semana")
76
+ long_run_day = gr.Dropdown(["Sábado","Domingo"], value="Domingo", label="Día de fondo")
77
+ current_5k_pace = gr.Number(label="Ritmo actual 5K (min/km)", value=5.30)
78
+ long_run_km = gr.Number(label="Fondo actual (km)", value=12)
79
+ experience = gr.Dropdown(["Principiante","Intermedio","Avanzado"], value="Intermedio", label="Experiencia")
80
+ btn = gr.Button("Generar plan y guardar envío")
81
+ plan_json = gr.Code(label="Plan (JSON)", language="json", lines=20)
82
+ saved_label = gr.Markdown()
83
+
84
+
85
+ btn.click(on_generate,
86
+ inputs=[name, age, sex, distance, target_date, days_per_week, long_run_day,
87
+ current_5k_pace, long_run_km, experience, keywords, topk],
88
+ outputs=[table_out, plan_json, saved_label])
89
+
90
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  if __name__ == "__main__":
92
+ demo.launch()
 
 
 
 
 
 
93