Miacademy Auto-Correct Answer Helper

Automatically selects correct answers for Miacademy assignments

Size

14.3 KB

Version

1.1.4

Created

Mar 20, 2026

Updated

26 days ago

1// ==UserScript==
2// @name		Miacademy Auto-Correct Answer Helper
3// @description		Automatically selects correct answers for Miacademy assignments
4// @version		1.1.4
5// @match		https://*.miacademy.co/*
6// @icon		https://robomonkey.io/favicon.ico
7// ==/UserScript==
8(function() {
9    'use strict';
10
11    console.log('Miacademy Auto-Correct Answer Helper loaded');
12
13    // Debounce function to prevent multiple rapid calls
14    function debounce(func, wait) {
15        let timeout;
16        return function executedFunction(...args) {
17            const later = () => {
18                clearTimeout(timeout);
19                func(...args);
20            };
21            clearTimeout(timeout);
22            timeout = setTimeout(later, wait);
23        };
24    }
25
26    // Function to extract question and answers from the page
27    function extractQuestionData() {
28        try {
29            // Get the question text
30            const questionElement = document.querySelector('.mia-Prompt .mia-promptText');
31            if (!questionElement) {
32                console.log('No question found on page');
33                return null;
34            }
35
36            const questionText = questionElement.textContent.trim();
37
38            // Get all answer options
39            const answerElements = document.querySelectorAll('.mia-SelectableAnswer');
40            if (answerElements.length === 0) {
41                console.log('No answer options found');
42                return null;
43            }
44
45            const answers = Array.from(answerElements).map((el, index) => {
46                const textBlock = el.querySelector('.mia-TextBlock');
47                return {
48                    index: index,
49                    text: textBlock ? textBlock.textContent.trim() : '',
50                    element: el
51                };
52            });
53
54            console.log('Question extracted:', questionText);
55            console.log('Answers extracted:', answers.map(a => a.text));
56
57            return {
58                question: questionText,
59                answers: answers
60            };
61        } catch (error) {
62            console.error('Error extracting question data:', error);
63            return null;
64        }
65    }
66
67    // Function to select the correct answer using AI
68    async function selectCorrectAnswer() {
69        try {
70            const questionData = extractQuestionData();
71            if (!questionData) {
72                console.log('Could not extract question data');
73                return;
74            }
75
76            console.log('Asking AI for the correct answer...');
77
78            // Check if we have a stored correct answer for this question
79            const storedAnswers = await GM.getValue('miacademy_correct_answers', {});
80            const questionKey = questionData.question.substring(0, 100); // Use first 100 chars as key
81            
82            let correctIndex = -1;
83
84            if (storedAnswers[questionKey] !== undefined) {
85                console.log('Found stored answer for this question!');
86                correctIndex = storedAnswers[questionKey];
87            } else {
88                // Create a prompt for the AI
89                const prompt = `You are helping with a Miacademy quiz question. 
90
91Question: ${questionData.question}
92
93Answer options:
94${questionData.answers.map((a, i) => `${i + 1}. ${a.text}`).join('\n')}
95
96Which answer is correct? Respond with ONLY the number (1, 2, 3, or 4) of the correct answer.`;
97
98                // Use AI to determine the correct answer
99                const aiResponse = await RM.aiCall(prompt, {
100                    type: 'json_schema',
101                    json_schema: {
102                        name: 'correct_answer',
103                        schema: {
104                            type: 'object',
105                            properties: {
106                                answerNumber: {
107                                    type: 'number',
108                                    minimum: 1,
109                                    maximum: 10,
110                                    description: 'The number of the correct answer'
111                                },
112                                reasoning: {
113                                    type: 'string',
114                                    description: 'Brief explanation of why this is correct'
115                                }
116                            },
117                            required: ['answerNumber']
118                        }
119                    }
120                });
121
122                console.log('AI Response:', aiResponse);
123                console.log('Reasoning:', aiResponse.reasoning);
124                correctIndex = aiResponse.answerNumber - 1;
125            }
126
127            if (correctIndex >= 0 && correctIndex < questionData.answers.length) {
128                const correctAnswer = questionData.answers[correctIndex];
129                console.log(`Selecting answer ${correctIndex + 1}: ${correctAnswer.text}`);
130
131                // Click the radio button for the correct answer
132                const radioButton = correctAnswer.element.querySelector('input[type="radio"]');
133                if (radioButton) {
134                    radioButton.click();
135                    console.log('Answer selected successfully!');
136
137                    // Wait a moment, then click submit
138                    setTimeout(() => {
139                        const submitButton = document.querySelector('.mia-SubmitButton:not(.disabled)');
140                        if (submitButton) {
141                            console.log('Clicking submit button...');
142                            submitButton.click();
143                            
144                            // After submitting, check if answer was correct and store it
145                            setTimeout(() => {
146                                checkAnswerResult(questionKey, correctIndex);
147                            }, 1000);
148                        } else {
149                            console.log('Submit button not available yet');
150                        }
151                    }, 500);
152                } else {
153                    console.error('Could not find radio button for answer');
154                }
155            } else {
156                console.error('Invalid answer index from AI:', correctIndex);
157            }
158        } catch (error) {
159            console.error('Error selecting correct answer:', error);
160        }
161    }
162
163    // Function to check if the answer was correct and store it
164    async function checkAnswerResult(questionKey, answerIndex) {
165        try {
166            // Look for correct/incorrect indicators
167            const correctIndicator = document.querySelector('.mia-SelectableAnswer.correct, .mia-correct, [class*="correct"]');
168            const incorrectIndicator = document.querySelector('.mia-SelectableAnswer.incorrect, .mia-incorrect, [class*="incorrect"]');
169            
170            if (correctIndicator) {
171                console.log('Answer was CORRECT! Storing for future reference...');
172                const storedAnswers = await GM.getValue('miacademy_correct_answers', {});
173                storedAnswers[questionKey] = answerIndex;
174                await GM.setValue('miacademy_correct_answers', storedAnswers);
175            } else if (incorrectIndicator) {
176                console.log('Answer was INCORRECT. Looking for the correct answer...');
177                
178                // Find which answer is marked as correct
179                const allAnswers = document.querySelectorAll('.mia-SelectableAnswer');
180                for (let i = 0; i < allAnswers.length; i++) {
181                    if (allAnswers[i].classList.contains('correct') || 
182                        allAnswers[i].querySelector('.correct, [class*="correct"]')) {
183                        console.log(`Correct answer was option ${i + 1}. Storing for next time...`);
184                        const storedAnswers = await GM.getValue('miacademy_correct_answers', {});
185                        storedAnswers[questionKey] = i;
186                        await GM.setValue('miacademy_correct_answers', storedAnswers);
187                        break;
188                    }
189                }
190            }
191            
192            // Click next button after checking result
193            setTimeout(() => {
194                clickNextButton();
195            }, 1500);
196        } catch (error) {
197            console.error('Error checking answer result:', error);
198            // Still try to click next even if there's an error
199            setTimeout(() => {
200                clickNextButton();
201            }, 1500);
202        }
203    }
204
205    // Function to click the next button
206    function clickNextButton() {
207        // Look for various "next" button selectors
208        const nextButton = document.querySelector(
209            '.mia-NextButton, .mia-ContinueButton, button[class*="next"], button[class*="continue"], ' +
210            'button:contains("Next"), button:contains("Continue")'
211        );
212        
213        if (nextButton && !nextButton.disabled) {
214            console.log('Clicking next button...');
215            nextButton.click();
216        } else {
217            // Try alternative selectors
218            const buttons = document.querySelectorAll('button');
219            for (const button of buttons) {
220                const text = button.textContent.toLowerCase();
221                if ((text.includes('next') || text.includes('continue')) && !button.disabled) {
222                    console.log('Found and clicking next/continue button...');
223                    button.click();
224                    return;
225                }
226            }
227            console.log('No next button found or button is disabled');
228        }
229    }
230
231    // Function to check if we're on a quiz page
232    function isQuizPage() {
233        return document.querySelector('.mia-Prompt') !== null && 
234               document.querySelector('.mia-SelectableAnswer') !== null;
235    }
236
237    // Track which questions we've already answered
238    let lastQuestionText = '';
239    let isProcessing = false;
240
241    // Function to check and auto-answer new questions
242    async function checkAndAutoAnswer() {
243        // Don't process if already processing
244        if (isProcessing) {
245            console.log('Already processing a question, skipping...');
246            return;
247        }
248
249        // Check if we're on a quiz page
250        if (!isQuizPage()) {
251            console.log('Not on a quiz page');
252            lastQuestionText = '';
253            return;
254        }
255
256        // Extract current question
257        const questionElement = document.querySelector('.mia-Prompt .mia-promptText');
258        if (!questionElement) {
259            return;
260        }
261
262        const currentQuestionText = questionElement.textContent.trim();
263
264        // Check if this is a new question
265        if (currentQuestionText === lastQuestionText) {
266            return;
267        }
268
269        // Check if question is already answered
270        const selectedAnswer = document.querySelector('.mia-SelectableAnswer input[type="radio"]:checked');
271        if (selectedAnswer) {
272            console.log('Question already answered, skipping...');
273            lastQuestionText = currentQuestionText;
274            return;
275        }
276
277        console.log('New question detected! Auto-answering...');
278        lastQuestionText = currentQuestionText;
279        isProcessing = true;
280
281        try {
282            await selectCorrectAnswer();
283        } catch (error) {
284            console.error('Error auto-answering:', error);
285        } finally {
286            isProcessing = false;
287        }
288    }
289
290    // Debounced version of auto-answer check
291    const debouncedAutoAnswer = debounce(checkAndAutoAnswer, 1000);
292
293    // Function to add a helper button to the page
294    function addHelperButton() {
295        // Check if button already exists
296        if (document.getElementById('mia-auto-answer-btn')) {
297            return;
298        }
299
300        // Only add button if we're on a quiz page
301        if (!isQuizPage()) {
302            return;
303        }
304
305        const button = document.createElement('button');
306        button.id = 'mia-auto-answer-btn';
307        button.textContent = '🤖 Auto Answer';
308        button.style.cssText = `
309            position: fixed;
310            top: 20px;
311            right: 20px;
312            z-index: 10000;
313            padding: 12px 20px;
314            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
315            color: white;
316            border: none;
317            border-radius: 8px;
318            font-size: 16px;
319            font-weight: bold;
320            cursor: pointer;
321            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
322            transition: all 0.3s ease;
323        `;
324
325        button.addEventListener('mouseenter', () => {
326            button.style.transform = 'translateY(-2px)';
327            button.style.boxShadow = '0 6px 20px rgba(0, 0, 0, 0.3)';
328        });
329
330        button.addEventListener('mouseleave', () => {
331            button.style.transform = 'translateY(0)';
332            button.style.boxShadow = '0 4px 15px rgba(0, 0, 0, 0.2)';
333        });
334
335        button.addEventListener('click', async () => {
336            button.disabled = true;
337            button.textContent = '⏳ Thinking...';
338            try {
339                await selectCorrectAnswer();
340            } finally {
341                setTimeout(() => {
342                    button.disabled = false;
343                    button.textContent = '🤖 Auto Answer';
344                }, 2000);
345            }
346        });
347
348        document.body.appendChild(button);
349        console.log('Auto Answer button added to page');
350    }
351
352    // Watch for page changes and add button when quiz appears
353    const debouncedAddButton = debounce(addHelperButton, 500);
354
355    // Use MutationObserver to detect when quiz content loads
356    const observer = new MutationObserver(() => {
357        debouncedAddButton();
358        debouncedAutoAnswer();
359    });
360
361    // Initialize when page loads
362    function init() {
363        console.log('Initializing Miacademy Auto-Correct Answer Helper');
364        console.log('Auto-answer mode: ENABLED - will automatically answer new questions');
365
366        // Add button immediately if quiz is already visible
367        addHelperButton();
368
369        // Check for questions immediately
370        checkAndAutoAnswer();
371
372        // Watch for changes in the page
373        observer.observe(document.body, {
374            childList: true,
375            subtree: true
376        });
377
378        console.log('Watching for quiz questions...');
379    }
380
381    // Wait for page to be ready
382    if (document.readyState === 'loading') {
383        document.addEventListener('DOMContentLoaded', init);
384    } else {
385        init();
386    }
387})();
Miacademy Auto-Correct Answer Helper | Robomonkey