![]() |
WEBSITE > https://teacherkhen.github.io/TeacherKhen-sLearningHubWebsite/ |
Give or Keep is an interactive classroom review game where students answer questions and decide whether to keep rewards or give them to the opposing team. It increases engagement, competition, and participation in any subject. |
📌 Part 1: How to Play
🎯 Objective: Earn the highest score by answering correctly and using strategy.
- Divide class into Team 1 and Team 2
- Select a letter from the game grid (A–Z)
- Answer the question shown
- Choose KEEP IT or GIVE IT AWAY
🤲 KEEP IT
Rewards or penalties affect your own team.
🎁 GIVE IT AWAY
Rewards or penalties affect the opposing team.
💥 Possible Outcomes
- +5 to +50 points
- -5 to -30 points
- Swap scores
- Lose all points
❌ Wrong answers trigger a Mystery Box that gives bonus points to the opposing team.
Note: Manually lick the X button above to reveal the mystery box.
⚙️ Setup Guide (Teacher Controls)
You can fully customize the game using the built-in Setup Panel.
- Edit questions for any subject or grade
- Switch between Multiple Choice and Identification mode
- Paste images using Ctrl + V
- Assign rewards per question
- Save everything in browser storage
💾 JSON Backup System (Important)
The JSON file allows you to safely store and transfer your game data.
- Move game to another device
- Share with other teachers
- Backup your question sets
- Create multiple versions for different lessons
👉 Think of it as your portable classroom game storage system.
📤 Export & Import Feature
- Export: Download your game data as a file
- Import: Upload saved game data anytime
This is useful for teachers using multiple devices or sharing games.
🤖 Part 2: AI Question Generator
You can use AI tools to quickly generate classroom questions.
Create a complete, single-file HTML5 classroom game called "Give or Keep - Classroom Edition" utilizing responsive design, modern arcade/cartoon themes, and local state management. The game must run beautifully in a desktop browser or on an interactive whiteboard.
Incorporate the following specific technical modules and layout requirements into a single code output:
1. AUDIO SYSTEM & LIBRARIES
- Embed standard HTML5 <audio> tags for game feedback with the following local file targets:
* 'background music.mp3' (looped continuously, lower volume default)
* 'click.wav' (for generic interface interactions)
* 'add.wav' (for scoring additions or correct multi-choice items)
* 'minus.wav' (for penalty reveals or incorrect locks)
* 'swap points.wav' (for score rotation events)
* 'lose all points.wav' & 'bomb.mp3' (played together at maximum volume)
* 'reveal.wav' (for generic modal popup animations)
* 'winner.mp3' (played at maximum volume upon victory)
- Link Google Web Fonts to style specific typography: 'DynaPuff' for cartoonish headers, 'Press Start 2P' for retro/arcade point values, and 'Comic Neue' for clean text/problem components.
2. STATE-BASED ROUTING & INTERFACE SCREENS
- Use a single-page engine structure driven by dynamic CSS visibility classes (.screen { display:none; } .screen.active { display:flex; }).
- Include 7 structured interfaces: Welcome Title Screen, Rules Board, Main A-Z Selection Board, Question View Dashboard, Reveal Outcome View, Setup Configurations Dashboard, and Final Winner Podium.
- Maintain a global dynamic scoreboard element visible during active gameplay stages that tracks Team 1 and Team 2 points independently, featuring a visual indicator highlighting whichever team currently has the active turn.
3. INTERACTIVE MAIN GRID & PROBLEM MODULES
- Create a 7-column layout representing the 26 letters of the English alphabet (A to Z). Map these letters dynamically to a shuffled array of 26 index spaces tracking custom data objects.
- Each interactive box must turn permanently into a disabled button state once clicked. Tapping an active letter loads the Question View Dashboard, which must seamlessly handle two game modes:
* MULTIPLE CHOICE MODE: Arrange up to 4 answers in a responsive 2x2 block. Selecting an item unlocks a prominent "LOCK ANSWER" button. Once clicked, use CSS animations (.glow-correct-ans) to highlight the correct answer in green, highlight wrong selections in red, and play corresponding SFX cues.
* IDENTIFICATION MODE: Render text blocks along with a simple "REVEAL ANSWER" button that displays the text answer inline upon interaction.
4. RECOVERY LOOP (TEACHER OVERRIDE SYSTEM)
- Place a distinct '❌' icon in the upper navigation panel of the question view.
- If a team fails to provide a correct answer, the teacher can tap this override to display a full-screen "Mystery Box Overlay" layer hiding the background card.
- Show a central clickable box animation container targeting 'mystery box.gif'. When clicked, reveal a randomized point award (+5 to +20 points) that is immediately added to the *opposing* team's score to keep the game engaging and fair.
5. MYSTERY REWARD SELECTION MATRIX
- Support 12 discrete hidden outcome mechanics assigned to the 26 letter slots: "+5", "+10", "+20", "+30", "+50", "-5", "-10", "-25", "-20", "-30", "swap score", and "lose all points".
- Include active decision buttons ("KEEP IT" or "GIVE IT AWAY") that remain disabled until the answer stage is fully locked or revealed.
* "KEEP IT" applies the hidden outcome directly to the current team's scoreboard.
* "GIVE IT AWAY" transfers the positive score boost or negative penalty straight to the rival team.
6. OUTCOME REVEAL & PODIUM SCREEN BALANCING
- REVEAL SCREEN LAYOUT (#screenOutcome): Frame the results neatly inside a side-by-side flexbox container card. The left side must house the mystery animation graphics ('plus.gif', 'minus.gif', 'swap.gif', 'lose points.gif', or 'bomb.gif'). The right side must frame the text outcomes and point changes, perfectly horizontally and vertically centered.
- FINAL PODIUM SCREEN LAYOUT (#screenPodium): When the 26 alphabet items are completely exhausted, halt the background music loop and fire 'winner.mp3' along with a canvas confetti loop. The results card box must center perfectly in the middle of the viewport screen, showcasing 'winner.gif', announcing the winning team, and ensuring that the "PLAY AGAIN" button remains fully visible inside the central card boundaries.
7. DATA CONFIGURATION & SYNCHRONIZATION ENGINE
- Design a scrollable Setup Panel (`#screenSettings`) containing a form matrix loop for all 26 item spaces. Each space must allow editing of the question text, switching types (Multiple Choice vs. Identification), choosing the hidden reward outcome from a dropdown, and adjusting target answers.
- Implement a clipboard paste interceptor (`onpaste`). When an image is copied from anywhere and pasted into a slot's dropzone area, read the binary file stream and translate it instantly into a lightweight Base64 data-URI string stored inside the active application state.
- Include data backup utility controls: An "Export" feature that packages the 26 configurations into a download container named `give_or_keep_game_backup.json`, and an "Import" handler that accepts file uploads, parses the data securely, saves it into local storage, and dynamically redraws the interactive interface.
This helps teachers create complete lesson games in minutes.
💻 HTML CODES Here
IMPORTANT: Paste your full game code below in Blogger HTML view.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Give or Keep - Final Version</title> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=DynaPuff:wght@400;700&family=Press+Start+2P&family=Comic+Neue:wght@400;700&display=swap" rel="stylesheet"> <style> :root { --team-1-color: #2e86de; --team-2-color: #ee5253; --arcade-font: 'Press Start 2P', cursive; --cute-font: 'DynaPuff', cursive; --body-font: 'Comic Neue', cursive; } * { box-sizing: border-box; font-family: var(--body-font); } html, body { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background-image: url('background image.png'); background-size: cover; background-position: center; background-repeat: no-repeat; background-color: #000; } .game-wrapper { position: relative; width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: space-between; align-items: center; padding: 20px; } .screen { display: none; width: 100%; height: 100%; flex-direction: column; justify-content: center; align-items: center; position: relative; z-index: 2; text-align: center; } .screen.active { display: flex; } #screenTitle.screen.active { backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); background: rgba(0, 0, 0, 0.2); } h2 { font-family: var(--cute-font); font-size: 3rem; color: #ffffff; text-shadow: 4px 4px 0px #000000, -2px -2px 0px #000000, 2px -2px 0px #000000, -2px 2px 0px #000000; margin: 10px 0; } .arcade-text { font-family: var(--arcade-font); font-size: 1.5rem; } .btn { background: linear-gradient(135deg, #FF6B6B, #EE5253); color: white; border: 4px solid #fff; padding: 14px 35px; font-size: 1.4rem; font-weight: bold; border-radius: 50px; cursor: pointer; box-shadow: 0 8px 0 #b33939, 0 10px 20px rgba(0,0,0,0.5); transition: all 0.1s ease; margin: 12px; display: inline-block; text-decoration: none; text-transform: uppercase; text-shadow: 2px 2px 0px #000; } .btn:active { transform: translateY(6px); box-shadow: 0 2px 0 #b33939, 0 5px 10px rgba(0,0,0,0.4); } .btn-blue { background: linear-gradient(135deg, #54a0ff, #2e86de); box-shadow: 0 8px 0 #227093; } .btn-orange { background: linear-gradient(135deg, #ff9f43, #ee5253); box-shadow: 0 8px 0 #cd6133; } .btn-green { background: linear-gradient(135deg, #2ecc71, #27ae60); box-shadow: 0 8px 0 #1e7e43; } /* Play and Setup buttons much larger */ .title-action-panel .btn-giant { padding: 22px 60px; font-size: 2.2rem; border-width: 6px; box-shadow: 0 12px 0 #b33939, 0 15px 30px rgba(0,0,0,0.6); } .title-action-panel .btn-giant.btn-blue { box-shadow: 0 12px 0 #227093; } .title-action-panel .btn-giant:active { transform: translateY(8px); box-shadow: 0 4px 0 #b33939, 0 6px 12px rgba(0,0,0,0.4); } .title-action-panel .btn-giant.btn-blue:active { box-shadow: 0 4px 0 #227093; } /* Hub button significantly smaller */ .title-action-panel .btn-mini { padding: 8px 20px; font-size: 1.0rem; border-width: 3px; box-shadow: 0 5px 0 #cd6133, 0 6px 12px rgba(0,0,0,0.4); align-self: center; } .title-action-panel .btn-mini:active { transform: translateY(3px); box-shadow: 0 2px 0 #cd6133, 0 4px 6px rgba(0,0,0,0.3); } .title-image-box { width: 100%; height: 80%; display: flex; justify-content: center; align-items: center; margin-bottom: 5px; } .title-image-box img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 20px; filter: drop-shadow(0 12px 24px rgba(0,0,0,0.7)); } .title-action-panel { display: flex; gap: 15px; align-items: center; background: none !important; box-shadow: none !important; border: none !important; } .grid-az { display: grid; grid-template-columns: repeat(7, 1fr); gap: 15px; width: 95%; height: 65vh; } .letter-box { background: linear-gradient(135deg, #ffffff, #eccc68); border: 5px solid #2f3542; border-radius: 20px; display: flex; justify-content: center; align-items: center; font-size: 3.5rem; font-family: var(--cute-font); color: #2f3542; cursor: pointer; box-shadow: 0 10px 0 #2f3542; transition: 0.1s; text-shadow: 2px 2px 0px rgba(255,255,255,0.5); } .letter-box:not(.disabled):hover { background: linear-gradient(135deg, #fffae6, #ff7f50); color: #fff; text-shadow: 2px 2px 0px #000; } .letter-box.disabled { background: #747d8c !important; color: #a4b0be !important; opacity: 0.5; box-shadow: none !important; cursor: not-allowed; transform: scale(0.92); text-shadow: none; } .scoreboard { display: flex; justify-content: space-around; width: 95%; background: rgba(0, 0, 0, 0.9); padding: 15px; border-radius: 25px; border: 4px solid #fff; box-shadow: 0 8px 16px rgba(0,0,0,0.6); margin-bottom: 10px; } .team-box { font-family: var(--arcade-font); font-size: 1.6rem; padding: 5px 25px; color: #fff; text-shadow: 3px 3px 0px #000; transition: all 0.3s ease; } .team-box span { font-size: 2.2rem; margin-left: 5px; } .team-a { color: #54a0ff; } .team-b { color: #ff6b6b; } .team-a.active-team-turn-indicator { border-bottom: 5px solid #ff9f43; transform: scale(1.05); text-shadow: 0 0 10px #54a0ff, 0 0 20px #54a0ff, 3px 3px 0px #000; } .team-b.active-team-turn-indicator { border-bottom: 5px solid #ff9f43; transform: scale(1.05); text-shadow: 0 0 10px #ff6b6b, 0 0 20px #ff6b6b, 3px 3px 0px #000; } .turn-container { display: flex; align-items: center; justify-content: center; gap: 15px; margin-bottom: 15px; background: rgba(0, 0, 0, 0.7); padding: 10px 30px; border-radius: 40px; border: 2px solid rgba(255,255,255,0.3); } .turn-dot { height: 25px; width: 25px; border-radius: 50%; display: inline-block; box-shadow: 0 0 10px rgba(0,0,0,0.8); border: 2px solid #fff; } .content-card { background: rgba(255, 255, 255, 0.98); width: 95%; height: 78vh; border-radius: 35px; border: 8px solid var(--team-1-color); padding: 15px; display: flex; flex-direction: column; justify-content: space-between; align-items: center; box-shadow: 0 25px 50px rgba(0,0,0,0.5); position: relative; } .q-scroll-body { width: 100%; flex: 1; overflow-y: auto; display: flex; flex-direction: column; align-items: center; justify-content: center; /* Adjusted to keep elements beautifully centered vertically */ padding: 10px; gap: 15px; } .question-text { font-size: 2.3rem; color: #1e272e; font-weight: bold; margin: 5px; word-break: break-word; transition: font-size 0.2s ease; } .options-container { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; width: 90%; } .options-container .btn { text-transform: none !important; margin: 5px; padding: 12px 20px; font-size: 1.2rem; transition: all 0.2s ease; } /* Added: Dynamic adjustment handling when NO images are loaded */ .q-scroll-body.no-image-layout { gap: 30px; } .q-scroll-body.no-image-layout .question-text { font-size: 3.4rem; /* Scaled up text to look grand and proportioned */ margin-bottom: 15px; } .q-scroll-body.no-image-layout .options-container { width: 95%; gap: 20px; } .q-scroll-body.no-image-layout .options-container .btn { padding: 20px 30px; /* Enhanced options sizes */ font-size: 1.6rem; } .q-scroll-body.no-image-layout #idAns { font-size: 3.8rem !important; /* Scaled identification answer */ } .settings-panel { background: #fff; border-radius: 25px; padding: 30px; width: 95%; height: 85vh; overflow-y: auto; color: #333; border: 5px solid #2f3542; } .settings-panel h2, .settings-panel h3 { text-shadow: none; color: #2f3542; } .q-row { border: 3px solid #ced6e0; padding: 20px; margin-bottom: 20px; border-radius: 16px; border-left: 10px solid var(--team-1-color); background: #f1f2f6; } .correct-radio { transform: scale(1.6); cursor: pointer; margin-right: 8px; } .opt-input-row { display: flex; align-items: center; gap: 10px; width: 100%; margin-top: 5px; } input[type="text"], select { padding: 10px; font-size: 1.1rem; border-radius: 8px; border: 2px solid #ced6e0; font-weight: bold; } .volume-control-box { display: flex; flex-direction: column; gap: 10px; margin-top: 15px; background: #fff; padding: 15px; border-radius: 10px; border: 1px solid #ced6e0; } .volume-row { display: flex; align-items: center; gap: 15px; font-weight: bold; } .volume-row input[type="range"] { flex: 1; } .q-nav-header { width: 100%; display: flex; justify-content: space-between; align-items: center; padding: 0 10px; margin-bottom: 5px; flex-shrink: 0; } .nav-icon-btn { background: none; border: none; font-size: 2.2rem; cursor: pointer; transition: transform 0.1s; } .nav-icon-btn:hover { transform: scale(1.15); } .mystery-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.85); border-radius: 27px; z-index: 10; display: none; flex-direction: column; justify-content: center; align-items: center; } .gif-box-wrapper { height: 50vh; width: 100%; max-width: 350px; cursor: pointer; margin-bottom: 25px; animation: floatAnim 1.8s ease-in-out infinite alternate; transition: transform 0.2s; display: flex; justify-content: center; align-items: center; } .gif-box-wrapper:hover { transform: scale(1.08); } .gif-box-wrapper img { width: 100%; height: 100%; object-fit: contain; } @keyframes floatAnim { 0% { transform: translateY(0px); } 100% { transform: translateY(-15px); } } .box-reward-reveal { font-family: var(--cute-font); font-size: 5.5rem; color: #2ecc71; text-shadow: 4px 4px 0 #000, 0 0 30px #2ecc71; display: none; animation: bounceIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); } @keyframes bounceIn { 0% { transform: scale(0.3); opacity: 0; } 50% { transform: scale(1.1); } 100% { transform: scale(1); opacity: 1; } } </style> </head> <body> <div class="game-wrapper"> <audio id="bgMusic" loop src="background music.mp3"></audio> <audio id="sndClick" src="click.wav"></audio> <audio id="sndAdd" src="add.wav"></audio> <audio id="sndMinus" src="minus.wav"></audio> <audio id="sndSwap" src="swap points.wav"></audio> <audio id="sndLose" src="lose all points.wav"></audio> <audio id="sndReveal" src="reveal.wav"></audio> <div id="globalScoreboard" class="scoreboard" style="display:none;"> <div id="boxTeamA" class="team-box team-a">TEAM 1: <span id="scoreA">0</span></div> <div id="boxTeamB" class="team-box team-b">TEAM 2: <span id="scoreB">0</span></div> </div> <div id="screenTitle" class="screen active"> <div class="title-image-box"> <img src="titlepage.gif" alt="Game Logo Graphic"> </div> <div class="title-action-panel"> <button class="btn btn-giant" onclick="changeScreen('screenRules')">PLAY</button> <a href="https://teacherkhenlearninghub.blogspot.com/" target="_blank" class="btn btn-orange btn-mini">HUB</a> <button class="btn btn-blue btn-giant" onclick="changeScreen('screenSettings')">SETUP</button> </div> </div> <div id="screenRules" class="screen"> <div style="background:rgba(255,255,255,0.98); padding:40px; border-radius:30px; border: 6px solid #ff9f43; max-width:850px; color:#1e272e; box-shadow: 0 20px 40px rgba(0,0,0,0.5);"> <h2 style="color:#2f3542; text-shadow: none; margin-top:0;">📜 How to Play!</h2> <ul style="text-align:left; font-size:1.8rem; font-weight:bold; line-height: 1.6; padding-left: 25px;"> <li>Work with your team to solve the letter box challenge!</li> <li>Choose <strong>KEEP IT</strong> to lock the surprise rewards for your side.</li> <li>Choose <strong>GIVE IT AWAY</strong> to throw the mystery package at your rivals!</li> <li>If your team gets an answer wrong, the <strong>Mystery Box</strong> appears and gives additional points to the other team!</li> <li>Keep scores up! Scores can never plunge lower than zero points!</li> </ul> <button class="btn btn-green" onclick="startGame()">OPEN GAME GRID 🎮</button> </div> </div> <div id="screenMain" class="screen"> <div class="turn-container"> <span id="turnDot" class="turn-dot"></span> <h2 id="turnIndicator" style="margin:0;">Team 1's Turn</h2> </div> <div id="azGrid" class="grid-az"></div> </div> <div id="screenQuestion" class="screen"> <div class="content-card" id="qCardShell"> <div class="q-nav-header"> <button class="nav-icon-btn" onclick="goToGridScreen()" title="Go back to Letters page">🏠</button> <button class="nav-icon-btn" style="color:#ee5253; font-weight:bold;" onclick="triggerWrongAnswerSequence()" title="Mark Answer Wrong">❌</button> </div> <div id="qScrollArea" class="q-scroll-body"> <div id="qText" class="question-text"></div> <img id="qImg" src="" style="max-height:22vh; object-fit:contain; border-radius:15px; border:4px solid #2f3542; display:none;"> <div id="qOptions" class="options-container"></div> <div id="qIdArea" style="display:none; width:100%;"> <button id="btnRevealId" class="btn btn-orange" onclick="revealIdAnswer()">REVEAL ANSWER</button> <p id="idAns" style="font-size:2.5rem; color:#2ecc71; font-weight:bold; text-shadow: 2px 2px 0px #000; margin: 10px 0 0 0; text-transform: none;"></p> </div> </div> <div style="border-top:5px dashed #ced6e0; padding-top:10px; width:100%; flex-shrink:0;"> <button class="btn btn-green" onclick="handleDecision('keep')">🤲 KEEP IT</button> <button class="btn btn-orange" onclick="handleDecision('give')">🎁 GIVE IT AWAY</button> </div> <div id="mysteryOverlay" class="mystery-overlay"> <h2 id="mysteryTitle" style="font-size:3.5rem; margin-bottom:15px;">Mystery Box 🎁</h2> <div id="gifBoxWrapper" class="gif-box-wrapper" onclick="revealMysteryGift()"> <img src="mystery box.gif" alt="Mystery Gift Box Graphic Target"> </div> <div id="mysteryRewardDisplay" class="box-reward-reveal"></div> <button id="btnMysteryClose" class="btn btn-blue" style="display:none; margin-top:20px;" onclick="closeMysterySequence()">CONTINUE ➡️</button> </div> </div> </div> <div id="screenOutcome" class="screen"> <div class="content-card" style="height:60vh; justify-content:center; border-color:#ff9f43;"> <h2 style="color:#2f3542; text-shadow:none; font-size:2.8rem; margin:0;">Mystery Box Content...</h2> <div id="outcomeText" style="font-size:5rem; color:#ee5253; font-weight:bold; margin:30px 0; text-shadow: 3px 3px 0px #000;"></div> <button class="btn btn-blue" onclick="nextTurn()">NEXT TURN ➡️</button> </div> </div> <div id="screenSettings" class="screen"> <div class="settings-panel"> <h2>⚙️ Dashboard Configuration Terminal</h2> <div style="background:#f1f2f6; padding:20px; border-radius:15px; margin-bottom:20px; border:2px solid #ced6e0;"> <h3>📂 Cross-Device Sync Engine & Audio</h3> <div style="margin-bottom: 15px; display: flex; gap: 10px; flex-wrap: wrap;"> <button class="btn btn-small btn-green" style="padding:8px 20px; font-size:1rem;" onclick="exportData()">📥 Export Question Matrix (.json)</button> <button class="btn btn-small btn-blue" style="padding:8px 20px; font-size:1rem;" onclick="document.getElementById('fileIn').click()">📤 Load File Backups</button> <input type="file" id="fileIn" style="display:none;" accept=".json" onchange="importData(event)"> <button id="btnMusicToggle" class="btn btn-small btn-orange" style="padding:8px 20px; font-size:1rem;" onclick="toggleMusic()">🎵 MUSIC: ON</button> </div> <div class="volume-control-box"> <div class="volume-row"> <span>🎵 Music Volume:</span> <input type="range" id="volMusic" min="0" max="1" step="0.1" value="0.3" oninput="updateVolumes()"> </div> <div class="volume-row"> <span>🔊 Sound Effects Volume (Louder by Default):</span> <input type="range" id="volSFX" min="0" max="1" step="0.1" value="0.9" oninput="updateVolumes()"> </div> </div> </div> <h3>Edit Content Loops (26 Slots)</h3> <div id="setupList"></div> <div style="text-align:center; padding:20px 0;"> <button class="btn btn-green" onclick="saveData()">💾 SAVE SETTINGS</button> <button class="btn btn-blue" onclick="changeScreen('screenTitle')">CLOSE PANEL</button> </div> </div> </div> </div> <script> let scores = { A: 0, B: 0 }; let currentTeam = 'A'; let questions = []; let mapping = []; let used = new Array(26).fill(false); let activeIdx = null; let isMusicPlaying = true; let isAnswerLocked = false; let pendingWrongPoints = 0; const outcomes = ["+5", "+10", "+20", "+30", "+50", "-5", "-10", "-25", "-20", "-30", "swap score", "lose all points"]; window.onload = () => { loadData(); buildSetup(); shuffle(); updateVolumes(); }; function changeScreen(id) { document.querySelectorAll('.screen').forEach(s => s.classList.remove('active')); document.getElementById(id).classList.add('active'); document.getElementById('globalScoreboard').style.display = (['screenMain', 'screenQuestion', 'screenOutcome'].includes(id)) ? 'flex' : 'none'; } function loadData() { let data = localStorage.getItem('give_keep_v3'); if (data) { questions = JSON.parse(data); } else { questions = []; for (let i = 0; i < 26; i++) { questions.push({ text: `What is the target challenge query block #${i+1}?`, type: 'id', options: ['Choice Option A', 'Choice Option B', 'Choice Option C', 'Choice Option D'], correct: 0, answer: 'Answer Description Key', image: '', outcome: outcomes[i % outcomes.length] }); } } } function buildSetup() { const list = document.getElementById('setupList'); list.innerHTML = ''; questions.forEach((q, i) => { let optsHTML = [0,1,2,3].map(oi => ` <div class="opt-input-row"> <input type="radio" name="correct_radio_${i}" class="correct-radio" ${q.correct == oi ? 'checked' : ''} value="${oi}" id="radio_${i}_${oi}"> <input type="text" id="q${i}_o${oi}" value="${q.options[oi] || ''}" placeholder="Option Value ${oi+1}" style="flex:1;"> </div> `).join(''); list.insertAdjacentHTML('beforeend', ` <div class="q-row"> <strong>Matrix Letter Unit Slot Assignment #${i+1}</strong> <input type="text" id="qText_${i}" value="${q.text}" style="width:100%; margin: 8px 0;"> <div style="display:flex; gap:15px; margin-bottom:8px;"> <select id="qType_${i}" onchange="toggleType(${i}, this.value)"> <option value="id" ${q.type=='id'?'selected':''}>Identification Mode</option> <option value="multiple" ${q.type=='multiple'?'selected':''}>Multiple Choice Mode</option> </select> <select id="qOut_${i}">${outcomes.map(o => `<option value="${o}" ${q.outcome==o?'selected':''}>${o}</option>`).join('')}</select> </div> <div id="paste_${i}" style="border:3px dashed #747d8c; padding:15px; font-weight:bold; text-align:center; background:#fff; margin:8px 0; color:#57606f;" onpaste="handlePaste(event, ${i})"> ${q.image ? `<img src="${q.image}" style="height:65px; border-radius:5px;">` : 'Click Content Block & Tap Ctrl+V to Append Picture Asset'} </div> <div id="mc_${i}" style="display:${q.type=='multiple'?'block':'none'}; background:#fff; padding:10px; border-radius:8px; border:1px solid #ced6e0;"> <span style="font-size:0.9rem; font-weight:bold; color:#747d8c;">Select the dot marking the valid correct choice option answer:</span> ${optsHTML} </div> <input type="text" id="qAns_${i}" value="${q.answer}" style="display:${q.type=='id'?'block':'none'}; width:100%;" placeholder="Valid Answer Details Key"> </div> `); }); } function toggleType(i, type) { document.getElementById(`mc_${i}`).style.display = type == 'multiple' ? 'block' : 'none'; document.getElementById(`qAns_${i}`).style.display = type == 'id' ? 'block' : 'none'; } function handlePaste(e, i) { const items = (e.clipboardData || e.originalEvent.clipboardData).items; for (let item of items) { if (item.type.indexOf("image") !== -1) { const reader = new FileReader(); reader.onload = (event) => { questions[i].image = event.target.result; buildSetup(); }; reader.readAsDataURL(item.getAsFile()); } } } function toggleMusic() { const music = document.getElementById('bgMusic'); const btn = document.getElementById('btnMusicToggle'); if (isMusicPlaying) { music.pause(); btn.innerText = "🎵 MUSIC: OFF"; isMusicPlaying = false; } else { music.play().catch(()=>{}); btn.innerText = "🎵 MUSIC: ON"; isMusicPlaying = true; } } function updateVolumes() { const musicVol = document.getElementById('volMusic').value; const sfxVol = document.getElementById('volSFX').value; document.getElementById('bgMusic').volume = musicVol; document.getElementById('sndClick').volume = sfxVol; document.getElementById('sndAdd').volume = sfxVol; document.getElementById('sndMinus').volume = sfxVol; document.getElementById('sndSwap').volume = sfxVol; document.getElementById('sndLose').volume = sfxVol; document.getElementById('sndReveal').volume = sfxVol; } function saveData() { questions.forEach((q, i) => { q.text = document.getElementById(`qText_${i}`).value; q.type = document.getElementById(`qType_${i}`).value; q.outcome = document.getElementById(`qOut_${i}`).value; q.answer = document.getElementById(`qAns_${i}`).value; q.options = [0,1,2,3].map(oi => document.getElementById(`q${i}_o${oi}`).value); let radios = document.getElementsByName(`correct_radio_${i}`); for(let r = 0; r < radios.length; r++) { if(radios[r].checked) { q.correct = parseInt(radios[r].value); break; } } }); localStorage.setItem('give_keep_v3', JSON.stringify(questions)); alert("Configurations saved safely inside internal storage memory!"); changeScreen('screenTitle'); } function exportData() { const str = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(questions)); const dl = document.createElement('a'); dl.setAttribute("href", str); dl.setAttribute("download", "give_or_keep_game_backup.json"); document.body.appendChild(dl); dl.click(); dl.remove(); } function importData(e) { const fr = new FileReader(); fr.onload = (event) => { try { const parsed = JSON.parse(event.target.result); if (Array.isArray(parsed) && parsed.length === 26) { questions = parsed; localStorage.setItem('give_keep_v3', JSON.stringify(questions)); buildSetup(); alert("External Database Pack Connected Successfully!"); } else { alert("Data structure package mismatch."); } } catch(err) { alert("Failed to parse target package framework cleanly."); } }; fr.readAsText(e.target.files[0]); } function shuffle() { mapping = Array.from({length: 26}, (_, i) => i).sort(() => Math.random() - 0.5); buildGrid(); } function buildGrid() { const grid = document.getElementById('azGrid'); grid.innerHTML = ''; "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split('').forEach((l, i) => { let qi = mapping[i]; let div = document.createElement('div'); div.className = `letter-box ${used[qi] ? 'disabled' : ''}`; div.innerText = l; if (!used[qi]) { div.onclick = () => launch(l, qi); } grid.appendChild(div); }); } function launch(l, qi) { playSound('sndClick'); activeIdx = qi; let q = questions[qi]; isAnswerLocked = false; document.getElementById('mysteryOverlay').style.display = 'none'; document.getElementById('gifBoxWrapper').style.display = 'flex'; document.getElementById('mysteryRewardDisplay').style.display = 'none'; document.getElementById('btnMysteryClose').style.display = 'none'; document.getElementById('mysteryTitle').style.display = 'block'; let shell = document.getElementById('qCardShell'); shell.style.borderColor = (currentTeam === 'A') ? 'var(--team-1-color)' : 'var(--team-2-color)'; document.getElementById('qText').innerText = q.text; // Layout Adjustments triggered dynamically depending on Image Presence let scrollArea = document.getElementById('qScrollArea'); let img = document.getElementById('qImg'); if(q.image) { img.src = q.image; img.style.display = 'block'; scrollArea.classList.remove('no-image-layout'); } else { img.style.display = 'none'; scrollArea.classList.add('no-image-layout'); } let opts = document.getElementById('qOptions'); let idArea = document.getElementById('qIdArea'); opts.innerHTML = ''; document.getElementById('idAns').innerText = ''; if (q.type == 'multiple') { idArea.style.display = 'block'; document.getElementById('btnRevealId').innerText = "LOCK ANSWER"; opts.style.display = 'grid'; q.options.forEach((o, oi) => { if (o.trim()) { let b = document.createElement('button'); b.className = 'btn'; b.style.color = '#fff'; b.innerText = o; b.onclick = () => { if (isAnswerLocked) return; playSound('sndClick'); Array.from(opts.children).forEach(child => { child.style.background = ''; child.style.boxShadow = ''; }); b.style.background = '#ff9f43'; b.style.boxShadow = '0 5px 0 #cd6133'; b.dataset.selectedIdx = oi; }; opts.appendChild(b); } }); } else { opts.style.display = 'none'; idArea.style.display = 'block'; document.getElementById('btnRevealId').innerText = "REVEAL ANSWER"; document.getElementById('idAns').innerText = q.answer; document.getElementById('idAns').style.display = 'none'; } changeScreen('screenQuestion'); } function revealIdAnswer() { playSound('sndClick'); let q = questions[activeIdx]; if (q.type == 'multiple') { if (isAnswerLocked) return; isAnswerLocked = true; let opts = document.getElementById('qOptions'); let selectedBtn = Array.from(opts.children).find(btn => btn.dataset.selectedIdx !== undefined); Array.from(opts.children).forEach((btn, oi) => { if (oi == q.correct) { btn.style.background = '#2ecc71'; btn.style.boxShadow = '0 5px 0 #1e7e43'; } else if (btn === selectedBtn) { btn.style.background = '#ee5253'; btn.style.boxShadow = '0 5px 0 #b33939'; } }); } else { document.getElementById('idAns').style.display = 'block'; } } function goToGridScreen() { playSound('sndClick'); changeScreen('screenMain'); } function triggerWrongAnswerSequence() { pendingWrongPoints = Math.floor(Math.random() * 46) + 5; document.getElementById('mysteryOverlay').style.display = 'flex'; playSound('sndReveal'); } function revealMysteryGift() { playSound('sndReveal'); let opponentTeam = (currentTeam === 'A') ? 'B' : 'A'; scores[opponentTeam] += pendingWrongPoints; document.getElementById('gifBoxWrapper').style.display = 'none'; document.getElementById('mysteryTitle').style.display = 'none'; let rewardDisplay = document.getElementById('mysteryRewardDisplay'); rewardDisplay.innerText = `+${pendingWrongPoints} Points to Team ${opponentTeam === 'A' ? '1' : '2'}!`; rewardDisplay.style.display = 'block'; document.getElementById('btnMysteryClose').style.display = 'inline-block'; updateScores(); } function closeMysterySequence() { used[activeIdx] = true; nextTurn(); } function handleDecision(choice) { let q = questions[activeIdx]; used[activeIdx] = true; let target = (choice == 'keep') ? currentTeam : (currentTeam == 'A' ? 'B' : 'A'); let val = q.outcome; let chosenSound = 'sndAdd'; if (val.includes('+')) { scores[target] += parseInt(val.replace('+', '')); chosenSound = 'sndAdd'; } else if (val.includes('-')) { scores[target] = Math.max(0, scores[target] - parseInt(val.replace('-', ''))); chosenSound = 'sndMinus'; } else if (val == 'swap score') { let temp = scores.A; scores.A = scores.B; scores.B = temp; chosenSound = 'sndSwap'; } else if (val == 'lose all points') { scores[target] = 0; chosenSound = 'sndLose'; } playSound(chosenSound); let displayTargetName = (target === currentTeam) ? "your team" : "the other team"; document.getElementById('outcomeText').innerText = choice == 'keep' ? `You kept: ${val} for ${displayTargetName}!` : `You gave away: ${val} to ${displayTargetName}!`; updateScores(); changeScreen('screenOutcome'); } function updateScores() { document.getElementById('scoreA').innerText = scores.A; document.getElementById('scoreB').innerText = scores.B; let dot = document.getElementById('turnDot'); let ind = document.getElementById('turnIndicator'); dot.style.background = (currentTeam == 'A') ? 'var(--team-1-color)' : 'var(--team-2-color)'; ind.innerText = (currentTeam == 'A') ? "Team 1's Turn" : "Team 2's Turn"; document.getElementById('boxTeamA').className = `team-box team-a ${currentTeam=='A'?'active-team-turn-indicator':''}`; document.getElementById('boxTeamB').className = `team-box team-b ${currentTeam=='B'?'active-team-turn-indicator':''}`; } function nextTurn() { playSound('sndClick'); currentTeam = (currentTeam == 'A') ? 'B' : 'A'; updateScores(); buildGrid(); if(used.every(v => v === true)) { alert(`Game Over! Final Results -> Team 1: ${scores.A} | Team 2: ${scores.B}`); changeScreen('screenTitle'); } else { changeScreen('screenMain'); } } function startGame() { scores = {A:0, B:0}; used.fill(false); currentTeam = 'A'; updateScores(); buildGrid(); changeScreen('screenMain'); if (isMusicPlaying) { document.getElementById('bgMusic').play().catch(()=>{}); } } function playSound(id) { let audio = document.getElementById(id); audio.currentTime = 0; audio.play().catch(()=>{}); } </script> </body> </html>
Created for teachers 🎓 | Interactive Classroom Learning Tool | TEACHER KHEN

0 Comments