diff --git a/stable.js b/stable.js
index 6a007a3..3df0d3a 100644
--- a/stable.js
+++ b/stable.js
@@ -21,7 +21,7 @@
// ==UserScript==
// @name Moodle/Elearning/KMOOC test help
-// @version 1.6.3.0
+// @version 1.6.3.1
// @description Online Moodle/Elearning/KMOOC test help
// @author YourFriendlyNeighborhoodDealer
// @match https://elearning.uni-obuda.hu/main/*
@@ -34,2287 +34,2227 @@
// @grant GM_xmlhttpRequest
// @grant GM_openInTab
// @license GNU General Public License v3.0 or later
-// @supportURL qmining.tk
-// @contributionURL qmining.tk
+// @supportURL qmining.frylabs.net
+// @contributionURL qmining.frylabs.net
// @resource data file:///
// @namespace https://greasyfork.org/users/153067
// ==/UserScript==
(function() {
- 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.tk/";
-
- // 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 = false;
-
- 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 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) {
- if (typeof q2 == 'string') {
- var qmatchpercent = Question.CompareString(this.Q, q2);
-
- if (i == undefined || i.length == 0)
- return qmatchpercent;
- else {
- if (this.HasImage()) {
- const imatchpercent = this.HasImage() ? Question.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 = Question.CompareString(this.Q, q2.Q);
- const amatchpercent = Question.CompareString(this.A, q2.A);
- if (this.I != undefined) {
- const imatchpercent = this.I == undefined ? Question.CompareString(this.I.join(" "), q2.I.join(
- " ")) : 0;
- return (qmatchpercent + amatchpercent + imatchpercent) / 3;
- } else {
- return (qmatchpercent + amatchpercent) / 2;
- }
- }
- }
- static CompareString(s1, s2) {
- s1 = SimplifyStringForComparison(s1).split(" ");
- s2 = 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 Subject {
- constructor(n) {
- this.Name = n;
- this.Questions = [];
- }
- get length() {
- return this.Questions.length;
- }
- AddQuestion(q) {
- this.Questions.push(q);
- }
- Search(q, img) {
- var r = [];
- for (var 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 (var 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) {
- 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) {
- var r = [];
- for (var i = 0; i < this.length; i++)
- if (this.GetIfActive(i))
- r = r.concat(this.Subjects[i].Search(q, img));
-
- for (var 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) {
- 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");
- }
- }
- //: }}}
-
- //: 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 // trying to get tha current questions
- {
- allQuestions = this.GetAllQuestionsQtext(); // getting questions
- if (allQuestions.length == 0) // if there are no found questions
- {
- var ddq = this.GetAllQuestionsDropdown();
- if (EmptyOrWhiteSpace(ddq)) {
- var questionData = "";
- for (var j = 0; j < allQuestions.length; j++) {
- // TODO: test dis
- let subAllQuestions = allQuestions[j].childNodes;
- for (var i = 0; i < subAllQuestions.length; i++) {
- if (subAllQuestions[i].data != undefined && !EmptyOrWhiteSpace(subAllQuestions[i].data)) // if the current element has some text data to add
- {
- questionData += subAllQuestions[i].data + " "; // adding text to question data
- }
- }
- }
- questions = [questionData];
- } else
- questions = [ddq];
- } else // if there is
- {
- questions = [];
- for (var 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 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("
")[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++) {
-
- function 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) // if the qtext element is not 0 length
- {
- 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) // if there is dropdown list in the current question
- {
- 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 && !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) // if the rightanswer element is not 0 length
- 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 && 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 GetRightAnswerFromResult(i);
-
- for (var j = 0; j < items.length; j++) {
- var cn = items[j].className;
- if (cn.includes("correct") && !cn.includes("incorrect"))
- return items[j].innerText;
- }
- if (items.length == 2) {
- for (var j = 0; j < items.length; j++) {
- var 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();
-
- //: }}}
+ /* 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('
')[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++) {
+ function 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()
+
+ // : Main function {{{
+ function Main () {
+ 'use strict'
+ console.time('main')
+
+ Init(function (count, subjCount) {
+ var url = location.href
+
+ let skipLoad = GM_getValue('skipLoad')
+ 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', {
+ 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) {
+ GM_setValue('version16', undefined)
+ GM_setValue('version15', undefined)
+ GM_setValue('firstRun', undefined) // GM_getValue("lastVerson") == undefined => firstrun
+ GM_setValue('showQuestions', undefined)
+ GM_setValue('showSplash', undefined)
+ }
+ 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(
+ 'Moodle teszt userscript: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!
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!!!
Ez az ablak frissités után eltűnik. Ha nem, akkor a visza gombbal próbálkozz.
'
+ )
+ 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) // if its undefined, or 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(
+ 'Moodle teszt userscript: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
'
+ )
+ 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 = '' + sentData.subj + '
TXT-ben nem szereplő kérdések: ' + addedQ + '/' +
+ allQ + '
' +
+ output.replace(/\n/g, '
') + '
Összes kérdés/válasz:
' + allOutput.replace(
+ /\n/g, '
')
+
+ var useNetDB = GM_getValue('useNetDB')
+ if (useNetDB != undefined && useNetDB == 1) {
+ try {
+ towrite += '
Elküldött adatok: ' + JSON.stringify(sentData)
+ } catch (e) {
+ towrite += 'Elküldött adatok: ' + 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.
- Main();
-
- //: Main function {{{
- function Main() {
- 'use strict';
- console.time('main');
-
- Init(function(count, subjCount) {
- var url = location.href;
-
- let skipLoad = GM_getValue("skipLoad");
- 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', {
- active: true
- });
- });
- Exception(e, "script error at main:");
- }
- if (url.includes("eduplayer")) // if the current site is a video site
- 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) // reset, only for testing!
- {
- GM_setValue("version16", undefined);
- GM_setValue("version15", undefined);
- GM_setValue("firstRun", undefined); // GM_getValue("lastVerson") == undefined => firstrun
- GM_setValue("showQuestions", undefined);
- GM_setValue("showSplash", undefined);
- }
- 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) // if its undefined, or 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) // if its undefined, or true
- {
- GM_setValue("useNetDB", "0");
- GM_setValue("version15", false);
- document.write(
- 'Moodle teszt userscript: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!
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!!!
Ez az ablak frissités után eltűnik. Ha nem, akkor a visza gombbal próbálkozz.
'
- );
- 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) // if its undefined, or 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", "0");
- GM_setValue("version161", false);
- document.write(
- 'Moodle teszt userscript: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
'
- );
- 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 (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) {
- 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++;
- }
-
- // TODO: move this
- AlertOnNoQuestion(i);
-
- } catch (e) {
- Exception(e, "script error at loading:");
- count = -1; // returns -1 if error
- }
- cwith(count, subjCount);
- }
-
- var AlertOnNoQuestion = (i) => {
- try {
- if (i >= data.length)
- 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 {
- 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 (!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 = 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) {
- 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) {
- 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();
- SaveQuiz(GetQuiz(), data); // saves the quiz questions and answers
- }
-
- 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 = 'TXT-ben nem szereplő kérdések: ' + addedQ + '/' + allQ + '
' +
- output.replace(/\n/g, '
') + '
Összes kérdés/válasz:
' + allOutput.replace(
- /\n/g, '
');
-
- var useNetDB = GM_getValue("useNetDB");
- if (useNetDB != undefined && useNetDB == 1)
- towrite += "Elküldött adatok: " + sentData;
- document.write(towrite);
- document.close();
- });
- }
-
- function SearchSameQuestion(questionData, quiz, i) {
- var r = questionData.Search(quiz[i].Q);
-
- 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(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 += "?" + RemoveUnnecesarySpaces(quiz[i].Q) + "\n"; // adding quiz question
- toAdd += "!" + RemoveUnnecesarySpaces(quiz[i].A) + "\n"; // adding quiz answer
- if (quiz[i].HasImage()) {
- toAdd += ">" + 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.");
- }
- ShowSaveQuizDialog(addedQ, allQ, allOutput, output, sendSuccess, 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 = SimplifyQuery(q);
-
- // RIGHTANSWER ---------------------------------------------------------------------------------------------------------------------
- var a = RPM.GetRightAnswerFromResultv2(i);
- if (a == undefined)
- a = RPM.GetRightAnswerFromResult(i);
- if (a != undefined)
- question.a = SimplifyQuery(a);
- // IMG ---------------------------------------------------------------------------------------------------------------------
- var img = GetImageFormResult(i);
- question.i = img;
-
- if (q != undefined)
- q = ReplaceCharsWithSpace(q, "\n");
- if (a != undefined)
- a = 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(RemoveUnnecesarySpaces(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 = 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
- }
-
- function GetMatchPercent(currData, questionParts) {
- var currQuestion = SimplifyQuery(currData.q); // current question simplified
- var match = 0; // how many times the current question matches the current question in the database
- for (var i = 0; i < questionParts.length; i++) // going through the question parts
- {
- if (currQuestion.includes(questionParts[i])) // if the current question from questionData includes one of the question parts
- {
- match++;
- }
- }
- var percent = Math.round(((match / questionParts.length) * 100).toFixed(2)); // matched words percent
- var lengthDifference = RemoveMultipleItems(SimplifyQuery(currQuestion).split(" ")).length -
- questionParts.length;
- percent -= Math.abs(lengthDifference) * 2;
- return percent;
- }
-
- // 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 RemoveUnnecesarySpaces(inp.substr(inp.indexOf(".") + 1, inp.length));
- else if (doubledotIndex < maxInd)
- return 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 (EmptyOrWhiteSpace(correct) || EmptyOrWhiteSpace(answer))
- continue;
-
- if (NormalizeSpaces(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;
- }
-
- // removes some crap from "q"
- function SimplifyQuery(q) {
- var result = q.replace(/\n/g, " ").replace(/\s/g, ' '); // WHY TF ARE THERE TWO KINDA SPACES??? (charcode 160 n 32)
- return RemoveUnnecesarySpaces(result);
- }
-
- function ShortenString(toShorten, ammount) {
- var result = "";
- var i = 0;
- while (i < toShorten.length && i < ammount) {
- result += toShorten[i];
- i++;
- }
- return result;
- }
-
- 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 ReplaceCharsWithSpace(val, char) {
-
- assert(val);
- assert(char);
-
- toremove = NormalizeSpaces(val);
-
- var regex = new RegExp(char, "g");
- toremove.replace(regex, " ");
-
- return RemoveUnnecesarySpaces(toremove);
- }
-
- // removes whitespace from begining and and, and replaces multiple spaces with one space
- function RemoveUnnecesarySpaces(toremove) {
- toremove = NormalizeSpaces(toremove);
- while (toremove.includes(" ")) // while the text includes double spaces replaces all of them with a single one
- {
- toremove = toremove.replace(/ /g, " ");
- }
- return toremove.trim();
- }
-
- // simplifies a string for easier comparison
- function SimplifyStringForComparison(value) {
- value = 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
- function 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
- function NormalizeSpaces(input) {
- return input.replace(/\s/g, ' ');
- }
-
- 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.
-
})();