kolaslab commited on
Commit
1b10f5c
1 Parent(s): d1bc016

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +285 -210
index.html CHANGED
@@ -3,285 +3,360 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>3D Audio Spectrum Analyzer</title>
7
  <style>
8
  * {
9
  margin: 0;
10
  padding: 0;
11
  box-sizing: border-box;
12
- font-family: Arial, sans-serif;
13
  }
14
 
15
  body {
16
- background: #1a1a1a;
17
- color: #fff;
 
 
 
 
 
18
  }
19
 
20
- .container {
21
- max-width: 1200px;
22
- margin: 0 auto;
23
  padding: 20px;
 
 
24
  }
25
 
26
- .header {
27
- text-align: center;
28
- padding: 20px 0;
 
 
 
 
 
29
  }
30
 
31
- .controls {
32
- display: grid;
33
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
34
- gap: 20px;
35
- margin: 20px 0;
36
  }
37
 
38
- .control-panel {
39
- background: #2a2a2a;
40
- padding: 20px;
41
- border-radius: 8px;
 
 
 
 
42
  }
43
 
44
- .visualization {
45
- display: grid;
46
- grid-template-columns: 2fr 1fr;
47
- gap: 20px;
48
- margin: 20px 0;
 
 
 
49
  }
50
 
51
- canvas {
52
- width: 100%;
53
- height: 400px;
54
- background: #2a2a2a;
55
- border-radius: 8px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  }
57
 
58
  button {
59
- background: #4CAF50;
60
- color: white;
61
  padding: 10px 20px;
 
62
  border: none;
63
- border-radius: 4px;
64
  cursor: pointer;
65
- margin: 5px;
 
 
66
  }
67
 
68
  button:hover {
69
  background: #45a049;
70
  }
71
 
72
- input[type="number"] {
73
- width: 100%;
74
- padding: 8px;
75
- margin: 5px 0;
76
- border-radius: 4px;
77
- border: 1px solid #444;
78
- background: #333;
79
- color: white;
80
- }
81
-
82
- .device-status {
83
- background: #2a2a2a;
84
- padding: 20px;
85
- border-radius: 8px;
86
  margin-top: 20px;
 
 
 
87
  }
88
 
89
- .preset-container {
90
- display: grid;
91
- grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
92
- gap: 10px;
93
- margin: 20px 0;
94
- }
95
-
96
- .preset {
97
- background: #333;
98
- padding: 10px;
99
- border-radius: 4px;
100
- cursor: pointer;
101
  }
102
 
103
- .preset:hover {
104
- background: #444;
 
 
105
  }
106
  </style>
107
  </head>
108
  <body>
109
- <div class="container">
110
- <div class="header">
111
- <h1>3D Audio Spectrum Analyzer</h1>
112
- </div>
113
-
114
- <div class="controls">
115
- <div class="control-panel">
116
- <h3>Device Configuration</h3>
117
- <button id="startAnalysis">Start Analysis</button>
118
- <button id="stopAnalysis">Stop Analysis</button>
119
- <button id="calibrate">Calibrate Devices</button>
120
- <div>
121
- <label>Device Role:</label>
122
- <select id="deviceRole">
123
- <option value="left">Left Channel</option>
124
- <option value="right">Right Channel</option>
125
- <option value="center">Center Channel</option>
126
- </select>
127
- </div>
128
- </div>
129
-
130
- <div class="control-panel">
131
- <h3>Binaural Beat Generator</h3>
132
- <div>
133
- <label>Base Frequency (Hz):</label>
134
- <input type="number" id="baseFreq" value="432" min="20" max="1000">
135
- </div>
136
- <div>
137
- <label>Beat Frequency (Hz):</label>
138
- <input type="number" id="beatFreq" value="7" min="1" max="40">
139
- </div>
140
- <button id="startBinaural">Generate Binaural Beat</button>
141
- <button id="stopBinaural">Stop</button>
142
- </div>
143
- </div>
144
-
145
- <div class="visualization">
146
- <canvas id="spectrumCanvas"></canvas>
147
- <canvas id="3dRoomCanvas"></canvas>
148
- </div>
149
-
150
- <div class="preset-container">
151
- <div class="preset">
152
- <h4>Alpha Wave</h4>
153
- <p>8-12 Hz</p>
154
- </div>
155
- <div class="preset">
156
- <h4>Theta Wave</h4>
157
- <p>4-7 Hz</p>
158
- </div>
159
- <div class="preset">
160
- <h4>Delta Wave</h4>
161
- <p>0.5-4 Hz</p>
162
- </div>
163
- </div>
164
-
165
- <div class="device-status">
166
- <h3>Connected Devices</h3>
167
- <div id="deviceList"></div>
168
- </div>
169
  </div>
