sunrise-sunset: Streak Counting is Hard
This commit is contained in:
parent
801bb6586a
commit
f7235b26cb
2 changed files with 57 additions and 21 deletions
|
|
@ -27,7 +27,7 @@ describe('SunriseSunsetStreakCalculator', () => {
|
||||||
expect(currentStreakLength).toBe(1);
|
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
|
// GIVEN
|
||||||
const correctDays = ['2023-01-29', '2023-01-28', '2023-01-26', '2023-01-25', '2023-01-24'];
|
const correctDays = ['2023-01-29', '2023-01-28', '2023-01-26', '2023-01-25', '2023-01-24'];
|
||||||
const today = '2023-01-29';
|
const today = '2023-01-29';
|
||||||
|
|
@ -51,6 +51,17 @@ describe('SunriseSunsetStreakCalculator', () => {
|
||||||
expect(currentStreakLength).toBe(1);
|
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`, () => {
|
it(`should recognise a two day streak`, () => {
|
||||||
// GIVEN
|
// GIVEN
|
||||||
const correctDays = ['2023-01-28', '2023-01-27'];
|
const correctDays = ['2023-01-28', '2023-01-27'];
|
||||||
|
|
@ -135,15 +146,15 @@ describe('SunriseSunsetStreakCalculator', () => {
|
||||||
|
|
||||||
it(`should get a fully shareable streak`, () => {
|
it(`should get a fully shareable streak`, () => {
|
||||||
// GIVEN
|
// GIVEN
|
||||||
const correctDays = ['2023-01-10', '2023-01-11', '2023-01-15', '2023-01-16'];
|
const correctDays = ['2023-01-26', '2023-01-27', '2023-01-31'];
|
||||||
const incorrectDays = ['2023-01-12', '2023-01-13'];
|
const incorrectDays = ['2023-01-28'];
|
||||||
const today = new Date('2023-01-20T21:52Z');
|
const today = new Date('2023-01-31T21:52Z');
|
||||||
|
|
||||||
// WHEN
|
// WHEN
|
||||||
const shareableStatement = calculator.getShareableStatement(correctDays, incorrectDays, today);
|
const shareableStatement = calculator.getShareableStatement(correctDays, incorrectDays, today);
|
||||||
|
|
||||||
// THEN
|
// 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);
|
expect(shareableStatement).toStrictEqual(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -78,31 +78,53 @@ class SunriseSunsetDayGuessSet {
|
||||||
}
|
}
|
||||||
|
|
||||||
class SunriseSunsetStreak {
|
class SunriseSunsetStreak {
|
||||||
private readonly longestStreak: number;
|
readonly longestStreak: number;
|
||||||
private readonly allStreaks: number[];
|
private readonly allStreaks: number[];
|
||||||
readonly mostRecentStreak: number;
|
readonly mostRecentStreak: number;
|
||||||
|
|
||||||
constructor(correctDays: Date[]) {
|
constructor(correctDays: Date[]) {
|
||||||
|
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.
|
// A (reverse-order) list of streaks in the lis tof correct days.
|
||||||
const sortedDays = correctDays.sort((a, b) => b.getTime() - a.getTime());
|
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) {
|
const allStreaks: number[] = sortedDays.reduce(
|
||||||
// The streak continues ! Add a day.
|
(streaks: number[], day, index, days) => {
|
||||||
streaks[0] = currentStreakLength + 1;
|
const currentStreakLength = streaks.at(-1);
|
||||||
} else {
|
|
||||||
// We've hit a gap, so start a new streak
|
|
||||||
streaks.unshift(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return streaks;
|
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.
|
// The streaks are in reverse order, so the most recent streak is the last one.
|
||||||
this.mostRecentStreak = allStreaks[allStreaks.length - 1] ?? 0;
|
console.log('allStreaks', allStreaks);
|
||||||
this.longestStreak = Math.max(...allStreaks);
|
this.mostRecentStreak = allStreaks[0] ?? 0;
|
||||||
|
this.longestStreak = allStreaks.length > 0 ? Math.max(...allStreaks) : 0;
|
||||||
this.allStreaks = allStreaks;
|
this.allStreaks = allStreaks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -139,11 +161,14 @@ export class SunriseSunsetStreakCalculator {
|
||||||
todayFormatted,
|
todayFormatted,
|
||||||
emoji,
|
emoji,
|
||||||
`Current Streak: ${streak.mostRecentStreak}`,
|
`Current Streak: ${streak.mostRecentStreak}`,
|
||||||
`Longest Streak: ${streak.mostRecentStreak}`,
|
`Longest Streak: ${streak.longestStreak}`,
|
||||||
].join(joiningString);
|
].join(joiningString);
|
||||||
}
|
}
|
||||||
|
|
||||||
getStreakLength(correctDays: string[]): number {
|
getStreakLength(correctDays: string[]): number {
|
||||||
|
console.log(`getStreakLength`);
|
||||||
|
console.log(correctDays);
|
||||||
|
|
||||||
if (correctDays.length === 0) {
|
if (correctDays.length === 0) {
|
||||||
console.log(`No correct days, returning 0.`);
|
console.log(`No correct days, returning 0.`);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue