Stop a marked day distorting Timing, the trends, and its neighbour

Marking a day "not counted" was implemented by filtering its events out of the
list the cross-day panels are given. That is too blunt a tool, because three of
those panels are not asking "which days count":

  - Timing's marker is how long since the last pee, which is a question about
    now. With the marked day's events gone it answered from the day before —
    27 hours instead of 2 in the case I reproduced, so the marker sat off the
    end of its band.

  - The sleep and walk trends draw the day you are looking at against yesterday
    and the average. Marking that day collapsed its own curve to a flat zero.
    Marking a day means don't let it drag the average, not pretend nothing
    happened on it.

  - A nap from 23:00 on a marked day to 07:00 the next morning lost its
    sleep-start, leaving a dangling sleep-end that pairWindows discards. The
    next day — not marked — lost seven hours it really slept. Nobody reported
    this one; it turned up while reproducing the other two.

None of them needed the filtering, because each already excludes marked days
itself and more precisely than deleting events can: gapsBetween throws away a
gap that *touches* one, the trend loops skip them when averaging, weeklyData
and the actograms zero and hatch them. The filter was a second mechanism
fighting the first. Only the by-hour and training panels still get the filtered
list — they bucket individual events and care about neither day boundaries nor
spans, which is exactly what removing events does.
This commit is contained in:
Alexander Heldt
2026-09-20 10:42:51 +00:00
parent e4b056b5b9
commit 8d7139b031
3 changed files with 32 additions and 6 deletions
+9
View File
@@ -164,6 +164,15 @@ heading, takes the day you're looking at out of the aggregates.
- **What stops counting** is the behaviour: sleep hours, timeline and trend,
walk minutes and patterns, pee/poo/meal counts, food, by-hour, the training
grid, and the Timing panel's typical gaps.
- **Marking a day is not the same as deleting its events**, and only two panels
are handed a filtered list (by-hour and training, which bucket individual
events and care about neither day boundaries nor spans). The rest take the
whole log and exclude days themselves, because three things break if the
events simply go: "how long since the last pee" is a question about *now* and
answered from the wrong event; the trend curve for the day you are *looking
at* collapses to zero; and a nap from 23:00 on a marked day to 07:00 on the
next loses its `sleep-start`, leaving a dangling `sleep-end` and costing the
next day — which isn't marked — seven hours it really slept.
- **What keeps counting** is weight and notes. A weigh-in and a vet note are
records of fact, not behaviour a sparse logger distorts, so they stay on the
weight curve and in the Notes log.
+22 -6
View File
@@ -2792,12 +2792,28 @@
// logger distorts, so they count everywhere regardless.
renderWeight(events);
renderNotes(events);
// Everything that aggregates across days works from the counted list.
renderTiming(counted);
renderWeekly(counted);
renderSleepTimeline(counted);
renderWalkPatterns(counted);
renderSleepTrend(counted);
// These take the whole list even though they aggregate, because each
// already knows about marked days and does something more precise with
// them than dropping their events would:
//
// - gapsBetween throws away a gap that *touches* a marked day, and
// "how long since the last one" is a question about now, not about
// the window — with the events gone it answered from the wrong one.
// - the trend curves skip marked days when averaging, but the curve for
// the day you are looking at is about that day; marking it means
// "don't let it drag the average", not "pretend nothing happened".
// - weeklyData and the actograms zero and hatch a marked day themselves,
// and need the events either side of it: a nap from 23:00 on a marked
// day to 07:00 on the next belongs, for those seven hours, to the next
// day — which is not marked and should show them. Dropping the
// sleep-start left a dangling sleep-end and lost the window entirely.
renderTiming(events);
renderWeekly(events);
renderSleepTimeline(events);
renderWalkPatterns(events);
renderSleepTrend(events);
// These two bucket individual events with no notion of a day boundary or a
// span, so removing the marked days' events is exactly the right tool.
renderHourHeatmap(counted);
renderTraining(counted);
}
+1
View File
@@ -1,4 +1,5 @@
[
{ "date": "2026-09-20", "text": "Fixed three things that went wrong around a day marked “not counted”. The Timing panel measured “how long since the last pee” from before the marked day rather than from the actual last one, so the marker sat far out to the right. The Sleep and Walk trends drew the marked day's own curve as a flat zero when you were looking at that day — marking a day means don't let it drag the average, not pretend nothing happened on it. And a nap that started on a marked day and ended the next morning vanished from that next day's figures, even though the next day wasn't marked and the puppy really did sleep those hours" },
{ "date": "2026-09-09", "text": "The big asleep/awake card at the top of Today is gone, and both timers now live permanently in the frozen bar at the top — visible on every tab, wherever you have scrolled to. The card only existed on one tab and the timers hid themselves whenever it was on screen, which meant the thing you most often want at a glance was the thing you had to go and find. With only one place left to show them they have their seconds back too" },
{ "date": "2026-09-08", "text": "The date now opens a small month grid of the app's own instead of the browser's date picker. The browser's one is a sheet that covers the screen, which is backwards when the reason to change day is to see what the numbers did on it — this one sits under the bar with the overview still visible and updating as you move. ← and → still step a day at a time; the grid is for jumping further, and the Today button now lives inside it. That is what made room for the walk timer and the sleep timer to sit on one row: the top bar no longer splits onto two rows on a phone, except on the very smallest. The two timers count in minutes now rather than seconds — the big card on Today still ticks in seconds, which is where you look if you want them" },
{ "date": "2026-09-08", "text": "A walk in progress now has a timer in the frozen bar at the top, next to the asleep/awake one, counting from when the walk started — so you can see how long you have been out from any tab without going to look. Tapping it ends the walk, the same way tapping the sleep timer logs the sleep boundary. On a narrow phone two timers no longer fit beside the date controls, so the bar splits onto two rows while a walk is on and goes back to one when it ends. The big timer card on Today shows the walk too while there is one — you are awake on a walk either way, so the walk is the more useful of the two" },