• Detects patterns in the user's skip behavior using multi-dimensional analysis

    Coordinates the entire pattern detection process by:

    1. Retrieving necessary data (artist metrics, time patterns, skipped tracks)
    2. Running specialized detection algorithms for different pattern types
    3. Consolidating, filtering, and sorting the detected patterns
    4. Persisting patterns to disk for later analysis and trend detection

    The detection process employs multiple specialized algorithms to identify different types of patterns, including:

    • Artist aversion (consistently skipping specific artists)
    • Time-based patterns (skipping at certain times/days)
    • Immediate skip behaviors (skipping tracks very early)
    • Skip streak detection (consecutive rapid skips)
    • Context-specific behaviors (skipping in specific playlists/albums)

    Each pattern is assigned a confidence score, filtered based on configurable thresholds, and sorted by confidence for presentation.

    Returns Promise<
        | { success: boolean; data: DetectedPattern[]; error?: undefined }
        | { success: boolean; data: never[]; error: string },
    >

    Promise resolving to an object containing:

    • success: Whether the pattern detection completed successfully
    • data: Array of detected patterns meeting confidence thresholds
    • error: Error message if detection failed (only if success is false)
    // Get all detected patterns with confidence scores
    const patterns = await detectSkipPatterns();
    if (patterns.success && patterns.data.length > 0) {
    // Process high-confidence patterns first
    const highConfidencePatterns = patterns.data
    .filter(p => p.confidence > 0.8);

    // Display insights to user
    displayPatternInsights(highConfidencePatterns);
    }
    export async function detectSkipPatterns() {
    try {
    // Get required data
    const artistMetrics = await aggregateArtistSkipMetrics();
    const timePatterns = await analyzeTimeBasedPatterns();
    const skippedTracks = await getSkippedTracks();

    // Check if we have enough skipped tracks for meaningful analysis
    if (!skippedTracks || skippedTracks.length < 10) {
    return {
    success: true,
    data: [],
    };
    }

    const patterns: DetectedPattern[] = [];

    // Detect artist aversion patterns
    const artistAversionPatterns = detectArtistAversionPatterns(artistMetrics);
    patterns.push(...artistAversionPatterns);

    // Detect time of day patterns - check if timePatterns exists first
    if (timePatterns) {
    const timeOfDayPatterns = detectTimeOfDayPatterns(timePatterns);
    patterns.push(...timeOfDayPatterns);
    }

    // Detect immediate skip patterns
    const immediateSkipPatterns = detectImmediateSkipPatterns(skippedTracks);
    patterns.push(...immediateSkipPatterns);

    // Detect skip streak patterns
    const skipStreakPatterns = detectSkipStreakPatterns(skippedTracks);
    patterns.push(...skipStreakPatterns);

    // Detect context-specific patterns
    const contextPatterns = detectContextSpecificPatterns(skippedTracks);
    patterns.push(...contextPatterns);

    // Sort patterns by confidence score
    patterns.sort((a, b) => b.confidence - a.confidence);

    // Only store patterns if we have some
    if (patterns.length > 0) {
    // Store the detected patterns in a JSON file
    const patternsFilePath = join(
    ensureStatisticsDir(),
    "detected_patterns.json",
    );

    writeJsonSync(patternsFilePath, patterns, { spaces: 2 });
    }

    return {
    success: true,
    data: patterns,
    };
    } catch (error) {
    return {
    success: false,
    data: [],
    error: error instanceof Error ? error.message : "Unknown error",
    };
    }
    }