© AlastairRunning.com — Training Plan Builder CHANGELOG ============================================================= v2.26 (2026-10-18) — full algorithm audit and rebuild of the script block Verified with an automated harness (13 scenario plans, 5K to 100-mile, road and trail, miles and km, Friday/Saturday/Monday/Sunday races) plus a headless UI test of the complete form → generate → unit toggle → print → edit flow. ALGORITHM FIXES - Short-race long runs were broken. The 95%-of-race-distance cap on the peak long run (meant for marathons) applied to every distance, so a 5K plan ran a flat 4 mi long run every week and a 10K never got past 6 mi. The cap now applies only from 25K upward. Peak long-run table raised for short races: 5K 5/7/9 mi, 10K 6/8/10, half 10/12/14 (beginner/intermediate/advanced). - Easy runs could dwarf the long run (11.5 mi easy days next to a 4 mi long run; 26 mi "easy" runs for an 80 mpw runner on 4 days). Easy runs are now capped at 75% of that week's long run and 12 mi; a plan that cannot hold the runner's volume on the chosen number of days says so in the summary. - 10–15% rule enforced. Weekly volume is now built sequentially and capped at 115% of the previous build week's realized volume. Step-back weeks are 75% of the previous build week. The taper is a fraction of the peak actually reached. - Phase curve made continuous: Build now ends where Peak begins (previously the first Peak week could be lower than the last Build week). - Step-back weeks no longer land in a short Peak block (3 weeks or fewer); long peak blocks on 40+ week plans still get them. Long run drops to 80% on step-back weeks. Trail hill day becomes a steady "Hilly Run" on step-back weeks. - Minimum peak-volume floors added for half (22 mi) and marathon (35 mi) so a low-base runner is not handed a 25 mi/week marathon plan. Reaching the floor is still governed by the ramp; if the plan length cannot get there the summary says so and suggests a longer runway. - Long run start point respects the runner's base (≈22% of current weekly volume), so a 60–80 mpw runner no longer opens with a 10 mi long run. - Weekly elevation now equals the sum of the day cells. Per-day fractions used to add to 116–129% of the week; days are now allocated by normalized weights, gradient-capped, and rounded to 100 by largest remainder so cells add up and the week-to-week progression is smooth. Elevation peaks in the last pre-taper week and tapers in step with volume. - Final seven days before the race handled by calendar day, not by week: 1–2 days out rest, 3–6 days out short shakeout (strides 3–4 days out), race on the correct day. The last taper long run relocates to exactly six days out when the race is early in the week (fixes Friday and Monday races where the final long run sat 1–5 days before the race). Race week keeps at most (days/week − 1) shakeouts; shakeouts sized at 7% of peak week (2–5 mi). - Run/walk progression now applies only to beginners under ~10 mi (16 km) per week, not to every "beginner" (a 25 mpw runner does not need run/walk). - Goal time parsing: a two-part entry that implies an impossible pace is read as H:MM ("1:45" for a half = 1h45, previously 1 min 45 s → 0:05/km cues). Entries outside 4:00–25:00 per mile are rejected with a clear message. Goal time is only used when Time Goal is selected. - Pace model rebuilt: threshold and interval paces derived per distance from goal pace (5K: tempo ≈ 5K pace + 20–40 s; half: threshold ≈ HM pace − 8 s, reps at 10K pace; marathon: threshold ≈ MP − 20 s, reps at 10K pace). Tempo blocks progress from threshold toward race pace; marathon tempos finish at MP. - Hill repeats sized from the day's elevation: "6 × ~80 m hill". Base-phase and taper hill days are steady hilly runs, not repeats. TEXT / UNITS - Interval reps localized (4×1.6 km, not 4×1 mi, for km plans); tempo warm-up, block and cool-down computed in display units so they add up to the badge distance; warm-up scales to 1 mi / 2 km on longer tempos. - Summary peak now reports the plan's actual peak week (previously the theoretical target, and double-converted for km plans). - Race day text uses the entered race name. Trail time-goal long runs say "goal race effort", not "Marathon Pace finish". Leading-space and "pace., 0.5 mi" punctuation glitches fixed. - Phase chips say "Wk 9" rather than "Wks 9–9". UI - Typing in the distance or mileage field no longer re-renders the whole form (which stole focus); only the calendar/date section refreshes, debounced. - Unit toggle on a generated plan regenerates it from canonical inputs so every number and description is in the new unit (previously converted numbers only). - Day cards on screen show the calendar date next to the day name. - Print: restores the widget to its place via afterprint (with fallback) and reopens the week you had open; step-back rows labelled in the Phase column. - Calendar opens on the race month once a date is picked; "Earliest recommended race date" hint matches the first selectable day. - Generate button validates inputs and goal time with specific messages; the page scrolls to the top of the plan. - Race date stat card and print stats show the day of week. v2.25 (2026-05-04) - Plan start date and available week count anchored on the Monday of race week (raceMondayDate). Fixes non-Sunday races landing in the wrong week. v2.24 (2026-05-04) - nextMonday() returns today when today is Monday. - Print cells show calendar date ("May 4th"). v2.23 (2026-04-23) - Session distances snapped to 0.5; print descriptions rebalanced; 30K label threshold; stat card contrast; spacing. v2.22 (2026-04-23) Race Name field; TAK spacing applied to AR. v2.21 (2026-04-23) Race week built around actual race day of week. v2.20 (2026-04-23) Gradient caps per session type. v2.19 (2026-04-23) Race week elevation zeroed; syncF() before setState(). v2.18 (2026-04-23) Trail long run elevation 45%; elevation rounded to 100. v2.17 (2026-04-23) Elevation formula no longer ignores race elevation. v2.16–v2.0 (2026-03-30 to 03-31) See earlier changelogs.