eaglelandsonce commited on
Commit
1b5ae87
·
verified ·
1 Parent(s): 72e94a5

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +851 -19
index.html CHANGED
@@ -1,19 +1,851 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>Pattern Sprint Interview Game</title>
7
+ <style>
8
+ :root {
9
+ --navy: #071833;
10
+ --blue: #2563eb;
11
+ --green: #16a34a;
12
+ --red: #dc2626;
13
+ --yellow: #facc15;
14
+ --purple: #7c3aed;
15
+ --orange: #f97316;
16
+ --gray: #f3f4f6;
17
+ --dark-gray: #374151;
18
+ --white: #ffffff;
19
+ --border: #d1d5db;
20
+ }
21
+
22
+ * {
23
+ box-sizing: border-box;
24
+ }
25
+
26
+ body {
27
+ margin: 0;
28
+ min-height: 100vh;
29
+ font-family: Arial, Helvetica, sans-serif;
30
+ background: linear-gradient(135deg, #eef2ff, #f8fafc);
31
+ color: var(--navy);
32
+ display: flex;
33
+ align-items: center;
34
+ justify-content: center;
35
+ padding: 24px;
36
+ }
37
+
38
+ .app {
39
+ width: min(1100px, 100%);
40
+ background: var(--white);
41
+ border: 2px solid #e5e7eb;
42
+ border-radius: 22px;
43
+ box-shadow: 0 20px 50px rgba(7, 24, 51, 0.15);
44
+ overflow: hidden;
45
+ }
46
+
47
+ header {
48
+ background: var(--navy);
49
+ color: var(--white);
50
+ padding: 24px 28px;
51
+ }
52
+
53
+ header h1 {
54
+ margin: 0;
55
+ font-size: clamp(28px, 4vw, 44px);
56
+ letter-spacing: -1px;
57
+ }
58
+
59
+ header p {
60
+ margin: 8px 0 0;
61
+ font-size: 17px;
62
+ opacity: 0.9;
63
+ }
64
+
65
+ .main {
66
+ display: grid;
67
+ grid-template-columns: 1.4fr 0.9fr;
68
+ gap: 20px;
69
+ padding: 24px;
70
+ }
71
+
72
+ .panel {
73
+ border: 2px solid #e5e7eb;
74
+ border-radius: 18px;
75
+ background: #ffffff;
76
+ padding: 22px;
77
+ }
78
+
79
+ .game-area {
80
+ min-height: 520px;
81
+ display: flex;
82
+ flex-direction: column;
83
+ justify-content: space-between;
84
+ }
85
+
86
+ .status-row {
87
+ display: grid;
88
+ grid-template-columns: repeat(4, 1fr);
89
+ gap: 12px;
90
+ margin-bottom: 18px;
91
+ }
92
+
93
+ .stat {
94
+ background: var(--gray);
95
+ border-radius: 14px;
96
+ padding: 14px;
97
+ text-align: center;
98
+ border: 1px solid #e5e7eb;
99
+ }
100
+
101
+ .stat .label {
102
+ font-size: 13px;
103
+ color: var(--dark-gray);
104
+ margin-bottom: 4px;
105
+ }
106
+
107
+ .stat .value {
108
+ font-size: 24px;
109
+ font-weight: 800;
110
+ }
111
+
112
+ .screen {
113
+ flex: 1;
114
+ border: 3px dashed #c7d2fe;
115
+ border-radius: 18px;
116
+ background: #f8fafc;
117
+ display: flex;
118
+ align-items: center;
119
+ justify-content: center;
120
+ text-align: center;
121
+ padding: 28px;
122
+ margin-bottom: 18px;
123
+ min-height: 260px;
124
+ }
125
+
126
+ .screen h2 {
127
+ font-size: clamp(28px, 4vw, 44px);
128
+ margin: 0 0 12px;
129
+ }
130
+
131
+ .screen p {
132
+ font-size: 18px;
133
+ line-height: 1.45;
134
+ margin: 8px 0;
135
+ }
136
+
137
+ .sequence-display {
138
+ display: flex;
139
+ flex-wrap: wrap;
140
+ justify-content: center;
141
+ gap: 14px;
142
+ margin: 20px 0;
143
+ }
144
+
145
+ .tile {
146
+ width: 78px;
147
+ height: 78px;
148
+ border-radius: 18px;
149
+ display: grid;
150
+ place-items: center;
151
+ font-weight: 900;
152
+ font-size: 22px;
153
+ color: white;
154
+ box-shadow: 0 12px 20px rgba(0, 0, 0, 0.18);
155
+ border: 3px solid rgba(255, 255, 255, 0.7);
156
+ user-select: none;
157
+ }
158
+
159
+ .tile.small {
160
+ width: 56px;
161
+ height: 56px;
162
+ border-radius: 14px;
163
+ font-size: 17px;
164
+ cursor: pointer;
165
+ transition: transform 0.15s, box-shadow 0.15s;
166
+ }
167
+
168
+ .tile.small:hover {
169
+ transform: translateY(-3px);
170
+ box-shadow: 0 16px 24px rgba(0, 0, 0, 0.2);
171
+ }
172
+
173
+ .Blue { background: var(--blue); }
174
+ .Green { background: var(--green); }
175
+ .Red { background: var(--red); }
176
+ .Yellow { background: #ca8a04; }
177
+ .Purple { background: var(--purple); }
178
+ .Orange { background: var(--orange); }
179
+
180
+ .choice-grid {
181
+ display: grid;
182
+ grid-template-columns: 1fr 1fr;
183
+ gap: 12px;
184
+ width: 100%;
185
+ max-width: 720px;
186
+ margin: 0 auto;
187
+ }
188
+
189
+ .choice {
190
+ background: white;
191
+ border: 2px solid var(--border);
192
+ border-radius: 16px;
193
+ padding: 14px;
194
+ cursor: pointer;
195
+ transition: all 0.15s ease;
196
+ text-align: left;
197
+ font-weight: 700;
198
+ }
199
+
200
+ .choice:hover {
201
+ border-color: var(--blue);
202
+ transform: translateY(-2px);
203
+ box-shadow: 0 10px 18px rgba(37, 99, 235, 0.12);
204
+ }
205
+
206
+ .choice.correct {
207
+ border-color: var(--green);
208
+ background: #ecfdf5;
209
+ }
210
+
211
+ .choice.wrong {
212
+ border-color: var(--red);
213
+ background: #fef2f2;
214
+ }
215
+
216
+ .button-row {
217
+ display: flex;
218
+ flex-wrap: wrap;
219
+ gap: 12px;
220
+ align-items: center;
221
+ justify-content: center;
222
+ }
223
+
224
+ button {
225
+ border: none;
226
+ border-radius: 14px;
227
+ padding: 14px 20px;
228
+ font-size: 16px;
229
+ font-weight: 800;
230
+ cursor: pointer;
231
+ transition: transform 0.15s, opacity 0.15s;
232
+ }
233
+
234
+ button:hover {
235
+ transform: translateY(-2px);
236
+ }
237
+
238
+ button:disabled {
239
+ opacity: 0.5;
240
+ cursor: not-allowed;
241
+ transform: none;
242
+ }
243
+
244
+ .primary {
245
+ background: var(--blue);
246
+ color: white;
247
+ }
248
+
249
+ .secondary {
250
+ background: #e5e7eb;
251
+ color: var(--navy);
252
+ }
253
+
254
+ .danger {
255
+ background: var(--red);
256
+ color: white;
257
+ }
258
+
259
+ .side h2 {
260
+ margin: 0 0 12px;
261
+ font-size: 26px;
262
+ }
263
+
264
+ .side-section {
265
+ margin-bottom: 22px;
266
+ padding-bottom: 18px;
267
+ border-bottom: 1px solid #e5e7eb;
268
+ }
269
+
270
+ .side-section:last-child {
271
+ border-bottom: none;
272
+ margin-bottom: 0;
273
+ padding-bottom: 0;
274
+ }
275
+
276
+ .meter-wrap {
277
+ margin: 12px 0;
278
+ }
279
+
280
+ .meter-label {
281
+ display: flex;
282
+ justify-content: space-between;
283
+ font-weight: 700;
284
+ margin-bottom: 6px;
285
+ font-size: 14px;
286
+ }
287
+
288
+ .meter {
289
+ height: 12px;
290
+ background: #e5e7eb;
291
+ border-radius: 999px;
292
+ overflow: hidden;
293
+ }
294
+
295
+ .meter-fill {
296
+ height: 100%;
297
+ width: 0%;
298
+ background: var(--blue);
299
+ transition: width 0.4s ease;
300
+ }
301
+
302
+ .history {
303
+ max-height: 210px;
304
+ overflow-y: auto;
305
+ padding-right: 6px;
306
+ }
307
+
308
+ .history-item {
309
+ background: #f9fafb;
310
+ border: 1px solid #e5e7eb;
311
+ border-radius: 12px;
312
+ padding: 10px;
313
+ margin-bottom: 8px;
314
+ font-size: 14px;
315
+ }
316
+
317
+ .feedback {
318
+ font-size: 20px;
319
+ font-weight: 900;
320
+ min-height: 30px;
321
+ text-align: center;
322
+ margin: 8px 0 14px;
323
+ }
324
+
325
+ .good { color: var(--green); }
326
+ .bad { color: var(--red); }
327
+ .neutral { color: var(--dark-gray); }
328
+
329
+ .report {
330
+ text-align: left;
331
+ max-width: 760px;
332
+ margin: 0 auto;
333
+ }
334
+
335
+ .report h2 {
336
+ text-align: center;
337
+ }
338
+
339
+ .report-card {
340
+ background: white;
341
+ border: 2px solid #e5e7eb;
342
+ border-radius: 16px;
343
+ padding: 16px;
344
+ margin: 12px 0;
345
+ }
346
+
347
+ .report-card strong {
348
+ color: var(--navy);
349
+ }
350
+
351
+ .hidden {
352
+ display: none !important;
353
+ }
354
+
355
+ @media (max-width: 850px) {
356
+ .main {
357
+ grid-template-columns: 1fr;
358
+ }
359
+
360
+ .status-row {
361
+ grid-template-columns: 1fr 1fr;
362
+ }
363
+
364
+ .choice-grid {
365
+ grid-template-columns: 1fr;
366
+ }
367
+ }
368
+ </style>
369
+ </head>
370
+ <body>
371
+ <div class="app">
372
+ <header>
373
+ <h1>Pattern Sprint</h1>
374
+ <p>A gamified interview assessment for memory, attention, speed, and learning improvement.</p>
375
+ </header>
376
+
377
+ <main class="main">
378
+ <section class="panel game-area">
379
+ <div>
380
+ <div class="status-row">
381
+ <div class="stat">
382
+ <div class="label">Round</div>
383
+ <div class="value" id="roundValue">0/8</div>
384
+ </div>
385
+ <div class="stat">
386
+ <div class="label">Score</div>
387
+ <div class="value" id="scoreValue">0</div>
388
+ </div>
389
+ <div class="stat">
390
+ <div class="label">Accuracy</div>
391
+ <div class="value" id="accuracyValue">0%</div>
392
+ </div>
393
+ <div class="stat">
394
+ <div class="label">Timer</div>
395
+ <div class="value" id="timerValue">--</div>
396
+ </div>
397
+ </div>
398
+
399
+ <div class="screen" id="screen">
400
+ <div>
401
+ <h2>Ready?</h2>
402
+ <p>You will see a short color pattern. Memorize it before it disappears.</p>
403
+ <p>Then choose the matching sequence as quickly and accurately as possible.</p>
404
+ </div>
405
+ </div>
406
+
407
+ <div class="feedback neutral" id="feedback">Press Start to begin.</div>
408
+ </div>
409
+
410
+ <div class="button-row">
411
+ <button class="primary" id="startBtn">Start Game</button>
412
+ <button class="secondary" id="nextBtn" disabled>Next Round</button>
413
+ <button class="danger" id="resetBtn">Reset</button>
414
+ </div>
415
+ </section>
416
+
417
+ <aside class="panel side">
418
+ <div class="side-section">
419
+ <h2>Assessment Signals</h2>
420
+ <div class="meter-wrap">
421
+ <div class="meter-label"><span>Working Memory</span><span id="memoryScore">0%</span></div>
422
+ <div class="meter"><div class="meter-fill" id="memoryFill"></div></div>
423
+ </div>
424
+ <div class="meter-wrap">
425
+ <div class="meter-label"><span>Attention</span><span id="attentionScore">0%</span></div>
426
+ <div class="meter"><div class="meter-fill" id="attentionFill"></div></div>
427
+ </div>
428
+ <div class="meter-wrap">
429
+ <div class="meter-label"><span>Speed</span><span id="speedScore">0%</span></div>
430
+ <div class="meter"><div class="meter-fill" id="speedFill"></div></div>
431
+ </div>
432
+ <div class="meter-wrap">
433
+ <div class="meter-label"><span>Learning Trend</span><span id="learningScore">0%</span></div>
434
+ <div class="meter"><div class="meter-fill" id="learningFill"></div></div>
435
+ </div>
436
+ </div>
437
+
438
+ <div class="side-section">
439
+ <h2>Game Rules</h2>
440
+ <p><strong>1.</strong> Watch the sequence.</p>
441
+ <p><strong>2.</strong> Remember the order.</p>
442
+ <p><strong>3.</strong> Pick the correct answer.</p>
443
+ <p><strong>4.</strong> Later rounds get harder.</p>
444
+ </div>
445
+
446
+ <div class="side-section">
447
+ <h2>Round History</h2>
448
+ <div class="history" id="history"></div>
449
+ </div>
450
+ </aside>
451
+ </main>
452
+ </div>
453
+
454
+ <script>
455
+ const COLORS = ["Blue", "Green", "Red", "Yellow", "Purple", "Orange"];
456
+ const TOTAL_ROUNDS = 8;
457
+
458
+ const state = {
459
+ round: 0,
460
+ score: 0,
461
+ correct: 0,
462
+ attempts: 0,
463
+ currentSequence: [],
464
+ roundStartTime: null,
465
+ timerInterval: null,
466
+ responseTimes: [],
467
+ history: [],
468
+ acceptingAnswer: false
469
+ };
470
+
471
+ const els = {
472
+ screen: document.getElementById("screen"),
473
+ feedback: document.getElementById("feedback"),
474
+ roundValue: document.getElementById("roundValue"),
475
+ scoreValue: document.getElementById("scoreValue"),
476
+ accuracyValue: document.getElementById("accuracyValue"),
477
+ timerValue: document.getElementById("timerValue"),
478
+ startBtn: document.getElementById("startBtn"),
479
+ nextBtn: document.getElementById("nextBtn"),
480
+ resetBtn: document.getElementById("resetBtn"),
481
+ history: document.getElementById("history"),
482
+ memoryScore: document.getElementById("memoryScore"),
483
+ attentionScore: document.getElementById("attentionScore"),
484
+ speedScore: document.getElementById("speedScore"),
485
+ learningScore: document.getElementById("learningScore"),
486
+ memoryFill: document.getElementById("memoryFill"),
487
+ attentionFill: document.getElementById("attentionFill"),
488
+ speedFill: document.getElementById("speedFill"),
489
+ learningFill: document.getElementById("learningFill")
490
+ };
491
+
492
+ function randomItem(arr) {
493
+ return arr[Math.floor(Math.random() * arr.length)];
494
+ }
495
+
496
+ function createSequence(length) {
497
+ const seq = [];
498
+ for (let i = 0; i < length; i++) {
499
+ seq.push(randomItem(COLORS));
500
+ }
501
+ return seq;
502
+ }
503
+
504
+ function sequenceToText(seq) {
505
+ return seq.join(" → ");
506
+ }
507
+
508
+ function makeTile(color, small = false) {
509
+ const div = document.createElement("div");
510
+ div.className = `tile ${small ? "small" : ""} ${color}`;
511
+ div.textContent = color[0];
512
+ div.title = color;
513
+ return div;
514
+ }
515
+
516
+ function renderSequence(seq, small = false) {
517
+ const wrapper = document.createElement("div");
518
+ wrapper.className = "sequence-display";
519
+ seq.forEach(color => wrapper.appendChild(makeTile(color, small)));
520
+ return wrapper;
521
+ }
522
+
523
+ function shuffle(array) {
524
+ const copy = [...array];
525
+ for (let i = copy.length - 1; i > 0; i--) {
526
+ const j = Math.floor(Math.random() * (i + 1));
527
+ [copy[i], copy[j]] = [copy[j], copy[i]];
528
+ }
529
+ return copy;
530
+ }
531
+
532
+ function mutateSequence(seq) {
533
+ const mutated = [...seq];
534
+ const mutationType = Math.floor(Math.random() * 3);
535
+
536
+ if (mutationType === 0 && mutated.length > 1) {
537
+ const i = Math.floor(Math.random() * mutated.length);
538
+ let j = Math.floor(Math.random() * mutated.length);
539
+ while (j === i) j = Math.floor(Math.random() * mutated.length);
540
+ [mutated[i], mutated[j]] = [mutated[j], mutated[i]];
541
+ } else if (mutationType === 1) {
542
+ const i = Math.floor(Math.random() * mutated.length);
543
+ let newColor = randomItem(COLORS);
544
+ while (newColor === mutated[i]) newColor = randomItem(COLORS);
545
+ mutated[i] = newColor;
546
+ } else {
547
+ mutated.reverse();
548
+ }
549
+
550
+ return mutated;
551
+ }
552
+
553
+ function createChoices(correctSeq) {
554
+ const choices = [correctSeq];
555
+ const seen = new Set([sequenceToText(correctSeq)]);
556
+
557
+ while (choices.length < 4) {
558
+ const mutated = mutateSequence(correctSeq);
559
+ const key = sequenceToText(mutated);
560
+ if (!seen.has(key)) {
561
+ choices.push(mutated);
562
+ seen.add(key);
563
+ }
564
+ }
565
+
566
+ return shuffle(choices);
567
+ }
568
+
569
+ function setFeedback(text, type = "neutral") {
570
+ els.feedback.textContent = text;
571
+ els.feedback.className = `feedback ${type}`;
572
+ }
573
+
574
+ function updateStats() {
575
+ const accuracy = state.attempts ? Math.round((state.correct / state.attempts) * 100) : 0;
576
+ els.roundValue.textContent = `${state.round}/${TOTAL_ROUNDS}`;
577
+ els.scoreValue.textContent = state.score;
578
+ els.accuracyValue.textContent = `${accuracy}%`;
579
+
580
+ const memory = accuracy;
581
+ const attention = calculateAttentionScore();
582
+ const speed = calculateSpeedScore();
583
+ const learning = calculateLearningTrend();
584
+
585
+ updateMeter("memory", memory);
586
+ updateMeter("attention", attention);
587
+ updateMeter("speed", speed);
588
+ updateMeter("learning", learning);
589
+ }
590
+
591
+ function updateMeter(name, value) {
592
+ const clamped = Math.max(0, Math.min(100, Math.round(value)));
593
+ els[`${name}Score`].textContent = `${clamped}%`;
594
+ els[`${name}Fill`].style.width = `${clamped}%`;
595
+ }
596
+
597
+ function calculateAttentionScore() {
598
+ if (state.history.length === 0) return 0;
599
+ const harderRounds = state.history.filter(item => item.length >= 5);
600
+ if (harderRounds.length === 0) return Math.round((state.correct / Math.max(1, state.attempts)) * 100);
601
+ const correctHard = harderRounds.filter(item => item.correct).length;
602
+ return (correctHard / harderRounds.length) * 100;
603
+ }
604
+
605
+ function calculateSpeedScore() {
606
+ if (state.responseTimes.length === 0) return 0;
607
+ const avg = state.responseTimes.reduce((a, b) => a + b, 0) / state.responseTimes.length;
608
+ return Math.max(0, Math.min(100, 100 - (avg - 1.5) * 18));
609
+ }
610
+
611
+ function calculateLearningTrend() {
612
+ if (state.history.length < 4) return 0;
613
+ const midpoint = Math.floor(state.history.length / 2);
614
+ const firstHalf = state.history.slice(0, midpoint);
615
+ const secondHalf = state.history.slice(midpoint);
616
+ const firstAccuracy = firstHalf.filter(x => x.correct).length / firstHalf.length;
617
+ const secondAccuracy = secondHalf.filter(x => x.correct).length / secondHalf.length;
618
+ const improvement = secondAccuracy - firstAccuracy;
619
+ return Math.max(0, Math.min(100, 50 + improvement * 100));
620
+ }
621
+
622
+ function updateHistory() {
623
+ els.history.innerHTML = "";
624
+ state.history.slice().reverse().forEach(item => {
625
+ const div = document.createElement("div");
626
+ div.className = "history-item";
627
+ div.innerHTML = `
628
+ <strong>Round ${item.round}</strong> - ${item.correct ? "Correct" : "Incorrect"}<br>
629
+ Length: ${item.length} | Time: ${item.time.toFixed(2)}s | Points: ${item.points}
630
+ `;
631
+ els.history.appendChild(div);
632
+ });
633
+ }
634
+
635
+ function startTimer() {
636
+ state.roundStartTime = performance.now();
637
+ els.timerValue.textContent = "0.0";
638
+ clearInterval(state.timerInterval);
639
+ state.timerInterval = setInterval(() => {
640
+ const seconds = (performance.now() - state.roundStartTime) / 1000;
641
+ els.timerValue.textContent = seconds.toFixed(1);
642
+ }, 100);
643
+ }
644
+
645
+ function stopTimer() {
646
+ clearInterval(state.timerInterval);
647
+ const seconds = (performance.now() - state.roundStartTime) / 1000;
648
+ els.timerValue.textContent = seconds.toFixed(1);
649
+ return seconds;
650
+ }
651
+
652
+ function startGame() {
653
+ resetGame(false);
654
+ els.startBtn.disabled = true;
655
+ els.nextBtn.disabled = true;
656
+ nextRound();
657
+ }
658
+
659
+ function nextRound() {
660
+ if (state.round >= TOTAL_ROUNDS) {
661
+ showReport();
662
+ return;
663
+ }
664
+
665
+ state.round += 1;
666
+ state.acceptingAnswer = false;
667
+ els.nextBtn.disabled = true;
668
+ setFeedback("Memorize the pattern...", "neutral");
669
+ updateStats();
670
+
671
+ const length = Math.min(3 + Math.floor((state.round - 1) / 2), 7);
672
+ state.currentSequence = createSequence(length);
673
+
674
+ els.screen.innerHTML = "";
675
+ const content = document.createElement("div");
676
+ content.innerHTML = `<h2>Round ${state.round}</h2><p>Watch carefully.</p>`;
677
+ content.appendChild(renderSequence(state.currentSequence));
678
+ els.screen.appendChild(content);
679
+
680
+ const displayTime = Math.max(1300, 2600 - state.round * 120);
681
+ setTimeout(showChoices, displayTime);
682
+ }
683
+
684
+ function showChoices() {
685
+ state.acceptingAnswer = true;
686
+ setFeedback("Choose the exact matching sequence.", "neutral");
687
+ startTimer();
688
+
689
+ const choices = createChoices(state.currentSequence);
690
+ els.screen.innerHTML = "";
691
+
692
+ const content = document.createElement("div");
693
+ content.style.width = "100%";
694
+ content.innerHTML = `<h2>Select the Match</h2><p>The original pattern is hidden.</p>`;
695
+
696
+ const grid = document.createElement("div");
697
+ grid.className = "choice-grid";
698
+
699
+ choices.forEach((choiceSeq, index) => {
700
+ const button = document.createElement("button");
701
+ button.className = "choice";
702
+ button.setAttribute("aria-label", `Choice ${index + 1}: ${sequenceToText(choiceSeq)}`);
703
+ button.innerHTML = `<div style="margin-bottom: 8px;">Choice ${index + 1}</div><div>${sequenceToText(choiceSeq)}</div>`;
704
+ button.addEventListener("click", () => handleAnswer(button, choiceSeq));
705
+ grid.appendChild(button);
706
+ });
707
+
708
+ content.appendChild(grid);
709
+ els.screen.appendChild(content);
710
+ }
711
+
712
+ function handleAnswer(button, selectedSeq) {
713
+ if (!state.acceptingAnswer) return;
714
+ state.acceptingAnswer = false;
715
+
716
+ const responseTime = stopTimer();
717
+ const isCorrect = sequenceToText(selectedSeq) === sequenceToText(state.currentSequence);
718
+ const sequenceLength = state.currentSequence.length;
719
+ const speedBonus = Math.max(0, Math.round(30 - responseTime * 4));
720
+ const points = isCorrect ? sequenceLength * 20 + speedBonus : 0;
721
+
722
+ state.attempts += 1;
723
+ state.responseTimes.push(responseTime);
724
+ if (isCorrect) {
725
+ state.correct += 1;
726
+ state.score += points;
727
+ button.classList.add("correct");
728
+ setFeedback(`Correct! +${points} points`, "good");
729
+ } else {
730
+ button.classList.add("wrong");
731
+ setFeedback("Not quite. Review the correct pattern below.", "bad");
732
+ }
733
+
734
+ document.querySelectorAll(".choice").forEach(choice => {
735
+ if (choice.textContent.includes(sequenceToText(state.currentSequence))) {
736
+ choice.classList.add("correct");
737
+ }
738
+ choice.disabled = true;
739
+ });
740
+
741
+ state.history.push({
742
+ round: state.round,
743
+ correct: isCorrect,
744
+ length: sequenceLength,
745
+ time: responseTime,
746
+ points
747
+ });
748
+
749
+ updateStats();
750
+ updateHistory();
751
+ showCorrectPattern();
752
+
753
+ if (state.round >= TOTAL_ROUNDS) {
754
+ els.nextBtn.textContent = "View Report";
755
+ } else {
756
+ els.nextBtn.textContent = "Next Round";
757
+ }
758
+ els.nextBtn.disabled = false;
759
+ }
760
+
761
+ function showCorrectPattern() {
762
+ const existing = els.screen.querySelector(".correct-pattern");
763
+ if (existing) existing.remove();
764
+
765
+ const div = document.createElement("div");
766
+ div.className = "correct-pattern";
767
+ div.style.marginTop = "18px";
768
+ div.innerHTML = `<p><strong>Correct pattern:</strong> ${sequenceToText(state.currentSequence)}</p>`;
769
+ els.screen.firstElementChild.appendChild(div);
770
+ }
771
+
772
+ function showReport() {
773
+ clearInterval(state.timerInterval);
774
+ els.startBtn.disabled = false;
775
+ els.nextBtn.disabled = true;
776
+ els.nextBtn.textContent = "Next Round";
777
+
778
+ const accuracy = state.attempts ? Math.round((state.correct / state.attempts) * 100) : 0;
779
+ const avgTime = state.responseTimes.length
780
+ ? state.responseTimes.reduce((a, b) => a + b, 0) / state.responseTimes.length
781
+ : 0;
782
+
783
+ const memory = accuracy;
784
+ const attention = Math.round(calculateAttentionScore());
785
+ const speed = Math.round(calculateSpeedScore());
786
+ const learning = Math.round(calculateLearningTrend());
787
+
788
+ let recommendation = "Balanced performance. Use this as one signal, not a final hiring decision.";
789
+ if (memory >= 80 && speed >= 70) recommendation = "Strong pattern recognition and fast decision-making under time pressure.";
790
+ if (memory < 60 && learning >= 60) recommendation = "Early misses improved over time, suggesting coachability and learning adaptation.";
791
+ if (memory < 50) recommendation = "May need additional job-relevant assessment before drawing conclusions.";
792
+
793
+ els.screen.innerHTML = `
794
+ <div class="report">
795
+ <h2>Candidate Assessment Report</h2>
796
+ <div class="report-card"><strong>Total Score:</strong> ${state.score}</div>
797
+ <div class="report-card"><strong>Accuracy:</strong> ${accuracy}% (${state.correct}/${state.attempts} correct)</div>
798
+ <div class="report-card"><strong>Average Response Time:</strong> ${avgTime.toFixed(2)} seconds</div>
799
+ <div class="report-card"><strong>Working Memory:</strong> ${memory}%</div>
800
+ <div class="report-card"><strong>Attention Under Difficulty:</strong> ${attention}%</div>
801
+ <div class="report-card"><strong>Decision Speed:</strong> ${speed}%</div>
802
+ <div class="report-card"><strong>Learning Trend:</strong> ${learning}%</div>
803
+ <div class="report-card"><strong>Interpretation:</strong> ${recommendation}</div>
804
+ <div class="report-card"><strong>Fairness Note:</strong> This game should only support hiring decisions when combined with human review, job-relevant tasks, accessibility options, and bias monitoring.</div>
805
+ </div>
806
+ `;
807
+
808
+ setFeedback("Game complete. Review the assessment report.", "good");
809
+ updateStats();
810
+ }
811
+
812
+ function resetGame(showStartScreen = true) {
813
+ clearInterval(state.timerInterval);
814
+ state.round = 0;
815
+ state.score = 0;
816
+ state.correct = 0;
817
+ state.attempts = 0;
818
+ state.currentSequence = [];
819
+ state.roundStartTime = null;
820
+ state.responseTimes = [];
821
+ state.history = [];
822
+ state.acceptingAnswer = false;
823
+
824
+ els.startBtn.disabled = false;
825
+ els.nextBtn.disabled = true;
826
+ els.nextBtn.textContent = "Next Round";
827
+ els.timerValue.textContent = "--";
828
+ els.history.innerHTML = "";
829
+
830
+ if (showStartScreen) {
831
+ els.screen.innerHTML = `
832
+ <div>
833
+ <h2>Ready?</h2>
834
+ <p>You will see a short color pattern. Memorize it before it disappears.</p>
835
+ <p>Then choose the matching sequence as quickly and accurately as possible.</p>
836
+ </div>
837
+ `;
838
+ setFeedback("Press Start to begin.", "neutral");
839
+ }
840
+
841
+ updateStats();
842
+ }
843
+
844
+ els.startBtn.addEventListener("click", startGame);
845
+ els.nextBtn.addEventListener("click", nextRound);
846
+ els.resetBtn.addEventListener("click", () => resetGame(true));
847
+
848
+ resetGame(true);
849
+ </script>
850
+ </body>
851
+ </html>