Sorryops

Collect and reuse ORIOKS test answers

当前为 2024-04-29 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Sorryops
  3. // @name:ru Сориупс
  4. // @namespace https://git.disroot.org/electromagneticcyclone/sorryops
  5. // @version 20240429.1
  6. // @description Collect and reuse ORIOKS test answers
  7. // @description:ru Скрипт для сбора и переиспользования ответов на тесты ОРИОКС
  8. // @icon https://orioks.miet.ru/favicon.ico
  9. // @author electromagneticcyclone & angelbeautifull
  10. // @license GPL-3.0-or-later
  11. // @supportURL https://git.disroot.org/electromagneticcyclone/sorryops
  12. // @match https://orioks.miet.ru/student/student/test*
  13. // @grant GM_getValue
  14. // @grant GM_setValue
  15. // @grant GM_addStyle
  16. // @grant GM_registerMenuCommand
  17. // @grant GM_setClipboard
  18. // @grant GM_xmlhttpRequest
  19. // @require https://openuserjs.org/src/libs/sizzle/GM_config.js
  20. // @connect sorryops.ru
  21. // @run-at document-start
  22. // ==/UserScript==
  23.  
  24. /* Charset */
  25. const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  26. /* End Charset */
  27.  
  28. /* Labels */
  29.  
  30. const all_labels = {
  31. en: {
  32. l: "English",
  33. settings_title: "Settings",
  34. script_language: "Language",
  35. show_user_id: "Show user ID",
  36. user_id: "User ID (keep private)",
  37. server: "Sync answers with server (leave blank to disable)",
  38. auto_answer: "Auto answer",
  39. auto_answer_no: "No",
  40. auto_answer_first: "First",
  41. auto_answer_random: "Random",
  42. display_values: "Answers variant",
  43. display_values_ori: "ORIOKS",
  44. display_values_sorry: "Sorry",
  45. display_values_both: "Both",
  46. display_answer: "Display answer near variant",
  47. stop_timer: "Freeze and hide timer",
  48. register_keyboard_keys: "Register hotkeys",
  49. copy_answers: "Copy results to the clipboard",
  50. append_question_number: "Show question numbers in the final report",
  51. accumulator_enable: "Accumulate test results in one field",
  52. auto_continue: "Auto continue (DANGEROUS!!! Will be disabled after an hour. Press `d` to disable)",
  53. auto_restart: "Auto restart (DANGEROUS!!! Will be disabled after an hour. Press `d` to disable. Make sure you have infinite attempts)",
  54. },
  55. ru: {
  56. l: "Русский",
  57. settings_title: "Настройки",
  58. script_language: "Язык",
  59. show_user_id: "Показать индетификатор пользователя",
  60. user_id: "Индетификатор (держать в секрете)",
  61. server: "Синхронизировать ответы с сервером (оставить пустым для отключения)",
  62. auto_answer: "Автовыбор ответа",
  63. auto_answer_no: "Нет",
  64. auto_answer_first: "Первый",
  65. auto_answer_random: "Случайный",
  66. display_values: "Вариант отображения ответов",
  67. display_values_ori: "ОРИОКС",
  68. display_values_sorry: "Сори",
  69. display_values_both: "Оба",
  70. display_answer: "Отображать ответ рядом с вариантом",
  71. stop_timer: "Заморозить и скрыть таймер",
  72. register_keyboard_keys: "Горячие клавиши",
  73. copy_answers: "Копировать результаты в буфер обмена",
  74. append_question_number: "Отображать номер вопроса в финальном отчёте",
  75. accumulator_enable: "Собирать отчёты в одно поле",
  76. auto_continue: "Автопродолжение (ОПАСНО!!! Отключается через час. Нажмите `d`, чтобы остановить)",
  77. auto_restart: "Автоперезапуск (ОПАСНО!!! Отключается через час. Нажмите `d`, чтобы остановить. Убедитесь, что количество попыток неограничено)",
  78. },
  79. };
  80.  
  81. var labels = all_labels[(() => {
  82. var lang = GM_getValue('language', "-");
  83. if (!lang || (lang == "-")) {
  84. lang = navigator.language || navigator.userLanguage;
  85. }
  86. for (var l in all_labels) {
  87. if (lang.includes(l)) {
  88. return l;
  89. }
  90. }
  91. })()];
  92. if (labels == undefined) {
  93. labels = all_labels.ru;
  94. }
  95.  
  96. /* End Labels */
  97.  
  98. /* Config */
  99.  
  100. var config = new GM_config({
  101. id: 'config',
  102. title: labels.settings_title,
  103. fields: {
  104. script_language: {
  105. label: labels.script_language,
  106. type: 'select',
  107. options: [
  108. '-',
  109. all_labels.en.l,
  110. all_labels.ru.l,
  111. ],
  112. default: '-',
  113. },
  114. show_user_id: {
  115. label: labels.show_user_id,
  116. type: 'checkbox',
  117. default: false,
  118. },
  119. user_id: {
  120. label: labels.user_id + (GM_getValue("show_user_id", false) ? "" : "<input readonly value='******'>"),
  121. type: GM_getValue("show_user_id", false) ? 'text' : 'hidden',
  122. save: false,
  123. default: '',
  124. },
  125. server: {
  126. label: labels.server,
  127. type: 'text',
  128. default: '',
  129. },
  130. valid_user_id: {
  131. type: 'hidden',
  132. default: '',
  133. },
  134. auto_answer: {
  135. label: labels.auto_answer,
  136. type: 'select',
  137. options: [
  138. labels.auto_answer_no,
  139. labels.auto_answer_first,
  140. labels.auto_answer_random,
  141. ],
  142. default: labels.auto_answer_no,
  143. },
  144. display_values: {
  145. label: labels.display_values,
  146. type: 'select',
  147. options: [
  148. labels.display_values_ori,
  149. labels.display_values_sorry,
  150. labels.display_values_both,
  151. ],
  152. default: labels.display_values_ori,
  153. },
  154. display_answer: {
  155. label: labels.display_answer,
  156. type: 'checkbox',
  157. default: true,
  158. },
  159. stop_timer: {
  160. label: labels.stop_timer,
  161. type: 'checkbox',
  162. default: false,
  163. },
  164. register_keyboard_keys: {
  165. label: labels.register_keyboard_keys,
  166. type: 'checkbox',
  167. default: true,
  168. },
  169. copy_answers: {
  170. label: labels.copy_answers,
  171. type: 'checkbox',
  172. default: false,
  173. },
  174. append_question_number: {
  175. label: labels.append_question_number,
  176. type: 'checkbox',
  177. default: true,
  178. },
  179. accumulator_enable: {
  180. label: labels.accumulator_enable,
  181. type: 'checkbox',
  182. default: false,
  183. },
  184. auto_continue: {
  185. label: labels.auto_continue,
  186. type: 'checkbox',
  187. default: false,
  188. },
  189. auto_continue_time: {
  190. type: 'hidden',
  191. default: 0,
  192. },
  193. auto_restart: {
  194. label: labels.auto_restart,
  195. type: 'checkbox',
  196. default: false,
  197. },
  198. auto_restart_time: {
  199. type: 'hidden',
  200. default: 0,
  201. },
  202. },
  203. events: {
  204. init: function() {
  205. var valid_user_id = this.get('valid_user_id');
  206. if (!validate_user_id(valid_user_id)) {
  207. valid_user_id = generate_user_id();
  208. }
  209. this.set('user_id', valid_user_id);
  210. this.set('valid_user_id', valid_user_id);
  211. GM_setValue('show_user_id', this.get('show_user_id'));
  212. GM_setValue('stop_timer', this.get('stop_timer'));
  213. if (this.get('auto_continue') && (this.get('auto_answer') == "No")) {
  214. this.set('auto_continue', false);
  215. }
  216. if (this.get('accumulator_enable') == false) {
  217. GM_setValue('accumulated_answers', "");
  218. }
  219. switch (this.get('script_language')) {
  220. case all_labels.en.l:
  221. GM_setValue('language', "en");
  222. break;
  223. case all_labels.ru.l:
  224. GM_setValue('language', "ru");
  225. break;
  226. default:
  227. GM_setValue('language', "-");
  228. break;
  229. }
  230. },
  231. save: function(forgotten) {
  232. this.set('auto_continue_time', Date.now());
  233. this.set('auto_restart_time', Date.now());
  234. if (this.isOpen && this.get('auto_continue') && (this.get('auto_answer') == "No")) {
  235. this.set('auto_continue', false);
  236. alert("Can't automatically continue without answer.");
  237. }
  238. if (!validate_user_id(forgotten['user_id'])) {
  239. this.set('user_id', this.get('valid_user_id'))
  240. alert('User ID is invalid!');
  241. } else {
  242. this.set('valid_user_id', forgotten['user_id'])
  243. }
  244. this.init();
  245. },
  246. },
  247. });
  248.  
  249. GM_registerMenuCommand(labels.settings_title, () => {
  250. config.open();
  251. });
  252.  
  253. /* End Config */
  254.  
  255. /* Server */
  256.  
  257. function send_to_server(results) {
  258. var server = config.get('server');
  259. if (server != '') {
  260. GM_xmlhttpRequest({
  261. method: 'POST',
  262. url: 'https://' + server,
  263. headers: {
  264. 'Content-Type': 'application/json',
  265. },
  266. data: JSON.stringify(results),
  267. });
  268. }
  269. }
  270.  
  271. function fetch_from_server(path, func) {
  272. var server = config.get('server');
  273. if (server != '') {
  274. GM_xmlhttpRequest({
  275. method: 'GET',
  276. url: 'https://' + server + '/' + path,
  277. onload: function (response) {
  278. var text = response.responseText;
  279. if (!text.includes("{")) {
  280. func({});
  281. } else {
  282. func(JSON.parse(text));
  283. }
  284. },
  285. onerror: function (e) {
  286. func({});
  287. },
  288. onabort: function (e) {
  289. func({});
  290. },
  291. ontimeout: function (e) {
  292. func({});
  293. }
  294. });
  295. } else {
  296. func({});
  297. }
  298. }
  299.  
  300. /* End Server */
  301.  
  302. /* Stop timer */
  303.  
  304. if (GM_getValue('stop_timer', true)) {
  305. var i, pbox;
  306. var pboxes = document.getElementsByTagName('p');
  307. for (i = 0; i < pboxes.length; i++) {
  308. pbox = pboxes[i];
  309. if (pbox.textContent.includes("Осталось:")) {
  310. pbox.parentNode.remove();
  311. document.getElementsByTagName('hr')[0].remove();
  312. var injectFakeTimer = function(window) {
  313. window.setInterval = (f, t) => {
  314. return window.setInterval(f, 10^999);
  315. };
  316. }
  317. var scriptFakeTimer = document.createElement('script');
  318. scriptFakeTimer.setAttribute("type", "application/javascript");
  319. scriptFakeTimer.textContent = '(' + injectFakeTimer + ')(window);';
  320. document.body.appendChild(scriptFakeTimer);
  321. break;
  322. }
  323. }
  324. }
  325.  
  326. /* End Stop timer */
  327.  
  328. /* Events */
  329.  
  330. window.addEventListener('load', main);
  331. window.onkeydown = (e) => {
  332. if ((e.key == "Enter") && config.get('register_keyboard_keys')) {
  333. press_continue_btn();
  334. }
  335. if (e.key == "d") {
  336. config.set('auto_continue', false);
  337. config.set('auto_restart', false);
  338. config.save();
  339. }
  340. };
  341.  
  342. /* End Events */
  343.  
  344. /* Page properties */
  345.  
  346. // const success = -1487162948;
  347. var answers = [];
  348. var variant, hash, type;
  349. var testID = (() => {
  350. var url = document.URL;
  351. url = url.slice(url.indexOf("idKM=") + 5);
  352. url = url.slice(0, url.indexOf("&"));
  353. return url;
  354. })();
  355.  
  356. /* End properties */
  357.  
  358. /* Functions */
  359.  
  360. // https://github.com/ajayyy/maze-utils/blob/036086403f675b8fea0e22065f26ba534e351562/src/setup.ts
  361. function generate_user_id(length = 36) {
  362. var i;
  363. var result = "";
  364. const cryptoFuncs = typeof window === "undefined" ? crypto : window.crypto;
  365. if (cryptoFuncs && cryptoFuncs.getRandomValues) {
  366. const values = new Uint32Array(length);
  367. cryptoFuncs.getRandomValues(values);
  368. for (i = 0; i < length; i++) {
  369. result += charset[values[i] % charset.length];
  370. }
  371. } else {
  372. for (i = 0; i < length; i++) {
  373. result += charset[Math.floor(Math.random() * charset.length)];
  374. }
  375. }
  376. return result;
  377. }
  378.  
  379. function validate_user_id(uid, length = 36) {
  380. var i;
  381. if (uid.length != length) {
  382. return false;
  383. }
  384. for (i = 0; i < length; i++) {
  385. if (!charset.includes(uid[i])) {
  386. return false;
  387. }
  388. }
  389. return true;
  390. }
  391.  
  392. // https://stackoverflow.com/a/15710692
  393. function hashCode(s, return_num = false) {
  394. var result = "";
  395. var h = s.split("").reduce(function(a, b) {
  396. a = ((a << 5) - a) + b.charCodeAt(0);
  397. return a & a;
  398. }, 0);
  399. if (return_num) {
  400. return h;
  401. }
  402. while (h != 0) {
  403. result += charset[((h % charset.length) + charset.length) % charset.length];
  404. h = Math.floor(Math.abs(h) / charset.length) * (h / Math.abs(h));
  405. }
  406. return result;
  407. }
  408.  
  409. function set_to_clear(id, exec_if_not_cleared) {
  410. var clear = GM_getValue('clear_tests', new Object());
  411. if (!clear[id]) {
  412. exec_if_not_cleared();
  413. }
  414. clear[id] = true;
  415. GM_setValue('clear_tests', clear);
  416. }
  417.  
  418. function DB_cleaner() {
  419. var clear = GM_getValue('clear_tests', new Object());
  420. var tests = GM_getValue('tests', new Object());
  421. for (var test in clear) {
  422. delete tests[test];
  423. }
  424. GM_setValue('tests', tests);
  425. GM_setValue('clear_tests', new Object());
  426. }
  427.  
  428. function press_continue_btn() {
  429. var i;
  430. var buttons = document.getElementsByTagName('button');
  431. var button = undefined;
  432. for (i = 0; i < buttons.length; i++) {
  433. var btn = buttons[i];
  434. if (btn.textContent.includes("Пройти") || btn.textContent.includes("Продолжить")) {
  435. button = btn;
  436. break;
  437. }
  438. }
  439. if (button === undefined) {
  440. return;
  441. }
  442. if (button.textContent.includes("Пройти")) {
  443. window.location.replace(button.parentNode.href);
  444. } else if (button.textContent.includes("Продолжить")) {
  445. button.click();
  446. }
  447. }
  448.  
  449. function calculate_variant_hash() {
  450. variant = document.getElementById('w0').parentNode.textContent;
  451. variant = variant.slice(variant.indexOf("Вопрос:"));
  452. hash = hashCode(variant);
  453. }
  454.  
  455. function update_variant() {
  456. var i, pbox;
  457. var chosen_answer = "";
  458. switch (type) {
  459. case 'checkbox':
  460. case 'radio': {
  461. for (i = 0; i < answers.length; i++) {
  462. chosen_answer += answers[i].checked ? answers[i].sorry_value : "";
  463. }
  464. chosen_answer = chosen_answer.split('').sort().join('');
  465. if (type == 'checkbox') {
  466. chosen_answer = "{" + chosen_answer + "}";
  467. }
  468. } break;
  469. case 'text': {
  470. for (i = 0; i < answers.length; i++) {
  471. chosen_answer += "[" + answers[i].value + "]";
  472. }
  473. }
  474. }
  475. var pboxes = document.getElementsByTagName('p');
  476. const display_answer = config.get('display_answer');
  477. for (i = 0; i < pboxes.length; i++) {
  478. pbox = pboxes[i];
  479. if (pbox.textContent.includes("Вопрос:")) {
  480. pbox.innerHTML = "<i>(Вариант <input onfocus='this.select();' id='variant' value='" + hash + (display_answer == true ? (" " + chosen_answer) : "") + "' readonly>)</i><br>Вопрос:";
  481. break;
  482. }
  483. }
  484. var question_num = undefined;
  485. for (i = 0; i < pboxes.length; i++) {
  486. pbox = pboxes[i];
  487. if (pbox.textContent.includes("Текущий вопрос: ")) {
  488. question_num = pbox.textContent.slice(variant.indexOf("Текущий вопрос: ") + 16).trim();
  489. break;
  490. }
  491. }
  492. if (hash !== undefined) {
  493. var tests = GM_getValue('tests', new Object());
  494. if (tests[testID] === undefined) {
  495. tests[testID] = new Object();
  496. }
  497. tests[testID][hash] = [question_num, chosen_answer, answers.length];
  498. GM_setValue('tests', tests);
  499. }
  500. }
  501.  
  502. /* End Functions */
  503.  
  504. /* Handlers */
  505.  
  506. function test_form_handler(server_data) {
  507. var i, key, correct, incorrect, answer, sorry_val;
  508. var boxes = [];
  509. var sorted_objects;
  510. var objects_hash = new Object();
  511. var objects_value = new Object();
  512. var form = document.getElementById('testform-answer');
  513. var manual_form = document.getElementById('testform-answer-0');
  514. if (form != null) {
  515. boxes = form.getElementsByTagName('input');
  516. } else if (manual_form != null) {
  517. i = 1;
  518. while (manual_form != null) {
  519. boxes.push(manual_form);
  520. manual_form = document.getElementById('testform-answer-' + i++);
  521. }
  522. }
  523. type = boxes[0].type;
  524. switch (type) {
  525. case 'checkbox':
  526. case 'radio': {
  527. for (i = 0; i < boxes.length; i++) {
  528. boxes[i].hash = hashCode(boxes[i].parentNode.innerText, true);
  529. objects_hash[boxes[i].hash] = boxes[i];
  530. objects_value[boxes[i].value] = boxes[i];
  531. }
  532. const sorted_objects_hash = Object.keys(objects_hash).sort().reduce(
  533. (obj, key) => {
  534. obj[key] = objects_hash[key];
  535. return obj;
  536. }, {}
  537. );
  538. const sorted_objects_value = Object.keys(objects_value).sort().reduce(
  539. (obj, key) => {
  540. obj[key] = objects_value[key];
  541. return obj;
  542. }, {}
  543. );
  544. i = 0;
  545. sorted_objects = sorted_objects_hash;
  546. for (key in sorted_objects) {
  547. sorted_objects[key].parentNode.remove();
  548. form.appendChild(sorted_objects[key].parentNode);
  549. }
  550. calculate_variant_hash();
  551. if (server_data.hasOwnProperty('correct')) {
  552. correct = server_data.correct;
  553. if (correct === undefined) {
  554. correct = undefined;
  555. } else if (correct.hasOwnProperty(hash)) {
  556. correct = correct[hash];
  557. } else {
  558. correct = undefined;
  559. }
  560. } else {
  561. correct = undefined;
  562. }
  563. if (server_data.hasOwnProperty('incorrect')) {
  564. incorrect = server_data.incorrect;
  565. if (incorrect === undefined) {
  566. incorrect = [];
  567. } else if (incorrect.hasOwnProperty(hash)) {
  568. incorrect = incorrect[hash];
  569. } else {
  570. incorrect = [];
  571. }
  572. } else {
  573. incorrect = [];
  574. }
  575. for (key in sorted_objects) {
  576. sorted_objects[key].sorry_value = charset[i++];
  577. var span = document.createElement('span');
  578. var disp_val;
  579. switch (config.get('display_values')) {
  580. case labels.display_values_ori:
  581. disp_val = sorted_objects[key].value;
  582. break;
  583. case labels.display_values_sorry:
  584. disp_val = sorted_objects[key].sorry_value;
  585. break;
  586. case labels.display_values_both:
  587. disp_val = sorted_objects[key].value + ":" + sorted_objects[key].sorry_value;
  588. break;
  589. }
  590. span.innerHTML = disp_val + ") ";
  591. sorted_objects[key].parentNode.insertBefore(span, sorted_objects[key]);
  592. answers.push(sorted_objects[key]);
  593. }
  594. if (config.get('display_values') == labels.display_values_ori) {
  595. for (key in sorted_objects_value) {
  596. sorted_objects_value[key].parentNode.remove();
  597. form.appendChild(sorted_objects_value[key].parentNode);
  598. }
  599. }
  600. const auto_answer = config.get('auto_answer');
  601. if (correct != undefined) {
  602. for (answer in answers) {
  603. if (answers[answer].sorry_value == correct) {
  604. var correct_element = answers[answer].parentNode;
  605. sorry_val = answers[answer].sorry_value;
  606. correct_element.innerHTML = "<div style='color: green;'>" + correct_element.innerHTML + "</div>";
  607. answers[answer] = correct_element.getElementsByTagName('input')[0];
  608. answers[answer].sorry_value = sorry_val;
  609. answers[answer].click();
  610. break;
  611. }
  612. }
  613. } else if (auto_answer == labels.auto_answer_random) {
  614. if (answers[0].type === 'radio') {
  615. var possible_answers = [];
  616. for (answer in answers) {
  617. if (incorrect.includes(answers[answer].sorry_value) == false) {
  618. possible_answers.push(answer);
  619. } else {
  620. var incorrect_element = answers[answer].parentNode;
  621. sorry_val = answers[answer].sorry_value;
  622. incorrect_element.innerHTML = "<div style='color: red;'>" + incorrect_element.innerHTML + "</div>";
  623. answers[answer] = incorrect_element.getElementsByTagName('input')[0];
  624. answers[answer].sorry_value = sorry_val;
  625. answers[answer] = incorrect_element.getElementsByTagName('input')[0];
  626. }
  627. }
  628. var chosen_answer;
  629. chosen_answer = Math.floor(Math.random() * possible_answers.length);
  630. answers[possible_answers[chosen_answer]].click();
  631. } else {
  632. var pick = Math.floor(Math.random() * (Math.pow(2, answers.length) - 1)) + 1;
  633. for (i = 0; i < answers.length; i++) {
  634. if(pick & Math.pow(2, i)) {
  635. answers[i].click();
  636. }
  637. }
  638. }
  639. } else if (auto_answer == labels.auto_answer_first) {
  640. Object.values(sorted_objects_value)[0].click();
  641. }
  642. } break;
  643. case 'text': {
  644. answers = boxes;
  645. calculate_variant_hash();
  646. if (server_data.hasOwnProperty('correct')) {
  647. correct = server_data.correct[hash];
  648. }
  649. if (server_data.hasOwnProperty('correct')) {
  650. incorrect = server_data.incorrect[hash];
  651. }
  652. } break;
  653. }
  654. update_variant();
  655. for (i = 0; i < answers.length; i++) {
  656. answers[i].addEventListener('change', update_variant);
  657. }
  658. }
  659.  
  660. function result_page_handler() {
  661. var i;
  662. var correct = variant.slice(variant.indexOf("Число верных ответов: ") + 22);
  663. correct = correct.slice(0, correct.indexOf("\n")).trim();
  664. var test = GM_getValue('tests', new Object())[testID];
  665. if (test === undefined) {
  666. return;
  667. }
  668. var printer = "";
  669. var sorted_test = [];
  670. for (var hash in test) {
  671. sorted_test.push([hash].concat(test[hash]));
  672. }
  673. sorted_test.sort((a, b) => {return a[1] - b[1]});
  674. for (i = 0; i < sorted_test.length; i++) {
  675. printer += (config.get('append_question_number') ? (sorted_test[i][1] + ") ") : "") + sorted_test[i][0] + " " + sorted_test[i][2] + "\n";
  676. }
  677. printer += correct;
  678. if (config.get('copy_answers')) {
  679. GM_setClipboard(printer);
  680. }
  681. if (config.get('accumulator_enable')) {
  682. var acc = GM_getValue('accumulated_answers', "");
  683. if (acc != "") {
  684. acc += "\n\n";
  685. }
  686. var prefix = testID;
  687. if (prefix != "") {
  688. acc += prefix + "\n";
  689. }
  690. acc += printer;
  691. GM_setValue('accumulated_answers', acc);
  692. printer = acc;
  693. }
  694. printer = "<textarea readonly style='resize:none; width:fit-content; height:fit-content' rows='" + String(Object.keys(test).length + 1) + "' cols='50' onfocus='this.select();' id='answers'>" + printer + "</textarea>";
  695. var pboxes = document.getElementsByTagName('p');
  696. for (i = 0; i < pboxes.length; i++) {
  697. var pbox = pboxes[i];
  698. if (pbox.textContent.includes("Попытка ")) {
  699. pbox.outerHTML += printer;
  700. break;
  701. }
  702. }
  703. set_to_clear(testID, () => {
  704. send_to_server({
  705. type: "test_results",
  706. uid: config.get('user_id'),
  707. id: testID,
  708. answers: sorted_test,
  709. correct: correct,
  710. });
  711. });
  712. }
  713.  
  714. /* End Handlers */
  715.  
  716. function main() {
  717. var old_time, cur_time;
  718. variant = document.getElementById('w0').parentNode.textContent;
  719. if (variant.includes("Вопрос:")) {
  720. fetch_from_server(testID, (server_response) => {
  721. DB_cleaner();
  722. test_form_handler(server_response);
  723. if (config.get('auto_continue')) {
  724. old_time = config.get('auto_continue_time');
  725. cur_time = Date.now();
  726. if (cur_time - old_time > 60 * 60 * 1000) {
  727. config.set('auto_continue', false);
  728. } else {
  729. press_continue_btn();
  730. }
  731. }
  732. });
  733. } else if (variant.includes("Результат прохождения теста:")) {
  734. result_page_handler();
  735. if (config.get('auto_restart')) {
  736. old_time = config.get('auto_restart_time');
  737. cur_time = Date.now();
  738. if (cur_time - old_time > 60 * 60 * 1000) {
  739. config.set('auto_restart', false);
  740. } else {
  741. press_continue_btn();
  742. }
  743. }
  744. }
  745. }