170
 
171
  <script>
172
- class AudioAnalyzer {
173
  constructor() {
174
- this.audioContext = null;
175
- this.analyser = null;
176
- this.oscillator = null;
177
- this.isPlaying = false;
 
 
 
 
 
 
178
  }
179
 
180
- async initialize() {
181
- try {
182
- this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
183
- this.analyser = this.audioContext.createAnalyser();
184
- const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
185
- const source = this.audioContext.createMediaStreamSource(stream);
186
- source.connect(this.analyser);
187
- this.setupVisualization();
188
- } catch (error) {
189
- console.error('Error initializing audio:', error);
 
 
 
190
  }
 
 
 
 
 
 
 
191
  }
192
 
193
- generateBinauralBeat(baseFreq, beatFreq) {
194
- if (this.isPlaying) this.stopBinauralBeat();
 
195
 
196
- const leftOsc = this.audioContext.createOscillator();
197
- const rightOsc = this.audioContext.createOscillator();
198
- const leftGain = this.audioContext.createGain();
199
- const rightGain = this.audioContext.createGain();
200
- const merger = this.audioContext.createChannelMerger(2);
 
 
 
201
 
202
- leftOsc.frequency.value = baseFreq;
203
- rightOsc.frequency.value = baseFreq + beatFreq;
 
 
 
 
 
 
 
 
 
 
 
204
 
205
- leftOsc.connect(leftGain);
206
- rightOsc.connect(rightGain);
207
- leftGain.connect(merger, 0, 0);
208
- rightGain.connect(merger, 0, 1);
209
- merger.connect(this.audioContext.destination);
 
 
 
 
 
 
 
 
 
 
 
 
210
 
211
- leftOsc.start();
212
- rightOsc.start();
213
- this.oscillator = { left: leftOsc, right: rightOsc };
214
- this.isPlaying = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
  }
216
 
217
- stopBinauralBeat() {
218
- if (this.oscillator) {
219
- this.oscillator.left.stop();
220
- this.oscillator.right.stop();
221
- this.isPlaying = false;
 
 
 
 
 
 
 
222
  }
 
 
223
  }
224
 
225
- setupVisualization() {
226
- const canvas = document.getElementById('spectrumCanvas');
227
- const ctx = canvas.getContext('2d');
228
- const width = canvas.width;
229
- const height = canvas.height;
 
 
 
 
 
 
 
 
 
 
230
 
231
- const draw = () => {
232
- requestAnimationFrame(draw);
233
- const dataArray = new Uint8Array(this.analyser.frequencyBinCount);
234
- this.analyser.getByteFrequencyData(dataArray);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
 
236
- ctx.fillStyle = '#2a2a2a';
237
- ctx.fillRect(0, 0, width, height);
 
 
 
 
 
 
 
238
 
239
- const barWidth = width / dataArray.length;
240
- let x = 0;
 
 
 
 
 
241
 
242
- dataArray.forEach(value => {
243
- const barHeight = value * height / 255;
244
- ctx.fillStyle = `hsl(${value}, 100%, 50%)`;
245
- ctx.fillRect(x, height - barHeight, barWidth, barHeight);
246
- x += barWidth;
247
- });
248
- };
 
 
 
 
249
 
250
- draw();
 
 
 
 
 
 
 
 
251
  }
252
- }
253
 
