fix(oura): stop importing the equivalent walking distance as distance

Oura's equivalent_walking_distance is the distance a walk of the day's
effort would have covered, not distance travelled. Written as
WALKING_RUNNING_DISTANCE it counted a bike ride or a yoga hour as
kilometres walked. The daily activity mapper now writes steps and active
energy only.
This commit is contained in:
Marc-André Bombeck committed 2026-10-21 19:23:34 +02:00
1 parent b60fa0123b
commit 9a3523a498
3 files changed
+24 -25

No files matched your search

+7 -7
View File
@@ -471,7 +471,7 @@ describe("mapSleep", () => {
});
describe("mapDailyActivity", () => {
it("maps steps, active energy, and equivalent walking distance (m)", () => {
it("maps steps and active energy, and never the equivalent walking distance", () => {
const a: OuraDailyActivity = {
id: "1",
day: "2026-06-10",
@@ -484,12 +484,12 @@ describe("mapDailyActivity", () => {
expect(mapped.find((m) => m.type === "ACTIVE_ENERGY_BURNED")?.value).toBe(
412,
);
const dist = mapped.find((m) => m.type === "WALKING_RUNNING_DISTANCE");
expect(dist).toMatchObject({
value: 6543,
unit: "m",
fieldTag: "distance",
});
// An activity equivalent, not distance travelled: no distance row at all.
expect(mapped.map((m) => m.type).sort()).toEqual([
"ACTIVE_ENERGY_BURNED",
"ACTIVITY_STEPS",
]);
expect(mapped.some((m) => m.fieldTag === "distance")).toBe(false);
});
});
+16 -17
View File
@@ -449,7 +449,11 @@ export interface OuraDailyActivity {
steps?: number | null;
active_calories?: number | null;
total_calories?: number | null;
/** Equivalent walking distance for the day, metres. */
/**
* Oura's activity-equivalent distance, metres: what a walk of the day's
* effort would have covered. Not distance travelled; never imported (see
* `mapDailyActivity`).
*/
equivalent_walking_distance?: number | null;
}
@@ -972,8 +976,17 @@ export function mapDailySpo2(
];
}
/** Map one Oura daily-activity record: steps, active energy, and the
* equivalent walking distance (B5 — the OURA distance ladder slot was dead). */
/**
* Map one Oura daily-activity record: steps and active energy.
*
* `equivalent_walking_distance` is deliberately not mapped. Oura derives it
* from the day's whole activity (the distance a walk of the same effort would
* have covered), so an hour of cycling or yoga adds kilometres nobody walked.
* Stored as `WALKING_RUNNING_DISTANCE` it read as real distance, and on a day
* no other source covered it became the day's distance. The rows earlier
* syncs wrote under `activity:<day>:distance` are retired on their own
* (`./retire-distance`).
*/
export function mapDailyActivity(
a: OuraDailyActivity,
tz?: string,
@@ -999,20 +1012,6 @@ export function mapDailyActivity(
fieldTag: "active_energy",
});
}
if (
typeof a.equivalent_walking_distance === "number" &&
a.equivalent_walking_distance >= 0
) {
out.push({
type: "WALKING_RUNNING_DISTANCE",
// Oura reports the equivalent walking distance in metres — the canonical
// WALKING_RUNNING_DISTANCE unit (no conversion).
value: importValue(a.equivalent_walking_distance),
unit: "m",
measuredAt,
fieldTag: "distance",
});
}
return out;
}
+1 -1
View File
@@ -4,7 +4,7 @@
* Pulls daily readiness (→ RECOVERY_SCORE + BODY_TEMPERATURE_DEVIATION), sleep
* (real per-segment hypnogram timeline when present, else per-stage totals;
* efficiency, HRV, RHR, respiratory rate), daily activity (steps, active
* energy, equivalent walking distance), the daily Sleep Score (→ SLEEP_SCORE),
* energy), the daily Sleep Score (→ SLEEP_SCORE),
* daily SpO2 (→ OXYGEN_SATURATION), the dedicated vO2_max collection (→
* VO2_MAX), and the daily cardiovascular-age estimate (→ VASCULAR_AGE) for one
* connected user, mapping each into `Measurement` rows tagged `source = OURA`.