您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Show the complexity of the text in the race
// KG_ComplexityPanel // ==UserScript== // @name KG_ComplexityPanel // @version 0.2 // @namespace klavogonki // @author NoNe // @description Show the complexity of the text in the race // @include https://klavogonki.ru/g/* // @include http://klavogonki.ru/g/* // @grant none // ==/UserScript== function embed() { var COMPLEXITY_TEXT = [ "СУПЕР РЕКОРДНЫЙ ТЕКСТ", // < 1 "РЕКОРДНЫЙ ТЕКСТ", // < 2 "очень лёгкий текст", // < 3 "лёгкий текст", // < 4 "нормальный текст", // < 5 "нормальный текст", // < 6 "текст сложней нормального",// < 7 "сложноватый текст", // < 8 "сложный текст", // < 9 "очень сложный текст", // < 10 "очень сложный текст", // < 11 "крайне сложный текст", // < 12 "крайне сложный текст", // < 13 "мега сложный текст", // < 14 "мега сложный текст", // < 15 "текст - жесть", // < 16 "текст - жесть", // < 17 "запредельная сложность" // < 18 ]; // 2 letters combinations for the Russian language, ordered by their frequency. Only the first 791 most common combinations are included. // The rest will get the worst coefficient. var SYLLABLES = "тостнанопонеконираеналроовголипркаосерреотволаолтатьонваореллоеттеомодзавеилриатдеанлеогесдальитактиемасмеойсяныдообскмо" + "инчежесеамазтрмикиависвиедбысоманнимарсьчтслегнурутвбовыдииевсизейивикпеокэтхооеадожчабемушеспаяихияудкрочсидневчиляылкузнсапаты" + "дуульншиутнящежитсеесвыйрыопозекмнидаетуусичглужлуятлсвнийыеымезгабребтныхиражмыжадруюьсснлюпиечгднтбугрииахрярнабжнаюссучачьквл" + "ньумчноиугапывцеплщизвбиепгиешсмашблсуцишазджддвошбактврукицагайртежпуялупклдлвуурытоязолытккенсубещысянушвшдыувцаютишиггуйсшьох" + "хатяехядндчуьшзирьшкющибшлбягеясдьнквзземязыьюзуямзмрврмышиюкндснцухщайнявлнунбнюдркрсьефилкиоецпырдсычкущллржсрдяацзрзгузфоиаюб" + "счргязлжеоксвягнижшнджьяащвтоойтвкзлипдкящощхнуефебщхишовдтлыршувпзяоюсдчьыбьмжуфаршмлпяхрмпквяхнгцоофяецыбсынхвсхеяыкищаивьдцоц" + "якфрйднчьзрхыпычйчауафзбючмсюсяжзкэлпньтбъяюсюрлцущунюхулгеювмдттдеарюнщзьхлуабкмкгкэнчшдпеиыдэкъеыгтчйкммррячрплчъятттпштеуяржк" + "ягжоьцуйэрьбптоупппкоэйшефифрчрбмьсшяяюрхерцлднрызлткцсбдммбчоймбхпьддцвфлфущнжчьгзжнфтмюньчэмьдьицкпсдшйокжуятцйцтюхмсцйлуивввч" + "бвдчяцмряйхсэйдхщьюзаоккрзябыжмгсэтбсфюкбмвхюмнзмчэсмэжьчлбьяпьфлпффрэжбюлдбэдвцнвгчуэвгиулбяилмхтюцдздгшвоаюжьврфсжэвкэнжьодюсг" + "съмцююдъэпрщлздэыягвюшббэфюглвчргсфтаэкззсггшпуфтщйруошмжсззпчмвтхфыюхгтзъааяшбюбдэгуцйеншбжгмлэыцкшйзхэмфнбвщжрфстэлштъпцбшзтжл" + "иэнхйвшрыщьщжжтгкмжгйфтшэхзчтфвънлыивблхсзнэйбйабэлфэшхшьпэзюпкгжмпшбтзцйгчвгэмтйхбзмюйяэбтзфьзюшцюйфюйпкпмъюабцпюхьювкхгбщрхъвэ" + "пэчмзшмзбчууфнцзкдлщчжхгфэыумщгюфгкюгшжюшюбгнъщоцлццфммхюикъкбцнпбнмцмйикьнплъюепфъюдфлрьхцсмшкчххюфьркфжтмдвжзэцрхкфчгхсщюэшсцд" + "ччхчгпфбеэхдшээямжжэяугзшхвюйщфяжцээйюгфпвхпэожвчэтжцп"; // Complexity weight for each character. Russian letters and special characters use different formulas, so even if you // see the same weights for some Russian letter and some special character, they will contribute different final weights. var CHAR_WEIGHTS = { "а": 105, "б": 142, "в": 119, "г": 140, "д": 125, "е": 105, "ж": 153, "з": 142, "и": 107, "й": 150, "к": 122, "л": 117, "м": 122, "н": 108, "о": 100, "п": 126, "р": 118, "с": 115, "т": 110, "у": 127, "ф": 155, "х": 157, "ц": 175, "ч": 145, "ш": 160, "щ": 180, "ъ": 200, "ы": 140, "ь": 137, "э": 183, "ю": 167, "я": 135, "\n": 0.3, " ": 0.3, ".": 2.0, ",": 2.5, "!": 4.0, "?": 3.0, ":": 4.0, ";": 4.5, "\"": 7.0, "«": 5.0, "»": 5.0, "'": 9.0, "_": 8.0, "%": 8.0, "—": 5.0, "–": 5.0, "-": 5.0, "(": 5.0, ")": 5.0, "*": 7.0, "=": 7.0, "+": 7.0, "№": 5.0, "#": 9.0, "$": 9.0, "&": 9.0, "/": 9.0, "\\": 10.0, "|": 10.0, "<": 11.0, ">": 11.0, "@": 11.0, "[": 11.0, "]": 11.0, "^": 11.0, "~": 11.0, "`": 11.0, "{": 11.0, "}": 11.0, "0": 5.0, "1": 5.0, "2": 5.0, "3": 5.0, "4": 5.0, "5": 5.0, "6": 5.0, "7": 5.0, "8": 5.0, "9": 5.0 }; // Spectrum canvas settings var CANVAS_HEIGHT = 12; var CANVAS_OPACITY = 0.65; // This is the upper threshold for the spectrum complexity. Everything up will be pure red. var MAX_SPECTRUM_COMPLEXITY = 310; // This is the bottom threshold for the spectrum complexity. Everything down will be pure green. var MIN_SPECTRUM_COMPLEXITY = 120; var SPECTRUM_COMPLEXITY_RANGE = MAX_SPECTRUM_COMPLEXITY - MIN_SPECTRUM_COMPLEXITY; // If character is not found, then it will be treated as a special character with the given weight var UNKNOWN_CHAR_WEIGHT = 15.0; // All Russian letters, with the exception of the first one, in the word will get such default weight var DEFAULT_LETTER_WEIGHT = 100; // Characters for Russian language. var ALPHABETICAL_CHARACTERS = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"; // If letter is a capital, we add such a number to its weight var CAPITAL_WEIGHT = 200.0; // If the some word has number of capitals more than this value, then we stop apply CAPITAL_COEF, because user will likely use Caps key var CAPS_LENGTH = 4; // If character is not part of Russian letters, we multiply weight by this number var SPECIAL_CHARACTER_COEF = 200.0; // Whole word's weight will get coefficient multiplied depending on its size. Longer words are harder to type. // If a word has only a single letter, then it will take longer to type it, because it doesn't have keys combination // with other letters. var WORD_LENGTH_COEF = [2.0, 1.0, 1.0, 1.0, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0]; // Dictionary with 2 letters combinations and their frequency orders. We use associative array for search, because it is much faster (if it is hot), // than other approaches: String#indexOf, RegExp, Array#indexOf. var dictionary = {}; // A flag for preventing clone panel creation: var initialized = false; // Saving the original prototype method: var proxied = window.XMLHttpRequest.prototype.send; window.XMLHttpRequest.prototype.send = function () { this.addEventListener('load', function () { try { var json = JSON.parse(this.responseText); if ('text' in json) { createPanel(json.text.text); } } catch (e) {} }.bind(this)); return proxied.apply(this, [].slice.call(arguments)); }; function createPanel (text) { if (initialized) { return false; } initialized = true; prepareDictionary(); var complexityObject = getComplexity(text); var complexity = complexityObject.complexity.toFixed(2); var params = document.getElementById("params"); if (params) { // We use wrapper only as a workaround to support KTS custom styles. // KTS changes panel style by ID. We use "statistics" ID, which is also used by another panel. // HTML 5 allows duplicate IDs. They just need to be in different subtrees. I don't like // such approach, but I fear it's the only way for now, unless we ask KTS developer to // include some lines into img/apply.js file. var wrapper = document.createElement("div"); wrapper.id = "complexity-panel"; var elem = document.createElement("div"); elem.style.setProperty("background", "none repeat scroll 0 0 #F8F4E6", null); elem.style.setProperty("margin-top", "10px", null); elem.style.setProperty("margin-bottom", "10px", null); elem.id = "statistics"; wrapper.appendChild(elem); params.parentNode.insertBefore(wrapper, params.nextSibling); elem.innerHTML = '<div class="r tl" title="v1.4"><div class="tr"><div class="bl"><div class="br"><div class="rc">' + '<h4>Прогноз сложности</h4>' + '<div><span style="font-size:17px;font-weight:bold;color:#333">' + (complexity >= 0 ? complexity.slice(0, -3) : '') + '</span>' + '<span style="font-size:14px;font-weight:bold;color:#666">' + (complexity >= 0 ? '.' + complexity.slice(-2) : 'N/A')+ '</span>' + ' − ' + (complexity >= 0 ? getComplexityText(complexity) : 'неприменимо к данному заезду') + '</div><div style="margin:10px 0 4px;background-color:white"id="spectrumCanvas"/>' + '</div></div></div></div></div>'; // Add spectrum canvas to the panel if (complexity >= 0) { var spectrum = complexityObject.spectrum; smoothArray(spectrum, 10); var canvasDiv = document.getElementById("spectrumCanvas"); var canvasElem = getSpectrumCanvas(spectrum, canvasDiv.clientWidth, CANVAS_HEIGHT); if (canvasElem != null) { canvasDiv.appendChild(canvasElem); } } } } function prepareDictionary() { for (var i = 0; i < SYLLABLES.length; i += 2) { dictionary[SYLLABLES.substr(i, 2)] = i / 2; } } function getWordLengthCoef(length) { return WORD_LENGTH_COEF[(length < WORD_LENGTH_COEF.length) ? length - 1 : WORD_LENGTH_COEF.length - 1]; } function getComplexityText(complexity) { var position = Math.floor(complexity); return COMPLEXITY_TEXT[(position < COMPLEXITY_TEXT.length) ? position : COMPLEXITY_TEXT.length - 1]; } // Return string complexity and its spectrum. Return -1 for the complexity, if it can't be applied to the string. function getComplexity(str) { var complexity = 0.0; var wordLength = 0; var wordComplexity = 0; var capsLength = 0; var prevChar = ""; var unknownCharNum = 0; var spectrum = []; var pos = 0; var wordComplexityPerCharacter, j; // Replace all "ё" occurrences to "е". str = str.split("ё").join("е"); for (var i = 0; i < str.length; i++) { var char = str.charAt(i); var charLowerCase = char.toLowerCase(); var weight; if (ALPHABETICAL_CHARACTERS.indexOf(charLowerCase) != -1) { // Alphabetical character wordLength++; if (wordLength === 1) { // First letter in a word will get weight depending on its frequency weight = CHAR_WEIGHTS[charLowerCase]; } else { // All the following letters in the word will get default weight. Their final weight will depend on the letters combination frequency. weight = DEFAULT_LETTER_WEIGHT; } // All letters in the word, starting from the second, will apply coefficient depending on the 2 letters frequency if (wordLength > 1) { var n = dictionary[prevChar + charLowerCase]; if (n == null) { n = -3.75; // This is minimum value, which can be achieved by the following formula } // Such formula returns 2 letters frequency in the decimal logarithmic scale, e.g. "0" - most common, "-1", // if frequency is 10 times less. Formula is a polynomial interpolation based on the experimental selection. var syllableDifficulty = -7e-9 * Math.pow(n, 3) + 7e-6 * Math.pow(n, 2) - 0.0059 * n; // Increase weight based on the difficulty weight *= Math.pow(1 - syllableDifficulty, 1.3); } // Capitals are harder to type var isLowerCase = char === charLowerCase; if (!isLowerCase) { capsLength++; if (capsLength < CAPS_LENGTH) { weight += CAPITAL_WEIGHT; } } else { capsLength = 0; } wordComplexity += weight; prevChar = charLowerCase; } else { // Special character (not part of Russian letters) // If we reached the end of the word, we need to calculate final word's weight depending on its length if (wordLength > 0) { wordComplexity *= getWordLengthCoef(wordLength); complexity += wordComplexity; wordComplexityPerCharacter = wordComplexity / wordLength; for(j = 0; j < wordLength; j++) { spectrum[pos++] = wordComplexityPerCharacter; } } wordComplexity = 0; capsLength = 0; wordLength = 0; weight = CHAR_WEIGHTS[charLowerCase]; if (weight == null) { weight = UNKNOWN_CHAR_WEIGHT; unknownCharNum++; } weight *= SPECIAL_CHARACTER_COEF; complexity += weight; spectrum[pos++] = weight; } } // If text doesn't finish with the special character, we need to add last word's weight if (wordLength > 0) { wordComplexity *= getWordLengthCoef(wordLength); complexity += wordComplexity; wordComplexityPerCharacter = wordComplexity / wordLength; for(j = 0; j < wordLength; j++) { spectrum[pos++] = wordComplexityPerCharacter; } } // Complexity is per character if (str.length > 0) { complexity /= str.length; } else { return {complexity: 0, spectrum: spectrum}; } // if number of unknown characters is more than 10%, then complexity value is inconsistent if (unknownCharNum / str.length > 0.1) { return {complexity: -1, spectrum: spectrum}; } // Divide by theoretical complexity minimum in order to start our reference frame for complexity from 1 complexity /= 160; if (complexity < 1) { complexity = 1; } complexity -= 1; complexity *= 20; // Scale complexity to readable values, so ~10 is close to usual hard complexity return { complexity: complexity, spectrum: spectrum }; } // Function smooths (blurs) 1D array using flat convolution buffer. Algorithm complexity is O(N + power). function smoothArray(array, power) { var smoothedValue = 0; var fractions = []; var coef = 2 * power + 1; for (var i = 0; i < array.length + power; i++) { if (i >= coef) { smoothedValue -= fractions[i % coef]; } if (i < array.length) { var value = array[i]; smoothedValue += value; fractions[i % coef] = value; } if (i >= power) { var factor; if (i < array.length) { factor = Math.min(i + 1, coef); } else { factor = coef + array.length - i - 1; } array[i - power] = smoothedValue / factor; } } } // Function returns canvas with the given width and height. We paint spectrum on the canvas using values in the array. // Lowest values will be green. Middle will be yellow. Highest will be red. function getSpectrumCanvas(array, width, height) { var canvas = document.createElement('canvas'); if (!canvas || !canvas.getContext) { // We are very sorry for our dinosaurs. God bless them. return null; } canvas.setAttribute('width', width); canvas.setAttribute('height', height); if(typeof G_vmlCanvasManager != 'undefined') { canvas = G_vmlCanvasManager.initElement(canvas); } var ctx = canvas.getContext("2d"); // Too opaque spectrum burns eyes ctx.globalAlpha = CANVAS_OPACITY; // We need to scale to the given canvas width ctx.scale(width / array.length, 1); var r, g; for (var i = 0; i < array.length; i++) { // Apply the thresholds var value = Math.min(Math.max(array[i], MIN_SPECTRUM_COMPLEXITY), MAX_SPECTRUM_COMPLEXITY); // Scale complexity to 0 - 255 range var complexity = Math.floor(255 * (value - MIN_SPECTRUM_COMPLEXITY) / SPECTRUM_COMPLEXITY_RANGE); // Calculate red and green components. Blue will be always 0. r = Math.min(complexity * 2, 255); g = Math.min(2 * (255 - complexity), 255); // Paint vertical line ctx.strokeStyle="rgb(" + r + "," + g + ",0)"; ctx.beginPath(); ctx.moveTo(i, 0); ctx.lineTo(i, height); ctx.stroke(); } return canvas; } } var inject = document.createElement("script"); inject.setAttribute("type", "text/javascript"); inject.appendChild(document.createTextNode("(" + embed + ")()")); document.body.appendChild(inject);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址