notification changes
This commit is contained in:
@@ -68,14 +68,89 @@ function msUntilNextMonth() {
|
||||
|
||||
// Callbacks to run on daily reset (e.g. clear firedToday in patternChecker)
|
||||
const dailyResetCallbacks = [];
|
||||
const weeklyResetCallbacks = [];
|
||||
|
||||
function onDailyReset(fn) {
|
||||
dailyResetCallbacks.push(fn);
|
||||
}
|
||||
|
||||
function onWeeklyReset(fn) {
|
||||
weeklyResetCallbacks.push(fn);
|
||||
}
|
||||
|
||||
// --- Threshold firing state ---
|
||||
// key -> Set<thresholdMs> that have fired within the key's window.
|
||||
const firedThresholds = new Map();
|
||||
// key -> window type used for threshold clearing ("today" | "week" | "month")
|
||||
const firedThresholdWindows = new Map();
|
||||
|
||||
function clearFiredThresholdsForWindow(windowType) {
|
||||
for (const [key, mappedWindowType] of firedThresholdWindows.entries()) {
|
||||
if (mappedWindowType === windowType) {
|
||||
firedThresholds.delete(key);
|
||||
firedThresholdWindows.delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function shouldFireThreshold(key, ageMs, thresholdsMs, windowType) {
|
||||
if (!Array.isArray(thresholdsMs) || thresholdsMs.length === 0) return null;
|
||||
if (!['today', 'week', 'month'].includes(windowType)) return null;
|
||||
|
||||
firedThresholdWindows.set(key, windowType);
|
||||
|
||||
const firedForKey = firedThresholds.get(key) || new Set();
|
||||
const sortedThresholds = [...thresholdsMs].sort((a, b) => a - b);
|
||||
|
||||
let highestUnfiredCrossed = null;
|
||||
for (const thresholdMs of sortedThresholds) {
|
||||
if (ageMs >= thresholdMs && !firedForKey.has(thresholdMs)) {
|
||||
highestUnfiredCrossed = thresholdMs;
|
||||
}
|
||||
}
|
||||
|
||||
if (highestUnfiredCrossed === null) return null;
|
||||
|
||||
firedForKey.add(highestUnfiredCrossed);
|
||||
firedThresholds.set(key, firedForKey);
|
||||
return highestUnfiredCrossed;
|
||||
}
|
||||
|
||||
// --- Escalating cooldown state ---
|
||||
// key -> { startedAtMs, lastFireAtMs, fireCount }
|
||||
const escalatingCooldowns = new Map();
|
||||
|
||||
function shouldFireCooldownEscalating(key, thresholdsMs) {
|
||||
if (!Array.isArray(thresholdsMs) || thresholdsMs.length === 0) return null;
|
||||
|
||||
const sortedThresholds = [...thresholdsMs].sort((a, b) => a - b);
|
||||
const now = Date.now();
|
||||
let state = escalatingCooldowns.get(key);
|
||||
|
||||
if (!state) {
|
||||
state = { startedAtMs: now, lastFireAtMs: null, fireCount: 0 };
|
||||
escalatingCooldowns.set(key, state);
|
||||
}
|
||||
|
||||
const nextThreshold = sortedThresholds[state.fireCount];
|
||||
if (typeof nextThreshold !== 'number') return null;
|
||||
|
||||
const referenceMs = state.fireCount === 0 ? state.startedAtMs : state.lastFireAtMs;
|
||||
if ((now - referenceMs) < nextThreshold) return null;
|
||||
|
||||
state.fireCount += 1;
|
||||
state.lastFireAtMs = now;
|
||||
return nextThreshold;
|
||||
}
|
||||
|
||||
function clearEscalating(key) {
|
||||
escalatingCooldowns.delete(key);
|
||||
}
|
||||
|
||||
function scheduleDailyReset() {
|
||||
setTimeout(() => {
|
||||
store.today = new Map();
|
||||
clearFiredThresholdsForWindow('today');
|
||||
for (const fn of dailyResetCallbacks) {
|
||||
try { fn(); } catch (_) {}
|
||||
}
|
||||
@@ -86,6 +161,10 @@ function scheduleDailyReset() {
|
||||
function scheduleWeeklyReset() {
|
||||
setTimeout(() => {
|
||||
store.week = new Map();
|
||||
clearFiredThresholdsForWindow('week');
|
||||
for (const fn of weeklyResetCallbacks) {
|
||||
try { fn(); } catch (_) {}
|
||||
}
|
||||
scheduleWeeklyReset();
|
||||
}, msUntilNextMonday());
|
||||
}
|
||||
@@ -93,6 +172,7 @@ function scheduleWeeklyReset() {
|
||||
function scheduleMonthlyReset() {
|
||||
setTimeout(() => {
|
||||
store.month = new Map();
|
||||
clearFiredThresholdsForWindow('month');
|
||||
scheduleMonthlyReset();
|
||||
}, msUntilNextMonth());
|
||||
}
|
||||
@@ -140,6 +220,11 @@ module.exports = {
|
||||
getAll,
|
||||
scheduleResets,
|
||||
onDailyReset,
|
||||
onWeeklyReset,
|
||||
firedThresholds,
|
||||
shouldFireThreshold,
|
||||
shouldFireCooldownEscalating,
|
||||
clearEscalating,
|
||||
setCooldown,
|
||||
isOnCooldown,
|
||||
updateStaffLastSeen,
|
||||
|
||||
Reference in New Issue
Block a user