The data
This app uses 2,507 public runner performances from Superior 100 races held from 2014 through 2025, excluding 2020. The records contain passage times at up to 14 aid stations, from Split Rock through the finish.
A person who raced in several years contributes one performance for each year. Missing splits are allowed, so not every performance contains every aid station.
Timing errors are removed when the data is built, and every removal is logged. Each race is checked against the field: a wrong split makes its two adjacent sections disagree wildly with the field’s typical time for those exact sections, and the split whose removal restores a normal race is dropped. A physical floor (no section faster than 8 min/mile) catches timing-station glitches that hit a whole pack identically. In total 49 of ~29,000 splits were dropped and 133 past-midnight clock wraps repaired; Split Rock times before 2017 are excluded because the course changed there.
Building the group
Your most recent sighting defines the group: every historical performance that reached that aid station within 10 minutes of your sighting. If fewer than 40 match, the window widens to 15, then 20 minutes. At least five are required to show results.
Older sightings are shown for reference but do not change the estimates. We tested this: matching on an earlier sighting as well, at any distance back, did not improve accuracy; it only shrank the group.
Every performance in the group counts equally. Nothing is weighted, modeled, or excluded at query time.
Turning history into clock times
The app measures how long each group member took to travel from your runner's latest sighted aid station to the upcoming station, and adds those real travel times to your sighting time.
This means the app does not copy a historical runner's absolute time of day. A runner seen at Sawbill at 1 PM is compared using historical Sawbill-to-Oberg travel durations, all starting from 1 PM on the current race clock.
Reading the results
- Every number in a row is a statistic of one group: the runners who reached the sighted station near the sighted time.
- Earliest is the group's fastest-ever arrival, and the lower bound of the display: in 11 years, nobody sighted where your runner was has arrived before it.
- 25%, half by, 75%, 95%: cumulative arrival marks. 25% of the group had arrived by the 25% time, and so on. Pick the mark that matches how much waiting you can afford; the app does not pick for you.
The app always shows how many runners are in the group and the window used to build it.
How the method was tested
Every claim above is verified by leave-one-year-out backtesting (tools/backtest.py): one race year is hidden, groups are built from every other year, and each hidden runner's recorded splits are replayed as sightings: 24,875 predictions across 2,407 runner-races.
- "Earliest" was beaten 2.4% of the time (about 1 in 40), which is what a sample minimum should do. Across a whole race, a runner beats at least one of their group minimums in about 1 in 5 races, usually by a few minutes.
- "Half by" split future arrivals 48.6% / 51.4%.
- The middle-half window (1 in 4 to 3 in 4) contained the actual arrival 49.7% of the time.
- The "95%" mark was exceeded by 6.2% of arrivals.
The test fails loudly if a future data or code change breaks any of these numbers.
Important limitations
- These statistics describe historical groups, not your specific runner. Weather, injury, aid station stops, and race-day decisions can change the result.
- "Earliest" is a statistic, not a guarantee: about 1 in 40 future runners arrive before their group's earliest. Leave margin for your own driving, parking, and walking.
- Public timing records can contain missing or incorrect splits. The build-time scrub removes obvious errors (and logs each one), but cannot identify every data problem.
- Aid station names and course distances have changed slightly across years. The model uses recorded passage times and station order, and excludes pre-2017 Split Rock times where the course change was material.