• Determines if a track change is likely a manual skip or automatic

    Analyzes playback state transitions to determine if a track change was likely triggered manually by the user or automatically by the system. This distinction is important for understanding user intent versus normal playback progression.

    The algorithm considers factors like:

    • Changes in playback state (playing/paused)
    • Progress at time of change
    • Timing between tracks
    • Context of playback (playlist, album, etc.)

    Parameters

    • state: PlaybackState

      Current playback state after track change

    • previousState: PlaybackState

      Previous playback state before track change

    Returns { isManual: boolean; confidence: number; reason: string }

    Object containing the analysis results:

    • isManual: Whether the skip appears to be manual
    • confidence: Confidence level in the determination (0.0-1.0)
    • reason: Human-readable explanation of the determination
    // Determine if a skip was manual or automatic
    const manualAnalysis = detectManualVsAutoSkip(currentState, previousState);

    console.log(
    `Skip was ${manualAnalysis.isManual ? 'manual' : 'automatic'} ` +
    `(${manualAnalysis.confidence.toFixed(2)} confidence): ${manualAnalysis.reason}`
    );
    export function detectManualVsAutoSkip(
    state: PlaybackState,
    previousState: PlaybackState,
    ): {
    isManual: boolean;
    confidence: number;
    reason: string;
    } {
    // Default to manual with medium confidence
    const result = {
    isManual: true,
    confidence: 0.6,
    reason: "Default to manual assumption",
    };

    // If playback is stopped after track change, likely manual
    if (!state.isPlaying && previousState.isPlaying) {
    return {
    isManual: true,
    confidence: 0.9,
    reason: "Playback stopped after track change, likely manual",
    };
    }

    // If progress was almost at end, likely automatic
    if (previousState.currentTrackDuration && previousState.lastProgress) {
    const progressPercent =
    previousState.lastProgress / previousState.currentTrackDuration;

    if (progressPercent > 0.98) {
    return {
    isManual: false,
    confidence: 0.95,
    reason: "Track completed normally, automatic progression",
    };
    }
    }

    // Check for rapid skip pattern which indicates manual skipping
    if (consecutiveQuickSkips >= AGGRESSIVE_SKIP_PATTERN_THRESHOLD) {
    return {
    isManual: true,
    confidence: 0.95,
    reason: `Part of rapid skip pattern (${consecutiveQuickSkips} consecutive)`,
    };
    }

    // Return the default if no other condition met
    return result;
    }