Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>GPT-4 Emergence Quiz - Hyper-Enhanced</title> | |
<style> | |
body { | |
margin: 0; | |
overflow: hidden; | |
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; | |
background: #000; /* Darker background for bloom */ | |
color: #fff; | |
} | |
canvas { | |
display: block; | |
} | |
#ui-container { | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
pointer-events: none; /* Let clicks pass through to the canvas */ | |
} | |
#questionBox, #feedback { | |
pointer-events: auto; /* Allow interaction with these elements */ | |
} | |
#questionBox { | |
position: absolute; | |
top: 20px; | |
left: 50%; | |
transform: translateX(-50%); | |
background: rgba(0,0,0,0.75); | |
padding: 15px 30px; | |
border-radius: 12px; | |
border: 1px solid rgba(255, 255, 255, 0.2); | |
max-width: 85%; | |
text-align: center; | |
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.5); | |
backdrop-filter: blur(8px); | |
} | |
#questionBox h3 { margin-top: 0; color: #4fc3f7; } | |
#questionBox ul { list-style: none; padding: 0; text-align: left; display: inline-block; } | |
#questionBox li { margin-bottom: 8px; font-size: 1.1em; } | |
#questionBox b { | |
display: inline-block; | |
width: 25px; | |
text-shadow: 0 0 5px currentColor; | |
} | |
#feedback { | |
position: absolute; | |
bottom: 20px; | |
left: 50%; | |
transform: translateX(-50%); | |
background: rgba(0,0,0,0.75); | |
padding: 10px 20px; | |
border-radius: 8px; | |
font-size: 1.2em; | |
font-weight: bold; | |
border: 1px solid rgba(255, 255, 255, 0.2); | |
} | |
</style> | |
</head> | |
<body> | |
<div id="ui-container"> | |
<div id="questionBox"></div> | |
<div id="feedback"></div> | |
</div> | |
<script type="importmap"> | |
{ | |
"imports": { | |
"three": "https://unpkg.com/three@0.157.0/build/three.module.js", | |
"three/addons/": "https://unpkg.com/three@0.157.0/examples/jsm/" | |
} | |
} | |
</script> | |
<script type="module"> | |
import * as THREE from 'three'; | |
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js'; | |
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js'; | |
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js'; | |
// --- Quiz Data --- | |
const questions = [ | |
{ text: "GPT-4 breaks down a complex problem into multiple reasoning paths...", options: ["Tree-of-Thought (ToT)", "ReAct Prompting", "Reflexive Dialogue", "Implicit Memory Simulation"], correct: 0 }, | |
{ text: "GPT-4 responds by alternating between thinking and acting...", options: ["Tree-of-Thought (ToT)", "ReAct Prompting", "Reflexive Dialogue", "Implicit Memory Simulation"], correct: 1 }, | |
{ text: "GPT-4 engages in a back-and-forth with itself to refine responses.", options: ["Tree-of-Thought (ToT)", "ReAct Prompting", "Reflexive Dialogue", "Implicit Memory Simulation"], correct: 2 }, | |
{ text: "GPT-4 'remembers' prior interactions naturally without explicit repeats.", options: ["Tree-of-Thought (ToT)", "ReAct Prompting", "Reflexive Dialogue", "Implicit Memory Simulation"], correct: 3 } | |
]; | |
let currentQuestionIndex = 0; | |
let isTransitioning = false; | |
// --- UI & Audio --- | |
const questionBox = document.getElementById('questionBox'); | |
const feedbackBox = document.getElementById('feedback'); | |
const audio = { | |
hover: new Audio('https://cdn.pixabay.com/audio/2022/11/21/audio_a721674937.mp3'), | |
click: new Audio('https://cdn.pixabay.com/audio/2022/03/15/audio_73ed20145c.mp3'), | |
correct: new Audio('https://cdn.pixabay.com/audio/2022/01/21/audio_816633f81d.mp3'), | |
wrong: new Audio('https://cdn.pixabay.com/audio/2021/08/04/audio_c89b3f4f71.mp3') | |
}; | |
Object.values(audio).forEach(a => a.volume = 0.5); | |
// --- Three.js Setup --- | |
const scene = new THREE.Scene(); | |
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 100); | |
// *** MODIFIED: Camera is lower and closer *** | |
camera.position.set(0, 1.5, 7.5); | |
camera.lookAt(0, 0, 0); | |
const renderer = new THREE.WebGLRenderer({ antialias: true }); | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
renderer.setPixelRatio(window.devicePixelRatio); | |
renderer.shadowMap.enabled = true; | |
renderer.shadowMap.type = THREE.PCFSoftShadowMap; | |
renderer.toneMapping = THREE.ReinhardToneMapping; | |
document.body.appendChild(renderer.domElement); | |
// --- Post-Processing (Bloom Effect) --- | |
const renderScene = new RenderPass(scene, camera); | |
const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.2, 0.4, 0.85); | |
const composer = new EffectComposer(renderer); | |
composer.addPass(renderScene); | |
composer.addPass(bloomPass); | |
// --- Lighting --- | |
scene.add(new THREE.AmbientLight(0xffffff, 0.3)); | |
const dirLight = new THREE.DirectionalLight(0xffffff, 1.5); | |
dirLight.position.set(5, 5, 5); | |
dirLight.castShadow = true; | |
dirLight.shadow.mapSize.width = 1024; | |
dirLight.shadow.mapSize.height = 1024; | |
scene.add(dirLight); | |
// --- Helper to create letter textures --- | |
function createLetterTexture(letter, textColor, boxColor) { | |
const canvas = document.createElement('canvas'); | |
canvas.width = 256; | |
canvas.height = 256; | |
const context = canvas.getContext('2d'); | |
context.fillStyle = `#${boxColor.getHexString()}`; | |
context.fillRect(0, 0, 256, 256); | |
context.font = 'bold 180px Arial'; | |
context.fillStyle = textColor; | |
context.textAlign = 'center'; | |
context.textBaseline = 'middle'; | |
context.fillText(letter, 128, 128); | |
return new THREE.CanvasTexture(canvas); | |
} | |
// --- Objects --- | |
const cubes = []; | |
const geometry = new THREE.BoxGeometry(1.2, 1.2, 1.2); | |
const colors = [0x66bb6a, 0xffca28, 0x42a5f5, 0xab47bc]; | |
const CUBE_BASE_Y = 0.7; // *** ADDED: A constant for the base height *** | |
for (let i = 0; i < 4; i++) { | |
const color = new THREE.Color(colors[i]); | |
const letter = String.fromCharCode(65 + i); | |
const letterTexture = createLetterTexture(letter, 'rgba(255,255,255,0.9)', color); | |
const materials = [ | |
new THREE.MeshStandardMaterial({ color: color }), | |
new THREE.MeshStandardMaterial({ color: color }), | |
new THREE.MeshStandardMaterial({ color: color }), | |
new THREE.MeshStandardMaterial({ color: color }), | |
new THREE.MeshStandardMaterial({ map: letterTexture, color: color }), | |
new THREE.MeshStandardMaterial({ color: color }) | |
]; | |
const cube = new THREE.Mesh(geometry, materials); | |
// *** MODIFIED: Set a lower Y position *** | |
cube.position.set((i - 1.5) * 2.8, CUBE_BASE_Y, 0); | |
cube.userData.id = i; | |
cube.userData.baseColor = color; | |
cube.userData.spin = 0; | |
cube.castShadow = true; | |
scene.add(cube); | |
cubes.push(cube); | |
} | |
const plane = new THREE.Mesh( | |
new THREE.PlaneGeometry(30, 30), | |
new THREE.MeshStandardMaterial({ color: 0x111111, side: THREE.DoubleSide }) | |
); | |
plane.rotation.x = -Math.PI / 2; | |
plane.receiveShadow = true; | |
scene.add(plane); | |
let activeParticles = []; | |
// --- Interactivity --- | |
const raycaster = new THREE.Raycaster(); | |
const mouse = new THREE.Vector2(); | |
let INTERSECTED; | |
function onPointerMove(event) { | |
mouse.x = (event.clientX / window.innerWidth) * 2 - 1; | |
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; | |
} | |
function onClick() { | |
if (isTransitioning || !INTERSECTED) return; | |
audio.click.currentTime = 0; | |
audio.click.play(); | |
checkAnswer(INTERSECTED.userData.id); | |
} | |
window.addEventListener('pointermove', onPointerMove); | |
window.addEventListener('click', onClick); | |
// --- Game Logic --- | |
function loadQuestion() { | |
isTransitioning = false; | |
if (currentQuestionIndex >= questions.length) { | |
questionBox.innerHTML = `<h2>Quiz Complete!</h2>`; | |
feedbackBox.innerHTML = 'Excellent work!'; | |
cubes.forEach((cube, i) => setTimeout(() => cube.visible = false, i * 100)); | |
return; | |
} | |
const q = questions[currentQuestionIndex]; | |
questionBox.innerHTML = `<h3>Question ${currentQuestionIndex + 1}:</h3><p>${q.text}</p><ul>${ | |
q.options.map((opt, i) => `<li style="color:#${colors[i].toString(16)}"><b style="color:#${colors[i].toString(16)}">${String.fromCharCode(65 + i)}:</b> ${opt}</li>`).join('') | |
}</ul>`; | |
feedbackBox.innerHTML = '<p>Select the correct concept</p>'; | |
} | |
function checkAnswer(selectedIndex) { | |
isTransitioning = true; | |
const q = questions[currentQuestionIndex]; | |
const correct = q.correct === selectedIndex; | |
feedbackBox.innerHTML = correct | |
? `<p style="color: #8BC34A;">Correct!</p>` | |
: `<p style="color: #E57373;">Incorrect. The answer was ${String.fromCharCode(65 + q.correct)}.</p>`; | |
const sound = correct ? audio.correct : audio.wrong; | |
sound.currentTime = 0; | |
sound.play(); | |
const cube = cubes[selectedIndex]; | |
cube.userData.spin += Math.PI * 2; | |
createParticleEffect(cube.position, correct ? 0x8BC34A : 0xE57373); | |
currentQuestionIndex++; | |
setTimeout(loadQuestion, 2500); | |
} | |
function createParticleEffect(position, color) { | |
const particleCount = 200; | |
const particles = new THREE.BufferGeometry(); | |
const posArray = new Float32Array(particleCount * 3); | |
const velArray = new Float32Array(particleCount * 3); | |
for (let i = 0; i < particleCount * 3; i+=3) { | |
posArray[i] = position.x; | |
posArray[i+1] = position.y; | |
posArray[i+2] = position.z; | |
velArray[i] = (Math.random() - 0.5) * 4; | |
velArray[i+1] = (Math.random() - 0.5) * 4 + 2; | |
velArray[i+2] = (Math.random() - 0.5) * 4; | |
} | |
particles.setAttribute('position', new THREE.BufferAttribute(posArray, 3)); | |
const material = new THREE.PointsMaterial({ size: 0.1, color: color, transparent: true, blending: THREE.AdditiveBlending, depthWrite: false }); | |
const particleSystem = new THREE.Points(particles, material); | |
particleSystem.userData.velocities = velArray; | |
particleSystem.userData.lifetime = 0; | |
scene.add(particleSystem); | |
activeParticles.push(particleSystem); | |
} | |
loadQuestion(); | |
// --- Render Loop --- | |
const clock = new THREE.Clock(); | |
function animate() { | |
requestAnimationFrame(animate); | |
const elapsedTime = clock.getElapsedTime(); | |
const deltaTime = clock.getDelta(); | |
// *** MODIFIED: Replaced orbit with a subtle dolly zoom *** | |
camera.position.z = 7.5 + Math.sin(elapsedTime * 0.2) * 0.5; | |
camera.lookAt(0, 0, 0); | |
cubes.forEach(cube => { | |
if (cube.userData.spin > 0) { | |
const spinAmount = Math.min(cube.userData.spin, deltaTime * 15); | |
cube.rotation.y += spinAmount; | |
cube.userData.spin -= spinAmount; | |
} else { | |
cube.rotation.y += deltaTime * 0.3; | |
} | |
// *** MODIFIED: Use the new base Y position for bobbing animation *** | |
cube.position.y = CUBE_BASE_Y + Math.sin(elapsedTime * 1.5 + cube.userData.id * 2) * 0.15; | |
}); | |
// Particle animation | |
activeParticles.forEach((system, index) => { | |
const positions = system.geometry.attributes.position; | |
const velocities = system.userData.velocities; | |
system.userData.lifetime += deltaTime; | |
for (let i = 0; i < positions.count; i++) { | |
velocities[i*3+1] -= 9.8 * deltaTime * 0.2; | |
positions.array[i*3] += velocities[i*3] * deltaTime; | |
positions.array[i*3+1] += velocities[i*3+1] * deltaTime; | |
positions.array[i*3+2] += velocities[i*3+2] * deltaTime; | |
} | |
positions.needsUpdate = true; | |
system.material.opacity = Math.max(0, 1.0 - system.userData.lifetime / 1.5); | |
if (system.userData.lifetime > 1.5) { | |
scene.remove(system); | |
system.geometry.dispose(); | |
system.material.dispose(); | |
activeParticles.splice(index, 1); | |
} | |
}); | |
raycaster.setFromCamera(mouse, camera); | |
const intersects = raycaster.intersectObjects(cubes); | |
if (intersects.length > 0 && !isTransitioning) { | |
if (INTERSECTED != intersects[0].object) { | |
if (INTERSECTED) INTERSECTED.scale.set(1, 1, 1); | |
INTERSECTED = intersects[0].object; | |
INTERSECTED.scale.set(1.1, 1.1, 1.1); | |
audio.hover.currentTime = 0; | |
audio.hover.play(); | |
} | |
} else { | |
if (INTERSECTED) INTERSECTED.scale.set(1, 1, 1); | |
INTERSECTED = null; | |
} | |
composer.render(); | |
} | |
animate(); | |
// --- Resize Handler --- | |
window.addEventListener('resize', () => { | |
camera.aspect = window.innerWidth / window.innerHeight; | |
camera.updateProjectionMatrix(); | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
composer.setSize(window.innerWidth, window.innerHeight); | |
}); | |
</script> | |
</body> | |
</html> |