- Feiertage: isWerktag berücksichtigt jetzt die 9 bundesweiten gesetzlichen Feiertage (Oster-Computus + feste Tage) → ein Feiertag bricht die Streak nicht mehr (zählt wie ein Wochenende neutral). Landesspezifische Feiertage bewusst (noch) nicht enthalten. - Wochenend-Edge: Reflexion an Sa/So setzte die angezeigte Streak auf 0 (Schleife brach am Nicht-Werktag ab). Jetzt wird übersprungen statt gebrochen. - Lookback von 120 auf 400 Tage erhöht, damit lange Streaks nicht abgeschnitten werden. - Streak-Zähllogik in reine, getestete countStreakDays() ausgelagert (8 Streak- + 5 Feiertags-Tests). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
48 lines
1.5 KiB
TypeScript
48 lines
1.5 KiB
TypeScript
import { isWerktag, previousWerktag } from './werktag.js';
|
|
|
|
/**
|
|
* Zählt aufeinanderfolgende Werktage (Mo-Fr, ohne Feiertage) mit voller
|
|
* Reflexion, rückwärts ab `today`.
|
|
*
|
|
* Regeln:
|
|
* - Nur Tage in `fullDates` (status = 'full') zählen.
|
|
* - Tage in `absenceDates` (Urlaub/Krank/…) sind neutral: überspringen, nicht
|
|
* zählen, nicht brechen.
|
|
* - Wochenenden und Feiertage sind keine Werktage → übersprungen.
|
|
* - Heute ist Schonfrist: ist heute noch nicht voll, wird ab dem vorherigen
|
|
* Werktag gezählt (die laufende Streak bleibt über den Tag erhalten).
|
|
* - Bricht beim ersten Werktag, der weder voll noch Abwesenheit ist.
|
|
*/
|
|
export function countStreakDays(opts: {
|
|
today: string;
|
|
fullDates: Set<string>;
|
|
absenceDates: Set<string>;
|
|
}): number {
|
|
const { today, fullDates, absenceDates } = opts;
|
|
let cursor = today;
|
|
let streak = 0;
|
|
|
|
// Heute noch nicht reflektiert → ab vorherigem Werktag zählen.
|
|
if (!fullDates.has(cursor)) cursor = previousWerktag(today);
|
|
|
|
while (true) {
|
|
// Nicht-Werktag (z. B. an einem Wochenende/Feiertag reflektiert) überspringen,
|
|
// statt die Streak fälschlich abzubrechen.
|
|
if (!isWerktag(cursor)) {
|
|
cursor = previousWerktag(cursor);
|
|
continue;
|
|
}
|
|
if (absenceDates.has(cursor)) {
|
|
cursor = previousWerktag(cursor);
|
|
continue;
|
|
}
|
|
if (fullDates.has(cursor)) {
|
|
streak++;
|
|
cursor = previousWerktag(cursor);
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
return streak;
|
|
}
|