Size
10.0 KB
Version
1.1.1
Created
Feb 28, 2026
Updated
21 days ago
1// ==UserScript==
2// @name Campus Quiz Auto-Answer
3// @description Automatically answers quiz questions using AI
4// @version 1.1.1
5// @match https://*.campus.castellsimmerscom.com/*
6// @icon https://campus.castellsimmerscom.com/pluginfile.php/1/theme_remui/faviconurl/1771165145/favicon-128%20%283%29.png
7// @grant GM.xmlhttpRequest
8// ==/UserScript==
9(function() {
10 'use strict';
11
12 console.log('Campus Quiz Auto-Answer extension loaded');
13
14 // Debounce function to prevent excessive calls
15 function debounce(func, wait) {
16 let timeout;
17 return function executedFunction(...args) {
18 const later = () => {
19 clearTimeout(timeout);
20 func(...args);
21 };
22 clearTimeout(timeout);
23 timeout = setTimeout(later, wait);
24 };
25 }
26
27 // Function to extract question text from a question element
28 function extractQuestionText(questionElement) {
29 const qtextDiv = questionElement.querySelector('.qtext');
30 if (!qtextDiv) return '';
31
32 // Get the full text including the blank space context
33 let fullText = qtextDiv.textContent.trim();
34
35 // Remove "Answer Question X" labels
36 fullText = fullText.replace(/Answer Question \d+/g, '').trim();
37
38 return fullText;
39 }
40
41 // Function to get all questions on the page
42 function getAllQuestions() {
43 const questions = [];
44 const questionElements = document.querySelectorAll('div.que[id^="question-"]');
45
46 console.log(`Found ${questionElements.length} questions on the page`);
47
48 questionElements.forEach((element, index) => {
49 const questionText = extractQuestionText(element);
50 const inputField = element.querySelector('input[type="text"][name*="_answer"]');
51
52 if (questionText && inputField) {
53 questions.push({
54 element: element,
55 text: questionText,
56 inputField: inputField,
57 questionNumber: index + 1
58 });
59 console.log(`Question ${index + 1}: ${questionText}`);
60 }
61 });
62
63 return questions;
64 }
65
66 // Function to use AI to answer a question
67 async function getAIAnswer(questionText) {
68 try {
69 console.log(`Getting AI answer for: ${questionText}`);
70
71 const prompt = `You are helping a student complete an English grammar quiz.
72The question is a fill-in-the-blank question. Analyze the sentence and provide ONLY the missing word or phrase that completes the sentence correctly.
73
74Question: ${questionText}
75
76Provide ONLY the word or short phrase that fills in the blank. Do not include any explanation, punctuation, or additional text. Just the answer word(s).`;
77
78 const answer = await RM.aiCall(prompt, {
79 type: 'json_schema',
80 json_schema: {
81 name: 'quiz_answer',
82 schema: {
83 type: 'object',
84 properties: {
85 answer: {
86 type: 'string',
87 description: 'The word or phrase that fills in the blank'
88 },
89 confidence: {
90 type: 'string',
91 enum: ['high', 'medium', 'low'],
92 description: 'Confidence level in the answer'
93 }
94 },
95 required: ['answer', 'confidence']
96 }
97 }
98 });
99
100 console.log(`AI Answer: ${answer.answer} (Confidence: ${answer.confidence})`);
101 return answer.answer;
102
103 } catch (error) {
104 console.error('Error getting AI answer:', error);
105 return null;
106 }
107 }
108
109 // Function to fill in an answer
110 function fillAnswer(inputField, answer) {
111 if (!inputField || !answer) return false;
112
113 inputField.value = answer;
114 inputField.dispatchEvent(new Event('input', { bubbles: true }));
115 inputField.dispatchEvent(new Event('change', { bubbles: true }));
116
117 return true;
118 }
119
120 // Main function to auto-answer all questions
121 async function autoAnswerQuestions() {
122 const button = document.getElementById('auto-answer-btn');
123 if (button) {
124 button.disabled = true;
125 button.textContent = 'Processing...';
126 button.style.backgroundColor = '#ffc107';
127 }
128
129 console.log('Starting auto-answer process...');
130
131 const questions = getAllQuestions();
132
133 if (questions.length === 0) {
134 alert('No questions found on this page!');
135 if (button) {
136 button.disabled = false;
137 button.textContent = 'š¤ Auto Answer Quiz';
138 button.style.backgroundColor = '#28a745';
139 }
140 return;
141 }
142
143 let successCount = 0;
144 let failCount = 0;
145
146 for (const question of questions) {
147 try {
148 // Show progress
149 if (button) {
150 button.textContent = `Processing ${question.questionNumber}/${questions.length}...`;
151 }
152
153 const answer = await getAIAnswer(question.text);
154
155 if (answer) {
156 const filled = fillAnswer(question.inputField, answer);
157 if (filled) {
158 successCount++;
159 console.log(`ā Question ${question.questionNumber} answered: ${answer}`);
160
161 // Visual feedback - highlight the filled input
162 question.inputField.style.backgroundColor = '#d4edda';
163 question.inputField.style.border = '2px solid #28a745';
164 } else {
165 failCount++;
166 console.error(`ā Failed to fill answer for question ${question.questionNumber}`);
167 }
168 } else {
169 failCount++;
170 console.error(`ā No answer received for question ${question.questionNumber}`);
171 }
172
173 // Small delay between questions to avoid overwhelming the AI
174 await new Promise(resolve => setTimeout(resolve, 500));
175
176 } catch (error) {
177 failCount++;
178 console.error(`Error processing question ${question.questionNumber}:`, error);
179 }
180 }
181
182 // Show completion message
183 const message = `Auto-answer complete!\nā Answered: ${successCount}\nā Failed: ${failCount}`;
184 console.log(message);
185 alert(message);
186
187 if (button) {
188 button.disabled = false;
189 button.textContent = 'š¤ Auto Answer Quiz';
190 button.style.backgroundColor = '#28a745';
191 }
192 }
193
194 // Function to create and add the auto-answer button
195 function createAutoAnswerButton() {
196 // Check if we're on a quiz attempt page
197 if (!window.location.href.includes('/mod/quiz/attempt.php')) {
198 console.log('Not on a quiz attempt page, skipping button creation');
199 return;
200 }
201
202 // Check if button already exists
203 if (document.getElementById('auto-answer-btn')) {
204 console.log('Auto-answer button already exists');
205 return;
206 }
207
208 // Find the submit button container
209 const submitContainer = document.querySelector('.submitbtns');
210 if (!submitContainer) {
211 console.log('Submit button container not found, will retry...');
212 return;
213 }
214
215 // Create the auto-answer button
216 const autoAnswerBtn = document.createElement('button');
217 autoAnswerBtn.id = 'auto-answer-btn';
218 autoAnswerBtn.type = 'button';
219 autoAnswerBtn.textContent = 'š¤ Auto Answer Quiz';
220 autoAnswerBtn.className = 'btn btn-success';
221 autoAnswerBtn.style.cssText = `
222 background-color: #28a745;
223 color: white;
224 border: none;
225 padding: 10px 20px;
226 font-size: 16px;
227 font-weight: bold;
228 border-radius: 4px;
229 cursor: pointer;
230 margin-right: 10px;
231 transition: background-color 0.3s;
232 `;
233
234 autoAnswerBtn.addEventListener('mouseover', () => {
235 if (!autoAnswerBtn.disabled) {
236 autoAnswerBtn.style.backgroundColor = '#218838';
237 }
238 });
239
240 autoAnswerBtn.addEventListener('mouseout', () => {
241 if (!autoAnswerBtn.disabled) {
242 autoAnswerBtn.style.backgroundColor = '#28a745';
243 }
244 });
245
246 autoAnswerBtn.addEventListener('click', autoAnswerQuestions);
247
248 // Insert the button before the submit button
249 submitContainer.insertBefore(autoAnswerBtn, submitContainer.firstChild);
250
251 console.log('Auto-answer button created successfully');
252 }
253
254 // Initialize the extension
255 function init() {
256 console.log('Initializing Campus Quiz Auto-Answer extension...');
257
258 // Wait for the page to be fully loaded
259 if (document.readyState === 'loading') {
260 document.addEventListener('DOMContentLoaded', init);
261 return;
262 }
263
264 // Create the button after a short delay to ensure DOM is ready
265 setTimeout(createAutoAnswerButton, 1000);
266
267 // Also observe for dynamic content changes
268 const observer = new MutationObserver(debounce(() => {
269 createAutoAnswerButton();
270 }, 1000));
271
272 observer.observe(document.body, {
273 childList: true,
274 subtree: true
275 });
276 }
277
278 // Start the extension
279 init();
280
281})();