Not Exported
Array of tracks with skip event data
Array of detected immediate skip patterns meeting confidence thresholds
// Detect immediate skip patterns from skip data
const skipData = await getSkippedTracks();
const immediatePatterns = detectImmediateSkipPatterns(skipData);
// Example result:
// {
// type: "immediate_skip",
// confidence: 0.82,
// description: "Immediately skips tracks by Artist X",
// details: { avgSkipProgress: 0.05, trackCount: 8, ... }
// }
function detectImmediateSkipPatterns(
skippedTracks: SkippedTrack[],
): DetectedPattern[] {
const patterns: DetectedPattern[] = [];
// Find tracks that are almost always skipped immediately
const immediateSkipArtists: Record<
string,
{
artist: string;
count: number;
tracks: string[];
avgProgress: number;
}
> = {};
skippedTracks.forEach((track) => {
if (!track.skipEvents || track.skipEvents.length === 0) return;
// Calculate average progress percentage for this track's skips
const avgProgress =
track.skipEvents.reduce((sum, event) => {
// Explicitly cast progress to number, defaulting to 0 if undefined
const progress =
typeof event.progress === "number" ? event.progress : 0;
return sum + progress;
}, 0) / track.skipEvents.length;
// Check if it's an immediate skip
if (avgProgress <= PATTERN_THRESHOLDS.IMMEDIATE_SKIP_THRESHOLD) {
// Track by artist
if (!immediateSkipArtists[track.artist]) {
immediateSkipArtists[track.artist] = {
artist: track.artist,
count: 0,
tracks: [],
avgProgress: 0,
};
}
immediateSkipArtists[track.artist].count += track.skipEvents.length;
immediateSkipArtists[track.artist].tracks.push(track.name);
immediateSkipArtists[track.artist].avgProgress =
(immediateSkipArtists[track.artist].avgProgress + avgProgress) / 2;
}
});
// Filter for artists with significant immediate skips
Object.values(immediateSkipArtists).forEach((artistData) => {
if (
artistData.count >= PATTERN_THRESHOLDS.MIN_OCCURRENCES &&
artistData.tracks.length >= 2
) {
const confidence = calculateConfidence(
1 - artistData.avgProgress, // Higher confidence for lower progress
artistData.tracks.length,
artistData.count,
);
if (confidence >= PATTERN_THRESHOLDS.CONFIDENCE_THRESHOLD) {
patterns.push({
type: PatternType.IMMEDIATE_SKIP,
confidence,
description: `Immediately skips tracks by ${artistData.artist}`,
occurrences: artistData.count,
relatedItems: [artistData.artist, ...artistData.tracks.slice(0, 3)],
details: {
artist: artistData.artist,
trackCount: artistData.tracks.length,
avgSkipProgress: artistData.avgProgress,
affectedTracks: artistData.tracks,
},
firstDetected: new Date().toISOString(),
lastDetected: new Date().toISOString(),
});
}
}
});
return patterns;
}
Detects patterns where users consistently skip tracks very early in playback
Analyzes skip events to identify when tracks are habitually skipped during the initial portion of playback. This reveals potential immediate aversion patterns, particularly when grouped by artist or other attributes.
The algorithm focuses on:
Immediate skip patterns are valuable for: