🎮ArcadeLab

trending news quiz

by RocketGecko40
539 lines23.3 KB
▶ Play
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>trending news quiz</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: #f0f4f8;
            padding: 30px 20px;
            color: #1e2a3e;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
        }

        h1 {
            font-size: 2.2rem;
            text-align: center;
            color: #0f3b5c;
            margin-bottom: 8px;
        }

        .sub {
            text-align: center;
            color: #2c6e9e;
            margin-bottom: 30px;
            border-bottom: 2px solid #bdd4e7;
            padding-bottom: 15px;
        }

        /* card style for each section */
        .quiz-section {
            background: white;
            border-radius: 24px;
            box-shadow: 0 8px 20px rgba(0,0,0,0.05);
            margin-bottom: 40px;
            padding: 24px 28px;
            transition: 0.2s;
        }

        .section-title {
            font-size: 1.7rem;
            font-weight: 600;
            margin-bottom: 20px;
            padding-left: 12px;
            border-left: 6px solid #2c7da0;
            color: #1e4a6e;
        }

        .question-item {
            margin-bottom: 28px;
            background: #fefefe;
            padding: 12px 16px;
            border-radius: 20px;
            border: 1px solid #e2edf2;
        }

        .question-text {
            font-weight: 600;
            font-size: 1.05rem;
            margin-bottom: 12px;
            color: #0b3b4f;
        }

        .options {
            margin-left: 20px;
            margin-bottom: 12px;
        }

        .options label {
            display: block;
            margin: 6px 0;
            cursor: pointer;
        }

        button {
            background: #2c7da0;
            border: none;
            color: white;
            padding: 8px 18px;
            border-radius: 40px;
            font-size: 0.9rem;
            cursor: pointer;
            margin-top: 8px;
            margin-right: 12px;
            transition: 0.2s;
        }

        button:hover {
            background: #1f5e7e;
        }

        .feedback {
            margin-top: 10px;
            padding: 8px 12px;
            border-radius: 14px;
            font-size: 0.9rem;
        }

        .correct-fb {
            background: #dcfce7;
            color: #15803d;
            border-left: 4px solid #22c55e;
        }

        .wrong-fb {
            background: #ffe4e2;
            color: #b91c1c;
            border-left: 4px solid #ef4444;
        }

        .matching-row {
            display: flex;
            flex-wrap: wrap;
            gap: 20px;
            margin: 20px 0;
        }

        .matching-col {
            flex: 1;
            min-width: 200px;
            background: #f9fbfd;
            padding: 16px;
            border-radius: 20px;
        }

        .match-item {
            background: white;
            margin: 10px 0;
            padding: 10px 12px;
            border-radius: 40px;
            border: 1px solid #cbdde9;
            cursor: pointer;
            transition: 0.1s;
            text-align: center;
        }

        .match-item.selected {
            background: #2c7da0;
            color: white;
            border-color: #2c7da0;
        }

        .match-pair {
            background: #e6f2f9;
            margin: 8px 0;
            padding: 8px 12px;
            border-radius: 20px;
            font-weight: 500;
        }

        hr {
            margin: 20px 0;
            border: 0;
            height: 1px;
            background: #cbdde9;
        }

        .truefalse-buttons {
            display: flex;
            gap: 12px;
            margin: 8px 0;
        }

        .tf-btn {
            background: #e2e8f0;
            color: #1e293b;
            padding: 4px 20px;
        }

        .tf-btn.active-true {
            background: #15803d;
            color: white;
        }

        .tf-btn.active-false {
            background: #b91c1c;
            color: white;
        }

        input[type="text"], textarea {
            width: 100%;
            padding: 10px;
            border-radius: 16px;
            border: 1px solid #bdd4e7;
            font-family: inherit;
            margin-top: 8px;
        }

        .short-answer-area {
            margin: 12px 0;
        }

        .score-area {
            text-align: center;
            margin: 20px 0;
        }

        .big-score {
            font-size: 2rem;
            font-weight: bold;
            color: #1e6f5c;
        }

        footer {
            text-align: center;
            margin-top: 20px;
            color: #5b7f95;
        }
    </style>
</head>
<body>
<div class="container">
    <h1>📖 Sight Translation Monitor</h1>
    <div class="sub">Based on News Materials: GDP · Colonial Artifacts · Flight Cancellations · Lululemon</div>

    <!-- SECTION 1: Multiple Choice (4 questions) -->
    <div class="quiz-section">
        <div class="section-title">✅ A. Multiple Choice</div>
        <div id="mc-area"></div>
    </div>

    <!-- SECTION 2: Matching (Vocabulary & Meaning / Entity) -->
    <div class="quiz-section">
        <div class="section-title">🔗 B. Matching Exercise</div>
        <p style="margin-bottom: 12px;"><strong>Match the term on the left with the correct definition/description on the right.</strong> Click on one from left, then one from right.</p>
        <div id="matching-container"></div>
        <button id="check-matching">Check Matching</button>
        <div id="matching-feedback" class="feedback" style="margin-top: 12px;"></div>
    </div>

    <!-- SECTION 3: True or False (4 statements) -->
    <div class="quiz-section">
        <div class="section-title">📌 C. True or False</div>
        <div id="tf-area"></div>
        <button id="check-tf">Submit True/False</button>
        <div id="tf-feedback" class="feedback"></div>
    </div>

    <!-- SECTION 4: Fill in the blanks (key data/terms) -->
    <div class="quiz-section">
        <div class="section-title">✍️ D. Fill in the Blanks</div>
        <div id="fill-area"></div>
        <button id="check-fill">Check Fill-in</button>
        <div id="fill-feedback" class="feedback"></div>
    </div>

    <!-- SECTION 5: Short Answer (interpretation & synthesis) -->
    <div class="quiz-section">
        <div class="section-title">📝 E. Short Answer Questions</div>
        <div id="short-area"></div>
        <button id="check-short">Reveal Suggested Answers</button>
        <div id="short-feedback" class="feedback"></div>
    </div>

    <div class="score-area">
        <p>⭐ Overall performance monitor: track your understanding of key facts & vocabulary ⭐</p>
    </div>
    <footer>Designed for English major sight translation / interpretation training | Source-based assessment</footer>
</div>

<script>
    // ---------- MULTIPLE CHOICE DATA ----------
    const mcqs = [
        {
            text: "1. According to the GDP news, China's GDP grew ____ in Q1 2026 compared to the same period last year.",
            options: ["4.5%", "5%", "5.5%", "6%"],
            correct: 1,
            explanation: "The article states 'China's gross domestic product (GDP) grew 5 percent year on year in the first quarter of 2026.'"
        },
        {
            text: "2. What percentage of routes like Wuhan-Sydney saw cancellations in April according to the flight cancellation article?",
            options: ["More than 30%", "More than 50%", "Exactly 70%", "Less than 20%"],
            correct: 1,
            explanation: "It says: 'Wuhan-Sydney and Guangzhou-Darwin... cancellation rates... exceeding 50 percent in April.'"
        },
        {
            text: "3. Who wrote the 1861 letter about the sack of the Summer Palace, quoted by French lawmaker Jérémie Patrier-Leitus?",
            options: ["Napoleon", "Victor Hugo", "Charles Baudelaire", "Jean-Paul Sartre"],
            correct: 1,
            explanation: "The bill speech referenced Victor Hugo’s letter to Captain Butler."
        },
        {
            text: "4. What did Lululemon say about PFAS in its products?",
            options: ["It still uses PFAS widely", "It does not use PFAS and phased it out in fiscal 2023", "It will start using PFAS next year", "It refused to comment"],
            correct: 1,
            explanation: "Lululemon spokesperson: 'Lululemon does not use PFAS in its products ... phased out the substance in fiscal 2023.'"
        }
    ];

    // ---------- MATCHING DATA (Left items and right items)
    const leftMatch = [
        "Year-on-year (YoY)", "PFAS", "Athleisure", "Oceania", "Plunder (in colonial context)"
    ];
    const rightMatch = [
        "Refers to 'forever chemicals' linked to health risks", "A term for sports-inspired casual wear, like Lululemon", "Comparison with the same period last year", "Region that includes Australia and affected by flight cancellations", "Goods taken illegally during war/colonial looting"
    ];
    // correct pairs indices: left[0] -> right[2], left[1]->right[0], left[2]->right[1], left[3]->right[3], left[4]->right[4]
    const correctPairs = [2, 0, 1, 3, 4];

    // ---------- TRUE/FALSE DATA ----------
    const tfStatements = [
        { text: "France’s new bill automatically returns all colonial-era artifacts immediately without any parliamentary process.", answer: false, explanation: "The bill simplifies procedures but still requires legislative steps. It passed National Assembly and will be sent again." },
        { text: "The May Day flight cancellations were caused by escalating jet fuel prices due to Middle East tensions and a US blockade.", answer: true, explanation: "First paragraph: Surging jet fuel prices, driven by escalating Middle East tensions and a United States blockade on Iranian ports, triggered cancellations." },
        { text: "China’s 2026 GDP growth target is set exactly at 5% with no flexibility.", answer: false, explanation: "The target is 4.5 to 5 percent and will strive for better in practice." },
        { text: "The Texas investigation will examine Lululemon's testing protocols and supply chain practices.", answer: true, explanation: "The OAG will examine testing protocols, restricted substances list and supply chain practices." }
    ];

    // ---------- FILL IN BLANKS ----------
    const fillBlanks = [
        { text: "China's Q1 2026 GDP reached approximately ______ trillion yuan (about 4.87 trillion USD).", correct: "33.4", hint: "number from GDP passage" },
        { text: "The French bill targets objects acquired between ______ and 1972.", correct: "1815", hint: "year from RFI quote" },
        { text: "The flight cancellation data from ______ (platform name) showed Xi'an-Phuket flights canceled since April 1.", correct: "Hangban Guanjia", hint: "Flight-tracking platform mentioned" },
        { text: "PFAS are called 'forever chemicals' because they do not break down easily in ______.", correct: "nature", hint: "environment" }
    ];

    // ---------- SHORT ANSWER (open with sample answers)
    const shortQuestions = [
        { q: "What does the article suggest about the resilience and vitality of China’s economy in Q1 2026? Provide two indicators mentioned.", sample: "The NBS statement mentioned that 'production and supply growth accelerated, market demand continued to improve, employment was generally stable, market prices picked up moderately.' Resilience and vitality are highlighted: 'development showing greater resilience and vitality.'" },
        { q: "Explain why Victor Hugo’s quote was used in the French parliamentary debate regarding returning looted artifacts. How does it relate to modern accountability?", sample: "Victor Hugo condemned the destruction of the Summer Palace and predicted France would return the plunder. Lawmakers used it to justify the bill as an act of historical justice, linking moral responsibility with modern restitution laws." },
        { q: "What are the main reasons for the mass flight cancellations ahead of May Day, and which regions are most affected?", sample: "Reasons: Surging jet fuel prices due to Middle East tensions + US blockade on Iranian ports. Most affected: routes from China to Southeast Asia (Bangkok, Phuket) and Oceania routes (Sydney, Darwin)." }
    ];

    // ------------------- RENDER FUNCTIONS -------------------
    function renderMultipleChoice() {
        const container = document.getElementById("mc-area");
        let html = "";
        mcqs.forEach((mc, idx) => {
            html += `<div class="question-item" data-mc-idx="${idx}">
                        <div class="question-text">${mc.text}</div>
                        <div class="options">`;
            mc.options.forEach((opt, optIdx) => {
                html += `<label><input type="radio" name="mc_${idx}" value="${optIdx}"> ${opt}</label>`;
            });
            html += `</div><button class="check-mc-btn" data-idx="${idx}">Check Answer</button>
                    <div class="feedback" id="mc-fb-${idx}"></div></div>`;
        });
        container.innerHTML = html;

        document.querySelectorAll(".check-mc-btn").forEach(btn => {
            btn.addEventListener("click", (e) => {
                const idx = parseInt(btn.getAttribute("data-idx"));
                const radios = document.getElementsByName(`mc_${idx}`);
                let selected = null;
                for(let r of radios) if(r.checked) { selected = parseInt(r.value); break; }
                const fbDiv = document.getElementById(`mc-fb-${idx}`);
                if(selected === null) {
                    fbDiv.innerHTML = `<div class="feedback wrong-fb">Please select an answer.</div>`;
                } else if(selected === mcqs[idx].correct) {
                    fbDiv.innerHTML = `<div class="feedback correct-fb">✓ Correct! ${mcqs[idx].explanation}</div>`;
                } else {
                    fbDiv.innerHTML = `<div class="feedback wrong-fb">✗ Incorrect. ${mcqs[idx].explanation}</div>`;
                }
            });
        });
    }

    // matching state
    let selectedLeft = null;
    let matchStatus = new Array(leftMatch.length).fill(null); // stores index of right matched
    function renderMatching() {
        let html = `<div class="matching-row">
                        <div class="matching-col"><h4>Terms / Concepts</h4>`;
        leftMatch.forEach((item, i) => {
            let matchedText = (matchStatus[i] !== null) ? ` → matched: "${rightMatch[matchStatus[i]]}"` : "";
            html += `<div class="match-item" data-left-idx="${i}">${item} ${matchedText ? `<span style="font-size:0.75rem;">✔️</span>` : ''}</div>`;
        });
        html += `</div><div class="matching-col"><h4>Definitions / Descriptions</h4>`;
        rightMatch.forEach((item, i) => {
            let isUsed = matchStatus.includes(i);
            html += `<div class="match-item" data-right-idx="${i}" style="${isUsed ? 'opacity:0.6; background:#eef2f5;' : ''}">${item}</div>`;
        });
        html += `</div></div>`;
        document.getElementById("matching-container").innerHTML = html;

        // attach events
        document.querySelectorAll("[data-left-idx]").forEach(el => {
            el.addEventListener("click", () => {
                const idx = parseInt(el.getAttribute("data-left-idx"));
                if(matchStatus[idx] !== null) {
                    alert("This term is already matched. Reset matching if you want to change (use reset below).");
                    return;
                }
                selectedLeft = idx;
                document.querySelectorAll("[data-left-idx]").forEach(l => l.classList.remove("selected"));
                el.classList.add("selected");
            });
        });
        document.querySelectorAll("[data-right-idx]").forEach(el => {
            el.addEventListener("click", () => {
                if(selectedLeft === null) { alert("First click a term on the left."); return; }
                const rightIdx = parseInt(el.getAttribute("data-right-idx"));
                if(matchStatus.includes(rightIdx)) { alert("This definition is already matched to another term."); return; }
                matchStatus[selectedLeft] = rightIdx;
                selectedLeft = null;
                renderMatching();
            });
        });
    }

    document.getElementById("check-matching").addEventListener("click", () => {
        let allCorrect = true;
        for(let i=0; i<matchStatus.length; i++) {
            if(matchStatus[i] !== correctPairs[i]) allCorrect = false;
        }
        const fbDiv = document.getElementById("matching-feedback");
        if(allCorrect && matchStatus.every(v => v !== null)) {
            fbDiv.innerHTML = `<div class="feedback correct-fb">🎉 Perfect! All matches are correct.</div>`;
        } else {
            let correctCount = matchStatus.reduce((acc, val, idx) => acc + (val === correctPairs[idx] ? 1 : 0), 0);
            fbDiv.innerHTML = `<div class="feedback wrong-fb">You matched ${correctCount}/${leftMatch.length} correctly. Review: <br> 
            Year-on-year → comparison with same period last year <br>
            PFAS → forever chemicals <br>
            Athleisure → sports-inspired casual wear <br>
            Oceania → region includes Australia <br>
            Plunder → goods taken illegally in colonial looting</div>`;
        }
    });

    // True/False rendering
    let tfSelections = new Array(tfStatements.length).fill(null);
    function renderTrueFalse() {
        let html = "";
        tfStatements.forEach((st, idx) => {
            html += `<div class="question-item">
                        <div class="question-text">${idx+1}. ${st.text}</div>
                        <div class="truefalse-buttons">
                            <button class="tf-btn tf-true" data-tf-idx="${idx}" data-val="true">True</button>
                            <button class="tf-btn tf-false" data-tf-idx="${idx}" data-val="false">False</button>
                        </div>
                        <div id="tf-indicator-${idx}" class="feedback" style="min-height:30px;"></div>
                    </div>`;
        });
        document.getElementById("tf-area").innerHTML = html;
        document.querySelectorAll(".tf-true, .tf-false").forEach(btn => {
            btn.addEventListener("click", (e) => {
                const idx = parseInt(btn.getAttribute("data-tf-idx"));
                const val = btn.getAttribute("data-val") === "true";
                tfSelections[idx] = val;
                // highlight buttons
                const parent = btn.parentElement;
                parent.querySelectorAll(".tf-btn").forEach(b => b.classList.remove("active-true","active-false"));
                if(val) btn.classList.add("active-true");
                else btn.classList.add("active-false");
                document.getElementById(`tf-indicator-${idx}`).innerHTML = "";
            });
        });
    }
    document.getElementById("check-tf").addEventListener("click", () => {
        let score = 0;
        tfStatements.forEach((st, idx) => {
            const indicator = document.getElementById(`tf-indicator-${idx}`);
            if(tfSelections[idx] === null) {
                indicator.innerHTML = `<span class="wrong-fb">⚠️ Not answered.</span>`;
            } else if(tfSelections[idx] === st.answer) {
                score++;
                indicator.innerHTML = `<span class="correct-fb">✓ Correct. ${st.explanation}</span>`;
            } else {
                indicator.innerHTML = `<span class="wrong-fb">✗ Wrong. ${st.explanation}</span>`;
            }
        });
        const fbDiv = document.getElementById("tf-feedback");
        fbDiv.innerHTML = `<div class="feedback">You got ${score}/${tfStatements.length} correct.</div>`;
    });

    // Fill in blanks
    let fillAnswers = [];
    function renderFillBlanks() {
        let html = "";
        fillBlanks.forEach((item, idx) => {
            html += `<div class="question-item">
                        <div class="question-text">${idx+1}. ${item.text}</div>
                        <input type="text" id="fill-input-${idx}" placeholder="Your answer">
                        <div id="fill-fb-${idx}" class="feedback" style="margin-top:6px;"></div>
                    </div>`;
        });
        document.getElementById("fill-area").innerHTML = html;
    }
    document.getElementById("check-fill").addEventListener("click", () => {
        let correctCount = 0;
        fillBlanks.forEach((item, idx) => {
            const userAns = document.getElementById(`fill-input-${idx}`).value.trim().toLowerCase();
            const correctAns = item.correct.toLowerCase();
            const fbDiv = document.getElementById(`fill-fb-${idx}`);
            if(userAns === correctAns || (item.correct === "33.4" && userAns === "33.4") || (item.correct === "Hangban Guanjia" && userAns.includes("hangban"))) {
                fbDiv.innerHTML = `<span class="correct-fb">✓ Correct!</span>`;
                correctCount++;
            } else {
                fbDiv.innerHTML = `<span class="wrong-fb">✗ Incorrect. Correct answer: ${item.correct}. Hint: ${item.hint}</span>`;
            }
        });
        document.getElementById("fill-feedback").innerHTML = `<div class="feedback">Fill-in score: ${correctCount}/${fillBlanks.length}</div>`;
    });

    // Short answer
    function renderShort() {
        let html = "";
        shortQuestions.forEach((sq, idx) => {
            html += `<div class="question-item">
                        <div class="question-text">${idx+1}. ${sq.q}</div>
                        <textarea rows="2" placeholder="Your answer (interpretation)" id="short-${idx}"></textarea>
                        <div id="short-sample-${idx}" class="feedback" style="display:none; background:#f1f9fe;"></div>
                    </div>`;
        });
        document.getElementById("short-area").innerHTML = html;
    }
    document.getElementById("check-short").addEventListener("click", () => {
        shortQuestions.forEach((sq, idx) => {
            const sampleDiv = document.getElementById(`short-sample-${idx}`);
            sampleDiv.style.display = "block";
            sampleDiv.innerHTML = `<strong>Suggested key points:</strong><br> ${sq.sample}`;
            if(!sampleDiv.parentNode.querySelector(".feedback")) {
                document.getElementById(`short-${idx}`).insertAdjacentElement('afterend', sampleDiv);
            }
        });
        document.getElementById("short-feedback").innerHTML = `<div class="feedback correct-fb">✅ Compare your answers with the suggested points. Self-assess clarity & accuracy.</div>`;
    });

    function init() {
        renderMultipleChoice();
        renderMatching();
        renderTrueFalse();
        renderFillBlanks();
        renderShort();
    }
    init();
</script>
</body>
</html>

Game Source: trending news quiz

Creator: RocketGecko40

Libraries: none

Complexity: complex (539 lines, 23.3 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: trending-news-quiz-rocketgecko40" to link back to the original. Then publish at arcadelab.ai/publish.