synthos 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/synthos.js +2 -2
- package/default-pages/[application].html +94 -86
- package/default-pages/[markdown].html +270 -260
- package/default-pages/[sidebar].html +67 -42
- package/default-pages/[split-application].html +55 -70
- package/default-pages/json_tools.html +113 -130
- package/default-pages/solar_system.html +432 -0
- package/default-pages/space_invaders.html +617 -0
- package/default-scripts/windows-terminal.json +6 -6
- package/dist/service/createCompletePrompt.d.ts.map +1 -1
- package/dist/service/createCompletePrompt.js +6 -5
- package/dist/service/createCompletePrompt.js.map +1 -1
- package/package.json +1 -1
- package/required-pages/apis.html +361 -346
- package/required-pages/home.html +69 -26
- package/required-pages/pages.html +152 -134
- package/required-pages/scripts.html +349 -334
- package/required-pages/settings.html +184 -157
- package/src/service/createCompletePrompt.ts +6 -5
- package/src/settings.ts +1 -1
|
@@ -0,0 +1,432 @@
|
|
|
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>SynthOS</title>
|
|
7
|
+
<style>
|
|
8
|
+
/* Nebula Dusk Theme */
|
|
9
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
10
|
+
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f0f23 100%); color: #e0e0e0; height: 100vh; display: flex; }
|
|
11
|
+
.chat-panel { width: 30%; background: linear-gradient(180deg, rgba(26,26,46,0.95) 0%, rgba(22,33,62,0.95) 100%); box-shadow: 0 0 30px rgba(138,43,226,0.2), inset 0 0 60px rgba(75,0,130,0.1); padding: 20px; display: flex; flex-direction: column; border-right: 1px solid rgba(138,43,226,0.3); }
|
|
12
|
+
.chat-header { font-size: 24px; padding: 15px; background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); color: #fff; text-align: center; border-radius: 15px; box-shadow: 0 4px 20px rgba(102,126,234,0.4); text-shadow: 0 2px 10px rgba(0,0,0,0.3); letter-spacing: 2px; }
|
|
13
|
+
.chat-messages { flex-grow: 1; overflow-y: auto; padding: 15px; margin-top: 15px; background: rgba(15,15,35,0.6); border-radius: 15px; border: 1px solid rgba(138,43,226,0.2); box-shadow: inset 0 0 30px rgba(75,0,130,0.2); }
|
|
14
|
+
.chat-message { margin-bottom: 15px; padding: 12px 15px; background: linear-gradient(135deg, rgba(102,126,234,0.15) 0%, rgba(118,75,162,0.15) 100%); border-radius: 15px; box-shadow: 0 2px 10px rgba(138,43,226,0.2); border: 1px solid rgba(138,43,226,0.1); backdrop-filter: blur(5px); }
|
|
15
|
+
.chat-message p { margin-bottom: 5px; line-height: 1.5; }
|
|
16
|
+
.chat-message p strong { font-weight: 600; background: linear-gradient(90deg, #667eea, #f093fb); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
|
|
17
|
+
.chat-message p code { background: rgba(138,43,226,0.3); padding: 2px 6px; border-radius: 5px; font-family: 'Courier New', Courier, monospace; color: #f093fb; border: 1px solid rgba(240,147,251,0.3); }
|
|
18
|
+
.link-group { display: flex; justify-content: space-between; margin: 15px 0; padding: 10px; background: rgba(15,15,35,0.4); border-radius: 10px; border: 1px solid rgba(138,43,226,0.2); }
|
|
19
|
+
.link-group a { font-size: 14px; color: #b794f6; text-decoration: none; padding: 8px 15px; border-radius: 8px; transition: all 0.3s ease; border: 1px solid transparent; }
|
|
20
|
+
.link-group a:hover { background: linear-gradient(135deg, rgba(102,126,234,0.3) 0%, rgba(118,75,162,0.3) 100%); border-color: rgba(183,148,246,0.5); box-shadow: 0 0 15px rgba(138,43,226,0.3); color: #f093fb; }
|
|
21
|
+
form { display: flex; flex-direction: row; width: 100%; gap: 10px; align-items: center; }
|
|
22
|
+
.chat-input { padding: 14px 18px; border: 1px solid rgba(138,43,226,0.3); border-radius: 25px; flex-grow: 1; font-size: 14px; background: rgba(15,15,35,0.8); color: #e0e0e0; box-shadow: inset 0 2px 10px rgba(0,0,0,0.3), 0 0 20px rgba(138,43,226,0.1); transition: all 0.3s ease; }
|
|
23
|
+
.chat-input:focus { outline: none; border-color: rgba(183,148,246,0.6); box-shadow: inset 0 2px 10px rgba(0,0,0,0.3), 0 0 25px rgba(138,43,226,0.3); }
|
|
24
|
+
.chat-input::placeholder { color: rgba(183,148,246,0.5); }
|
|
25
|
+
.chat-submit { padding: 14px 20px; border: none; border-radius: 25px; font-size: 14px; background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); color: #fff; cursor: pointer; transition: all 0.3s ease; font-weight: 600; letter-spacing: 1px; box-shadow: 0 4px 20px rgba(102,126,234,0.4); white-space: nowrap; }
|
|
26
|
+
.chat-submit:hover { transform: translateY(-2px); box-shadow: 0 6px 25px rgba(102,126,234,0.6); }
|
|
27
|
+
.chat-submit:active { transform: translateY(0); }
|
|
28
|
+
.viewer-panel { width: 70%; padding: 25px; background: linear-gradient(135deg, rgba(22,33,62,0.9) 0%, rgba(15,15,35,0.95) 100%); display: flex; flex-direction: column; justify-content: center; align-items: center; box-shadow: inset 0 0 60px rgba(75,0,130,0.15); position: relative; overflow: hidden; }
|
|
29
|
+
.loading-overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(15,15,35,0.9); justify-content: center; align-items: center; z-index: 1000; }
|
|
30
|
+
.spinner { width: 50px; height: 50px; border: 4px solid rgba(138,43,226,0.3); border-top-color: #f093fb; border-radius: 50%; animation: spin 1s linear infinite; }
|
|
31
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
32
|
+
|
|
33
|
+
/* Scrollbar Styles */
|
|
34
|
+
::-webkit-scrollbar { width: 10px; height: 10px; }
|
|
35
|
+
::-webkit-scrollbar-track { background: rgba(15,15,35,0.6); border-radius: 10px; }
|
|
36
|
+
::-webkit-scrollbar-thumb { background: linear-gradient(180deg, #667eea 0%, #764ba2 50%, #f093fb 100%); border-radius: 10px; border: 2px solid rgba(15,15,35,0.6); box-shadow: 0 0 10px rgba(138,43,226,0.4); }
|
|
37
|
+
::-webkit-scrollbar-thumb:hover { background: linear-gradient(180deg, #f093fb 0%, #764ba2 50%, #667eea 100%); box-shadow: 0 0 15px rgba(240,147,251,0.5); }
|
|
38
|
+
::-webkit-scrollbar-corner { background: rgba(15,15,35,0.6); }
|
|
39
|
+
* { scrollbar-width: thin; scrollbar-color: #764ba2 rgba(15,15,35,0.6); }
|
|
40
|
+
|
|
41
|
+
/* Solar System Styles */
|
|
42
|
+
#solarSystem { width: 100%; height: 100%; position: relative; }
|
|
43
|
+
.controls { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); display: flex; gap: 15px; z-index: 100; background: rgba(15,15,35,0.8); padding: 15px 25px; border-radius: 25px; border: 1px solid rgba(138,43,226,0.3); }
|
|
44
|
+
.controls button { padding: 10px 20px; border: none; border-radius: 15px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #fff; cursor: pointer; font-size: 13px; transition: all 0.3s ease; }
|
|
45
|
+
.controls button:hover { transform: scale(1.05); box-shadow: 0 0 15px rgba(102,126,234,0.5); }
|
|
46
|
+
.controls button.active { background: linear-gradient(135deg, #f093fb 0%, #764ba2 100%); }
|
|
47
|
+
.info-panel { position: absolute; top: 20px; right: 20px; background: rgba(15,15,35,0.9); padding: 20px; border-radius: 15px; border: 1px solid rgba(138,43,226,0.3); max-width: 280px; z-index: 100; }
|
|
48
|
+
.info-panel h3 { color: #f093fb; margin-bottom: 10px; font-size: 18px; }
|
|
49
|
+
.info-panel p { font-size: 13px; line-height: 1.6; color: #b794f6; margin-bottom: 8px; }
|
|
50
|
+
.speed-control { position: absolute; top: 20px; left: 20px; background: rgba(15,15,35,0.9); padding: 15px 20px; border-radius: 15px; border: 1px solid rgba(138,43,226,0.3); z-index: 100; }
|
|
51
|
+
.speed-control label { color: #b794f6; font-size: 13px; display: block; margin-bottom: 8px; }
|
|
52
|
+
.speed-control input[type="range"] { width: 150px; accent-color: #f093fb; }
|
|
53
|
+
.planet-label { font-size: 11px; fill: #b794f6; pointer-events: none; text-anchor: middle; }
|
|
54
|
+
</style>
|
|
55
|
+
</head>
|
|
56
|
+
<body>
|
|
57
|
+
<div class="chat-panel">
|
|
58
|
+
<div class="chat-header">SynthOS</div>
|
|
59
|
+
<div class="chat-messages" id="chatMessages">
|
|
60
|
+
<div class="chat-message"><p><strong>SynthOS:</strong> What can I create for you?</p></div>
|
|
61
|
+
<div class="chat-message"><p><strong>You:</strong> create an accurate animation of the solar system</p></div>
|
|
62
|
+
<div class="chat-message"><p><strong>SynthOS:</strong> I've created an accurate, interactive solar system simulation! Features include: real orbital periods (scaled for visibility), accurate relative planet sizes, elliptical orbits with correct eccentricities, the asteroid belt, and dwarf planet Pluto. Use the controls to adjust speed, toggle orbits, and click planets for info.</p></div>
|
|
63
|
+
</div>
|
|
64
|
+
<div class="link-group">
|
|
65
|
+
<a href="#" id="saveLink">Save</a>
|
|
66
|
+
<a href="/pages" id="pagesLink">Pages</a>
|
|
67
|
+
<a href="#" id="resetLink">Reset</a>
|
|
68
|
+
</div>
|
|
69
|
+
<form action="/" method="POST" id="chatForm">
|
|
70
|
+
<input type="text" class="chat-input" id="chatInput" name="message" placeholder="Type a message...">
|
|
71
|
+
<button type="submit" class="chat-submit">Send</button>
|
|
72
|
+
</form>
|
|
73
|
+
</div>
|
|
74
|
+
<div class="viewer-panel" id="viewerPanel">
|
|
75
|
+
<div id="solarSystem"></div>
|
|
76
|
+
<div class="speed-control">
|
|
77
|
+
<label>Simulation Speed: <span id="speedValue">1x</span></label>
|
|
78
|
+
<input type="range" id="speedSlider" min="0.1" max="10" step="0.1" value="1">
|
|
79
|
+
</div>
|
|
80
|
+
<div class="info-panel" id="infoPanel">
|
|
81
|
+
<h3>Solar System</h3>
|
|
82
|
+
<p>Click on any planet to see detailed information.</p>
|
|
83
|
+
<p>The simulation shows accurate relative orbital periods and distances (scaled for visibility).</p>
|
|
84
|
+
</div>
|
|
85
|
+
<div class="controls">
|
|
86
|
+
<button id="toggleOrbits" class="active">Show Orbits</button>
|
|
87
|
+
<button id="toggleLabels" class="active">Show Labels</button>
|
|
88
|
+
<button id="toggleAsteroids">Show Asteroids</button>
|
|
89
|
+
<button id="resetView">Reset View</button>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
<div id="thoughts" style="display: none;">Created an accurate solar system animation using canvas. Key accuracy features: 1) Real orbital periods relative to Earth (Mercury 0.24 years, Venus 0.62, Mars 1.88, Jupiter 11.86, Saturn 29.46, Uranus 84.01, Neptune 164.8, Pluto 248). 2) Accurate orbital eccentricities for elliptical orbits (Mercury has the most eccentric at 0.206). 3) Relative planet sizes (though scaled up for visibility). 4) Included the asteroid belt between Mars and Jupiter. 5) Added Pluto as a dwarf planet with its highly inclined and eccentric orbit. The simulation is interactive with speed controls, orbit toggles, and clickable planets for information. Used requestAnimationFrame for smooth animation.</div>
|
|
93
|
+
<div id="loadingOverlay" class="loading-overlay"><div class="spinner"></div></div>
|
|
94
|
+
<script>
|
|
95
|
+
document.getElementById("chatInput").focus();
|
|
96
|
+
document.getElementById("chatForm").addEventListener('submit', () => {
|
|
97
|
+
document.getElementById("loadingOverlay").style.display = 'flex';
|
|
98
|
+
document.getElementById("chatForm").action = window.location.pathname;
|
|
99
|
+
});
|
|
100
|
+
document.getElementById("saveLink").addEventListener("click", function() {
|
|
101
|
+
const pageName = prompt("Enter the name of the page to save as:");
|
|
102
|
+
if (pageName) {
|
|
103
|
+
window.location.href = `${window.location.pathname}/save?name=${encodeURIComponent(pageName)}`;
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
document.getElementById("resetLink").addEventListener("click", function() {
|
|
107
|
+
window.location.href = `${window.location.pathname}/reset`;
|
|
108
|
+
});
|
|
109
|
+
window.onload = function() {
|
|
110
|
+
const chatMessages = document.getElementById('chatMessages');
|
|
111
|
+
chatMessages.scrollTo({
|
|
112
|
+
top: chatMessages.scrollHeight,
|
|
113
|
+
behavior: 'smooth'
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Solar System Simulation
|
|
118
|
+
const container = document.getElementById('solarSystem');
|
|
119
|
+
const canvas = document.createElement('canvas');
|
|
120
|
+
const ctx = canvas.getContext('2d');
|
|
121
|
+
container.appendChild(canvas);
|
|
122
|
+
|
|
123
|
+
let width, height, centerX, centerY;
|
|
124
|
+
let simulationSpeed = 1;
|
|
125
|
+
let showOrbits = true;
|
|
126
|
+
let showLabels = true;
|
|
127
|
+
let showAsteroids = false;
|
|
128
|
+
let time = 0;
|
|
129
|
+
|
|
130
|
+
// Planet data with accurate orbital periods (in Earth years) and eccentricities
|
|
131
|
+
const planets = [
|
|
132
|
+
{ name: 'Mercury', color: '#b5b5b5', size: 4, distance: 50, period: 0.24, eccentricity: 0.206, info: 'Smallest planet, closest to Sun. Surface temp: -180°C to 430°C. No moons.' },
|
|
133
|
+
{ name: 'Venus', color: '#e6c87a', size: 6, distance: 75, period: 0.62, eccentricity: 0.007, info: 'Hottest planet due to greenhouse effect. Rotates backwards. No moons.' },
|
|
134
|
+
{ name: 'Earth', color: '#6b93d6', size: 6, distance: 100, period: 1.0, eccentricity: 0.017, info: 'Our home! Only known planet with life. 1 moon (Luna).' },
|
|
135
|
+
{ name: 'Mars', color: '#c1440e', size: 5, distance: 130, period: 1.88, eccentricity: 0.093, info: 'The Red Planet. Has the largest volcano (Olympus Mons). 2 moons.' },
|
|
136
|
+
{ name: 'Jupiter', color: '#d4a574', size: 18, distance: 200, period: 11.86, eccentricity: 0.049, info: 'Largest planet. Great Red Spot is a giant storm. 95 known moons.' },
|
|
137
|
+
{ name: 'Saturn', color: '#f4d59e', size: 15, distance: 270, period: 29.46, eccentricity: 0.057, info: 'Famous for its rings made of ice and rock. 146 known moons.' },
|
|
138
|
+
{ name: 'Uranus', color: '#d1e7e7', size: 10, distance: 330, period: 84.01, eccentricity: 0.046, info: 'Ice giant, rotates on its side. 28 known moons.' },
|
|
139
|
+
{ name: 'Neptune', color: '#5b5ddf', size: 10, distance: 380, period: 164.8, eccentricity: 0.010, info: 'Windiest planet (2,100 km/h). 16 known moons.' },
|
|
140
|
+
{ name: 'Pluto', color: '#a89f91', size: 3, distance: 420, period: 248, eccentricity: 0.249, info: 'Dwarf planet. Has a heart-shaped glacier. 5 known moons.' }
|
|
141
|
+
];
|
|
142
|
+
|
|
143
|
+
// Asteroid belt
|
|
144
|
+
let asteroids = [];
|
|
145
|
+
function generateAsteroids() {
|
|
146
|
+
asteroids = [];
|
|
147
|
+
for (let i = 0; i < 500; i++) {
|
|
148
|
+
asteroids.push({
|
|
149
|
+
distance: 155 + Math.random() * 35,
|
|
150
|
+
angle: Math.random() * Math.PI * 2,
|
|
151
|
+
speed: 0.0005 + Math.random() * 0.001,
|
|
152
|
+
size: 0.5 + Math.random() * 1.5
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
generateAsteroids();
|
|
157
|
+
|
|
158
|
+
function resize() {
|
|
159
|
+
width = container.clientWidth;
|
|
160
|
+
height = container.clientHeight;
|
|
161
|
+
canvas.width = width;
|
|
162
|
+
canvas.height = height;
|
|
163
|
+
centerX = width / 2;
|
|
164
|
+
centerY = height / 2;
|
|
165
|
+
}
|
|
166
|
+
resize();
|
|
167
|
+
window.addEventListener('resize', resize);
|
|
168
|
+
|
|
169
|
+
// Calculate position on elliptical orbit
|
|
170
|
+
function getOrbitalPosition(planet, t) {
|
|
171
|
+
const angularSpeed = (2 * Math.PI) / (planet.period * 365); // radians per day
|
|
172
|
+
const meanAnomaly = angularSpeed * t * simulationSpeed;
|
|
173
|
+
|
|
174
|
+
// Simplified Kepler's equation approximation
|
|
175
|
+
const e = planet.eccentricity;
|
|
176
|
+
const trueAnomaly = meanAnomaly + 2 * e * Math.sin(meanAnomaly);
|
|
177
|
+
|
|
178
|
+
const r = planet.distance * (1 - e * e) / (1 + e * Math.cos(trueAnomaly));
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
x: centerX + r * Math.cos(trueAnomaly),
|
|
182
|
+
y: centerY + r * Math.sin(trueAnomaly),
|
|
183
|
+
angle: trueAnomaly
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Draw elliptical orbit path
|
|
188
|
+
function drawOrbit(planet) {
|
|
189
|
+
ctx.beginPath();
|
|
190
|
+
ctx.strokeStyle = 'rgba(138, 43, 226, 0.2)';
|
|
191
|
+
ctx.lineWidth = 1;
|
|
192
|
+
|
|
193
|
+
const a = planet.distance; // semi-major axis
|
|
194
|
+
const e = planet.eccentricity;
|
|
195
|
+
const b = a * Math.sqrt(1 - e * e); // semi-minor axis
|
|
196
|
+
const c = a * e; // focus offset
|
|
197
|
+
|
|
198
|
+
ctx.ellipse(centerX + c, centerY, a, b, 0, 0, Math.PI * 2);
|
|
199
|
+
ctx.stroke();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Draw the Sun with glow effect
|
|
203
|
+
function drawSun() {
|
|
204
|
+
// Outer glow
|
|
205
|
+
const gradient = ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, 60);
|
|
206
|
+
gradient.addColorStop(0, 'rgba(255, 200, 50, 1)');
|
|
207
|
+
gradient.addColorStop(0.3, 'rgba(255, 150, 0, 0.8)');
|
|
208
|
+
gradient.addColorStop(0.6, 'rgba(255, 100, 0, 0.3)');
|
|
209
|
+
gradient.addColorStop(1, 'rgba(255, 50, 0, 0)');
|
|
210
|
+
|
|
211
|
+
ctx.beginPath();
|
|
212
|
+
ctx.arc(centerX, centerY, 60, 0, Math.PI * 2);
|
|
213
|
+
ctx.fillStyle = gradient;
|
|
214
|
+
ctx.fill();
|
|
215
|
+
|
|
216
|
+
// Sun core
|
|
217
|
+
ctx.beginPath();
|
|
218
|
+
ctx.arc(centerX, centerY, 25, 0, Math.PI * 2);
|
|
219
|
+
ctx.fillStyle = '#fff5c0';
|
|
220
|
+
ctx.fill();
|
|
221
|
+
|
|
222
|
+
// Corona effect
|
|
223
|
+
ctx.beginPath();
|
|
224
|
+
ctx.arc(centerX, centerY, 30, 0, Math.PI * 2);
|
|
225
|
+
ctx.fillStyle = 'rgba(255, 220, 100, 0.5)';
|
|
226
|
+
ctx.fill();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Draw Saturn's rings
|
|
230
|
+
function drawSaturnRings(x, y, size, angle) {
|
|
231
|
+
ctx.save();
|
|
232
|
+
ctx.translate(x, y);
|
|
233
|
+
ctx.rotate(0.4); // Tilt the rings
|
|
234
|
+
|
|
235
|
+
ctx.beginPath();
|
|
236
|
+
ctx.ellipse(0, 0, size * 2.2, size * 0.5, 0, 0, Math.PI * 2);
|
|
237
|
+
ctx.strokeStyle = 'rgba(210, 180, 140, 0.6)';
|
|
238
|
+
ctx.lineWidth = 3;
|
|
239
|
+
ctx.stroke();
|
|
240
|
+
|
|
241
|
+
ctx.beginPath();
|
|
242
|
+
ctx.ellipse(0, 0, size * 1.8, size * 0.4, 0, 0, Math.PI * 2);
|
|
243
|
+
ctx.strokeStyle = 'rgba(180, 150, 120, 0.4)';
|
|
244
|
+
ctx.lineWidth = 2;
|
|
245
|
+
ctx.stroke();
|
|
246
|
+
|
|
247
|
+
ctx.restore();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Draw a planet
|
|
251
|
+
function drawPlanet(planet, pos) {
|
|
252
|
+
// Planet shadow (simple 3D effect)
|
|
253
|
+
ctx.beginPath();
|
|
254
|
+
ctx.arc(pos.x + 2, pos.y + 2, planet.size, 0, Math.PI * 2);
|
|
255
|
+
ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
|
|
256
|
+
ctx.fill();
|
|
257
|
+
|
|
258
|
+
// Planet body
|
|
259
|
+
const gradient = ctx.createRadialGradient(
|
|
260
|
+
pos.x - planet.size * 0.3, pos.y - planet.size * 0.3, 0,
|
|
261
|
+
pos.x, pos.y, planet.size
|
|
262
|
+
);
|
|
263
|
+
gradient.addColorStop(0, lightenColor(planet.color, 30));
|
|
264
|
+
gradient.addColorStop(1, planet.color);
|
|
265
|
+
|
|
266
|
+
ctx.beginPath();
|
|
267
|
+
ctx.arc(pos.x, pos.y, planet.size, 0, Math.PI * 2);
|
|
268
|
+
ctx.fillStyle = gradient;
|
|
269
|
+
ctx.fill();
|
|
270
|
+
|
|
271
|
+
// Saturn's rings
|
|
272
|
+
if (planet.name === 'Saturn') {
|
|
273
|
+
drawSaturnRings(pos.x, pos.y, planet.size, pos.angle);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Label
|
|
277
|
+
if (showLabels) {
|
|
278
|
+
ctx.fillStyle = '#b794f6';
|
|
279
|
+
ctx.font = '11px Segoe UI';
|
|
280
|
+
ctx.textAlign = 'center';
|
|
281
|
+
ctx.fillText(planet.name, pos.x, pos.y - planet.size - 8);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Draw asteroid belt
|
|
286
|
+
function drawAsteroidBelt() {
|
|
287
|
+
ctx.fillStyle = 'rgba(150, 150, 150, 0.6)';
|
|
288
|
+
asteroids.forEach(asteroid => {
|
|
289
|
+
asteroid.angle += asteroid.speed * simulationSpeed;
|
|
290
|
+
const x = centerX + asteroid.distance * Math.cos(asteroid.angle);
|
|
291
|
+
const y = centerY + asteroid.distance * Math.sin(asteroid.angle);
|
|
292
|
+
|
|
293
|
+
ctx.beginPath();
|
|
294
|
+
ctx.arc(x, y, asteroid.size, 0, Math.PI * 2);
|
|
295
|
+
ctx.fill();
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Helper function to lighten colors
|
|
300
|
+
function lightenColor(color, percent) {
|
|
301
|
+
const num = parseInt(color.replace('#', ''), 16);
|
|
302
|
+
const amt = Math.round(2.55 * percent);
|
|
303
|
+
const R = (num >> 16) + amt;
|
|
304
|
+
const G = (num >> 8 & 0x00FF) + amt;
|
|
305
|
+
const B = (num & 0x0000FF) + amt;
|
|
306
|
+
return '#' + (0x1000000 + (R < 255 ? R < 1 ? 0 : R : 255) * 0x10000 +
|
|
307
|
+
(G < 255 ? G < 1 ? 0 : G : 255) * 0x100 +
|
|
308
|
+
(B < 255 ? B < 1 ? 0 : B : 255)).toString(16).slice(1);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Draw stars background
|
|
312
|
+
let stars = [];
|
|
313
|
+
function generateStars() {
|
|
314
|
+
stars = [];
|
|
315
|
+
for (let i = 0; i < 200; i++) {
|
|
316
|
+
stars.push({
|
|
317
|
+
x: Math.random() * width,
|
|
318
|
+
y: Math.random() * height,
|
|
319
|
+
size: Math.random() * 1.5,
|
|
320
|
+
brightness: 0.3 + Math.random() * 0.7
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
generateStars();
|
|
325
|
+
|
|
326
|
+
function drawStars() {
|
|
327
|
+
stars.forEach(star => {
|
|
328
|
+
const twinkle = 0.8 + Math.sin(time * 0.01 + star.x) * 0.2;
|
|
329
|
+
ctx.beginPath();
|
|
330
|
+
ctx.arc(star.x, star.y, star.size, 0, Math.PI * 2);
|
|
331
|
+
ctx.fillStyle = `rgba(255, 255, 255, ${star.brightness * twinkle})`;
|
|
332
|
+
ctx.fill();
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Main animation loop
|
|
337
|
+
function animate() {
|
|
338
|
+
ctx.fillStyle = 'rgba(10, 10, 25, 1)';
|
|
339
|
+
ctx.fillRect(0, 0, width, height);
|
|
340
|
+
|
|
341
|
+
drawStars();
|
|
342
|
+
|
|
343
|
+
// Draw orbits
|
|
344
|
+
if (showOrbits) {
|
|
345
|
+
planets.forEach(planet => drawOrbit(planet));
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Draw asteroid belt
|
|
349
|
+
if (showAsteroids) {
|
|
350
|
+
drawAsteroidBelt();
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Draw Sun
|
|
354
|
+
drawSun();
|
|
355
|
+
|
|
356
|
+
// Draw planets
|
|
357
|
+
planets.forEach(planet => {
|
|
358
|
+
const pos = getOrbitalPosition(planet, time);
|
|
359
|
+
drawPlanet(planet, pos);
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
time += 1;
|
|
363
|
+
requestAnimationFrame(animate);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Event listeners
|
|
367
|
+
document.getElementById('speedSlider').addEventListener('input', (e) => {
|
|
368
|
+
simulationSpeed = parseFloat(e.target.value);
|
|
369
|
+
document.getElementById('speedValue').textContent = simulationSpeed.toFixed(1) + 'x';
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
document.getElementById('toggleOrbits').addEventListener('click', (e) => {
|
|
373
|
+
showOrbits = !showOrbits;
|
|
374
|
+
e.target.classList.toggle('active');
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
document.getElementById('toggleLabels').addEventListener('click', (e) => {
|
|
378
|
+
showLabels = !showLabels;
|
|
379
|
+
e.target.classList.toggle('active');
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
document.getElementById('toggleAsteroids').addEventListener('click', (e) => {
|
|
383
|
+
showAsteroids = !showAsteroids;
|
|
384
|
+
e.target.classList.toggle('active');
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
document.getElementById('resetView').addEventListener('click', () => {
|
|
388
|
+
time = 0;
|
|
389
|
+
simulationSpeed = 1;
|
|
390
|
+
document.getElementById('speedSlider').value = 1;
|
|
391
|
+
document.getElementById('speedValue').textContent = '1x';
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
// Click on planets for info
|
|
395
|
+
canvas.addEventListener('click', (e) => {
|
|
396
|
+
const rect = canvas.getBoundingClientRect();
|
|
397
|
+
const clickX = e.clientX - rect.left;
|
|
398
|
+
const clickY = e.clientY - rect.top;
|
|
399
|
+
|
|
400
|
+
planets.forEach(planet => {
|
|
401
|
+
const pos = getOrbitalPosition(planet, time);
|
|
402
|
+
const dist = Math.sqrt((clickX - pos.x) ** 2 + (clickY - pos.y) ** 2);
|
|
403
|
+
|
|
404
|
+
if (dist < planet.size + 10) {
|
|
405
|
+
const infoPanel = document.getElementById('infoPanel');
|
|
406
|
+
infoPanel.innerHTML = `
|
|
407
|
+
<h3>${planet.name}</h3>
|
|
408
|
+
<p><strong>Orbital Period:</strong> ${planet.period} Earth years</p>
|
|
409
|
+
<p><strong>Orbital Eccentricity:</strong> ${planet.eccentricity}</p>
|
|
410
|
+
<p>${planet.info}</p>
|
|
411
|
+
`;
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
// Check if clicked on Sun
|
|
416
|
+
const sunDist = Math.sqrt((clickX - centerX) ** 2 + (clickY - centerY) ** 2);
|
|
417
|
+
if (sunDist < 30) {
|
|
418
|
+
const infoPanel = document.getElementById('infoPanel');
|
|
419
|
+
infoPanel.innerHTML = `
|
|
420
|
+
<h3>The Sun</h3>
|
|
421
|
+
<p><strong>Type:</strong> G-type main-sequence star</p>
|
|
422
|
+
<p><strong>Age:</strong> ~4.6 billion years</p>
|
|
423
|
+
<p>Contains 99.86% of the Solar System's mass. Surface temperature: 5,500°C. Core temperature: 15 million°C.</p>
|
|
424
|
+
`;
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
// Start animation
|
|
429
|
+
animate();
|
|
430
|
+
</script>
|
|
431
|
+
</body>
|
|
432
|
+
</html>
|