254
- // Initialize application
255
- const analyzer = new AudioAnalyzer();
256
-
257
- document.getElementById('startAnalysis').addEventListener('click', () => analyzer.initialize());
258
- document.getElementById('startBinaural').addEventListener('click', () => {
259
- const baseFreq = parseFloat(document.getElementById('baseFreq').value);
260
- const beatFreq = parseFloat(document.getElementById('beatFreq').value);
261
- analyzer.generateBinauralBeat(baseFreq, beatFreq);
262
- });
263
- document.getElementById('stopBinaural').addEventListener('click', () => analyzer.stopBinauralBeat());
264
-
265
- // Setup room visualization
266
- const room3d = document.getElementById('3dRoomCanvas');
267
- const ctx3d = room3d.getContext('2d');
268
-
269
- function draw3dRoom() {
270
- // Basic 3D room visualization implementation would go here
271
- // This would require a more complex 3D rendering library for proper implementation
272
- ctx3d.fillStyle = '#2a2a2a';
273
- ctx3d.fillRect(0, 0, room3d.width, room3d.height);
274
- ctx3d.strokeStyle = '#4CAF50';
275
- ctx3d.beginPath();
276
- ctx3d.moveTo(50, 50);
277
- ctx3d.lineTo(room3d.width - 50, 50);
278
- ctx3d.lineTo(room3d.width - 50, room3d.height - 50);
279
- ctx3d.lineTo(50, room3d.height - 50);
280
- ctx3d.closePath();
281
- ctx3d.stroke();
282
  }
283
 
284
- draw3dRoom();
285
  </script>
286
  </body>
287
  </html><script async data-explicit-opt-in="true" data-cookie-opt-in="true" src="https://vercel.live/_next-live/feedback/feedback.js"></script>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Go Game</title>
7
  <style>
8
  * {
9
  margin: 0;
10
  padding: 0;
11
  box-sizing: border-box;
 
12
  }
13
 
14
  body {
15
+ display: flex;
16
+ flex-direction: column;
17
+ align-items: center;
18
+ min-height: 100vh;
19
+ background: #f0f0f0;
20
+ font-family: Arial, sans-serif;
21
+ padding: 20px;
22
  }
23
 
24
+ .game-container {
25
+ background: #DEB887;
 
26
  padding: 20px;
27
+ border-radius: 10px;
28
+ box-shadow: 0 0 20px rgba(0,0,0,0.1);
29
  }
30
 
31
+ .board {
32
+ display: grid;
33
+ grid-template-columns: repeat(19, 30px);
34
+ grid-template-rows: repeat(19, 30px);
35
+ gap: 0px;
36
+ background: #DEB887;
37
+ border: 2px solid #000;
38
+ position: relative;
39
  }
40
 
41
+ .intersection {
42
+ width: 30px;
43
+ height: 30px;
44
+ position: relative;
45
+ cursor: pointer;
46
  }
47
 
48
+ .intersection::before {
49
+ content: '';
50
+ position: absolute;
51
+ top: 50%;
52
+ left: 0;
53
+ width: 100%;
54
+ height: 1px;
55
+ background: #000;
56
  }
57
 
58
+ .intersection::after {
59
+ content: '';
60
+ position: absolute;
61
+ left: 50%;
62
+ top: 0;
63
+ height: 100%;
64
+ width: 1px;
65
+ background: #000;
66
  }
67
 
68
+ .stone {
69
+ position: absolute;
70
+ width: 26px;
71
+ height: 26px;
72
+ border-radius: 50%;
73
+ top: 2px;
74
+ left: 2px;
75
+ z-index: 1;
76
+ transition: all 0.2s ease;
77
+ }
78
+
79
+ .black {
80
+ background: #000;
81
+ box-shadow: 2px 2px 2px rgba(0,0,0,0.2);
82
+ }
83
+
84
+ .white {
85
+ background: #fff;
86
+ box-shadow: 2px 2px 2px rgba(0,0,0,0.2);
87
+ }
88
+
89
+ .controls {
90
+ margin-top: 20px;
91
+ display: flex;
92
+ gap: 10px;
93
  }
94
 
95
  button {
 
 
96
  padding: 10px 20px;
97
+ font-size: 16px;
98
  border: none;
99
+ border-radius: 5px;
100
  cursor: pointer;
101
+ background: #4CAF50;
102
+ color: white;
103
+ transition: background 0.3s;
104
  }
105
 
106
  button:hover {
107
  background: #45a049;
108
  }
109
 
110
+ .score {
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  margin-top: 20px;
112
+ font-size: 18px;
113
+ display: flex;
114
+ gap: 20px;
115
  }
116
 
117
+ .mode-select {
118
+ margin-bottom: 20px;
 
 
 
 
 
 
 
 
 
 
119
  }
120
 
121
+ select {
122
+ padding: 8px;
123
+ font-size: 16px;
124
+ border-radius: 5px;
125
  }
126
  </style>
127
  </head>
128
  <body>
129
+ <div class="mode-select">
130
+ <select id="gameMode">
131
+ <option value="pvp">Player vs Player</option>
132
+ <option value="ai">Player vs AI</option>
133
+ </select>
134
+ </div>
135
+
136
+ <div class="game-container">
137
+ <div class="board" id="board"></div>
138
+ </div>
139
+
140
+ <div class="score">
141
+ <div>Black Score: <span id="blackScore">0</span></div>
142
+ <div>White Score: <span id="whiteScore">0</span></div>
143
+ </div>
144
+
145
+ <div class="controls">
146
+ <button id="passBtn">Pass</button>
147
+ <button id="resetBtn">Reset</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  </div>
149
 
150
  <script>
151
+ class GoGame {
152
  constructor() {
153
+ this.size = 19;
154
+ this.board = Array(this.size).fill().map(() => Array(this.size).fill(null));
155
+ this.currentPlayer = 'black';
156
+ this.lastMove = null;
157
+ this.passes = 0;
158
+ this.gameMode = 'pvp';
159
+ this.score = { black: 0, white: 0 };
160
+ this.capturedStones = { black: 0, white: 0 };
161
+
162
+ this.initialize();
163
  }
164
 
165
+ initialize() {
166
+ const boardElement = document.getElementById('board');
167
+ boardElement.innerHTML = '';
168
+
169
+ for(let i = 0; i < this.size; i++) {
170
+ for(let j = 0; j < this.size; j++) {
171
+ const intersection = document.createElement('div');
172
+ intersection.className = 'intersection';
173
+ intersection.dataset.row = i;
174
+ intersection.dataset.col = j;
175
+ intersection.addEventListener('click', (e) => this.handleMove(e));
176
+ boardElement.appendChild(intersection);
177
+ }
178
  }
179
+
180
+ document.getElementById('passBtn').addEventListener('click', () => this.pass());
181
+ document.getElementById('resetBtn').addEventListener('click', () => this.reset());
182
+ document.getElementById('gameMode').addEventListener('change', (e) => {
183
+ this.gameMode = e.target.value;
184
+ this.reset();
185
+ });
186
  }
187
 
188
+ handleMove(e) {
189
+ const row = parseInt(e.target.dataset.row);
190
+ const col = parseInt(e.target.dataset.col);
191
 
192
+ if(this.isValidMove(row, col)) {
193
+ this.placeStone(row, col);
194
+
195
+ if(this.gameMode === 'ai' && this.currentPlayer === 'white') {
196
+ setTimeout(() => this.makeAIMove(), 500);
197
+ }
198
+ }
199
+ }
200
 
201
+ isValidMove(row, col) {
202
+ if(this.board[row][col] !== null) return false;
203
+
204
+ // Place stone temporarily to check if it would be immediately captured
205
+ this.board[row][col] = this.currentPlayer;
206
+ const group = this.getGroup(row, col);
207
+ const liberties = this.countLiberties(group);
208
+
209
+ // Revert the temporary stone
210
+ this.board[row][col] = null;
211
+
212
+ return liberties > 0;
213
+ }
214
 
215
+ placeStone(row, col) {
216
+ if(this.board[row][col] === null) {
217
+ this.board[row][col] = this.currentPlayer;
218
+ this.renderStone(row, col);
219
+ this.captures();
220
+ this.passes = 0;
221
+ this.currentPlayer = this.currentPlayer === 'black' ? 'white' : 'black';
222
+ this.updateScore();
223
+ }
224
+ }
225
+
226
+ renderStone(row, col) {
227
+ const intersection = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);
228
+ const stone = document.createElement('div');
229
+ stone.className = `stone ${this.currentPlayer}`;
230
+ intersection.appendChild(stone);
231
+ }
232
 
