openfree commited on
Commit
a5aa9e1
Β·
verified Β·
1 Parent(s): 69a6cde

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +346 -182
index.html CHANGED
@@ -3,235 +3,399 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>PDF Reader with Text-to-Speech</title>
7
- <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.min.js"></script>
8
  <style>
 
 
 
 
 
 
 
9
  * {
10
  margin: 0;
11
  padding: 0;
12
  box-sizing: border-box;
13
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
14
  }
15
 
16
  body {
17
- background: #f0f2f5;
 
 
18
  min-height: 100vh;
19
- padding: 20px;
 
20
  }
21
 
22
- .container {
23
- max-width: 800px;
24
- margin: 0 auto;
25
- background: white;
26
- padding: 30px;
27
- border-radius: 12px;
28
- box-shadow: 0 2px 10px rgba(0,0,0,0.1);
29
  }
30
 
31
- h1 {
32
- text-align: center;
33
- color: #1a73e8;
34
- margin-bottom: 30px;
 
 
35
  }
36
 
37
- .upload-section {
38
- border: 2px dashed #1a73e8;
39
- padding: 30px;
40
- text-align: center;
41
- border-radius: 8px;
42
- margin-bottom: 20px;
 
43
  cursor: pointer;
44
- transition: all 0.3s ease;
45
  }
46
 
47
- .upload-section:hover {
48
- background: #f8f9fe;
49
  }
50
 
51
- .upload-section i {
52
- font-size: 40px;
53
- color: #1a73e8;
54
- margin-bottom: 10px;
55
  }
56
 
57
- .controls {
58
- display: flex;
59
- gap: 10px;
60
- margin-bottom: 20px;
61
- justify-content: center;
62
  }
63
 
64
- button {
65
- padding: 10px 20px;
66
- border: none;
67
- border-radius: 5px;
68
- background: #1a73e8;
69
- color: white;
70
- cursor: pointer;
71
- transition: all 0.3s ease;
72
  }
73
 
74
- button:hover {
75
- background: #1557b0;
 
 
76
  }
77
 
78
- button:disabled {
79
- background: #ccc;
80
- cursor: not-allowed;
 
 
81
  }
82
 
83
- #pdf-content {
84
- background: white;
85
- padding: 20px;
86
- border-radius: 8px;
87
- min-height: 200px;
88
- max-height: 400px;
89
- overflow-y: auto;
90
- line-height: 1.6;
91
  }
92
 
93
- .status {
94
- text-align: center;
95
- margin: 10px 0;
96
- color: #666;
97
  }
98
 
99
- @media (max-width: 600px) {
100
- .container {
101
- padding: 15px;
102
- }
103
-
104
- .controls {
105
  flex-direction: column;
106
  }
107
-
108
- button {
109
- width: 100%;
 
 
 
 
 
 
 
110
  }
111
  }
112
  </style>
113
  </head>
114
  <body>
115
- <div class="container">
116
- <h1>PDF Text-to-Speech Reader</h1>
117
-
118
- <div class="upload-section" id="upload-area">
119
- <i>πŸ“„</i>
120
- <p>Click or drag PDF file here to upload</p>
121
- <input type="file" id="file-input" accept=".pdf" style="display: none;">
122
  </div>
123
-
124
- <div class="controls">
125
- <button id="play-btn" disabled>
126
- <i>▢️</i> Play
127
- </button>
128
- <button id="pause-btn" disabled>
129
- <i>⏸️</i> Pause
130
- </button>
131
- <button id="stop-btn" disabled>
132
- <i>⏹️</i> Stop
133
- </button>
134
- </div>
135
-
136
- <div class="status" id="status"></div>
137
-
138
- <div id="pdf-content"></div>
139
  </div>
140
 
141
  <script>
