mirror of
				https://gitlab.com/MrFry/moodle-test-userscript
				synced 2025-04-01 20:22:48 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			2235 lines
		
	
	
		
			74 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			2235 lines
		
	
	
		
			74 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
// vim:foldmethod=marker
 | 
						|
/* ----------------------------------------------------------------------------
 | 
						|
 | 
						|
 Online Moodle/Elearning/KMOOC test help
 | 
						|
 Greasyfork: <https://greasyfork.org/en/scripts/38999-moodle-elearning-kmooc-test-help>
 | 
						|
 GitLab: <https://gitlab.com/YourFriendlyNeighborhoodDealer/moodle-test-userscript>
 | 
						|
 | 
						|
 This program is free software: you can redistribute it and/or modify
 | 
						|
 it under the terms of the GNU General Public License as published by
 | 
						|
 the Free Software Foundation, either version 3 of the License, or
 | 
						|
 (at your option) any later version.
 | 
						|
 | 
						|
 This program is distributed in the hope that it will be useful,
 | 
						|
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 GNU General Public License for more details.
 | 
						|
 | 
						|
 You should have received a copy of the GNU General Public License
 | 
						|
 along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
						|
 | 
						|
 ------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/* TODO
 | 
						|
 * remove stuff like "b. answer", "c. answer" ....
 | 
						|
 * */
 | 
						|
 | 
						|
var data // all data, which is in the resource txt
 | 
						|
var addEventListener // add event listener function
 | 
						|
const lastChangeLog = 'Néhány szerkezeti átalakítás, és bugfix. Ha valami elromlott akkor pls report, thanx'
 | 
						|
const serverAdress = 'https://qmining.frylabs.net/'
 | 
						|
 | 
						|
// forcing pages for testing. unless you test, do not set these to true!
 | 
						|
// only one of these should be true for testing
 | 
						|
const forceTestPage = false
 | 
						|
const forceResultPage = false
 | 
						|
const forceDefaultPage = false
 | 
						|
const logElementGetting = false
 | 
						|
const log = true
 | 
						|
 | 
						|
const motdShowCount = 3 /* Ammount of times to show motd */
 | 
						|
var motd = ''
 | 
						|
var lastestVersion = ''
 | 
						|
 | 
						|
const minMatchAmmount = 60 /* Minimum ammount to consider that two questions match during answering */
 | 
						|
const minResultMatchPercent = 99 /* Minimum ammount to consider that two questions match during saving */
 | 
						|
const lengthDiffMultiplier = 10 /* Percent minus for length difference */
 | 
						|
 | 
						|
// : Class descriptions {{{
 | 
						|
 | 
						|
