Suppress the target band for laps that are just an unplanned continuation
Confirmed against Garmin Connect's own workout view: a lap whose IntensityType merely repeats the immediately preceding lap's (e.g. a second "cool-down" lap right after the first) means the recording continued past the end of that step, not that the workout prescribed a second target for it. Only the first lap of such a run keeps its target/HR fields; the continuation shows the actual trace with no expectation overlay. Doesn't affect normal interval structure, since Effort/Recovery always alternate and never appear back-to-back.
This commit is contained in:
@@ -147,10 +147,20 @@ interface Point {
|
||||
function buildLapWindows(laps: Lap[]): LapWindow[] {
|
||||
const windows: LapWindow[] = [];
|
||||
let elapsedMin = 0;
|
||||
for (const l of laps) {
|
||||
laps.forEach((l, i) => {
|
||||
const start = elapsedMin;
|
||||
elapsedMin += l.DurationSeconds / 60;
|
||||
|
||||
// A lap whose type merely repeats the previous lap's (e.g. a second
|
||||
// "cool-down" lap right after the first) means the recording continued
|
||||
// past the end of that step -- confirmed against Garmin Connect's own
|
||||
// workout view for a real activity where this happened: the run kept
|
||||
// going well past the prescribed cool-down, and Garmin logged the extra
|
||||
// time as a further same-type lap that was never actually part of the
|
||||
// workout. Only the first lap of such a run carries a real prescribed
|
||||
// target; the continuation's target/HR fields are suppressed.
|
||||
const isContinuation = i > 0 && laps[i - 1].IntensityType === l.IntensityType;
|
||||
|
||||
// Pace (sec/km) is inverted vs speed (m/s): the *faster* (higher) speed
|
||||
// bound is the *lower* (faster) pace bound.
|
||||
const paceLow = l.TargetPaceHighMps != null ? paceSecPerKm(l.TargetPaceHighMps) : null;
|
||||
@@ -160,13 +170,13 @@ function buildLapWindows(laps: Lap[]): LapWindow[] {
|
||||
start,
|
||||
end: elapsedMin,
|
||||
intensityType: l.IntensityType,
|
||||
targetPaceRange: paceLow != null && paceHigh != null ? [paceLow, paceHigh] : null,
|
||||
targetHRRange: l.TargetHRLowBpm != null && l.TargetHRHighBpm != null ? [l.TargetHRLowBpm, l.TargetHRHighBpm] : null,
|
||||
targetPaceRange: !isContinuation && paceLow != null && paceHigh != null ? [paceLow, paceHigh] : null,
|
||||
targetHRRange: !isContinuation && l.TargetHRLowBpm != null && l.TargetHRHighBpm != null ? [l.TargetHRLowBpm, l.TargetHRHighBpm] : null,
|
||||
avgPace: paceSecPerKm(l.AvgSpeedMps),
|
||||
avgHR: l.AvgHR,
|
||||
color: PHASE_COLORS[l.IntensityType],
|
||||
});
|
||||
}
|
||||
});
|
||||
return windows;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user