eaglelandsonce commited on
Commit
1ed8b7f
Β·
verified Β·
1 Parent(s): b63a6c5

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +363 -66
index.html CHANGED
@@ -1,89 +1,386 @@
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
- <meta charset="UTF-8" />
5
- <title>Jeopardy Game - Five Algorithms</title>
6
- <meta name="viewport" content="width=device-width, initial-scale=1" />
7
- <script src="https://cdn.tailwindcss.com"></script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  </head>
9
- <body class="bg-gradient-to-br from-blue-50 to-indigo-100 min-h-screen flex items-center justify-center p-6">
10
- <div class="w-full max-w-5xl bg-white rounded-2xl shadow-xl p-6">
11
- <h1 class="text-4xl font-extrabold text-center text-indigo-700 mb-6">
12
- Jeopardy: Five Algorithms
13
- </h1>
14
-
15
- <!-- Game Board -->
16
- <div id="board" class="grid grid-cols-5 gap-2 text-center">
17
- <!-- Categories will go here -->
 
 
 
 
 
 
 
 
 
 
18
  </div>
19
  </div>
20
 
 
 
 
 
 
 
 
 
21
  <script>
22
- // Categories = Five Algorithms
23
  const categories = [
24
  "Logistic Regression",
25
  "Decision Tree",
26
  "Random Forest",
27
- "Support Vector Machine",
28
- "KNN"
29
  ];