class StringUtils {
 | 
						|
  SimplifyQuery (q) {
 | 
						|
    assert(q)
 | 
						|
 | 
						|
    var result = q.replace(/\n/g, ' ').replace(/\s/g, ' ')
 | 
						|
    return this.RemoveUnnecesarySpaces(result)
 | 
						|
  }
 | 
						|
 | 
						|
  ShortenString (toShorten, ammount) {
 | 
						|
    assert(toShorten)
 | 
						|
 | 
						|
    var result = ''
 | 
						|
    var i = 0
 | 
						|
    while (i < toShorten.length && i < ammount) {
 | 
						|
      result += toShorten[i]
 | 
						|
      i++
 | 
						|
    }
 | 
						|
    return result
 | 
						|
  }
 | 
						|
 | 
						|
  ReplaceCharsWithSpace (val, char) {
 | 
						|
    assert(val)
 | 
						|
    assert(char)
 | 
						|
 | 
						|
    var toremove = this.NormalizeSpaces(val)
 | 
						|
 | 
						|
    var regex = new RegExp(char, 'g')
 | 
						|
    toremove.replace(regex, ' ')
 | 
						|
 | 
						|
    return this.RemoveUnnecesarySpaces(toremove)
 | 
						|
  }
 | 
						|
 | 
						|
  // removes whitespace from begining and and, and replaces multiple spaces with one space
 | 
						|
  RemoveUnnecesarySpaces (toremove) {
 | 
						|
    assert(toremove)
 | 
						|
 | 
						|
    toremove = this.NormalizeSpaces(toremove)
 | 
						|
    while (toremove.includes('  ')) {
 | 
						|
      toremove = toremove.replace(/ {2}/g, ' ')
 | 
						|
    }
 | 
						|
    return toremove.trim()
 | 
						|
  }
 | 
						|
 | 
						|
  // simplifies a string for easier comparison
 | 
						|
  SimplifyStringForComparison (value) {
 | 
						|
    assert(value)
 | 
						|
 | 
						|
    value = this.RemoveUnnecesarySpaces(value).toLowerCase()
 | 
						|
    var removableChars = [',', '.', ':', '!']
 | 
						|
    for (var i = 0; i < removableChars.length; i++) {
 | 
						|
      var regex = new RegExp(removableChars[i], 'g')
 | 
						|
      value.replace(regex, '')
 | 
						|
    }
 | 
						|
    return value
 | 
						|
  }
 | 
						|
 | 
						|
  // if the value is empty, or whitespace
 | 
						|
  EmptyOrWhiteSpace (value) {
 | 
						|
    // replaces /n-s with "". then replaces spaces with "". if it equals "", then its empty, or only consists of white space
 | 
						|
    if (value === undefined) { return true }
 | 
						|
    return (value.replace(/\n/g, '').replace(/ /g, '').replace(/\s/g, ' ') === '')
 | 
						|
  }
 | 
						|
 | 
						|
  // damn nonbreaking space
 | 
						|
  NormalizeSpaces (input) {
 | 
						|
    assert(input)
 | 
						|
 | 
						|
    return input.replace(/\s/g, ' ')
 | 
						|
  }
 | 
						|
 | 
						|
  CompareString (s1, s2) {
 | 
						|
    assert(s1)
 | 
						|
    assert(s2)
 | 
						|
 | 
						|
    s1 = this.SimplifyStringForComparison(s1).split(' ')
 | 
						|
    s2 = this.SimplifyStringForComparison(s2).split(' ')
 | 
						|
    var match = 0
 | 
						|
    for (var i = 0; i < s1.length; i++) {
 | 
						|
      if (s2.includes(s1[i])) { match++ }
 | 
						|
    }
 | 
						|
    var percent = Math.round(((match / s1.length) * 100).toFixed(2)) // matched words percent
 | 
						|
    var lengthDifference = Math.abs(s2.length - s1.length)
 | 
						|
    percent -= lengthDifference * lengthDiffMultiplier
 | 
						|
    if (percent < 0) { percent = 0 }
 | 
						|
    return percent
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class Question {
 | 
						|
  constructor (q, a, i) {
 | 
						|
    this.Q = q
 | 
						|
    this.A = a
 | 
						|
    this.I = i
 | 
						|
  }
 | 
						|
 | 
						|
  toString () {
 | 
						|
    var r = '?' + this.Q + '\n!' + this.A
 | 
						|
    if (this.I) { r += '\n>' + this.I }
 | 
						|
    return r
 | 
						|
  }
 | 
						|
 | 
						|
  HasQuestion () {
 | 
						|
    return this.Q !== undefined
 | 
						|
  }
 | 
						|
 | 
						|
  HasAnswer () {
 | 
						|
    return this.A !== undefined
 | 
						|
  }
 | 
						|
 | 
						|
  HasImage () {
 | 
						|
    return this.I !== undefined
 | 
						|
  }
 | 
						|
 | 
						|
  IsComplete () {
 | 
						|
    return this.HasQuestion() && this.HasAnswer()
 | 
						|
  }
 | 
						|
 | 
						|
  Compare (q2, i) {
 | 
						|
    assert(q2)
 | 
						|
 | 
						|
    if (typeof q2 === 'string') {
 | 
						|
      var qmatchpercent = SUtils.CompareString(this.Q, q2)
 | 
						|
 | 
						|
      if (i === undefined || i.length === 0) { return qmatchpercent } else {
 | 
						|
        if (this.HasImage()) {
 | 
						|
          const imatchpercent = this.HasImage() ? SUtils.CompareString(this.I.join(' '), i.join(' '))
 | 
						|
            : 0
 | 
						|
          return (qmatchpercent + imatchpercent) / 2
 | 
						|
        } else {
 | 
						|
          qmatchpercent -= 30
 | 
						|
          if (qmatchpercent < 0) { return 0 } else { return qmatchpercent }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      const qmatchpercent = SUtils.CompareString(this.Q, q2.Q)
 | 
						|
      const amatchpercent = SUtils.CompareString(this.A, q2.A)
 | 
						|
      if (this.I !== undefined) {
 | 
						|
        const imatchpercent = this.I === undefined ? SUtils.CompareString(this.I.join(' '), q2.I.join(
 | 
						|
          ' ')) : 0
 | 
						|
        return (qmatchpercent + amatchpercent + imatchpercent) / 3
 | 
						|
      } else {
 | 
						|
        return (qmatchpercent + amatchpercent) / 2
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class Subject {
 | 
						|
  constructor (n) {
 | 
						|
    assert(n)
 | 
						|
 | 
						|
    this.Name = n
 | 
						|
    this.Questions = []
 | 
						|
  }
 | 
						|
 | 
						|
  get length () {
 | 
						|
    return this.Questions.length
 | 
						|
  }
 | 
						|
 | 
						|
  AddQuestion (q) {
 | 
						|
    assert(q)
 | 
						|
 | 
						|
    this.Questions.push(q)
 | 
						|
  }
 | 
						|
 | 
						|
  Search (q, img) {
 | 
						|
    assert(q)
 | 
						|
 | 
						|
    var r = []
 | 
						|
    for (let i = 0; i < this.length; i++) {
 | 
						|
      let percent = this.Questions[i].Compare(q, img)
 | 
						|
      if (percent > minMatchAmmount) {
 | 
						|
        r.push({
 | 
						|
          q: this.Questions[i],
 | 
						|
          match: percent
 | 
						|
        })
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    for (let i = 0; i < r.length; i++) {
 | 
						|
      for (var j = i; j < r.length; j++) {
 | 
						|
        if (r[i].match < r[j].match) {
 | 
						|
          var tmp = r[i]
 | 
						|
          r[i] = r[j]
 | 
						|
          r[j] = tmp
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    return r
 | 
						|
  }
 | 
						|
 | 
						|
  toString () {
 | 
						|
    var r = []
 | 
						|
    for (var i = 0; i < this.Questions.length; i++) { r.push(this.Questions[i].toString()) }
 | 
						|
    return '+' + this.Name + '\n' + r.join('\n')
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class QuestionDB {
 | 
						|
  constructor () {
 | 
						|
    this.Subjects = []
 | 
						|
  }
 | 
						|
 | 
						|
  get length () {
 | 
						|
    return this.Subjects.length
 | 
						|
  }
 | 
						|
 | 
						|
  get activeIndexes () {
 | 
						|
    var r = []
 | 
						|
    for (var i = 0; i < this.length; i++) {
 | 
						|
      if (GM_getValue('Is' + i + 'Active')) {
 | 
						|
        r.push(i)
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return r
 | 
						|
  }
 | 
						|
 | 
						|
  GetIfActive (ind) {
 | 
						|
    return GM_getValue('Is' + ind + 'Active')
 | 
						|
  }
 | 
						|
 | 
						|
  ChangeActive (i, value) {
 | 
						|
    GM_setValue('Is' + i + 'Active', !!value)
 | 
						|
  }
 | 
						|
 | 
						|
  AddQuestion (subj, q) {
 | 
						|
    assert(subj)
 | 
						|
 | 
						|
    var i = 0
 | 
						|
    while (i < this.Subjects.length && this.Subjects[i].Name !== subj) { i++ }
 | 
						|
    if (i < this.Subjects.length) { this.Subjects[i].AddQuestion(q) } else {
 | 
						|
      const n = new Subject(subj)
 | 
						|
      n.AddQuestion(q)
 | 
						|
      this.Subjects.push(n)
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Search (q, img) {
 | 
						|
    assert(q)
 | 
						|
 | 
						|
    var r = []
 | 
						|
    for (let i = 0; i < this.length; i++) {
 | 
						|
      if (this.GetIfActive(i)) { r = r.concat(this.Subjects[i].Search(q, img)) }
 | 
						|
    }
 | 
						|
 | 
						|
    for (let i = 0; i < r.length; i++) {
 | 
						|
      for (var j = i; j < r.length; j++) {
 | 
						|
        if (r[i].match < r[j].match) {
 | 
						|
          var tmp = r[i]
 | 
						|
          r[i] = r[j]
 | 
						|
          r[j] = tmp
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    return r
 | 
						|
  }
 | 
						|
 | 
						|
  AddSubject (subj) {
 | 
						|
    assert(subj)
 | 
						|
 | 
						|
    var i = 0
 | 
						|
    while (i < this.length && subj.Name !== this.Subjects[i].Name) { i++ }
 | 
						|
 | 
						|
    if (i < this.length) {
 | 
						|
      this.Subjects.concat(subj.Questions)
 | 
						|
    } else {
 | 
						|
      this.Subjects.push(subj)
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  toString () {
 | 
						|
    var r = []
 | 
						|
    for (var i = 0; i < this.Subjects.length; i++) { r.push(this.Subjects[i].toString()) }
 | 
						|
    return r.join('\n\n')
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
var SUtils = new StringUtils()
 | 
						|
 | 
						|
// : }}}
 | 
						|
 | 
						|
// : DOM getting stuff {{{
 | 
						|
// all dom getting stuff are in this sections, so on
 | 
						|
// moodle dom change, stuff breaks here
 | 
						|
 | 
						|
class QuestionsPageModell {
 | 
						|
  GetAllQuestionsDropdown () {
 | 
						|
    if (logElementGetting) { Log('getting dropdown question') }
 | 
						|
    let items = document.getElementById('responseform').getElementsByTagName('p')[0].childNodes
 | 
						|
    let r = ''
 | 
						|
    items.forEach((item) => {
 | 
						|
      if (item.tagName === undefined) { r += item.nodeValue }
 | 
						|
    })
 | 
						|
    return r
 | 
						|
  }
 | 
						|
 | 
						|
  GetAllQuestionsQtext () {
 | 
						|
    if (logElementGetting) { Log('getting all questions qtext') }
 | 
						|
    return document.getElementById('responseform').getElementsByClassName('qtext') // getting questions
 | 
						|
  }
 | 
						|
 | 
						|
  GetAllQuestionsP () {
 | 
						|
    if (logElementGetting) { Log('getting all questions by tag p') }
 | 
						|
    return document.getElementById('responseform').getElementsByTagName('p')
 | 
						|
  }
 | 
						|
 | 
						|
  GetFormulationClearfix () {
 | 
						|
    if (logElementGetting) { Log('getting formulation clearfix lol') }
 | 
						|
    return document.getElementsByClassName('formulation clearfix')
 | 
						|
  }
 | 
						|
 | 
						|
  GetAnswerOptions () {
 | 
						|
    if (logElementGetting) { Log('getting all answer options') }
 | 
						|
    return this.GetFormulationClearfix()[0].childNodes[3].innerText
 | 
						|
  }
 | 
						|
 | 
						|
  GetQuestionImages () {
 | 
						|
    if (logElementGetting) { Log('getting question images') }
 | 
						|
    return this.GetFormulationClearfix()[0].getElementsByTagName('img')
 | 
						|
  }
 | 
						|
 | 
						|
  // this function should return the question, posible answers, and image names
 | 
						|
  GetQuestionFromTest () {
 | 
						|
    var questions // the important questions
 | 
						|
    var allQuestions // all questions
 | 
						|
    try {
 | 
						|
      allQuestions = this.GetAllQuestionsQtext() // getting questions
 | 
						|
      if (allQuestions.length === 0) {
 | 
						|
        var ddq = this.GetAllQuestionsDropdown()
 | 
						|
        if (SUtils.EmptyOrWhiteSpace(ddq)) {
 | 
						|
          var questionData = ''
 | 
						|
          for (var j = 0; j < allQuestions.length; j++) {
 | 
						|
            // TODO: test dis
 | 
						|
            let subAllQuestions = allQuestions[j].childNodes
 | 
						|
            for (let i = 0; i < subAllQuestions.length; i++) {
 | 
						|
              if (subAllQuestions[i].data !== undefined && !SUtils.EmptyOrWhiteSpace(subAllQuestions[i].data)) {
 | 
						|
                questionData += subAllQuestions[i].data + ' ' // adding text to question data
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
          questions = [questionData]
 | 
						|
        } else { questions = [ddq] }
 | 
						|
      } else {
 | 
						|
        questions = []
 | 
						|
        for (let i = 0; i < allQuestions.length; i++) {
 | 
						|
          questions.push(allQuestions[i].innerText)
 | 
						|
        }
 | 
						|
      }
 | 
						|
    } catch (e) {
 | 
						|
      Exception(e, 'script error at getting question:')
 | 
						|
    }
 | 
						|
    var imgNodes = '' // the image nodes for questions
 | 
						|
    try {
 | 
						|
      imgNodes = this.GetQuestionImages() // getting question images, if there is any
 | 
						|
      AddImageNamesToImages(imgNodes) // adding image names to images, so its easier to search for, or even guessing
 | 
						|
    } catch (e) {
 | 
						|
      Log(e)
 | 
						|
      Log('Some error with images')
 | 
						|
    }
 | 
						|
 | 
						|
    questions = questions.map((item, ind) => {
 | 
						|
      return SUtils.ReplaceCharsWithSpace(item, '\n')
 | 
						|
    })
 | 
						|
 | 
						|
    return {
 | 
						|
      imgnodes: imgNodes,
 | 
						|
      allQ: allQuestions,
 | 
						|
      q: questions
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class ResultsPageModell {
 | 
						|
  DetermineQuestionType (nodes) {
 | 
						|
    let qtype = ''
 | 
						|
    let i = 0
 | 
						|
 | 
						|
    while (i < nodes.length && qtype === '') {
 | 
						|
      let inps = nodes[i].getElementsByTagName('input')
 | 
						|
 | 
						|
      if (inps.length > 0) {
 | 
						|
        qtype = inps[0].type
 | 
						|
      }
 | 
						|
 | 
						|
      i++
 | 
						|
    }
 | 
						|
 | 
						|
    return qtype
 | 
						|
  }
 | 
						|
 | 
						|
  GetSelectAnswer () {
 | 
						|
    if (logElementGetting) { Log('getting selected answer') }
 | 
						|
    var t = document.getElementsByTagName('select')
 | 
						|
    if (t.length > 0) {
 | 
						|
      return t[0].options[document.getElementsByTagName('select')[0].selectedIndex].innerText
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  GetCurrQuestion (i) {
 | 
						|
    if (logElementGetting) { Log('getting curr questions by index: ' + i) }
 | 
						|
    return document.getElementsByTagName('form')[0].childNodes[0].childNodes[i].childNodes[1].childNodes[0].innerText
 | 
						|
  }
 | 
						|
 | 
						|
  GetFormResult () {
 | 
						|
    if (logElementGetting) { Log('getting form result') }
 | 
						|
    var t = document.getElementsByTagName('form')[0].childNodes[0].childNodes
 | 
						|
    if (t.length > 0 && t[0].tagName === undefined) { // debreceni moodle
 | 
						|
      return document.getElementsByTagName('form')[1].childNodes[0].childNodes
 | 
						|
    } else {
 | 
						|
      return t
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  GetAnswerNode (i) {
 | 
						|
    if (logElementGetting) { Log('getting answer node') }
 | 
						|
 | 
						|
    var results = this.GetFormResult() // getting results element
 | 
						|
 | 
						|
    var r = results[i].getElementsByClassName('answer')[0].childNodes
 | 
						|
    var ret = []
 | 
						|
    for (var j = 0; j < r.length; j++) {
 | 
						|
      if (r[j].tagName !== undefined && r[j].tagName.toLowerCase() === 'div') { ret.push(r[j]) }
 | 
						|
    }
 | 
						|
 | 
						|
    let qtype = this.DetermineQuestionType(ret)
 | 
						|
 | 
						|
    return {
 | 
						|
      nodes: ret,
 | 
						|
      type: qtype
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  GetCurrentAnswer (i) {
 | 
						|
    if (logElementGetting) { Log('getting curr answer by index: ' + i) }
 | 
						|
    var results = this.GetFormResult() // getting results element
 | 
						|
    var t = results[i].getElementsByClassName('formulation clearfix')[0].getElementsByTagName('span')
 | 
						|
    if (t.length > 2) { return t[1].innerHTML.split('<br>')[1] }
 | 
						|
  }
 | 
						|
 | 
						|
  GetQText (i) {
 | 
						|
    if (logElementGetting) { Log('getting qtext by index: ' + i) }
 | 
						|
    var results = this.GetFormResult() // getting results element
 | 
						|
    return results[i].getElementsByClassName('qtext')
 | 
						|
  }
 | 
						|
 | 
						|
  GetDropboxes (i) {
 | 
						|
    if (logElementGetting) { Log('getting dropboxes by index: ' + i) }
 | 
						|
    var results = this.GetFormResult() // getting results element
 | 
						|
    return results[i].getElementsByTagName('select')
 | 
						|
  }
 | 
						|
 | 
						|
  GetAllAnswer (index) {
 | 
						|
    if (logElementGetting) { Log('getting all answers, ind: ' + index) }
 | 
						|
    return document.getElementsByClassName('answer')[index].childNodes
 | 
						|
  }
 | 
						|
 | 
						|
  GetPossibleAnswers (i) {
 | 
						|
    if (logElementGetting) { Log('getting possible answers') }
 | 
						|
    var results = this.GetFormResult() // getting results element
 | 
						|
    var items = results[i].getElementsByTagName('label')
 | 
						|
    var r = []
 | 
						|
    for (var j = 0; j < items.length; j++) {
 | 
						|
      const TryGetCorrect = (j) => {
 | 
						|
        var cn = items[j].parentNode.className
 | 
						|
        if (cn.includes('correct')) { return cn.includes('correct') && !cn.includes('incorrect') }
 | 
						|
      }
 | 
						|
      r.push({
 | 
						|
        value: items[j].innerText,
 | 
						|
        iscorrect: TryGetCorrect(j)
 | 
						|
      })
 | 
						|
    }
 | 
						|
    return r
 | 
						|
  }
 | 
						|
 | 
						|
  GetRightAnswerIfCorrectShown (i) {
 | 
						|
    if (logElementGetting) { Log('getting right answer if correct shown') }
 | 
						|
    var results = this.GetFormResult() // getting results element
 | 
						|
    return results[i].getElementsByClassName('rightanswer')
 | 
						|
  }
 | 
						|
 | 
						|
  GetWrongAnswerIfCorrectNotShown (i) {
 | 
						|
    if (logElementGetting) { Log('getting wrong answer if correct not shown') }
 | 
						|
    var results = this.GetFormResult() // getting results element
 | 
						|
    var n = results[i].getElementsByTagName('i')[0].parentNode
 | 
						|
    if (n.className.includes('incorrect')) { return results[i].getElementsByTagName('i')[0].parentNode.innerText } else { return '' }
 | 
						|
  }
 | 
						|
 | 
						|
  GetRightAnswerIfCorrectNotShown (i) {
 | 
						|
    if (logElementGetting) { Log('Getting right answer if correct not shown') }
 | 
						|
    var results = this.GetFormResult() // getting results element
 | 
						|
    var n = results[i].getElementsByTagName('i')[0].parentNode
 | 
						|
    if (n.className.includes('correct') && !n.className.includes('incorrect')) { return results[i].getElementsByTagName('i')[0].parentNode.innerText } else { return '' }
 | 
						|
  }
 | 
						|
 | 
						|
  GetFormCFOfResult (result) {
 | 
						|
    if (logElementGetting) { Log('getting formulation clearfix') }
 | 
						|
    return result.getElementsByClassName('formulation clearfix')[0]
 | 
						|
  }
 | 
						|
 | 
						|
  GetResultText (i) {
 | 
						|
    if (logElementGetting) { Log('getting result text') }
 | 
						|
    var results = this.GetFormResult() // getting results element
 | 
						|
    return this.GetFormCFOfResult(results[i]).getElementsByTagName('p')
 | 
						|
  }
 | 
						|
 | 
						|
  GetResultImage (i) {
 | 
						|
    if (logElementGetting) { Log('getting result image') }
 | 
						|
    var results = this.GetFormResult() // getting results element
 | 
						|
    return this.GetFormCFOfResult(results[i]).getElementsByTagName('img')
 | 
						|
  }
 | 
						|
 | 
						|
  // gets the question from the result page
 | 
						|
  // i is the index of the question
 | 
						|
  GetQuestionFromResult (i) {
 | 
						|
    var temp = this.GetQText(i)
 | 
						|
    var currQuestion = ''
 | 
						|
    if (temp.length > 0) {
 | 
						|
      currQuestion = temp[0].innerText // adding the question to curr question as .q
 | 
						|
    } else {
 | 
						|
      // this is black magic fuckery a bit
 | 
						|
      if (this.GetDropboxes(i).length > 0) {
 | 
						|
        var allNodes = this.GetResultText(i)
 | 
						|
        currQuestion = ''
 | 
						|
        for (var k = 0; k < allNodes.length; k++) {
 | 
						|
          var allQuestions = this.GetResultText(i)[k].childNodes
 | 
						|
          for (var j = 0; j < allQuestions.length; j++) {
 | 
						|
            if (allQuestions[j].data !== undefined && !SUtils.EmptyOrWhiteSpace(allQuestions[j].data)) {
 | 
						|
              currQuestion += allQuestions[j].data + ' '
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        try {
 | 
						|
          currQuestion = this.GetCurrQuestion(i)
 | 
						|
        } catch (e) {
 | 
						|
          currQuestion = 'REEEEEEEEEEEEEEEEEEEEE' // this shouldnt really happen sry guys
 | 
						|
          Log('Unable to get question in GetQuestionFromResult')
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return currQuestion
 | 
						|
  }
 | 
						|
 | 
						|
  // tries to get right answer from result page
 | 
						|
  // i is the index of the question
 | 
						|
  GetRightAnswerFromResult (i) {
 | 
						|
    var fun = []
 | 
						|
 | 
						|
    // the basic type of getting answers
 | 
						|
    fun.push(function TryGet0 (i) {
 | 
						|
      var temp = RPM.GetRightAnswerIfCorrectShown(i) // getting risht answer
 | 
						|
      if (temp.length > 0) { return temp[0].innerText } // adding the answer to curr question as .a
 | 
						|
    })
 | 
						|
 | 
						|
    // if there is dropdown list in the current question
 | 
						|
    fun.push(function TryGet1 (i) {
 | 
						|
      if (RPM.GetDropboxes(i).length > 0) { return RPM.GetCurrentAnswer(i) }
 | 
						|
    })
 | 
						|
 | 
						|
    // if the correct answers are not shown, and the selected answer
 | 
						|
    // is correct
 | 
						|
    fun.push(function TryGet2 (i) {
 | 
						|
      return RPM.GetRightAnswerIfCorrectNotShown(i)
 | 
						|
    })
 | 
						|
 | 
						|
    // if there is dropbox in the question
 | 
						|
    fun.push(function TryGet3 (i) {
 | 
						|
      return RPM.GetSelectAnswer()
 | 
						|
    })
 | 
						|
 | 
						|
    // if the correct answers are not shown, and the selected answer
 | 
						|
    // is incorrect, and there are only 2 options
 | 
						|
    fun.push(function TryGet4 (i) {
 | 
						|
      var possibleAnswers = RPM.GetPossibleAnswers(i)
 | 
						|
      if (possibleAnswers.length === 2) {
 | 
						|
        for (var k = 0; k < possibleAnswers.length; k++) {
 | 
						|
          if (possibleAnswers[k].iscorrect === undefined) { return possibleAnswers[k].value }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    })
 | 
						|
 | 
						|
    fun.push(function TryGetFinal (i) {
 | 
						|
      return undefined
 | 
						|
    })
 | 
						|
 | 
						|
    var j = 0
 | 
						|
    var currAnswer
 | 
						|
    while (j < fun.length && SUtils.EmptyOrWhiteSpace(currAnswer)) {
 | 
						|
      currAnswer = fun[j](i)
 | 
						|
      j++
 | 
						|
    }
 | 
						|
 | 
						|
    return currAnswer
 | 
						|
  }
 | 
						|
 | 
						|
  // version 2 of getting right answer from result page
 | 
						|
  // i is the index of the question
 | 
						|
  GetRightAnswerFromResultv2 (i) {
 | 
						|
    try {
 | 
						|
      var answerNodes = this.GetAnswerNode(i)
 | 
						|
      let items = answerNodes.nodes
 | 
						|
 | 
						|
      if (answerNodes.type === 'checkbox') { return RPM.GetRightAnswerFromResult(i) }
 | 
						|
 | 
						|
      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 (items.length === 2) {
 | 
						|
        for (let j = 0; j < items.length; j++) {
 | 
						|
          let cn = items[j].className
 | 
						|
          if (!cn.includes('correct')) { return items[j].innerText }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    } catch (e) {
 | 
						|
      Log('error at new nodegetting, trying the oldschool way')
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class MiscPageModell {
 | 
						|
  GetCurrentSubjectName () {
 | 
						|
    if (logElementGetting) { Log('getting current subjects name') }
 | 
						|
    return document.getElementById('page-header').innerText.split('\n')[0]
 | 
						|
  }
 | 
						|
 | 
						|
  GetVideo () {
 | 
						|
    if (logElementGetting) { Log('getting video stuff') }
 | 
						|
    return document.getElementsByTagName('video')[0]
 | 
						|
  }
 | 
						|
 | 
						|
  GetVideoElement () {
 | 
						|
    if (logElementGetting) { Log('getting video element') }
 | 
						|
    return document.getElementById('videoElement').parentNode
 | 
						|
  }
 | 
						|
 | 
						|
  GetInputType (answers, i) {
 | 
						|
    if (logElementGetting) { Log('getting input type') }
 | 
						|
    return answers[i].getElementsByTagName('input')[0].type
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
var QPM = new QuestionsPageModell()
 | 
						|
var RPM = new ResultsPageModell()
 | 
						|
var MPM = new MiscPageModell()
 | 
						|
 | 
						|
// : }}}
 | 
						|
 | 
						|
// : Main function {{{
 | 
						|
function Main () { // eslint-disable-line
 | 
						|
  'use strict'
 | 
						|
  console.time('main')
 | 
						|
 | 
						|
  Init(function (count, subjCount) {
 | 
						|
    var url = location.href // eslint-disable-line
 | 
						|
 | 
						|
    let skipLoad = GM_getValue('skipLoad') // eslint-disable-line
 | 
						|
    if (count === -2 && subjCount === -2 && skipLoad) {
 | 
						|
      if (url.includes('/quiz/') && url.includes('attempt.php')) {
 | 
						|
        ShowMessage({
 | 
						|
          m: 'Passzív mód bekapcsolva, válaszok megjelenítéséhez menü gomb alatt kapcsold ki, és frissíts!',
 | 
						|
          isSimple: true
 | 
						|
        })
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      try {
 | 
						|
        if ((url.includes('/quiz/') && url.includes('attempt.php')) || forceTestPage) { // if the current page is a test
 | 
						|
          HandleQuiz()
 | 
						|
        } else if ((url.includes('/quiz/') && url.includes('review.php')) || forceResultPage) { // if the current window is a test-s result
 | 
						|
          HandleResults(url)
 | 
						|
        } else if ((!url.includes('/quiz/') && !url.includes('review.php') && !url.includes('.pdf')) ||
 | 
						|
          (forceDefaultPage)) { // if the current window is any other window than a quiz or pdf.
 | 
						|
          HandleUI(url, count, subjCount)
 | 
						|
        }
 | 
						|
      } catch (e) {
 | 
						|
        ShowMessage({
 | 
						|
          m: 'Fatál error. Check console (f12). Kattints az üzenetre az összes kérdés/válaszért manuális kereséshez!',
 | 
						|
          isSimple: true
 | 
						|
        }, undefined, function () {
 | 
						|
          GM_openInTab(serverAdress + 'lred', { // eslint-disable-line
 | 
						|
            active: true
 | 
						|
          })
 | 
						|
        })
 | 
						|
        Exception(e, 'script error at main:')
 | 
						|
      }
 | 
						|
      if (url.includes('eduplayer')) { AddVideoHotkeys(url) } // adding video hotkeys
 | 
						|
      Log(
 | 
						|
        'Itteni hibák 100% a moodle hiba. Kivéve, ha oda van írva hogy script error ;) Ha ilyesmi szerepel itt, akkor olvasd el a segítség szekciót! Nagy esélyel a kérdéseket nem lehetett beolvasni.'
 | 
						|
      )
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  console.log('Moodle Test Script run time:')
 | 
						|
  console.timeEnd('main')
 | 
						|
 | 
						|
  if (forceTestPage || forceResultPage || forceDefaultPage) {
 | 
						|
    if (document.getElementById('scriptMessage')) { document.getElementById('scriptMessage').style.background = 'green' }
 | 
						|
  }
 | 
						|
}
 | 
						|
// : }}}
 | 
						|
 | 
						|
// : Main logic stuff {{{
 | 
						|
 | 
						|
// : Loading {{{
 | 
						|
 | 
						|
function Init (cwith) {
 | 
						|
  if (false) { // eslint-disable-line
 | 
						|
    GM_setValue('version16', undefined) // eslint-disable-line
 | 
						|
    GM_setValue('version15', undefined) // eslint-disable-line
 | 
						|
    GM_setValue('firstRun', undefined) // eslint-disable-line
 | 
						|
    GM_setValue('showQuestions', undefined) // eslint-disable-line
 | 
						|
    GM_setValue('showSplash', undefined) // eslint-disable-line
 | 
						|
  }
 | 
						|
  var url = location.href // window location
 | 
						|
  var count = -1 // loaded question count. stays -1 if the load failed.
 | 
						|
  // --------------------------------------------------------------------------------------
 | 
						|
  // event listener fuckery
 | 
						|
  // --------------------------------------------------------------------------------------
 | 
						|
  try {
 | 
						|
    // adding addeventlistener stuff, for the ability to add more event listeners for the same event
 | 
						|
    addEventListener = (function () {
 | 
						|
      if (document.addEventListener) {
 | 
						|
        return function (element, event, handler) {
 | 
						|
          element.addEventListener(event, handler, false)
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        return function (element, event, handler) {
 | 
						|
          element.attachEvent('on' + event, handler)
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }())
 | 
						|
  } catch (e) {
 | 
						|
    Exception(e, 'script error at addEventListener:')
 | 
						|
  }
 | 
						|
  VersionActions()
 | 
						|
  count = Load(cwith) // loads resources
 | 
						|
  if (!url.includes('.pdf')) { ShowMenu() }
 | 
						|
  return count
 | 
						|
}
 | 
						|
 | 
						|
function VersionActions () {
 | 
						|
  // FOR TESTING ONLY
 | 
						|
  // GM_setValue("version15", true);
 | 
						|
  // GM_setValue("firstRun", true);
 | 
						|
  // GM_setValue("version16", true);
 | 
						|
  // GM_setValue("version161", true);
 | 
						|
  // throw "asd";
 | 
						|
 | 
						|
  let r = FreshStart()
 | 
						|
  if (r !== true) { GM_setValue('version161', false) }
 | 
						|
 | 
						|
  Version15()
 | 
						|
  Version16()
 | 
						|
  Version161()
 | 
						|
}
 | 
						|
 | 
						|
// : Version action functions {{{
 | 
						|
 | 
						|
function FreshStart () {
 | 
						|
  var firstRun = GM_getValue('firstRun') // if the current run is the frst
 | 
						|
  if (firstRun === undefined || firstRun === true) {
 | 
						|
    GM_setValue('firstRun', false)
 | 
						|
    ShowHelp() // showing help
 | 
						|
    return true
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function Version15 () {
 | 
						|
  var version15 = GM_getValue('version15') // if the current run is the frst
 | 
						|
  if (version15 === undefined || version15 === true) {
 | 
						|
    GM_setValue('useNetDB', '1')
 | 
						|
    GM_setValue('version15', false)
 | 
						|
    document.write(
 | 
						|
      '<h1>Moodle teszt userscript:<h1><h3>1.5.0 verzió: a script mostantól XMLHTTP kéréseket küld szerver fele! Erre a userscript futtató kiegészitőd is figyelmeztetni fog! Ha ez történik, a script rendes működése érdekében engedélyezd (Always allow domain)! Ha nem akarod, hogy ez történjen, akkor ne engedélyezd, vagy a menüben válaszd ki a "helyi fájl használata" opciót!</h3> <h3>Elküldött adatok: minden teszt után a kérdés-válasz páros. Fogadott adatok: Az összes eddig ismert kérdés. Érdemes help-et elolvasni!!!</h3><h5>Ez az ablak frissités után eltűnik. Ha nem, akkor a visza gombbal próbálkozz.</h5>'
 | 
						|
    )
 | 
						|
    document.close()
 | 
						|
    throw 'something, so this stuff stops'
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function Version16 () {
 | 
						|
  var version16 = GM_getValue('version16') // if the current run is the frst
 | 
						|
  if (version16 === undefined || version16 === true) {
 | 
						|
    var i = 0
 | 
						|
    while (GM_getValue('Is' + i + 'Active') !== undefined) {
 | 
						|
      GM_setValue('Is' + i + 'Active', false)
 | 
						|
      i++
 | 
						|
    }
 | 
						|
    GM_setValue('version16', false)
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function Version161 () {
 | 
						|
  var version161 = GM_getValue('version161') // if the current run is the frst
 | 
						|
  if (version161 == undefined || version161 == true) // if its undefined, or true
 | 
						|
  {
 | 
						|
    GM_setValue('useNetDB', '1')
 | 
						|
    GM_setValue('version161', false)
 | 
						|
    document.write(
 | 
						|
      '<h1>Moodle teszt userscript:<h1><h3>1.6.1.0 verzió: Új domain név: qmining.tk. Ha frissíted az oldalt, akkor tampremonkey rá fog kérdezni, hpgy engedélyezed-e a kérdések külését erre az új domain-re. A rendes működés érdekében kattints a "Allow always domain"-gombra</h3>'
 | 
						|
    )
 | 
						|
    document.close()
 | 
						|
    throw 'something, so this stuff stops'
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// : }}}
 | 
						|
 | 
						|
var GetFileData = () => {
 | 
						|
  return GM_getResourceText('data')
 | 
						|
}
 | 
						|
 | 
						|
function ReadFile (cwith) {
 | 
						|
  var resource = ''
 | 
						|
  try {
 | 
						|
    resource = GetFileData() // getting data from txt
 | 
						|
    if (resource == undefined) {
 | 
						|
      ShowMessage({
 | 
						|
        m: 'Nem lehetett beolvasni a fájlt :c Ellenőrizd az elérési utat, vagy a fájl jogosultságokat',
 | 
						|
        isSimple: true
 | 
						|
      })
 | 
						|
      return
 | 
						|
    }
 | 
						|
    if (SUtils.EmptyOrWhiteSpace(resource)) {
 | 
						|
      throw {
 | 
						|
        message: 'data file empty'
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } catch (e) {
 | 
						|
    Exception(e, 'script error at reading file:')
 | 
						|
  }
 | 
						|
  NLoad(resource, cwith)
 | 
						|
}
 | 
						|
 | 
						|
function ReadNetDB (cwith, useNetDB) {
 | 
						|
  function NewXMLHttpRequest () {
 | 
						|
    const url = serverAdress + 'data.json'
 | 
						|
    GM_xmlhttpRequest({
 | 
						|
      method: 'GET',
 | 
						|
      synchronous: true,
 | 
						|
      url: url,
 | 
						|
      onload: function (response) {
 | 
						|
        NLoad(response.responseText, cwith)
 | 
						|
      },
 | 
						|
      onerror: function () {
 | 
						|
        NLoad(undefined, cwith) // server down
 | 
						|
      }
 | 
						|
    })
 | 
						|
  }
 | 
						|
  try {
 | 
						|
    Log('Sending XMLHTTP Request...')
 | 
						|
    return NewXMLHttpRequest()
 | 
						|
  } catch (e) {
 | 
						|
    Exception(e, 'script error at reading online database:')
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Returns a question database from the given data.
 | 
						|
 * Parameter should be raw read file in string with "\n"-s
 | 
						|
 * */
 | 
						|
function ParseRawData (data) {
 | 
						|
  const d = data.split('\n')
 | 
						|
  const r = new QuestionDB()
 | 
						|
  var logs = []
 | 
						|
  var currSubj = '' // the current subjects name
 | 
						|
  var ExpectedIdentifier = ['+', '?']
 | 
						|
  let currQuestion = new Question()
 | 
						|
 | 
						|
  var i = -1
 | 
						|
  while (i < d.length) {
 | 
						|
    let currIdentifier
 | 
						|
    let skipped = 0
 | 
						|
    do {
 | 
						|
      if (skipped >= 1) { logs.push(i + ': ' + d[i]) }
 | 
						|
      i++
 | 
						|
      if (i >= d.length) {
 | 
						|
        if (currQuestion.IsComplete()) { r.AddQuestion(currSubj, currQuestion) }
 | 
						|
        return {
 | 
						|
          result: r,
 | 
						|
          logs: logs
 | 
						|
        }
 | 
						|
      }
 | 
						|
      currIdentifier = d[i][0]
 | 
						|
      skipped++
 | 
						|
    } while (!ExpectedIdentifier.includes(currIdentifier) && i < d.length)
 | 
						|
 | 
						|
    let currData = d[i].substring(1).trim()
 | 
						|
 | 
						|
    if (currIdentifier == '+') {
 | 
						|
      if (currQuestion.IsComplete()) { r.AddQuestion(currSubj, currQuestion) }
 | 
						|
      currQuestion = new Question()
 | 
						|
      currSubj = currData
 | 
						|
      ExpectedIdentifier = ['?']
 | 
						|
      continue
 | 
						|
    }
 | 
						|
 | 
						|
    if (currIdentifier == '?') {
 | 
						|
      if (currQuestion.IsComplete()) {
 | 
						|
        r.AddQuestion(currSubj, currQuestion)
 | 
						|
        currQuestion = new Question()
 | 
						|
      }
 | 
						|
      // overwriting is allowed here, bcus:
 | 
						|
      // ?????!>
 | 
						|
      currQuestion.Q = currData
 | 
						|
      ExpectedIdentifier = ['!', '?']
 | 
						|
      continue
 | 
						|
    }
 | 
						|
 | 
						|
    if (currIdentifier == '!') {
 | 
						|
      // if dont have question continue
 | 
						|
      if (!currQuestion.HasQuestion()) { throw 'No question! (A)' }
 | 
						|
      // dont allow overwriting
 | 
						|
      // ?!!!!
 | 
						|
      if (!currQuestion.HasAnswer()) {
 | 
						|
        currData = currData.replace('A helyes válaszok: ', '')
 | 
						|
        currData = currData.replace('A helyes válasz: ', '')
 | 
						|
 | 
						|
        currQuestion.A = currData
 | 
						|
      }
 | 
						|
      ExpectedIdentifier = ['?', '>', '+']
 | 
						|
      continue
 | 
						|
    }
 | 
						|
 | 
						|
    if (currIdentifier == '>') {
 | 
						|
      // if dont have question or answer continue
 | 
						|
      if (!currQuestion.HasQuestion()) { throw 'No question! (I)' }
 | 
						|
      if (!currQuestion.HasAnswer()) { throw 'No asnwer! (I)' }
 | 
						|
      // dont allow overwriting
 | 
						|
      // ?!>>>
 | 
						|
      if (!currQuestion.HasImage()) {
 | 
						|
        try {
 | 
						|
          currQuestion.I = JSON.parse(currData)
 | 
						|
        } catch (e) {
 | 
						|
          currQuestion.I = currData.split(',')
 | 
						|
        }
 | 
						|
      }
 | 
						|
      ExpectedIdentifier = ['?', '+']
 | 
						|
      continue
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return {
 | 
						|
    result: r,
 | 
						|
    logs: logs
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function Load (cwith) {
 | 
						|
  var useNetDB = GM_getValue('useNetDB')
 | 
						|
  let skipLoad = GM_getValue('skipLoad')
 | 
						|
 | 
						|
  if (skipLoad) {
 | 
						|
    cwith(-2, -2)
 | 
						|
    return -1
 | 
						|
  }
 | 
						|
 | 
						|
  if (useNetDB != undefined && useNetDB == 1) { return ReadNetDB(cwith, useNetDB) } else { return ReadFile(cwith) }
 | 
						|
}
 | 
						|
 | 
						|
function LoadMOTD (resource) {
 | 
						|
  try {
 | 
						|
    motd = resource.motd
 | 
						|
  } catch (e) {
 | 
						|
    Log('Error loading motd :c')
 | 
						|
    Log(e)
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function LoadVersion (resource) {
 | 
						|
  try {
 | 
						|
    lastestVersion = resource.version
 | 
						|
  } catch (e) {
 | 
						|
    Log('Error loading version :c')
 | 
						|
    Log(e)
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// loading stuff
 | 
						|
function NLoad (resource, cwith) {
 | 
						|
  assert(resource)
 | 
						|
 | 
						|
  var count = -1
 | 
						|
  var subjCount = 0
 | 
						|
  try {
 | 
						|
    var d = {}
 | 
						|
    try {
 | 
						|
      d = JSON.parse(resource)
 | 
						|
    } catch (e) {
 | 
						|
      Log('Old data, trying with old methods....')
 | 
						|
      try {
 | 
						|
        d = ParseRawData(resource).result
 | 
						|
      } catch (e2) {
 | 
						|
        Log('Couldt parse data!')
 | 
						|
        ShowMessage({
 | 
						|
          m: 'Nem sikerült betölteni az adatokat! Ellenőriz a megadott fájlt, vagy az internetelérésed!',
 | 
						|
          isSimple: true
 | 
						|
        })
 | 
						|
        return
 | 
						|
      }
 | 
						|
    }
 | 
						|
    var r = new QuestionDB()
 | 
						|
    var rt = []
 | 
						|
    var allCount = -1
 | 
						|
    LoadMOTD(d)
 | 
						|
    LoadVersion(d)
 | 
						|
 | 
						|
    for (var i = 0; i < d.Subjects.length; i++) {
 | 
						|
      let s = new Subject(d.Subjects[i].Name)
 | 
						|
      if (GM_getValue('Is' + i + 'Active')) {
 | 
						|
        var j = 0
 | 
						|
        for (j = 0; j < d.Subjects[i].Questions.length; j++) {
 | 
						|
          var currQ = d.Subjects[i].Questions[j]
 | 
						|
          s.AddQuestion(new Question(currQ.Q, currQ.A, currQ.I))
 | 
						|
        }
 | 
						|
        rt.push({
 | 
						|
          name: d.Subjects[i].Name,
 | 
						|
          count: j
 | 
						|
        })
 | 
						|
        allCount += j
 | 
						|
        subjCount++
 | 
						|
      }
 | 
						|
      r.AddSubject(s)
 | 
						|
    }
 | 
						|
    data = r
 | 
						|
    count = allCount + 1 // couse starting with -1 to show errors
 | 
						|
 | 
						|
    var i = 0
 | 
						|
    while (i < data.length && !GM_getValue('Is' + i + 'Active')) {
 | 
						|
      i++
 | 
						|
    }
 | 
						|
  } catch (e) {
 | 
						|
    Exception(e, 'script error at loading:')
 | 
						|
    count = -1 // returns -1 if error
 | 
						|
  }
 | 
						|
  cwith(count, subjCount)
 | 
						|
}
 | 
						|
 | 
						|
function AlertOnNoQuestion () {
 | 
						|
  try {
 | 
						|
    document.getElementById('HelperMenuButton').style.background = 'yellow'
 | 
						|
  } catch (e) {
 | 
						|
    Log('Unable to get helper menu button')
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// : }}}
 | 
						|
 | 
						|
// : UI handling {{{
 | 
						|
function HandleUI (url, count, subjCount) {
 | 
						|
  var newVersion = false // if the script is newer than last start
 | 
						|
  var loaded = count != -1 // if script could load stuff
 | 
						|
 | 
						|
  try // try, cus im suspicious
 | 
						|
  {
 | 
						|
    newVersion = GM_info.script.version !== GM_getValue('lastVerson')
 | 
						|
  } catch (e) {
 | 
						|
    Log('Some weird error trying to set new verison')
 | 
						|
  }
 | 
						|
  var greetMsg = '' // message to show at the end
 | 
						|
  var timeout = null // the timeout. if null, it wont be hidden
 | 
						|
  // no new version, nothing loaded
 | 
						|
  if (!newVersion && !loaded) // --------------------------------------------------------------------------------------------------------------
 | 
						|
  {
 | 
						|
    greetMsg =
 | 
						|
			'Hiba a @resource tagnál, vagy a fileval van gond! (Lehet át lett helyezve, vagy üres, vagy nincs tárgy kiválasztva) Vagy válaszd a netes adatok használatát menüben. Ellenőrizd az elérési utat, vagy hogy a Tampermonkey bővítmény eléri-e a fájlokat. Ha netes forrást használsz, akkor nem elérhető a szerver! Segítségért kattints!'
 | 
						|
  }
 | 
						|
  var showSplash = (GM_getValue('showSplash') == undefined) || GM_getValue('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 && loaded && showSplash) // ------------------------------------------------------------------------------------------------
 | 
						|
  {
 | 
						|
    timeout = 5
 | 
						|
    greetMsg = 'Moodle/Elearning/KMOOC segéd v. ' + GM_info.script.version + '. '
 | 
						|
 | 
						|
    if (lastestVersion != undefined && GM_info.script.version != lastestVersion) {
 | 
						|
      greetMsg += 'Új verzió elérhető: ' + lastestVersion + '\n'
 | 
						|
      timeout = undefined
 | 
						|
    }
 | 
						|
    greetMsg += count + ' kérdés és ' + subjCount + ' tárgy betöltve. (click for help).'
 | 
						|
    if (data.length > 0) {
 | 
						|
      var toAdd = []
 | 
						|
      for (var i = 0; i < data.length; i++) {
 | 
						|
        if (data.GetIfActive(i)) {
 | 
						|
          toAdd.push(data.Subjects[i].Name + ' (' + data.Subjects[i].length + ')')
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (toAdd.length != 0) {
 | 
						|
        greetMsg += '\nAktív tárgyak: ' + toAdd.join(', ') + '.'
 | 
						|
      } else {
 | 
						|
        AlertOnNoQuestion()
 | 
						|
        greetMsg += '\nNincs aktív tárgyad. Menüből válassz ki eggyet!'
 | 
						|
        timeout = undefined
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      greetMsg += ' Az adatfájlban nem adtál meg nevet. Vagy nem elérhető a szerver. Katt a helpért!'
 | 
						|
    }
 | 
						|
  }
 | 
						|
  // new version, nothing loaded
 | 
						|
  if (newVersion && !loaded) // --------------------------------------------------------------------------------------------------------------
 | 
						|
  {
 | 
						|
    greetMsg = 'Moodle/Elearning/KMOOC segéd v. ' + GM_info.script.version +
 | 
						|
			'. Új verzió!\n Írd át a @resouce tagnál az elírési utat! Kivéve ha üres a file, akkor töltsd fel :) Nincs kérdés betöltve! Segítséghez kattints. Changelog:\n' +
 | 
						|
			lastChangeLog // showing changelog too
 | 
						|
  }
 | 
						|
  // new version, everything loaded -> set lastVerson to current
 | 
						|
  if (newVersion && loaded) // --------------------------------------------------------------------------------------------------------------
 | 
						|
  {
 | 
						|
    greetMsg = 'Moodle/Elearning/KMOOC segéd v. ' + GM_info.script.version + '. ' + count +
 | 
						|
			' kérdés és ' + subjCount + ' tárgy betöltve. Verzió frissítve ' + GM_info.script.version +
 | 
						|
			'-re. Changelog:\n' + lastChangeLog
 | 
						|
    GM_setValue('lastVerson', GM_info.script.version) // setting lastVersion
 | 
						|
  }
 | 
						|
  if (!SUtils.EmptyOrWhiteSpace(motd)) {
 | 
						|
    var prevmotd = GM_getValue('motd')
 | 
						|
    if (prevmotd != motd) {
 | 
						|
      greetMsg += '\nMOTD:\n' + motd
 | 
						|
      timeout = null
 | 
						|
      GM_setValue('motdcount', motdShowCount)
 | 
						|
      GM_setValue('motd', motd)
 | 
						|
    } else {
 | 
						|
      var motdcount = GM_getValue('motdcount')
 | 
						|
      if (motdcount == undefined) {
 | 
						|
        GM_setValue('motdcount', motdShowCount)
 | 
						|
        motdcount = motdShowCount
 | 
						|
      }
 | 
						|
 | 
						|
      motdcount--
 | 
						|
      if (motdcount > 0) {
 | 
						|
        greetMsg += '\nMOTD:\n' + motd
 | 
						|
        timeout = null
 | 
						|
        GM_setValue('motdcount', motdcount)
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  ShowMessage({
 | 
						|
    m: greetMsg,
 | 
						|
    isSimple: true
 | 
						|
  }, timeout, ShowHelp) // showing message. If "m" is empty it wont show it, thats how showSplash works.
 | 
						|
}
 | 
						|
 | 
						|
// : }}}
 | 
						|
 | 
						|
// : Answering stuffs {{{
 | 
						|
 | 
						|
function HandleQuiz () {
 | 
						|
  var q = QPM.GetQuestionFromTest()
 | 
						|
  var questions = q.q
 | 
						|
  var allQuestions = q.allQ
 | 
						|
  var imgNodes = q.imgnodes
 | 
						|
  // ------------------------------------------------------------------------------------------------------
 | 
						|
  var answers = []
 | 
						|
  for (var j = 0; j < questions.length; j++) // going thru all answers
 | 
						|
  {
 | 
						|
    var question = SUtils.RemoveUnnecesarySpaces(questions[j]) // simplifying question
 | 
						|
    var result = data.Search(question, SimplifyImages(imgNodes))
 | 
						|
    var r = PrepareAnswers(result, j)
 | 
						|
    if (r != undefined) { answers.push(r) }
 | 
						|
    HighLightAnswer(result, j) // highlights the answer for the current result
 | 
						|
  }
 | 
						|
  ShowAnswers(answers)
 | 
						|
}
 | 
						|
 | 
						|
function PrepareAnswers (result, j) {
 | 
						|
  assert(result)
 | 
						|
 | 
						|
  if (result.length > 0) // if there are more than zero results
 | 
						|
  {
 | 
						|
    var allMessages = [] // preparing all messages
 | 
						|
    for (var k = 0; k < result.length; k++) // going throuh all results
 | 
						|
    {
 | 
						|
      var msg = '' // the current message
 | 
						|
      if ((GM_getValue('showQuestions') == undefined) || GM_getValue('showQuestions')) // if the question should be shown
 | 
						|
      {
 | 
						|
        msg += result[k].q.Q + '\n' // adding the question if yes
 | 
						|
      }
 | 
						|
      msg += result[k].q.A.replace(/, /g, '\n') // adding answer
 | 
						|
      if (result[k].q.HasImage()) // and adding image, if it exists
 | 
						|
      {
 | 
						|
        msg += '\n' + result[k].q.I // if it has image part, adding that too
 | 
						|
      }
 | 
						|
      allMessages.push({
 | 
						|
        m: msg,
 | 
						|
        p: result[k].match
 | 
						|
      })
 | 
						|
    }
 | 
						|
    return allMessages
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function ShowAnswers (answers) {
 | 
						|
  assert(answers)
 | 
						|
 | 
						|
  if (answers.length > 0) { // if there are more than 0 answer
 | 
						|
    ShowMessage(answers)
 | 
						|
  } else {
 | 
						|
    ShowMessage({
 | 
						|
      m: 'Nincs találat :( Kattints az üzenetre az összes kérdés/válaszért manuális kereséshez! Előfordulhat, hogy a tárgyat nem válsztottad ki a menüben.',
 | 
						|
      isSimple: true
 | 
						|
    }, undefined, function () {
 | 
						|
      GM_openInTab(serverAdress + 'lred', {
 | 
						|
        active: true
 | 
						|
      })
 | 
						|
    })
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// : }}}
 | 
						|
 | 
						|
// : Quiz saving {{{
 | 
						|
 | 
						|
function HandleResults (url) {
 | 
						|
  var allResults = new QuestionDB()
 | 
						|
  var d = SaveQuiz(GetQuiz(), data) // saves the quiz questions and answers
 | 
						|
 | 
						|
  if (d) { ShowSaveQuizDialog(d.addedQ, d.allQ, d.allOutput, d.output, d.sendSuccess, d.sentData) }
 | 
						|
}
 | 
						|
 | 
						|
function ShowSaveQuizDialog (addedQ, allQ, allOutput, output, sendSuccess, sentData) {
 | 
						|
  var msg = ''
 | 
						|
  if (addedQ > 0) // if there are more than 0 new question
 | 
						|
  {
 | 
						|
    msg = 'Klikk ide a nyers adatokhoz. ' + addedQ +
 | 
						|
			' új kérdés!'
 | 
						|
 | 
						|
    var useNetDB = GM_getValue('useNetDB')
 | 
						|
    if (useNetDB != undefined && useNetDB == 1) {
 | 
						|
      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.' }
 | 
						|
    } else { msg += 'Ne felejtsd el bemásolni a fő txt-be!' }
 | 
						|
  } else // if there is 0 or less new question
 | 
						|
  {
 | 
						|
    msg = 'A kérdőívben nincsen új kérdés. Ha mégis le akarod menteni klikk ide.'
 | 
						|
    if (!data) { msg += ' Lehet azért, mert nincs kérdés betöltve.' }
 | 
						|
  }
 | 
						|
  // showing a message wit the click event, and the generated page
 | 
						|
  ShowMessage({
 | 
						|
    m: msg,
 | 
						|
    isSimple: true
 | 
						|
  }, null, function () {
 | 
						|
    var towrite = '<h3>' + sentData.subj + '<br>TXT-ben nem szereplő kérdések: ' + addedQ + '/' +
 | 
						|
			allQ + '</h3><br>' +
 | 
						|
			output.replace(/\n/g, '<br>') + '<br><h3>Összes kérdés/válasz:</h3>' + allOutput.replace(
 | 
						|
      /\n/g, '<br>')
 | 
						|
 | 
						|
    var useNetDB = GM_getValue('useNetDB')
 | 
						|
    if (useNetDB != undefined && useNetDB == 1) {
 | 
						|
      try {
 | 
						|
        towrite += '</p>Elküldött adatok:</p> ' + JSON.stringify(sentData)
 | 
						|
      } catch (e) {
 | 
						|
        towrite += '</p>Elküldött adatok:</p> ' + sentData
 | 
						|
      }
 | 
						|
    }
 | 
						|
    document.write(towrite)
 | 
						|
    document.close()
 | 
						|
  })
 | 
						|
}
 | 
						|
 | 
						|
function SearchSameQuestion (questionData, quiz, i) {
 | 
						|
  var r = questionData.Search(quiz[i])
 | 
						|
 | 
						|
  let count = 0
 | 
						|
  r.forEach((item) => {
 | 
						|
    if (item.match > minResultMatchPercent) { count++ }
 | 
						|
  })
 | 
						|
 | 
						|
  return count == 0 ? -1 : count
 | 
						|
}
 | 
						|
 | 
						|
// this should get the image url from a result page
 | 
						|
// i is the index of the question
 | 
						|
function GetImageFormResult (i) {
 | 
						|
  var temp = null
 | 
						|
  try {
 | 
						|
    var imgElements = RPM.GetResultImage(i) // trying to get image
 | 
						|
    var imgURL = [] // image urls
 | 
						|
    for (var j = 0; j < imgElements.length; j++) {
 | 
						|
      if (!imgElements[j].src.includes('brokenfile')) // idk why brokenfile is in some urls, which are broken, so why tf are they there damn moodle
 | 
						|
      {
 | 
						|
        var filePart = imgElements[j].src.split('/') // splits the link by "/"
 | 
						|
        filePart = filePart[filePart.length - 1] // the last one is the image name
 | 
						|
        imgURL.push(decodeURI(SUtils.ShortenString(filePart, 30)))
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (imgURL.length > 0) {
 | 
						|
      temp = JSON.stringify(imgURL)
 | 
						|
      return temp
 | 
						|
    }
 | 
						|
  } catch (e) {
 | 
						|
    Log("Couldn't get images from result")
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// saves the current quiz. questionData contains the active subjects questions
 | 
						|
function SaveQuiz (quiz, questionData) {
 | 
						|
  try {
 | 
						|
    if (quiz.length == 0) {
 | 
						|
      throw {
 | 
						|
        message: 'quiz length is zero!',
 | 
						|
        stack: 'no stack.'
 | 
						|
      }
 | 
						|
    }
 | 
						|
    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++) // going though quiz
 | 
						|
    {
 | 
						|
      // 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
 | 
						|
      if (quiz[i].HasImage()) {
 | 
						|
        toAdd += '>' + SUtils.RemoveUnnecesarySpaces(quiz[i].I) + '\n' // adding quiz image if there is any
 | 
						|
      }
 | 
						|
      if (SearchSameQuestion(questionData, quiz, i) == -1) // if there is no such item in the database (w/ same q and a)
 | 
						|
      {
 | 
						|
        output += toAdd // adding to output
 | 
						|
        newQuestions.push(quiz[i])
 | 
						|
        addedQ++
 | 
						|
      }
 | 
						|
      allOutput += toAdd // adding to all
 | 
						|
      allQ++
 | 
						|
    }
 | 
						|
    var sendSuccess = false
 | 
						|
    var sentData = {}
 | 
						|
    try {
 | 
						|
      try {
 | 
						|
        sentData.subj = MPM.GetCurrentSubjectName()
 | 
						|
      } catch (e) {
 | 
						|
        sentData.subj = 'NOSUBJ'
 | 
						|
        Log('unable to get subject name :c')
 | 
						|
      }
 | 
						|
      var useNetDB = GM_getValue('useNetDB')
 | 
						|
      if (useNetDB != undefined && useNetDB == 1) {
 | 
						|
        sentData.allData = quiz
 | 
						|
        sentData.data = newQuestions
 | 
						|
        sentData.version = GM_info.script.version
 | 
						|
        SendXHRMessage('datatoadd=' + JSON.stringify(sentData))
 | 
						|
        sendSuccess = true
 | 
						|
      }
 | 
						|
    } 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')
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// getting quiz from finish page
 | 
						|
function GetQuiz () {
 | 
						|
  try {
 | 
						|
    var quiz = [] // final quiz stuff
 | 
						|
    var results = RPM.GetFormResult() // getting results element
 | 
						|
    for (var i = 0; i < results.length - 2; i++) // going through results, except last two, idk why, dont remember, go check it man
 | 
						|
    {
 | 
						|
      var question = {} // the current question
 | 
						|
      // QUESTION --------------------------------------------------------------------------------------------------------------------
 | 
						|
      var q = RPM.GetQuestionFromResult(i)
 | 
						|
      if (q != undefined) { question.q = SUtils.SimplifyQuery(q) }
 | 
						|
 | 
						|
      // RIGHTANSWER ---------------------------------------------------------------------------------------------------------------------
 | 
						|
      var a = RPM.GetRightAnswerFromResultv2(i)
 | 
						|
      if (a == undefined) { a = RPM.GetRightAnswerFromResult(i) }
 | 
						|
      if (a != undefined) { question.a = SUtils.SimplifyQuery(a) }
 | 
						|
      // IMG ---------------------------------------------------------------------------------------------------------------------
 | 
						|
      var img = GetImageFormResult(i)
 | 
						|
      question.i = img
 | 
						|
 | 
						|
      if (q != undefined) { q = SUtils.ReplaceCharsWithSpace(q, '\n') }
 | 
						|
      if (a != undefined) { a = SUtils.ReplaceCharsWithSpace(a, '\n') }
 | 
						|
 | 
						|
      if (question.a != undefined) // adding only if has question
 | 
						|
      {
 | 
						|
        quiz.push(new Question(question.q, question.a, question.i)) // adding current question to quiz
 | 
						|
      } else {
 | 
						|
        Log('error getting queston, no correct answer given, or its incorrect')
 | 
						|
        Log(question)
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return quiz
 | 
						|
  } catch (e) {
 | 
						|
    Exception(e, 'script error at quiz parsing:')
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// : }}}
 | 
						|
 | 
						|
// : Helpers {{{
 | 
						|
 | 
						|
function SimplifyImages (imgs) {
 | 
						|
  var questionImages = [] // the array for the image names in question
 | 
						|
  for (var i = 0; i < imgs.length; i++) // going through all image
 | 
						|
  {
 | 
						|
    if (!imgs[i].src.includes('brokenfile')) // if its includes borken file its broken. Its another moodle crap. So i just wont check those
 | 
						|
    {
 | 
						|
      var filePart = imgs[i].src.split('/') // splits the link by "/"
 | 
						|
      filePart = filePart[filePart.length - 1] // the last one is the image name
 | 
						|
      questionImages.push(decodeURI(SUtils.RemoveUnnecesarySpaces(SUtils.ShortenString(filePart, 30)))) // decodes uri codes, and removes exess spaces, and shortening it
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return questionImages
 | 
						|
}
 | 
						|
 | 
						|
// adds image names to image nodes
 | 
						|
function AddImageNamesToImages (imgs) {
 | 
						|
  for (var i = 0; i < imgs.length; i++) // going through all image
 | 
						|
  {
 | 
						|
    if (!imgs[i].src.includes('brokenfile')) // if its includes borken file its broken. Its another moodle crap. So i just wont check those
 | 
						|
    {
 | 
						|
      var filePart = imgs[i].src.split('/') // splits the link by "/"
 | 
						|
      filePart = filePart[filePart.length - 1] // the last one is the image name
 | 
						|
      var appedtTo = imgs[i].parentNode // it will be appended here
 | 
						|
      var mainDiv = document.createElement('div')
 | 
						|
      var fileName = SUtils.ShortenString(decodeURI(filePart), 15) // shortening name, couse it can be long as fuck
 | 
						|
      var textNode = document.createTextNode('(' + fileName + ')')
 | 
						|
      mainDiv.appendChild(textNode)
 | 
						|
      appedtTo.appendChild(mainDiv)
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// this function adds basic hotkeys for video controll.
 | 
						|
function AddVideoHotkeys (url) {
 | 
						|
  var seekTime = 20
 | 
						|
  document.addEventListener('keydown', function (e) // keydown event listener
 | 
						|
  {
 | 
						|
    try {
 | 
						|
      var video = MPM.GetVideo()
 | 
						|
      var keyCode = e.keyCode // getting keycode
 | 
						|
      if (keyCode == 32) // if the keycode is 32 (space)
 | 
						|
      {
 | 
						|
        e.preventDefault() // preventing default action (space scrolles down)
 | 
						|
        if (video.paused && video.buffered.length > 0) {
 | 
						|
          video.play()
 | 
						|
        } else {
 | 
						|
          video.pause()
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (keyCode == 39) // rigth : 39
 | 
						|
      {
 | 
						|
        video.currentTime += seekTime
 | 
						|
      }
 | 
						|
      if (keyCode == 37) // left : 37
 | 
						|
      {
 | 
						|
        video.currentTime -= seekTime
 | 
						|
      }
 | 
						|
    } catch (err) {
 | 
						|
      Log('Hotkey error.')
 | 
						|
      Log(err.message)
 | 
						|
    }
 | 
						|
  })
 | 
						|
  var toadd = MPM.GetVideoElement()
 | 
						|
  var node = CreateNodeWithText(toadd,
 | 
						|
    'Miután elindítottad: Play/pause: space. Seek: Bal/jobb nyíl.')
 | 
						|
  node.style.margin = '5px 5px 5px 5px' // fancy margin
 | 
						|
}
 | 
						|
 | 
						|
// simple sort.
 | 
						|
function SortByPercent (results) {
 | 
						|
  for (var i = 0; i < results.length; i++) {
 | 
						|
    for (var j = results.length - 1; j > i; j--) {
 | 
						|
      if (results[i].p < results[j].p) {
 | 
						|
        var temp = results[i]
 | 
						|
        results[i] = results[j]
 | 
						|
        results[j] = temp
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return results
 | 
						|
}
 | 
						|
 | 
						|
// removes stuff like " a. q1" -> "q1"
 | 
						|
function RemoveLetterMarking (inp) {
 | 
						|
  let dotIndex = inp.indexOf('.')
 | 
						|
  let doubledotIndex = inp.indexOf(':')
 | 
						|
  let maxInd = 4 // inp.length * 0.2;
 | 
						|
 | 
						|
  if (dotIndex < maxInd) { return SUtils.RemoveUnnecesarySpaces(inp.substr(inp.indexOf('.') + 1, inp.length)) } else if (doubledotIndex < maxInd) { return SUtils.RemoveUnnecesarySpaces(inp.substr(inp.indexOf(':') + 1, inp.length)) } else { return inp }
 | 
						|
}
 | 
						|
 | 
						|
// highlights the possible solutions to the current question
 | 
						|
function HighLightAnswer (results, currQuestionNumber) {
 | 
						|
  try {
 | 
						|
    if (results.length > 0) // if there are items in the result
 | 
						|
    {
 | 
						|
      var answers = RPM.GetAllAnswer(currQuestionNumber) // getting all answers
 | 
						|
      var toColor = [] // the numberth in the array will be colored, and .length items will be colored
 | 
						|
      var type = '' // type of the question. radio or ticbox or whatitscalled
 | 
						|
      for (var i = 0; i < answers.length; i++) // going thtough answers
 | 
						|
      {
 | 
						|
        if (answers[i].tagName && answers[i].tagName.toLowerCase() == 'div') // if its not null and is "div"
 | 
						|
        {
 | 
						|
          var correct = results[0].q.A.toLowerCase() // getting current correct answer from data
 | 
						|
          var answer = answers[i].innerText.replace(/\n/g, '').toLowerCase() // getting current answer
 | 
						|
 | 
						|
          // removing stuff like "a."
 | 
						|
          answer = RemoveLetterMarking(answer)
 | 
						|
 | 
						|
          if (SUtils.EmptyOrWhiteSpace(correct) || SUtils.EmptyOrWhiteSpace(answer)) { continue }
 | 
						|
 | 
						|
          if (SUtils.NormalizeSpaces(SUtils.RemoveUnnecesarySpaces(correct)).includes(answer)) // if the correct answer includes the current answer
 | 
						|
          {
 | 
						|
            toColor.push(i) // adding the index
 | 
						|
            type = MPM.GetInputType(answers, i) // setting the type
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (results[0].match == 100) // if the result is 100% correct
 | 
						|
      {
 | 
						|
        if (type !== 'radio' || toColor.length == 1) // TODO why not radio
 | 
						|
        {
 | 
						|
          for (var i = 0; i < toColor.length; i++) // going through "toColor"
 | 
						|
          { answers[toColor[i]].style.backgroundColor = '#8cff66' }
 | 
						|
        }
 | 
						|
      } // and coloring the correct index
 | 
						|
    }
 | 
						|
  } catch (e) // catching errors. Sometimes there are random errors, wich i did not test, but they are rare, and does not break the main script.
 | 
						|
  {
 | 
						|
    Log('script error at highlightin answer: ' + e.message)
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// : }}}
 | 
						|
 | 
						|
function Log (value) {
 | 
						|
  if (log) { console.log(value) }
 | 
						|
}
 | 
						|
 | 
						|
function Exception (e, msg) {
 | 
						|
  Log('------------------------------------------')
 | 
						|
  Log(msg)
 | 
						|
  Log(e.message)
 | 
						|
  Log('------------------------------------------')
 | 
						|
  Log(e.stack)
 | 
						|
  Log('------------------------------------------')
 | 
						|
}
 | 
						|
 | 
						|
// : }}}
 | 
						|
 | 
						|
// : Minor UI stuff {{{
 | 
						|
 | 
						|
// shows a message with "msg" text, "matchPercent" tip and transp, and "timeout" time
 | 
						|
function ShowMessage (msgItem, timeout, funct) {
 | 
						|
  // msgItem help:
 | 
						|
  // [ [ {}{}{}{} ] [ {}{}{} ] ]
 | 
						|
  // msgItem[] <- a questions stuff
 | 
						|
  // msgItem[][] <- a questions relevant answers array
 | 
						|
  // msgItem[][].p <- a questions precent
 | 
						|
  // msgItem[][].m <- a questions message
 | 
						|
  try {
 | 
						|
    var defMargin = '0px 5px 0px 5px'
 | 
						|
    var isSimpleMessage = false
 | 
						|
    var simpleMessageText = ''
 | 
						|
    if (msgItem.isSimple) // parsing msgItem for easier use
 | 
						|
    {
 | 
						|
      simpleMessageText = msgItem.m
 | 
						|
      if (simpleMessageText == '') {
 | 
						|
        return
 | 
						|
      }
 | 
						|
      msgItem = [
 | 
						|
        [{
 | 
						|
          m: simpleMessageText
 | 
						|
        }]
 | 
						|
      ]
 | 
						|
      isSimpleMessage = true
 | 
						|
    }
 | 
						|
 | 
						|
    var appedtTo = document.body // will be appended here
 | 
						|
    var width = window.innerWidth - window.innerWidth / 6 // with of the box
 | 
						|
    var startFromLeft = window.innerWidth / 2 - width / 2 // dont change this
 | 
						|
    var startFromTop = 25 // top distance
 | 
						|
 | 
						|
    var mainDiv = document.createElement('div') // the main divider, wich items will be attached to
 | 
						|
    mainDiv.setAttribute('id', 'messageMainDiv')
 | 
						|
    if (funct) // if there is a function as parameter
 | 
						|
    {
 | 
						|
      addEventListener(mainDiv, 'click', funct) // adding it as click
 | 
						|
    }
 | 
						|
    // lotsa crap style
 | 
						|
    mainDiv.style.position = 'fixed'
 | 
						|
    mainDiv.style.zIndex = 999999
 | 
						|
    mainDiv.style.textAlign = 'center'
 | 
						|
    mainDiv.style.width = width + 'px'
 | 
						|
    // mainDiv.style.height = height + 'px';
 | 
						|
    mainDiv.style.padding = '0px'
 | 
						|
    mainDiv.style.background = '#222d32' // background color
 | 
						|
    mainDiv.style.color = '#ffffff' // text color
 | 
						|
    mainDiv.style.borderColor = '#035a8f' // border color
 | 
						|
    mainDiv.style.border = 'none'
 | 
						|
    mainDiv.style.top = (startFromTop) + 'px'
 | 
						|
    mainDiv.style.left = (window.innerWidth - width) / 2 + 'px'
 | 
						|
    mainDiv.style.opacity = '0.9' // setting starting opacity
 | 
						|
    mainDiv.setAttribute('id', 'scriptMessage')
 | 
						|
    var matchPercent = msgItem[0][0].p
 | 
						|
    if (isSimpleMessage) {
 | 
						|
      var simpleMessageParagrapg = document.createElement('p') // new paragraph
 | 
						|
      simpleMessageParagrapg.style.margin = defMargin // fancy margin
 | 
						|
      var splitText = simpleMessageText.split('\n')
 | 
						|
      for (var i = 0; i < splitText.length; i++) {
 | 
						|
        var mesageNode = CreateNodeWithText(simpleMessageParagrapg, splitText[i])
 | 
						|
        mesageNode.style.margin = defMargin // fancy margin
 | 
						|
      }
 | 
						|
      mainDiv.appendChild(simpleMessageParagrapg) // adding text box to main div
 | 
						|
    } else // if its a fucking complicated message
 | 
						|
    {
 | 
						|
      // TABLE SETUP ------------------------------------------------------------------------------------------------------------
 | 
						|
      var table = document.createElement('table')
 | 
						|
      table.style.width = '100%'
 | 
						|
      // ROWS -----------------------------------------------------------------------------------------------------
 | 
						|
      var rowOne = table.insertRow() // previous suggestion, question text, and prev question
 | 
						|
      var rowTwo = table.insertRow() // next question button
 | 
						|
      var rowThree = table.insertRow() // next suggetsion button
 | 
						|
      // CELLS -----------------------------------------------------------------------------------------------------
 | 
						|
      // row one
 | 
						|
      var numberTextCell = rowOne.insertCell()
 | 
						|
      var questionCell = rowOne.insertCell() // QUESTION CELL
 | 
						|
      questionCell.setAttribute('id', 'questionCell')
 | 
						|
      questionCell.rowSpan = 3
 | 
						|
      questionCell.style.width = '90%'
 | 
						|
      var prevQuestionCell = rowOne.insertCell()
 | 
						|
      // row two
 | 
						|
      var percentTextCell = rowTwo.insertCell()
 | 
						|
      var nextQuestionCell = rowTwo.insertCell()
 | 
						|
      // row three
 | 
						|
      var prevSuggestionCell = rowThree.insertCell()
 | 
						|
      var nextSuggestionCell = rowThree.insertCell()
 | 
						|
      // adding finally
 | 
						|
      mainDiv.appendChild(table)
 | 
						|
      // PERCENT TEXT SETUP -----------------------------------------------------------------------------------------------------
 | 
						|
      var percentTextBox = CreateNodeWithText(percentTextCell, '')
 | 
						|
      percentTextBox.setAttribute('id', 'percentTextBox')
 | 
						|
 | 
						|
      if (matchPercent) // if match percent param is not null
 | 
						|
      {
 | 
						|
        percentTextBox.innerText = matchPercent + '%'
 | 
						|
      }
 | 
						|
      // NUMBER SETUP -----------------------------------------------------------------------------------------------------
 | 
						|
      var numberTextBox = CreateNodeWithText(numberTextCell, '1.')
 | 
						|
      numberTextBox.setAttribute('id', 'numberTextBox')
 | 
						|
 | 
						|
      // ANSWER NODE SETUP -------------------------------------------------------------------------------------------------------------
 | 
						|
      var questionTextElement = CreateNodeWithText(questionCell, 'ur question goes here, mister OwO')
 | 
						|
      questionTextElement.setAttribute('id', 'questionTextElement')
 | 
						|
 | 
						|
      // BUTTON SETUP -----------------------------------------------------------------------------------------------------------
 | 
						|
      var currItem = 0
 | 
						|
      var currRelevantQuestion = 0
 | 
						|
 | 
						|
      function GetRelevantQuestion () // returns the currItemth questions currRelevantQuestionth relevant question
 | 
						|
      {
 | 
						|
        return msgItem[currItem][currRelevantQuestion]
 | 
						|
      }
 | 
						|
 | 
						|
      function ChangeCurrItemIndex (to) {
 | 
						|
        currItem += to
 | 
						|
        if (currItem < 0) {
 | 
						|
          currItem = 0
 | 
						|
        }
 | 
						|
        if (currItem > msgItem.length - 1) {
 | 
						|
          currItem = msgItem.length - 1
 | 
						|
        }
 | 
						|
        currRelevantQuestion = 0
 | 
						|
      }
 | 
						|
 | 
						|
      function ChangeCurrRelevantQuestionIndex (to) {
 | 
						|
        currRelevantQuestion += to
 | 
						|
        if (currRelevantQuestion < 0) {
 | 
						|
          currRelevantQuestion = 0
 | 
						|
        }
 | 
						|
        if (currRelevantQuestion > msgItem[currItem].length - 1) {
 | 
						|
          currRelevantQuestion = msgItem[currItem].length - 1
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      function SetQuestionText () {
 | 
						|
        var relevantQuestion = GetRelevantQuestion()
 | 
						|
        questionTextElement.innerText = relevantQuestion.m
 | 
						|
        if (currItem == 0 && currRelevantQuestion == 0) {
 | 
						|
          numberTextBox.innerText = (currRelevantQuestion + 1) + '.'
 | 
						|
        } else {
 | 
						|
          numberTextBox.innerText = (currItem + 1) + './' + (currRelevantQuestion + 1) + '.'
 | 
						|
        }
 | 
						|
        percentTextBox.innerText = relevantQuestion.p + '%'
 | 
						|
      }
 | 
						|
 | 
						|
      var buttonMargin = '2px 2px 2px 2px' // uniform button margin
 | 
						|
      if (msgItem[currItem].length > 1) {
 | 
						|
        // PREV SUGG BUTTON ------------------------------------------------------------------------------------------------------------
 | 
						|
        var prevSuggButton = CreateNodeWithText(prevSuggestionCell, '<', 'button')
 | 
						|
        prevSuggButton.style.margin = buttonMargin // fancy margin
 | 
						|
 | 
						|
        prevSuggButton.addEventListener('click', function () {
 | 
						|
          ChangeCurrRelevantQuestionIndex(-1)
 | 
						|
          SetQuestionText()
 | 
						|
        })
 | 
						|
        // NEXT SUGG BUTTON ------------------------------------------------------------------------------------------------------------
 | 
						|
        var nextSuggButton = CreateNodeWithText(nextSuggestionCell, '>', 'button')
 | 
						|
        nextSuggButton.style.margin = buttonMargin // fancy margin
 | 
						|
 | 
						|
        nextSuggButton.addEventListener('click', function () {
 | 
						|
          ChangeCurrRelevantQuestionIndex(1)
 | 
						|
          SetQuestionText()
 | 
						|
        })
 | 
						|
      }
 | 
						|
      // deciding if has multiple questions ------------------------------------------------------------------------------------------------
 | 
						|
      if (msgItem.length == 1) {
 | 
						|
        SetQuestionText()
 | 
						|
      } else // if there are multiple items to display
 | 
						|
      {
 | 
						|
        // PREV QUESTION BUTTON ------------------------------------------------------------------------------------------------------------
 | 
						|
        var prevButton = CreateNodeWithText(prevQuestionCell, '^', 'button')
 | 
						|
        prevButton.style.margin = buttonMargin // fancy margin
 | 
						|
 | 
						|
        // event listener
 | 
						|
        prevButton.addEventListener('click', function () {
 | 
						|
          ChangeCurrItemIndex(-1)
 | 
						|
          SetQuestionText()
 | 
						|
        })
 | 
						|
        // NEXT QUESTION BUTTON ------------------------------------------------------------------------------------------------------------
 | 
						|
        var nextButton = CreateNodeWithText(nextQuestionCell, 'ˇ', 'button')
 | 
						|
        nextButton.style.margin = buttonMargin // fancy margin
 | 
						|
 | 
						|
        // event listener
 | 
						|
        nextButton.addEventListener('click', function () {
 | 
						|
          ChangeCurrItemIndex(1)
 | 
						|
          SetQuestionText()
 | 
						|
        })
 | 
						|
        SetQuestionText()
 | 
						|
      }
 | 
						|
    }
 | 
						|
    appedtTo.appendChild(mainDiv) // THE FINAL APPEND
 | 
						|
 | 
						|
    // setting some events
 | 
						|
    // addEventListener(window, 'scroll', function () {
 | 
						|
    //	mainDiv.style.top = (pageYOffset + startFromTop) + 'px';
 | 
						|
    // })
 | 
						|
    addEventListener(window, 'resize', function () {
 | 
						|
      mainDiv.style.left = (window.innerWidth - width) / 2 + 'px'
 | 
						|
    })
 | 
						|
    var timeOut
 | 
						|
    if (timeout && timeout > 0) // setting timeout if not zero or null
 | 
						|
    {
 | 
						|
      timeOut = setTimeout(function () {
 | 
						|
        mainDiv.parentNode.removeChild(mainDiv)
 | 
						|
      }, timeout * 1000)
 | 
						|
    }
 | 
						|
    // middle click close event listener
 | 
						|
    addEventListener(mainDiv, 'mousedown', function (e) {
 | 
						|
      if (e.which == 2) {
 | 
						|
        mainDiv.parentNode.removeChild(mainDiv)
 | 
						|
        if (timeOut) {
 | 
						|
          clearTimeout(timeOut)
 | 
						|
        }
 | 
						|
      }
 | 
						|
    })
 | 
						|
  } catch (e) {
 | 
						|
    Exception(e, 'script error at showing message:')
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// shows a fancy menu
 | 
						|
function ShowMenu () {
 | 
						|
  try {
 | 
						|
    var buttonWidth = 100 // button size ;)
 | 
						|
    var buttonHeight = 85
 | 
						|
    var appedtTo = document.body // will be appended here
 | 
						|
 | 
						|
    // mainDiv.style.left = (window.innerWidth - width) / 2 + 'px';
 | 
						|
 | 
						|
    var menuButtonDiv = document.createElement('div')
 | 
						|
    menuButtonDiv.style.width = buttonWidth + 'px'
 | 
						|
    menuButtonDiv.style.height = buttonHeight + 'px'
 | 
						|
    menuButtonDiv.style.top = (window.innerHeight - buttonHeight * 1.5) + 'px'
 | 
						|
    menuButtonDiv.style.left = window.innerWidth - buttonWidth * 1.5 + 'px'
 | 
						|
    menuButtonDiv.style.zIndex = 999999 // TO THE MAX
 | 
						|
    menuButtonDiv.style.position = 'fixed'
 | 
						|
    // menuButtonDiv.style.borderStyle = "solid";
 | 
						|
    // menuButtonDiv.style.borderWidth = "1px";
 | 
						|
 | 
						|
    // design
 | 
						|
    menuButtonDiv.style.textAlign = 'center'
 | 
						|
    menuButtonDiv.style.padding = '0px'
 | 
						|
    menuButtonDiv.style.margin = '0px'
 | 
						|
    menuButtonDiv.style.background = 'transparent' // background color
 | 
						|
 | 
						|
    // menu text
 | 
						|
    // var menuTextBox = CreateNodeWithText(menuButtonDiv, "Kérdések\nMenü");
 | 
						|
 | 
						|
    var menuButton = CreateNodeWithText(menuButtonDiv, 'Kérdések Menu', 'button')
 | 
						|
    menuButton.style.width = buttonWidth + 'px'
 | 
						|
    menuButton.style.border = 'none'
 | 
						|
    menuButton.style.height = buttonHeight - 20 + 'px'
 | 
						|
    menuButton.style.background = '#222d32' // background color
 | 
						|
    menuButton.style.color = '#ffffff' // background color
 | 
						|
    menuButton.setAttribute('id', 'HelperMenuButton')
 | 
						|
 | 
						|
    menuButton.addEventListener('click', function () {
 | 
						|
      if (document.getElementById('HelperMenu') == null) {
 | 
						|
        ShowMenuList()
 | 
						|
      } else {
 | 
						|
        CloseMenu()
 | 
						|
      }
 | 
						|
    }) // adding click
 | 
						|
 | 
						|
    // passive mode stuff
 | 
						|
    var questionsTickBox = document.createElement('input')
 | 
						|
    questionsTickBox.type = 'checkbox'
 | 
						|
    questionsTickBox.checked = GM_getValue('skipLoad')
 | 
						|
    questionsTickBox.style.position = ''
 | 
						|
    questionsTickBox.style.left = 10 + 'px'
 | 
						|
    questionsTickBox.style.margin = '5px 5px 5px 5px' // fancy margin
 | 
						|
    questionsTickBox.style.top = 0 + 'px'
 | 
						|
 | 
						|
    menuButtonDiv.appendChild(questionsTickBox) // adding to main div
 | 
						|
 | 
						|
    questionsTickBox.addEventListener('click', function () {
 | 
						|
      GM_setValue('skipLoad', questionsTickBox.checked)
 | 
						|
      var msg = ''
 | 
						|
      if (GM_getValue('skipLoad')) { msg = 'Passzív mód bekapcsolva, mostantól kérdések nem lesznek betöltve/lekérve.' } else { msg = 'Passzív mód kikapcsolva, frissíts az érvénybe lépéshez!' }
 | 
						|
 | 
						|
      ShowMessage({
 | 
						|
        m: msg,
 | 
						|
        isSimple: true
 | 
						|
      }, 6)
 | 
						|
    })
 | 
						|
    var loadDataCheckBoxText = CreateNodeWithText(questionsTickBox,
 | 
						|
      'Passzív mód', 'span')
 | 
						|
    loadDataCheckBoxText.style.fontSize = '12px'
 | 
						|
 | 
						|
    menuButtonDiv.appendChild(loadDataCheckBoxText)
 | 
						|
 | 
						|
    addEventListener(window, 'resize', function () {
 | 
						|
      menuButtonDiv.style.left = window.innerWidth - buttonWidth * 2 + 'px'
 | 
						|
    })
 | 
						|
 | 
						|
    appedtTo.appendChild(menuButtonDiv)
 | 
						|
  } catch (e) {
 | 
						|
    Exception(e, 'script error at showing menu:')
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// shows a fancy menu list with the subjects
 | 
						|
function ShowMenuList () {
 | 
						|
  try {
 | 
						|
    var appedtTo = document.body // will be appended here
 | 
						|
 | 
						|
    var menuDiv = document.createElement('div')
 | 
						|
    menuDiv.setAttribute('id', 'HelperMenu')
 | 
						|
    menuDiv.style.width = (window.innerWidth / 2) + 'px'
 | 
						|
    menuDiv.style.top = (window.innerHeight / 10) + 'px'
 | 
						|
    menuDiv.style.left = window.innerWidth / 2 - (window.innerWidth / 2) / 2 + 'px'
 | 
						|
    menuDiv.style.zIndex = 999999
 | 
						|
    menuDiv.style.position = 'fixed'
 | 
						|
 | 
						|
    // design
 | 
						|
    menuDiv.style.textAlign = 'center'
 | 
						|
    menuDiv.style.padding = '0px'
 | 
						|
    menuDiv.style.background = '#222d32' // background color
 | 
						|
    menuDiv.style.color = '#ffffff' // text color
 | 
						|
    menuDiv.style.borderColor = '#035a8f' // border color
 | 
						|
    menuDiv.style.border = 'none'
 | 
						|
    menuDiv.style.opacity = '1' // setting starting opacity
 | 
						|
 | 
						|
    var fiveMargin = '5px 5px 5px 5px'
 | 
						|
    var tbl = document.createElement('table')
 | 
						|
    tbl.style.margin = fiveMargin
 | 
						|
    tbl.style.textAlign = 'left'
 | 
						|
    tbl.style.width = '98%'
 | 
						|
 | 
						|
    // adding headers ---------------------------------------------------------------------------------------------------------------
 | 
						|
    var subjTable = document.createElement('table')
 | 
						|
    subjTable.style.margin = fiveMargin
 | 
						|
    subjTable.style.textAlign = 'left'
 | 
						|
    subjTable.style.width = '98%'
 | 
						|
 | 
						|
    var tr = subjTable.insertRow()
 | 
						|
    var header1 = tr.insertCell()
 | 
						|
 | 
						|
    var headerSubjInfoParagraph = CreateNodeWithText(header1, 'Tárgynév [darab kérdés]', 'center')
 | 
						|
    headerSubjInfoParagraph.style.margin = fiveMargin // fancy margin
 | 
						|
 | 
						|
    var header2 = tr.insertCell()
 | 
						|
    var headerSubjInfoParagraph = CreateNodeWithText(header2, 'Aktív')
 | 
						|
    headerSubjInfoParagraph.style.margin = fiveMargin // fancy margin
 | 
						|
 | 
						|
    if (data && data.length > 0) {
 | 
						|
      for (let i = 0; i < data.length; i++) {
 | 
						|
        var subjRow = subjTable.insertRow()
 | 
						|
        subjRow.style.border = '1px solid #131319'
 | 
						|
 | 
						|
        var td = subjRow.insertCell()
 | 
						|
        var text = data.Subjects[i].Name
 | 
						|
        if (data.Subjects[i].length != 0) { text += ' [ ' + data.Subjects[i].length + 'db ]' }
 | 
						|
 | 
						|
        var textBox = CreateNodeWithText(td, text)
 | 
						|
 | 
						|
        textBox.style.margin = fiveMargin // fancy margin
 | 
						|
 | 
						|
        td = subjRow.insertCell()
 | 
						|
        var 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
 | 
						|
 | 
						|
        var active = data.GetIfActive(i)
 | 
						|
        checkbox.checked = active
 | 
						|
 | 
						|
        checkbox.setAttribute('id', 'HelperTextNode' + i)
 | 
						|
 | 
						|
        checkbox.addEventListener('click', function () {
 | 
						|
          var checked = document.getElementById('HelperTextNode' + i).checked
 | 
						|
          data.ChangeActive(i, checked)
 | 
						|
        }) // adding click
 | 
						|
      }
 | 
						|
 | 
						|
      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()
 | 
						|
      var textBox
 | 
						|
 | 
						|
      if (GM_getValue('skipLoad')) {
 | 
						|
        textBox = CreateNodeWithText(noDataRowCell,
 | 
						|
          'Passszív mód bekapcsolva. Kapcsold ki a kérdések betöltéséhez!'
 | 
						|
        )
 | 
						|
      } else {
 | 
						|
        textBox = CreateNodeWithText(noDataRowCell,
 | 
						|
          'A kérdéseket nem lehetett beolvasni. Vagy nem elérhető a szerver, vagy ha offline módot használsz, akkor hibás a fájl elérési útja, vagy a fájl maga. Olvasd el a manualt!'
 | 
						|
        )
 | 
						|
      }
 | 
						|
      textBox.style.margin = fiveMargin // fancy margin
 | 
						|
    }
 | 
						|
 | 
						|
    // show splash tickbox -----------------------------------------------------------------------------------------------------------------------------
 | 
						|
    var splasTickboxRow = tbl.insertRow()
 | 
						|
    var splashTickboxCell = splasTickboxRow.insertCell()
 | 
						|
 | 
						|
    var splashTickBox = document.createElement('input')
 | 
						|
    splashTickBox.type = 'checkbox'
 | 
						|
    splashTickBox.checked = GM_getValue('showSplash') || false
 | 
						|
    splashTickBox.style.position = ''
 | 
						|
    // splashTickBox.style.background = "white";
 | 
						|
    splashTickBox.style.left = 10 + 'px'
 | 
						|
    splashTickBox.style.margin = '5px 5px 5px 5px' // fancy margin
 | 
						|
    splashTickBox.style.top = menuDiv.offsetHeight + 'px'
 | 
						|
    splashTickboxCell.appendChild(splashTickBox) // adding to main div
 | 
						|
 | 
						|
    splashTickBox.addEventListener('click', function () {
 | 
						|
      GM_setValue('showSplash', splashTickBox.checked)
 | 
						|
    }) // adding clicktextNode
 | 
						|
 | 
						|
    var splashTickBoxTextSpan = CreateNodeWithText(splashTickboxCell,
 | 
						|
      'Üdvözlő üzenet mutatása minden oldalon', 'span')
 | 
						|
 | 
						|
    // show questons tickbox -----------------------------------------------------------------------------------------------------------------------------
 | 
						|
    var questionTickboxRow = tbl.insertRow()
 | 
						|
    var questionTickboxCell = questionTickboxRow.insertCell()
 | 
						|
 | 
						|
    var questionsTickBox = document.createElement('input')
 | 
						|
    questionsTickBox.type = 'checkbox'
 | 
						|
    questionsTickBox.checked = GM_getValue('showQuestions')
 | 
						|
    questionsTickBox.style.position = ''
 | 
						|
    // questionsTickBox.style.background = "white";
 | 
						|
    questionsTickBox.style.left = 10 + 'px'
 | 
						|
    questionsTickBox.style.margin = '5px 5px 5px 5px' // fancy margin
 | 
						|
    questionsTickBox.style.top = menuDiv.offsetHeight + 'px'
 | 
						|
    questionTickboxCell.appendChild(questionsTickBox) // adding to main div
 | 
						|
 | 
						|
    questionsTickBox.addEventListener('click', function () {
 | 
						|
      GM_setValue('showQuestions', questionsTickBox.checked)
 | 
						|
      if (!questionsTickBox.checked) {
 | 
						|
        ShowMessage({
 | 
						|
          m: 'Szinte mindég jó az talált válasz a kérdésre, de attól még könnyen előfordulhat, hogy rosz kérdésre írja ki a választ! Ez a opció nélkül ezt az ellenőrzési lehetőséget nem tudod kihasználni',
 | 
						|
          isSimple: true
 | 
						|
        }, 7)
 | 
						|
      }
 | 
						|
    }) // adding clicktextNode
 | 
						|
    var questionsTickBoxTextSpan = CreateNodeWithText(questionTickboxCell,
 | 
						|
      'Kérdések mutatása válaszhoz', 'span')
 | 
						|
 | 
						|
    // database mode listbox -----------------------------------------------------------------------------------------------------------------------------
 | 
						|
    var databasemodeListboxRow = tbl.insertRow()
 | 
						|
    var databasemodeListboxCell = databasemodeListboxRow.insertCell()
 | 
						|
 | 
						|
    var databasemodeListbox = document.createElement('select')
 | 
						|
    databasemodeListbox.type = 'checkbox'
 | 
						|
    // databasemodeListbox.checked = GM_getValue("showSplash") || false;
 | 
						|
    databasemodeListbox.style.position = ''
 | 
						|
    // databasemodeListbox.style.background = "white";
 | 
						|
    databasemodeListbox.style.left = 10 + 'px'
 | 
						|
    databasemodeListbox.style.margin = '5px 5px 5px 5px' // fancy margin
 | 
						|
    databasemodeListbox.style.top = menuDiv.offsetHeight + 'px'
 | 
						|
 | 
						|
    var databasemodeListboxText = CreateNodeWithText(questionTickboxCell,
 | 
						|
      'Kérdések beszerzése:', 'span')
 | 
						|
    databasemodeListboxCell.appendChild(databasemodeListboxText)
 | 
						|
 | 
						|
    databasemodeListboxCell.appendChild(databasemodeListbox) // adding to main div
 | 
						|
 | 
						|
    databasemodeListbox.addEventListener('change', function (e) {
 | 
						|
      // sorry for using selectedindex :c
 | 
						|
      GM_setValue('useNetDB', databasemodeListbox.selectedIndex)
 | 
						|
    })
 | 
						|
 | 
						|
    var uselocal = document.createElement('option')
 | 
						|
    uselocal.text = 'Helyi fájlból (old school)'
 | 
						|
    uselocal.value = 2
 | 
						|
    databasemodeListbox.add(uselocal, 0)
 | 
						|
 | 
						|
    var usenetsafe = document.createElement('option')
 | 
						|
    usenetsafe.text = 'Netről'
 | 
						|
    usenetsafe.value = 0
 | 
						|
    databasemodeListbox.add(usenetsafe, 1)
 | 
						|
 | 
						|
    var selected = GM_getValue('useNetDB')
 | 
						|
    if (selected != undefined) { databasemodeListbox.selectedIndex = selected }
 | 
						|
 | 
						|
    var databasemodeListboxElement = document.createElement('span') // new paragraph
 | 
						|
    databasemodeListboxCell.appendChild(databasemodeListboxElement)
 | 
						|
 | 
						|
    // setting up buttons
 | 
						|
    var buttonRow = tbl.insertRow()
 | 
						|
    var buttonCell = buttonRow.insertCell()
 | 
						|
    buttonCell.style.textAlign = 'center'
 | 
						|
    // x button ------------------------------------------------------------------------------------------------------------------------------
 | 
						|
    var xButton = CreateNodeWithText(buttonCell, 'Bezárás', 'button')
 | 
						|
 | 
						|
    xButton.style.position = ''
 | 
						|
    xButton.style.left = 10 + 'px'
 | 
						|
    xButton.style.margin = '5px 5px 5px 5px' // fancy margin
 | 
						|
    xButton.style.top = menuDiv.offsetHeight + 'px'
 | 
						|
 | 
						|
    xButton.addEventListener('click', function () {
 | 
						|
      CloseMenu()
 | 
						|
    }) // adding clicktextNode
 | 
						|
    // help button ----------------------------------------------------------------------------------------------------------------
 | 
						|
    var helpButton = CreateNodeWithText(buttonCell, 'Help', 'button')
 | 
						|
 | 
						|
    helpButton.style.position = ''
 | 
						|
    helpButton.style.left = 10 + 'px'
 | 
						|
    helpButton.style.margin = '5px 5px 5px 5px' // fancy margin
 | 
						|
    helpButton.style.top = menuDiv.offsetHeight + 'px'
 | 
						|
 | 
						|
    helpButton.addEventListener('click', function () {
 | 
						|
      ShowHelp()
 | 
						|
    }) // adding clicktextNode
 | 
						|
 | 
						|
    // site link ----------------------------------------------------------------------------------------------------------------
 | 
						|
 | 
						|
    var siteLink = CreateNodeWithText(buttonCell, 'Help', 'button')
 | 
						|
    siteLink.innerText = 'Weboldal'
 | 
						|
 | 
						|
    siteLink.addEventListener('click', function () {
 | 
						|
      location.href = serverAdress + 'menuClick'
 | 
						|
    })
 | 
						|
 | 
						|
    // addEventListener(window, 'scroll', function () {
 | 
						|
    //	menuDiv.style.top = (pageYOffset + window.innerHeight / 3) + 'px';
 | 
						|
    // })
 | 
						|
    addEventListener(window, 'resize', function () {
 | 
						|
      menuDiv.style.left = window.innerWidth / 2 + 'px'
 | 
						|
    })
 | 
						|
 | 
						|
    menuDiv.appendChild(tbl)
 | 
						|
    appedtTo.appendChild(menuDiv)
 | 
						|
  } catch (e) {
 | 
						|
    Exception(e, 'script error at showing menu list:')
 | 
						|
  }
 | 
						|
 | 
						|
  document.addEventListener('keydown', EscClose)
 | 
						|
}
 | 
						|
 | 
						|
function EscClose (e) {
 | 
						|
  if (e.keyCode == 27) { CloseMenu() }
 | 
						|
}
 | 
						|
 | 
						|
function CloseMenu () {
 | 
						|
  document.getElementById('HelperMenu').parentNode.removeChild(document.getElementById(
 | 
						|
    'HelperMenu'))
 | 
						|
 | 
						|
  document.removeEventListener('keydown', EscClose)
 | 
						|
}
 | 
						|
 | 
						|
// : }}}
 | 
						|
 | 
						|
// : Generic utils {{{
 | 
						|
 | 
						|
function RemoveMultipleItems (array) {
 | 
						|
  var newArray = []
 | 
						|
  for (var i = 0; i < array.length; i++) {
 | 
						|
    var j = 0
 | 
						|
    while (j < newArray.length && newArray[j] !== array[i]) {
 | 
						|
      j++
 | 
						|
    }
 | 
						|
    if (j >= newArray.length) {
 | 
						|
      newArray.push(array[i])
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return newArray
 | 
						|
}
 | 
						|
 | 
						|
function CreateNodeWithText (to, text, type) {
 | 
						|
  var paragraphElement = document.createElement(type || 'p') // new paragraph
 | 
						|
  var textNode = document.createTextNode(text)
 | 
						|
  paragraphElement.appendChild(textNode)
 | 
						|
  to.appendChild(paragraphElement)
 | 
						|
  return paragraphElement
 | 
						|
}
 | 
						|
 | 
						|
function SendXHRMessage (message) {
 | 
						|
  var url = serverAdress + 'isAdding'
 | 
						|
  GM_xmlhttpRequest({
 | 
						|
    method: 'POST',
 | 
						|
    url: url,
 | 
						|
    data: message,
 | 
						|
    headers: {
 | 
						|
      'Content-Type': 'application/x-www-form-urlencoded'
 | 
						|
    },
 | 
						|
    onerror: function (response) {
 | 
						|
      Log('XMLHTTP request POST error')
 | 
						|
    }
 | 
						|
  })
 | 
						|
}
 | 
						|
 | 
						|
var assert = (val) => {
 | 
						|
  if (!val) { throw new Error('Assertion failed') }
 | 
						|
}
 | 
						|
 | 
						|
// : }}}
 | 
						|
 | 
						|
// : Help {{{
 | 
						|
 | 
						|
// shows some neat help
 | 
						|
function ShowHelp () {
 | 
						|
  GM_openInTab(serverAdress + 'manual', {
 | 
						|
    active: true
 | 
						|
  })
 | 
						|
}
 | 
						|
 | 
						|
// : }}}
 | 
						|
 | 
						|
// I am not too proud to cry that He and he
 | 
						|
// Will never never go out of my mind.
 | 
						|
// All his bones crying, and poor in all but pain,
 | 
						|
 | 
						|
// Being innocent, he dreaded that he died
 | 
						|
// Hating his God, but what he was was plain:
 | 
						|
// An old kind man brave in his burning pride.
 | 
						|
 | 
						|
// The sticks of the house were his; his books he owned.
 | 
						|
// Even as a baby he had never cried;
 | 
						|
// Nor did he now, save to his secret wound.
 | 
						|
 | 
						|
// Out of his eyes I saw the last light glide.
 | 
						|
// Here among the liught of the lording sky
 | 
						|
// An old man is with me where I go
 | 
						|
 | 
						|
// Walking in the meadows of his son's eye
 | 
						|
// Too proud to cry, too frail to check the tears,
 | 
						|
// And caught between two nights, blindness and death.
 | 
						|
 | 
						|
// O deepest wound of all that he should die
 | 
						|
// On that darkest day.
 |