Add more statistics

This commit is contained in:
Alexander Heldt
2026-06-25 14:23:44 +00:00
parent 06c51bb715
commit 709a051afb
3 changed files with 66 additions and 0 deletions
+48
View File
@@ -473,6 +473,52 @@
document.getElementById("stat-poos").textContent = count("poo");
}
// Gaps (ms) between consecutive events of `type` logged within the last
// `days` days, sorted ascending. These intervals are what tell you how
// often the puppy needs to go out.
function gapsBetween(events, type, days = 7) {
const cutoff = startOfDay(new Date());
cutoff.setDate(cutoff.getDate() - (days - 1));
const from = cutoff.getTime();
const times = events
.filter(e => e.type === type && e.at >= from)
.map(e => e.at)
.sort((a, b) => a - b);
const gaps = [];
for (let i = 1; i < times.length; i++) gaps.push(times[i] - times[i - 1]);
return gaps.sort((a, b) => a - b);
}
// Median is used for the "typical" gap because it ignores the single long
// overnight gap each day, so it reflects real daytime frequency.
function median(sorted) {
if (sorted.length === 0) return null;
const mid = Math.floor(sorted.length / 2);
return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
}
function renderTiming(events) {
const peeGaps = gapsBetween(events, "pee");
const pooGaps = gapsBetween(events, "poo");
const show = (id, ms) => {
document.getElementById(id).textContent = ms == null ? "—" : formatDuration(ms);
};
show("gap-pee", median(peeGaps));
show("gap-pee-min", peeGaps[0] ?? null);
show("gap-poo", median(pooGaps));
show("gap-poo-min", pooGaps[0] ?? null);
const hint = document.getElementById("timing-hint");
const typicalPee = median(peeGaps);
if (typicalPee != null) {
hint.textContent =
`Based on ${peeGaps.length} pee gap${peeGaps.length === 1 ? "" : "s"}. ` +
`Aim to take the puppy out a little before the typical ${formatDuration(typicalPee)} mark.`;
} else {
hint.textContent = "Log a few more pees and poos to see typical timings.";
}
}
function renderLasts(events) {
const setLast = (id, type) => {
const ev = lastEventOfType(events, type);
@@ -832,6 +878,7 @@
renderBigClock(events);
renderStats(events);
renderLasts(events);
renderTiming(events);
renderSleepWindows(events);
renderWakeWindows(events);
renderWeekly(events);
@@ -1169,6 +1216,7 @@
renderBigClock(evs);
renderStats(evs);
renderLasts(evs);
renderTiming(evs);
renderSleepWindows(evs);
renderWakeWindows(evs);
renderWeekly(evs);