mirror of
https://gitlab.com/MrFry/moodle-test-userscript
synced 2025-04-01 20:22:48 +02:00
Removed lotsa stuff
This commit is contained in:
parent
2ae514b1fc
commit
2a612c1bd5
1 changed files with 91 additions and 365 deletions
406
stable.user.js
406
stable.user.js
|
@ -247,7 +247,7 @@
|
|||
console.warn('NO QUESTION FOR QTEXT')
|
||||
}
|
||||
question = question[0].innerText
|
||||
return SUtils.RemoveUnnecesarySpaces(question)
|
||||
return removeUnnecesarySpaces(question)
|
||||
}
|
||||
|
||||
function getBase64Image(img) {
|
||||
|
@ -298,102 +298,21 @@
|
|||
return input.replace(/\s/g, ' ')
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
||||
class StringUtils {
|
||||
removeMultipleEnters(text) {
|
||||
let res = text.replace(/\t/g, '')
|
||||
|
||||
while (res.includes('\n\n')) {
|
||||
res = res.replace('\n\n', '\n')
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
RemoveStuff(value, removableStrings, toReplace) {
|
||||
removableStrings.forEach(x => {
|
||||
var regex = new RegExp(x, 'g')
|
||||
value = value.replace(regex, toReplace || '')
|
||||
})
|
||||
return value
|
||||
}
|
||||
|
||||
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 = 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()
|
||||
}
|
||||
|
||||
RemoveSpecialChars(value) {
|
||||
assert(value)
|
||||
|
||||
return this.RemoveStuff(value, specialChars, ' ')
|
||||
}
|
||||
|
||||
// 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
|
||||
function emptyOrWhiteSpace(value) {
|
||||
if (value === undefined) {
|
||||
return true
|
||||
}
|
||||
|
||||
return (
|
||||
value
|
||||
.replace(/\n/g, '')
|
||||
.replace(/\t/g, '')
|
||||
.replace(/ /g, '')
|
||||
.replace(/\s/g, ' ') === ''
|
||||
)
|
||||
}
|
||||
|
||||
// damn nonbreaking space
|
||||
NormalizeSpaces(input) {
|
||||
assert(input)
|
||||
|
||||
return input.replace(/\s/g, ' ')
|
||||
}
|
||||
|
||||
SimplifyStack(stack) {
|
||||
return this.SimplifyQuery(stack)
|
||||
}
|
||||
}
|
||||
|
||||
const SUtils = new StringUtils()
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
||||
// : }}}
|
||||
|
||||
|
@ -530,151 +449,39 @@
|
|||
return overlayElement
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// Misc
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
||||
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++) {
|
||||
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 => {
|
||||
if (item) {
|
||||
return SUtils.ReplaceCharsWithSpace(item, '\n')
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
imgnodes: imgNodes,
|
||||
allQ: allQuestions,
|
||||
q: questions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MiscPageModell {
|
||||
GetCurrentSubjectName() {
|
||||
function getCurrentSubjectName() {
|
||||
if (logElementGetting) {
|
||||
Log('getting current subjects name')
|
||||
}
|
||||
return (
|
||||
document.getElementById('page-header').innerText.split('\n')[0] || ''
|
||||
)
|
||||
return document.getElementById('page-header').innerText.split('\n')[0] || ''
|
||||
}
|
||||
|
||||
GetVideo() {
|
||||
function getVideo() {
|
||||
if (logElementGetting) {
|
||||
Log('getting video stuff')
|
||||
}
|
||||
return document.getElementsByTagName('video')[0]
|
||||
}
|
||||
|
||||
GetVideoElement() {
|
||||
function getVideoElement() {
|
||||
if (logElementGetting) {
|
||||
Log('getting video element')
|
||||
}
|
||||
return document.getElementById('videoElement').parentNode
|
||||
}
|
||||
|
||||
GetInputType(answers, i) {
|
||||
function getInputType(answers, i) {
|
||||
if (logElementGetting) {
|
||||
Log('getting input type')
|
||||
}
|
||||
return answers[i].getElementsByTagName('input')[0].type
|
||||
}
|
||||
}
|
||||
|
||||
var QPM = new QuestionsPageModell()
|
||||
var MPM = new MiscPageModell()
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
||||
// : }}}
|
||||
|
||||
|
@ -973,7 +780,7 @@
|
|||
}
|
||||
|
||||
let showMOTD = false
|
||||
if (!SUtils.EmptyOrWhiteSpace(motd)) {
|
||||
if (!emptyOrWhiteSpace(motd)) {
|
||||
var prevmotd = getVal('motd')
|
||||
if (prevmotd !== motd) {
|
||||
showMOTD = true
|
||||
|
@ -1041,37 +848,35 @@
|
|||
// : Answering stuffs {{{
|
||||
|
||||
function HandleQuiz() {
|
||||
var q = QPM.GetQuestionFromTest()
|
||||
var questions = q.q
|
||||
var imgNodes = q.imgnodes
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
let promises = []
|
||||
questions.forEach(x => {
|
||||
let question = SUtils.EmptyOrWhiteSpace(x)
|
||||
? ''
|
||||
: SUtils.RemoveUnnecesarySpaces(x) // simplifying question
|
||||
promises.push(
|
||||
GetXHRQuestionAnswer({
|
||||
q: question,
|
||||
data: GetImageDataFromImgNodes(imgNodes),
|
||||
subj: MPM.GetCurrentSubjectName(),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
Promise.all(promises).then(res => {
|
||||
let answers = []
|
||||
|
||||
res.forEach((result, j) => {
|
||||
var r = PrepareAnswers(result, j)
|
||||
if (r !== undefined) {
|
||||
answers.push(r)
|
||||
}
|
||||
HighLightAnswer(result, j) // highlights the answer for the current result
|
||||
})
|
||||
|
||||
ShowAnswers(answers, q.q)
|
||||
})
|
||||
// TODO
|
||||
// var q = QPM.GetQuestionFromTest()
|
||||
// var questions = q.q
|
||||
// var imgNodes = q.imgnodes
|
||||
// // ------------------------------------------------------------------------------------------------------
|
||||
// let promises = []
|
||||
// questions.forEach(x => {
|
||||
// let question = SUtils.EmptyOrWhiteSpace(x)
|
||||
// ? ''
|
||||
// : SUtils.RemoveUnnecesarySpaces(x) // simplifying question
|
||||
// promises.push(
|
||||
// GetXHRQuestionAnswer({
|
||||
// q: question,
|
||||
// data: GetImageDataFromImgNodes(imgNodes),
|
||||
// subj: MPM.GetCurrentSubjectName(),
|
||||
// })
|
||||
// )
|
||||
// })
|
||||
// Promise.all(promises).then(res => {
|
||||
// let answers = []
|
||||
// res.forEach((result, j) => {
|
||||
// var r = PrepareAnswers(result, j)
|
||||
// if (r !== undefined) {
|
||||
// answers.push(r)
|
||||
// }
|
||||
// HighLightAnswer(result, j) // highlights the answer for the current result
|
||||
// })
|
||||
// ShowAnswers(answers, q.q)
|
||||
// })
|
||||
}
|
||||
|
||||
function PrepareAnswers(result, j) {
|
||||
|
@ -1183,7 +988,7 @@
|
|||
}
|
||||
try {
|
||||
try {
|
||||
sentData.subj = MPM.GetCurrentSubjectName()
|
||||
sentData.subj = getCurrentSubjectName()
|
||||
} catch (e) {
|
||||
sentData.subj = 'NOSUBJ'
|
||||
Log('unable to get subject name :c')
|
||||
|
@ -1207,48 +1012,24 @@
|
|||
|
||||
// : Helpers {{{
|
||||
|
||||
function GetImageDataFromImgNodes(imgs) {
|
||||
var questionImages = [] // the array for the image names in question
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
if (!imgs[i].src.includes('brokenfile')) {
|
||||
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
|
||||
}
|
||||
}
|
||||
if (questionImages.length > 0) {
|
||||
return {
|
||||
type: 'image',
|
||||
images: questionImages,
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
type: 'simple',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// adds image names to image nodes
|
||||
function AddImageNamesToImages(imgs) {
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
if (!imgs[i].src.includes('brokenfile')) {
|
||||
// TODO: add this to shadowroot
|
||||
var filePart = imgs[i].src.split('/') // splits the link by "/"
|
||||
// console.log(imgs[i].src.split("base64,")[1])
|
||||
// TODO: base64
|
||||
filePart = filePart[filePart.length - 1] // the last one is the image name
|
||||
var appendTo = 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)
|
||||
appendBelowElement(appendTo, mainDiv)
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
// for (var i = 0; i < imgs.length; i++) {
|
||||
// if (!imgs[i].src.includes('brokenfile')) {
|
||||
// // TODO: add this to shadowroot
|
||||
// var filePart = imgs[i].src.split('/') // splits the link by "/"
|
||||
// // console.log(imgs[i].src.split("base64,")[1])
|
||||
// // TODO: base64
|
||||
// filePart = filePart[filePart.length - 1] // the last one is the image name
|
||||
// var appendTo = 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)
|
||||
// appendBelowElement(appendTo, mainDiv)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
// this function adds basic hotkeys for video controll.
|
||||
|
@ -1256,7 +1037,7 @@
|
|||
var seekTime = 20
|
||||
document.addEventListener('keydown', function(e) {
|
||||
try {
|
||||
var video = MPM.GetVideo()
|
||||
var video = getVideo()
|
||||
var keyCode = e.keyCode // getting keycode
|
||||
if (keyCode === 32) {
|
||||
// if the keycode is 32 (space)
|
||||
|
@ -1280,7 +1061,7 @@
|
|||
Log(err.message)
|
||||
}
|
||||
})
|
||||
var toadd = MPM.GetVideoElement()
|
||||
var toadd = getVideoElement()
|
||||
var node = CreateNodeWithText(toadd, texts.videoHelp)
|
||||
node.style.margin = '5px 5px 5px 5px' // fancy margin
|
||||
}
|
||||
|
@ -1292,11 +1073,11 @@
|
|||
let maxInd = 4 // inp.length * 0.2;
|
||||
|
||||
if (dotIndex < maxInd) {
|
||||
return SUtils.RemoveUnnecesarySpaces(
|
||||
return removeUnnecesarySpaces(
|
||||
inp.substr(inp.indexOf('.') + 1, inp.length)
|
||||
)
|
||||
} else if (doubledotIndex < maxInd) {
|
||||
return SUtils.RemoveUnnecesarySpaces(
|
||||
return removeUnnecesarySpaces(
|
||||
inp.substr(inp.indexOf(':') + 1, inp.length)
|
||||
)
|
||||
} else {
|
||||
|
@ -1307,61 +1088,6 @@
|
|||
// highlights the possible solutions to the current question
|
||||
function HighLightAnswer(results, currQuestionNumber) {
|
||||
// TODO: fix this
|
||||
try {
|
||||
if (results.length > 0) {
|
||||
var answers = QPM.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 (let 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) {
|
||||
// FIXME why not radio
|
||||
for (let i = 0; i < toColor.length; i++) {
|
||||
// going through "toColor"
|
||||
let highlight = createHoverOver(answers[toColor[i]])
|
||||
Object.assign(highlight.style, {
|
||||
border: '4px solid rgba(100, 240, 100, 0.8)',
|
||||
borderRadius: '10px',
|
||||
})
|
||||
}
|
||||
}
|
||||
} // 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)
|
||||
}
|
||||
}
|
||||
|
||||
// : }}}
|
||||
|
@ -1570,7 +1296,7 @@
|
|||
|
||||
const SetQuestionText = () => {
|
||||
var relevantQuestion = GetRelevantQuestion()
|
||||
questionTextElement.innerText = SUtils.removeMultipleEnters(
|
||||
questionTextElement.innerText = removeUnnecesarySpaces(
|
||||
relevantQuestion.m
|
||||
)
|
||||
if (currItem === 0 && currRelevantQuestion === 0) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue