科举小抄 - 阿里云大学“科考”辅助工具
目前為
// ==UserScript==
// @name 科举小抄
// @namespace https://github.com/fuckKeju/fuckKeju
// @version 0.0.4
// @description 科举小抄 - 阿里云大学“科考”辅助工具
// @author fuckKeju
// @match *.developer.aliyun.com/*
// @run-at document-start
// @grant unsafeWindow
// ==/UserScript==
/* 题库数据 */
var customQuestionsDatabase = []
var useCustomQuestionsDatabase = false
var hasInit = false
function fuckKeju () {
if (hasInit) { return false }
console.log('科举小抄 init suc')
hasInit = true
const subjectTitle = document.querySelector('.yq-main-examination .top-info h2.title-content').innerText
const isExamMode = document.querySelector('.yq-main-examination .time-info')
let questionsDatabase = []
try {
questionsDatabase = JSON.parse(localStorage.getItem(subjectTitle) || '[]')
} catch (e) {
questionsDatabase = []
}
/* 使用预置数据,而非定义的数据 */
if (useCustomQuestionsDatabase) {
questionsDatabase = customQuestionsDatabase
}
var result = []
var items = document.querySelectorAll('.question-panel .question-item')
if (items) {
items.forEach(item => {
const type = item.querySelector('.q-title .q-tag').innerText.trim()
const title = item.querySelector('.q-title .q-t-text').innerText.trim().replace(/\s+/gi, ' ').replace(/\?{2,}/gi, ' ')
const answerList = []
const answerListEl = item.querySelectorAll('.q-option .answer-text')
console.log(answerListEl)
answerListEl.forEach(answerEl => {
let answer = answerEl.innerText.trim()
const checkedEl = answerEl.parentNode.querySelector('input')
if (checkedEl && checkedEl.checked) {
answer += ' --checked'
}
answerList.push(answer)
})
const data = {
title,
type,
answerList
}
const pointEl = item.querySelector('.e-point .p-detail')
if (pointEl) {
data.point = '相关知识点:' + pointEl.innerText.trim()
} else {
data.point = '未匹配到任何相关知识点'
}
const rightAnswerEl = item.querySelector('.right-answer')
if (rightAnswerEl) {
data.rightAnswer = rightAnswerEl.innerText.trim() || '答案正确'
} else {
if (isExamMode) {
data.rightAnswer = '答案未知'
} else {
data.rightAnswer = '答案正确'
}
}
result.push(data)
/* 判断当前题目是否已经存在 */
let hasInDatabase = false
/* 提取相关问题 */
const titleTxt = title.replace(/^\d+\./, '')
let relatedQuestions = []
function relatedQuestionsHandler (item) {
const itemTitle = item.title.replace(/\s+/gi, ' ').replace(/\?{2,}/gi, ' ')
if (itemTitle.includes(titleTxt)) {
const answerA = answerList[0].replace(/^[ABCDEFG]\.\s/, '').replace(/\s+--checked/, '')
for (let i = 0; i < item.answerList.length; i++) {
const answerTxt = item.answerList[i]
if (answerTxt.includes(answerA)) {
relatedQuestions.push(item)
break
}
}
}
if (itemTitle === title) {
hasInDatabase = true
}
}
questionsDatabase.forEach(list => {
if (Array.isArray(list)) {
list.forEach(item => {
relatedQuestionsHandler(item)
})
} else {
relatedQuestionsHandler(list)
}
})
/* 查找是否存在答对的历史记录,优先显示答对的数据 */
if (relatedQuestions.length > 1) {
const rightAnswerArr = []
const wrongAnswerArr = []
relatedQuestions.forEach(data => {
if (data.rightAnswer === '答案正确') {
rightAnswerArr.push(data)
} else {
wrongAnswerArr.push(data)
}
})
relatedQuestions = rightAnswerArr.concat(wrongAnswerArr)
}
/* 收集题目数据 */
if (!isExamMode && !hasInDatabase) {
questionsDatabase.push(data)
}
const dd = document.createElement('dd')
dd.setAttribute('class', 'relatedQuestions')
dd.style.marginTop = '30px'
dd.style.display = 'none'
dd.style.border = '1px solid #ccc'
dd.style.borderRadius = '5px'
// dd.style.padding = '10px'
// dd.style.backgroundColor = '#f9f9f9'
if (item.querySelector('.relatedQuestions')) {
item.removeChild(item.querySelector('.relatedQuestions'))
}
if (relatedQuestions.length) {
const codeEl = document.createElement('pre')
codeEl.style.border = 'none'
codeEl.innerHTML = JSON.stringify(relatedQuestions, null, 2)
dd.appendChild(codeEl)
item.appendChild(dd)
} else {
dd.innerText = '暂无相关题目信息,先考几遍,然后查看考试结果再试试吧'
item.appendChild(dd)
}
item.ondblclick = function (event) {
const relatedQuestions = item.querySelector('.relatedQuestions')
if (relatedQuestions) {
if (relatedQuestions.style.display === 'none') {
relatedQuestions.style.display = 'block'
relatedQuestions.style.opacity = 0.4
relatedQuestions.style.overflow = 'auto'
relatedQuestions.style.maxHeight = '200px'
} else {
relatedQuestions.style.display = 'none'
}
}
}
})
}
localStorage.setItem(subjectTitle, JSON.stringify(questionsDatabase))
/* 切换题目时候,隐藏小抄 */
const switchDoms = document.querySelectorAll('.question-num span.item')
const switchDoms02 = document.querySelectorAll('.e-opt-panel a')
function hideRelatedQuestions () {
const relatedQuestionsEls = document.querySelectorAll('.relatedQuestions')
relatedQuestionsEls.forEach(item => {
item.style.display = 'none'
})
}
switchDoms.forEach(el => {
el.onmouseenter = hideRelatedQuestions
})
switchDoms02.forEach(el => {
el.onclick = hideRelatedQuestions
})
console.log(JSON.stringify(result, null, 2))
}
function ready (selector, fn, shadowRoot) {
const listeners = []
const win = window
const doc = shadowRoot || win.document
const MutationObserver = win.MutationObserver || win.WebKitMutationObserver
let observer
function $ready (selector, fn) {
// 储存选择器和回调函数
listeners.push({
selector: selector,
fn: fn
})
if (!observer) {
// 监听document变化
observer = new MutationObserver(check)
observer.observe(shadowRoot || doc.documentElement, {
childList: true,
subtree: true
})
}
// 检查该节点是否已经在DOM中
check()
}
function check () {
for (let i = 0; i < listeners.length; i++) {
var listener = listeners[i]
var elements = doc.querySelectorAll(listener.selector)
for (let j = 0; j < elements.length; j++) {
var element = elements[j]
if (!element._isMutationReady_) {
element._isMutationReady_ = true
listener.fn.call(element, element)
}
}
}
}
$ready(selector, fn)
}
ready('.question-panel .question-item', () => {
/**
* 此处必须延迟执行,题目渲染和选中渲染是异步操作
* 需要延时等待选中的渲染成功才执行初始化逻辑
*/
console.log('检查到进入了试题页面,即将为你初始化小炒逻辑')
setTimeout(function () {
fuckKeju()
}, 1000 * 3)
})