233
+ getGroup(row, col) {
234
+ const color = this.board[row][col];
235
+ const group = new Set();
236
+ const stack = [[row, col]];
237
+
238
+ while(stack.length > 0) {
239
+ const [r, c] = stack.pop();
240
+ const key = `${r},${c}`;
241
+
242
+ if(!group.has(key)) {
243
+ group.add(key);
244
+ const neighbors = this.getNeighbors(r, c);
245
+
246
+ for(const [nr, nc] of neighbors) {
247
+ if(this.board[nr][nc] === color) {
248
+ stack.push([nr, nc]);
249
+ }
250
+ }
251
+ }
252
+ }
253
+
254
+ return group;
255
  }
256
 
257
+ countLiberties(group) {
258
+ const liberties = new Set();
259
+
260
+ for(const pos of group) {
261
+ const [row, col] = pos.split(',').map(Number);
262
+ const neighbors = this.getNeighbors(row, col);
263
+
264
+ for(const [nr, nc] of neighbors) {
265
+ if(this.board[nr][nc] === null) {
266
+ liberties.add(`${nr},${nc}`);
267
+ }
268
+ }
269
  }
270
+
271
+ return liberties.size;
272
  }
273
 
274
+ getNeighbors(row, col) {
275
+ const neighbors = [];
276
+ const directions = [[-1,0], [1,0], [0,-1], [0,1]];
277
+
278
+ for(const [dr, dc] of directions) {
279
+ const newRow = row + dr;
280
+ const newCol = col + dc;
281
+
282
+ if(newRow >= 0 && newRow < this.size && newCol >= 0 && newCol < this.size) {
283
+ neighbors.push([newRow, newCol]);
284
+ }
285
+ }
286
+
287
+ return neighbors;
288
+ }
289
 
290
+ captures() {
291
+ for(let i = 0; i < this.size; i++) {
292
+ for(let j = 0; j < this.size; j++) {
293
+ if(this.board[i][j] !== null) {
294
+ const group = this.getGroup(i, j);
295
+ if(this.countLiberties(group) === 0) {
296
+ for(const pos of group) {
297
+ const [row, col] = pos.split(',').map(Number);
298
+ const capturedColor = this.board[row][col];
299
+ this.board[row][col] = null;
300
+ const intersection = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);
301
+ intersection.innerHTML = '';
302
+ this.capturedStones[this.currentPlayer]++;
303
+ }
304
+ }
305
+ }
306
+ }
307
+ }
308
+ }
309
 
310
+ makeAIMove() {
311
+ const validMoves = [];
312
+ for(let i = 0; i < this.size; i++) {
313
+ for(let j = 0; j < this.size; j++) {
314
+ if(this.isValidMove(i, j)) {
315
+ validMoves.push([i, j]);
316
+ }
317
+ }
318
+ }
319
 
320
+ if(validMoves.length > 0) {
321
+ const [row, col] = validMoves[Math.floor(Math.random() * validMoves.length)];
322
+ this.placeStone(row, col);
323
+ } else {
324
+ this.pass();
325
+ }
326
+ }
327
 
328
+ pass() {
329
+ this.passes++;
330
+ if(this.passes === 2) {
331
+ alert('Game Over!');
332
+ return;
333
+ }
334
+ this.currentPlayer = this.currentPlayer === 'black' ? 'white' : 'black';
335
+ if(this.gameMode === 'ai' && this.currentPlayer === 'white') {
336
+ setTimeout(() => this.makeAIMove(), 500);
337
+ }
338
+ }
339
 
340
+ reset() {
341
+ this.board = Array(this.size).fill().map(() => Array(this.size).fill(null));
342
+ this.currentPlayer = 'black';
343
+ this.passes = 0;
344
+ this.score = { black: 0, white: 0 };
345
+ this.capturedStones = { black: 0, white: 0 };
346
+ const intersections = document.querySelectorAll('.intersection');
347
+ intersections.forEach(intersection => intersection.innerHTML = '');
348
+ this.updateScore();
349
  }
 
350
 
351
+ updateScore() {
352
+ document.getElementById('blackScore').textContent =
353
+ this.score.black + this.capturedStones.black;
354
+ document.getElementById('whiteScore').textContent =
355
+ this.score.white + this.capturedStones.white;
356
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
357
  }
358
 
359
+ const game = new GoGame();
360
  </script>
361
  </body>
362
  </html><script async data-explicit-opt-in="true" data-cookie-opt-in="true" src="https://vercel.live/_next-live/feedback/feedback.js"></script>