mtgbrr - Monkeytype Speeder 2025

just press slash and start typing.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name mtgbrr - Monkeytype Speeder 2025
// @author natsukitheslashuser 
// @description just press slash and start typing.
// @icon https://i.imgur.com/fUjylt3.png
// @version 42.01
// @match *://monkeytype.com/*
// @run-at document-start
// @grant none
// @license idk
// @namespace natsuki
// ==/UserScript==
/* jshint esversion:6 */

(function() {
    "use strict";

    // Configuration
    const MIN_DELAY = 0;
    const MAX_DELAY = 0;
    const TOGGLE_KEY = "Slash";
    const MISTAKES_PER_MINUTE = 5; // Target mistakes per minute
    const STOP_DELAY = 1; // Ultra-fast 1ms stop delay
    const log = console.log;

    // State variables
    let toggle = false;
    let typingTimeout = null;
    let stopCheckInterval = null;
    let lastKeyPressTime = 0;
    let realKeypressCount = 0;
    let autoKeypressCount = 0;
    let mistakeCount = 0;
    let startTime = 0;
    let isTyping = false;

    function random(min, max) {
        return Math.floor(Math.random() * (max - min + 1) + min);
    }

    function canType() {
        const typingTest = document.getElementById("typingTest");
        if (!typingTest) return false;
        
        const isHidden = typingTest.classList.contains("hidden");
        if (isHidden) toggle = false;
        
        // Only allow typing if toggle is on, test is visible AND we're in active typing state
        return toggle && !isHidden && isTyping;
    }

    function getNextCharacter() {
        const currentWord = document.querySelector(".word.active");
        if (!currentWord) return "";
        
        for (const letter of currentWord.children) {
            if (letter.className === "") return letter.textContent;
        }
        return " ";
    }

    function shouldMakeMistake() {
        // Calculate dynamic mistake chance based on elapsed time to meet target mistakes per minute
        const elapsedSeconds = (Date.now() - startTime) / 1000;
        const elapsedMinutes = elapsedSeconds / 60;
        const targetMistakes = elapsedMinutes * MISTAKES_PER_MINUTE;
        
        // If we've made fewer mistakes than target, increase the chance
        if (mistakeCount < targetMistakes) {
            const remainingTime = 60 - (elapsedSeconds % 60);
            const remainingMistakes = Math.ceil(MISTAKES_PER_MINUTE - mistakeCount % MISTAKES_PER_MINUTE);
            
            // Higher chance as we approach the end of the minute with fewer mistakes
            return Math.random() < (remainingMistakes / (remainingTime * 2));
        }
        
        return false;
    }
    
    function getRandomWrongCharacter(correctChar) {
        const nearbyKeys = {
            'a': ['s', 'q', 'z', 'w'],
            'b': ['v', 'n', 'g', 'h'],
            'c': ['x', 'v', 'd', 'f'],
            'd': ['s', 'f', 'e', 'r'],
            'e': ['w', 'r', 'd', 'f'],
            'f': ['d', 'g', 'r', 't'],
            'g': ['f', 'h', 't', 'y'],
            'h': ['g', 'j', 'y', 'u'],
            'i': ['u', 'o', 'k', 'l'],
            'j': ['h', 'k', 'u', 'i'],
            'k': ['j', 'l', 'i', 'o'],
            'l': ['k', ';', 'o', 'p'],
            'm': ['n', ',', 'j', 'k'],
            'n': ['b', 'm', 'h', 'j'],
            'o': ['i', 'p', 'k', 'l'],
            'p': ['o', '[', 'l', ';'],
            'q': ['w', 'a', '1', '2'],
            'r': ['e', 't', 'd', 'f'],
            's': ['a', 'd', 'w', 'e'],
            't': ['r', 'y', 'f', 'g'],
            'u': ['y', 'i', 'h', 'j'],
            'v': ['c', 'b', 'f', 'g'],
            'w': ['q', 'e', 'a', 's'],
            'x': ['z', 'c', 's', 'd'],
            'y': ['t', 'u', 'g', 'h'],
            'z': ['a', 'x', 's', 'd'],
            ' ': ['n', 'm', 'b', 'v']
        };
        
        if (correctChar in nearbyKeys) {
            const possibleMistakes = nearbyKeys[correctChar];
            return possibleMistakes[Math.floor(Math.random() * possibleMistakes.length)];
        }
        
        // Fallback for characters not in the map
        return String.fromCharCode(correctChar.charCodeAt(0) + (Math.random() > 0.5 ? 1 : -1));
    }

    const InputEvents = {};
    function pressKey(key) {
        const wordsInput = document.getElementById("wordsInput");
        if (!wordsInput) return;
        
        const KeyboardEvent = Object.assign({}, DEFAULT_INPUT_OPTIONS, { target: wordsInput, data: key });
        const InputEvent = Object.assign({}, DEFAULT_KEY_OPTIONS, { target: wordsInput, key: key });

        wordsInput.value += key;
        
        if (InputEvents.beforeinput) InputEvents.beforeinput(InputEvent);
        if (InputEvents.input) InputEvents.input(InputEvent);
        if (InputEvents.keyup) InputEvents.keyup(KeyboardEvent);
        
        autoKeypressCount++;
        
        // Log status occasionally
        if (autoKeypressCount % 10 === 0) {
            log(`Auto: ${autoKeypressCount}, Real: ${realKeypressCount}, Mistakes: ${mistakeCount}`);
        }
    }

    // Ultra-fast continuous stop check
    function setupStopCheck() {
        if (stopCheckInterval) {
            clearInterval(stopCheckInterval);
        }
        
        // Check every 1ms if we should be typing
        stopCheckInterval = setInterval(() => {
            const now = Date.now();
            const idleTime = now - lastKeyPressTime;
            
            // If we haven't had a keypress in STOP_DELAY ms, immediately stop typing
            if (idleTime > STOP_DELAY && isTyping) {
                isTyping = false;
                
                // Clear typing timeout to stop immediately
                if (typingTimeout) {
                    clearTimeout(typingTimeout);
                    typingTimeout = null;
                }
            }
        }, 1); // Check every 1ms for optimal responsiveness
    }

    function typeCharacter() {
        // Clear any existing timeout
        if (typingTimeout) {
            clearTimeout(typingTimeout);
            typingTimeout = null;
        }
        
        // Check if we can type
        if (!canType()) {
            return; // Don't schedule another character if conditions aren't met
        }

        // Get the correct next character
        const nextChar = getNextCharacter();
        
        if (nextChar) {
            // Decide if we should make a mistake
            if (shouldMakeMistake()) {
                const wrongChar = getRandomWrongCharacter(nextChar);
                pressKey(wrongChar);
                mistakeCount++;
                log(`Made mistake: typed '${wrongChar}' instead of '${nextChar}'. Total mistakes: ${mistakeCount}`);
            } else {
                pressKey(nextChar);
            }
            
            // Schedule the next character if still active
            if (canType()) {
                typingTimeout = setTimeout(typeCharacter, random(MIN_DELAY, MAX_DELAY));
            }
        }
    }

    // Handle keydown events
    window.addEventListener("keydown", function(event) {
        if (event.code === TOGGLE_KEY) {
            event.preventDefault();
            if (event.repeat) return;
            
            toggle = !toggle;
            if (toggle) {
                // Reset counters and timers when starting
                realKeypressCount = 0;
                autoKeypressCount = 0;
                mistakeCount = 0;
                startTime = Date.now();
                log("TYPING BOT ENABLED - Press keys to activate typing");
                
                // Set up the ultra-fast stop check interval
                setupStopCheck();
            } else {
                log("TYPING BOT DISABLED");
                
                // Clear all timers
                if (typingTimeout) {
                    clearTimeout(typingTimeout);
                    typingTimeout = null;
                }
                
                if (stopCheckInterval) {
                    clearInterval(stopCheckInterval);
                    stopCheckInterval = null;
                }
                
                isTyping = false;
            }
        } else if (toggle) {
            // Count real keypresses for regular keys
            if (!["Control", "Alt", "Shift", "Meta", "CapsLock", "Tab", "Escape"].includes(event.key)) {
                realKeypressCount++;
                
                // Update the last key press time to keep typing active
                lastKeyPressTime = Date.now();
                
                // Set typing state to active
                isTyping = true;
                
                // Start typing if not already typing
                if (!typingTimeout) {
                    typeCharacter();
                }
                
                // Prevent the keypress from affecting the typing
                event.preventDefault();
            }
        }
    }, true);

    // Clean up when page unloads
    window.addEventListener("beforeunload", function() {
        if (typingTimeout) clearTimeout(typingTimeout);
        if (stopCheckInterval) clearInterval(stopCheckInterval);
    });

    // Intercept event listeners
    function hook(element) {
        element.addEventListener = new Proxy(element.addEventListener, {
            apply(target, _this, args) {
                const [type, listener, ...options] = args;
                if (_this.id === "wordsInput") {
                    InputEvents[type] = listener;
                }
                return target.apply(_this, args);
            }
        });
    }
    hook(HTMLInputElement.prototype);

    const DEFAULT_KEY_OPTIONS = {
        key: "", code: "", keyCode: 0, which: 0, isTrusted: true, altKey: false,
        bubbles: true, cancelBubble: false, cancelable: true, charCode: 0,
        composed: true, ctrlKey: false, currentTarget: null, defaultPrevented: false,
        detail: 0, eventPhase: 0, isComposing: false, location: 0, metaKey: false,
        path: null, repeat: false, returnValue: true, shiftKey: false, srcElement: null,
        target: null, timeStamp: Date.now(), type: "", view: window,
    };

    const DEFAULT_INPUT_OPTIONS = {
        isTrusted: true, bubbles: true, cancelBubble: false, cancelable: false,
        composed: true, data: "", dataTransfer: null, defaultPrevented: false,
        detail: 0, eventPhase: 0, inputType: "insertText", isComposing: false,
        path: null, returnValue: true, sourceCapabilities: null, srcElement: null,
        target: null, currentTarget: null, timeStamp: Date.now(), type: "input",
        view: null, which: 0
    };
    
    log("MonkeyType Script loaded - Press / to toggle, then type to activate");
})();