Correct answer saver.
当前为
// ==UserScript==
// @name Quiz House Answer Local Database
// @namespace http://tampermonkey.net/
// @version 1.0.2a
// @description Correct answer saver.
// @author Meffiu
// @match https://app.quizhouse.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=quizhouse.com
// @grant GM_setValue
// @grant GM_getValue
// @license MIT
// ==/UserScript==
(function() {
'use strict';
let lastQuestion = '',
instantPickEnabled = false;
function initDatabase() {
let data = loadData('qh_answers');
let dataImg = loadData('qh_answers_imgs');
if (!data) {
data = {};
saveData('qh_answers', data);
}
if (!dataImg) {
dataImg = {};
saveData('qh_answers_imgs', dataImg)
}
}
function createInstantPickButton() {
const instantPickButton = document.createElement('button');
instantPickButton.textContent = 'Instant Pick Correct Answer';
instantPickButton.style.backgroundColor = 'red';
instantPickButton.style.color = 'white';
instantPickButton.style.marginTop = '10px';
instantPickButton.style.padding = '5px';
instantPickButton.style.borderRadius = '5px';
instantPickButton.style.fontSize = '12px';
instantPickButton.addEventListener('click', function() {
instantPickEnabled = !instantPickEnabled;
instantPickButton.style.backgroundColor = instantPickEnabled ? 'green' : 'red';
updateStatsBox();
});
return instantPickButton;
}
function createCheckButton() {
const checkButton = document.createElement('button');
checkButton.textContent = 'Pick Correct Answer';
checkButton.style.backgroundColor = 'green';
checkButton.style.color = 'white';
checkButton.style.marginTop = '10px';
checkButton.style.padding = '5px';
checkButton.style.borderRadius = '5px';
checkButton.style.fontSize = '12px';
checkButton.addEventListener('click', checkQuestion);
return checkButton;
}
function createToggleButton() {
const toggleButton = document.createElement('button');
toggleButton.textContent = 'Toggle StatsBox';
toggleButton.style.backgroundColor = 'blue';
toggleButton.style.color = 'white';
toggleButton.style.marginTop = '10px';
toggleButton.style.padding = '5px';
toggleButton.style.borderRadius = '5px';
toggleButton.style.fontSize = '12px';
toggleButton.style.display = 'block';
toggleButton.addEventListener('click', function() {
const statsBox = document.getElementById('statsBox');
if (statsBox.style.display === 'none') {
statsBox.style.display = 'block';
} else {
statsBox.style.display = 'none';
}
});
return toggleButton;
}
function updateStatsBox() {
const data = loadData('qh_answers');
const dataImg = loadData('qh_answers_imgs');
let totalImgAnswers = 0;
for (let key in dataImg) {
totalImgAnswers += dataImg[key].length;
}
let statsContainer = document.getElementById('statsContainer');
if (!statsContainer) {
statsContainer = document.createElement('div');
statsContainer.id = 'statsContainer';
statsContainer.style.position = 'fixed';
statsContainer.style.bottom = '20px';
statsContainer.style.left = '20px';
document.body.appendChild(statsContainer);
}
let buttonsContainer = document.getElementById('buttonsContainer');
if (!buttonsContainer) {
buttonsContainer = document.createElement('div');
buttonsContainer.id = 'buttonsContainer';
buttonsContainer.style.display = 'flex';
statsContainer.appendChild(buttonsContainer);
}
let instantPickButton = document.getElementById('instantPickButton');
if (!instantPickButton) {
instantPickButton = createInstantPickButton();
instantPickButton.id = 'instantPickButton';
buttonsContainer.appendChild(instantPickButton);
}
let checkButton = document.getElementById('checkButton');
if (!checkButton) {
checkButton = createCheckButton();
checkButton.id = 'checkButton';
buttonsContainer.appendChild(checkButton);
}
checkButton.style.display = instantPickEnabled ? 'none' : 'block';
let toggleButton = document.getElementById('toggleButton');
if (!toggleButton) {
toggleButton = createToggleButton();
toggleButton.id = 'toggleButton';
statsContainer.appendChild(toggleButton);
}
let statsBox = document.getElementById('statsBox');
if (!statsBox) {
statsBox = document.createElement('div');
statsBox.id = 'statsBox';
statsBox.style.padding = '10px';
statsBox.style.color = 'white';
statsBox.style.backgroundColor = 'black';
statsContainer.appendChild(statsBox);
}
statsBox.innerHTML = `QH Answer Local Database v${GM_info.script.version}<br>Answers: ${Object.keys(data).length}<br>Image Answers: ${totalImgAnswers}`;
}
function showAlert(message, color, duration) {
const alertBox = document.createElement('div');
const formattedMessage = message.replace(/\n/g, '<br>');
alertBox.innerHTML = formattedMessage;
alertBox.style.position = 'fixed';
alertBox.style.bottom = '20px';
alertBox.style.right = '20px';
alertBox.style.padding = '10px';
alertBox.style.color = 'white';
alertBox.style.backgroundColor = color;
document.body.appendChild(alertBox);
setTimeout(() => {
document.body.removeChild(alertBox);
}, duration);
}
function saveData(key, data) {
GM_setValue(key, JSON.stringify(data));
}
function loadData(key) {
const data = GM_getValue(key, null);
return data ? JSON.parse(data) : null;
}
function saveQuestion() {
const data = loadData('qh_answers');
const dataImg = loadData('qh_answers_imgs')
const question = document.querySelector('div.css-219n91 p').textContent;
const answer = document.querySelector('div.css-1wxx39n')?.textContent || document.querySelector('div.css-91izyb')?.textContent;
const image = document.querySelector('img.css-18a88ps')?.getAttribute('src');
if (!question || !answer) {
return showAlert('Could not extract question or answer!', 'red', 3000);
}
if (image) {
dataImg[question] = dataImg[question] || [];
if (!dataImg[question]?.some(i => i.src === image)) {
dataImg[question].push({ src: image, answer: answer });
saveData('qh_answers_imgs', dataImg);
showAlert(`Saved answer "${answer}" to question "${question}"`, 'green', 3000);
}
}
else if (!data[question]) {
data[question] = answer;
saveData('qh_answers', data);
showAlert(`Saved answer "${answer}" to question "${question}"`, 'green', 3000);
}
updateStatsBox();
}
function checkQuestion() {
const data = loadData('qh_answers');
const dataImg = loadData('qh_answers_imgs');
const question = document.querySelector('div.css-219n91 p').textContent;
const image = document.querySelector('img.css-18a88ps')?.getAttribute('src');
if (image) {
if (dataImg[question]) {
const imgAnswer = dataImg[question].find(i => i.src === image)?.answer;
if (imgAnswer) {
const divs = Array.from(document.querySelectorAll('div'));
const targetDiv = divs.find(div => div.innerText === imgAnswer);
if (targetDiv) {
targetDiv.click();
} else {
showAlert(`No div with the saved answer found!\n\nAnswer: ${imgAnswer}`, 'red', 5000);
}
} else {
showAlert('No answer to that question with image in database!', 'red', 3000);
}
} else {
showAlert('No data for this question in database!', 'red', 3000);
}
}
else if (data[question]) {
const divs = Array.from(document.querySelectorAll('div'));
const targetDiv = divs.find(div => div.innerText === data[question]);
if (targetDiv) {
targetDiv.click();
} else {
showAlert(`No div with the saved answer found!\n\nAnswer: ${data[question]}`, 'red', 5000);
}
} else {
showAlert('No answer to that question in database!', 'red', 3000);
}
}
const qhObserver = new MutationObserver((qhMutationsList, qhObserver) => {
for (let mutation of qhMutationsList) {
if(mutation.type === 'attributes') {
if(mutation.attributeName === 'class') {
const targetElement = mutation.target;
if(targetElement.classList.contains('css-1wxx39n') || targetElement.classList.contains('css-91izyb')) {
saveQuestion();
}
}
}
}
});
const qhConfig = { attributes: true, attributeFilter: ['class'], subtree: true };
qhObserver.observe(document, qhConfig);
setInterval(() => {
const questionElement = document.querySelector('div.css-219n91 p');
if (questionElement && instantPickEnabled) {
const currentQuestion = questionElement.textContent;
if (currentQuestion !== lastQuestion) {
checkQuestion();
lastQuestion = currentQuestion;
}
}
}, 1000);
initDatabase();
updateStatsBox();
showAlert('Quiz House Answer Local Database loaded!\n\nClick that green "Pick Corrent Answer" button to guess answer to actual question.', 'green', 8000);
})();