From 692c41bb7f560e2cf32b92463b271058d75fc634 Mon Sep 17 00:00:00 2001 From: MrFry Date: Sat, 25 Jan 2020 17:37:24 +0100 Subject: [PATCH] Bug fixes, logic polishing --- stable.user.js | 404 ++++++++++--------------------------------------- 1 file changed, 81 insertions(+), 323 deletions(-) diff --git a/stable.user.js b/stable.user.js index be24012..51e070a 100755 --- a/stable.user.js +++ b/stable.user.js @@ -62,7 +62,7 @@ // forcing pages for testing. unless you test, do not set these to true! // only one of these should be true for testing - const forceTestPage = true + const forceTestPage = false const forceResultPage = false const forceDefaultPage = false const logElementGetting = false @@ -110,7 +110,6 @@ const commonUselessStringParts = [',', '\\.', ':', '!', '\\+'] const specialChars = [ '&', '\\+' ] const lengthDiffMultiplier = 10 /* Percent minus for length difference */ - const notSameDataTypePenalty = 30 // substracted from match percent if 2 questions are not same type const assert = (val) => { if (!val) { throw new Error('Assertion failed') } @@ -270,85 +269,6 @@ const SUtils = new StringUtils() - class Question { - constructor (q, a, data) { - this.Q = SUtils.SimplifyQuestion(q) - this.A = SUtils.SimplifyAnswer(a) - this.data = { ...data } - } - - toString () { - if (this.data.type !== 'simple') { - return '?' + this.Q + '\n!' + this.A + '\n>' + JSON.stringify(this.data) - } else { - return '?' + this.Q + '\n!' + this.A - } - } - - HasQuestion () { - return this.Q !== undefined - } - - HasAnswer () { - return this.A !== undefined - } - - HasImage () { - return this.data.type === 'image' - } - - IsComplete () { - return this.HasQuestion() && this.HasAnswer() - } - - CompareToQuestionObj (q2) { - const qmatchpercent = SUtils.CompareString(this.Q, q2.Q) - const amatchpercent = SUtils.CompareString(this.A, q2.A) - if (this.data.images !== undefined) { - const imatchpercent = this.data.images === undefined ? SUtils.CompareString(this.data.images.join(' '), q2.data.images.join( - ' ')) : 0 - return (qmatchpercent + amatchpercent + imatchpercent) / 3 - } else { - return (qmatchpercent + amatchpercent) / 2 - } - } - - CompareImage (data2) { - return SUtils.CompareString(this.data.images.join(' '), data2.images.join(' ')) - } - - CompareToQuestionString (q2, data) { - assert(data) - - let qmatchpercent = SUtils.CompareString(this.Q, q2) - let dataMatchPercent = 0 - - if (data.type === this.data.type) { // both questins are same type - if (data.type === 'simple') { - return qmatchpercent - } else if (data.type === 'image') { - dataMatchPercent = this.CompareImage(data) - } - - return (qmatchpercent + dataMatchPercent) / 2 - } else { // question types are not the same - dataMatchPercent = 0 - qmatchpercent -= notSameDataTypePenalty - if (qmatchpercent < 0) { return 0 } else { return qmatchpercent } - } - } - - Compare (q2, data) { - assert(q2) - - if (typeof q2 === 'string') { - return this.CompareToQuestionString(q2, data) - } else { - return this.CompareToQuestionObj(q2) - } - } - } - // : }}} // : DOM getting stuff {{{ @@ -713,7 +633,9 @@ for (let j = 0; j < items.length; j++) { let cn = items[j].className - if (cn.includes('correct') && !cn.includes('incorrect')) { return items[j].innerText } + if (cn.includes('correct') && !cn.includes('incorrect')) { + return items[j].getElementsByTagName('label')[0].innerText + } } if (items.length === 2) { for (let j = 0; j < items.length; j++) { @@ -801,6 +723,7 @@ if (forceTestPage || forceResultPage || forceDefaultPage) { if (document.getElementById('scriptMessage')) { document.getElementById('scriptMessage').style.background = 'green' } } + ShowMenuList() // TODO: remove } // : }}} @@ -838,9 +761,10 @@ } VersionActions() if (!url.includes('.pdf')) { ShowMenu() } - GetXHRVersion().then((version) => { - lastestVersion = version - cwith(version) + GetXHRInfos().then((inf) => { + lastestVersion = inf.version + motd = inf.motd + cwith() }) } @@ -882,17 +806,11 @@ } var greetMsg = '' // message to show at the end var timeout = null // the timeout. if null, it wont be hidden - // no new version, nothing loaded - var showSplash = (getVal('showSplash') === undefined) || getVal('showSplash') // getting value, if splash screen should be shown. Its true, if its undefined, or true - // no new version, everything loaded, and show splash is enabled. otherwise something happened, so showing it - if (!newVersion && showSplash) { // ------------------------------------------------------------------------------------------------ + if (lastestVersion !== undefined && info().script.version !== lastestVersion) { timeout = 5 greetMsg = 'Moodle/Elearning/KMOOC segéd v. ' + info().script.version + '. ' - - if (lastestVersion !== undefined && info().script.version !== lastestVersion) { - greetMsg += 'Új verzió elérhető: ' + lastestVersion + '\n' - timeout = undefined - } + greetMsg += 'Új verzió elérhető: ' + lastestVersion + timeout = undefined } if (newVersion) { // -------------------------------------------------------------------------------------------------------------- greetMsg = 'Moodle/Elearning/KMOOC segéd v. ' + info().script.version + '. Verzió frissítve ' + info().script.version + '-re. Changelog:\n' + texts.lastChangeLog @@ -936,19 +854,17 @@ var imgNodes = q.imgnodes // ------------------------------------------------------------------------------------------------------ let promises = [] - // TODO: test multiple promises questions.forEach((x) => { let question = SUtils.EmptyOrWhiteSpace(x) ? '' : SUtils.RemoveUnnecesarySpaces(x) // simplifying question promises.push(GetXHRQuestionAnswer({ q: question, data: GetImageDataFromImgNodes(imgNodes), - subj: '' // MPM.GetCurrentSubjectName() // TODO: set subj to '' if no result as backup plan + subj: MPM.GetCurrentSubjectName() })) }) - // TODO: check answer order! + // FIXME: promise.all promise resolve order same as original? Promise.all(promises).then((res) => { - console.log('All data recieved', res) // TODO: delete let answers = [] res.forEach((result, j) => { @@ -1007,30 +923,26 @@ // : Quiz saving {{{ function HandleResults (url) { - var d = SaveQuiz(GetQuiz()) // saves the quiz questions and answers - - if (d) { ShowSaveQuizDialog(d.addedQ, d.allQ, d.allOutput, d.output, d.sendSuccess, d.sentData) } + SaveQuiz( + GetQuiz(), + ShowSaveQuizDialog + ) // saves the quiz questions and answers } - function ShowSaveQuizDialog (addedQ, allQ, allOutput, output, sendSuccess, sentData) { + function ShowSaveQuizDialog (sendResult, sentData, newQuestions) { // FIXME: normal string building with localisation :/ var msg = '' - if (addedQ > 0) { - msg = 'Klikk ide a nyers adatokhoz. ' + addedQ + ' új kérdés!' - - if (!sendSuccess) { msg += ' Nem sikerült kérdéseket elküldeni szervernek. Ha gondolod utánanézhetsz.' } else { msg += 'Az új kérdések elküldve.' } + if (sendResult) { + msg = 'Kérdések elküldve, katt az elküldött adatokért. ' + newQuestions + ' új kérdés' } else { - msg = 'A kérdőívben nincsen új kérdés. Ha mégis le akarod menteni klikk ide.' - // TODO if (!data) { msg += ' Lehet azért, mert nincs kérdés betöltve.' } + msg = 'Szerver nem elérhető, vagy egyéb hiba kérdések elküldésénél! (F12 -> Console)' } // showing a message wit the click event, and the generated page ShowMessage({ m: msg, isSimple: true }, null, function () { - var towrite = '

