Spaces:
Runtime error
Runtime error
Delete static/index.html
Browse files- static/index.html +0 -281
static/index.html
DELETED
|
@@ -1,281 +0,0 @@
|
|
| 1 |
-
<!DOCTYPE html>
|
| 2 |
-
<html>
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="utf-8">
|
| 5 |
-
<title>Enhanced 3D Solar System</title>
|
| 6 |
-
<style>
|
| 7 |
-
body { margin: 0; overflow: hidden; }
|
| 8 |
-
#info { position: absolute; top: 10px; left: 10px; color: white; background: rgba(0,0,0,0.5); padding: 10px; font-family: Arial, sans-serif; border-radius: 5px; z-index: 100; }
|
| 9 |
-
#panel { position: absolute; top: 10px; right: 10px; background: rgba(0,0,0,0.8); color: #fff; padding: 15px; border-radius: 10px; min-width: 220px; z-index: 200; display: none; }
|
| 10 |
-
#panel h2 { margin-top: 0; }
|
| 11 |
-
#closePanel { float: right; cursor: pointer; color: #fff; font-size: 18px; }
|
| 12 |
-
#ai-chat { position: absolute; bottom: 10px; right: 10px; color: white; background: rgba(0,0,0,0.7); padding: 10px; font-family: Arial, sans-serif; border-radius: 5px; max-width: 300px; z-index: 100; }
|
| 13 |
-
#loading { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; background: rgba(0,0,0,0.7); padding: 20px; border-radius: 10px; font-family: Arial, sans-serif; display: none; z-index: 1000; }
|
| 14 |
-
button { background: #444; color: white; border: none; padding: 5px 10px; margin: 5px 0; cursor: pointer; border-radius: 3px; }
|
| 15 |
-
button:hover { background: #666; }
|
| 16 |
-
input { padding: 5px; margin: 5px 0; width: 100%; }
|
| 17 |
-
#ai-response { margin-top: 10px; max-height: 200px; overflow-y: auto; }
|
| 18 |
-
</style>
|
| 19 |
-
</head>
|
| 20 |
-
<body>
|
| 21 |
-
<div id="info">Click a planet to learn more!</div>
|
| 22 |
-
<div id="panel"><span id="closePanel">×</span><h2 id="panel-title"></h2><div id="panel-content"></div></div>
|
| 23 |
-
<div id="ai-chat">
|
| 24 |
-
<h3>Ask the AI about the Solar System</h3>
|
| 25 |
-
<input id="ai-question" type="text" placeholder="Your question...">
|
| 26 |
-
<button id="ai-submit">Ask</button>
|
| 27 |
-
<div id="ai-response"></div>
|
| 28 |
-
</div>
|
| 29 |
-
<div id="loading">Loading...</div>
|
| 30 |
-
<script src="https://cdn.jsdelivr.net/npm/three@0.152.2/build/three.min.js"></script>
|
| 31 |
-
<script src="https://cdn.jsdelivr.net/npm/three@0.152.2/examples/js/controls/OrbitControls.js"></script>
|
| 32 |
-
<script src="https://cdn.jsdelivr.net/npm/three@0.152.2/examples/js/renderers/CSS2DRenderer.js"></script>
|
| 33 |
-
<script>
|
| 34 |
-
// --- Three.js Solar System with enhancements ---
|
| 35 |
-
const scene = new THREE.Scene();
|
| 36 |
-
scene.background = new THREE.Color(0x000010);
|
| 37 |
-
|
| 38 |
-
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
|
| 39 |
-
camera.position.set(0, 30, 70);
|
| 40 |
-
|
| 41 |
-
const renderer = new THREE.WebGLRenderer({ antialias: true });
|
| 42 |
-
renderer.setSize(window.innerWidth, window.innerHeight);
|
| 43 |
-
document.body.appendChild(renderer.domElement);
|
| 44 |
-
|
| 45 |
-
// CSS2DRenderer for labels
|
| 46 |
-
const labelRenderer = new THREE.CSS2DRenderer();
|
| 47 |
-
labelRenderer.setSize(window.innerWidth, window.innerHeight);
|
| 48 |
-
labelRenderer.domElement.style.position = 'absolute';
|
| 49 |
-
labelRenderer.domElement.style.top = '0px';
|
| 50 |
-
labelRenderer.domElement.style.pointerEvents = 'none';
|
| 51 |
-
document.body.appendChild(labelRenderer.domElement);
|
| 52 |
-
|
| 53 |
-
// Controls
|
| 54 |
-
const controls = new THREE.OrbitControls(camera, renderer.domElement);
|
| 55 |
-
|
| 56 |
-
// Lighting
|
| 57 |
-
scene.add(new THREE.AmbientLight(0x404040));
|
| 58 |
-
const sunLight = new THREE.PointLight(0xffffaa, 2, 200);
|
| 59 |
-
scene.add(sunLight);
|
| 60 |
-
|
| 61 |
-
// Textures (remote URLs)
|
| 62 |
-
const textures = {
|
| 63 |
-
"Sun": "https://www.solarsystemscope.com/textures/download/2k_sun.jpg",
|
| 64 |
-
"Mercury": "https://www.solarsystemscope.com/textures/download/2k_mercury.jpg",
|
| 65 |
-
"Venus": "https://www.solarsystemscope.com/textures/download/2k_venus_surface.jpg",
|
| 66 |
-
"Earth": "https://www.solarsystemscope.com/textures/download/2k_earth_daymap.jpg",
|
| 67 |
-
"Moon": "https://www.solarsystemscope.com/textures/download/2k_moon.jpg",
|
| 68 |
-
"Mars": "https://www.solarsystemscope.com/textures/download/2k_mars.jpg",
|
| 69 |
-
"Jupiter": "https://www.solarsystemscope.com/textures/download/2k_jupiter.jpg",
|
| 70 |
-
"Saturn": "https://www.solarsystemscope.com/textures/download/2k_saturn.jpg",
|
| 71 |
-
"Uranus": "https://www.solarsystemscope.com/textures/download/2k_uranus.jpg",
|
| 72 |
-
"Neptune": "https://www.solarsystemscope.com/textures/download/2k_neptune.jpg"
|
| 73 |
-
};
|
| 74 |
-
|
| 75 |
-
// Planets and moons
|
| 76 |
-
const planets = [
|
| 77 |
-
{ name: "Mercury", radius: 0.8, distance: 10, speed: 0.04, moons: [] },
|
| 78 |
-
{ name: "Venus", radius: 1.2, distance: 15, speed: 0.03, moons: [] },
|
| 79 |
-
{
|
| 80 |
-
name: "Earth", radius: 1.2, distance: 20, speed: 0.02,
|
| 81 |
-
moons: [{ name: "Moon", radius: 0.3, distance: 2, speed: 0.05 }]
|
| 82 |
-
},
|
| 83 |
-
{ name: "Mars", radius: 0.9, distance: 25, speed: 0.015, moons: [] },
|
| 84 |
-
{
|
| 85 |
-
name: "Jupiter", radius: 2.5, distance: 35, speed: 0.01,
|
| 86 |
-
moons: [{ name: "Europa", radius: 0.2, distance: 4, speed: 0.04 }]
|
| 87 |
-
},
|
| 88 |
-
{
|
| 89 |
-
name: "Saturn", radius: 2.2, distance: 45, speed: 0.008, rings: true, moons: []
|
| 90 |
-
},
|
| 91 |
-
{ name: "Uranus", radius: 1.8, distance: 55, speed: 0.005, moons: [] },
|
| 92 |
-
{ name: "Neptune", radius: 1.8, distance: 65, speed: 0.003, moons: [] }
|
| 93 |
-
];
|
| 94 |
-
|
| 95 |
-
// Asteroid belt
|
| 96 |
-
for (let i = 0; i < 200; i++) {
|
| 97 |
-
const beltGeometry = new THREE.SphereGeometry(0.1, 8, 8);
|
| 98 |
-
const beltMaterial = new THREE.MeshPhongMaterial({ color: 0x888888 });
|
| 99 |
-
const beltMesh = new THREE.Mesh(beltGeometry, beltMaterial);
|
| 100 |
-
const angle = Math.random() * Math.PI * 2;
|
| 101 |
-
const distance = 28 + Math.random() * 4;
|
| 102 |
-
beltMesh.position.x = Math.cos(angle) * distance;
|
| 103 |
-
beltMesh.position.z = Math.sin(angle) * distance;
|
| 104 |
-
beltMesh.position.y = (Math.random() - 0.5) * 0.5;
|
| 105 |
-
scene.add(beltMesh);
|
| 106 |
-
}
|
| 107 |
-
|
| 108 |
-
// Sun
|
| 109 |
-
const sunTexture = new THREE.TextureLoader().load(textures["Sun"]);
|
| 110 |
-
const sunGeometry = new THREE.SphereGeometry(4, 64, 64);
|
| 111 |
-
const sunMaterial = new THREE.MeshBasicMaterial({ map: sunTexture });
|
| 112 |
-
const sun = new THREE.Mesh(sunGeometry, sunMaterial);
|
| 113 |
-
scene.add(sun);
|
| 114 |
-
sunLight.position.copy(sun.position);
|
| 115 |
-
addLabel(sun, "Sun");
|
| 116 |
-
|
| 117 |
-
// Create planets, moons, rings, orbits
|
| 118 |
-
const planetObjects = [];
|
| 119 |
-
const clickableObjects = [];
|
| 120 |
-
planets.forEach((planet) => {
|
| 121 |
-
const texture = textures[planet.name] ? new THREE.TextureLoader().load(textures[planet.name]) : null;
|
| 122 |
-
const geometry = new THREE.SphereGeometry(planet.radius, 32, 32);
|
| 123 |
-
const material = texture ? new THREE.MeshPhongMaterial({ map: texture }) : new THREE.MeshPhongMaterial({ color: 0xffffff });
|
| 124 |
-
const mesh = new THREE.Mesh(geometry, material);
|
| 125 |
-
mesh.position.x = planet.distance;
|
| 126 |
-
mesh.userData = { type: 'planet', name: planet.name };
|
| 127 |
-
scene.add(mesh);
|
| 128 |
-
clickableObjects.push(mesh);
|
| 129 |
-
addLabel(mesh, planet.name);
|
| 130 |
-
|
| 131 |
-
// Saturn's rings
|
| 132 |
-
if (planet.rings) {
|
| 133 |
-
const ringGeometry = new THREE.RingGeometry(planet.radius * 1.5, planet.radius * 2.2, 64);
|
| 134 |
-
const ringMaterial = new THREE.MeshPhongMaterial({ color: 0xe9e5c6, side: THREE.DoubleSide, transparent: true, opacity: 0.7 });
|
| 135 |
-
const ring = new THREE.Mesh(ringGeometry, ringMaterial);
|
| 136 |
-
ring.rotation.x = Math.PI / 2;
|
| 137 |
-
mesh.add(ring);
|
| 138 |
-
}
|
| 139 |
-
|
| 140 |
-
// Moons
|
| 141 |
-
const planetMoons = [];
|
| 142 |
-
if (planet.moons && planet.moons.length > 0) {
|
| 143 |
-
planet.moons.forEach(moon => {
|
| 144 |
-
const moonGeometry = new THREE.SphereGeometry(moon.radius, 16, 16);
|
| 145 |
-
const moonMaterial = new THREE.MeshPhongMaterial({ color: 0xcccccc });
|
| 146 |
-
const moonMesh = new THREE.Mesh(moonGeometry, moonMaterial);
|
| 147 |
-
moonMesh.position.x = moon.distance;
|
| 148 |
-
moonMesh.userData = { type: 'moon', name: moon.name, parent: planet.name };
|
| 149 |
-
mesh.add(moonMesh);
|
| 150 |
-
planetMoons.push({ mesh: moonMesh, ...moon });
|
| 151 |
-
addLabel(moonMesh, moon.name);
|
| 152 |
-
clickableObjects.push(moonMesh);
|
| 153 |
-
});
|
| 154 |
-
}
|
| 155 |
-
|
| 156 |
-
// Orbit path
|
| 157 |
-
const orbitGeometry = new THREE.BufferGeometry();
|
| 158 |
-
const points = [];
|
| 159 |
-
const segments = 64;
|
| 160 |
-
for (let i = 0; i <= segments; i++) {
|
| 161 |
-
const theta = (i / segments) * Math.PI * 2;
|
| 162 |
-
points.push(new THREE.Vector3(
|
| 163 |
-
Math.cos(theta) * planet.distance,
|
| 164 |
-
0,
|
| 165 |
-
Math.sin(theta) * planet.distance
|
| 166 |
-
));
|
| 167 |
-
}
|
| 168 |
-
orbitGeometry.setFromPoints(points);
|
| 169 |
-
const orbitMaterial = new THREE.LineBasicMaterial({ color: 0xaaaaaa, transparent: true, opacity: 0.4 });
|
| 170 |
-
const orbit = new THREE.Line(orbitGeometry, orbitMaterial);
|
| 171 |
-
scene.add(orbit);
|
| 172 |
-
|
| 173 |
-
planetObjects.push({ mesh, ...planet, moons: planetMoons });
|
| 174 |
-
});
|
| 175 |
-
|
| 176 |
-
// Add labels
|
| 177 |
-
function addLabel(object, name) {
|
| 178 |
-
const div = document.createElement('div');
|
| 179 |
-
div.className = 'label';
|
| 180 |
-
div.textContent = name;
|
| 181 |
-
div.style.color = '#fff';
|
| 182 |
-
div.style.fontSize = '14px';
|
| 183 |
-
div.style.textShadow = '0 0 5px #000';
|
| 184 |
-
const label = new THREE.CSS2DObject(div);
|
| 185 |
-
label.position.set(0, object.geometry.parameters.radius + 0.6, 0);
|
| 186 |
-
object.add(label);
|
| 187 |
-
}
|
| 188 |
-
|
| 189 |
-
// Raycaster for click events
|
| 190 |
-
const raycaster = new THREE.Raycaster();
|
| 191 |
-
const mouse = new THREE.Vector2();
|
| 192 |
-
|
| 193 |
-
window.addEventListener('click', (event) => {
|
| 194 |
-
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
|
| 195 |
-
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
|
| 196 |
-
raycaster.setFromCamera(mouse, camera);
|
| 197 |
-
const intersects = raycaster.intersectObjects(clickableObjects, true);
|
| 198 |
-
if (intersects.length > 0) {
|
| 199 |
-
const obj = intersects[0].object;
|
| 200 |
-
showPanel(obj.userData);
|
| 201 |
-
}
|
| 202 |
-
});
|
| 203 |
-
|
| 204 |
-
// Info panel logic
|
| 205 |
-
function showPanel(data) {
|
| 206 |
-
const panel = document.getElementById('panel');
|
| 207 |
-
const title = document.getElementById('panel-title');
|
| 208 |
-
const content = document.getElementById('panel-content');
|
| 209 |
-
panel.style.display = 'block';
|
| 210 |
-
title.textContent = data.name;
|
| 211 |
-
content.innerHTML = "Loading info...";
|
| 212 |
-
// Example: fetch Wikipedia summary (or use your AI backend)
|
| 213 |
-
fetch(`https://en.wikipedia.org/api/rest_v1/page/summary/${encodeURIComponent(data.name)}`)
|
| 214 |
-
.then(res => res.json())
|
| 215 |
-
.then(info => {
|
| 216 |
-
content.innerHTML = info.extract_html || "No info found.";
|
| 217 |
-
})
|
| 218 |
-
.catch(() => {
|
| 219 |
-
content.innerHTML = "No info found.";
|
| 220 |
-
});
|
| 221 |
-
}
|
| 222 |
-
document.getElementById('closePanel').onclick = () => {
|
| 223 |
-
document.getElementById('panel').style.display = 'none';
|
| 224 |
-
};
|
| 225 |
-
|
| 226 |
-
// Animation loop
|
| 227 |
-
let angle = 0;
|
| 228 |
-
function animate() {
|
| 229 |
-
requestAnimationFrame(animate);
|
| 230 |
-
controls.update();
|
| 231 |
-
angle += 0.005;
|
| 232 |
-
planetObjects.forEach((planet) => {
|
| 233 |
-
planet.mesh.position.x = Math.cos(angle * planet.speed) * planet.distance;
|
| 234 |
-
planet.mesh.position.z = Math.sin(angle * planet.speed) * planet.distance;
|
| 235 |
-
if (planet.moons) {
|
| 236 |
-
planet.moons.forEach((moon) => {
|
| 237 |
-
moon.mesh.position.x = Math.cos(angle * moon.speed) * moon.distance;
|
| 238 |
-
moon.mesh.position.z = Math.sin(angle * moon.speed) * moon.distance;
|
| 239 |
-
});
|
| 240 |
-
}
|
| 241 |
-
});
|
| 242 |
-
renderer.render(scene, camera);
|
| 243 |
-
labelRenderer.render(scene, camera);
|
| 244 |
-
}
|
| 245 |
-
animate();
|
| 246 |
-
|
| 247 |
-
// Responsive resize
|
| 248 |
-
window.addEventListener('resize', () => {
|
| 249 |
-
camera.aspect = window.innerWidth / window.innerHeight;
|
| 250 |
-
camera.updateProjectionMatrix();
|
| 251 |
-
renderer.setSize(window.innerWidth, window.innerHeight);
|
| 252 |
-
labelRenderer.setSize(window.innerWidth, window.innerHeight);
|
| 253 |
-
});
|
| 254 |
-
|
| 255 |
-
// --- AI Chat Integration ---
|
| 256 |
-
document.getElementById('ai-submit').addEventListener('click', async () => {
|
| 257 |
-
const question = document.getElementById('ai-question').value;
|
| 258 |
-
const responseDiv = document.getElementById('ai-response');
|
| 259 |
-
const loadingDiv = document.getElementById('loading');
|
| 260 |
-
responseDiv.textContent = "";
|
| 261 |
-
loadingDiv.style.display = "block";
|
| 262 |
-
try {
|
| 263 |
-
const resp = await fetch("/api/ask", {
|
| 264 |
-
method: "POST",
|
| 265 |
-
headers: { "Content-Type": "application/json" },
|
| 266 |
-
body: JSON.stringify({ question })
|
| 267 |
-
});
|
| 268 |
-
const data = await resp.json();
|
| 269 |
-
if (data.answer) {
|
| 270 |
-
responseDiv.textContent = "AI: " + data.answer;
|
| 271 |
-
} else {
|
| 272 |
-
responseDiv.textContent = "Error: " + (data.error || "Unknown error.");
|
| 273 |
-
}
|
| 274 |
-
} catch (error) {
|
| 275 |
-
responseDiv.textContent = "Error: Could not connect to AI.";
|
| 276 |
-
}
|
| 277 |
-
loadingDiv.style.display = "none";
|
| 278 |
-
});
|
| 279 |
-
</script>
|
| 280 |
-
</body>
|
| 281 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|