Enhanced Scroll Position Cycler

Cycle through recent scroll positions with enhanced functionality

// ==UserScript==
// @name         Enhanced Scroll Position Cycler
// @namespace    http://tampermonkey.net/
// @license      MIT
// @version      1.0
// @author       Rekt
// @description  Cycle through recent scroll positions with enhanced functionality
// @match        *://*/*
// @grant        none
// ==/UserScript==
(function() {
    'use strict';

    let scrollPositions = [];
    let currentIndex = -1;
    let isSwitching = false;
    let switchStartTime = 0;
    let lastSwitchTime = 0;

    // Timing constants based on human reaction research
    const FAST_SWITCH_THRESHOLD = 180; // Visual reaction threshold[6]
    const POSITION_THRESHOLD = 250;    // Average reaction time[2][7]
    let positionTimer = null;

    function addPositionToList(position) {
        let index = scrollPositions.findIndex(p => Math.abs(p.y - position.y) < 50);
        if (index !== -1) {
            scrollPositions.splice(index, 1);
        }
        scrollPositions.unshift(position);
        if (scrollPositions.length > 10) {
            scrollPositions.pop();
        }
    }

    function recordScrollPosition() {
        clearTimeout(positionTimer);
        positionTimer = setTimeout(() => {
            let position = { y: window.pageYOffset };
            addPositionToList(position);
        }, POSITION_THRESHOLD);
    }

    function scrollToPosition(position) {
        window.scrollTo({
            top: position.y,
            behavior: 'smooth'
        });
    }

    function cycleScrollPositions(event) {
        if (event.altKey && event.key === 'c') {
            event.preventDefault();

            let now = Date.now();
            if (!isSwitching) {
                isSwitching = true;
                switchStartTime = now;
                currentIndex = 0;
            } else {
                currentIndex = (currentIndex + 1) % scrollPositions.length;
            }

            if (now - lastSwitchTime > FAST_SWITCH_THRESHOLD) {
                // Slow switch: only use the last two positions
                let lastTwo = scrollPositions.slice(0, 2);
                currentIndex = currentIndex % 2;
                scrollToPosition(lastTwo[currentIndex]);
            } else {
                // Fast switch: use all positions
                scrollToPosition(scrollPositions[currentIndex]);
            }

            lastSwitchTime = now;
        }
    }

    function endSwitching() {
        if (isSwitching) {
            isSwitching = false;
            let currentPosition = scrollPositions[currentIndex];
            scrollPositions = [currentPosition, ...scrollPositions.filter(p => p !== currentPosition)];
        }
    }

    function registerTopPosition() {
        let topPosition = { y: 0 };
        addPositionToList(topPosition);
    }

    // Register top position on page load
    registerTopPosition();

    window.addEventListener('scroll', recordScrollPosition);
    window.addEventListener('keydown', cycleScrollPositions);
    window.addEventListener('keyup', event => {
        if (event.key === 'Alt') {
            endSwitching();
        }
    });
})();