' + sentData.subj + '
TXT-ben nem szereplő kérdések: ' + addedQ + '/' + allQ + '


' + output.replace(/\n/g, '
') + '

Összes kérdés/válasz:

' + allOutput.replace( - /\n/g, '
') - + let towrite = '' try { towrite += '

Elküldött adatok:

' + JSON.stringify(sentData) } catch (e) { @@ -1086,32 +998,12 @@ } // saves the current quiz. questionData contains the active subjects questions - function SaveQuiz (quiz) { + function SaveQuiz (quiz, next) { try { + let sentData = {} if (quiz.length === 0) { throw new Error('quiz length is zero!') } - var output = '' // thefinal output - var allOutput = '' // thefinal output with all questions - var allQ = 0 - var addedQ = 0 - var newQuestions = [] - for (var i = 0; i < quiz.length; i++) { - // searching for same questions in questionData - var toAdd = '' // this will be added to some variable depending on if its already in the database - toAdd += '?' + SUtils.RemoveUnnecesarySpaces(quiz[i].Q) + '\n' // adding quiz question - toAdd += '!' + SUtils.RemoveUnnecesarySpaces(quiz[i].A) + '\n' // adding quiz answer - // TODO: hasimage - // if (quiz[i].HasImage()) { - // let imgString = quiz[i].data.images.join(', ') - // toAdd += '>' + imgString + '\n' // adding quiz image if there is any - // } - // TODO: search same question removed - allOutput += toAdd // adding to all - allQ++ - } - var sendSuccess = false - var sentData = {} try { try { sentData.subj = MPM.GetCurrentSubjectName() @@ -1119,24 +1011,16 @@ sentData.subj = 'NOSUBJ' Log('unable to get subject name :c') } - sentData.allData = quiz - sentData.data = newQuestions sentData.version = info().script.version sentData.id = GetId() + sentData.quiz = quiz Log('SENT DATA', sentData) - SendXHRMessage('datatoadd=' + JSON.stringify(sentData)) - sendSuccess = true + SendXHRMessage('datatoadd=' + JSON.stringify(sentData)).then((res) => { + next(res.success, sentData, res.newQuestions) + }) } catch (e) { Exception(e, 'error at sending data to server.') } - return { - addedQ: addedQ, - allQ: allQ, - allOutput: allOutput, - output: output, - sendSuccess: sendSuccess, - sentData: sentData - } } catch (e) { Exception(e, 'script error at saving quiz') } @@ -1151,17 +1035,17 @@ var question = {} // the current question // QUESTION -------------------------------------------------------------------------------------------------------------------- var q = RPM.GetQuestionFromResult(i) - if (q !== undefined) { question.q = SUtils.SimplifyQuestion(q) } + if (q !== undefined) { question.Q = SUtils.SimplifyQuestion(q) } // RIGHTANSWER --------------------------------------------------------------------------------------------------------------------- var a = RPM.GetRightAnswerFromResultv2(i) if (a === undefined) { a = RPM.GetRightAnswerFromResult(i) } - if (a !== undefined) { question.a = SUtils.SimplifyAnswer(a) } + if (a !== undefined) { question.A = SUtils.SimplifyAnswer(a) } // DATA --------------------------------------------------------------------------------------------------------------------- question.data = GetDataFormResult(i) - if (question.a !== undefined) { - quiz.push(new Question(question.q, question.a, question.data)) // adding current question to quiz + if (question.A !== undefined) { + quiz.push(question) // adding current question to quiz } else { Log('error getting queston, no correct answer given, or its incorrect') Log(question) @@ -1323,7 +1207,7 @@ var simpleMessageText = '' if (msgItem.isSimple) { // parsing msgItem for easier use simpleMessageText = msgItem.m - if (simpleMessageText === '') { + if (simpleMessageText === '') { // if msg is empty return } msgItem = [ @@ -1534,7 +1418,7 @@ var menuButtonDiv = document.createElement('div') SetStyle(menuButtonDiv, { width: buttonWidth + 'px', - height: buttonHeight + 'px', + // height: buttonHeight + 'px', top: (window.innerHeight - buttonHeight * 1.5) + 'px', left: window.innerWidth - buttonWidth * 1.5 + 'px', zIndex: 999999, @@ -1644,167 +1528,17 @@ width: '98%' }) - // if (data && data.length > 0) { - // let grouped = data.Subjects.reduce((res, s) => { - // let sName = s.getSubjNameWithoutYear() - // if (sName) { - // if (!res[sName]) { - // res[sName] = [] - // } - // res[sName].push(s) - // } else { - // res.others.push(s) - // } - // return res - // }, { - // others: [] - // }) + var scrollDiv = document.createElement('div') + scrollDiv.appendChild(subjTable) + scrollDiv.style.textAlign = 'center' + var subjtblrow = tbl.insertRow() + var subjtbltd = subjtblrow.insertCell() + subjtbltd.appendChild(scrollDiv) - // const ordered = {} - // Object.keys(grouped).sort().forEach((key) => { - // ordered[key] = grouped[key] - // }) - - // grouped = ordered - - // let collapsibles = [] - - // // -------------------------------------------------------------------------------- - // let searchBar = CreateNodeWithText(subjTable, '', 'input') - // SetStyle(searchBar, { - // backgroundColor: '#222d32', - // color: '#ffffff', - // width: '100%', - // border: 'none' - // }) - // searchBar.placeholder = texts.search - // searchBar.addEventListener('keyup', function (e) { - // collapsibles.forEach((x) => { - // if (x.innerText.toLowerCase().includes(this.value.toLowerCase())) { - // x.style.display = '' - // } else { - // x.style.display = 'none' - // } - // }) - // }) // adding click - - // Object.entries(grouped).forEach(([subjName, subjGroup], i) => { - // let b = CreateNodeWithText(subjTable, subjName, 'div') - // SetStyle(b, { - // backgroundColor: '#222d32', - // color: '#ffffff', - // cursor: 'pointer', - // padding: '5px', - // width: '100%', - // border: 'none', - // textAlign: 'left', - // outline: 'none' - // }) - // b.setAttribute('id', 'subjectGroup' + i) - // collapsibles.push(b) - - // let content = document.createElement('div') - // SetStyle(content, { - // padding: '0 18px', - // overflow: 'hidden', - // backgroundColor: '#222d32', - // borderColor: '#212127', - // borderStyle: 'solid', - // borderWidth: '2px' - // }) - // content.addEventListener('click', function (e) { - // e.stopPropagation() - // }) - - // let ifGroupActive = subjGroup.some((x) => { - // return x.getIfActive() - // }) - // content.style.display = ifGroupActive ? 'block' : 'none' - - // b.appendChild(content) - - // let tbl = document.createElement('table') - // content.appendChild(tbl) - // subjGroup.forEach((subj) => { - // var row = tbl.insertRow() - // let td = row.insertCell() - // let text = subj.getYear() || subj.Name - // if (subj.length !== 0) { text += ' [ ' + subj.length + 'db ]' } - // CreateNodeWithText(td, text) - - // td = row.insertCell() - // let checkbox = document.createElement('input') // new paragraph - // checkbox.type = 'checkbox' - // checkbox.style.background = 'white' - // checkbox.style.margin = '5px 5px 5px 5px' // fancy margin - // td.appendChild(checkbox) // adding text box to main td - - // checkbox.checked = subj.active - // let i = subj.getIndex() - // checkbox.setAttribute('id', 'HelperTextNode' + i) - // checkbox.addEventListener('click', function () { - // var checked = document.getElementById('HelperTextNode' + i).checked - // data.ChangeActive(subj.Name, checked) - // }) // adding click - // }) - - // b.addEventListener('click', function (e) { - // this.classList.toggle('active') - // if (content.style.display === 'block') { - // content.style.display = 'none' - // } else { - // content.style.display = 'block' - // } - // }) - // }) - - // var scrollDiv = document.createElement('div') - // scrollDiv.style.width = '100%' - // scrollDiv.style.height = window.innerHeight - (window.innerHeight * 0.4) + 'px' - // scrollDiv.style.overflow = 'auto' - - // scrollDiv.appendChild(subjTable) - - // var subjtblrow = tbl.insertRow() - // var subjtbltd = subjtblrow.insertCell() - // subjtbltd.appendChild(scrollDiv) - // } else { // if no data - // var noDataRow = tbl.insertRow() - // var noDataRowCell = noDataRow.insertCell() - // let textBox - - // if (getVal('skipLoad')) { - // textBox = CreateNodeWithText(noDataRowCell, - // texts.passiveModeActivePopupMenuText - // ) - // } else { - // textBox = CreateNodeWithText(noDataRowCell, - // texts.couldntLoadDataPopupMenuText - // ) - // } - // textBox.style.margin = fiveMargin // fancy margin - // } - - // show splash tickbox ----------------------------------------------------------------------------------------------------------------------------- - var splasTickboxRow = tbl.insertRow() - var splashTickboxCell = splasTickboxRow.insertCell() - - var splashTickBox = document.createElement('input') - SetStyle(splashTickBox, { - position: '', - left: 10 + 'px', - margin: '5px 5px 5px 5px', - top: menuDiv.offsetHeight + 'px' + // TODO: something in menubox + GetXHRSubjCount(true).then((res) => { + CreateNodeWithText(scrollDiv, `${res.subjects} tárgy, ${res.questions} kérdés`, 'div') }) - splashTickBox.type = 'checkbox' - splashTickBox.checked = getVal('showSplash') || false - splashTickboxCell.appendChild(splashTickBox) // adding to main div - - splashTickBox.addEventListener('click', function () { - setVal('showSplash', splashTickBox.checked) - }) // adding clicktextNode - - CreateNodeWithText(splashTickboxCell, texts.showGreetingOnEveryPage, 'span') // setting up buttons var buttonRow = tbl.insertRow() @@ -1910,12 +1644,30 @@ return paragraphElement } - function GetXHRVersion () { + function GetXHRSubjCount () { + let url = 'datacount' return new Promise((resolve, reject) => { xmlhttpRequest({ method: 'GET', - url: serverAdress + 'version', + url: serverAdress + url, onload: function (response) { + resolve(JSON.parse(response.responseText)) + }, + onerror: (e) => { + console.log('GET ERROR', e) + reject(new Error('get error')) + } + }) + }) + } + + function GetXHRInfos () { + return new Promise((resolve, reject) => { + xmlhttpRequest({ + method: 'GET', + url: serverAdress + 'infos?version=true&motd=true', + onload: function (response) { + // resolve(JSON.parse(response.responseText)) resolve(response.responseText) }, onerror: (e) => { @@ -1927,7 +1679,6 @@ } function GetXHRQuestionAnswer (question) { - console.log('sentquestion:', question) // TODO: remove return new Promise((resolve, reject) => { let url = serverAdress + 'q?' let params = [] @@ -1960,16 +1711,23 @@ function SendXHRMessage (message) { var url = serverAdress + 'isAdding' - xmlhttpRequest({ - method: 'POST', - url: url, - data: message, - headers: { - 'Content-Type': 'application/x-www-form-urlencoded' - }, - onerror: function (response) { - Log('XMLHTTP request POST error') - } + return new Promise((resolve, reject) => { + xmlhttpRequest({ + method: 'POST', + url: url, + data: message, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + onerror: function (response) { + Log('XMLHTTP request POST error') + reject(new Error('unhandled error')) + }, + onload: (resp) => { + console.log(resp.responseText) + resolve(JSON.parse(resp.responseText)) + } + }) }) }