PierreH commited on
Commit
79b474d
·
verified ·
1 Parent(s): 5d72532

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +594 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Test
3
- emoji: 💻
4
- colorFrom: purple
5
- colorTo: blue
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: test
3
+ emoji: 🐳
4
+ colorFrom: pink
5
+ colorTo: pink
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,594 @@
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="fr">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>HypnoMap Live</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ .map-container {
11
+ background-image: url('https://maps.googleapis.com/maps/api/staticmap?center=48.8566,2.3522&zoom=13&size=800x600&scale=2');
12
+ background-size: cover;
13
+ background-position: center;
14
+ }
15
+
16
+ .bubble {
17
+ position: absolute;
18
+ border-radius: 50%;
19
+ display: flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+ cursor: pointer;
23
+ transition: all 0.3s ease;
24
+ }
25
+
26
+ .bubble:hover {
27
+ transform: scale(1.05);
28
+ }
29
+
30
+ .message-banner {
31
+ animation: slideIn 0.5s forwards, fadeOut 0.5s 5s forwards;
32
+ }
33
+
34
+ @keyframes slideIn {
35
+ from { transform: translateY(100px); opacity: 0; }
36
+ to { transform: translateY(0); opacity: 1; }
37
+ }
38
+
39
+ @keyframes fadeOut {
40
+ from { opacity: 1; }
41
+ to { opacity: 0; }
42
+ }
43
+
44
+ .range-slider::-webkit-slider-thumb {
45
+ -webkit-appearance: none;
46
+ width: 20px;
47
+ height: 20px;
48
+ border-radius: 50%;
49
+ background: #4f46e5;
50
+ cursor: pointer;
51
+ }
52
+
53
+ .participant-marker {
54
+ position: absolute;
55
+ width: 24px;
56
+ height: 24px;
57
+ border-radius: 50%;
58
+ display: flex;
59
+ align-items: center;
60
+ justify-content: center;
61
+ font-weight: bold;
62
+ color: white;
63
+ }
64
+ </style>
65
+ </head>
66
+ <body class="bg-gray-900 text-white min-h-screen">
67
+ <!-- Home Screen -->
68
+ <div id="home-screen" class="flex flex-col items-center justify-center min-h-screen p-4">
69
+ <div class="text-center mb-12">
70
+ <h1 class="text-5xl font-bold mb-4 text-purple-500">HypnoMap Live</h1>
71
+ <p class="text-xl text-gray-300">Expérience sonore géolocalisée</p>
72
+ </div>
73
+
74
+ <div class="w-full max-w-md space-y-6">
75
+ <button id="join-btn" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-bold py-4 px-6 rounded-lg text-xl transition flex items-center justify-center">
76
+ <i class="fas fa-user-friends mr-3"></i> Rejoindre une session
77
+ </button>
78
+
79
+ <button id="create-btn" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-4 px-6 rounded-lg text-xl transition flex items-center justify-center">
80
+ <i class="fas fa-music mr-3"></i> Créer une session (DJ)
81
+ </button>
82
+ </div>
83
+ </div>
84
+
85
+ <!-- Join Session Modal -->
86
+ <div id="join-modal" class="fixed inset-0 bg-black bg-opacity-80 flex items-center justify-center z-50 hidden">
87
+ <div class="bg-gray-800 rounded-xl p-6 w-full max-w-md">
88
+ <div class="flex justify-between items-center mb-4">
89
+ <h2 class="text-2xl font-bold">Rejoindre une session</h2>
90
+ <button id="close-join-modal" class="text-gray-400 hover:text-white">
91
+ <i class="fas fa-times"></i>
92
+ </button>
93
+ </div>
94
+
95
+ <div class="mb-6">
96
+ <label class="block text-gray-300 mb-2">Code de session</label>
97
+ <input type="text" id="session-code" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="Entrez le code">
98
+ </div>
99
+
100
+ <div class="mb-6">
101
+ <label class="block text-gray-300 mb-2">Votre pseudo</label>
102
+ <input type="text" id="participant-name" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="Optionnel">
103
+ </div>
104
+
105
+ <button id="confirm-join" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-6 rounded-lg transition">
106
+ Rejoindre
107
+ </button>
108
+ </div>
109
+ </div>
110
+
111
+ <!-- DJ Mode -->
112
+ <div id="dj-screen" class="hidden min-h-screen flex flex-col">
113
+ <div class="bg-gray-800 p-4 flex justify-between items-center">
114
+ <div>
115
+ <h2 class="text-xl font-bold">Mode DJ</h2>
116
+ <p class="text-sm text-gray-400">Session: <span id="dj-session-code" class="font-mono">XXXXXX</span></p>
117
+ </div>
118
+ <div class="flex space-x-2">
119
+ <button id="dj-settings" class="p-2 rounded-full hover:bg-gray-700">
120
+ <i class="fas fa-cog"></i>
121
+ </button>
122
+ <button id="leave-dj" class="p-2 rounded-full hover:bg-gray-700">
123
+ <i class="fas fa-sign-out-alt"></i>
124
+ </button>
125
+ </div>
126
+ </div>
127
+
128
+ <div class="relative flex-1">
129
+ <div id="dj-map" class="map-container w-full h-full relative overflow-hidden">
130
+ <!-- Map will be rendered here -->
131
+ <div id="dj-bubbles-container"></div>
132
+ <div id="dj-participants-container"></div>
133
+ </div>
134
+
135
+ <div class="absolute bottom-4 left-0 right-0 flex justify-center">
136
+ <button id="create-bubble-btn" class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-6 rounded-full shadow-lg flex items-center">
137
+ <i class="fas fa-plus-circle mr-2"></i> Créer une bulle
138
+ </button>
139
+ </div>
140
+
141
+ <div id="dj-controls" class="absolute top-4 right-4 bg-gray-800 bg-opacity-80 rounded-lg p-3 space-y-3">
142
+ <button id="play-all" class="p-2 bg-green-600 hover:bg-green-700 rounded-full">
143
+ <i class="fas fa-play"></i>
144
+ </button>
145
+ <button id="pause-all" class="p-2 bg-yellow-600 hover:bg-yellow-700 rounded-full">
146
+ <i class="fas fa-pause"></i>
147
+ </button>
148
+ <button id="global-message" class="p-2 bg-blue-600 hover:bg-blue-700 rounded-full">
149
+ <i class="fas fa-bullhorn"></i>
150
+ </button>
151
+ </div>
152
+ </div>
153
+ </div>
154
+
155
+ <!-- Participant Mode -->
156
+ <div id="participant-screen" class="hidden min-h-screen flex flex-col">
157
+ <div class="bg-gray-800 p-4 flex justify-between items-center">
158
+ <div>
159
+ <h2 class="text-xl font-bold">Mode Participant</h2>
160
+ <p class="text-sm text-gray-400">Session: <span id="participant-session-code" class="font-mono">XXXXXX</span></p>
161
+ </div>
162
+ <div class="flex space-x-2">
163
+ <button id="leave-participant" class="p-2 rounded-full hover:bg-gray-700">
164
+ <i class="fas fa-sign-out-alt"></i>
165
+ </button>
166
+ </div>
167
+ </div>
168
+
169
+ <div class="relative flex-1">
170
+ <div id="participant-map" class="map-container w-full h-full relative overflow-hidden">
171
+ <!-- Map will be rendered here -->
172
+ <div id="participant-bubbles-container"></div>
173
+ <div id="participant-participants-container"></div>
174
+ </div>
175
+
176
+ <div id="message-banner" class="message-banner absolute bottom-20 left-0 right-0 mx-auto bg-purple-600 bg-opacity-90 rounded-lg p-4 max-w-md text-center hidden">
177
+ <p id="message-content" class="font-medium"></p>
178
+ </div>
179
+
180
+ <div class="absolute bottom-4 left-0 right-0 flex justify-center px-4">
181
+ <div class="flex w-full max-w-md bg-gray-800 bg-opacity-80 rounded-full p-2">
182
+ <input type="text" id="participant-message" class="flex-1 bg-transparent px-4 py-2 focus:outline-none" placeholder="Envoyer un message..." maxlength="140">
183
+ <button id="send-message" class="bg-purple-600 hover:bg-purple-700 rounded-full px-4">
184
+ <i class="fas fa-paper-plane"></i>
185
+ </button>
186
+ </div>
187
+ </div>
188
+ </div>
189
+ </div>
190
+
191
+ <!-- Create Bubble Modal -->
192
+ <div id="bubble-modal" class="fixed inset-0 bg-black bg-opacity-80 flex items-center justify-center z-50 hidden">
193
+ <div class="bg-gray-800 rounded-xl p-6 w-full max-w-md">
194
+ <div class="flex justify-between items-center mb-4">
195
+ <h2 class="text-2xl font-bold">Nouvelle bulle sonore</h2>
196
+ <button id="close-bubble-modal" class="text-gray-400 hover:text-white">
197
+ <i class="fas fa-times"></i>
198
+ </button>
199
+ </div>
200
+
201
+ <div class="mb-4">
202
+ <label class="block text-gray-300 mb-2">Nom de la bulle</label>
203
+ <input type="text" id="bubble-name" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="Ma bulle sonore">
204
+ </div>
205
+
206
+ <div class="mb-4">
207
+ <label class="block text-gray-300 mb-2">Fichier audio</label>
208
+ <div class="flex items-center">
209
+ <label for="audio-upload" class="bg-gray-700 hover:bg-gray-600 border border-gray-600 rounded-lg px-4 py-3 cursor-pointer flex-1">
210
+ <span id="audio-file-name" class="text-gray-300">Sélectionner un fichier...</span>
211
+ </label>
212
+ <input type="file" id="audio-upload" class="hidden" accept="audio/*">
213
+ </div>
214
+ </div>
215
+
216
+ <div class="mb-6">
217
+ <label class="block text-gray-300 mb-2">Rayon d'activation: <span id="radius-value">25</span>m</label>
218
+ <input type="range" id="bubble-radius" min="5" max="50" value="25" class="w-full range-slider">
219
+ </div>
220
+
221
+ <button id="confirm-bubble" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-6 rounded-lg transition">
222
+ Créer la bulle
223
+ </button>
224
+ </div>
225
+ </div>
226
+
227
+ <!-- Global Message Modal -->
228
+ <div id="global-message-modal" class="fixed inset-0 bg-black bg-opacity-80 flex items-center justify-center z-50 hidden">
229
+ <div class="bg-gray-800 rounded-xl p-6 w-full max-w-md">
230
+ <div class="flex justify-between items-center mb-4">
231
+ <h2 class="text-2xl font-bold">Message global</h2>
232
+ <button id="close-global-message-modal" class="text-gray-400 hover:text-white">
233
+ <i class="fas fa-times"></i>
234
+ </button>
235
+ </div>
236
+
237
+ <div class="mb-6">
238
+ <label class="block text-gray-300 mb-2">Message</label>
239
+ <textarea id="global-message-text" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-3 h-32 focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="Écrivez un message pour tous les participants..." maxlength="140"></textarea>
240
+ </div>
241
+
242
+ <button id="send-global-message" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-6 rounded-lg transition">
243
+ Envoyer
244
+ </button>
245
+ </div>
246
+ </div>
247
+
248
+ <script>
249
+ // State management
250
+ const appState = {
251
+ currentScreen: 'home',
252
+ isDJ: false,
253
+ sessionCode: '',
254
+ bubbles: [],
255
+ participants: [],
256
+ messages: [],
257
+ currentUser: {
258
+ id: Math.random().toString(36).substring(2, 10),
259
+ name: 'Participant ' + Math.floor(Math.random() * 1000),
260
+ position: { x: 50, y: 50 }
261
+ }
262
+ };
263
+
264
+ // DOM elements
265
+ const homeScreen = document.getElementById('home-screen');
266
+ const joinModal = document.getElementById('join-modal');
267
+ const djScreen = document.getElementById('dj-screen');
268
+ const participantScreen = document.getElementById('participant-screen');
269
+ const bubbleModal = document.getElementById('bubble-modal');
270
+ const globalMessageModal = document.getElementById('global-message-modal');
271
+
272
+ // Event listeners
273
+ document.getElementById('join-btn').addEventListener('click', () => {
274
+ joinModal.classList.remove('hidden');
275
+ });
276
+
277
+ document.getElementById('create-btn').addEventListener('click', () => {
278
+ createSession(true);
279
+ });
280
+
281
+ document.getElementById('close-join-modal').addEventListener('click', () => {
282
+ joinModal.classList.add('hidden');
283
+ });
284
+
285
+ document.getElementById('confirm-join').addEventListener('click', () => {
286
+ const code = document.getElementById('session-code').value;
287
+ const name = document.getElementById('participant-name').value;
288
+
289
+ if (code) {
290
+ if (name) appState.currentUser.name = name;
291
+ joinSession(code);
292
+ joinModal.classList.add('hidden');
293
+ } else {
294
+ alert('Veuillez entrer un code de session');
295
+ }
296
+ });
297
+
298
+ document.getElementById('leave-dj').addEventListener('click', () => {
299
+ showScreen('home');
300
+ });
301
+
302
+ document.getElementById('leave-participant').addEventListener('click', () => {
303
+ showScreen('home');
304
+ });
305
+
306
+ document.getElementById('create-bubble-btn').addEventListener('click', () => {
307
+ bubbleModal.classList.remove('hidden');
308
+ });
309
+
310
+ document.getElementById('close-bubble-modal').addEventListener('click', () => {
311
+ bubbleModal.classList.add('hidden');
312
+ });
313
+
314
+ document.getElementById('confirm-bubble').addEventListener('click', () => {
315
+ const name = document.getElementById('bubble-name').value;
316
+ const radius = parseInt(document.getElementById('bubble-radius').value);
317
+
318
+ if (name) {
319
+ createBubble(name, radius);
320
+ bubbleModal.classList.add('hidden');
321
+ } else {
322
+ alert('Veuillez donner un nom à votre bulle');
323
+ }
324
+ });
325
+
326
+ document.getElementById('bubble-radius').addEventListener('input', (e) => {
327
+ document.getElementById('radius-value').textContent = e.target.value;
328
+ });
329
+
330
+ document.getElementById('audio-upload').addEventListener('change', (e) => {
331
+ const file = e.target.files[0];
332
+ if (file) {
333
+ document.getElementById('audio-file-name').textContent = file.name;
334
+ }
335
+ });
336
+
337
+ document.getElementById('global-message').addEventListener('click', () => {
338
+ globalMessageModal.classList.remove('hidden');
339
+ });
340
+
341
+ document.getElementById('close-global-message-modal').addEventListener('click', () => {
342
+ globalMessageModal.classList.add('hidden');
343
+ });
344
+
345
+ document.getElementById('send-global-message').addEventListener('click', () => {
346
+ const message = document.getElementById('global-message-text').value;
347
+ if (message) {
348
+ sendGlobalMessage(message);
349
+ globalMessageModal.classList.add('hidden');
350
+ document.getElementById('global-message-text').value = '';
351
+ }
352
+ });
353
+
354
+ document.getElementById('send-message').addEventListener('click', () => {
355
+ const message = document.getElementById('participant-message').value;
356
+ if (message) {
357
+ sendParticipantMessage(message);
358
+ document.getElementById('participant-message').value = '';
359
+ }
360
+ });
361
+
362
+ // Functions
363
+ function showScreen(screen) {
364
+ homeScreen.classList.add('hidden');
365
+ djScreen.classList.add('hidden');
366
+ participantScreen.classList.add('hidden');
367
+
368
+ appState.currentScreen = screen;
369
+
370
+ if (screen === 'home') {
371
+ homeScreen.classList.remove('hidden');
372
+ } else if (screen === 'dj') {
373
+ djScreen.classList.remove('hidden');
374
+ renderDJMap();
375
+ } else if (screen === 'participant') {
376
+ participantScreen.classList.remove('hidden');
377
+ renderParticipantMap();
378
+ }
379
+ }
380
+
381
+ function createSession(isDJ) {
382
+ appState.isDJ = isDJ;
383
+ appState.sessionCode = generateSessionCode();
384
+
385
+ if (isDJ) {
386
+ document.getElementById('dj-session-code').textContent = appState.sessionCode;
387
+ showScreen('dj');
388
+ } else {
389
+ document.getElementById('participant-session-code').textContent = appState.sessionCode;
390
+ showScreen('participant');
391
+ }
392
+
393
+ // Simulate other participants joining
394
+ setTimeout(() => {
395
+ addParticipant('DJ Master', { x: 30, y: 30 });
396
+ addParticipant('Sound Explorer', { x: 70, y: 70 });
397
+ addParticipant('Music Traveler', { x: 60, y: 40 });
398
+
399
+ if (isDJ) {
400
+ renderDJMap();
401
+ } else {
402
+ renderParticipantMap();
403
+ }
404
+ }, 1000);
405
+ }
406
+
407
+ function joinSession(code) {
408
+ appState.isDJ = false;
409
+ appState.sessionCode = code;
410
+ document.getElementById('participant-session-code').textContent = code;
411
+ showScreen('participant');
412
+
413
+ // Simulate existing bubbles
414
+ setTimeout(() => {
415
+ addBubble('Ambiance Chill', 20, { x: 40, y: 60 });
416
+ addBubble('Rythme Urbain', 15, { x: 70, y: 30 });
417
+
418
+ renderParticipantMap();
419
+ }, 1000);
420
+ }
421
+
422
+ function generateSessionCode() {
423
+ return Math.random().toString(36).substring(2, 8).toUpperCase();
424
+ }
425
+
426
+ function createBubble(name, radius) {
427
+ const bubble = {
428
+ id: Math.random().toString(36).substring(2, 10),
429
+ name,
430
+ radius,
431
+ position: { x: 50, y: 50 }, // Center position
432
+ audio: 'sample.mp3' // In a real app, this would be the uploaded file
433
+ };
434
+
435
+ appState.bubbles.push(bubble);
436
+ renderDJMap();
437
+ }
438
+
439
+ function addBubble(name, radius, position) {
440
+ const bubble = {
441
+ id: Math.random().toString(36).substring(2, 10),
442
+ name,
443
+ radius,
444
+ position,
445
+ audio: 'sample.mp3'
446
+ };
447
+
448
+ appState.bubbles.push(bubble);
449
+ }
450
+
451
+ function addParticipant(name, position) {
452
+ const participant = {
453
+ id: Math.random().toString(36).substring(2, 10),
454
+ name,
455
+ position
456
+ };
457
+
458
+ appState.participants.push(participant);
459
+ }
460
+
461
+ function sendGlobalMessage(message) {
462
+ // In a real app, this would be sent to all participants
463
+ console.log('Global message sent:', message);
464
+ }
465
+
466
+ function sendParticipantMessage(message) {
467
+ const messageObj = {
468
+ id: Math.random().toString(36).substring(2, 10),
469
+ sender: appState.currentUser.name,
470
+ content: message,
471
+ timestamp: new Date()
472
+ };
473
+
474
+ // Show the message banner
475
+ const banner = document.getElementById('message-banner');
476
+ const content = document.getElementById('message-content');
477
+
478
+ content.textContent = `${messageObj.sender}: ${messageObj.content}`;
479
+ banner.classList.remove('hidden');
480
+
481
+ // Hide after animation
482
+ setTimeout(() => {
483
+ banner.classList.add('hidden');
484
+ }, 5500);
485
+ }
486
+
487
+ function renderDJMap() {
488
+ const container = document.getElementById('dj-bubbles-container');
489
+ const participantsContainer = document.getElementById('dj-participants-container');
490
+
491
+ container.innerHTML = '';
492
+ participantsContainer.innerHTML = '';
493
+
494
+ // Render bubbles
495
+ appState.bubbles.forEach(bubble => {
496
+ const bubbleEl = document.createElement('div');
497
+ bubbleEl.className = 'bubble bg-purple-500 bg-opacity-30 border-2 border-purple-400';
498
+ bubbleEl.style.width = `${bubble.radius * 6}px`;
499
+ bubbleEl.style.height = `${bubble.radius * 6}px`;
500
+ bubbleEl.style.left = `${bubble.position.x}%`;
501
+ bubbleEl.style.top = `${bubble.position.y}%`;
502
+ bubbleEl.title = bubble.name;
503
+
504
+ // Make draggable
505
+ bubbleEl.draggable = true;
506
+ bubbleEl.addEventListener('dragstart', (e) => {
507
+ e.dataTransfer.setData('text/plain', bubble.id);
508
+ });
509
+
510
+ container.appendChild(bubbleEl);
511
+ });
512
+
513
+ // Render participants
514
+ appState.participants.forEach(participant => {
515
+ const participantEl = document.createElement('div');
516
+ participantEl.className = 'participant-marker bg-blue-500';
517
+ participantEl.style.left = `${participant.position.x}%`;
518
+ participantEl.style.top = `${participant.position.y}%`;
519
+ participantEl.textContent = participant.name.charAt(0);
520
+ participantEl.title = participant.name;
521
+
522
+ participantsContainer.appendChild(participantEl);
523
+ });
524
+
525
+ // Add drop zone for bubbles
526
+ const map = document.getElementById('dj-map');
527
+ map.addEventListener('dragover', (e) => {
528
+ e.preventDefault();
529
+ });
530
+
531
+ map.addEventListener('drop', (e) => {
532
+ e.preventDefault();
533
+ const bubbleId = e.dataTransfer.getData('text/plain');
534
+ const bubble = appState.bubbles.find(b => b.id === bubbleId);
535
+
536
+ if (bubble) {
537
+ const rect = map.getBoundingClientRect();
538
+ const x = ((e.clientX - rect.left) / rect.width) * 100;
539
+ const y = ((e.clientY - rect.top) / rect.height) * 100;
540
+
541
+ bubble.position = { x, y };
542
+ renderDJMap();
543
+ }
544
+ });
545
+ }
546
+
547
+ function renderParticipantMap() {
548
+ const container = document.getElementById('participant-bubbles-container');
549
+ const participantsContainer = document.getElementById('participant-participants-container');
550
+
551
+ container.innerHTML = '';
552
+ participantsContainer.innerHTML = '';
553
+
554
+ // Render bubbles
555
+ appState.bubbles.forEach(bubble => {
556
+ const bubbleEl = document.createElement('div');
557
+ bubbleEl.className = 'bubble bg-purple-500 bg-opacity-20 border border-purple-400';
558
+ bubbleEl.style.width = `${bubble.radius * 6}px`;
559
+ bubbleEl.style.height = `${bubble.radius * 6}px`;
560
+ bubbleEl.style.left = `${bubble.position.x}%`;
561
+ bubbleEl.style.top = `${bubble.position.y}%`;
562
+ bubbleEl.title = bubble.name;
563
+
564
+ container.appendChild(bubbleEl);
565
+ });
566
+
567
+ // Render participants
568
+ appState.participants.forEach(participant => {
569
+ const participantEl = document.createElement('div');
570
+ participantEl.className = 'participant-marker bg-blue-500';
571
+ participantEl.style.left = `${participant.position.x}%`;
572
+ participantEl.style.top = `${participant.position.y}%`;
573
+ participantEl.textContent = participant.name.charAt(0);
574
+ participantEl.title = participant.name;
575
+
576
+ participantsContainer.appendChild(participantEl);
577
+ });
578
+
579
+ // Add current user
580
+ const currentUserEl = document.createElement('div');
581
+ currentUserEl.className = 'participant-marker bg-green-500';
582
+ currentUserEl.style.left = `${appState.currentUser.position.x}%`;
583
+ currentUserEl.style.top = `${appState.currentUser.position.y}%`;
584
+ currentUserEl.textContent = appState.currentUser.name.charAt(0);
585
+ currentUserEl.title = appState.currentUser.name;
586
+
587
+ participantsContainer.appendChild(currentUserEl);
588
+ }
589
+
590
+ // Initialize
591
+ showScreen('home');
592
+ </script>
593
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=PierreH/test" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
594
+ </html>