Remove the walking goal
It was mine, not the user's: added unprompted alongside the Walks panel because sleepTargetFor existed and it seemed to fit. The number came from the "five-minute rule" — five minutes per month of age, twice a day — written from general knowledge with no source consulted and none cited in the code. That rule is widely repeated but is folk guidance, not a veterinary standard. Its origin is unclear, it is contested by what evidence exists on early exercise and joint development, and it ignores breed, terrain, lead or off-lead and the individual dog. Drawing it as a line labelled "Goal", with a ✓ for clearing it, stated it far more confidently than a rule of thumb earns — particularly in an app whose entire job is otherwise to record what happened rather than to advise. So the target line goes, along with its legend chip, the ✓, and walkTargetFor itself, which had no other caller. The trend keeps today against yesterday and the average: a record, with the judgement left to whoever knows the dog.
This commit is contained in:
+4
-48
@@ -664,19 +664,6 @@
|
||||
.map(w => ({ start: w.start, end: w.end, ongoing: w.ongoing && today }));
|
||||
}
|
||||
|
||||
// Rough age-based walking guideline (the widely used "five-minute rule"):
|
||||
// about 5 minutes per month of age per walk, twice a day, until the puppy is
|
||||
// grown. Returns null without a birthday or once it's a year old, the same
|
||||
// way sleepTargetFor bows out.
|
||||
function walkTargetFor(birthday) {
|
||||
const a = ageParts(birthday);
|
||||
if (!a || a.months >= 12) return null;
|
||||
// Under a month of counted age the rule has nothing to say yet; treat it
|
||||
// as one "month" so the advice stays a short outing rather than zero.
|
||||
const months = Math.max(1, a.months);
|
||||
return { perWalk: months * 5, walks: 2, total: months * 10 };
|
||||
}
|
||||
|
||||
// ---------- rendering ----------
|
||||
const dayPicker = document.getElementById("day-picker");
|
||||
const eventList = document.getElementById("event-list");
|
||||
@@ -1762,7 +1749,7 @@
|
||||
};
|
||||
}
|
||||
|
||||
function drawWalkTrendChart(curves, target) {
|
||||
function drawWalkTrendChart(curves) {
|
||||
const svg = document.getElementById("chart-walk-trend");
|
||||
if (!svg) return;
|
||||
const W = 320, H = 180;
|
||||
@@ -1777,12 +1764,7 @@
|
||||
{ pts: curves.today, cls: "wtrend-today", label: curves.dayLabel },
|
||||
].filter(s => s.pts && s.pts.length > 1);
|
||||
|
||||
// The axis has to reach the goal even on a day that fell well short of it,
|
||||
// or the line it is measured against would sit off the top of the chart.
|
||||
const rawMax = Math.max(
|
||||
target ? target.total : 0,
|
||||
...series.flatMap(s => s.pts.map(p => p.y)),
|
||||
);
|
||||
const rawMax = Math.max(...series.flatMap(s => s.pts.map(p => p.y)));
|
||||
const { yMax, steps } = niceAxisLinear(rawMax);
|
||||
// Minutes are linear all the way down, so no split axis: the sleep trend
|
||||
// stretches its top because the interesting hours cluster near a 16h goal,
|
||||
@@ -1804,16 +1786,6 @@
|
||||
parts.push(`<text x="${x.toFixed(1)}" y="${H - MB + 14}" text-anchor="${anchor}">${pad2(hr)}</text>`);
|
||||
}
|
||||
|
||||
// The five-minute rule as one line rather than a band: it is a target to
|
||||
// reach, with no upper bound a band would imply.
|
||||
if (target) {
|
||||
const y = yOf(Math.min(target.total, yMax));
|
||||
parts.push(
|
||||
`<line class="wtrend-goal" x1="${ML}" y1="${y.toFixed(1)}" x2="${W - MR}" y2="${y.toFixed(1)}">` +
|
||||
`<title>${escapeText(`Goal ~${target.total} min (${target.perWalk} min × ${target.walks})`)}</title></line>`
|
||||
);
|
||||
}
|
||||
|
||||
for (const s of series) {
|
||||
const d = s.pts
|
||||
.map((p, i) => `${i === 0 ? "M" : "L"}${xOf(p.x).toFixed(1)} ${yOf(p.y).toFixed(1)}`)
|
||||
@@ -1830,22 +1802,11 @@
|
||||
|
||||
function renderWalkTrend(events) {
|
||||
const curves = walkTrendCurves(events);
|
||||
const target = walkTargetFor(loadConfig().birthday);
|
||||
drawWalkTrendChart(curves, target);
|
||||
drawWalkTrendChart(curves);
|
||||
|
||||
const chip = (id) => document.getElementById(id);
|
||||
const mins = (pts) => `${Math.round(pts[pts.length - 1].y)} min`;
|
||||
// With no projection to carry it, the ✓ goes on today's own chip: the goal
|
||||
// is a total for the day, so today's line is what meets it or doesn't.
|
||||
let mark = "";
|
||||
if (target) {
|
||||
const done = curves.today[curves.today.length - 1].y >= target.total;
|
||||
mark = done ? " ✓" : "";
|
||||
chip("legend-wtrend-today-text").parentElement.title = done
|
||||
? "Past the walking goal for this age"
|
||||
: `Goal is about ${target.total} min a day at this age`;
|
||||
}
|
||||
chip("legend-wtrend-today-text").textContent = `${curves.dayLabel} ${mins(curves.today)}${mark}`;
|
||||
chip("legend-wtrend-today-text").textContent = `${curves.dayLabel} ${mins(curves.today)}`;
|
||||
|
||||
const yLegend = chip("legend-wtrend-yesterday");
|
||||
yLegend.hidden = !curves.yesterday;
|
||||
@@ -1857,11 +1818,6 @@
|
||||
if (curves.avg) {
|
||||
chip("legend-wtrend-avg-text").textContent = `${curves.avgDays}-day avg ${mins(curves.avg)}`;
|
||||
}
|
||||
const gLegend = chip("legend-wtrend-goal");
|
||||
gLegend.hidden = !target;
|
||||
if (target) {
|
||||
chip("legend-wtrend-goal-text").textContent = `Goal ~${target.total} min`;
|
||||
}
|
||||
}
|
||||
|
||||
// Which heatmap block is focused, remembered across re-renders so a background
|
||||
|
||||
Reference in New Issue
Block a user