{"id":3889,"date":"2025-02-04T08:25:36","date_gmt":"2025-02-04T08:25:36","guid":{"rendered":"https:\/\/luyenthitokutei.com\/?page_id=3889"},"modified":"2025-07-17T04:44:11","modified_gmt":"2025-07-17T04:44:11","slug":"thu-nghiem-3","status":"publish","type":"page","link":"https:\/\/luyenthitokutei.com\/ja\/thu-nghiem-3\/","title":{"rendered":"Th\u1eed nghi\u1ec7m"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"vi\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>H\u1ec7 Th\u1ed1ng Thi Tr\u1eafc Nghi\u1ec7m<\/title>\n    <style>\n          \/* Th\u00eam c\u00e1c style ch\u1ed1ng sao ch\u00e9p *\/\n          body {\n            -webkit-user-select: none; \/* Chrome\/Safari *\/\n            -moz-user-select: none; \/* Firefox *\/\n            -ms-user-select: none; \/* IE10+ *\/\n            user-select: none;\n            -webkit-touch-callout: none; \/* iOS Safari *\/\n        }\n        \n        \/* \u1ea8n c\u00e1c ph\u1ea7n t\u1eed khi in *\/\n        @media print {\n            body * {\n                visibility: hidden;\n            }\n        }\n        .test-container * {\n            box-sizing: border-box;\n            margin: 0;\n            padding: 0;\n            font-family: 'Roboto', Arial, sans-serif;\n        }\n        \n        .test-container {\n            background-color: #f5f5f5;\n            color: #333;\n            position: relative;\n        }\n        \n        .test-container .popup {\n            position: fixed;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: rgba(0, 0, 0, 0.7);\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            z-index: 1000;\n        }\n        \n        .test-container .popup-content {\n            background: white;\n            padding: 25px;\n            border-radius: 10px;\n            width: 90%;\n            max-width: 500px;\n            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);\n        }\n        \n        .test-container .popup-content h3 {\n            color: #00448D;\n            margin-bottom: 20px;\n            text-align: center;\n        }\n        \n        .test-container .popup-content input {\n            width: 100%;\n            padding: 12px;\n            margin-bottom: 15px;\n            border: 1px solid #ddd;\n            border-radius: 5px;\n            font-size: 16px;\n        }\n        \n        .test-container .popup-content button {\n            width: 100%;\n            padding: 12px;\n            background-color: #00448D;\n            color: white;\n            border: none;\n            border-radius: 5px;\n            font-size: 16px;\n            cursor: pointer;\n            transition: background-color 0.3s;\n        }\n        \n        .test-container .popup-content button:hover {\n            background-color: #003366;\n        }\n        \n        .test-container .container {\n            display: flex;\n            min-height: 100vh;\n        }\n        \n        .test-container .sidebar {\n            width: 280px;\n            background-color: #fff;\n            border-right: 1px solid #ddd;\n            box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1);\n            overflow-y: auto;\n            transition: transform 0.3s ease;\n        }\n        \n        .test-container .sidebar-header {\n            padding: 20px;\n            background-color: #00448D;\n            color: white;\n            text-align: center;\n            font-weight: bold;\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n        }\n        \n        .test-container .exam-list {\n            padding: 10px;\n        }\n        \n        .test-container .exam-item {\n            padding: 10px;\n            margin-bottom: 5px;\n            cursor: pointer;\n            border-radius: 5px;\n            transition: all 0.2s;\n        }\n        \n        .test-container .exam-item:hover {\n            background-color: #f0f0f0;\n        }\n        \n        .test-container .exam-item.active {\n            background-color: #00448D;\n            color: white;\n            font-weight: bold;\n        }\n        \n        .test-container .content {\n            flex: 1;\n            padding: 0;\n            height: 100vh;\n            overflow-y: auto;\n            position: relative;\n        }\n        \n        .test-container .header {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n            padding: 10px 15px;\n            background-color: white;\n            position: sticky;\n            top: 0;\n            z-index: 900;\n            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);\n        }\n\n        .test-container .header-left {\n            display: flex;\n            align-items: center;\n            gap: 15px;\n        }\n        \n        .test-container .timer-container {\n            background-color: #00448D;\n            color: white;\n            padding: 5px 10px;\n            border-radius: 20px;\n            font-size: 15px;\n            white-space: nowrap;\n        }\n        \n        .test-container .header-right {\n            display: flex;\n            align-items: center;\n        }\n        \n        .test-container .submit-button {\n            padding: 5px 15px;\n            background-color: #28a745;\n            color: white;\n            border: none;\n            border-radius: 20px;\n            font-size: 15px;\n            cursor: pointer;\n            transition: all 0.3s;\n        }\n        \n        .test-container .submit-button:hover {\n            background-color: #218838;\n        }\n        \n        .test-container .question-group {\n            background-color: white;\n            border-radius: 5px;\n            margin-bottom: 20px;\n            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);\n        }\n        \n        .test-container .group-header {\n            padding: 10px;\n            background-color: #f8f9fa;\n            border-bottom: 1px solid #eee;\n            border-radius: 5px 5px 0 0;\n        }\n        \n        .test-container .group-title {\n            font-weight: normal;\n            color: #00448D;\n        }\n        \n        .test-container .group-subtitle {\n            color: #666;\n            font-size: 14px;\n            margin-top: 5px;\n        }\n        \n        .test-container .question {\n            padding: 15px;\n            font-weight: normal;\n            border-bottom: 2px solid #eee;\n        }\n        .test-container .question-container {\n            display: none;\n        }\n        .test-container .question-container.show-questions {\n            display: block;\n        }\n        \n        .test-container .question-text {\n            margin-bottom: 15px;\n            font-weight: normal;\n        }\n        \n        .test-container .question-image {\n            max-width: 100%;\n            height: auto;\n            margin: 10px 0;\n            border-radius: 5px;\n        }\n        \n        .test-container .question-option {\n            display: block;\n            padding: 10px;\n            margin: 5px 0;\n            border-radius: 5px;\n            transition: all 0.2s;\n            font-weight: normal;\n        }\n        \n        .test-container .question-option:hover {\n            background-color: #f0f7ff;\n        }\n        \n        .test-container .question-option input {\n            margin-right: 10px;\n        }\n        \n        .test-container .explanation {\n            display: none;\n            background-color: #e6f7ff;\n            padding: 10px;\n            margin-top: 10px;\n            border-radius: 5px;\n            border-left: 4px solid #00448D;\n            font-size: 14px;\n            font-weight: normal;\n        }\n        \n        \/* Start quiz popup *\/\n        .test-container .start-popup {\n            position: fixed;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: rgba(0, 0, 0, 0.7);\n            display: none;\n            justify-content: center;\n            align-items: center;\n            z-index: 1000;\n        }\n        \n        .test-container .start-popup-content {\n            background: white;\n            padding: 30px;\n            border-radius: 10px;\n            text-align: center;\n            max-width: 400px;\n        }\n        \n        .test-container .start-popup button {\n            padding: 10px 20px;\n            background-color: #00448D;\n            color: white;\n            border: none;\n            border-radius: 5px;\n            margin-top: 20px;\n            cursor: pointer;\n        }\n        \n        \/* No exam message *\/\n        .test-container .no-exam-message {\n            text-align: center;\n            padding: 50px;\n            font-size: 18px;\n            color: #dc3545;\n        }\n        \n        \/* Menu toggle button *\/\n        .test-container .menu-toggle {\n            display: none;\n            background: none;\n            border: none;\n            color: #00448D; \/* \u0110\u1ed5i m\u00e0u icon th\u00e0nh m\u00e0u xanh \u0111\u1eadm *\/\n            font-size: 22px; \/* T\u0103ng k\u00edch th\u01b0\u1edbc icon *\/\n            cursor: pointer;\n            padding: 4px;\n            margin-right: 15px;\n            border-radius: 50%;\n            width: 40px;\n            height: 40px;\n            align-items: center;\n            justify-content: center;\n            transition: all 0.3s ease;\n        }\n\n        .test-container .menu-toggle:hover {\n            background-color: white;\n            transform: scale(1.1);\n        }\n\n        .test-container .menu-toggle#closeMenu {\n            color: white;\n            background-color: transparent;\n            box-shadow: none;\n            font-size: 22px;\n            margin-right: 0;\n        }\n\n        .test-container .menu-toggle#closeMenu:hover {\n            color: #f0f0f0;\n        }\n        .test-container .result-popup {\n        position: fixed;\n        top: 0;\n        left: 0;\n        width: 100%;\n        height: 100%;\n        background: rgba(0, 0, 0, 0.7);\n        display: none;\n        justify-content: center;\n        align-items: center;\n        z-index: 1000;\n    }\n    \n    .test-container .result-popup-content {\n        background: white;\n        padding: 30px;\n        border-radius: 10px;\n        width: 90%;\n        max-width: 500px;\n        box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);\n        text-align: center;\n    }\n    \n    .test-container .result-popup h3 {\n        color: #00448D;\n        margin-bottom: 20px;\n    }\n    \n    .test-container .result-details {\n        text-align: left;\n        margin: 20px 0;\n        line-height: 1.8;\n    }\n    \n    .test-container .result-row {\n        display: flex;\n        justify-content: space-between;\n        margin-bottom: 10px;\n    }\n    \n    .test-container .result-label {\n        font-weight: bold;\n        color: #555;\n    }\n    \n    .test-container .result-value {\n        color: #00448D;\n        font-weight: bold;\n    }\n    \n    .test-container .result-popup button {\n        padding: 10px 20px;\n        background-color: #00448D;\n        color: white;\n        border: none;\n        border-radius: 5px;\n        cursor: pointer;\n        transition: background-color 0.3s;\n    }\n    \n    .test-container .result-popup button:hover {\n        background-color: #003366;\n    }\n        \/* Responsive styles *\/\n        @media (max-width: 768px) {\n            .test-container .container {\n                flex-direction: column;\n            }\n            \n            .test-container .sidebar {\n                position: fixed;\n                top: 0;\n                left: 0;\n                height: 100vh;\n                width: 280px;\n                z-index: 1000;\n                transform: translateX(-100%);\n            }\n            \n            .test-container .sidebar.visible {\n                transform: translateX(0);\n            }\n            \n            .test-container .content {\n                margin-left: 0;\n                padding-top: 60px; \/* Space for fixed header *\/\n            }\n            \n            .test-container .menu-toggle {\n                display: block;\n            }\n            \n            .test-container .header {\n                position: fixed;\n                width: 100%;\n                top: 0;\n                padding: 10px 15px;\n            }\n        }\n    <\/style>\n<\/head>\n<body>\n    <div class=\"test-container\">\n    <div id=\"userIdPopup\" class=\"popup\">\n        <div class=\"popup-content\">  \n            <h3>NH\u1eacP TH\u00d4NG TIN \u0110\u1ec2 TI\u1ebeP T\u1ee4C<\/h3>\n            <input style=\"display:none;\" id=\"userName\" placeholder=\"H\u1ecd v\u00e0 t\u00ean\"\/>\n            <input id=\"userId\" placeholder=\"M\u00e3 h\u1ecdc vi\u00ean\" \/>\n            <input style=\"display:none;\" id=\"classId\" placeholder=\"L\u1edbp h\u1ecdc\" \/>\n            <button id=\"userInfo-button\" onclick=\"checkUserId()\">X\u00e1c nh\u1eadn<\/button>\n        <\/div>\n    <\/div>\n    <!-- Main Container -->\n    <div class=\"container\" id=\"mainContainer\" style=\"display:none;\">\n        <div class=\"sidebar\" id=\"sidebar\">\n            <div class=\"sidebar-header\">\n                Danh s\u00e1ch \u0111\u1ec1 thi\n                <button class=\"menu-toggle\" id=\"closeMenu\">\u00d7<\/button>\n            <\/div>\n            <div class=\"exam-list\" id=\"examList\"><\/div>\n        <\/div>\n        \n        <div class=\"content\" id=\"contentArea\">\n            <!-- Content will be loaded here -->\n        <\/div>\n    <\/div>\n    \n    <!-- Start Quiz Popup -->\n    <div id=\"startQuizPopup\" class=\"start-popup\">\n        <div class=\"start-popup-content\">\n            <p>H\u00e3y ch\u1edd hi\u1ec7u l\u1ec7nh \u0111\u1ec3 b\u1eaft \u0111\u1ea7u!<\/p>\n            <button onclick=\"startTimer()\">B\u1eaft \u0111\u1ea7u l\u00e0m b\u00e0i<\/button>\n        <\/div>\n    <\/div>\n    <!-- No Exam Message -->\n    <div id=\"noExamMessage\" class=\"no-exam-message\" style=\"display:none;\">\n        <h2>Kh\u00f4ng c\u00f3 \u0111\u1ec1 thi n\u00e0o \u0111\u01b0\u1ee3c hi\u1ec3n th\u1ecb<\/h2>\n        <p>Hi\u1ec7n t\u1ea1i kh\u00f4ng c\u00f3 \u0111\u1ec1 thi n\u00e0o s\u1eb5n s\u00e0ng. Vui l\u00f2ng quay l\u1ea1i sau.<\/p>\n    <\/div>\n    <div id=\"resultPopup\" class=\"result-popup\">\n        <div class=\"result-popup-content\">\n            <h3>K\u1ebeT QU\u1ea2 B\u00c0I THI<\/h3>\n            <div class=\"result-details\" id=\"resultDetails\">\n                <!-- N\u1ed9i dung k\u1ebft qu\u1ea3 s\u1ebd \u0111\u01b0\u1ee3c \u0111i\u1ec1n v\u00e0o \u0111\u00e2y -->\n            <\/div>\n            <button onclick=\"closeResultPopup()\">\u0110\u00f3ng<\/button>\n        <\/div>\n    <\/div>\n    <\/div>\n    <script>\n        const scriptUrl = \"https:\/\/script.google.com\/macros\/s\/AKfycbxx8OEjLGfiVUQpjS7UfONJOYytJyaKTtT0bG_mH0Jgux-wmBgqaoT3LnIxNFZgqgBHmA\/exec\";\n        let timeLeft = 0; \n        let timerInterval;\n        let correctAnswers = [];\n        let questionScores = [];\n        let totalQuestions = 0;\n        let allExamsData = {};\n        let currentQuestionIds = [];\n        let examDuration = 10; \n        function disableCopyPaste() {\n            const userIdInput = document.getElementById('userId');\n            if (userIdInput) {\n                userIdInput.onpaste = function(e) {\n                    return true; \/\/ Cho ph\u00e9p paste\n                };\n            }\n            \/\/ Ch\u1ed1ng nh\u1ea5p chu\u1ed9t ph\u1ea3i\n            document.addEventListener('contextmenu', function(e) {\n                e.preventDefault();\n                return false;\n            });\n            \n            \/\/ Ch\u1ed1ng k\u00e9o th\u1ea3\n            document.addEventListener('dragstart', function(e) {\n                e.preventDefault();\n                return false;\n            });\n            \n            \/\/ Ch\u1ed1ng ph\u00edm t\u1eaft (Ctrl+C, Ctrl+V, etc.)\n            document.addEventListener('keydown', function(e) {\n                \/\/ Disable Ctrl+A, Ctrl+C, Ctrl+X, Ctrl+V\n                if (e.ctrlKey && (e.keyCode === 65 || e.keyCode === 67 || e.keyCode === 86 || e.keyCode === 88)) {\n                    e.preventDefault();\n                    return false;\n                }\n                \n                \/\/ Disable F12 (DevTools)\n                if (e.keyCode === 123) {\n                    e.preventDefault();\n                    return false;\n                }\n            });\n            \n            \/\/ Ch\u1ed1ng ch\u1ee5p m\u00e0n h\u00ecnh tr\u00ean Android\n            document.addEventListener('visibilitychange', function() {\n                if (document.hidden) {\n                    visibilityChangeCount++;\n                    if (visibilityChangeCount > 2 && isQuizStarted) {\n                        alert('B\u1ea1n \u0111\u00e3 r\u1eddi kh\u1ecfi trang thi qu\u00e1 nhi\u1ec1u l\u1ea7n. B\u00e0i thi s\u1ebd t\u1ef1 \u0111\u1ed9ng n\u1ed9p.');\n                        submitQuiz();\n                    } else if (isQuizStarted) {\n                        alert('C\u1ea3nh b\u00e1o: B\u1ea1n \u0111\u00e3 r\u1eddi kh\u1ecfi trang thi. N\u1ebfu ti\u1ebfp t\u1ee5c, b\u00e0i thi s\u1ebd t\u1ef1 \u0111\u1ed9ng n\u1ed9p.');\n                    }\n                }\n            });\n        }\n        \n        \/\/ G\u1ecdi h\u00e0m b\u1ea3o v\u1ec7 khi trang \u0111\u01b0\u1ee3c t\u1ea3i\n        disableCopyPaste();\n        document.addEventListener('DOMContentLoaded', () => {  \n            const savedUserId = localStorage.getItem('userId');\n            const savedName = localStorage.getItem('userName');\n            const savedClassId = localStorage.getItem('classId');\n            const deviceId = localStorage.getItem('deviceId');\n\n            if (savedUserId && savedName && savedClassId) {\n                \/\/ \u0110i\u1ec1n th\u00f4ng tin v\u00e0o c\u00e1c input \u1ea9n\n                document.getElementById('userName').value = savedName;\n                document.getElementById('classId').value = savedClassId;\n                \n                \/\/ \u1ea8n popup \u0111\u0103ng nh\u1eadp v\u00e0 hi\u1ec3n th\u1ecb n\u1ed9i dung ch\u00ednh\n                document.getElementById('userIdPopup').style.display = 'none';\n                document.getElementById('mainContainer').style.display = 'flex';\n                \n                \/\/ Load danh s\u00e1ch \u0111\u1ec1 thi\n                loadExams();\n            } else {\n                \/\/ Hi\u1ec3n th\u1ecb popup \u0111\u0103ng nh\u1eadp n\u1ebfu thi\u1ebfu th\u00f4ng tin\n                document.getElementById('userIdPopup').style.display = 'flex';\n            }\n            \n            \/\/ Setup menu toggle\n            document.getElementById('closeMenu').addEventListener('click', () => {\n                document.getElementById('sidebar').classList.remove('visible');\n            });\n        });\n        \n        \/\/ Toggle menu function\n        function toggleMenu() {\n            const sidebar = document.getElementById('sidebar');\n            sidebar.classList.toggle('visible');\n        }\n        \n        \/\/ Check User ID\n        function checkUserId() {\n            const userIdInput = document.getElementById('userId');\n            const userId = userIdInput.value.trim();\n            const confirmButton = document.getElementById('userInfo-button');\n            \n            if (!userId) {\n                alert('Vui l\u00f2ng nh\u1eadp \u0111\u1ea7y \u0111\u1ee7 th\u00f4ng tin!');\n                return;\n            }\n\n            \/\/ V\u00f4 hi\u1ec7u n\u00fat X\u00e1c nh\u1eadn ngay sau khi nh\u1ea5n\n            confirmButton.disabled = true;\n            confirmButton.textContent = '\u0110ang ki\u1ec3m tra...';\n\n            const url = `${scriptUrl}?action=checkUserId&userId=${userId}`;\n\n            fetch(url)\n                .then(response => response.json())\n                .then(result => {\n                    if (result.error) throw new Error(result.error);\n\n                    if (result.exists) {\n                        const classId = result.classId || \"\";\n                        const userName = result.userName || \"\";\n                        if (!classId) {\n                            alert(\"Kh\u00f4ng t\u00ecm th\u1ea5y l\u1edbp h\u1ecdc c\u1ee7a h\u1ecdc vi\u00ean. Vui l\u00f2ng ki\u1ec3m tra l\u1ea1i.\");\n                            confirmButton.disabled = false;\n                            confirmButton.textContent = 'X\u00e1c nh\u1eadn';\n                            return;\n                        }\n\n                        localStorage.setItem('userId', userId);\n                        localStorage.setItem('userName', userName);\n                        localStorage.setItem('classId', classId);\n\n                        document.getElementById('classId').value = classId;\n                        document.getElementById('userName').value = userName;\n\n                        if (!localStorage.getItem('deviceId')) {\n                            localStorage.setItem('deviceId', generateRandomID());\n                        }\n\n                        document.getElementById('userIdPopup').style.display = 'none';\n                        loadExams();\n                    } else {\n                        alert('M\u00e3 h\u1ecdc vi\u00ean kh\u00f4ng t\u1ed3n t\u1ea1i. Vui l\u00f2ng nh\u1eadp m\u00e3 h\u1ecdc vi\u00ean \u0111\u00fang.');\n                        confirmButton.disabled = false;\n                        confirmButton.textContent = 'X\u00e1c nh\u1eadn';\n                    }\n                })\n                .catch(error => {\n                    console.error('Error:', error);\n                    alert('C\u00f3 l\u1ed7i x\u1ea3y ra khi ki\u1ec3m tra m\u00e3 h\u1ecdc vi\u00ean: ' + error.message);\n                    confirmButton.disabled = false;\n                    confirmButton.textContent = 'X\u00e1c nh\u1eadn';\n                });\n        }\n\n        \n        \/\/ Load Exams\n        function loadExams() {\n            const classId = localStorage.getItem('classId');\n            const url = `${scriptUrl}?action=fetchExams&classId=${encodeURIComponent(classId)}`;\n            \n            fetch(url)\n                .then(response => response.json())\n                .then(result => {\n                    if (result.error) {\n                        throw new Error(result.error);\n                    }\n                    \n                    if (result.status === \"all_hidden\") {\n                        document.getElementById('mainContainer').style.display = 'none';\n                        document.getElementById('noExamMessage').style.display = 'block';\n                        return;\n                    }\n                    \n                    if (result.status === \"success\" && result.exams.length > 0) {\n                        document.getElementById('mainContainer').style.display = 'flex';\n                        document.getElementById('noExamMessage').style.display = 'none';\n                        \n                        const examList = document.getElementById('examList');\n                        examList.innerHTML = '';\n                        \n                        \/\/ Load all exams data first\n                        const loadPromises = result.exams.map(exam => {\n                            return loadExamData(exam.id, exam.name)\n                                .then(questions => {\n                                    allExamsData[exam.id] = {\n                                        id: exam.id,\n                                        name: exam.name,\n                                        duration: exam.duration, \n                                        questions: questions\n                                    };\n                                    return exam;\n                                });\n                        });\n                        \n                        Promise.all(loadPromises).then(exams => {\n                            \/\/ After all data loaded, create menu items\n                            exams.forEach(exam => {\n                                const examItem = document.createElement('div');\n                                examItem.className = 'exam-item';\n                                examItem.textContent = exam.name;\n                                examItem.dataset.examId = exam.id;\n                                examItem.onclick = () => {\n                                    showExam(exam.id);\n                                    document.getElementById('sidebar').classList.remove('visible');\n                                };\n                                examList.appendChild(examItem);\n                            });\n                            \n                            \/\/ Add menu toggle button to header for mobile\n                            const headerHTML = `\n                                <div class=\"header\">\n                                    <div class=\"header-left\">\n                                        <button class=\"menu-toggle\" onclick=\"toggleMenu()\">\u2630<\/button>\n                                        <div class=\"timer-container\">\n                                            <span id=\"timer\">${formatTime(timeLeft)}<\/span>\n                                        <\/div>\n                                    <\/div>\n                                    <div class=\"header-right\">\n                                        <button class=\"submit-button\" id=\"submitButton\" onclick=\"submitQuiz()\">N\u1ed9p b\u00e0i<\/button>\n                                    <\/div>\n                                <\/div>\n                            `;\n                            document.getElementById('contentArea').innerHTML = headerHTML;\n                        });\n                    } else {\n                        document.getElementById('mainContainer').style.display = 'none';\n                        document.getElementById('noExamMessage').style.display = 'block';\n                    }\n                })\n                .catch(error => {\n                    console.error('Error:', error);\n                    alert('C\u00f3 l\u1ed7i x\u1ea3y ra khi t\u1ea3i danh s\u00e1ch \u0111\u1ec1 thi: ' + error.message);\n                });\n        }\n     \n        \/\/ Load Exam Data\n        function loadExamData(examId, examName) {\n            return fetch(`${scriptUrl}?action=fetchQuestions&examId=${examId}`)\n                .then(response => {\n                    if (!response.ok) {\n                        throw new Error('Network response was not ok');\n                    }\n                    return response.json();\n                })\n                .then(data => {\n                    if (data.error) {\n                        throw new Error(data.error);\n                    }\n                    return data;\n                });\n        }\n        \n        \/\/ Show Exam\n        function showExam(examId) {\n            \/\/ Update active state in sidebar\n            const examItems = document.querySelectorAll('.exam-item');\n            examItems.forEach(item => {\n                item.classList.remove('active');\n                if (item.dataset.examId === examId) {\n                    item.classList.add('active');\n                }\n            });\n            \n            \/\/ Get exam data from cache\n            const examData = allExamsData[examId];\n            if (!examData) {\n                alert('Kh\u00f4ng th\u1ec3 t\u1ea3i d\u1eef li\u1ec7u \u0111\u1ec1 thi. Vui l\u00f2ng th\u1eed l\u1ea1i.');\n                return;\n            }\n            \n            currentExamId = examId;\n            examDuration = examData.duration || 10;\n            timeLeft = examDuration * 60;\n            \n            const contentArea = document.getElementById('contentArea');\n            contentArea.innerHTML = `\n                <div class=\"header\">\n                    <div class=\"header-left\">\n                        <button class=\"menu-toggle\" onclick=\"toggleMenu()\">\u2630<\/button>\n                        <div class=\"timer-container\">\n                            <span id=\"timer\">${formatTime(timeLeft)}<\/span>\n                        <\/div>\n                    <\/div>\n                    <div class=\"header-right\">\n                        <button class=\"submit-button\" id=\"submitButton\" onclick=\"submitQuiz()\">N\u1ed9p b\u00e0i<\/button>\n                    <\/div>\n                <\/div>\n                <div id=\"questionContainer\" class=\"question-container\"><\/div>\n            `;\n            \n            displayQuestions(examData.questions);\n            document.getElementById('startQuizPopup').style.display = 'flex';\n            if (timerInterval) {\n                clearInterval(timerInterval);\n                timerInterval = null;\n            }\n        }\n        \n        function formatTime(seconds) {\n            const mins = Math.floor(seconds \/ 60);\n            const secs = seconds % 60;\n            return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\n        }\n        \n        function displayQuestions(questions) {\n            const container = document.getElementById('questionContainer');\n            container.innerHTML = '';\n\n            if (!questions || questions.length === 0) {\n                container.innerHTML = '<p>Kh\u00f4ng c\u00f3 c\u00e2u h\u1ecfi n\u00e0o trong \u0111\u1ec1 thi n\u00e0y.<\/p>';\n                return;\n            }\n\n            \/\/ T\u1ea1o m\u1ea3ng tracking \u0111\u1ec3 l\u01b0u th\u00f4ng tin c\u00e2u h\u1ecfi \u0111\u00e3 \u0111\u01b0\u1ee3c shuffle\n            let questionTracking = [];\n\n            \/\/ Group questions based on groupTitle\n            const groupedQuestions = [];\n            let currentGroup = null;\n\n            questions.forEach(question => {\n                \/\/ If this question has a groupTitle, start a new group\n                if (question.groupTitle) {\n                    currentGroup = {\n                        title: question.groupTitle,\n                        subtitle: question.groupSubtitle,\n                        image: question.groupImage,\n                        audio: question.groupAudio,\n                        questions: []\n                    };\n                    groupedQuestions.push(currentGroup);\n                }\n                \n                \/\/ If we have a current group, add the question to it\n                if (currentGroup) {\n                    currentGroup.questions.push(question);\n                } else {\n                    \/\/ If no group, create a default group for ungrouped questions\n                    currentGroup = {\n                        title: 'Ungrouped',\n                        subtitle: '',\n                        image: '',\n                        audio: '',\n                        questions: [question]\n                    };\n                    groupedQuestions.push(currentGroup);\n                }\n            });\n\n            \/\/ Shuffle the order of groups\n            shuffle(groupedQuestions);\n\n            let globalQuestionIndex = 0;\n\n            \/\/ Reset v\u00e0 t\u1ea1o m\u1edbi c\u00e1c m\u1ea3ng tracking\n            correctAnswers = [];\n            questionScores = [];\n            let allQuestionIds = [];\n\n            \/\/ Display each group and its questions\n            groupedQuestions.forEach((group, groupIndex) => {\n                \/\/ Shuffle questions within the group\n                const shuffledQuestions = [...group.questions];\n                shuffle(shuffledQuestions);\n\n                \/\/ L\u01b0u th\u00f4ng tin tracking cho c\u00e1c c\u00e2u h\u1ecfi \u0111\u00e3 shuffle\n                shuffledQuestions.forEach(q => {\n                    questionTracking.push({\n                        question: q,\n                        originalIndex: questions.indexOf(q)\n                    });\n                    \n                    \/\/ C\u1eadp nh\u1eadt correctAnswers v\u00e0 questionScores theo th\u1ee9 t\u1ef1 \u0111\u00e3 shuffle\n                    correctAnswers.push(q.correctAnswer);\n                    questionScores.push(parseFloat(q.questionScore) || 1);\n                    allQuestionIds.push(q.questionId);\n                });\n\n                let groupHTML = '';\n\n                \/\/ Group header (only if not 'Ungrouped')\n                if (group.title !== 'Ungrouped') {\n                    groupHTML += `\n                        <div class=\"group-header\">\n                            <div class=\"group-title\">Ph\u1ea7n ${groupIndex + 1}: ${group.title}<\/div>\n                            ${group.subtitle ? `<div class=\"group-subtitle\">${group.subtitle}<\/div>` : ''}\n                            ${group.image ? `<img decoding=\"async\" class=\"question-image\" src=\"${group.image}\">` : ''}\n                            ${group.audio ? `\n                                <div class=\"audio-player\">\n                                    <audio controls><source src=\"${group.audio}\" type=\"audio\/mpeg\"><\/audio>\n                                <\/div>\n                            ` : ''}\n                        <\/div>\n                    `;\n                }\n\n                \/\/ Add each question in the group\n                shuffledQuestions.forEach(question => {\n                    const questionIndex = globalQuestionIndex;\n\n                    groupHTML += `\n                        <div class=\"question\" id=\"question-${questionIndex}\">\n                            <div class=\"question-text\">C\u00e2u ${questionIndex + 1}: ${question.questionText}<\/div>\n                            ${question.questionImage ? `<img decoding=\"async\" class=\"question-image\" src=\"${question.questionImage}\">` : ''}\n                            ${question.questionAudio ? `\n                                <div class=\"audio-player\">\n                                    <audio controls controlsList=\"nodownload\" data-plays=\"0\" onplay=\"checkAudioPlays(this)\">\n                                        <source src=\"${question.questionAudio}\" type=\"audio\/mpeg\">\n                                    <\/audio><br>\n                                    <small class=\"play-counter\">(L\u01b0\u1ee3t nghe c\u00f2n l\u1ea1i: 3)<\/small>\n                                <\/div>\n                            ` : ''}\n                            <label class=\"question-option\">\n                                <input type=\"radio\" name=\"question${questionIndex}\" value=\"A\">\n                                ${question.optionA || 'N\/A'}\n                            <\/label>\n                            <label class=\"question-option\">\n                                <input type=\"radio\" name=\"question${questionIndex}\" value=\"B\">\n                                ${question.optionB || 'N\/A'}\n                            <\/label>\n                            ${question.optionC ? `\n                                <label class=\"question-option\">\n                                    <input type=\"radio\" name=\"question${questionIndex}\" value=\"C\">\n                                    ${question.optionC}\n                                <\/label>\n                            ` : ''}\n                            ${question.optionD ? `\n                                <label class=\"question-option\">\n                                    <input type=\"radio\" name=\"question${questionIndex}\" value=\"D\">\n                                    ${question.optionD}\n                                <\/label>\n                            ` : ''}\n                            ${question.explanation ? `\n                                <div class=\"explanation\" id=\"explanation-${questionIndex}\">\n                                    <strong>Gi\u1ea3i th\u00edch:<\/strong> ${question.explanation}\n                                <\/div>\n                            ` : ''}\n                        <\/div>\n                    `;\n                    globalQuestionIndex++;\n                });\n\n                \/\/ Add the group to the container\n                container.innerHTML += `<div class=\"question-group\">${groupHTML}<\/div>`;\n            });\n\n            \/\/ L\u01b0u l\u1ea1i danh s\u00e1ch questionIds theo th\u1ee9 t\u1ef1 hi\u1ec3n th\u1ecb\n            window.currentQuestionIds = allQuestionIds;\n            totalQuestions = globalQuestionIndex;\n            setupAnswerSelection();\n        }\n      \n        function checkAudioPlays(audioElement) {\n            let playCount = parseInt(audioElement.dataset.plays || \"0\") || 0;\n            const maxPlays = 3;\n\n            if (playCount >= maxPlays) {\n                audioElement.pause();\n                audioElement.currentTime = 0;\n                alert(`B\u1ea1n ch\u1ec9 \u0111\u01b0\u1ee3c nghe t\u1ed1i \u0111a ${maxPlays} l\u1ea7n.`);\n                return;\n            }\n\n            playCount += 1;\n            audioElement.dataset.plays = playCount;\n\n            const counterText = audioElement.parentElement.querySelector('.play-counter');\n            if (counterText) {\n                const remaining = maxPlays - playCount;\n                counterText.textContent = `(L\u01b0\u1ee3t nghe c\u00f2n l\u1ea1i: ${remaining})`;\n            }\n        }\n        function shuffle(array) {\n            try {\n                \/\/ S\u1eed d\u1ee5ng Fisher-Yates shuffle algorithm\n                for (let i = array.length - 1; i > 0; i--) {\n                    const j = Math.floor(Math.random() * (i + 1));\n                    [array[i], array[j]] = [array[j], array[i]];\n                }\n                return array;\n            } catch (error) {\n                console.error('Shuffle error:', error);\n                return array; \/\/ Tr\u1ea3 v\u1ec1 m\u1ea3ng g\u1ed1c n\u1ebfu c\u00f3 l\u1ed7i\n            }\n        }\n\n        \n        \/\/ Setup Answer Selection\n        function setupAnswerSelection() {\n            const radioButtons = document.querySelectorAll('input[type=\"radio\"]');\n            radioButtons.forEach(radio => {\n                radio.addEventListener('change', function() {\n                    const questionDiv = this.closest('.question');\n                    const labels = questionDiv.querySelectorAll('.question-option');\n                    \n                    labels.forEach(label => {\n                        label.style.backgroundColor = '';\n                        label.style.color = '';\n                    });\n                    \n                    this.closest('.question-option').style.backgroundColor = '#e6f7ff';\n                });\n            });\n        }\n        \n        \/\/ Start Timer\n        function startTimer() {\n            document.getElementById('startQuizPopup').style.display = 'none';\n            document.querySelector('.question-container').style.display = 'block';\n            \n            if (!timerInterval) {\n                timerInterval = setInterval(updateTimer, 1000);\n            }\n        }\n        \n        \/\/ Update Timer\n        function updateTimer() {\n            const timerElement = document.getElementById('timer');\n            timeLeft--;\n            \n            timerElement.textContent = formatTime(timeLeft);\n            \n            if (timeLeft < 0) {\n                clearInterval(timerInterval);\n                endQuiz();\n            }\n        }\n        \n        \/\/ Submit Quiz\n        \/\/ Submit Quiz\n        function submitQuiz() {\n            const userName = document.getElementById('userName').value;\n            const classId = document.getElementById('classId').value;\n            const userId = localStorage.getItem('userId');\n            const examId = allExamsData[currentExamId].id;\n            const testName = allExamsData[currentExamId].name;\n            \n            if (!confirm(\"B\u1ea1n c\u00f3 ch\u1eafc ch\u1eafn mu\u1ed1n n\u1ed9p b\u00e0i thi n\u00e0y?\")) {\n                return;\n            }\n            \n            clearInterval(timerInterval);\n            document.getElementById('submitButton').style.display = 'none';\n            document.getElementById('submitButton').disabled = true;\n            \n            \/\/ Disable all inputs\n            const radioButtons = document.querySelectorAll('input[type=\"radio\"]');\n            radioButtons.forEach(radio => {\n                radio.disabled = true;\n            });\n            \n            \/\/ Calculate time spent\n            const totalTime = examDuration * 60;\n            const timeSpent = totalTime - timeLeft;\n            const minutes = Math.floor(timeSpent \/ 60);\n            const seconds = timeSpent % 60;\n            \n            \/\/ Collect answers\n            let answers = [];\n            let correctCount = 0;\n            let totalScore = 0;\n            let maxPossibleScore = 0;\n            \n            for (let i = 0; i < totalQuestions; i++) {\n                const selected = document.querySelector(`input[name=\"question${i}\"]:checked`);\n                const answer = selected ? selected.value : \"N\/A\";\n                answers.push(answer);\n                \n                \/\/ Check if answer is correct\n                if (answer === correctAnswers[i]) {\n                    correctCount++;\n                    totalScore += questionScores[i];\n                }\n                \n                \/\/ Calculate max possible score\n                maxPossibleScore += questionScores[i];\n            }\n            \n            \/\/ Show explanations\n            for (let i = 0; i < totalQuestions; i++) {\n                const explanation = document.getElementById(`explanation-${i}`);\n                if (explanation) {\n                    explanation.style.display = 'block';\n                }\n            }\n            \n            fetch(scriptUrl, {\n                method: 'POST',\n                mode: 'no-cors',\n                headers: {\n                    'Content-Type': 'application\/json',\n                },\n                body: JSON.stringify({ \n                    action: 'submitQuiz', \n                    userId, \n                    userName, \n                    classId, \n                    examId, \n                    correctCount, \n                    minutes, \n                    totalQuestions,\n                    totalScore, \n                    answers,\n                    questionIds: window.currentQuestionIds || [], \/\/ S\u1eed d\u1ee5ng danh s\u00e1ch questionIds \u0111\u00e3 l\u01b0u\n                    correctAnswers: correctAnswers \n                }),\n            })\n            .then(() => {\n                showResultPopup({\n                    totalQuestions,\n                    correctCount,\n                    totalScore,\n                    maxPossibleScore,\n                    minutes,\n                    seconds\n                });\n            })\n            .catch(error => {\n                console.error('Error:', error);\n                alert('C\u00f3 l\u1ed7i x\u1ea3y ra khi n\u1ed9p b\u00e0i: ' + error.message);\n            });\n        }\n\n        \/\/ Show Result Popup\n        function showResultPopup(results) {\n            const resultDetails = document.getElementById('resultDetails');\n            const percentage = (results.correctCount \/ results.totalQuestions) * 100;\n            \n            resultDetails.innerHTML = `\n                <div class=\"result-row\">\n                    <span class=\"result-label\">S\u1ed1 c\u00e2u \u0111\u00fang:<\/span>\n                    <span class=\"result-value\">${results.correctCount}<\/span>\n                <\/div>\n                <div class=\"result-row\">\n                    <span class=\"result-label\">T\u1ed5ng \u0111i\u1ec3m:<\/span>\n                    <span class=\"result-value\">${results.totalScore.toFixed(1)}\/${results.maxPossibleScore.toFixed(1)}<\/span>\n                <\/div>\n                <div class=\"result-row\">\n                    <span class=\"result-label\">T\u1ec9 l\u1ec7 \u0111\u00fang:<\/span>\n                    <span class=\"result-value\">${percentage.toFixed(1)}%<\/span>\n                <\/div>\n                <div class=\"result-row\">\n                    <span class=\"result-label\">Th\u1eddi gian l\u00e0m b\u00e0i:<\/span>\n                    <span class=\"result-value\">${results.minutes} ph\u00fat ${results.seconds} gi\u00e2y<\/span>\n                <\/div>\n            `;\n            \n            document.getElementById('resultPopup').style.display = 'flex';\n        }\n\n        \/\/ Close Result Popup\n        function closeResultPopup() {\n            document.getElementById('resultPopup').style.display = 'none';\n        }\n        \n        \/\/ End Quiz\n        function endQuiz() {\n            const radioButtons = document.querySelectorAll('input[type=\"radio\"]');\n            radioButtons.forEach(radio => {\n                radio.disabled = true;\n            });\n            \n            alert(\"Th\u1eddi gian l\u00e0m b\u00e0i \u0111\u00e3 h\u1ebft! H\u1ec7 th\u1ed1ng s\u1ebd t\u1ef1 \u0111\u1ed9ng n\u1ed9p b\u00e0i.\");\n            submitQuiz();\n        }\n        \n        \/\/ Helper Functions\n        function generateRandomID() {\n            return Math.random().toString(36).substr(2, 9);\n        }\n        \n        function validateEmail(email) {\n            const re = \/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$\/;\n            return re.test(String(email).toLowerCase());\n        }\n    <\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>H\u1ec7 Th\u1ed1ng Thi Tr\u1eafc Nghi\u1ec7m NH\u1eacP TH\u00d4NG TIN \u0110\u1ec2 TI\u1ebeP T\u1ee4C X\u00e1c nh\u1eadn Danh s\u00e1ch \u0111\u1ec1 thi \u00d7 H\u00e3y ch\u1edd hi\u1ec7u l\u1ec7nh \u0111\u1ec3 b\u1eaft \u0111\u1ea7u! B\u1eaft \u0111\u1ea7u l\u00e0m b\u00e0i Kh\u00f4ng c\u00f3 \u0111\u1ec1 thi n\u00e0o \u0111\u01b0\u1ee3c hi\u1ec3n th\u1ecb Hi\u1ec7n t\u1ea1i kh\u00f4ng c\u00f3 \u0111\u1ec1 thi n\u00e0o s\u1eb5n s\u00e0ng. Vui l\u00f2ng quay l\u1ea1i sau. K\u1ebeT QU\u1ea2 B\u00c0I THI \u0110\u00f3ng<\/p>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-3889","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/luyenthitokutei.com\/ja\/wp-json\/wp\/v2\/pages\/3889","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/luyenthitokutei.com\/ja\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/luyenthitokutei.com\/ja\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/luyenthitokutei.com\/ja\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/luyenthitokutei.com\/ja\/wp-json\/wp\/v2\/comments?post=3889"}],"version-history":[{"count":6,"href":"https:\/\/luyenthitokutei.com\/ja\/wp-json\/wp\/v2\/pages\/3889\/revisions"}],"predecessor-version":[{"id":5149,"href":"https:\/\/luyenthitokutei.com\/ja\/wp-json\/wp\/v2\/pages\/3889\/revisions\/5149"}],"wp:attachment":[{"href":"https:\/\/luyenthitokutei.com\/ja\/wp-json\/wp\/v2\/media?parent=3889"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}