Period day toggle, flow strength on calendar, end dates for past periods
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
94372c6abc
commit
ce66b857db
6 changed files with 149 additions and 55 deletions
|
|
@ -5,6 +5,9 @@
|
|||
})(typeof window === "undefined" ? globalThis : window, () => {
|
||||
const MS_PER_DAY = 86400000;
|
||||
const PERIOD_FLOWS = new Set(["period", "light", "medium", "heavy"]);
|
||||
// "period" is a period day without a strength, so it has no level.
|
||||
const FLOW_LEVELS = { light: 1, medium: 2, heavy: 3 };
|
||||
const LEVEL_NAMES = [null, "light", "medium", "heavy"];
|
||||
const DEFAULT_CYCLE = 28;
|
||||
const DEFAULT_PERIOD = 5;
|
||||
// Days from ovulation to the next period. Fairly constant between people,
|
||||
|
|
@ -66,6 +69,23 @@
|
|||
return { mean, sd: Math.sqrt(variance) };
|
||||
}
|
||||
|
||||
// Typical strength on each day of a period (index 0 = first day), averaged
|
||||
// over recent periods. Days nobody rated stay null.
|
||||
function flowProfile(days, periodList, recent = 6) {
|
||||
const sums = [];
|
||||
const counts = [];
|
||||
for (const period of periodList.slice(-recent)) {
|
||||
for (let index = 0; index < period.length; index += 1) {
|
||||
const entry = days[toIso(period.start + index)];
|
||||
const level = entry && FLOW_LEVELS[entry.flow];
|
||||
if (!level) continue;
|
||||
sums[index] = (sums[index] || 0) + level;
|
||||
counts[index] = (counts[index] || 0) + 1;
|
||||
}
|
||||
}
|
||||
return Array.from({ length: sums.length }, (_, index) => (counts[index] ? Math.round(sums[index] / counts[index]) : null));
|
||||
}
|
||||
|
||||
function fertileWindow(nextStart, previousEnd) {
|
||||
const ovulation = nextStart - LUTEAL_DAYS;
|
||||
if (ovulation <= previousEnd) return null;
|
||||
|
|
@ -86,10 +106,12 @@
|
|||
cycleLength: DEFAULT_CYCLE,
|
||||
cycleSpread: null,
|
||||
periodLength: DEFAULT_PERIOD,
|
||||
periodSamples: 0,
|
||||
current: null,
|
||||
late: 0,
|
||||
predictions: [],
|
||||
fertile: []
|
||||
fertile: [],
|
||||
flowProfile: flowProfile(days, periodList)
|
||||
};
|
||||
if (!periodList.length) return summary;
|
||||
|
||||
|
|
@ -105,6 +127,7 @@
|
|||
if (lengths.length) {
|
||||
const mean = lengths.reduce((sum, value) => sum + value, 0) / lengths.length;
|
||||
summary.periodLength = Math.min(10, Math.max(2, Math.round(mean)));
|
||||
summary.periodSamples = lengths.length;
|
||||
}
|
||||
|
||||
summary.current = {
|
||||
|
|
@ -139,5 +162,5 @@
|
|||
return summary;
|
||||
}
|
||||
|
||||
return { PERIOD_FLOWS, LUTEAL_DAYS, MIN_CYCLE, MAX_CYCLE, toDay, toIso, periods, cycles, weightedStats, summarize };
|
||||
return { PERIOD_FLOWS, FLOW_LEVELS, LEVEL_NAMES, LUTEAL_DAYS, MIN_CYCLE, MAX_CYCLE, toDay, toIso, periods, cycles, weightedStats, flowProfile, summarize };
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue