sunrise-sunset: Streak Counting is Hard

This commit is contained in:
Thomas 2023-01-31 22:47:45 +00:00
parent 801bb6586a
commit f7235b26cb
2 changed files with 57 additions and 21 deletions

View file

@ -27,7 +27,7 @@ describe('SunriseSunsetStreakCalculator', () => {
expect(currentStreakLength).toBe(1);
});
it(`should return a two day stream if it's the most recent`, () => {
it(`should return a two day streak if it's the most recent`, () => {
// GIVEN
const correctDays = ['2023-01-29', '2023-01-28', '2023-01-26', '2023-01-25', '2023-01-24'];
const today = '2023-01-29';
@ -51,6 +51,17 @@ describe('SunriseSunsetStreakCalculator', () => {
expect(currentStreakLength).toBe(1);
});
it(`should recognise a one-day streak with gaps`, () => {
// GIVEN
const correctDays = ['2023-01-26', '2023-01-27', '2023-01-31'];
// WHEN
const currentStreakLength = new SunriseSunsetStreakCalculator('2023-01-31').getStreakLength(correctDays);
// THEN
expect(currentStreakLength).toBe(1);
});
it(`should recognise a two day streak`, () => {
// GIVEN
const correctDays = ['2023-01-28', '2023-01-27'];
@ -135,15 +146,15 @@ describe('SunriseSunsetStreakCalculator', () => {
it(`should get a fully shareable streak`, () => {
// GIVEN
const correctDays = ['2023-01-10', '2023-01-11', '2023-01-15', '2023-01-16'];
const incorrectDays = ['2023-01-12', '2023-01-13'];
const today = new Date('2023-01-20T21:52Z');
const correctDays = ['2023-01-26', '2023-01-27', '2023-01-31'];
const incorrectDays = ['2023-01-28'];
const today = new Date('2023-01-31T21:52Z');
// WHEN
const shareableStatement = calculator.getShareableStatement(correctDays, incorrectDays, today);
// THEN
const expected = `Sunrise, Sunset?\n2023-01-20\n🌞🌞🥷🌚🌚🌞🌞\nCurrent Streak: 2\nLongest Streak: 2`;
const expected = `Sunrise, Sunset?\n2023-01-31\n🌞🥷🥷🌚🌞🌞\nCurrent Streak: 1\nLongest Streak: 2`;
expect(shareableStatement).toStrictEqual(expected);
});
});

View file

@ -78,31 +78,53 @@ class SunriseSunsetDayGuessSet {
}
class SunriseSunsetStreak {
private readonly longestStreak: number;
readonly longestStreak: number;
private readonly allStreaks: number[];
readonly mostRecentStreak: number;
constructor(correctDays: Date[]) {
// A (reverse-order) list of streaks in the lis tof correct days.
const sortedDays = correctDays.sort((a, b) => b.getTime() - a.getTime());
const allStreaks: number[] = sortedDays.reduce((streaks: number[], day, index, days) => {
const currentStreakLength = streaks[0] ?? 1;
const daysBetween = differenceInCalendarDays(day, days[index + 1]);
if (daysBetween === 1) {
// The streak continues ! Add a day.
streaks[0] = currentStreakLength + 1;
} else {
// We've hit a gap, so start a new streak
streaks.unshift(1);
if (correctDays.length === 0) {
this.longestStreak = 0;
this.mostRecentStreak = 0;
this.allStreaks = [];
return;
}
// A (reverse-order) list of streaks in the lis tof correct days.
const sortedDays = correctDays.sort((a, b) => b.getTime() - a.getTime());
const allStreaks: number[] = sortedDays.reduce(
(streaks: number[], day, index, days) => {
const currentStreakLength = streaks.at(-1);
const daysBetween = differenceInCalendarDays(day, days.at(index + 1));
console.log(
streaks,
`Day ${index}: ${formatDate(
day,
'yyyy-MM-dd'
)}, streak length: ${currentStreakLength}, days between: ${daysBetween}`
);
if (isNaN(daysBetween)) {
// We're on the last day, so just return the streaks
return streaks;
}, []);
} else if (daysBetween === 1) {
// Add one to the last item in the streaks array
return [...streaks.slice(0, -1), currentStreakLength + 1];
} else {
// We've hit a gap, so start a new streak
return [...streaks, 1];
}
},
[1]
);
// The streaks are in reverse order, so the most recent streak is the last one.
this.mostRecentStreak = allStreaks[allStreaks.length - 1] ?? 0;
this.longestStreak = Math.max(...allStreaks);
console.log('allStreaks', allStreaks);
this.mostRecentStreak = allStreaks[0] ?? 0;
this.longestStreak = allStreaks.length > 0 ? Math.max(...allStreaks) : 0;
this.allStreaks = allStreaks;
}
}
@ -139,11 +161,14 @@ export class SunriseSunsetStreakCalculator {
todayFormatted,
emoji,
`Current Streak: ${streak.mostRecentStreak}`,
`Longest Streak: ${streak.mostRecentStreak}`,
`Longest Streak: ${streak.longestStreak}`,
].join(joiningString);
}
getStreakLength(correctDays: string[]): number {
console.log(`getStreakLength`);
console.log(correctDays);
if (correctDays.length === 0) {
console.log(`No correct days, returning 0.`);
return 0;