Not Exported
Object containing hourly and daily skip distribution data
Array of detected time-based patterns that meet confidence thresholds
// Detecting time-of-day skip patterns
const timeData = await analyzeTimeBasedPatterns();
const timePatterns = detectTimeOfDayPatterns(timeData);
// Sample result patterns:
// [
// { type: "time_of_day", description: "Tends to skip more tracks during 8AM, 5PM", ... },
// { type: "time_of_day", description: "Skips more tracks on Monday", ... }
// ]
function detectTimeOfDayPatterns(
timePatterns: TimePatterns,
): DetectedPattern[] {
const patterns: DetectedPattern[] = [];
// Check if there are significant peak hours
if (timePatterns.peakSkipHours && timePatterns.peakSkipHours.length > 0) {
// Format hours in a readable way
const formatHour = (hour: number) => {
const amPm = hour >= 12 ? "PM" : "AM";
const hourFormatted = hour % 12 === 0 ? 12 : hour % 12;
return `${hourFormatted}${amPm}`;
};
const peakHoursFormatted = timePatterns.peakSkipHours
.map((hour) => formatHour(hour))
.join(", ");
// Calculate the average skip count and determine how much above average the peaks are
const avgSkips =
timePatterns.hourlyDistribution.reduce((sum, count) => sum + count, 0) /
24;
const peakSkipsAvg =
timePatterns.peakSkipHours.reduce(
(sum, hour) => sum + (timePatterns.hourlyDistribution[hour] || 0),
0,
) / timePatterns.peakSkipHours.length;
const peakFactor = peakSkipsAvg / avgSkips;
const confidence = Math.min(0.9, peakFactor / 2); // Cap at 0.9
if (confidence >= PATTERN_THRESHOLDS.CONFIDENCE_THRESHOLD) {
patterns.push({
type: PatternType.TIME_OF_DAY,
confidence,
description: `Tends to skip more tracks during ${peakHoursFormatted}`,
occurrences: timePatterns.peakSkipHours.reduce(
(sum, hour) => sum + (timePatterns.hourlyDistribution[hour] || 0),
0,
),
relatedItems: timePatterns.peakSkipHours.map((h) => formatHour(h)),
details: {
peakHours: timePatterns.peakSkipHours,
peakFactor,
hourlyDistribution: timePatterns.hourlyDistribution,
},
firstDetected: new Date().toISOString(),
lastDetected: new Date().toISOString(),
});
}
}
// Check if there's a strong day-of-week pattern
// Use dayOfWeekDistribution or dayDistribution, whichever is available
const dayDistribution =
timePatterns.dayOfWeekDistribution || timePatterns.dayDistribution;
if (dayDistribution && dayDistribution.length > 0) {
const dayNames = [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
];
const avgDaySkips =
dayDistribution.reduce((sum, count) => sum + count, 0) / 7;
dayDistribution.forEach((count, day) => {
if (
count > avgDaySkips * PATTERN_THRESHOLDS.TIME_FACTOR_THRESHOLD &&
count >= PATTERN_THRESHOLDS.MIN_OCCURRENCES
) {
const dayFactor = count / avgDaySkips;
const confidence = Math.min(0.9, dayFactor / 2);
if (confidence >= PATTERN_THRESHOLDS.CONFIDENCE_THRESHOLD) {
patterns.push({
type: PatternType.TIME_OF_DAY,
confidence,
description: `Skips more tracks on ${dayNames[day]}`,
occurrences: count,
relatedItems: [dayNames[day]],
details: {
day,
dayName: dayNames[day],
dayFactor,
dayDistribution: dayDistribution,
},
firstDetected: new Date().toISOString(),
lastDetected: new Date().toISOString(),
});
}
}
});
}
return patterns;
}
Detects patterns related to skip behavior at specific times of day or days of week
Analyzes temporal distribution of skips to identify periods when users are more likely to skip tracks. This detection algorithm recognizes both:
The algorithm performs several analytical steps:
Time patterns can reveal insights about: