diff --git a/user.js b/user.js index 0c486a2..466724c 100644 --- a/user.js +++ b/user.js @@ -2,7 +2,7 @@ // @name Sorryops // @name:ru Сориупс // @namespace https://git.disroot.org/electromagneticcyclone/sorryops -// @version 20240424.2 +// @version 20240427.1 // @description Collect and reuse ORIOKS test answers // @description:ru Скрипт для сбора и переиспользования ответов на тесты ОРИОКС // @icon https://orioks.miet.ru/favicon.ico @@ -21,18 +21,23 @@ // @updateURL https://update.greasyfork.org/scripts/481036/Sorryops.meta.js // ==/UserScript== +/* Labels */ + var all_labels = { en: { l: "English", settings_title: "Settings", script_language: "Language", auto_answer: "Auto answer", + auto_answer_no: "No", + auto_answer_first: "First", + auto_answer_random: "Random", display_answer: "Display answer near variant", + stop_timer: "Freeze and hide timer", register_keyboard_keys: "Register hotkeys", copy_answers: "Copy results to the clipboard", append_question_number: "Show question numbers in the final report", accumulator_enable: "Accumulate test results in one field", - accumulator_prefix: "Accumulated results prefix (test number)", auto_continue: "Auto continue (DANGEROUS!!! Will be disabled after an hour. Press `d` to disable)", auto_restart: "Auto restart (DANGEROUS!!! Will be disabled after an hour. Press `d` to disable. Make sure you have infinite attempts)", }, @@ -40,13 +45,16 @@ var all_labels = { l: "Русский", settings_title: "Настройки", script_language: "Язык", - auto_answer: "Автоответчик", + auto_answer: "Автовыбор ответа", + auto_answer_no: "Нет", + auto_answer_first: "Первый", + auto_answer_random: "Случайный", display_answer: "Отображать ответ рядом с вариантом", + stop_timer: "Заморозить и скрыть таймер", register_keyboard_keys: "Горячие клавиши", copy_answers: "Копировать результаты в буфер обмена", append_question_number: "Отображать номер вопроса в финальном отчёте", accumulator_enable: "Собирать отчёты в одно поле", - accumulator_prefix: "Префикс перенесённого отчёта (номер теста)", auto_continue: "Автопродолжение (ОПАСНО!!! Отключается через час. Нажмите `d`, чтобы остановить)", auto_restart: "Автоперезапуск (ОПАСНО!!! Отключается через час. Нажмите `d`, чтобы остановить. Убедитесь, что количество попыток неограничено)", }, @@ -67,6 +75,10 @@ if (labels == undefined) { labels = all_labels.ru; } +/* End Labels */ + +/* Config */ + var config = new GM_config({ id: 'config', title: labels.settings_title, @@ -74,20 +86,33 @@ var config = new GM_config({ script_language: { label: labels.script_language, type: 'select', - options: [ '-', all_labels.en.l, all_labels.ru.l ], + options: [ + '-', + all_labels.en.l, + all_labels.ru.l, + ], default: '-', }, auto_answer: { label: labels.auto_answer, type: 'select', - options: [ 'No', 'First', 'Random' ], - default: 'No', + options: [ + labels.auto_answer_no, + labels.auto_answer_first, + labels.auto_answer_random, + ], + default: labels.auto_answer_no, }, display_answer: { label: labels.display_answer, type: 'checkbox', default: true, }, + stop_timer: { + label: labels.stop_timer, + type: 'checkbox', + default: true, + }, register_keyboard_keys: { label: labels.register_keyboard_keys, type: 'checkbox', @@ -108,11 +133,6 @@ var config = new GM_config({ type: 'checkbox', default: false, }, - accumulator_prefix: { - label: labels.accumulator_prefix, - type: 'text', - default: "", - }, auto_continue: { label: labels.auto_continue, type: 'checkbox', @@ -134,6 +154,7 @@ var config = new GM_config({ }, events: { init: function() { + GM_setValue('stop_timer', this.get('stop_timer')); if (this.get('auto_continue') && (this.get('auto_answer') == "No")) { this.set('auto_continue', false); } @@ -164,20 +185,55 @@ var config = new GM_config({ }, }); -var answers = []; -var variant, hash; -var testID = (() => { - var url = document.URL; - url = url.slice(url.indexOf("idKM=") + 5); - url = url.slice(0, url.indexOf("&")); - return url; -})(); - -GM_registerMenuCommand('Script Settings', () => { +GM_registerMenuCommand(labels.settings_title, () => { config.open(); }); -window.addEventListener('load', actionFunction); +/* End Config */ + +/* Server */ + +// Local +function S_setValue(field, value) { + var v = GM_getValue("server", value); +} + +// Local +function S_getValue(field, default_value) { + var v = GM_getValue("server", default_value); +} + +/* End Server */ + +/* Stop timer */ + +if (GM_getValue('stop_timer', true)) { + var i, pbox; + var pboxes = document.getElementsByTagName('p'); + for (i = 0; i < pboxes.length; i++) { + pbox = pboxes[i]; + if (pbox.textContent.includes("Осталось:")) { + pbox.parentNode.remove(); + document.getElementsByTagName('hr')[0].remove(); + var injectFakeTimer = function(window) { + window.setInterval = (f, t) => { + return window.setInterval(f, 10^999); + }; + } + var scriptFakeTimer = document.createElement('script'); + scriptFakeTimer.setAttribute("type", "application/javascript"); + scriptFakeTimer.textContent = '(' + injectFakeTimer + ')(window);'; + document.body.appendChild(scriptFakeTimer); + break; + } + } +} + +/* End Stop timer */ + +/* Events */ + +window.addEventListener('load', main); window.onkeydown = (e) => { if ((e.key == "Enter") && config.get('register_keyboard_keys')) { press_continue_btn(); @@ -189,6 +245,24 @@ window.onkeydown = (e) => { } }; +/* End Events */ + +/* Page properties */ + +// const success = -1487162948; +var answers = []; +var variant, hash, type; +var testID = (() => { + var url = document.URL; + url = url.slice(url.indexOf("idKM=") + 5); + url = url.slice(0, url.indexOf("&")); + return url; +})(); + +/* End properties */ + +/* Functions */ + // https://stackoverflow.com/a/15710692 function hashCode(s) { return s.split("").reduce(function(a, b) { @@ -197,138 +271,6 @@ function hashCode(s) { }, 0); } -function update_variant() { - var i, pbox; - var chosen_answer = ""; - for (i = 0; i < answers.length; i++) { - chosen_answer += answers[i].checked ? answers[i].value : ""; - } - chosen_answer = chosen_answer.split('').sort().join(''); - var pboxes = document.getElementsByTagName('p'); - const display_answer = config.get('display_answer'); - for (i = 0; i < pboxes.length; i++) { - pbox = pboxes[i]; - if (pbox.textContent.includes("Вопрос:")) { - pbox.innerHTML = "(Вариант )
Вопрос:"; - break; - } - } - var question_num = undefined; - for (i = 0; i < pboxes.length; i++) { - pbox = pboxes[i]; - if (pbox.textContent.includes("Текущий вопрос: ")) { - question_num = pbox.textContent.slice(variant.indexOf("Текущий вопрос: ") + 16); - break; - } - } - var tests = GM_getValue('tests', new Object()); - if (tests[testID] === undefined) { - tests[testID] = new Object(); - } - tests[testID][hash] = [question_num, chosen_answer]; - GM_setValue('tests', tests); -} - -function test_form_handler() { - var i; - var objects = new Object(); - var boxes = document.getElementsByTagName('input'); - var form = document.getElementById('testform-answer'); - for (i = 0; i < boxes.length; i++) { - if (boxes[i].type === 'checkbox' | boxes[i].type === 'radio') { - var span = document.createElement('span'); - span.innerHTML = - boxes[i].type === 'radio' && boxes[i].value == "1" - ? "" + boxes[i].value + ") " - : boxes[i].value + ") "; - boxes[i].parentNode.insertBefore(span, boxes[i]); - objects[boxes[i].value] = boxes[i]; - } - } - const sorted_objects = Object.keys(objects).sort().reduce( - (obj, key) => { - obj[key] = objects[key]; - return obj; - }, {} - ); - for (var key in sorted_objects) { - sorted_objects[key].parentNode.remove(); - form.appendChild(sorted_objects[key].parentNode); - answers.push(sorted_objects[key]); - } - const auto_answer = config.get('auto_answer'); - var answer; - if (auto_answer == 'Random') { - if (answers[0].type === 'radio') { - var chosen_answer = Math.floor(Math.random() * answers.length); - answers[chosen_answer].click(); - } else { - var pick = Math.floor(Math.random() * (Math.pow(2, answers.length) - 1)) + 1; - for (i = 0; i < answers.length; i++) { - if(pick & Math.pow(2, i)) { - answers[i].click(); - } - } - } - } else if (auto_answer == 'First') { - answers[0].click(); - } - variant = document.getElementById('w0').parentNode.textContent; - variant = variant.slice(variant.indexOf("Вопрос:")); - hash = hashCode(variant); - update_variant(); - form.addEventListener('click', update_variant); -} - -function result_page_handler() { - var i; - var correct = variant.slice(variant.indexOf("Число верных ответов: ") + 22); - correct = correct.slice(0, correct.indexOf("\n")); - var test = GM_getValue('tests', new Object())[testID]; - if (test === undefined) { - return; - } - var printer = ""; - var sorted_test = []; - for (var hash in test) { - sorted_test.push([hash].concat(test[hash])); - } - sorted_test.sort((a, b) => {return a[1] - b[1]}); - console.log(sorted_test); - for (i = 0; i < sorted_test.length; i++) { - printer += (config.get('append_question_number') ? (sorted_test[i][1] + ") ") : "") + sorted_test[i][0] + " " + sorted_test[i][2] + "\n"; - } - printer += correct; - if (config.get('copy_answers')) { - GM_setClipboard(printer); - } - if (config.get('accumulator_enable')) { - var acc = GM_getValue('accumulated_answers', ""); - if (acc != "") { - acc += "\n\n"; - } - var prefix = config.get('accumulator_prefix'); - if (prefix != "") { - acc += prefix + "\n"; - } - acc += printer; - GM_setValue('accumulated_answers', acc); - printer = acc; - } - printer = ""; - var pboxes = document.getElementsByTagName('p'); - for (i = 0; i < pboxes.length; i++) { - var pbox = pboxes[i]; - if (pbox.textContent.includes("Попытка ")) { - pbox.outerHTML += printer; - break; - } - } - var clear = GM_getValue('clear_tests', new Object()); - clear[testID] = true; - GM_setValue('clear_tests', clear); -} - function DB_cleaner() { var clear = GM_getValue('clear_tests', new Object()); var tests = GM_getValue('tests', new Object()); @@ -360,7 +302,183 @@ function press_continue_btn() { } } -function actionFunction() { +function calculate_variant_hash() { + variant = document.getElementById('w0').parentNode.textContent; + variant = variant.slice(variant.indexOf("Вопрос:")); + hash = hashCode(variant); +} + +function update_variant() { + var i, pbox; + var chosen_answer = ""; + switch (type) { + case 'checkbox': + case 'radio': { + for (i = 0; i < answers.length; i++) { + chosen_answer += answers[i].checked ? answers[i].value : ""; + } + chosen_answer = chosen_answer.split('').sort().join(''); + } break; + case 'text': { + for (i = 0; i < answers.length; i++) { + chosen_answer += "[" + answers[i].value + "]"; + } + } + } + var pboxes = document.getElementsByTagName('p'); + const display_answer = config.get('display_answer'); + for (i = 0; i < pboxes.length; i++) { + pbox = pboxes[i]; + if (pbox.textContent.includes("Вопрос:")) { + pbox.innerHTML = "(Вариант )
Вопрос:"; + break; + } + } + var question_num = undefined; + for (i = 0; i < pboxes.length; i++) { + pbox = pboxes[i]; + if (pbox.textContent.includes("Текущий вопрос: ")) { + question_num = pbox.textContent.slice(variant.indexOf("Текущий вопрос: ") + 16); + break; + } + } + var tests = GM_getValue('tests', new Object()); + if (tests[testID] === undefined) { + tests[testID] = new Object(); + } + tests[testID][hash] = [question_num, chosen_answer]; + GM_setValue('tests', tests); +} + +/* End Functions */ + +/* Handlers */ + +function test_form_handler() { + var i; + var boxes = []; + var objects = new Object(); + var form = document.getElementById('testform-answer'); + var manual_form = document.getElementById('testform-answer-0'); + if (form != null) { + boxes = form.getElementsByTagName('input'); + } else if (manual_form != null) { + i = 1; + while (manual_form != null) { + boxes.push(manual_form); + manual_form = document.getElementById('testform-answer-' + i++); + } + console.log(boxes); + } + type = boxes[0].type; + console.log(type); + switch (type) { + case 'checkbox': + case 'radio': { + for (i = 0; i < boxes.length; i++) { + var answerHash = hashCode(boxes[i].parentNode.innerText) + var span = document.createElement('span'); + span.innerHTML = + boxes[i].type === 'radio' && boxes[i].value == "1" + ? "" + boxes[i].value + ") " + : boxes[i].value + ") "; + boxes[i].parentNode.insertBefore(span, boxes[i]); + objects[boxes[i].value] = boxes[i]; + } + const sorted_objects = Object.keys(objects).sort().reduce( + (obj, key) => { + obj[key] = objects[key]; + return obj; + }, {} + ); + for (var key in sorted_objects) { + sorted_objects[key].parentNode.remove(); + form.appendChild(sorted_objects[key].parentNode); + answers.push(sorted_objects[key]); + } + calculate_variant_hash(); + var correct_answer = S_getValue(testID + "." + hash + ".correct", undefined); + var incorrect_answers = S_getValue(testID + "." + hash + ".incorrect", undefined); + const auto_answer = config.get('auto_answer'); + if (auto_answer == labels.auto_answer_random) { + if (answers[0].type === 'radio') { + var chosen_answer = Math.floor(Math.random() * answers.length); + answers[chosen_answer].click(); + } else { + var pick = Math.floor(Math.random() * (Math.pow(2, answers.length) - 1)) + 1; + for (i = 0; i < answers.length; i++) { + if(pick & Math.pow(2, i)) { + answers[i].click(); + } + } + } + } else if (auto_answer == labels.auto_answer_first) { + answers[0].click(); + } + } break; + case 'text': { + answers = boxes; + calculate_variant_hash(); + } break; + } + update_variant(); + for (i = 0; i < answers.length; i++) { + answers[i].addEventListener('change', update_variant); + } +} + +function result_page_handler() { + var i; + var correct = variant.slice(variant.indexOf("Число верных ответов: ") + 22); + correct = correct.slice(0, correct.indexOf("\n")); + var test = GM_getValue('tests', new Object())[testID]; + if (test === undefined) { + return; + } + var printer = ""; + var sorted_test = []; + for (var hash in test) { + sorted_test.push([hash].concat(test[hash])); + } + sorted_test.sort((a, b) => {return a[1] - b[1]}); + console.log(sorted_test); + for (i = 0; i < sorted_test.length; i++) { + printer += (config.get('append_question_number') ? (sorted_test[i][1] + ") ") : "") + sorted_test[i][0] + " " + sorted_test[i][2] + "\n"; + } + printer += correct; + if (config.get('copy_answers')) { + GM_setClipboard(printer); + } + if (config.get('accumulator_enable')) { + var acc = GM_getValue('accumulated_answers', ""); + if (acc != "") { + acc += "\n\n"; + } + var prefix = testID; + if (prefix != "") { + acc += prefix + "\n"; + } + acc += printer; + GM_setValue('accumulated_answers', acc); + printer = acc; + } + printer = ""; + var pboxes = document.getElementsByTagName('p'); + for (i = 0; i < pboxes.length; i++) { + var pbox = pboxes[i]; + if (pbox.textContent.includes("Попытка ")) { + pbox.outerHTML += printer; + break; + } + } + var clear = GM_getValue('clear_tests', new Object()); + clear[testID] = true; + GM_setValue('clear_tests', clear); +} + +/* End Handlers */ + +function main() { var old_time, cur_time; variant = document.getElementById('w0').parentNode.textContent; if (variant.includes("Вопрос:")) {