30
-
31
- // 3 questions per category = 15 total
32
- const questions = {
33
- "Logistic Regression": [
34
- { points: 100, q: "Which algorithm estimates probabilities using a sigmoid function?", a: "Logistic Regression" },
35
- { points: 200, q: "This algorithm is often used for binary classification, like predicting churn (Yes/No).", a: "Logistic Regression" },
36
- { points: 300, q: "Which hyperparameter controls regularization strength in Logistic Regression?", a: "C" }
 
 
 
37
  ],
38
- "Decision Tree": [
39
- { points: 100, q: "Which algorithm splits data based on feature thresholds in a flowchart-like structure?", a: "Decision Tree" },
40
- { points: 200, q: "This algorithm is easy to visualize and interpret but prone to overfitting.", a: "Decision Tree" },
41
- { points: 300, q: "Which splitting criteria are commonly used in Decision Trees?", a: "Gini Impurity and Entropy" }
 
 
 
 
42
  ],
43
- "Random Forest": [
44
- { points: 100, q: "Which ensemble algorithm builds many trees and averages their predictions?", a: "Random Forest" },
45
- { points: 200, q: "This algorithm reduces overfitting by using bagging across multiple trees.", a: "Random Forest" },
46
- { points: 300, q: "Which hyperparameter controls the number of trees in a Random Forest?", a: "n_estimators" }
 
 
 
 
47
  ],
48
- "Support Vector Machine": [
49
- { points: 100, q: "Which algorithm finds the optimal hyperplane that separates classes?", a: "Support Vector Machine" },
50
- { points: 200, q: "This algorithm is powerful with high-dimensional data and can use kernels.", a: "Support Vector Machine" },
51
- { points: 300, q: "Which function transforms data into higher dimensions in SVM?", a: "Kernel Trick" }
 
 
 
 
52
  ],
53
- "KNN": [
54
- { points: 100, q: "Which algorithm classifies a point based on the labels of nearby points?", a: "K-Nearest Neighbors (KNN)" },
55
- { points: 200, q: "This lazy learner algorithm has no training phase and relies on distance metrics.", a: "K-Nearest Neighbors (KNN)" },
56
- { points: 300, q: "Which hyperparameter determines how many neighbors vote on classification?", a: "k" }
 
 
 
 
57
  ]
58
- };
59
-
60
- // Build board
61
- const board = document.getElementById("board");
62
-
63
- // First row = categories
64
- categories.forEach(cat => {
65
- const cell = document.createElement("div");
66
- cell.className = "bg-indigo-600 text-white font-bold p-2 rounded";
67
- cell.innerText = cat;
68
- board.appendChild(cell);
69
- });
70
-
71
- // Question rows (3 per category)
72
- for (let i = 0; i < 3; i++) {
73
- categories.forEach(cat => {
74
- const qData = questions[cat][i];
75
- const cell = document.createElement("button");
76
- cell.className = "bg-yellow-300 font-bold p-4 rounded hover:bg-yellow-400";
77
- cell.innerText = `$${qData.points}`;
78
- cell.onclick = () => {
79
- alert(`${qData.q}\n\nAnswer: ${qData.a}`);
80
- cell.disabled = true;
81
- cell.className = "bg-gray-300 font-bold p-4 rounded";
82
- };
83
- board.appendChild(cell);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  });
85
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  </script>
87
  </body>
88
  </html>
89
-
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
+ <meta charset="UTF-8"/>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
6
+ <title>Five Algorithms Jeopardy</title>
7
+ <style>
8
+ :root{
9
+ --blue:#0a49a6;
10
+ --blue-dark:#073a84;
11
+ --gold:#ffd24a;
12
+ --board-gap:10px;
13
+ --card-depth:28px;
14
+ }
15
+ *{box-sizing:border-box}
16
+ body{
17
+ font-family: system-ui, Arial, sans-serif;
18
+ display:flex;flex-direction:column;align-items:center;
19
+ background: radial-gradient(1200px 700px at 50% -200px, #f2f6ff 0%, #e9efff 30%, #cfdafc 100%) fixed;
20
+ margin:0; min-height:100vh;
21
+ }
22
+ h1{ color:#173e8c; margin:22px 0 6px; text-shadow:0 2px 0 #fff;}
23
+ a.source{ font-size:14px; color:#334; margin-bottom:8px; text-decoration:none}
24
+ a.source:hover{ text-decoration:underline }
25
+ .topbar {
26
+ width:min(1100px,95vw);
27
+ display:flex;
28
+ justify-content:space-between;
29
+ align-items:center;
30
+ gap:10px;
31
+ margin-bottom:8px;
32
+ }
33
+ .btn-reset{
34
+ padding:8px 12px; border-radius:10px; font-weight:800; cursor:pointer;
35
+ border:2px solid #0d3a85; color:#fff; background:linear-gradient(180deg,#1362ff,#0d3a85);
36
+ box-shadow:0 8px 18px rgba(0,0,0,.25);
37
+ }
38
+ .btn-reset:hover{ transform: translateY(-1px) }
39
+ .btn-reset:active{ transform: translateY(0) }
40
+ .stage{ perspective: 1200px; width:min(1100px, 95vw); }
41
+ #game-board{
42
+ display:grid;
43
+ grid-template-columns: repeat(5, 1fr);
44
+ grid-auto-rows: 120px;
45
+ gap: var(--board-gap);
46
+ padding: var(--board-gap);
47
+ border-radius:18px;
48
+ background: linear-gradient(180deg, #0e1a3a, #01060f);
49
+ box-shadow:
50
+ 0 20px 45px rgba(0,0,0,.35),
51
+ inset 0 0 0 4px #000;
52
+ transform: rotateX(8deg);
53
+ transform-origin: top center;
54
+ }
55
+ .category, .card{
56
+ position:relative;
57
+ border-radius:14px;
58
+ user-select:none;
59
+ transform-style: preserve-3d;
60
+ transition: transform .2s ease, box-shadow .2s ease, filter .2s ease;
61
+ box-shadow:
62
+ 0 var(--card-depth) calc(var(--card-depth) + 12px) rgba(0,0,0,.35),
63
+ inset 0 0 0 1px rgba(255,255,255,.15);
64
+ }
65
+ .category{
66
+ background: linear-gradient(180deg, #004fbf 0%, #003d93 60%, #003684 100%);
67
+ color:#fff; font-weight:800; text-transform:uppercase; letter-spacing:.3px;
68
+ display:flex; justify-content:center; align-items:center; text-align:center;
69
+ border:1px solid #00122c;
70
+ text-shadow:0 2px 0 rgba(0,0,0,.35);
71
+ padding:8px;
72
+ }
73
+ .card{
74
+ cursor:pointer; font-weight:900; color: var(--gold);
75
+ background:
76
+ radial-gradient(80% 80% at 50% 25%, rgba(255,255,255,.18), rgba(255,255,255,0) 60%),
77
+ linear-gradient(180deg, var(--blue) 0%, var(--blue-dark) 100%);
78
+ border:1px solid #031b3f;
79
+ display:flex; justify-content:center; align-items:center; text-align:center;
80
+ font-size: clamp(16px, 2.4vw, 26px);
81
+ text-shadow: 0 2px 0 #000, 0 0 10px rgba(255,210,74,.35);
82
+ padding:10px;
83
+ }
84
+ .card.tilt:hover{
85
+ transform: translateZ(10px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg));
86
+ box-shadow:
87
+ 0 24px 48px rgba(0,0,0,.4),
88
+ 0 0 24px rgba(255,210,74,.15),
89
+ inset 0 0 0 1px rgba(255,255,255,.18);
90
+ filter: saturate(1.1);
91
+ }
92
+ .card:active{ transform: translateZ(0) scale(.985); box-shadow: 0 12px 18px rgba(0,0,0,.45), inset 0 0 0 1px rgba(255,255,255,.12); }
93
+ .card.disabled{ cursor:default; color:#bfc7da; background: linear-gradient(180deg,#6b7aa6,#4e5b85); text-shadow:none; filter:grayscale(.2) brightness(.92); }
94
+ #question-display{ width:min(1000px, 92vw); text-align:center; margin:16px 0 6px; }
95
+ #question-display h2{ margin:8px 0 6px; color:#0d2b6f }
96
+ #question-display p { font-size: 22px; line-height: 1.4; }
97
+ #score{ font-size:24px; font-weight:800; color:#0d2b6f; margin:0 0 8px 0 }
98
+ .answer-container{ display:flex; justify-content:center; flex-wrap:wrap; gap:10px; margin-top:14px }
99
+ .answer-btn{
100
+ margin:0; padding:10px 16px; font-size:18px; cursor:pointer;
101
+ border:2px solid #0d3a85; border-radius:10px; font-weight:800; color:#fff;
102
+ background: linear-gradient(180deg,#1362ff,#0d3a85);
103
+ box-shadow: 0 8px 18px rgba(0,0,0,.25);
104
+ transition: transform .12s ease, box-shadow .12s ease, filter .12s ease;
105
+ }
106
+ .answer-btn:hover{ transform: translateY(-2px); box-shadow:0 12px 26px rgba(0,0,0,.28) }
107
+ .answer-btn:active{ transform: translateY(0); box-shadow:0 8px 18px rgba(0,0,0,.25) }
108
+ .answer-btn.disabled{ background:#aab4cc; color:#445; cursor:not-allowed; border-color:#889 }
109
+ .feedback{ margin-top:10px; font-size:18px; font-weight:800 }
110
+ .dd-overlay{
111
+ position: fixed; inset:0; display:none; align-items:center; justify-content:center;
112
+ z-index: 9999; pointer-events:none;
113
+ background: radial-gradient(60% 60% at 50% 50%, rgba(255,255,255,.08), rgba(0,0,0,.7));
114
+ animation: dd-bg 1.2s ease-in-out 2;
115
+ }
116
+ .dd-text{
117
+ font-size: clamp(40px, 7vw, 120px);
118
+ font-weight: 900; color:#ffe17a; letter-spacing:2px;
119
+ text-shadow:
120
+ 0 0 12px rgba(255,225,122,.9),
121
+ 0 0 40px rgba(255,225,122,.6),
122
+ 0 6px 0 #000;
123
+ animation: flash 1.2s steps(2, jump-none) 2, wobble .9s ease-in-out 2;
124
+ }
125
+ @keyframes flash{ 0%,49%{opacity:1;filter:drop-shadow(0 0 24px rgba(255,225,122,.85));} 50%,100%{opacity:0;filter:none;} }
126
+ @keyframes wobble{ 0%{transform:scale(1) rotate(0)} 50%{transform:scale(1.06) rotate(-2deg)} 100%{transform:scale(1) rotate(0)} }
127
+ @keyframes dd-bg{ 0%{background: radial-gradient(40% 40% at 50% 50%, rgba(255,255,255,.12), rgba(0,0,0,.9));} 100%{background: radial-gradient(60% 60% at 50% 50%, rgba(255,255,255,.08), rgba(0,0,0,.7));} }
128
+ .flash-ring{ position:absolute; inset:-3px; border-radius:14px; pointer-events:none; box-shadow:0 0 0 3px rgba(255,225,122,.95), 0 0 30px 6px rgba(255,225,122,.6); animation: ring 1.2s ease-in-out 2; }
129
+ @keyframes ring{ 0%{opacity:1;transform:scale(1)} 50%{opacity:.1;transform:scale(.96)} 100%{opacity:1;transform:scale(1)} }
130
+ .daily-double-banner{ color:#b30000; font-weight:900; font-size:22px; margin:8px 0 }
131
+ #review{
132
+ width:min(1000px, 92vw);
133
+ margin:14px 0 24px 0;
134
+ padding:12px;
135
+ background:#fff;
136
+ border:1px solid #ccd3e0;
137
+ border-radius:12px;
138
+ box-shadow:0 6px 20px rgba(0,0,0,.08);
139
+ }
140
+ #review h3{ margin:0 0 8px 0; color:#0d2b6f }
141
+ .missed{ margin:8px 0; text-align:left }
142
+ .missed .q{ font-weight:700 }
143
+ .missed .a{ margin-left:8px }
144
+ </style>
145
  </head>
146
+ <body>
147
+ <h1>Five Algorithms Jeopardy</h1>
148
+ <a class="source" href="#" target="_blank">
149
+ Source: Five Algorithms β€” Simplified Paper (Intelligent Applications)
150
+ </a>
151
+
152
+ <div class="topbar">
153
+ <div id="score">Score: 0</div>
154
+ <button class="btn-reset" id="reset-btn" title="Start a fresh round">Reset Game</button>
155
+ </div>
156
+
157
+ <div class="stage">
158
+ <div id="game-board">
159
+ <div class="category">Logistic Regression</div>
160
+ <div class="category">Decision Tree</div>
161
+ <div class="category">Random Forest</div>
162
+ <div class="category">Support Vector Machines</div>
163
+ <div class="category">K-Nearest Neighbors</div>
164
+ <!-- cards injected -->
165
  </div>
166
  </div>
167
 
168
+ <div id="question-display"></div>
169
+ <div id="review" style="display:none;"></div>
170
+
171
+ <audio id="dd-audio" preload="auto">
172
+ <source src="daily-double.mp3" type="audio/mpeg">
173
+ </audio>
174
+ <div id="dd-overlay" class="dd-overlay"><div class="dd-text">DAILY&nbsp;DOUBLE!</div></div>
175
+
176
  <script>
 
177
  const categories = [
178
  "Logistic Regression",
179
  "Decision Tree",
180
  "Random Forest",
181
+ "Support Vector Machines",
182
+ "K-Nearest Neighbors"
183
  ];
184
+ // 15 questions, indices evenly distributed: five 0s, five 1s, five 2s
185
+ const questions = [
186
+ // Logistic Regression
187
+ [
188
+ { q: "Which function maps a linear score to a probability between 0 and 1 in binary classification?",
189
+ a: ["Sigmoid (logistic) function", "ReLU activation", "Softmax over all classes"], correct: 0 },
190
+ { q: "A classic use case for Logistic Regression is:",
191
+ a: ["Binary classification like churn (Yes/No)", "Clustering customers into segments", "Dimensionality reduction"], correct: 0 },
192
+ { q: "Which hyperparameter controls the strength of regularization in Logistic Regression (inverse strength)?",
193
+ a: ["C", "k", "n_estimators"], correct: 0 }
194
  ],
195
+ // Decision Tree
196
+ [
197
+ { q: "How does a Decision Tree choose splits at each node?",
198
+ a: ["By selecting features/thresholds that reduce impurity most", "By maximizing margin from a hyperplane", "By averaging predictions across many trees"], correct: 0 },
199
+ { q: "Decision Trees tend to overfit unless you:",
200
+ a: ["Prune or limit depth/leaf size", "Add dropout layers", "Ignore categorical features"], correct: 0 },
201
+ { q: "Common split criteria for classification trees are:",
202
+ a: ["Gini impurity and Entropy (Information Gain)", "MSE and MAE", "Cosine similarity and Jaccard"], correct: 0 }
203
  ],
204
+ // Random Forest
205
+ [
206
+ { q: "What main technique does Random Forest use to reduce variance?",
207
+ a: ["Bagging (bootstrap aggregating)", "Boosting with sequential learners", "Early stopping"], correct: 0 },
208
+ { q: "Which hyperparameter sets the number of trees in a Random Forest?",
209
+ a: ["n_estimators", "C", "gamma"], correct: 0 },
210
+ { q: "At each split, a Random Forest typically:",
211
+ a: ["Considers a random subset of features", "Uses all features every time", "Learns attention weights across tokens"], correct: 0 }
212
  ],
213
+ // Support Vector Machines
214
+ [
215
+ { q: "SVMs primarily aim to:",
216
+ a: ["Maximize the margin via an optimal separating hyperplane", "Minimize tree depth", "Maximize training accuracy regardless of margin"], correct: 0 },
217
+ { q: "What enables SVMs to model non-linear decision boundaries?",
218
+ a: ["The kernel trick", "Batch normalization", "Bagging"], correct: 0 },
219
+ { q: "In an RBF-kernel SVM, which hyperparameter controls how far the influence of a single training example reaches?",
220
+ a: ["gamma (Ξ³)", "n_neighbors", "learning rate"], correct: 0 }
221
  ],
222
+ // K-Nearest Neighbors
223
+ [
224
+ { q: "KNN is best described as a:",
225
+ a: ["Lazy, instance-based learner", "Parametric, eager learner", "Generative probabilistic model"], correct: 0 },
226
+ { q: "If k is set too small in KNN, the model will most likely:",
227
+ a: ["Overfit to noise/outliers", "Underfit severely in all cases", "Generalize better automatically"], correct: 0 },
228
+ { q: "Which preprocessing step is especially important for KNN?",
229
+ a: ["Feature scaling/standardization", "Adding bias terms to features", "Label smoothing"], correct: 0 }
230
  ]
231
+ ];
232
+ let score = 0, answered = 0;
233
+ const total = 15;
234
+ const board = document.getElementById("game-board"),
235
+ qdisp = document.getElementById("question-display"),
236
+ sdisp = document.getElementById("score"),
237
+ review = document.getElementById("review");
238
+ const ddOverlay = document.getElementById("dd-overlay");
239
+ const ddAudio = document.getElementById("dd-audio");
240
+ const shuffleRegistry = new Map();
241
+ const missedQuestions = [];
242
+ const dailyDouble = { col: Math.floor(Math.random() * 5), row: Math.floor(Math.random() * 3) };
243
+ document.getElementById('reset-btn').addEventListener('click', () => location.reload());
244
+
245
+ function createBoard() {
246
+ // header row already has categories; now inject 15 value cards
247
+ for (let row = 0; row < 3; row++) {
248
+ for (let col = 0; col < 5; col++) {
249
+ const card = document.createElement("div");
250
+ card.className = "card tilt";
251
+ card.textContent = `$${(row + 1) * 100}`;
252
+ card.dataset.col = col;
253
+ card.dataset.row = row;
254
+ card.addEventListener("mousemove", (e) => {
255
+ const r = card.getBoundingClientRect();
256
+ const x = (e.clientX - r.left) / r.width;
257
+ const y = (e.clientY - r.top) / r.height;
258
+ card.style.setProperty("--ry", `${(x - 0.5) * 10}deg`);
259
+ card.style.setProperty("--rx", `${(0.5 - y) * 10}deg`);
260
+ });
261
+ card.addEventListener("mouseleave", () => {
262
+ card.style.removeProperty("--ry");
263
+ card.style.removeProperty("--rx");
264
+ });
265
+ card.onclick = () => handleCardClick(card);
266
+ board.appendChild(card);
267
+ }
268
+ }
269
+ }
270
+
271
+ function handleCardClick(card){
272
+ if (card.classList.contains("disabled")) return;
273
+ const col = +card.dataset.col;
274
+ const row = +card.dataset.row;
275
+ const isDD = (col === dailyDouble.col && row === dailyDouble.row);
276
+ if (isDD){
277
+ triggerDailyDouble(card, () => showQuestion(col, row, card, true));
278
+ } else {
279
+ showQuestion(col, row, card, false);
280
+ }
281
+ }
282
+
283
+ function triggerDailyDouble(card, onDone){
284
+ const ring = document.createElement("div");
285
+ ring.className = "flash-ring";
286
+ card.appendChild(ring);
287
+ ddAudio.currentTime = 0;
288
+ ddAudio.play().catch(()=>{});
289
+ ddOverlay.style.display = "flex";
290
+ setTimeout(() => {
291
+ ddOverlay.style.display = "none";
292
+ ring.remove();
293
+ onDone();
294
+ }, 2400);
295
+ }
296
+
297
+ function showQuestion(categoryIndex, difficulty, card, isDailyDouble){
298
+ const q = questions[categoryIndex][difficulty];
299
+ const options = q.a.map((text, origIdx) => ({ text, origIdx }));
300
+ // shuffle options for display
301
+ for (let i = options.length - 1; i > 0; i--) {
302
+ const j = Math.floor(Math.random() * (i + 1));
303
+ [options[i], options[j]] = [options[j], options[i]];
304
+ }
305
+ const shuffledCorrectIndex = options.findIndex(o => o.origIdx === q.correct);
306
+ const key = `${categoryIndex}-${difficulty}`;
307
+ shuffleRegistry.set(key, { shuffledCorrectIndex, isDailyDouble });
308
+
309
+ const dailyDoubleBanner = isDailyDouble ? `<div class="daily-double-banner">πŸŽ‰ DAILY DOUBLE! πŸŽ‰</div>` : "";
310
+ qdisp.innerHTML = `
311
+ ${dailyDoubleBanner}
312
+ <h2>${categories[categoryIndex]} for $${(difficulty + 1) * 100}${isDailyDouble ? " (x2)" : ""}</h2>
313
+ <p>${q.q}</p>
314
+ <div class="answer-container">
315
+ ${options.map((opt, i) =>
316
+ `<button class="answer-btn" data-ans="${i}" data-key="${key}">${opt.text}</button>`
317
+ ).join("")}
318
+ </div>
319
+ `;
320
+
321
+ card.classList.add("disabled");
322
+ document.querySelectorAll('.answer-btn').forEach(btn => {
323
+ btn.addEventListener('click', () => {
324
+ if (btn.classList.contains('disabled')) return;
325
+ const chosenIndex = parseInt(btn.getAttribute('data-ans'), 10);
326
+ const k = btn.getAttribute('data-key');
327
+ checkAnswer(categoryIndex, difficulty, chosenIndex, k);
328
+ }, { once: true });
329
  });
330
  }
331
+
332
+ function checkAnswer(cat, diff, chosenShuffledIndex, key){
333
+ const q = questions[cat][diff];
334
+ const reg = shuffleRegistry.get(key);
335
+ const isCorrect = (chosenShuffledIndex === reg.shuffledCorrectIndex);
336
+ let val = (diff + 1) * 100;
337
+ if (reg.isDailyDouble) val *= 2;
338
+
339
+ document.querySelectorAll(".answer-btn").forEach(b => {
340
+ b.disabled = true; b.classList.add("disabled");
341
+ });
342
+
343
+ if (isCorrect) {
344
+ score += val;
345
+ qdisp.innerHTML += `<p class="feedback" style="color:green;">βœ… Correct! +$${val.toLocaleString()}</p>`;
346
+ } else {
347
+ score -= val;
348
+ const correctText = q.a[q.correct];
349
+ const chosenBtn = document.querySelector(`.answer-btn[data-ans="${chosenShuffledIndex}"][data-key="${key}"]`);
350
+ const chosenPretty = chosenBtn ? chosenBtn.textContent : "(your choice)";
351
+ qdisp.innerHTML += `<p class="feedback" style="color:#b00020;">❌ Wrong! βˆ’$${val.toLocaleString()}<br/>Correct answer: <em>${correctText}</em></p>`;
352
+ missedQuestions.push({
353
+ category: categories[cat],
354
+ value: `$${(diff+1)*100}${reg.isDailyDouble ? " (x2)" : ""}`,
355
+ question: q.q,
356
+ yourAnswer: chosenPretty,
357
+ correctAnswer: correctText
358
+ });
359
+ }
360
+
361
+ sdisp.textContent = `Score: ${score}`;
362
+ if (++answered === total) endGame();
363
+ }
364
+
365
+ function endGame(){
366
+ qdisp.innerHTML += `<h2 style="margin-top:12px">Game Over!</h2><p>Your final score: $${score.toLocaleString()}</p>`;
367
+ if (missedQuestions.length){
368
+ const items = missedQuestions.map(m =>
369
+ `<div class="missed">
370
+ <div class="q">(${m.category} β€’ ${m.value}) ${m.question}</div>
371
+ <div class="a">Your answer: <em>${m.yourAnswer}</em></div>
372
+ <div class="a">Correct: <strong>${m.correctAnswer}</strong></div>
373
+ </div>`
374
+ ).join("");
375
+ review.style.display = "block";
376
+ review.innerHTML = `<h3>Review: Questions to Revisit (${missedQuestions.length})</h3>${items}`;
377
+ } else {
378
+ review.style.display = "block";
379
+ review.innerHTML = `<h3>Perfect Round!</h3><p>You answered all questions correctly πŸŽ‰</p>`;
380
+ }
381
+ }
382
+
383
+ createBoard();
384
  </script>
385
  </body>
386
  </html>