mirror of
https://gitlab.com/MrFry/moodle-test-userscript
synced 2025-04-01 20:22:48 +02:00
Basic test page handling
This commit is contained in:
parent
966a4093a4
commit
c987a27ee3
1 changed files with 186 additions and 102 deletions
288
stable.user.js
288
stable.user.js
|
@ -85,8 +85,8 @@
|
||||||
// forcing pages for testing. unless you test, do not set these to true!
|
// forcing pages for testing. unless you test, do not set these to true!
|
||||||
// only one of these should be true for testing
|
// only one of these should be true for testing
|
||||||
setVal('ISDEVEL', true)
|
setVal('ISDEVEL', true)
|
||||||
const forceTestPage = false
|
const forceTestPage = true
|
||||||
const forceResultPage = true
|
const forceResultPage = false
|
||||||
const forceDefaultPage = false
|
const forceDefaultPage = false
|
||||||
const logElementGetting = false
|
const logElementGetting = false
|
||||||
const log = true
|
const log = true
|
||||||
|
@ -160,10 +160,161 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------------
|
||||||
// Result page processing functions
|
// Basic processing helpers
|
||||||
// ----------------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
const uniq = a => [...new Set(a)]
|
function getTextPromisesFromNode(node) {
|
||||||
|
const promises = []
|
||||||
|
Array.from(node.childNodes).forEach(elem => {
|
||||||
|
if (elem.tagName === 'IMG') {
|
||||||
|
promises.push(digestMessage(getBase64Image(elem)))
|
||||||
|
} else if (elem.tagName === undefined) {
|
||||||
|
promises.push({ type: 'txt', val: elem.nodeValue })
|
||||||
|
} else {
|
||||||
|
promises.push({ type: 'txt', val: elem.innerText })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return promises
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeTextFromElements(item) {
|
||||||
|
// TODO!
|
||||||
|
// if (emptyOrWhiteSpace(item)) {
|
||||||
|
// return ''
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (item.type === 'img') {
|
||||||
|
return '[' + item.val + ']'
|
||||||
|
} else {
|
||||||
|
return item.val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getImagesFromElements(elements) {
|
||||||
|
return elements.reduce((acc, element) => {
|
||||||
|
if (element.type === 'img') {
|
||||||
|
acc.push(element.val)
|
||||||
|
}
|
||||||
|
return acc
|
||||||
|
}, [])
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentSubjectName() {
|
||||||
|
if (logElementGetting) {
|
||||||
|
Log('getting current subjects name')
|
||||||
|
}
|
||||||
|
return document.getElementById('page-header').innerText.split('\n')[0] || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function uniq(a) {
|
||||||
|
return [...new Set(a)]
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------------
|
||||||
|
// Test page processing functions
|
||||||
|
// ----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function handleQuiz() {
|
||||||
|
// TODO: dropdown in question
|
||||||
|
// TODO: multiple selects, img in question
|
||||||
|
// TODO:
|
||||||
|
const promises = []
|
||||||
|
const subjName = getCurrentSubjectName()
|
||||||
|
const questionNodes = Array.from(
|
||||||
|
document.getElementsByTagName('form')[0].childNodes[0].childNodes
|
||||||
|
)
|
||||||
|
|
||||||
|
let i = 0
|
||||||
|
while (
|
||||||
|
i < questionNodes.length &&
|
||||||
|
questionNodes[i].tagName === 'DIV' &&
|
||||||
|
questionNodes[i].className !== 'submitbtns'
|
||||||
|
) {
|
||||||
|
promises.push(getQuestionPromiseForSingleQuestion(questionNodes[i]))
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.all(promises)
|
||||||
|
.then(res => {
|
||||||
|
console.log(res)
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.warn('Error in handleQuiz()')
|
||||||
|
console.warn(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPossibleAnswersFromTest(node) {
|
||||||
|
const promises = []
|
||||||
|
const answers = Array.from(
|
||||||
|
node.getElementsByClassName('answer')[0].childNodes
|
||||||
|
)
|
||||||
|
|
||||||
|
answers.forEach(answer => {
|
||||||
|
if (answer.tagName) {
|
||||||
|
promises.push(getTextPromisesFromNode(answer))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return promises
|
||||||
|
}
|
||||||
|
|
||||||
|
function getQuestionPromiseForSingleQuestion(node) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
const qtextNode = node.getElementsByClassName('qtext')[0]
|
||||||
|
|
||||||
|
const questionPromises = getTextPromisesFromNode(qtextNode)
|
||||||
|
const possibleAnswerPromises = getPossibleAnswersFromTest(node)
|
||||||
|
|
||||||
|
Promise.all([
|
||||||
|
Promise.all(questionPromises),
|
||||||
|
Promise.all(possibleAnswerPromises),
|
||||||
|
])
|
||||||
|
.then(([question, possibleAnswerArray]) => {
|
||||||
|
const questionText = question.map(makeTextFromElements).join(' ')
|
||||||
|
const images = getImagesFromElements(question)
|
||||||
|
const data = getDataFromTest(images)
|
||||||
|
const possibleAnswers = possibleAnswerArray.map(x => {
|
||||||
|
return removeUnnecesarySpaces(x.map(makeTextFromElements).join(' '))
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('\n\n\n')
|
||||||
|
console.log(questionText)
|
||||||
|
console.log(images)
|
||||||
|
possibleAnswers.forEach(x => {
|
||||||
|
console.log(x)
|
||||||
|
})
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
question: questionText,
|
||||||
|
possibleAnswers,
|
||||||
|
images,
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.warn('Error in getQuestionPromiseForSingleQuestion()')
|
||||||
|
console.warn(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDataFromTest(images) {
|
||||||
|
if (images.length > 0) {
|
||||||
|
return {
|
||||||
|
type: 'image',
|
||||||
|
images: images,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
type: 'simple',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------------
|
||||||
|
// Result page processing functions
|
||||||
|
// ----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
function getQuiz() {
|
function getQuiz() {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
@ -187,7 +338,6 @@
|
||||||
// }]
|
// }]
|
||||||
Promise.all(promises)
|
Promise.all(promises)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
console.log(result)
|
|
||||||
resolve(result)
|
resolve(result)
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
|
@ -207,7 +357,6 @@
|
||||||
return true
|
return true
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Log(`${key} failed`)
|
Log(`${key} failed`)
|
||||||
console.log(e)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log(`${key} did not pass`)
|
Log(`${key} did not pass`)
|
||||||
|
@ -233,28 +382,11 @@
|
||||||
resolve({ success: false })
|
resolve({ success: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
const makeTextFromElements = element => {
|
|
||||||
if (element.type === 'img') {
|
|
||||||
return '[' + element.val + ']'
|
|
||||||
} else {
|
|
||||||
return element.val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getImagesFromElements = elements => {
|
|
||||||
return elements.reduce((acc, element) => {
|
|
||||||
if (element.type === 'img') {
|
|
||||||
acc.push(element.val)
|
|
||||||
}
|
|
||||||
return acc
|
|
||||||
}, [])
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise.all([Promise.all(questionPromises), Promise.all(answerPromises)])
|
Promise.all([Promise.all(questionPromises), Promise.all(answerPromises)])
|
||||||
.then(res => {
|
.then(([question, answer]) => {
|
||||||
const questionText = res[0].map(makeTextFromElements).join(' ')
|
const questionText = question.map(makeTextFromElements).join(' ')
|
||||||
const answerText = res[1].map(makeTextFromElements).join(' ')
|
const answerText = answer.map(makeTextFromElements).join(' ')
|
||||||
let images = getImagesFromElements([...res[0], ...res[1]])
|
let images = getImagesFromElements([...question, ...answer])
|
||||||
images = uniq(images)
|
images = uniq(images)
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
|
@ -293,18 +425,7 @@
|
||||||
},
|
},
|
||||||
getterFunction: node => {
|
getterFunction: node => {
|
||||||
let question = node.getElementsByClassName('qtext')[0]
|
let question = node.getElementsByClassName('qtext')[0]
|
||||||
const promises = []
|
return getTextPromisesFromNode(question)
|
||||||
|
|
||||||
Array.from(question.childNodes).forEach(elem => {
|
|
||||||
if (elem.tagName === 'IMG') {
|
|
||||||
promises.push(digestMessage(getBase64Image(elem)))
|
|
||||||
} else if (elem.tagName === undefined) {
|
|
||||||
promises.push({ type: 'txt', val: elem.nodeValue })
|
|
||||||
} else {
|
|
||||||
promises.push({ type: 'txt', val: elem.innerText })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return promises
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -318,29 +439,7 @@
|
||||||
},
|
},
|
||||||
getterFunction: node => {
|
getterFunction: node => {
|
||||||
let answer = node.getElementsByClassName('rightanswer')[0]
|
let answer = node.getElementsByClassName('rightanswer')[0]
|
||||||
const promises = []
|
return getTextPromisesFromNode(answer)
|
||||||
|
|
||||||
Array.from(answer.childNodes).forEach(elem => {
|
|
||||||
if (elem.tagName === 'IMG') {
|
|
||||||
promises.push(digestMessage(getBase64Image(elem)))
|
|
||||||
} else if (elem.tagName === undefined) {
|
|
||||||
promises.push({ type: 'txt', val: elem.nodeValue })
|
|
||||||
} else {
|
|
||||||
promises.push({ type: 'txt', val: elem.innerText })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return promises
|
|
||||||
},
|
|
||||||
},
|
|
||||||
getDropdownAnswer: {
|
|
||||||
description: 'Dropdown answer getter',
|
|
||||||
index: 1,
|
|
||||||
requirement: node => {
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
getterFunction: node => {
|
|
||||||
// TODO dropdown kérdés.html
|
|
||||||
return 'asd'
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
noCorrect: {
|
noCorrect: {
|
||||||
|
@ -378,6 +477,28 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
getDropdownAnswer: {
|
||||||
|
description: 'Dropdown answer getter',
|
||||||
|
index: 1,
|
||||||
|
requirement: node => {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
getterFunction: node => {
|
||||||
|
// TODO dropdown kérdés.html
|
||||||
|
return 'asd'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
getTextareaAnswer: {
|
||||||
|
description: 'Get complex answer',
|
||||||
|
index: 1,
|
||||||
|
requirement: node => {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
getterFunction: node => {
|
||||||
|
// TODO Ugrás... bug.html
|
||||||
|
return 'asd'
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function getIfSolutionIsCorrect(node) {
|
function getIfSolutionIsCorrect(node) {
|
||||||
|
@ -620,13 +741,6 @@
|
||||||
// Misc
|
// Misc
|
||||||
// ----------------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
function getCurrentSubjectName() {
|
|
||||||
if (logElementGetting) {
|
|
||||||
Log('getting current subjects name')
|
|
||||||
}
|
|
||||||
return document.getElementById('page-header').innerText.split('\n')[0] || ''
|
|
||||||
}
|
|
||||||
|
|
||||||
function getVideo() {
|
function getVideo() {
|
||||||
if (logElementGetting) {
|
if (logElementGetting) {
|
||||||
Log('getting video stuff')
|
Log('getting video stuff')
|
||||||
|
@ -680,7 +794,7 @@
|
||||||
forceTestPage
|
forceTestPage
|
||||||
) {
|
) {
|
||||||
// if the current page is a test
|
// if the current page is a test
|
||||||
HandleQuiz()
|
handleQuiz()
|
||||||
} else if (
|
} else if (
|
||||||
(url.includes('/quiz/') && url.includes('review.php')) ||
|
(url.includes('/quiz/') && url.includes('review.php')) ||
|
||||||
forceResultPage
|
forceResultPage
|
||||||
|
@ -1014,38 +1128,7 @@
|
||||||
|
|
||||||
// : Answering stuffs {{{
|
// : Answering stuffs {{{
|
||||||
|
|
||||||
function HandleQuiz() {
|
// TODO
|
||||||
// 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) {
|
function PrepareAnswers(result, j) {
|
||||||
assert(result)
|
assert(result)
|
||||||
|
|
||||||
|
@ -1077,6 +1160,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
function ShowAnswers(answers, question) {
|
function ShowAnswers(answers, question) {
|
||||||
assert(answers)
|
assert(answers)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue