Skip to main content

Best efforts

A best effort is the best stretch of a given size inside a section: the highest average power held for 20 minutes, the fastest kilometre. They sit under the measure they are about: power and pace.

Power​

import { readFileSync } from 'node:fs';
import { km, minutes, seconds } from '@pond-ts/fit';
import { readActivity } from '@pond-ts/fit/files';

const ride = readActivity(readFileSync('hill-ride.fit'));
const best20 = ride.power.bestEffort(minutes(20))!;
console.log(best20.duration.format(), best20.power.format());
console.log(
best20.section.label,
best20.section.bounds.elapsed?.from.format(),
'→',
best20.section.bounds.elapsed?.to.format(),
);
20:00 269 W
Best 20:00 58:49 → 1:18:49

Each result hands back the Section it came from, so you can ask that stretch anything else: where it was, what the heart rate did, how it compares.

const where = best20.section.stats();
console.log(
where.distance?.format('km'),
where.heartRate.average?.format(),
where.cadence.average?.format(),
);
7.04 km 162 bpm 81 rpm

curve() gives the best for many durations at once, shortest first. With no durations it picks a spread from one second to the length of the section; or pass the ones you want:

for (const e of ride.power.curve([
seconds(5),
minutes(1),
minutes(5),
minutes(20),
minutes(60),
]))
console.log(e.duration.format().padStart(7), e.power.format());
0:05 355 W
1:00 323 W
5:00 309 W
20:00 269 W
1:00:00 221 W

A longer duration never has a higher best than a shorter one. Durations longer than the section are left out, and with no power the curve is empty and bestEffort is null.

Pace​

pace.bestEffort(distance) is the fastest elapsed time over that distance, stops included. bestEfforts() takes several, or by default the usual race distances (400 m up to the marathon) that fit inside the section:

const run = readActivity(readFileSync('interval-run.fit'));
for (const e of run.pace.bestEfforts())
console.log(
e.section.label.padEnd(10),
e.time.format().padStart(6),
e.pace.format(),
);
Best 400 m 1:31 3:48/km
Best 0.5 mi 3:05 3:50/km
Best 1 km 4:10 4:10/km
Best 1 mi 7:16 4:31/km
Best 2 mi 15:39 4:52/km
Best 5 km 24:49 4:58/km

Inside any section​

Best efforts belong to sections, so you can ask inside a lap, a climb or a stretch you picked:

const secondClimb = ride.section({ distance: { from: km(28), to: km(32) } });
console.log(secondClimb.power.bestEffort(minutes(5))?.power.format());
309 W

How gaps and pauses count​

  • A power meter dropout counts as 0 W. A best effort is work over time, and a dropout did no measured work. The ride's best 20 minutes contains its 15-second dropout; Power curve and best efforts shows what changes if you skip it instead.
  • A pause counts as 10 seconds at most. Each sample stands for the time since the one before, capped at 10 seconds, at its own power. So after a café pause the first sample stands for 10 seconds at whatever it recorded, and the pause adds nothing else. An effort can run across a stop this way: the riding either side of it makes one 20-minute effort, whose section runs longer than its duration. On the example ride, the best hour is made that way.
  • Pace efforts are on elapsed time. The fastest kilometre includes any time stood still inside it, as a race result would.