Skip to content

feat: age grading with the 2025 road tables - #95

Closed
0jonjo wants to merge 2 commits into
mainfrom
feat/age-grade-road-2025
Closed

0jonjo wants to merge 2 commits into
mainfrom
feat/age-grade-road-2025

Conversation

@0jonjo

@0jonjo 0jonjo commented Oct 2, 2026

Copy link
Copy Markdown
Owner

What

Age grading now uses Alan Jones' 2025 road age-grading tables (approved 2025-01-10 by the USATF Masters Long Distance Running Council) — factors and open standards for 5K, 10K, half marathon and marathon, male and female.

The previous wma_2023_road.yml, despite its name, came from the WMA 2023 track and field tables (howardgrubb.co.uk/athletics/wmatnf23.html): track open standards (5000 m 12:35 / 14:06, 10 000 m 26:11 / 29:01), an outdated women's marathon standard (2:14:04), track keys "1500"/"3000", and factors only from age 30. Road age grades were off by ~1–3%.

Source (primary)

  • Repo: https://github.com/AlanLyttonJones/Age-Grade-Tables (pinned commit 4aac6737cb9f216c90a0a610355667cd3d921c61)
  • 2025 Files/MaleRoadStd2025.xlsx — sheet "Age Factors" (factors, row "OC sec" = open standard), sheet "AgeStdSec" (age standards, used for the cross-check)
  • 2025 Files/FemaleRoadStd2025.xlsx — sheet "Age Facctors" (sic) / "AgeStanSec"
  • Columns: "5 km", "10 km", "H. Mar" (21.0975 km), "Marathon" (42.195 km). Factors are "open standard / age standard" (≤ 1), so the gem's seconds * factor and open_standard / age_graded_time are unchanged.
  • The four columns are byte-identical to the version uploaded right after approval (commit 43e3cceb88, 2025-01-13); the later commits only changed the male road mile (per the author's commit message, verified by diffing).
  • Also verified identical to the AgeGrade.5k/.10k/.hm/.42k text files in 2025 Files/AgeGrade.zip (same repo) and to the data embedded in Howard Grubb's MLDR road calculator 2025 (http://howardgrubb.co.uk/athletics/mldrroad25.html) — the latter used only as a cross-check.

Changes

  • lib/calcpace/data/mldr_2025_road.yml (was wma_2023_road.yml): M/F → "5000", "10000", "21097", "42195" → one factor per age, 18–100. Ages > 100 clamp to the age-100 factor; < 18 still refused.
  • lib/calcpace/data/mldr_2025_road_open_standards.yml (was wma_2023_open_standards.yml): new meta (source, URL, files), table_version: MLDR_2025_ROAD_ONE_YEAR_FACTORS_V1, open standards M 769/1584/3451/7235 s, F 834/1726/3772/7796 s. Category labels/mins unchanged.
  • DATA_PATH, OPEN_STANDARDS_DATA_PATH, WMA_DATA, OPEN_STANDARDS_DATA, TABLE_VERSION keep their names and shapes.
  • Module docs, README age-grading section, gemspec description, CHANGELOG ([Unreleased]; no version bump — v1.19.0 is in flight on another branch).
  • Tests: official reference cases, open standards, under-30 factors, table coverage 18–100, clamp past 100; boundary test re-pointed (10K 2750 s → 2741 s still lands on exactly 60.0%).

Cross-check (gem vs official)

Official = age standard (AgeStdSec sheet) / time. Grubb = his 2025 calculator's algorithm on his embedded data.

Case Factor Gem Official spreadsheet Grubb 2025 calc Before (WMA 2023 track)
Male 40, marathon 3:30:00 0.9783 58.7% 58.69% (7395 s / 12600 s) 58.69% 58.8%
Female 50, marathon 4:00:00 0.8998 60.2% 60.17% (8664 / 14400) 60.17% 62.7%
Female 30, 5K 25:00 0.9959 55.8% 55.80% (837 / 1500) 55.83% 56.4%
Male 60, half 1:50:00 0.8082 64.7% 64.70% (4270 / 6600) 64.70% 63.3%

Baseline diff (gem_realismo/baseline.rb, 1.18.1 vs this branch) — only "Age grade" changes

@@ -18,13 +18,13 @@
 half_marathon 01:45:00 -> marathon: 03:38:55 | 03:30:00 | 03:37:58
 
 ## Age grade (%)
-male 30 5k 00:20:00: 62.9% Local Class (factor 1.0, std 00:12:35)
-male 45 10k 00:45:00: 63.6% Local Class (factor 0.9155, std 00:26:11)
-female 30 5k 00:25:00: 56.4% Intermediate (factor 1.0, std 00:14:06)
-female 50 marathon 04:00:00: 62.7% Local Class (factor 0.8915, std 02:14:04)
-male 60 half_marathon 01:50:00: 63.3% Local Class (factor 0.8264, std 00:57:31)
-female 35 10k 00:50:00: 58.8% Intermediate (factor 0.9869, std 00:29:01)
-male 40 marathon 03:30:00: 58.8% Intermediate (factor 0.9804, std 02:01:09)
+male 30 5k 00:20:00: 64.1% Local Class (factor 0.9999, std 00:12:49)
+male 45 10k 00:45:00: 63.3% Local Class (factor 0.9261, std 00:26:24)
+female 30 5k 00:25:00: 55.8% Intermediate (factor 0.9959, std 00:13:54)
+female 50 marathon 04:00:00: 60.2% Local Class (factor 0.8998, std 02:09:56)
+male 60 half_marathon 01:50:00: 64.7% Local Class (factor 0.8082, std 00:57:31)
+female 35 10k 00:50:00: 58.4% Intermediate (factor 0.9857, std 00:28:46)
+male 40 marathon 03:30:00: 58.7% Intermediate (factor 0.9783, std 02:00:35)
 
 ## Altitude (%)
 0 m: 0.0

Verification

  • bundle exec rake test: 513 runs, 1191 assertions, 0 failures, 0 errors, 0 skips
  • bundle exec rubocop: 44 files inspected, no offenses detected
  • gem build packages both new data files.

0jonjo added 2 commits October 2, 2026 06:21
Replace the age-grading data with Alan Jones' 2025 road tables (approved
2025-01-10 by the USATF Masters Long Distance Running Council), taken from
MaleRoadStd2025.xlsx / FemaleRoadStd2025.xlsx in
github.com/AlanLyttonJones/Age-Grade-Tables.

The old file, despite its "road" name, held the WMA 2023 track and field
factors and track open standards, with no factors under age 30, so road
age grades were off by about 1-3%. Factors now cover every age from 18 to
100 for 5K, 10K, half marathon and marathon.

Data files renamed to mldr_2025_road*.yml; table_version becomes
MLDR_2025_ROAD_ONE_YEAR_FACTORS_V1. Public constants and category labels
are unchanged.
Link the 2025 road tables at the commit the data came from, correct the
age-clamp note (old table ran to 110, new ends at 100), list the dropped
WMA_DATA track keys under Breaking, and replace the vacuous interpolation
test with one that drives a sparse stubbed table.
@0jonjo

0jonjo commented Oct 2, 2026

Copy link
Copy Markdown
Owner Author

Superseded by #97 (released as 2.0.0).

@0jonjo 0jonjo closed this Oct 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant