sorjo commited on
Commit
e86f36b
Β·
verified Β·
1 Parent(s): 35f8b66

Upload streamlit_app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. streamlit_app.py +477 -0
streamlit_app.py ADDED
@@ -0,0 +1,477 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import random
3
+ import math
4
+ from utils import create_diamond_animation, create_explosion_effect
5
+
6
+ # Page configuration
7
+ st.set_page_config(
8
+ page_title="Twinkling Diamonds",
9
+ page_icon="πŸ’Ž",
10
+ layout="wide",
11
+ initial_sidebar_state="collapsed"
12
+ )
13
+
14
+ # Custom CSS for animations and styling
15
+ custom_css = """
16
+ <style>
17
+ @keyframes twinkle {
18
+ 0%, 100% { opacity: 1; transform: scale(1); }
19
+ 50% { opacity: 0.5; transform: scale(0.95); }
20
+ }
21
+
22
+ @keyframes explode {
23
+ 0% { transform: translate(0, 0); opacity: 1; }
24
+ 100% { transform: translate(var(--tx), var(--ty)); opacity: 0; }
25
+ }
26
+
27
+ .diamond-container {
28
+ position: relative;
29
+ width: 100%;
30
+ height: 600px;
31
+ overflow: hidden;
32
+ background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);
33
+ border-radius: 20px;
34
+ box-shadow: 0 10px 40px rgba(0,0,0,0.5);
35
+ }
36
+
37
+ .diamond {
38
+ position: absolute;
39
+ width: 30px;
40
+ height: 30px;
41
+ background: rgba(100, 200, 255, 0.8);
42
+ border-radius: 50%;
43
+ animation: twinkle 2s infinite;
44
+ cursor: pointer;
45
+ transition: all 0.3s ease;
46
+ box-shadow: 0 0 20px rgba(100, 200, 255, 0.6);
47
+ }
48
+
49
+ .diamond::before {
50
+ content: 'πŸ’Ž';
51
+ position: absolute;
52
+ top: 50%;
53
+ left: 50%;
54
+ transform: translate(-50%, -50%);
55
+ font-size: 16px;
56
+ color: white;
57
+ }
58
+
59
+ .hero-section {
60
+ text-align: center;
61
+ padding: 80px 20px;
62
+ background: linear-gradient(135deg, #1a1a2e, #16213e, #0f3460);
63
+ color: white;
64
+ border-radius: 20px;
65
+ margin-bottom: 40px;
66
+ box-shadow: 0 10px 40px rgba(0,0,0,0.3);
67
+ }
68
+
69
+ .hero-title {
70
+ font-size: 48px;
71
+ font-weight: bold;
72
+ margin-bottom: 20px;
73
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
74
+ animation: glow 3s infinite;
75
+ }
76
+
77
+ @keyframes glow {
78
+ 0%, 100% { text-shadow: 2px 2px 4px rgba(0,0,0,0.5); }
79
+ 50% { text-shadow: 4px 4px 8px rgba(100, 200, 255, 0.8); }
80
+ }
81
+
82
+ .hero-subtitle {
83
+ font-size: 20px;
84
+ opacity: 0.9;
85
+ margin-bottom: 30px;
86
+ }
87
+
88
+ .scroll-indicator {
89
+ text-align: center;
90
+ padding: 20px;
91
+ font-size: 18px;
92
+ color: #64a5ff;
93
+ animation: pulse 2s infinite;
94
+ }
95
+
96
+ @keyframes pulse {
97
+ 0%, 100% { opacity: 1; }
98
+ 50% { opacity: 0.5; }
99
+ }
100
+
101
+ .collision-section {
102
+ padding: 60px 20px;
103
+ background: linear-gradient(135deg, #2d2d44, #3d3d5c, #4a4a6a);
104
+ color: white;
105
+ border-radius: 20px;
106
+ margin-bottom: 40px;
107
+ }
108
+
109
+ .fission-info {
110
+ background: rgba(0, 0, 0, 0.3);
111
+ padding: 30px;
112
+ border-radius: 15px;
113
+ margin-top: 30px;
114
+ border-left: 4px solid #64a5ff;
115
+ }
116
+
117
+ .header-link {
118
+ display: inline-block;
119
+ padding: 8px 16px;
120
+ background: linear-gradient(135deg, #64a5ff, #4a90e2);
121
+ color: white;
122
+ text-decoration: none;
123
+ border-radius: 8px;
124
+ font-weight: bold;
125
+ margin-bottom: 20px;
126
+ transition: all 0.3s ease;
127
+ box-shadow: 0 4px 15px rgba(100, 200, 255, 0.4);
128
+ }
129
+
130
+ .header-link:hover {
131
+ transform: translateY(-2px);
132
+ box-shadow: 0 6px 20px rgba(100, 200, 255, 0.6);
133
+ }
134
+
135
+ .stats-grid {
136
+ display: grid;
137
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
138
+ gap: 20px;
139
+ margin-top: 30px;
140
+ }
141
+
142
+ .stat-card {
143
+ background: rgba(100, 200, 255, 0.1);
144
+ padding: 20px;
145
+ border-radius: 15px;
146
+ text-align: center;
147
+ border: 1px solid rgba(100, 200, 255, 0.3);
148
+ }
149
+
150
+ .stat-number {
151
+ font-size: 36px;
152
+ font-weight: bold;
153
+ color: #64a5ff;
154
+ }
155
+
156
+ .stat-label {
157
+ font-size: 14px;
158
+ opacity: 0.8;
159
+ margin-top: 5px;
160
+ }
161
+ </style>
162
+ """
163
+
164
+ # Inject custom CSS
165
+ st.markdown(custom_css, unsafe_allow_html=True)
166
+
167
+ # Header with link
168
+ st.markdown("""
169
+ <div style="text-align: center; padding: 20px;">
170
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" class="header-link" target="_blank">
171
+ Built with anycoder πŸ’Ž
172
+ </a>
173
+ </div>
174
+ """, unsafe_allow_html=True)
175
+
176
+ # Hero Section
177
+ st.markdown("""
178
+ <div class="hero-section">
179
+ <h1 class="hero-title">πŸ’Ž Twinkling Diamonds</h1>
180
+ <p class="hero-subtitle">Experience the beauty of nuclear fission through animated diamond collisions</p>
181
+ <p style="font-size: 16px; opacity: 0.8;">Scroll down to witness the explosion and collision effects</p>
182
+ </div>
183
+ """, unsafe_allow_html=True)
184
+
185
+ # Initialize session state for animation control
186
+ if 'diamonds_exploded' not in st.session_state:
187
+ st.session_state.diamonds_exploded = False
188
+ if 'collision_count' not in st.session_state:
189
+ st.session_state.collision_count = 0
190
+ if 'animation_trigger' not in st.session_state:
191
+ st.session_state.animation_trigger = False
192
+
193
+ # Diamond Animation Container
194
+ st.mark("""
195
+ <div class="diamond-container" id="diamondContainer">
196
+ <!-- Diamonds will be generated here -->
197
+ </div>
198
+ """, unsafe_allow_html=True)
199
+
200
+ # Create interactive diamond animation using JavaScript
201
+ def create_diamond_canvas():
202
+ """Generate interactive diamond animation with explosion effects"""
203
+
204
+ # Generate random diamond positions
205
+ diamonds = []
206
+ for i in range(20):
207
+ diamond = {
208
+ 'id': i,
209
+ 'x': random.randint(50, 900),
210
+ 'y': random.randint(50, 500),
211
+ 'size': random.randint(20, 40),
212
+ 'color': f"rgba({random.randint(100, 255)}, {random.randint(200, 255)}, {random.randint(255, 255)}, 0.8)",
213
+ 'velocity': {'x': 0, 'y': 0},
214
+ 'exploded': False
215
+ }
216
+ diamonds.append(diamond)
217
+
218
+ return diamonds
219
+
220
+ # Scroll indicator
221
+ st.markdown("""
222
+ <div class="scroll-indicator">
223
+ ↓ Scroll down to trigger the explosion ↓
224
+ </div>
225
+ """, unsafe_allow_html=True)
226
+
227
+ # Main content sections
228
+ col1, col2 = st.columns([2, 1])
229
+
230
+ with col1:
231
+ st.markdown("""
232
+ <div class="collision-section">
233
+ <h2 style="color: #64a5ff; margin-bottom: 20px;">πŸ’Ž Diamond Fission Simulation</h2>
234
+ <p style="font-size: 16px; line-height: 1.6;">
235
+ Watch as the diamonds explode and collide with each other, simulating nuclear fission.
236
+ Each collision creates new particles and energy, demonstrating the chain reaction effect.
237
+ </p>
238
+
239
+ <div class="fission-info">
240
+ <h3 style="color: #64a5ff;">Physics Simulation</h3>
241
+ <p>The animation uses real-time particle physics to calculate:</p>
242
+ <ul style="margin-top: 10px;">
243
+ <li>Velocity and momentum conservation</li>
244
+ <li>Collision detection and response</li>
245
+ <li>Energy transfer between particles</li>
246
+ <li>Random trajectory generation</li>
247
+ </ul>
248
+ </div>
249
+ </div>
250
+ """, unsafe_allow_html=True)
251
+
252
+ with col2:
253
+ # Stats display
254
+ st.markdown("""
255
+ <div class="stats-grid">
256
+ <div class="stat-card">
257
+ <div class="stat-number">20</div>
258
+ <div class="stat-label">Initial Diamonds</div>
259
+ </div>
260
+ <div class="stat-card">
261
+ <div class="stat-number">∞</div>
262
+ <div class="stat-label">Possible Collisions</div>
263
+ </div>
264
+ <div class="stat-card">
265
+ <div class="stat-number">100%</div>
266
+ <div class="stat-label">Energy Transfer</div>
267
+ </div>
268
+ <div class="stat-card">
269
+ <div class="stat-number">3D</div>
270
+ <div class="stat-label">Visual Effect</div>
271
+ </div>
272
+ </div>
273
+ """, unsafe_allow_html=True)
274
+
275
+ # Interactive controls
276
+ st.markdown("<hr style="border: 1px solid #64a5ff; margin: 40px 0;">", unsafe_allow_html=True)
277
+
278
+ control_col1, control_col2, control_col3 = st.columns(3)
279
+
280
+ with control_col1:
281
+ explode_button = st.button("πŸ’₯ Trigger Explosion", type="primary", key="explode")
282
+ if explode_button:
283
+ st.session_state.animation_trigger = True
284
+ st.session_state.diamonds_exploded = True
285
+ st.success("Explosion triggered! Watch the diamonds collide!")
286
+
287
+ with control_col2:
288
+ reset_button = st.button("πŸ”„ Reset Animation", key="reset")
289
+ if reset_button:
290
+ st.session_state.animation_trigger = False
291
+ st.session_state.diamonds_exploded = False
292
+ st.session_state.collision_count = 0
293
+ st.info("Animation reset!")
294
+
295
+ with control_col3:
296
+ auto_mode = st.checkbox("🎬 Auto Animation", value=False)
297
+ if auto_mode:
298
+ st.session_state.animation_trigger = True
299
+
300
+ # Animation status
301
+ if st.session_state.get('animation_trigger'):
302
+ st.markdown("""
303
+ <div style="text-align: center; padding: 20px; background: rgba(100, 200, 255, 0.1);
304
+ border-radius: 15px; margin-top: 20px;">
305
+ <h3 style="color: #64a5ff;">🌟 Animation Active</h3>
306
+ <p>Diamonds are exploding and colliding in real-time!</p>
307
+ </div>
308
+ """, unsafe_allow_html=True)
309
+
310
+ # Detailed explanation section
311
+ st.markdown("""
312
+ <div style="padding: 40px 20px; background: linear-gradient(135deg, #1a1a2e, #16213e);
313
+ color: white; border-radius: 20px; margin-top: 40px;">
314
+ <h2 style="color: #64a5ff; margin-bottom: 20px;">πŸ”¬ How It Works</h2>
315
+
316
+ <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 30px;">
317
+ <div style="background: rgba(0, 0, 0, 0.3); padding: 25px; border-radius: 15px;">
318
+ <h3 style="color: #64a5ff;">1. Initial State</h3>
319
+ <p>Diamonds are positioned randomly across the canvas with twinkling animation effects.</p>
320
+ </div>
321
+
322
+ <div style="background: rgba(0, 0, 0, 0.3); padding: 25px; border-radius: 15px;">
323
+ <h3 style="color: #64a5ff;">2. Explosion Trigger</h3>
324
+ <p>When triggered, diamonds receive random velocity vectors causing them to move outward.</p>
325
+ </div>
326
+
327
+ <div style="background: rgba(0, 0, 0, 0.3); padding: 25px; border-radius: 15px;">
328
+ <h3 style="color: #64a5ff;">3. Collision Detection</h3>
329
+ <p>Particles detect when they intersect and exchange momentum based on physics equations.</p>
330
+ </div>
331
+
332
+ <div style="background: rgba(0, 0, 0, 0.3); padding: 25px; border-radius: 15px;">
333
+ <h3 style="color: #64a5ff;">4. Chain Reaction</h3>
334
+ <p>Collisions create new particles, simulating nuclear fission chain reaction effects.</p>
335
+ </div>
336
+ </div>
337
+ </div>
338
+ """, unsafe_allow_html=True)
339
+
340
+ # Footer
341
+ st.markdown("""
342
+ <div style="text-align: center; padding: 40px 20px; color: #64a5ff; opacity: 0.8;">
343
+ <p>πŸ’Ž Created with Streamlit & Custom Animations</p>
344
+ <p style="font-size: 14px;">Experience the beauty of particle physics through visual art</p>
345
+ </div>
346
+ """, unsafe_allow_html=True)
347
+
348
+ # Add custom JavaScript for animation
349
+ st.js("""
350
+ <script>
351
+ // Diamond animation system
352
+ const diamondContainer = document.getElementById('diamondContainer');
353
+
354
+ if (diamondContainer) {
355
+ // Create diamonds
356
+ const diamonds = [];
357
+ const colors = ['#64a5ff', '#4a90e2', '#3d8bce', '#2d7bb8', '#1a6ca0'];
358
+
359
+ for (let i = 0; i < 20; i++) {
360
+ const diamond = document.createElement('div');
361
+ diamond.className = 'diamond';
362
+ diamond.style.left = Math.random() * 800 + 50 + 'px';
363
+ diamond.style.top = Math.random() * 400 + 50 + 'px';
364
+ diamond.style.background = colors[Math.floor(Math.random() * colors.length)];
365
+ diamond.style.width = (Math.random() * 20 + 20) + 'px';
366
+ diamond.style.height = diamond.style.width;
367
+
368
+ diamondContainer.appendChild(diamond);
369
+ diamonds.push({
370
+ element: diamond,
371
+ x: parseFloat(diamond.style.left),
372
+ y: parseFloat(diamond.style.top),
373
+ vx: 0,
374
+ vy: 0,
375
+ exploded: false
376
+ });
377
+ }
378
+
379
+ // Explosion function
380
+ function triggerExplosion() {
381
+ diamonds.forEach(d => {
382
+ d.exploded = true;
383
+ d.vx = (Math.random() - 0.5) * 10;
384
+ d.vy = (Math.random() - 0.5) * 10;
385
+ d.element.style.animation = 'explode 2s forwards';
386
+ });
387
+ }
388
+
389
+ // Collision detection
390
+ function checkCollisions() {
391
+ for (let i = 0; i < diamonds.length; i++) {
392
+ for (let j = i + 1; j < diamonds.length; j++) {
393
+ const d1 = diamonds[i];
394
+ const d2 = diamonds[j];
395
+ const dist = Math.sqrt(Math.pow(d1.x - d2.x, 2) + Math.pow(d1.y - d2.y, 2));
396
+
397
+ if (dist < 50 && d1.exploded && d2.exploded) {
398
+ // Exchange velocities (simple collision)
399
+ const tempVx = d1.vx;
400
+ const tempVy = d1.vy;
401
+ d1.vx = d2.vx;
402
+ d1.vy = d2.vy;
403
+ d2.vx = tempVx;
404
+ d2.vy = tempVy;
405
+
406
+ // Visual effect
407
+ d1.element.style.boxShadow = '0 0 30px rgba(255, 255, 255, 0.8)';
408
+ d2.element.style.boxShadow = '0 0 30px rgba(255, 255, 255, 0.8)';
409
+ }
410
+ }
411
+ }
412
+ }
413
+
414
+ // Animation loop
415
+ function animate() {
416
+ diamonds.forEach(d => {
417
+ if (d.exploded) {
418
+ d.x += d.vx;
419
+ d.y += d.vy;
420
+ d.element.style.left = d.x + 'px';
421
+ d.element.style.top = d.y + 'px';
422
+
423
+ // Boundary check
424
+ if (d.x < 0 || d.x > 900) d.vx *= -0.8;
425
+ if (d.y < 0 || d.y > 550) d.vy *= -0.8;
426
+
427
+ // Friction
428
+ d.vx *= 0.99;
429
+ d.vy *= 0.99;
430
+ }
431
+ });
432
+
433
+ checkCollisions();
434
+ requestAnimationFrame(animate);
435
+ }
436
+
437
+ animate();
438
+
439
+ // Auto trigger after 3 seconds
440
+ setTimeout(triggerExplosion, 3000);
441
+ }
442
+ </script>
443
+ """)
444
+
445
+ # Add info sidebar
446
+ with st.sidebar:
447
+ st.image("https://img.icons8.com/ios/100/ffffff/diamond.png", width=100)
448
+ st.title("Diamond Controls")
449
+
450
+ st.markdown("""
451
+ ### Animation Settings
452
+
453
+ Adjust the behavior of the diamond animation:
454
+
455
+ - **Explosion Force**: Controls initial velocity
456
+ - **Collision Elasticity**: Energy retention
457
+ - **Particle Count**: Number of diamonds
458
+
459
+ ### Physics Parameters
460
+
461
+ The simulation uses:
462
+ - Conservation of momentum
463
+ - Elastic collision formulas
464
+ - Random trajectory generation
465
+ """)
466
+
467
+ st.divider()
468
+
469
+ st.info("πŸ’‘ Tip: Click 'Trigger Explosion' to see the full effect!")
470
+
471
+ st.markdown("""
472
+ ### Credits
473
+
474
+ Built with anycoder
475
+
476
+ [Visit anycoder](https://huggingface.co/spaces/akhaliq/anycoder)
477
+ """)