Spaces:
Configuration error
Configuration error
Create plan_generator.py
Browse files- plan_generator.py +67 -0
plan_generator.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from datetime import date
|
| 2 |
+
from dateutil.relativedelta import relativedelta
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
DISTANCES = {"5K": 5, "10K": 10, "21K": 21.097, "42K": 42.195}
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def weeks_until(target_iso):
|
| 9 |
+
tgt = date.fromisoformat(target_iso)
|
| 10 |
+
today = date.today()
|
| 11 |
+
return max(4, (tgt - today).days // 7)
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def base_paces(current_5k_pace_min_per_km: float):
|
| 15 |
+
# Deriva ritmos aproximados b谩sicos (puedes ajustar a tu criterio)
|
| 16 |
+
easy = current_5k_pace_min_per_km + 0.45 # ~+27s/km
|
| 17 |
+
tempo = current_5k_pace_min_per_km - 0.15 # ~-9s/km
|
| 18 |
+
intervals = current_5k_pace_min_per_km - 0.30
|
| 19 |
+
return round(easy,2), round(tempo,2), round(intervals,2)
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def build_plan(goal:str, target_date:str, days_per_week:int, long_run_day:str,
|
| 23 |
+
current_5k_pace:float, long_run_km:int|float, experience:str):
|
| 24 |
+
weeks = min(20, max(8, weeks_until(target_date)))
|
| 25 |
+
easy, tempo, intervals = base_paces(current_5k_pace)
|
| 26 |
+
goal_km = DISTANCES[goal]
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
# volumen inicial y progresi贸n simple
|
| 30 |
+
base_vol = max(20, int(long_run_km*2.5))
|
| 31 |
+
peak_vol = { "5K": 35, "10K": 45, "21K": 55, "42K": 80 }[goal]
|
| 32 |
+
progression = [(base_vol + int((peak_vol-base_vol)*i/(weeks-1))) for i in range(weeks)]
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
week_plan = []
|
| 36 |
+
for w in range(1, weeks+1):
|
| 37 |
+
vol = progression[w-1]
|
| 38 |
+
sessions = []
|
| 39 |
+
slots = min(5, max(3, days_per_week))
|
| 40 |
+
mix = ["Easy","Tempo","Easy","Intervals","LR"][:slots]
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
for s in mix:
|
| 44 |
+
if s=="Easy":
|
| 45 |
+
sessions.append({"tipo":"Rodaje suave","km": round(vol*0.20,1), "ritmo": f"{easy} min/km"})
|
| 46 |
+
elif s=="Tempo":
|
| 47 |
+
sessions.append({"tipo":"Tempo (umbral)","estructura": "2km cal + 4-6km tempo + 1km enf",
|
| 48 |
+
"ritmo": f"{tempo} min/km"})
|
| 49 |
+
elif s=="Intervals":
|
| 50 |
+
rep = 5 if goal in ("10K","21K") else 4
|
| 51 |
+
dist = 1.0 if goal!="5K" else 0.8
|
| 52 |
+
sessions.append({"tipo":"Intervalos", "estructura": f"{rep} x {dist}km (rec 2-3')",
|
| 53 |
+
"ritmo": f"{intervals} min/km"})
|
| 54 |
+
elif s=="LR":
|
| 55 |
+
lr = min(goal_km+10, max(long_run_km, int(vol*0.35)))
|
| 56 |
+
sessions.append({"tipo":f"Fondo {long_run_day}","km": lr, "ritmo": f"{easy+0.15} min/km"})
|
| 57 |
+
week_plan.append({"semana": w, "volumen_km": vol, "sesiones": sessions})
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
return {
|
| 61 |
+
"resumen": {
|
| 62 |
+
"semanas": weeks,
|
| 63 |
+
"volumen_pico_km": max(progression),
|
| 64 |
+
"ritmos": {"easy": easy, "tempo": tempo, "intervalos": intervals}
|
| 65 |
+
},
|
| 66 |
+
"plan": week_plan
|
| 67 |
+
}
|