Now highlights answers with green border and subtle glow only, no background fill.
This commit is contained in:
+67
-105
@@ -12,17 +12,11 @@ function injectCustomStyles() {
|
|||||||
style.id = 'quiz-helper-styles';
|
style.id = 'quiz-helper-styles';
|
||||||
style.textContent = `
|
style.textContent = `
|
||||||
.quiz-helper-correct {
|
.quiz-helper-correct {
|
||||||
background-color: #90EE90 !important;
|
|
||||||
border: 3px solid #28a745 !important;
|
border: 3px solid #28a745 !important;
|
||||||
box-shadow: 0 0 10px rgba(40, 167, 69, 0.6) !important;
|
box-shadow: 0 0 8px rgba(40, 167, 69, 0.5) !important;
|
||||||
padding: 8px !important;
|
|
||||||
border-radius: 4px !important;
|
border-radius: 4px !important;
|
||||||
transition: all 0.3s ease !important;
|
transition: all 0.3s ease !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.quiz-helper-correct * {
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
document.head.appendChild(style);
|
document.head.appendChild(style);
|
||||||
styleInjected = true;
|
styleInjected = true;
|
||||||
@@ -272,22 +266,17 @@ function findQuestions() {
|
|||||||
return questions;
|
return questions;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enhanced answer choice finding
|
// Enhanced answer choice finding - strictly finds only radio/checkbox options
|
||||||
function findAnswerChoices(questionElement) {
|
function findAnswerChoices(questionElement) {
|
||||||
const answers = [];
|
const answers = [];
|
||||||
const seenTexts = new Set();
|
const seenTexts = new Set();
|
||||||
let inputType = null;
|
let inputType = null;
|
||||||
|
|
||||||
let container = questionElement.closest('[role="group"], fieldset, form, [class*="question"], [class*="answer"], [class*="option"], div');
|
// Find the container with radio/checkbox inputs
|
||||||
|
let container = questionElement;
|
||||||
if (!container || container === questionElement) {
|
for (let i = 0; i < 6 && container; i++) {
|
||||||
container = questionElement.parentElement;
|
const inputs = container.querySelectorAll('input[type="radio"], input[type="checkbox"]');
|
||||||
}
|
if (inputs.length > 0) {
|
||||||
|
|
||||||
for (let i = 0; i < 4 && container; i++) {
|
|
||||||
const inputsInContainer = container.querySelectorAll('input[type="radio"], input[type="checkbox"]');
|
|
||||||
if (inputsInContainer.length > 0) {
|
|
||||||
console.log(` Found ${inputsInContainer.length} inputs at level ${i}`);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
container = container.parentElement;
|
container = container.parentElement;
|
||||||
@@ -295,93 +284,66 @@ function findAnswerChoices(questionElement) {
|
|||||||
|
|
||||||
if (!container) container = document.body;
|
if (!container) container = document.body;
|
||||||
|
|
||||||
let nextSibling = questionElement.nextElementSibling;
|
// Get all radio/checkbox inputs - these are the ONLY valid answer choices
|
||||||
let siblingAttempts = 0;
|
const inputs = container.querySelectorAll('input[type="radio"], input[type="checkbox"]');
|
||||||
const siblingContainers = [container];
|
console.log(` Found ${inputs.length} radio/checkbox inputs`);
|
||||||
|
|
||||||
while (nextSibling && siblingAttempts < 8) {
|
inputs.forEach((input, idx) => {
|
||||||
siblingContainers.push(nextSibling);
|
if (input.type === 'radio') inputType = 'radio';
|
||||||
nextSibling = nextSibling.nextElementSibling;
|
else if (input.type === 'checkbox') inputType = 'checkbox';
|
||||||
siblingAttempts++;
|
|
||||||
}
|
let text = '';
|
||||||
|
let labelElement = null;
|
||||||
const answerSelectors = [
|
|
||||||
'input[type="radio"]',
|
// Strategy 1: Find label with matching 'for' attribute
|
||||||
'input[type="checkbox"]',
|
if (input.id) {
|
||||||
'button[role="radio"]',
|
labelElement = document.querySelector(`label[for="${input.id}"]`);
|
||||||
'button[role="checkbox"]',
|
if (labelElement) {
|
||||||
'[role="option"]',
|
text = labelElement.textContent.trim();
|
||||||
'[class*="answer"]',
|
}
|
||||||
'[class*="option"]',
|
}
|
||||||
'[class*="choice"]',
|
|
||||||
'[data-test*="answer"]',
|
// Strategy 2: Find parent label
|
||||||
'[data-test*="option"]',
|
if (!text) {
|
||||||
'label',
|
labelElement = input.closest('label');
|
||||||
'li'
|
if (labelElement) {
|
||||||
];
|
text = labelElement.textContent.trim();
|
||||||
|
}
|
||||||
const excludePatterns = [
|
}
|
||||||
/^question\s+\d+\s+of\s+\d+$/i,
|
|
||||||
/^page\s+\d+/i,
|
// Strategy 3: Find adjacent sibling text
|
||||||
/^(next|previous|submit|skip|back|continue|finish|review)$/i,
|
if (!text) {
|
||||||
/^\d+\s*\/\s*\d+$/,
|
const parent = input.parentElement;
|
||||||
/^score:/i,
|
if (parent) {
|
||||||
/^time:/i,
|
// Clone and remove the input to get just the text
|
||||||
/^remaining:/i,
|
const clone = parent.cloneNode(true);
|
||||||
/^points?:/i
|
const inputClone = clone.querySelector('input');
|
||||||
];
|
if (inputClone) inputClone.remove();
|
||||||
|
text = clone.textContent.trim();
|
||||||
siblingContainers.forEach(searchContainer => {
|
}
|
||||||
answerSelectors.forEach(selector => {
|
}
|
||||||
const elements = searchContainer.querySelectorAll(selector);
|
|
||||||
|
// Strategy 4: Check next sibling
|
||||||
elements.forEach(el => {
|
if (!text && input.nextSibling) {
|
||||||
let text = el.textContent.trim();
|
text = input.nextSibling.textContent?.trim() || '';
|
||||||
|
}
|
||||||
if (el.tagName === 'INPUT') {
|
|
||||||
if (el.type === 'radio') {
|
// Skip if no text found or duplicate
|
||||||
inputType = 'radio';
|
if (!text || text.length < 1) {
|
||||||
} else if (el.type === 'checkbox') {
|
console.log(` Skipping input ${idx} - no text found`);
|
||||||
inputType = 'checkbox';
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const label = searchContainer.querySelector(`label[for="${el.id}"]`);
|
if (seenTexts.has(text)) {
|
||||||
if (label) {
|
console.log(` Skipping input ${idx} - duplicate text`);
|
||||||
text = label.textContent.trim();
|
return;
|
||||||
} else {
|
}
|
||||||
const parentLabel = el.closest('label');
|
|
||||||
if (parentLabel) {
|
seenTexts.add(text);
|
||||||
text = parentLabel.textContent.trim();
|
answers.push({
|
||||||
} else {
|
text: text,
|
||||||
const parent = el.parentElement;
|
element: input,
|
||||||
if (parent) {
|
parentLabel: labelElement || input.parentElement
|
||||||
text = parent.textContent.trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!text || text.length < 2 || text.length > 800 || seenTexts.has(text)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (excludePatterns.some(pattern => pattern.test(text))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const wordCount = text.split(/\s+/).length;
|
|
||||||
const numberCount = (text.match(/\d+/g) || []).length;
|
|
||||||
if (wordCount > 2 && numberCount > wordCount / 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
seenTexts.add(text);
|
|
||||||
answers.push({
|
|
||||||
text: text,
|
|
||||||
element: el,
|
|
||||||
parentLabel: el.closest('label') || el
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -516,7 +478,7 @@ ANALYSIS STEPS:
|
|||||||
|
|
||||||
Think carefully and provide your answer.
|
Think carefully and provide your answer.
|
||||||
|
|
||||||
FORMAT: Respond with only "ANSWER: " followed by the letter(s) separated by commas (e.g., "ANSWER: B" or "ANSWER: A,C,D")`;
|
FORMAT: Always respond with "ANSWER: " followed by the LETTER(s) of the correct option(s) (A, B, C, D, etc.), separated by commas if multiple. Never respond with numbers - always use letters to indicate which option is correct.`;
|
||||||
|
|
||||||
const response = await fetch('https://api.openai.com/v1/chat/completions', {
|
const response = await fetch('https://api.openai.com/v1/chat/completions', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|||||||
Reference in New Issue
Block a user