NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Answers2 // @description Tooltip for questions // @match http://obispace.ru/obi_life/testing/my_tests/* // @match http://obispace.ru/obuchenie-i-razvitie-v-obi/testing/my_tests/* // @match https://obispace.ru/obi_life/testing/my_tests/* // @match https://obispace.ru/obuchenie-i-razvitie-v-obi/testing/my_tests/* // @updateURL https://openuserjs.org/meta/Runner2k11/Answers2.meta.js // @downloadURL https://openuserjs.org/install/Runner2k11/Answers2.user.js // @grant none // @version 2.05 // @license MIT // @run-at document-end // @copyright 2017, Runner2k11 (https://openuserjs.org/users/Runner2k11) // ==/UserScript== (function(){ const JSONfirst = 2; // 1 - urlJSON download first, 2 - urlJSON2 download first //QuestionsOrig - скаченные вопросы-ответы, QuestionsCurr - отвеченные в текущем тесте вопросы-ответы, Question - md5 текущего вопроса var QuestionsOrig = {}, QuestionsCurr = {}, Question; var localStorage; /* https://jsonbin.io/60645a7df2163e5ad3f698cf/1#mode=edit var urlJSON = "https://api.jsonbin.io/v3/b/60645a7df2163e5ad3f698cf"; var urlJSONsc = "$2b$10$P29/PZweSp/Ft9FRAKGbIOQn6PA2w7ufsPjHD65ud2U.CESD.j/1G"; */ //https://jsonbin.it/bins/ttppUpgC var urlJSON = "https://api.jsonbin.it/bins/ttppUpgC"; var urlJSON2URL = "https://jsonblob.com/f8b01e36-87d4-11eb-96ff-fb776697762b"; var urlJSON2 = "https://jsonblob.com/api/jsonBlob/f8b01e36-87d4-11eb-96ff-fb776697762b"; var bQALoaded = false; const WaitForAutoAnswer = 20000; const cNOk = 100; const cOk = 255; //const SearchURL = "http://www.google.ru/search?q="; const SearchURL = "https://yandex.ru/search/?text="; if (!String.prototype.trim) { (function() { // Вырезаем BOM и неразрывный пробел String.prototype.trim = function() { return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,''); }; })(); } if (!String.prototype.prepare) { (function() { // Общая подготовка строки String.prototype.prepare = function() { return this.toLowerCase().replace(/ /g,' ').replace(/\s+/g,' ').trim(); }; })(); } var md5 = new function() { var l='length', h=[ '0123456789abcdef',0x0F,0x80,0xFFFF, 0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476 ], x=[ [0,1,[7,12,17,22]], [1,5,[5, 9,14,20]], [5,3,[4,11,16,23]], [0,7,[6,10,15,21]] ], A=function(x,y,z){ return(((x>>16)+(y>>16)+((z=(x&h[3])+(y&h[3]))>>16))<<16)|(z&h[3]) }, B=function(s){ var n=((s[l]+8)>>6)+1,b=new Array(1+n*16).join('0').split(''); for(var i=0;i<s[l];i++)b[i>>2]|=s.charCodeAt(i)<<((i%4)*8); return(b[i>>2]|=h[2]<<((i%4)*8),b[n*16-2]=s[l]*8,b) }, R=function(n,c){return(n<<c)|(n>>>(32-c))}, C=function(q,a,b,x,s,t){return A(R(A(A(a,q),A(x,t)),s),b)}, F=function(a,b,c,d,x,s,t){return C((b&c)|((~b)&d),a,b,x,s,t)}, G=function(a,b,c,d,x,s,t){return C((b&d)|(c&(~d)),a,b,x,s,t)}, H=function(a,b,c,d,x,s,t){return C(b^c^d,a,b,x,s,t)}, I=function(a,b,c,d,x,s,t){return C(c^(b|(~d)),a,b,x,s,t)}, _=[F,G,H,I], S=(function(){ with(Math)for(var i=0,a=[],x=pow(2,32);i<64;a[i]=floor(abs(sin(++i))*x)); return a })(), X=function (n){ for(var j=0,s='';j<4;j++) s+=h[0].charAt((n>>(j*8+4))&h[1])+h[0].charAt((n>>(j*8))&h[1]); return s }; return function(s){ var $=B(''+s),a=[0,1,2,3],b=[0,3,2,1],v=[h[4],h[5],h[6],h[7]]; for(var i,j,k,N=0,J=0,o=[].concat(v);N<$[l];N+=16,o=[].concat(v),J=0){ for(i=0;i<4;i++) for(j=0;j<4;j++) for(k=0;k<4;k++,a.unshift(a.pop())) v[b[k]]=_[i]( v[a[0]], v[a[1]], v[a[2]], v[a[3]], $[N+(((j*4+k)*x[i][1]+x[i][0])%16)], x[i][2][k], S[J++] ); for(i=0;i<4;i++) v[i]=A(v[i],o[i]); };return X(v[0])+X(v[1])+X(v[2])+X(v[3]); }}; function addCss(cssString) { var head = document.getElementsByTagName('head')[0]; var newCss = document.createElement('style'); newCss.type = "text/css"; newCss.innerHTML = cssString; head.appendChild(newCss); } addCss( '.toast { line-height: 12px; background-color: #A0D0F0; ' + 'box-shadow: inset 0 0 0 1px rgba(255,255,255,0.5), 0 3px 6px -3px rgba(0,0,0,0.25); ' + 'text-shadow: 0 2px 2px rgba(255,255,255,1); ' + 'border: 1px solid #6090B0; border-radius: 7px; padding: 3px; font-size: 10px }' + '.toast:not(:last-child) { margin-bottom: 0.75rem; }' + '.toast_show { display: block; }' ); var Toast = function (element, config) { var _this = this, _element = element, _config = { autohide: true, delay: 5000 }; for (var prop in config) { _config[prop] = config[prop]; } Object.defineProperty(this, 'element', { get: function () { return _element; } }); Object.defineProperty(this, 'config', { get: function () { return _config; } }); } Toast.prototype = { show: function () { var _this = this; this.element.classList.add('toast_show'); if (this.config.autohide) { setTimeout(function () { _this.hide(); }, this.config.delay) } }, hide: function () { var event = new CustomEvent('hidden.toast', { detail: { toast: this.element } }); this.element.classList.remove('toast_show'); document.dispatchEvent(event); } }; Toast.create = function (text, color) { var fragment = document.createDocumentFragment(), toast = document.createElement('div'); toast.classList.add('toast'); toast.textContent = text; fragment.appendChild(toast); return fragment; }; Toast.add = function (params) { var config = { text: 'Текст сообщения...', autohide: true, delay: 10000 }; if (params !== undefined) { for (var item in params) { config[item] = params[item]; } } if (!document.querySelector('.toasts')) { var container = document.createElement('div'); container.classList.add('toasts'); //container.style.cssText = 'position: fixed; bottom: 50px; right: 1px; width: 190px'; container.style.cssText = 'position: fixed; bottom: 60px; right: 1px; width: 190px'; document.body.appendChild(container); } document.querySelector('.toasts').appendChild(Toast.create(config.text, config.color)); var toasts = document.querySelectorAll('.toast'); var toast = new Toast(toasts[toasts.length - 1], { autohide: config.autohide, delay: config.delay }); toast.show(); return toast; } document.addEventListener('hidden.toast', function (e) { var element = e.detail.toast; if (element) { element.parentNode.removeChild(element); } }); function MergeAnswers(a1, a2) { //a1 берём за основу Object.keys(a1).forEach(function(key, id) { if ( (key in a2) && (JSON.stringify(a1[key]) != JSON.stringify(a2[key])) ) { //если в a2 есть такой вопрос и содержимое разное var n = a2[key].length; for (var i = 1; i < n; i += 3) { var PosPresent = a1[key].indexOf(a2[key][i]); if ( PosPresent == -1 ) { //не было такого ответа - добавляем его полностью: текст, md5, статус a1[key] = a1[key].concat(a2[key].slice(i,i+3)); console.log('add answer to key: ' + key + ' < ' + a2[key].slice(i,i+3)); } else { //такой ответ был if (a1[key][PosPresent+1] < cNOk) { //и статус у него не cOk или сNOk if (a2[key][i+1]>a1[key][PosPresent+1]) { //то оставляем ответ с максимальным статусом: по числу попыток, cOk или CNOk a1[key][PosPresent+1] = a2[key][i+1]; console.log('change answer in key: ' + key + ' < ' + a2[key].slice(i,i+3)); } } } } //сортировка результата по статусу от большего к меньшему n = a1[key].length; for (i = 2; i < n - 3; i += 3) { var min = i; for (var j = i + 3; j < n; j += 3) { if (a1[key][min] < a1[key][j]) { min = j; } } if (min != i) { [a1[key][i-1], a1[key][min-1]] = [a1[key][min-1], a1[key][i-1]]; [a1[key][i], a1[key][min]] = [a1[key][min], a1[key][i]]; [a1[key][i+1], a1[key][min+1]] = [a1[key][min+1], a1[key][i+1]]; } } } }); //осталось добавить в базу вопросы-ответы, которых не было в a1 Object.keys(a2).forEach(function(key, id) { if ( !(key in a1) ) { a1[key] = a2[key]; console.log('add new key: ' + key); } }); return a1; } function LoadAA(callback) { function Finishing(req) { document.getElementById('svgAnswersCounter').style.display='none'; if (req.status == 200) { QuestionsOrig = ( typeof(req.response)=='string' ? JSON.parse(req.response) : req.response ); if (!(localStorage)) { window.localStorage.setItem('Answers2', JSON.stringify(QuestionsOrig)); } } else { if (localStorage) { QuestionsOrig = localStorage; } else { Toast.add({text: 'Data loading failed!'}); return false; } } if ((req.status == 200)&&(localStorage)) { if (QuestionsOrig.ID > localStorage.ID) { QuestionsOrig = MergeAnswers(QuestionsOrig, localStorage); } else { QuestionsOrig = MergeAnswers(localStorage, QuestionsOrig); } } callback(); } function getJSON1() { var req = new XMLHttpRequest(); req.timeout = 10000; req.open('GET', urlJSON, true); req.onreadystatechange = function() { if (req.readyState == 4) { console.log(urlJSON + ' - ' + (req.status == 200 ? 'Ok' : 'Fail')); Toast.add({text: 'DB1 download - ' + (req.status == 200 ? 'Ok' : 'Fail')}); if((req.status != 200)&&(JSONfirst==1)) { getJSON2(); } else { Finishing(req); } } }; req.send(); } function getJSON2() { var req = new XMLHttpRequest(); req.timeout = 10000; req.open('GET', urlJSON2, true); req.onreadystatechange = function() { if (req.readyState == 4) { console.log(urlJSON2 + ' - ' + (req.status == 200 ? 'Ok' : 'Fail')); Toast.add({text: 'DB2 download - ' + (req.status == 200 ? 'Ok' : 'Fail')}); if((req.status != 200)&&(JSONfirst==2)) { getJSON1(); } else { Finishing(req); } } }; req.send(); } ShowAnswersCount(); document.getElementById('svgAnswersCounter').style.display='block'; localStorage = JSON.parse(window.localStorage.getItem('Answers2')); Toast.add({text: 'LocalStorage download - ' + (localStorage ? 'Ok' : 'Fail')}); if (JSONfirst==1) { getJSON1(); } else { getJSON2(); } } function LoadQA() { function LoadQA_cb() { sessionStorage.setItem('QuestionsOrig', JSON.stringify(QuestionsOrig)); sessionStorage.setItem('QuestionsCurr', JSON.stringify(QuestionsCurr)); bQALoaded = true; ShowAnswersCount(); } if (1 == 2) { sessionStorage.removeItem('QuestionsOrig'); sessionStorage.removeItem('QuestionsCurr'); } if ( sessionStorage.getItem('QuestionsOrig') && sessionStorage.getItem('QuestionsCurr') ) { QuestionsOrig = JSON.parse(sessionStorage.getItem('QuestionsOrig')); QuestionsCurr = JSON.parse(sessionStorage.getItem('QuestionsCurr')); bQALoaded = true; ShowAnswersCount(); } else { LoadAA(LoadQA_cb); } } function AppendSaveJSON() { if (QuestionsOrig) { var blob = new Blob([JSON.stringify(QuestionsOrig)], {type: 'application/json'}) var url = window.URL.createObjectURL(blob) var link = document.createElement('a') link.href = url; link.setAttribute('download', "Answers2.json"); link.innerHTML = '↓'; link.title='Download Answers JSON'; document.getElementById('AnswersDL').appendChild(link); } } function AppendLoadJSON() { function readFile_cb() { sessionStorage.setItem('QuestionsOrig', JSON.stringify(QuestionsOrig)); sessionStorage.setItem('QuestionsCurr', JSON.stringify(QuestionsCurr)); bQALoaded = true; ShowAnswersCount(); } function readFile(object){ var file = object.target.files[0]; var reader = new FileReader(); reader.onload = function() { var json = JSON.parse(reader.result); json.ID = [Date.now()]; window.localStorage.setItem('Answers2', JSON.stringify(json)); LoadAA(readFile_cb); } reader.readAsText(file); } var fileInput = document.createElement("input"); fileInput.type='file'; fileInput.id='getFile'; fileInput.style='display:none'; fileInput.onchange=readFile; var link = document.createElement("a"); link.href="#"; link.setAttribute("onclick","document.getElementById('getFile').click(); return false;"); link.innerHTML='↑'; link.title='Upload Answers JSON'; document.getElementById('AnswersUL').appendChild(fileInput); document.getElementById('AnswersUL').appendChild(link); } function ShowAnswersCount() { var elems = document.getElementById('AnswersCounter'); if (!elems) { elems= document.body.appendChild(document.createElement('div')); elems.id = 'AnswersCounter'; } var j = 0; var j2 = 0; Object.keys(QuestionsOrig).forEach(function(key, id) { if (QuestionsOrig[key].includes(cOk) != 0) { j++; } else if (QuestionsOrig[key].includes(cNOk) != 0) { j2++; } }); AppendScript(MyScripts); elems.innerHTML = '<style type="text/css">.acounter td {padding: 1px 3px 1px 3px;} .acountersvg {position: absolute; top: -3px; left: 7px; display: none;}</style>' + '<span style="z-index: 999; line-height: 12px; position: fixed; bottom: 1px; right: 1px; background-color: #A0D0F0; ' + 'box-shadow: inset 0 0 0 1px rgba(255,255,255,0.5), 0 3px 6px -3px rgba(0,0,0,0.25); ' + 'text-shadow: 0 2px 2px rgba(255,255,255,1); ' + 'border: 1px dashed #6090B0; border-radius: 7px; padding: 3px; text-align:center;">' + '<span style="font-size: 10px; font-weight: bold; color: red;">' + '<table class="acounter"><tr><td rowspan="2">' + 'Answers<br>v' + GM_info.script.version + '</td><td rowspan="2"><a href=\'#\' onClick="ToggleAA(); return false;">Auto<br>' + (sessionStorage.getItem('AutoAnswer') ? 'on' : 'off') + '</a></td>' + '<td><font color="green">Ok</font></td><td><font color="brown">???</font></td><td>NOk</td><td><font color="black">All</font></td></tr><tr>' + '<td><font color="green">' + j + '</font></td><td><font color="brown">' + (Object.keys(QuestionsOrig).length - j - j2) + '</font></td><td>' + j2 + '</td><td><font color="black">' + Object.keys(QuestionsOrig).length + '</font></td></tr></table></span>' + '<span style="font-size: 9px; float: center;">DB: ' + (QuestionsOrig.ID ? '<a href="' + urlJSON2URL + '" target="_blank">' + dateFormat(QuestionsOrig.ID[0], "dd/mm/yyyy HH:MM") + '</a>' : 'Loading now...') + '</span>' + '<span id="AnswersDL" style="float:left"></span>' + '<span id="AnswersUL" style="float:right"></span>' + '<span id="svgAnswersCounter" class="acountersvg">' + '<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 50 50"><path fill="#00AF00" d="M24.9 44a18.7 18.7 0 1 0 0-37.4v4a14.6 14.6 0 0 1 0 29.3v4z"><animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite"/></path></svg>' + '</span></span>'; AppendLoadJSON(); if (bQALoaded) AppendSaveJSON(); } function AppendScript(s) { document.head.appendChild(document.createElement('script')) .innerHTML = s.toString().replace(/^function.*{|}$/g, ''); } function MyScripts() { function ToggleAA() { if(sessionStorage.getItem('AutoAnswer')){ sessionStorage.removeItem('AutoAnswer'); }else{ sessionStorage.setItem('AutoAnswer', 'true'); } window.location.reload(); } } function SetAutoAnswer(AutoCheck) { if(sessionStorage.getItem('AutoAnswer')){ setTimeout(function(){AutoAnswer(AutoCheck)}, Math.floor(Math.random() * WaitForAutoAnswer * 0.75 + WaitForAutoAnswer * 0.5)); } } function AutoAnswer(AutoCheck) { if (AutoCheck) { var elems = document.getElementsByClassName('b-question-list__item')[0].getElementsByClassName('b-answer-list__item'); for (var i = 0; i < elems.length; i++) { if (elems[i].innerHTML.indexOf('_Ok:') != -1) { elems[i].getElementsByTagName('input')[0].checked = false; elems[i].getElementsByTagName('input')[0].click(); } } } elems = document.getElementById('test_questinos'); if (elems) { elems = elems.getElementsByClassName('b-submit'); var AutoOff = true; for (i = 0; i < elems.length; i++) { if (elems[i].innerHTML.toLowerCase().indexOf('далее') != -1) { setTimeout(function(){ elems[i].click(); }, 2000); AutoOff = false; break; } } if (AutoOff) { sessionStorage.removeItem('AutoAnswer'); } } } function SetOnClick() { var elems = document.getElementById('test_questinos'); if (elems) { elems = elems.getElementsByClassName('b-submit'); for (var i = 0; i < elems.length; i++) { elems[i].onclick = function() { var elems = document.getElementById('test_questinos').getElementsByClassName('checked'); if (elems.length != 0) { for (var i = 0; i < elems.length; i++) { if (elems[i].tagName == 'LABEL') { var s = elems[i].innerHTML.replace(/Q.*:/,'').replace(/<[^>]+>/g,'').replace(/ /g,' ').replace(/\s+/g,' ').trim(); var Answer_str = (Answer_str ? Answer_str + '++' : '') + s; var Answer_md5 = (Answer_md5 ? Answer_md5 + '++' : '') + md5(s.toLowerCase()); } } QuestionsCurr[Question][1] = Answer_md5; QuestionsCurr[Question][3] = Answer_str; } else { delete QuestionsCurr[Question]; } sessionStorage.setItem('QuestionsCurr', JSON.stringify(QuestionsCurr)); } } } } function FindQuestions() { function SetStyleAnswer(elems, mode) { elems.style.fontWeight = "bold" switch (mode) { case cOk: elems.style.backgroundColor = "#90EE90"; elems.style.color = "green"; var headAnswer = 'Q_Ok: '; break; case cNOk: elems.style.backgroundColor = "red"; headAnswer = 'Q_NOk: '; break; default: elems.style.backgroundColor = "yellow"; headAnswer = 'Q_?' + QuestionsOrig[Question][i2+1] + '?: '; } return headAnswer; } function FormatAnswer(elems, mode) { var wwwAnswer = elems.innerHTML.replace(/<[^>]+>/g,'').trim(); var wwwPos = elems.innerHTML.indexOf(wwwAnswer); elems.innerHTML = elems.innerHTML.substring(0,wwwPos) + SetStyleAnswer(elems, mode) + wwwAnswer + elems.innerHTML.substring(wwwPos + wwwAnswer.length); } var elems = document.getElementsByClassName('b-question-list__item'); if (elems) { SetOnClick(); for (var i = 0; i < elems.length; i++) { var Question_txt = elems[i].innerHTML.split('<')[0]; elems[i].innerHTML = elems[i].innerHTML.substring(0,elems[i].innerHTML.indexOf(Question_txt)) + '<a class="b-link b-h0" href="' + SearchURL + Question_txt.replaceAll('"','') + '" target="_blank">' + Question_txt + '</a>' + elems[i].innerHTML.substring(elems[i].innerHTML.indexOf(Question_txt) + Question_txt.length); Question_txt = Question_txt.replace(/ /g,' ').replace(/\s+/g,' ').trim(); Question = md5(Question_txt.toLowerCase().replace(/[^0-9а-яa-z]/g,"")); if ( !(Question in QuestionsCurr) ) { QuestionsCurr[Question] = [Question_txt, '', cOk, '']; sessionStorage.setItem('QuestionsCurr', JSON.stringify(QuestionsCurr)); } if ( Question in QuestionsOrig ) { var elems2 = elems[0].getElementsByClassName('b-answer-list__item'); var SingleSelectAnswer = elems2[0].getElementsByTagName('input')[0].type == 'radio'; var Found = false; for (var i2 = 1; i2 < QuestionsOrig[Question].length; i2 += 3) { var arrAnswers = QuestionsOrig[Question][i2].split('++'); var ff = 0; for (var ii = 0; ii < elems2.length; ii++) { ff += arrAnswers.indexOf(md5(elems2[ii].innerHTML.replace(/<[^>]+>/g,'').prepare())) != -1; } if (ff == arrAnswers.length) { //подходящий ответ найден for (ii = 0; ii < elems2.length; ii++) { if ( arrAnswers.indexOf(md5(elems2[ii].innerHTML.replace(/<[^>]+>/g,'').prepare())) != -1 ) { FormatAnswer(elems2[ii], QuestionsOrig[Question][i2+1]); } } /* Single Multi cOk F B F B cNok B c? B F - Found=true, B - need break */ Found = (QuestionsOrig[Question][i2+1] == cOk); if ((Found)||(!SingleSelectAnswer)) break; } } if ( !Found ) { for (i2 = 1; i2 < QuestionsOrig[Question].length; i2 += 3) { elems2 = elems[i].appendChild(document.createElement('span')); SetStyleAnswer(elems2, QuestionsOrig[Question][i2+1]); elems2.innerHTML = '<br><br>' + (QuestionsOrig[Question][i2+2] == '' ? 'old style answer' : QuestionsOrig[Question][i2+2].replaceAll('++',' &&<br>')); } } SetAutoAnswer(Found); } else { elems[i].innerHTML += '<br><font color="red">Вопрос отсутствует в базе =(</font>'; SetAutoAnswer(false); } } } } function UpdateQA(a1, a2) { function UpdateQA_cb() { QuestionsOrig.ID = [Date.now()]; //Обновляем ответы в основной базе. На входе: //QuestionsOrig - актуальная база с сервера, QuestionsCurr - вопросы-ответы с текущего теста и статусом их правильности //a1 - число правильных ответов, a2 - число неправильных ответов //В процессе обработки: b1 - рассчитанное число правильных ответов в QuestionOrig //если a1 будет равно b1, то значит все остальные ответы (со статусом '1') будут неверными var b1 = 0; Object.keys(QuestionsCurr).forEach(function(key, id) { console.log(QuestionsCurr); console.log('---begin--------------------'); console.log('key: ' + key); console.log('Orig >'); console.log(QuestionsOrig[key]); console.log('Curr >'); console.log(QuestionsCurr[key]); if ( !(key in QuestionsOrig) ) { //если такого вопроса ранее не было, то просто добавляем QuestionsOrig[key] = QuestionsCurr[key]; } else { //если такой вопрос уже был, то: //обновляем текст вопроса QuestionsOrig[key][0] = QuestionsCurr[key][0]; var PosPresent = QuestionsOrig[key].indexOf(QuestionsCurr[key][1]); if ( PosPresent == -1 ) { //не было такого ответа - добавляем его полностью: текст, md5, статус QuestionsOrig[key] = QuestionsOrig[key].concat(QuestionsCurr[key].slice(1)); } else { //такой ответ был, обновляем его текст QuestionsOrig[key][PosPresent+2] = QuestionsCurr[key][3]; if ( QuestionsCurr[key][2] != 1 ) { //если текущий статус не '1' (соответственно это или cOk, или cNOk), то и записываем его в базу QuestionsOrig[key][PosPresent+1] = QuestionsCurr[key][2]; } else { //в противном случае, если в базе статус не cOk или cNOk, то увеличиваем его на 1 QuestionsOrig[key][PosPresent+1] += (QuestionsOrig[key][PosPresent+1] < 8 ? 1 : 0); } } } console.log('Orig result >'); console.log(QuestionsOrig[key]); console.log('------------------------------end---'); //считаем сколько всего в результате стало правильных ответов PosPresent = QuestionsOrig[key].indexOf(QuestionsCurr[key][1]); b1 += (QuestionsOrig[key][PosPresent+1] == cOk ? 1 : 0); }); Object.keys(QuestionsCurr).forEach(function(key, id) { //если число правильных ответов по тесту совпадает с посчитанным в Orig, то можем вычислить, какие ответы были не правильными if ( (a2 != 0) && (a1 == b1) ) { var PosPresent = QuestionsOrig[key].indexOf(QuestionsCurr[key][1]); if (QuestionsOrig[key][PosPresent+1] < 10) { console.log('Key: ' + key + ' Pos: ' + PosPresent + ' -- вычисленный NOk!'); QuestionsOrig[key][PosPresent+1] = cNOk; } } //для упрощения в дальнейшем процесса поиска ответа, сортируем массив ответов по статусу cOk -> cNOk -> ... var n = QuestionsOrig[key].length; for (var i = 2; i < n - 3; i += 3) { var min = i; for (var j = i + 3; j < n; j += 3) { if (QuestionsOrig[key][min] < QuestionsOrig[key][j]) { min = j; } } if (min != i) { [QuestionsOrig[key][i-1], QuestionsOrig[key][min-1]] = [QuestionsOrig[key][min-1], QuestionsOrig[key][i-1]]; [QuestionsOrig[key][i], QuestionsOrig[key][min]] = [QuestionsOrig[key][min], QuestionsOrig[key][i]]; [QuestionsOrig[key][i+1], QuestionsOrig[key][min+1]] = [QuestionsOrig[key][min+1], QuestionsOrig[key][i+1]]; } } }); sessionStorage.setItem('QuestionsOrig', JSON.stringify(QuestionsOrig)); /* var req = new XMLHttpRequest(); req.open('POST', urlJSON, true); req.setRequestHeader('Content-type', 'application/json'); req.setRequestHeader('Access-Control-Allow-Origin', '*'); req.onload = function () { console.log('DB1 save - status:' + req.status); Toast.add({text: 'DB1 save - status:' + req.status}); } req.send(JSON.stringify(QuestionsOrig)); */ var req2 = new XMLHttpRequest(); req2.open('PUT', urlJSON2, true); req2.setRequestHeader('Content-type', 'application/json'); req2.onload = function () { console.log('DB2 save - status:' + req2.status); Toast.add({text: 'DB2 save - status:' + req2.status}); } req2.send(JSON.stringify(QuestionsOrig)); window.localStorage.setItem('Answers2', JSON.stringify(QuestionsOrig)); Toast.add({text: 'LocalStorage save - Ok'}); ShowAnswersCount(); } if (Object.keys(QuestionsCurr).length > 0) {LoadAA(UpdateQA_cb);} } function CheckResult() { //до этого по умолчанию все ответы заранее были со статусом cOk if ( Object.keys(QuestionsCurr).length > 0 ) { var i; var a1 = 0; var a2 = 0; //поиск списка неверных ответов try { var elems = document.getElementsByClassName('b-question-list')[0].getElementsByTagName('li'); } catch (e) { } if (elems) { //есть список неверных ответов for (i = 0; i < elems.length; i++) { //сначала проверим, что на такой вопрос мы отвечали (а, например, не пропустили) и если да, то ставим статус NOk if (md5(elems[i].innerHTML.prepare().replace(/[^0-9а-яa-z]/g,"")) in QuestionsCurr) {QuestionsCurr[md5(elems[i].innerHTML.prepare().replace(/[^0-9а-яa-z]/g,""))][2] = cNOk;} } sessionStorage.setItem('QuestionsCurr', JSON.stringify(QuestionsCurr)); } else { //если списка нет, например, при успешной сдаче, и результат не 100%, то выставляем 1 - точно неизвестно какие ответы верные, какие нет elems = document.getElementsByClassName('b-result-test__input'); if ( (!elems) || (Number(String(elems[0].value).replace('%','')) != 100) ) { //операторы && и || - операторы короткого замыкания, где правая часть не вычисляется, если слева уже однозначное решение по if Object.keys(QuestionsCurr).forEach(function(key, id) { QuestionsCurr[key][2] = 1; }); sessionStorage.setItem('QuestionsCurr', JSON.stringify(QuestionsCurr)); //достаём a1 и a2, вдруг далее получится косвенно, по числу имеющихся правильных ответов, вычислить неправильные elems = document.getElementsByClassName('b-result-test__answer_count'); a1 = (elems[0] ? elems[0].innerHTML : 0); //число правильных ответов a2 = (elems[1] ? elems[1].innerHTML : 0); //число неправильных ответов } } UpdateQA(a1, a2); //sessionStorage.removeItem('QuestionsOrig'); sessionStorage.setItem('QuestionsCurr', '{}'); } } function RunOnQALoad(call) { if (!bQALoaded) { setTimeout(function(){RunOnQALoad(call)},300); return false; } call(); } function Refakt() { UpdateQA(); } //проверка базы на пустые md5 function CheckForEmpty_md5() { Object.keys(QuestionsOrig).forEach(function(key, id) { var n = QuestionsOrig[key].length; for (var i = 1; i < n; i += 3) { if (QuestionsOrig[key][i] == '') {console.log(key)}; } }); } function chunk(arr, chunkSize) { var R = []; arr = Object.entries(arr); for (var i=0,len=arr.length; i<len; i+=chunkSize) R.push(arr.slice(i,i+chunkSize)); return R; } function unchunk(arr) { var R = []; for (var i=0,len=arr.length; i<len; i++) R.push(...arr[i]); return Object.fromEntries(R); } function tst() { var d = chunk(QuestionsOrig,200); console.log(d); //for (var i=0,len=d.length; i<len; i++) // console.log(JSON.stringify(Object.fromEntries(d[i]))); //console.log(unchunk(chunk(Object.entries(QuestionsOrig),200))); } //RunOnQALoad(tst); LoadQA(); //RunOnQALoad(Refakt); //RunOnQALoad(CheckForEmpty_md5); var href_locase = window.location.href.toLowerCase(); if (href_locase.indexOf("obuchenie-i-razvitie-v-obi") == -1) { //TestID = parseInt(href_locase.split('test_id=')[1]).toString(36) + '$'; if ((href_locase.indexOf("attempt") == -1)||(href_locase.indexOf("init_attempt=y") != -1)) { RunOnQALoad(FindQuestions); }else{ sessionStorage.removeItem('AutoAnswer'); //отключаем автоклик RunOnQALoad(CheckResult); } } })();