142
- pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.worker.min.js';
143
-
144
- const fileInput = document.getElementById('file-input');
145
- const uploadArea = document.getElementById('upload-area');
146
- const playBtn = document.getElementById('play-btn');
147
- const pauseBtn = document.getElementById('pause-btn');
148
- const stopBtn = document.getElementById('stop-btn');
149
- const status = document.getElementById('status');
150
- const content = document.getElementById('pdf-content');
151
-
152
- let pdfText = '';
153
- let utterance = null;
154
- let synth = window.speechSynthesis;
155
-
156
- uploadArea.addEventListener('click', () => fileInput.click());
157
- uploadArea.addEventListener('dragover', (e) => {
158
- e.preventDefault();
159
- uploadArea.style.background = '#f0f8ff';
160
- });
161
- uploadArea.addEventListener('dragleave', () => {
162
- uploadArea.style.background = 'transparent';
163
- });
164
- uploadArea.addEventListener('drop', (e) => {
165
- e.preventDefault();
166
- uploadArea.style.background = 'transparent';
167
- const file = e.dataTransfer.files[0];
168
- if (file && file.type === 'application/pdf') {
169
- handleFile(file);
170
- }
171
- });
172
-
173
- fileInput.addEventListener('change', (e) => {
174
- const file = e.target.files[0];
175
- if (file) handleFile(file);
176
- });
177
-
178
- function handleFile(file) {
179
- status.textContent = 'Loading PDF...';
180
- const reader = new FileReader();
181
- reader.onload = async function(event) {
182
- const typedarray = new Uint8Array(event.target.result);
183
- try {
184
- const pdf = await pdfjsLib.getDocument(typedarray).promise;
185
- pdfText = '';
186
-
187
- for(let i = 1; i <= pdf.numPages; i++) {
188
- const page = await pdf.getPage(i);
189
- const textContent = await page.getTextContent();
190
- pdfText += textContent.items.map(item => item.str).join(' ');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  }
192
-
193
- content.textContent = pdfText;
194
- status.textContent = 'PDF loaded successfully!';
195
- playBtn.disabled = false;
196
- stopBtn.disabled = false;
197
-
198
- } catch(error) {
199
- status.textContent = 'Error loading PDF: ' + error.message;
200
  }
201
- };
202
- reader.readAsArrayBuffer(file);
203
- }
204
-
205
- playBtn.addEventListener('click', () => {
206
- if (synth.speaking && synth.paused) {
207
- synth.resume();
208
- } else if (!synth.speaking) {
209
- utterance = new SpeechSynthesisUtterance(pdfText);
210
- utterance.onend = () => {
211
- playBtn.disabled = false;
212
- pauseBtn.disabled = true;
213
- stopBtn.disabled = true;
214
- };
215
- synth.speak(utterance);
216
- }
217
- playBtn.disabled = true;
218
- pauseBtn.disabled = false;
219
- stopBtn.disabled = false;
220
- });
221
-
222
- pauseBtn.addEventListener('click', () => {
223
- if (synth.speaking) {
224
- synth.pause();
225
- playBtn.disabled = false;
226
- }
227
- });
228
-
229
- stopBtn.addEventListener('click', () => {
230
- synth.cancel();
231
- playBtn.disabled = false;
232
- pauseBtn.disabled = true;
233
- stopBtn.disabled = true;
234
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  </script>
236
  </body>
237
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Chess Game</title>
 
7
  <style>
8
+ :root {
9
+ --light-square: #f0d9b5;
10
+ --dark-square: #b58863;
11
+ --highlight: rgba(255, 255, 0, 0.4);
12
+ --possible-move: rgba(0, 255, 0, 0.3);
13
+ }
14
+
15
  * {
16
  margin: 0;
17
  padding: 0;
18
  box-sizing: border-box;
 
19
  }
20
 
21
  body {
22
+ display: flex;
23
+ justify-content: center;
24
+ align-items: center;
25
  min-height: 100vh;
26
+ background: #2c3e50;
27
+ font-family: Arial, sans-serif;
28
  }
29
 
30
+ .game-container {
31
+ display: flex;
32
+ gap: 2rem;
33
+ padding: 1rem;
34
+ background: #34495e;
35
+ border-radius: 10px;
36
+ box-shadow: 0 0 20px rgba(0,0,0,0.5);
37
  }
38
 
39
+ .board {
40
+ width: 560px;
41
+ height: 560px;
42
+ display: grid;
43
+ grid-template-columns: repeat(8, 1fr);
44
+ border: 3px solid #111;
45
  }
46
 
47
+ .square {
48
+ width: 70px;
49
+ height: 70px;
50
+ display: flex;
51
+ justify-content: center;
52
+ align-items: center;
53
+ font-size: 45px;
54
  cursor: pointer;
55
+ position: relative;
56
  }
57
 
58
+ .light {
59
+ background-color: var(--light-square);
60
  }
61
 
62
+ .dark {
63
+ background-color: var(--dark-square);
 
 
64
  }
65
 
66
+ .highlight {
67
+ background-color: var(--highlight);
 
 
 
68
  }
69
 
70
+ .possible-move::after {
71
+ content: '';
72
+ position: absolute;
73
+ width: 25px;
74
+ height: 25px;
75
+ background: var(--possible-move);
76
+ border-radius: 50%;
 
77
  }
78
 
79
+ .game-info {
80
+ color: white;
81
+ padding: 1rem;
82
+ width: 200px;
83
  }
84
 
85
+ .status {
86
+ margin-bottom: 1rem;
87
+ padding: 1rem;
88
+ background: #2c3e50;
89
+ border-radius: 5px;
90
  }
91
 
92
+ .captured {
93
+ margin-top: 1rem;
94
+ display: flex;
95
+ flex-wrap: wrap;
96
+ gap: 0.5rem;
 
 
 
97
  }
98
 
99
+ .piece {
100
+ user-select: none;
 
 
101
  }
102
 
103
+ @media (max-width: 800px) {
104
+ .game-container {
 
 
 
 
105
  flex-direction: column;
106
  }
107
+
108
+ .board {
109
+ width: 400px;
110
+ height: 400px;
111
+ }
112
+
113
+ .square {
114
+ width: 50px;
115
+ height: 50px;
116
+ font-size: 35px;
117
  }
118
  }
119
  </style>
120
  </head>
121
  <body>
122
+ <div class="game-container">
123
+ <div class="board" id="board"></div>
124
+ <div class="game-info">
125
+ <div class="status" id="status">White's turn</div>
126
+ <div>Captured pieces:</div>
127
+ <div class="captured" id="captured"></div>
 
128
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  </div>
130
 
131
  <script>
132
+ class ChessGame {
133
+ constructor() {
134
+ this.board = document.getElementById('board');
135
+ this.status = document.getElementById('status');
136
+ this.captured = document.getElementById('captured');
137
+ this.selectedPiece = null;
138
+ this.currentPlayer = 'white';
139
+ this.possibleMoves = [];
140
+ this.gameBoard = this.initializeBoard();
141
+ this.createBoard();
142
+ this.capturedPieces = [];
143
+ }
144
+
145
+ initializeBoard() {
146
+ return [
147
+ ['β™œ', 'β™ž', '♝', 'β™›', 'β™š', '♝', 'β™ž', 'β™œ'],
148
+ ['β™Ÿ', 'β™Ÿ', 'β™Ÿ', 'β™Ÿ', 'β™Ÿ', 'β™Ÿ', 'β™Ÿ', 'β™Ÿ'],
149
+ ['', '', '', '', '', '', '', ''],
150
+ ['', '', '', '', '', '', '', ''],
151
+ ['', '', '', '', '', '', '', ''],
152
+ ['', '', '', '', '', '', '', ''],
153
+ ['β™™', 'β™™', 'β™™', 'β™™', 'β™™', 'β™™', 'β™™', 'β™™'],
154
+ ['β™–', 'β™˜', 'β™—', 'β™•', 'β™”', 'β™—', 'β™˜', 'β™–']
155
+ ];
156
+ }
157
+
158
+ createBoard() {
159
+ this.board.innerHTML = '';
160
+ for (let row = 0; row < 8; row++) {
161
+ for (let col = 0; col < 8; col++) {
162
+ const square = document.createElement('div');
163
+ square.classList.add('square');
164
+ square.classList.add((row + col) % 2 === 0 ? 'light' : 'dark');
165
+
166
+ const piece = this.gameBoard[row][col];
167
+ if (piece) {
168
+ square.innerHTML = `<span class="piece">${piece}</span>`;
169
+ }
170
+
171
+ square.dataset.row = row;
172
+ square.dataset.col = col;
173
+
174
+ square.addEventListener('click', (e) => this.handleSquareClick(e));
175
+ this.board.appendChild(square);
176
+ }
177
+ }
178
+ }
179
+
180
+ isPieceWhite(piece) {
181
+ return 'β™”β™•β™–β™—β™˜β™™'.includes(piece);
182
+ }
183
+
184
+ handleSquareClick(e) {
185
+ const square = e.target.closest('.square');
186
+ const row = parseInt(square.dataset.row);
187
+ const col = parseInt(square.dataset.col);
188
+ const piece = this.gameBoard[row][col];
189
+
190
+ if (this.currentPlayer === 'black') return; // Prevent moves during AI turn
191
+
192
+ if (this.selectedPiece) {
193
+ if (this.possibleMoves.some(move => move.row === row && move.col === col)) {
194
+ this.movePiece(row, col);
195
+ this.clearHighlights();
196
+ this.selectedPiece = null;
197
+ this.possibleMoves = [];
198
+
199
+ // AI move
200
+ setTimeout(() => this.makeAIMove(), 500);
201
+ } else {
202
+ this.clearHighlights();
203
+ this.selectedPiece = null;
204
+ this.possibleMoves = [];
205
+ }
206
+ } else if (piece && this.isPieceWhite(piece) === (this.currentPlayer === 'white')) {
207
+ this.selectedPiece = { row, col, piece };
208
+ this.highlightSquare(row, col);
209
+ this.possibleMoves = this.calculatePossibleMoves(row, col, piece);
210
+ this.showPossibleMoves();
211
+ }
212
+ }
213
+
214
+ clearHighlights() {
215
+ document.querySelectorAll('.square').forEach(square => {
216
+ square.classList.remove('highlight', 'possible-move');
217
+ });
218
+ }
219
+
220
+ highlightSquare(row, col) {
221
+ const square = this.getSquare(row, col);
222
+ square.classList.add('highlight');
223
+ }
224
+
225
+ showPossibleMoves() {
226
+ this.possibleMoves.forEach(move => {
227
+ const square = this.getSquare(move.row, move.col);
228
+ square.classList.add('possible-move');
229
+ });
230
+ }
231
+
232
+ getSquare(row, col) {
233
+ return this.board.children[row * 8 + col];
234
+ }
235
+
236
+ calculatePossibleMoves(row, col, piece) {
237
+ const moves = [];
238
+
239
+ // Pawn moves
240
+ if (piece === 'β™™') {
241
+ // Forward move
242
+ if (row > 0 && !this.gameBoard[row-1][col]) {
243
+ moves.push({row: row-1, col: col});
244
+ // Initial two-square move
245
+ if (row === 6 && !this.gameBoard[row-2][col]) {
246
+ moves.push({row: row-2, col: col});
247
+ }
248
+ }
249
+ // Diagonal captures
250
+ if (row > 0 && col > 0 && this.gameBoard[row-1][col-1] && !this.isPieceWhite(this.gameBoard[row-1][col-1])) {
251
+ moves.push({row: row-1, col: col-1});
252
+ }
253
+ if (row > 0 && col < 7 && this.gameBoard[row-1][col+1] && !this.isPieceWhite(this.gameBoard[row-1][col+1])) {
254
+ moves.push({row: row-1, col: col+1});
255
  }
 
 
 
 
 
 
 
 
256
  }
257
+
258
+ // Basic moves for other pieces (simplified)
259
+ if ('β™–β™œ'.includes(piece)) { // Rook
260
+ moves.push(...this.getRookMoves(row, col));
261
+ }
262
+ if ('♗♝'.includes(piece)) { // Bishop
263
+ moves.push(...this.getBishopMoves(row, col));
264
+ }
265
+ if ('β™•β™›'.includes(piece)) { // Queen
266
+ moves.push(...this.getRookMoves(row, col));
267
+ moves.push(...this.getBishopMoves(row, col));
268
+ }
269
+ if ('β™˜β™ž'.includes(piece)) { // Knight
270
+ const knightMoves = [
271
+ {row: row-2, col: col-1}, {row: row-2, col: col+1},
272
+ {row: row-1, col: col-2}, {row: row-1, col: col+2},
273
+ {row: row+1, col: col-2}, {row: row+1, col: col+2},
274
+ {row: row+2, col: col-1}, {row: row+2, col: col+1}
275
+ ];
276
+ moves.push(...knightMoves.filter(move =>
277
+ move.row >= 0 && move.row < 8 && move.col >= 0 && move.col < 8 &&
278
+ (!this.gameBoard[move.row][move.col] ||
279
+ this.isPieceWhite(this.gameBoard[move.row][move.col]) !== this.isPieceWhite(piece))
280
+ ));
281
+ }
282
+ if ('β™”β™š'.includes(piece)) { // King
283
+ for (let i = -1; i <= 1; i++) {
284
+ for (let j = -1; j <= 1; j++) {
285
+ if (i === 0 && j === 0) continue;
286
+ const newRow = row + i;
287
+ const newCol = col + j;
288
+ if (newRow >= 0 && newRow < 8 && newCol >= 0 && newCol < 8 &&
289
+ (!this.gameBoard[newRow][newCol] ||
290
+ this.isPieceWhite(this.gameBoard[newRow][newCol]) !== this.isPieceWhite(piece))) {
291
+ moves.push({row: newRow, col: newCol});
292
+ }
293
+ }
294
+ }
295
+ }
296
+
297
+ return moves;
298
+ }
299
+
300
+ getRookMoves(row, col) {
301
+ const moves = [];
302
+ const directions = [[0,1], [0,-1], [1,0], [-1,0]];
303
+ for (let [dx, dy] of directions) {
304
+ let x = row + dx;
305
+ let y = col + dy;
306
+ while (x >= 0 && x < 8 && y >= 0 && y < 8) {
307
+ if (!this.gameBoard[x][y]) {
308
+ moves.push({row: x, col: y});
309
+ } else {
310
+ if (this.isPieceWhite(this.gameBoard[x][y]) !== this.isPieceWhite(this.gameBoard[row][col])) {
311
+ moves.push({row: x, col: y});
312
+ }
313
+ break;
314
+ }
315
+ x += dx;
316
+ y += dy;
317
+ }
318
+ }
319
+ return moves;
320
+ }
321
+
322
+ getBishopMoves(row, col) {
323
+ const moves = [];
324
+ const directions = [[1,1], [1,-1], [-1,1], [-1,-1]];
325
+ for (let [dx, dy] of directions) {
326
+ let x = row + dx;
327
+ let y = col + dy;
328
+ while (x >= 0 && x < 8 && y >= 0 && y < 8) {
329
+ if (!this.gameBoard[x][y]) {
330
+ moves.push({row: x, col: y});
331
+ } else {
332
+ if (this.isPieceWhite(this.gameBoard[x][y]) !== this.isPieceWhite(this.gameBoard[row][col])) {
333
+ moves.push({row: x, col: y});
334
+ }
335
+ break;
336
+ }
337
+ x += dx;
338
+ y += dy;
339
+ }
340
+ }
341
+ return moves;
342
+ }
343
+
344
+ movePiece(toRow, toCol) {
345
+ const fromRow = this.selectedPiece.row;
346
+ const fromCol = this.selectedPiece.col;
347
+
348
+ // Capture logic
349
+ if (this.gameBoard[toRow][toCol]) {
350
+ this.capturedPieces.push(this.gameBoard[toRow][toCol]);
351
+ this.updateCapturedPieces();
352
+ }
353
+
354
+ this.gameBoard[toRow][toCol] = this.gameBoard[fromRow][fromCol];
355
+ this.gameBoard[fromRow][fromCol] = '';
356
+ this.currentPlayer = this.currentPlayer === 'white' ? 'black' : 'white';
357
+ this.status.textContent = `${this.currentPlayer.charAt(0).toUpperCase() + this.currentPlayer.slice(1)}'s turn`;
358
+ this.createBoard();
359
+ }
360
+
361
+ updateCapturedPieces() {
362
+ this.captured.innerHTML = this.capturedPieces.map(piece =>
363
+ `<span class="piece">${piece}</span>`
364
+ ).join('');
365
+ }
366
+
367
+ makeAIMove() {
368
+ // Simple AI: randomly select a valid move
369
+ let possibleAIMoves = [];
370
+ for (let row = 0; row < 8; row++) {
371
+ for (let col = 0; col < 8; col++) {
372
+ const piece = this.gameBoard[row][col];
373
+ if (piece && !this.isPieceWhite(piece)) {
374
+ const moves = this.calculatePossibleMoves(row, col, piece);
375
+ moves.forEach(move => {
376
+ possibleAIMoves.push({
377
+ from: {row, col},
378
+ to: move
379
+ });
380
+ });
381
+ }
382
+ }
383
+ }
384
+
385
+ if (possibleAIMoves.length > 0) {
386
+ const move = possibleAIMoves[Math.floor(Math.random() * possibleAIMoves.length)];
387
+ this.selectedPiece = {
388
+ row: move.from.row,
389
+ col: move.from.col,
390
+ piece: this.gameBoard[move.from.row][move.from.col]
391
+ };
392
+ this.movePiece(move.to.row, move.to.col);
393
+ }
394
+ }
395
+ }
396
+
397
+ // Start the game
398
+ const game = new ChessGame();
399
  </script>
400
  </body>
401
  </html>