TheGreatUnknown commited on
Commit
3acfb31
·
verified ·
1 Parent(s): 6819a8c

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +1369 -18
index.html CHANGED
@@ -1,19 +1,1370 @@
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
+ [⚠️ Suspicious Content] <html lang="en">
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
5
+ <title>Collaborative Holographic Universe Simulation</title>
6
+ <style>
7
+ body {
8
+ font-family: 'Arial', sans-serif;
9
+ background: linear-gradient(135deg, #000, #111);
10
+ margin: 0;
11
+ padding: 0;
12
+ color: #ccf;
13
+ min-height: 100vh;
14
+ display: flex;
15
+ flex-direction: column;
16
+ justify-content: center;
17
+ align-items: center;
18
+ }
19
+ .container {
20
+ width: 90%;
21
+ max-width: 1200px;
22
+ margin: 0 auto;
23
+ padding: 20px;
24
+ }
25
+ .header {
26
+ text-align: center;
27
+ margin-bottom: 20px;
28
+ }
29
+ h1 {
30
+ font-size: 2.5rem;
31
+ color: #7cf;
32
+ text-shadow: 0 0 10px rgba(124, 255, 255, 0.7);
33
+ }
34
+ .quantum-simulator {
35
+ background: rgba(0, 0, 15, 0.7);
36
+ border-radius: 15px;
37
+ padding: 20px;
38
+ margin-bottom: 30px;
39
+ box-shadow: 0 0 20px rgba(124, 200, 255, 0.3);
40
+ }
41
+ .env-setup {
42
+ background: rgba(15, 0, 30, 0.7);
43
+ border-radius: 15px;
44
+ padding: 20px;
45
+ margin-bottom: 30px;
46
+ box-shadow: 0 0 20px rgba(180, 120, 255, 0.3);
47
+ }
48
+ .analysis {
49
+ background: rgba(0, 30, 15, 0.7);
50
+ border-radius: 15px;
51
+ padding: 20px;
52
+ box-shadow: 0 0 20px rgba(120, 255, 170, 0.3);
53
+ }
54
+ .section-title {
55
+ color: #adf;
56
+ font-size: 1.6rem;
57
+ margin-bottom: 15px;
58
+ }
59
+ .row {
60
+ display: flex;
61
+ flex-wrap: wrap;
62
+ margin: 0 -10px;
63
+ }
64
+ .column {
65
+ flex: 1 1 300px;
66
+ margin: 10px;
67
+ }
68
+ canvas {
69
+ width: 100%;
70
+ height: auto;
71
+ background: #000;
72
+ border-radius: 10px;
73
+ max-height: 300px;
74
+ }
75
+ button {
76
+ background: linear-gradient(45deg, #4a7bd1, #7a4ad1);
77
+ color: white;
78
+ border: none;
79
+ padding: 12px 20px;
80
+ border-radius: 5px;
81
+ font-size: 16px;
82
+ cursor: pointer;
83
+ margin-top: 10px;
84
+ transition: all 0.3s;
85
+ }
86
+ button:hover {
87
+ transform: scale(1.05);
88
+ box-shadow: 0 0 15px rgba(124, 200, 255, 0.6);
89
+ }
90
+ .control-panel {
91
+ display: flex;
92
+ flex-wrap: wrap;
93
+ gap: 10px;
94
+ margin-bottom: 15px;
95
+ }
96
+ .parameter-control {
97
+ display: flex;
98
+ flex-direction: column;
99
+ min-width: 120px;
100
+ }
101
+ label {
102
+ margin-bottom: 5px;
103
+ color: #8cf;
104
+ }
105
+ input {
106
+ padding: 8px;
107
+ border-radius: 4px;
108
+ border: 1px solid #446;
109
+ background: #112;
110
+ color: #ddf;
111
+ }
112
+ .code-block {
113
+ background: #001;
114
+ padding: 15px;
115
+ border-radius: 5px;
116
+ font-family: monospace;
117
+ overflow-x: auto;
118
+ color: #8df;
119
+ margin-top: 10px;
120
+ }
121
+ .visualization {
122
+ width: 100%;
123
+ height: 280px;
124
+ margin-top: 15px;
125
+ position: relative;
126
+ }
127
+ .visualizer-canvas {
128
+ background: linear-gradient(to bottom, #000510, #001030);
129
+ border: 1px solid #333366;
130
+ width: 100%;
131
+ height: 100%;
132
+ border-radius: 8px;
133
+ }
134
+ .metrics {
135
+ display: grid;
136
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
137
+ gap: 15px;
138
+ margin-top: 15px;
139
+ }
140
+ .metric-card {
141
+ background: rgba(20, 30, 50, 0.6);
142
+ padding: 15px;
143
+ border-radius: 8px;
144
+ text-align: center;
145
+ }
146
+ .metric-value {
147
+ font-size: 1.8rem;
148
+ color: #7df;
149
+ margin: 10px 0;
150
+ font-weight: bold;
151
+ }
152
+ .metric-label {
153
+ color: #adf;
154
+ font-size: 0.9rem;
155
+ }
156
+ @media (max-width: 768px) {
157
+ .column {
158
+ flex: 1 1 100%;
159
+ }
160
+ }
161
+
162
+ .user-avatar {
163
+ width: 30px;
164
+ height: 30px;
165
+ border-radius: 50%;
166
+ margin-right: 5px;
167
+ }
168
+
169
+ .users-list {
170
+ background: rgba(10, 20, 40, 0.7);
171
+ border-radius: 10px;
172
+ padding: 15px;
173
+ margin-bottom: 20px;
174
+ max-height: 150px;
175
+ overflow-y: auto;
176
+ }
177
+
178
+ .user-container {
179
+ display: flex;
180
+ align-items: center;
181
+ margin-bottom: 8px;
182
+ color: #adf;
183
+ font-size: 0.9rem;
184
+ }
185
+
186
+ .user-cursor {
187
+ position: absolute;
188
+ pointer-events: none;
189
+ z-index: 1000;
190
+ font-size: 12px;
191
+ display: flex;
192
+ flex-direction: column;
193
+ align-items: center;
194
+ }
195
+
196
+ .cursor-pointer {
197
+ width: 20px;
198
+ height: 20px;
199
+ border-radius: 50%;
200
+ }
201
+
202
+ .cursor-label {
203
+ background: rgba(0, 0, 0, 0.7);
204
+ color: white;
205
+ padding: 2px 5px;
206
+ border-radius: 3px;
207
+ margin-top: 5px;
208
+ white-space: nowrap;
209
+ }
210
+
211
+ .chat-container {
212
+ background: rgba(10, 20, 40, 0.7);
213
+ border-radius: 10px;
214
+ padding: 15px;
215
+ margin-top: 20px;
216
+ display: flex;
217
+ flex-direction: column;
218
+ height: 200px;
219
+ }
220
+
221
+ .chat-messages {
222
+ flex-grow: 1;
223
+ overflow-y: auto;
224
+ margin-bottom: 10px;
225
+ color: #ddf;
226
+ }
227
+
228
+ .chat-input-container {
229
+ display: flex;
230
+ }
231
+
232
+ .chat-input {
233
+ flex-grow: 1;
234
+ padding: 8px;
235
+ border-radius: 4px;
236
+ border: 1px solid #446;
237
+ background: #112;
238
+ color: #ddf;
239
+ margin-right: 5px;
240
+ }
241
+
242
+ .chat-send {
243
+ background: linear-gradient(45deg, #4a7bd1, #7a4ad1);
244
+ color: white;
245
+ border: none;
246
+ padding: 8px 15px;
247
+ border-radius: 5px;
248
+ cursor: pointer;
249
+ }
250
+
251
+ .message {
252
+ margin-bottom: 8px;
253
+ }
254
+
255
+ .message-user {
256
+ font-weight: bold;
257
+ color: #7cf;
258
+ }
259
+
260
+ .message-text {
261
+ color: #ccf;
262
+ }
263
+ </style>
264
+ </head>
265
+ <body>
266
+ <div class="container">
267
+ <div class="header">
268
+ <h1>Collaborative Holographic Universe Simulation</h1>
269
+ <p>Explore quantum circuits and holographic frameworks together in real-time</p>
270
+ </div>
271
+
272
+ <div class="users-list" id="users-list">
273
+ <h3>Connected Users</h3>
274
+ <div id="users-container"></div>
275
+ </div>
276
+
277
+ <div class="quantum-simulator">
278
+ <h2 class="section-title">Quantum Circuit Setup</h2>
279
+ <div class="row">
280
+ <div class="column">
281
+ <div class="control-panel">
282
+ <div class="parameter-control">
283
+ <label for="num-qubits">Number of Qubits</label>
284
+ <input type="number" id="num-qubits" min="1" max="8" value="3">
285
+ </div>
286
+ <div class="parameter-control">
287
+ <label for="num-shots">Number of Shots</label>
288
+ <input type="number" id="num-shots" min="100" max="10000" value="1024">
289
+ </div>
290
+ </div>
291
+ <div class="code-block">
292
+ <pre>
293
+ # Define a quantum register and circuit
294
+ qr = QuantumRegister(3, 'q')
295
+ cr = ClassicalRegister(3, 'c')
296
+ qc = QuantumCircuit(qr, cr)
297
+
298
+ # Apply Hadamard gates to create superposition
299
+ for i in range(qr.size()):
300
+ qc.h(qr[i])
301
+
302
+ # Apply CNOT gate to entangle qubits
303
+ qc.cx(qr[0], qr[1])
304
+
305
+ # Measure all qubits
306
+ qc.measure(qr, cr)</pre>
307
+ </div>
308
+ <button id="run-circuit">Run Quantum Circuit</button>
309
+ </div>
310
+ <div class="column">
311
+ <div class="visualization">
312
+ <canvas id="circuit-canvas" class="visualizer-canvas"></canvas>
313
+ </div>
314
+ <div class="metrics">
315
+ <div class="metric-card">
316
+ <div class="metric-label">Entanglement Measure</div>
317
+ <div class="metric-value" id="entanglement-value">0.82</div>
318
+ </div>
319
+ <div class="metric-card">
320
+ <div class="metric-label">Coherence</div>
321
+ <div class="metric-value" id="coherence-value">0.65</div>
322
+ </div>
323
+ </div>
324
+ </div>
325
+ </div>
326
+ </div>
327
+
328
+ <div class="env-setup">
329
+ <h2 class="section-title">Holographic Environment Setup</h2>
330
+ <div class="row">
331
+ <div class="column">
332
+ <div class="control-panel">
333
+ <div class="parameter-control">
334
+ <label for="time-const">Time Constant (t)</label>
335
+ <input type="number" id="time-const" min="0" max="3" value="1">
336
+ </div>
337
+ <div class="parameter-control">
338
+ <label for="space-scale">Space Scale (s)</label>
339
+ <input type="number" id="space-scale" min="0" max="3" value="2">
340
+ </div>
341
+ <div class="parameter-control">
342
+ <label for="mass-value">Mass Value (m)</label>
343
+ <input type="number" id="mass-value" min="0" max="3" value="3">
344
+ </div>
345
+ <div class="parameter-control">
346
+ <label for="dimension-num">Dimensions (d)</label>
347
+ <input type="number" id="dimension-num" min="0" max="3" value="1">
348
+ </div>
349
+ </div>
350
+ <div class="code-block">
351
+ <pre>
352
+ # Define environment variables (2-bit representations)
353
+ t = 0b01 # Planck time (scaled)
354
+ s = 0b10 # Scale of space
355
+ m = 0b11 # Simplified number of atoms
356
+ d = 0b01 # Number of dimensions
357
+
358
+ # Concatenate to form 8-bit environment label
359
+ env_label = f"{t:02b}{s:02b}{m:02b}{d:02b}"
360
+
361
+ # Create environment state vector
362
+ env_state = Statevector.from_label(env_label)</pre>
363
+ </div>
364
+ <button id="update-env">Update Environment</button>
365
+ </div>
366
+ <div class="column">
367
+ <div class="visualization">
368
+ <canvas id="environment-canvas" class="visualizer-canvas"></canvas>
369
+ </div>
370
+ <div class="metrics">
371
+ <div class="metric-card">
372
+ <div class="metric-label">Environment Label</div>
373
+ <div class="metric-value" id="env-label-value">01101101</div>
374
+ </div>
375
+ <div class="metric-card">
376
+ <div class="metric-label">State Complexity</div>
377
+ <div class="metric-value" id="complexity-value">3.14</div>
378
+ </div>
379
+ </div>
380
+ </div>
381
+ </div>
382
+ </div>
383
+
384
+ <div class="analysis">
385
+ <h2 class="section-title">Analysis and Results</h2>
386
+ <div class="row">
387
+ <div class="column">
388
+ <div class="visualization">
389
+ <canvas id="histogram-canvas" class="visualizer-canvas"></canvas>
390
+ </div>
391
+ <div class="metrics">
392
+ <div class="metric-card">
393
+ <div class="metric-label">Mean Count</div>
394
+ <div class="metric-value" id="mean-count">128.00</div>
395
+ </div>
396
+ <div class="metric-card">
397
+ <div class="metric-label">Variance</div>
398
+ <div class="metric-value" id="variance-count">42.56</div>
399
+ </div>
400
+ </div>
401
+ </div>
402
+ <div class="column">
403
+ <div class="visualization">
404
+ <canvas id="evolution-canvas" class="visualizer-canvas"></canvas>
405
+ </div>
406
+ <div class="metrics">
407
+ <div class="metric-card">
408
+ <div class="metric-label">State Fidelity</div>
409
+ <div class="metric-value" id="fidelity-value">0.78</div>
410
+ </div>
411
+ <div class="metric-card">
412
+ <div class="metric-label">Quantum Entropy</div>
413
+ <div class="metric-value" id="entropy-value">1.23</div>
414
+ </div>
415
+ </div>
416
+ </div>
417
+ </div>
418
+ <button id="run-analysis">Run Full Analysis</button>
419
+ </div>
420
+
421
+ <div class="chat-container">
422
+ <div class="chat-messages" id="chat-messages"></div>
423
+ <div class="chat-input-container">
424
+ <input type="text" class="chat-input" id="chat-input" placeholder="Type your message...">
425
+ <button class="chat-send" id="chat-send">Send</button>
426
+ </div>
427
+ </div>
428
+ </div>
429
+
430
+ <script>
431
+ // Initialize WebSocket for multiplayer functionality
432
+ const room = new WebsimSocket();
433
+ let clientId, username;
434
+ const cursors = {};
435
+
436
+ // Map to track user colors
437
+ const userColors = {};
438
+
439
+ // Track when user last moved cursor (to avoid too many updates)
440
+ let lastCursorUpdate = 0;
441
+
442
+ // Initialize canvases
443
+ const canvases = {
444
+ circuit: document.getElementById('circuit-canvas'),
445
+ environment: document.getElementById('environment-canvas'),
446
+ histogram: document.getElementById('histogram-canvas'),
447
+ evolution: document.getElementById('evolution-canvas')
448
+ };
449
+
450
+ // Initialize contexts
451
+ const contexts = {};
452
+ for (const [key, canvas] of Object.entries(canvases)) {
453
+ contexts[key] = canvas.getContext('2d');
454
+ canvas.width = canvas.clientWidth;
455
+ canvas.height = canvas.clientHeight;
456
+ }
457
+
458
+ // Simulation state
459
+ const state = {
460
+ qubits: 3,
461
+ shots: 1024,
462
+ environmentParams: {
463
+ t: 1, // Time constant
464
+ s: 2, // Space scale
465
+ m: 3, // Mass value
466
+ d: 1 // Dimensions
467
+ },
468
+ measurements: {},
469
+ environmentState: {},
470
+ statistics: {
471
+ mean: 128.0,
472
+ variance: 42.56,
473
+ fidelity: 0.78,
474
+ entropy: 1.23,
475
+ entanglement: 0.82,
476
+ coherence: 0.65,
477
+ complexity: 3.14
478
+ }
479
+ };
480
+
481
+ // Draw quantum circuit visualization
482
+ function drawCircuit() {
483
+ const ctx = contexts.circuit;
484
+ const width = canvases.circuit.width;
485
+ const height = canvases.circuit.height;
486
+
487
+ ctx.clearRect(0, 0, width, height);
488
+
489
+ // Draw background grid
490
+ ctx.strokeStyle = 'rgba(100, 150, 255, 0.1)';
491
+ ctx.lineWidth = 1;
492
+
493
+ const gridSize = 20;
494
+
495
+ for (let x = 0; x <= width; x += gridSize) {
496
+ ctx.beginPath();
497
+ ctx.moveTo(x, 0);
498
+ ctx.lineTo(x, height);
499
+ ctx.stroke();
500
+ }
501
+
502
+ for (let y = 0; y <= height; y += gridSize) {
503
+ ctx.beginPath();
504
+ ctx.moveTo(0, y);
505
+ ctx.lineTo(width, y);
506
+ ctx.stroke();
507
+ }
508
+
509
+ // Draw qubit lines
510
+ const qubitSpacing = height / (state.qubits + 1);
511
+
512
+ ctx.strokeStyle = 'rgba(100, 200, 255, 0.8)';
513
+ ctx.lineWidth = 2;
514
+
515
+ for (let i = 0; i < state.qubits; i++) {
516
+ const y = (i + 1) * qubitSpacing;
517
+
518
+ ctx.beginPath();
519
+ ctx.moveTo(50, y);
520
+ ctx.lineTo(width - 50, y);
521
+ ctx.stroke();
522
+
523
+ // Qubit label
524
+ ctx.fillStyle = 'rgba(150, 220, 255, 0.8)';
525
+ ctx.font = '12px Arial';
526
+ ctx.textAlign = 'right';
527
+ ctx.fillText(`q${i}`, 40, y + 4);
528
+ }
529
+
530
+ // Draw Hadamard gates
531
+ const gateWidth = 30;
532
+ const gateHeight = 30;
533
+ const hGateX = 100;
534
+
535
+ for (let i = 0; i < state.qubits; i++) {
536
+ const y = (i + 1) * qubitSpacing - gateHeight / 2;
537
+
538
+ ctx.fillStyle = 'rgba(100, 150, 255, 0.7)';
539
+ ctx.fillRect(hGateX, y, gateWidth, gateHeight);
540
+
541
+ ctx.fillStyle = 'white';
542
+ ctx.font = 'bold 16px Arial';
543
+ ctx.textAlign = 'center';
544
+ ctx.textBaseline = 'middle';
545
+ ctx.fillText('H', hGateX + gateWidth / 2, y + gateHeight / 2);
546
+ }
547
+
548
+ // Draw CNOT gate
549
+ const cnotX = 200;
550
+ const controlY = 1 * qubitSpacing;
551
+ const targetY = 2 * qubitSpacing;
552
+
553
+ // Control point
554
+ ctx.fillStyle = 'rgba(255, 100, 100, 0.8)';
555
+ ctx.beginPath();
556
+ ctx.arc(cnotX, controlY, 5, 0, Math.PI * 2);
557
+ ctx.fill();
558
+
559
+ // Line connecting control and target
560
+ ctx.strokeStyle = 'rgba(255, 100, 100, 0.8)';
561
+ ctx.beginPath();
562
+ ctx.moveTo(cnotX, controlY);
563
+ ctx.lineTo(cnotX, targetY);
564
+ ctx.stroke();
565
+
566
+ // Target circle
567
+ ctx.beginPath();
568
+ ctx.arc(cnotX, targetY, 15, 0, Math.PI * 2);
569
+ ctx.stroke();
570
+
571
+ // Plus symbol
572
+ ctx.beginPath();
573
+ ctx.moveTo(cnotX - 10, targetY);
574
+ ctx.lineTo(cnotX + 10, targetY);
575
+ ctx.moveTo(cnotX, targetY - 10);
576
+ ctx.lineTo(cnotX, targetY + 10);
577
+ ctx.stroke();
578
+
579
+ // Draw measurement operations
580
+ const measureX = 300;
581
+
582
+ for (let i = 0; i < state.qubits; i++) {
583
+ const y = (i + 1) * qubitSpacing;
584
+
585
+ // Measurement symbol
586
+ ctx.strokeStyle = 'rgba(150, 255, 150, 0.8)';
587
+ ctx.fillStyle = 'rgba(100, 200, 100, 0.3)';
588
+
589
+ // Box
590
+ ctx.fillRect(measureX, y - 15, 40, 30);
591
+ ctx.strokeRect(measureX, y - 15, 40, 30);
592
+
593
+ // Meter symbol
594
+ ctx.beginPath();
595
+ ctx.moveTo(measureX + 10, y - 5);
596
+ ctx.lineTo(measureX + 10, y + 5);
597
+ ctx.lineTo(measureX + 30, y - 5);
598
+ ctx.lineTo(measureX + 30, y + 5);
599
+ ctx.stroke();
600
+ }
601
+ }
602
+
603
+ // Draw holographic environment visualization
604
+ function drawEnvironment() {
605
+ const ctx = contexts.environment;
606
+ const width = canvases.environment.width;
607
+ const height = canvases.environment.height;
608
+
609
+ ctx.clearRect(0, 0, width, height);
610
+
611
+ // Draw background
612
+ const gradient = ctx.createLinearGradient(0, 0, width, height);
613
+ gradient.addColorStop(0, 'rgba(0, 10, 30, 0.5)');
614
+ gradient.addColorStop(1, 'rgba(30, 0, 60, 0.5)');
615
+
616
+ ctx.fillStyle = gradient;
617
+ ctx.fillRect(0, 0, width, height);
618
+
619
+ // Update environment label display
620
+ const envLabel = `${state.environmentParams.t.toString(2).padStart(2, '0')}${state.environmentParams.s.toString(2).padStart(2, '0')}${state.environmentParams.m.toString(2).padStart(2, '0')}${state.environmentParams.d.toString(2).padStart(2, '0')}`;
621
+ document.getElementById('env-label-value').textContent = envLabel;
622
+
623
+ // Draw bit representations
624
+ const bitSize = 30;
625
+ const startX = width / 2 - (8 * bitSize) / 2;
626
+ const y = height / 2;
627
+
628
+ for (let i = 0; i < 8; i++) {
629
+ const x = startX + i * bitSize;
630
+ const bitValue = envLabel[i];
631
+
632
+ ctx.fillStyle = bitValue === '1' ? 'rgba(100, 200, 255, 0.8)' : 'rgba(50, 50, 100, 0.5)';
633
+ ctx.fillRect(x, y - bitSize / 2, bitSize - 2, bitSize);
634
+
635
+ ctx.fillStyle = 'white';
636
+ ctx.font = '14px Arial';
637
+ ctx.textAlign = 'center';
638
+ ctx.textBaseline = 'middle';
639
+ ctx.fillText(bitValue, x + bitSize / 2 - 1, y);
640
+ }
641
+
642
+ // Draw parameter indicators
643
+ const paramRadius = 50;
644
+ const centerX = width / 2;
645
+ const centerY = height / 2 - 70;
646
+
647
+ // Draw parameter circles
648
+ const params = [
649
+ { name: 't', value: state.environmentParams.t, color: 'rgba(255, 100, 100, 0.7)' },
650
+ { name: 's', value: state.environmentParams.s, color: 'rgba(100, 255, 100, 0.7)' },
651
+ { name: 'm', value: state.environmentParams.m, color: 'rgba(100, 100, 255, 0.7)' },
652
+ { name: 'd', value: state.environmentParams.d, color: 'rgba(255, 255, 100, 0.7)' }
653
+ ];
654
+
655
+ for (let i = 0; i < params.length; i++) {
656
+ const angle = (i * Math.PI / 2) - Math.PI / 4;
657
+ const x = centerX + Math.cos(angle) * paramRadius;
658
+ const y = centerY + Math.sin(angle) * paramRadius;
659
+ const param = params[i];
660
+
661
+ // Circle
662
+ ctx.fillStyle = param.color;
663
+ ctx.beginPath();
664
+ ctx.arc(x, y, 20, 0, Math.PI * 2);
665
+ ctx.fill();
666
+
667
+ // Label
668
+ ctx.fillStyle = 'white';
669
+ ctx.font = 'bold 16px Arial';
670
+ ctx.textAlign = 'center';
671
+ ctx.textBaseline = 'middle';
672
+ ctx.fillText(param.name, x, y - 2);
673
+
674
+ // Value
675
+ ctx.font = '12px Arial';
676
+ ctx.fillText(param.value, x, y + 12);
677
+ }
678
+
679
+ // Draw connecting lines
680
+ ctx.strokeStyle = 'rgba(150, 150, 255, 0.4)';
681
+ ctx.lineWidth = 1;
682
+
683
+ for (let i = 0; i < params.length; i++) {
684
+ const angle1 = (i * Math.PI / 2) - Math.PI / 4;
685
+ const x1 = centerX + Math.cos(angle1) * paramRadius;
686
+ const y1 = centerY + Math.sin(angle1) * paramRadius;
687
+
688
+ for (let j = i + 1; j < params.length; j++) {
689
+ const angle2 = (j * Math.PI / 2) - Math.PI / 4;
690
+ const x2 = centerX + Math.cos(angle2) * paramRadius;
691
+ const y2 = centerY + Math.sin(angle2) * paramRadius;
692
+
693
+ ctx.beginPath();
694
+ ctx.moveTo(x1, y1);
695
+ ctx.lineTo(x2, y2);
696
+ ctx.stroke();
697
+ }
698
+ }
699
+
700
+ // Draw holographic effect
701
+ for (let i = 0; i < 50; i++) {
702
+ const angle = Math.random() * Math.PI * 2;
703
+ const distance = Math.random() * 100 + 30;
704
+ const x = centerX + Math.cos(angle) * distance;
705
+ const y = centerY + Math.sin(angle) * distance;
706
+
707
+ ctx.fillStyle = `rgba(150, 220, 255, ${Math.random() * 0.2})`;
708
+ ctx.beginPath();
709
+ ctx.arc(x, y, Math.random() * 5 + 1, 0, Math.PI * 2);
710
+ ctx.fill();
711
+ }
712
+
713
+ // Update complexity metric
714
+ const complexity = (1 + Math.sin(Date.now() / 1000) * 0.1) * 3.14;
715
+ document.getElementById('complexity-value').textContent = complexity.toFixed(2);
716
+ }
717
+
718
+ // Draw measurement histogram
719
+ function drawHistogram() {
720
+ const ctx = contexts.histogram;
721
+ const width = canvases.histogram.width;
722
+ const height = canvases.histogram.height;
723
+
724
+ ctx.clearRect(0, 0, width, height);
725
+
726
+ // Generate some sample measurement data based on current qubits
727
+ const possibleOutcomes = Math.pow(2, state.qubits);
728
+ const measurements = {};
729
+ let total = 0;
730
+
731
+ // Create plausible quantum distribution
732
+ for (let i = 0; i < possibleOutcomes; i++) {
733
+ const bitString = i.toString(2).padStart(state.qubits, '0');
734
+
735
+ // Generate values with a slight bias towards balanced states
736
+ let probability = Math.random();
737
+
738
+ // Add interference pattern for more realistic quantum results
739
+ const hammingWeight = bitString.split('').filter(bit => bit === '1').length;
740
+ const balance = Math.abs(hammingWeight - state.qubits / 2) / state.qubits;
741
+ probability = probability * (1 - balance * 0.5);
742
+
743
+ // Add entanglement effect (correlations between bits 0 and 1)
744
+ if (state.qubits >= 2 && bitString[0] === bitString[1]) {
745
+ probability *= 1.5;
746
+ }
747
+
748
+ const count = Math.floor(probability * state.shots / possibleOutcomes * 2);
749
+ measurements[bitString] = count;
750
+ total += count;
751
+ }
752
+
753
+ // Normalize to ensure total equals shots
754
+ for (const outcome in measurements) {
755
+ measurements[outcome] = Math.floor(measurements[outcome] * state.shots / total);
756
+ }
757
+
758
+ // Calculate statistics
759
+ const values = Object.values(measurements);
760
+ const mean = values.reduce((sum, val) => sum + val, 0) / values.length;
761
+ const variance = values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / values.length;
762
+
763
+ state.statistics.mean = mean;
764
+ state.statistics.variance = variance;
765
+
766
+ // Update metrics display
767
+ document.getElementById('mean-count').textContent = mean.toFixed(2);
768
+ document.getElementById('variance-count').textContent = variance.toFixed(2);
769
+
770
+ // Draw histogram
771
+ const outcomes = Object.keys(measurements).sort();
772
+ const barWidth = width / outcomes.length;
773
+ const maxHeight = height - 40;
774
+ const maxCount = Math.max(...Object.values(measurements));
775
+
776
+ // Draw bars
777
+ for (let i = 0; i < outcomes.length; i++) {
778
+ const outcome = outcomes[i];
779
+ const count = measurements[outcome];
780
+ const barHeight = (count / maxCount) * maxHeight;
781
+
782
+ const hue = 240 - (i / outcomes.length) * 60;
783
+ ctx.fillStyle = `hsla(${hue}, 80%, 60%, 0.7)`;
784
+
785
+ ctx.fillRect(i * barWidth, height - barHeight - 30, barWidth - 2, barHeight);
786
+
787
+ // Label for bar
788
+ if (barWidth > 25) {
789
+ ctx.fillStyle = 'white';
790
+ ctx.font = '10px Arial';
791
+ ctx.textAlign = 'center';
792
+ ctx.textBaseline = 'top';
793
+ ctx.fillText(outcome, i * barWidth + barWidth / 2, height - 25);
794
+ }
795
+ }
796
+
797
+ // Draw axes
798
+ ctx.strokeStyle = 'rgba(200, 200, 255, 0.5)';
799
+ ctx.lineWidth = 1;
800
+
801
+ // X axis
802
+ ctx.beginPath();
803
+ ctx.moveTo(0, height - 30);
804
+ ctx.lineTo(width, height - 30);
805
+ ctx.stroke();
806
+
807
+ // Y axis
808
+ ctx.beginPath();
809
+ ctx.moveTo(0, 0);
810
+ ctx.lineTo(0, height - 30);
811
+ ctx.stroke();
812
+
813
+ // Y axis label
814
+ ctx.save();
815
+ ctx.translate(15, height / 2);
816
+ ctx.rotate(-Math.PI / 2);
817
+ ctx.fillStyle = 'rgba(200, 200, 255, 0.8)';
818
+ ctx.font = '12px Arial';
819
+ ctx.textAlign = 'center';
820
+ ctx.fillText('Counts', 0, 0);
821
+ ctx.restore();
822
+
823
+ // X axis label
824
+ ctx.fillStyle = 'rgba(200, 200, 255, 0.8)';
825
+ ctx.font = '12px Arial';
826
+ ctx.textAlign = 'center';
827
+ ctx.textBaseline = 'top';
828
+ ctx.fillText('Measurement Outcomes', width / 2, height - 10);
829
+ }
830
+
831
+ // Draw state evolution visualization
832
+ function drawEvolution() {
833
+ const ctx = contexts.evolution;
834
+ const width = canvases.evolution.width;
835
+ const height = canvases.evolution.height;
836
+
837
+ ctx.clearRect(0, 0, width, height);
838
+
839
+ // Create gradient background
840
+ const gradient = ctx.createRadialGradient(width / 2, height / 2, 0, width / 2, height / 2, height / 2);
841
+ gradient.addColorStop(0, 'rgba(10, 20, 40, 0.8)');
842
+ gradient.addColorStop(1, 'rgba(0, 5, 20, 0.8)');
843
+
844
+ ctx.fillStyle = gradient;
845
+ ctx.fillRect(0, 0, width, height);
846
+
847
+ // Draw evolution effect
848
+ const time = Date.now() / 1000;
849
+ const centerX = width / 2;
850
+ const centerY = height / 2;
851
+
852
+ // Draw quantum state amplitudes
853
+ const stateCount = Math.pow(2, state.qubits);
854
+ const radius = Math.min(width, height) * 0.35;
855
+
856
+ for (let i = 0; i < stateCount; i++) {
857
+ const angle = (i / stateCount) * Math.PI * 2;
858
+ const x = centerX + Math.cos(angle) * radius;
859
+ const y = centerY + Math.sin(angle) * radius;
860
+
861
+ // Amplitude visualization
862
+ const amplitude = 0.3 + 0.7 * Math.abs(Math.sin(time + i * 0.7));
863
+
864
+ // State vector
865
+ ctx.strokeStyle = `rgba(100, 200, 255, ${amplitude * 0.7})`;
866
+ ctx.lineWidth = 2;
867
+
868
+ ctx.beginPath();
869
+ ctx.moveTo(centerX, centerY);
870
+ ctx.lineTo(x, y);
871
+ ctx.stroke();
872
+
873
+ // Amplitude point
874
+ ctx.fillStyle = `rgba(150, 220, 255, ${amplitude})`;
875
+ ctx.beginPath();
876
+ ctx.arc(x, y, 5 + amplitude * 3, 0, Math.PI * 2);
877
+ ctx.fill();
878
+
879
+ // State label
880
+ const bitString = i.toString(2).padStart(state.qubits, '0');
881
+ ctx.fillStyle = 'rgba(255, 255, 255, 0.7)';
882
+ ctx.font = '10px Arial';
883
+ ctx.textAlign = 'center';
884
+ ctx.textBaseline = 'middle';
885
+
886
+ const textX = centerX + Math.cos(angle) * (radius + 15);
887
+ const textY = centerY + Math.sin(angle) * (radius + 15);
888
+ ctx.fillText(bitString, textX, textY);
889
+ }
890
+
891
+ // Draw environment influence (adaptive effects)
892
+ const envInfluence = Math.sin(time * 0.5) * 0.5 + 0.5;
893
+
894
+ // Draw interference pattern
895
+ ctx.strokeStyle = `rgba(100, 255, 200, ${0.1 + envInfluence * 0.2})`;
896
+ ctx.lineWidth = 1;
897
+
898
+ for (let i = 0; i < stateCount; i++) {
899
+ const angle1 = (i / stateCount) * Math.PI * 2;
900
+ const x1 = centerX + Math.cos(angle1) * radius;
901
+ const y1 = centerY + Math.sin(angle1) * radius;
902
+
903
+ for (let j = i + 1; j < stateCount; j++) {
904
+ // Only connect interfering states
905
+ if ((i ^ j) & 1) {
906
+ const angle2 = (j / stateCount) * Math.PI * 2;
907
+ const x2 = centerX + Math.cos(angle2) * radius;
908
+ const y2 = centerY + Math.sin(angle2) * radius;
909
+
910
+ // Draw interference line
911
+ ctx.beginPath();
912
+ ctx.moveTo(x1, y1);
913
+ ctx.lineTo(x2, y2);
914
+ ctx.stroke();
915
+ }
916
+ }
917
+ }
918
+
919
+ // Draw holographic projection
920
+ ctx.fillStyle = `rgba(100, 200, 255, ${0.05 + envInfluence * 0.1})`;
921
+
922
+ for (let i = 0; i < 3; i++) {
923
+ const projRadius = radius * (0.5 + i * 0.2);
924
+
925
+ ctx.beginPath();
926
+ ctx.arc(centerX, centerY, projRadius, 0, Math.PI * 2);
927
+ ctx.fill();
928
+ }
929
+
930
+ // Update metrics based on time
931
+ const fidelity = 0.5 + 0.3 * Math.sin(time * 0.3);
932
+ const entropy = 1 + 0.3 * Math.cos(time * 0.7);
933
+ const entanglement = 0.7 + 0.2 * Math.sin(time * 0.5);
934
+ const coherence = 0.5 + 0.2 * Math.cos(time * 0.4);
935
+
936
+ // Update metrics display
937
+ document.getElementById('fidelity-value').textContent = fidelity.toFixed(2);
938
+ document.getElementById('entropy-value').textContent = entropy.toFixed(2);
939
+ document.getElementById('entanglement-value').textContent = entanglement.toFixed(2);
940
+ document.getElementById('coherence-value').textContent = coherence.toFixed(2);
941
+ }
942
+
943
+ // Initialize multiplayer functionality
944
+ function initMultiplayer() {
945
+ // Get client info
946
+ clientId = room.party.client.id;
947
+ username = room.party.client.username;
948
+
949
+ // Setup message handler
950
+ room.onmessage = (event) => {
951
+ const data = event.data;
952
+ switch (data.type) {
953
+ case "connected":
954
+ addUserToList(data.clientId, data.username);
955
+ addSystemMessage(`${data.username} joined the simulation`);
956
+ break;
957
+ case "disconnected":
958
+ removeUserFromList(data.clientId);
959
+ removeCursor(data.clientId);
960
+ addSystemMessage(`${data.username} left the simulation`);
961
+ break;
962
+ case "chat":
963
+ addChatMessage(data.username, data.message);
964
+ break;
965
+ case "cursor_move":
966
+ updateCursor(data.clientId, data.x, data.y, data.username);
967
+ break;
968
+ case "parameter_change":
969
+ handleParameterChange(data.parameter, data.value, data.username);
970
+ break;
971
+ case "run_circuit":
972
+ handleRunCircuit(data.username);
973
+ break;
974
+ case "update_env":
975
+ handleUpdateEnv(data.username);
976
+ break;
977
+ case "run_analysis":
978
+ handleRunAnalysis(data.username);
979
+ break;
980
+ }
981
+ };
982
+
983
+ // Listen for mouse movement to broadcast cursor position
984
+ document.addEventListener('mousemove', (e) => {
985
+ const now = Date.now();
986
+ if (now - lastCursorUpdate > 50) { // Limit updates to every 50ms
987
+ lastCursorUpdate = now;
988
+ room.send({
989
+ type: "cursor_move",
990
+ x: e.clientX,
991
+ y: e.clientY
992
+ });
993
+ }
994
+ });
995
+
996
+ // Setup chat functionality
997
+ document.getElementById('chat-send').addEventListener('click', sendChatMessage);
998
+ document.getElementById('chat-input').addEventListener('keypress', (e) => {
999
+ if (e.key === 'Enter') {
1000
+ sendChatMessage();
1001
+ }
1002
+ });
1003
+
1004
+ // Update existing button handlers to broadcast events
1005
+ document.getElementById('run-circuit').addEventListener('click', function() {
1006
+ // Existing handler code
1007
+ drawCircuit();
1008
+ setTimeout(() => {
1009
+ drawHistogram();
1010
+ drawEvolution();
1011
+ }, 500);
1012
+
1013
+ // Broadcast the event
1014
+ room.send({
1015
+ type: "run_circuit"
1016
+ });
1017
+ });
1018
+
1019
+ document.getElementById('update-env').addEventListener('click', function() {
1020
+ // Existing handler code
1021
+ drawEnvironment();
1022
+ setTimeout(() => {
1023
+ drawEvolution();
1024
+ }, 500);
1025
+
1026
+ // Broadcast the event
1027
+ room.send({
1028
+ type: "update_env"
1029
+ });
1030
+ });
1031
+
1032
+ document.getElementById('run-analysis').addEventListener('click', function() {
1033
+ // Existing handler code
1034
+ drawCircuit();
1035
+ setTimeout(() => {
1036
+ drawEnvironment();
1037
+ setTimeout(() => {
1038
+ drawHistogram();
1039
+ setTimeout(() => {
1040
+ drawEvolution();
1041
+ }, 300);
1042
+ }, 300);
1043
+ }, 300);
1044
+
1045
+ // Broadcast the event
1046
+ room.send({
1047
+ type: "run_analysis"
1048
+ });
1049
+ });
1050
+
1051
+ // Update input handlers to broadcast parameter changes
1052
+ const parameterInputs = [
1053
+ 'num-qubits', 'num-shots', 'time-const',
1054
+ 'space-scale', 'mass-value', 'dimension-num'
1055
+ ];
1056
+
1057
+ parameterInputs.forEach(inputId => {
1058
+ const inputElement = document.getElementById(inputId);
1059
+
1060
+ // Store original event handler
1061
+ const originalHandler = inputElement.onchange;
1062
+
1063
+ // Add new handler that broadcasts changes
1064
+ inputElement.addEventListener('change', function(e) {
1065
+ // Call original handler if it exists
1066
+ if (originalHandler) originalHandler(e);
1067
+
1068
+ // Broadcast parameter change
1069
+ room.send({
1070
+ type: "parameter_change",
1071
+ parameter: inputId,
1072
+ value: parseInt(e.target.value)
1073
+ });
1074
+ });
1075
+ });
1076
+
1077
+ // Initialize users list
1078
+ updateUsersList();
1079
+ }
1080
+
1081
+ // Add user to the connected users list
1082
+ function addUserToList(userId, userName) {
1083
+ if (!userColors[userId]) {
1084
+ // Assign a random color for this user
1085
+ const hue = Math.floor(Math.random() * 360);
1086
+ userColors[userId] = `hsl(${hue}, 70%, 60%)`;
1087
+ }
1088
+
1089
+ updateUsersList();
1090
+ }
1091
+
1092
+ // Remove user from the connected users list
1093
+ function removeUserFromList(userId) {
1094
+ updateUsersList();
1095
+ }
1096
+
1097
+ // Update the entire users list
1098
+ function updateUsersList() {
1099
+ const usersContainer = document.getElementById('users-container');
1100
+ usersContainer.innerHTML = '';
1101
+
1102
+ for (const clientId in room.party.peers) {
1103
+ const { username } = room.party.peers[clientId];
1104
+ const color = userColors[clientId] || 'hsl(200, 70%, 60%)';
1105
+
1106
+ const userDiv = document.createElement('div');
1107
+ userDiv.className = 'user-container';
1108
+
1109
+ const userAvatar = document.createElement('div');
1110
+ userAvatar.className = 'user-avatar';
1111
+ userAvatar.style.backgroundColor = color;
1112
+
1113
+ const userNameSpan = document.createElement('span');
1114
+ userNameSpan.textContent = username;
1115
+
1116
+ userDiv.appendChild(userAvatar);
1117
+ userDiv.appendChild(userNameSpan);
1118
+ usersContainer.appendChild(userDiv);
1119
+ }
1120
+ }
1121
+
1122
+ // Update cursor position for a specific user
1123
+ function updateCursor(userId, x, y, userName) {
1124
+ // Don't show the current user's cursor
1125
+ if (userId === clientId) return;
1126
+
1127
+ let cursor = cursors[userId];
1128
+ if (!cursor) {
1129
+ // Create cursor element if it doesn't exist
1130
+ cursor = document.createElement('div');
1131
+ cursor.className = 'user-cursor';
1132
+
1133
+ const pointer = document.createElement('div');
1134
+ pointer.className = 'cursor-pointer';
1135
+
1136
+ const label = document.createElement('div');
1137
+ label.className = 'cursor-label';
1138
+ label.textContent = userName;
1139
+
1140
+ cursor.appendChild(pointer);
1141
+ cursor.appendChild(label);
1142
+ document.body.appendChild(cursor);
1143
+
1144
+ cursors[userId] = cursor;
1145
+ }
1146
+
1147
+ // Get user's color or assign a new one
1148
+ if (!userColors[userId]) {
1149
+ const hue = Math.floor(Math.random() * 360);
1150
+ userColors[userId] = `hsl(${hue}, 70%, 60%)`;
1151
+ }
1152
+
1153
+ // Update cursor position and color
1154
+ cursor.style.left = `${x}px`;
1155
+ cursor.style.top = `${y}px`;
1156
+ cursor.querySelector('.cursor-pointer').style.backgroundColor = userColors[userId];
1157
+ }
1158
+
1159
+ // Remove cursor for a disconnected user
1160
+ function removeCursor(userId) {
1161
+ if (cursors[userId]) {
1162
+ document.body.removeChild(cursors[userId]);
1163
+ delete cursors[userId];
1164
+ }
1165
+ }
1166
+
1167
+ // Send a chat message
1168
+ function sendChatMessage() {
1169
+ const inputElement = document.getElementById('chat-input');
1170
+ const message = inputElement.value.trim();
1171
+
1172
+ if (message) {
1173
+ room.send({
1174
+ type: "chat",
1175
+ message: message
1176
+ });
1177
+
1178
+ addChatMessage(username, message);
1179
+ inputElement.value = '';
1180
+ }
1181
+ }
1182
+
1183
+ // Add a message to the chat box
1184
+ function addChatMessage(userName, message) {
1185
+ const messagesContainer = document.getElementById('chat-messages');
1186
+
1187
+ const messageDiv = document.createElement('div');
1188
+ messageDiv.className = 'message';
1189
+
1190
+ const userSpan = document.createElement('span');
1191
+ userSpan.className = 'message-user';
1192
+ userSpan.textContent = `${userName}: `;
1193
+
1194
+ const textSpan = document.createElement('span');
1195
+ textSpan.className = 'message-text';
1196
+ textSpan.textContent = message;
1197
+
1198
+ messageDiv.appendChild(userSpan);
1199
+ messageDiv.appendChild(textSpan);
1200
+ messagesContainer.appendChild(messageDiv);
1201
+
1202
+ // Auto-scroll to the bottom
1203
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
1204
+ }
1205
+
1206
+ // Add a system message
1207
+ function addSystemMessage(message) {
1208
+ const messagesContainer = document.getElementById('chat-messages');
1209
+
1210
+ const messageDiv = document.createElement('div');
1211
+ messageDiv.className = 'message';
1212
+ messageDiv.style.color = '#8cf';
1213
+ messageDiv.style.fontStyle = 'italic';
1214
+ messageDiv.textContent = message;
1215
+
1216
+ messagesContainer.appendChild(messageDiv);
1217
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
1218
+ }
1219
+
1220
+ // Handle parameter change events from other users
1221
+ function handleParameterChange(paramId, value, userName) {
1222
+ const inputElement = document.getElementById(paramId);
1223
+ if (inputElement) {
1224
+ inputElement.value = value;
1225
+
1226
+ // Update the state accordingly
1227
+ if (paramId === 'num-qubits') {
1228
+ state.qubits = value;
1229
+ drawCircuit();
1230
+ drawHistogram();
1231
+ drawEvolution();
1232
+ } else if (paramId === 'num-shots') {
1233
+ state.shots = value;
1234
+ drawHistogram();
1235
+ } else if (paramId === 'time-const') {
1236
+ state.environmentParams.t = value;
1237
+ drawEnvironment();
1238
+ } else if (paramId === 'space-scale') {
1239
+ state.environmentParams.s = value;
1240
+ drawEnvironment();
1241
+ } else if (paramId === 'mass-value') {
1242
+ state.environmentParams.m = value;
1243
+ drawEnvironment();
1244
+ } else if (paramId === 'dimension-num') {
1245
+ state.environmentParams.d = value;
1246
+ drawEnvironment();
1247
+ }
1248
+
1249
+ addSystemMessage(`${userName} changed ${paramId} to ${value}`);
1250
+ }
1251
+ }
1252
+
1253
+ // Handle run circuit events from other users
1254
+ function handleRunCircuit(userName) {
1255
+ addSystemMessage(`${userName} ran the quantum circuit`);
1256
+ }
1257
+
1258
+ // Handle update environment events from other users
1259
+ function handleUpdateEnv(userName) {
1260
+ addSystemMessage(`${userName} updated the environment`);
1261
+ }
1262
+
1263
+ // Handle run analysis events from other users
1264
+ function handleRunAnalysis(userName) {
1265
+ addSystemMessage(`${userName} ran a full analysis`);
1266
+ }
1267
+
1268
+ // Modify the initialize function to include multiplayer
1269
+ function initialize() {
1270
+ // Set up input event handlers
1271
+ document.getElementById('num-qubits').addEventListener('change', function(e) {
1272
+ state.qubits = parseInt(e.target.value);
1273
+ drawCircuit();
1274
+ drawHistogram();
1275
+ drawEvolution();
1276
+ });
1277
+
1278
+ document.getElementById('num-shots').addEventListener('change', function(e) {
1279
+ state.shots = parseInt(e.target.value);
1280
+ drawHistogram();
1281
+ });
1282
+
1283
+ document.getElementById('time-const').addEventListener('change', function(e) {
1284
+ state.environmentParams.t = parseInt(e.target.value);
1285
+ drawEnvironment();
1286
+ });
1287
+
1288
+ document.getElementById('space-scale').addEventListener('change', function(e) {
1289
+ state.environmentParams.s = parseInt(e.target.value);
1290
+ drawEnvironment();
1291
+ });
1292
+
1293
+ document.getElementById('mass-value').addEventListener('change', function(e) {
1294
+ state.environmentParams.m = parseInt(e.target.value);
1295
+ drawEnvironment();
1296
+ });
1297
+
1298
+ document.getElementById('dimension-num').addEventListener('change', function(e) {
1299
+ state.environmentParams.d = parseInt(e.target.value);
1300
+ drawEnvironment();
1301
+ });
1302
+
1303
+ // Set up button event handlers
1304
+ document.getElementById('run-circuit').addEventListener('click', function() {
1305
+ // Simulate running circuit
1306
+ drawCircuit();
1307
+ setTimeout(() => {
1308
+ drawHistogram();
1309
+ drawEvolution();
1310
+ }, 500);
1311
+ });
1312
+
1313
+ document.getElementById('update-env').addEventListener('click', function() {
1314
+ // Simulate updating environment
1315
+ drawEnvironment();
1316
+ setTimeout(() => {
1317
+ drawEvolution();
1318
+ }, 500);
1319
+ });
1320
+
1321
+ document.getElementById('run-analysis').addEventListener('click', function() {
1322
+ // Simulate full analysis
1323
+ drawCircuit();
1324
+ setTimeout(() => {
1325
+ drawEnvironment();
1326
+ setTimeout(() => {
1327
+ drawHistogram();
1328
+ setTimeout(() => {
1329
+ drawEvolution();
1330
+ }, 300);
1331
+ }, 300);
1332
+ }, 300);
1333
+ });
1334
+
1335
+ // Initial draw
1336
+ drawCircuit();
1337
+ drawEnvironment();
1338
+ drawHistogram();
1339
+ drawEvolution();
1340
+
1341
+ // Animation loop for evolution visualization
1342
+ function animate() {
1343
+ drawEvolution();
1344
+ requestAnimationFrame(animate);
1345
+ }
1346
+
1347
+ animate();
1348
+
1349
+ // Initialize multiplayer functionality
1350
+ initMultiplayer();
1351
+ }
1352
+
1353
+ // Handle window resize
1354
+ window.addEventListener('resize', function() {
1355
+ for (const canvas of Object.values(canvases)) {
1356
+ canvas.width = canvas.clientWidth;
1357
+ canvas.height = canvas.clientHeight;
1358
+ }
1359
+
1360
+ drawCircuit();
1361
+ drawEnvironment();
1362
+ drawHistogram();
1363
+ drawEvolution();
1364
+ });
1365
+
1366
+ // Start the simulation
1367
+ initialize();
1368
+ </script>
1369
+ </body>
1370
  </html>