Extract MCQs

Extract MCQs from the webpage

Per 26-02-2024. Zie de nieuwste versie.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         Extract MCQs
// @namespace    themrsami
// @version      2.0
// @description  Extract MCQs from the webpage
// @author       You
// @match        http://*/*
// @match        https://*/*
// @grant        GM_registerMenuCommand
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Add some CSS for the button
    GM_addStyle(`
        #extract-mcqs-button {
            position: fixed;
            bottom: 20px;
            right: 20px;
            padding: 10px 20px;
            font-size: 16px;
            color: white;
            background-color: #007BFF;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            z-index: 9999;
        }
        #extract-mcqs-button:hover {
            background-color: #0056b3;
        }
    `);

    // Create the button
    let button = document.createElement('button');
    button.id = 'extract-mcqs-button';
    button.innerText = 'Extract MCQs';
    document.body.appendChild(button);

GM_registerMenuCommand('Extract MCQs', function() {
// Remove elements that destroy the structure
let elementsToRemove = [
    ...document.querySelectorAll('div[style="margin:30px 0px;"]'),
    ...document.querySelectorAll('div.sf-mobile-ads'),
    ...document.querySelectorAll('div.sf-desktop-ads'),
    ...document.querySelectorAll('span.collapseomatic')
];

for (let element of elementsToRemove) {
    if (element.parentNode) {
        element.parentNode.removeChild(element);
    }
}

let pTags = document.getElementsByTagName('p');
let results = [];

for (let i = 0; i < pTags.length; i++) {
    let imgHref = null;
    let aTag = pTags[i].getElementsByTagName('a')[0];
    if (aTag) {
        let imgTag = aTag.getElementsByTagName('img')[0];
        if (imgTag) {
            imgHref = imgTag.src || imgTag.getAttribute('data-src');
            aTag.parentNode.removeChild(aTag);
        }
    }

    let startsWithNumber = /^\d/.test(pTags[i].textContent);
    let nextSibling = pTags[i].nextElementSibling;
    if (startsWithNumber && nextSibling && nextSibling.tagName.toLowerCase() === 'div' && nextSibling.classList.contains('collapseomatic_content')) {
        let statementAndOptions = pTags[i].innerHTML.split('<br>');
        let statement = statementAndOptions.shift();
        let options = statementAndOptions.join('<br>').replace(/\n/g, '');
        let answerAndExplanation = nextSibling.innerHTML.split('<br>');
        let answer = answerAndExplanation.shift().replace(/\n/g, '');
        let explanation = answerAndExplanation.join('<br>').replace(/\n/g, '');
        results.push({
            statement: statement,
            imgHref: imgHref,
            options: options,
            answer: answer,
            explanation: explanation
        });
    }

    let nextDiv = pTags[i].nextElementSibling;
    if (nextDiv && nextDiv.tagName.toLowerCase() === 'div' && nextDiv.classList.contains('hk1_style-wrap5')) {
        let pre = nextDiv.getElementsByTagName('pre')[0];
        if (pre) {
            let nextP = nextDiv.nextElementSibling;
            if (nextP && nextP.tagName.toLowerCase() === 'p') {
                let nextDiv2 = nextP.nextElementSibling;
                if (nextDiv2 && nextDiv2.tagName.toLowerCase() === 'div' && nextDiv2.classList.contains('collapseomatic_content')) {
                    let statement = pTags[i].textContent;
                    let preContent = pre.textContent.replace(/\n/g, '');
                    let options = nextP.innerHTML.split('<br>').join('<br>').replace(/\n/g, '');
                    let answerAndExplanation = nextDiv2.innerHTML.split('<br>');
                    let answer = answerAndExplanation.shift().replace(/\n/g, '');
                    let explanation = answerAndExplanation.join('<br>').replace(/\n/g, '');
                    results.push({
                        statement: statement,
                        preContent: preContent,
                        options: options,
                        answer: answer,
                        explanation: explanation
                    });
                }
            }
        }

        let del1 = nextDiv.getElementsByClassName('del1')[0];
        if (del1) {
            let statement = pTags[i].textContent + ' ' + del1.textContent;
            let nextP = nextDiv.nextElementSibling;
            if (nextP && nextP.tagName.toLowerCase() === 'p') {
                let nextDiv2 = nextP.nextElementSibling;
                if (nextDiv2 && nextDiv2.tagName.toLowerCase() === 'div' && nextDiv2.classList.contains('collapseomatic_content')) {
                    let options = nextP.innerHTML.split('<br>').join('<br>').replace(/\n/g, '');
                    let answerAndExplanation = nextDiv2.innerHTML.split('<br>');
                    let answer = answerAndExplanation.shift().replace(/\n/g, '');
                    let explanation = answerAndExplanation.join('<br>').replace(/\n/g, '');
                    results.push({
                        statement: statement,
                        options: options,
                        answer: answer,
                        explanation: explanation
                    });
                }
            }
        }
    }
}

console.log(JSON.stringify(results, null, 2));


// ... Your existing code to extract the MCQs ...

// Now let's generate the HTML
let html = `
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"="width=device-width, initial-scale=1.0">
    <title>Quiz</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        @tailwind base;
        @tailwind components;
        @tailwind utilities;

        .option:hover:not(.selected) {
          @apply bg-gray-300;
        }
        .correct {
          @apply bg-green-200;
        }
        .incorrect {
          @apply bg-red-200;
        }
        .selected {
          @apply bg-gray-400;
        }
        .option:hover {
          @apply scale-105;
        }
        .selected {
          @apply scale-110;
        }
        .option:focus {
          @apply ring-4 ring-blue-500 ring-offset-2 ring-offset-gray-100;
        }
    </style>
</head>
<body class="bg-gray-100 p-10">

    <div class="flex justify-between items-center mb-4 sticky top-0 bg-white z-50">
        <div>
            <p class="text-lg font-bold">Time: <span id="timer" class="text-blue-500">00:00</span></p>
        </div>
        <div>
            <p class="text-lg font-bold text-green-500">Correct: <span id="correct-count">0</span></p>
            <p class="text-lg font-bold text-red-500">Incorrect: <span id="incorrect-count">0</span></p>
        </div>
    </div>



    ${results.map((result, index) => `
    <div class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4 flex flex-col my-2">
        <div class="md:flex mb-6">
            <div class="md:w-1/2 px-3">
                <label class="block uppercase tracking-wide text-blue-900 text-lg font-bold mb-2" for="grid-first-name">
                    Q${index + 1}: ${result.statement.replace(/^\d+\.\s*/, '')}
                </label>
                ${result.preContent ? `<pre>${result.preContent}</pre>` : ''}
            </div>
            <div class="md:w-1/2 px-3">
                ${result.imgHref ? `<img src="${result.imgHref}" alt="Image" class="mb-4">` : ''}
            </div>
        </div>
        <div class="md:flex mb-6">
            <div class="md:w-full px-3">
                <div id="options-${index}" class="grid grid-cols-1 md:grid-cols-2 gap-4">
                    ${result.options.split('<br>').map((option, optionIndex) => option.trim() !== "" ? `
                    <p class="option cursor-pointer py-2 px-4 rounded bg-blue-100 hover:bg-blue-200" onclick="checkAnswer(${index}, ${optionIndex})">${option}</p>
                    ` : '').join('')}
                </div>
                <button class="mt-3 text-white bg-blue-700 border-0 py-2 px-6 focus:outline-none hover:bg-blue-800 rounded text-lg" onclick="document.getElementById('answer-${index}').classList.toggle('hidden');document.getElementById('explanation-${index}').classList.toggle('hidden');">Show/Hide Answer</button>
                <p id="answer-${index}" class="hidden mt-3 text-grey-darker text-base bg-gray-200 p-4 rounded">${result.answer}</p>
                <p id="explanation-${index}" class="hidden mt-3 text-grey-darker text-base bg-gray-200 p-4 rounded">${result.explanation}</p>
            </div>
        </div>
    </div>
    `).join('')}
    <script src="script.js"></script>
</body>
</html>`;

// Download the file
let blob = new Blob([html], {type: "text/html;charset=utf-8"});
let link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = "quiz.html";
link.click();});

    // Add an event listener to the button
    button.addEventListener('click', function() {
        // Execute the menu command
        GM_executeMenuCommand('Extract MCQs');
    });

})();