vs4vijay commited on
Commit
ae67fb7
Β·
verified Β·
1 Parent(s): 27ab2e9

undefined - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +452 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Rock Paper Scissors
3
- emoji: ⚑
4
- colorFrom: yellow
5
- colorTo: pink
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: rock-paper-scissors
3
+ emoji: 🐳
4
+ colorFrom: purple
5
+ colorTo: yellow
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,452 @@
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="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Rock Paper Scissors for Kids</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/handpose@latest"></script>
10
+ <style>
11
+ @import url('https://fonts.googleapis.com/css2?family=Comic+Neue:wght@400;700&display=swap');
12
+
13
+ body {
14
+ font-family: 'Comic Neue', cursive;
15
+ background-color: #f0f9ff;
16
+ }
17
+
18
+ .hand-animation {
19
+ animation: bounce 0.5s infinite alternate;
20
+ }
21
+
22
+ @keyframes bounce {
23
+ from { transform: translateY(0); }
24
+ to { transform: translateY(-10px); }
25
+ }
26
+
27
+ .result-bubble {
28
+ animation: pop 0.3s ease-out;
29
+ }
30
+
31
+ @keyframes pop {
32
+ 0% { transform: scale(0.5); opacity: 0; }
33
+ 80% { transform: scale(1.1); }
34
+ 100% { transform: scale(1); opacity: 1; }
35
+ }
36
+
37
+ .emoji {
38
+ font-size: 2rem;
39
+ }
40
+
41
+ .animate-pulse {
42
+ animation: pulse 0.5s ease-in-out;
43
+ }
44
+
45
+ @keyframes pulse {
46
+ 0%, 100% { transform: scale(1); }
47
+ 50% { transform: scale(1.2); }
48
+ }
49
+ </style>
50
+ </head>
51
+ <body class="min-h-screen flex flex-col items-center justify-center p-4">
52
+ <div class="max-w-4xl w-full bg-white rounded-3xl shadow-xl overflow-hidden">
53
+ <!-- Header -->
54
+ <div class="bg-gradient-to-r from-blue-500 to-purple-600 p-6 text-center">
55
+ <h1 class="text-4xl font-bold text-white mb-2">πŸ‘‹ Rock Paper Scissors πŸ‘‹</h1>
56
+ <p class="text-white text-lg">Show your hand to the camera to play!</p>
57
+ </div>
58
+
59
+ <!-- Game Area -->
60
+ <div class="p-6 md:p-8 grid grid-cols-1 md:grid-cols-2 gap-8">
61
+ <!-- Camera Section -->
62
+ <div class="bg-blue-50 rounded-2xl p-4 flex flex-col items-center">
63
+ <h2 class="text-2xl font-bold text-blue-800 mb-4">Your Move</h2>
64
+ <div class="relative w-full aspect-square max-w-md bg-gray-200 rounded-xl overflow-hidden mb-4">
65
+ <video id="video" class="w-full h-full object-cover" playsinline autoplay muted></video>
66
+ <div id="overlay" class="absolute inset-0"></div>
67
+ </div>
68
+ <div class="flex gap-4 mb-4">
69
+ <button id="startCamera" class="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded-full transition">
70
+ Start Camera
71
+ </button>
72
+ <button id="stopCamera" class="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded-full transition">
73
+ Stop Camera
74
+ </button>
75
+ </div>
76
+ <div class="text-center">
77
+ <p class="text-gray-700 mb-2">Show one of these to the camera:</p>
78
+ <div class="flex justify-center gap-6">
79
+ <div class="text-center">
80
+ <div class="emoji">✊</div>
81
+ <p class="text-sm">Rock</p>
82
+ </div>
83
+ <div class="text-center">
84
+ <div class="emoji">βœ‹</div>
85
+ <p class="text-sm">Paper</p>
86
+ </div>
87
+ <div class="text-center">
88
+ <div class="emoji">✌️</div>
89
+ <p class="text-sm">Scissors</p>
90
+ </div>
91
+ </div>
92
+ </div>
93
+ </div>
94
+
95
+ <!-- Game Section -->
96
+ <div class="bg-purple-50 rounded-2xl p-4 flex flex-col items-center justify-between">
97
+ <h2 class="text-2xl font-bold text-purple-800 mb-4">Game</h2>
98
+
99
+ <!-- Score Board -->
100
+ <div class="w-full bg-white rounded-xl p-4 mb-6 shadow-md">
101
+ <div class="flex justify-between items-center">
102
+ <div class="text-center">
103
+ <p class="text-sm text-gray-600">You</p>
104
+ <p id="playerScore" class="text-3xl font-bold text-blue-600">0</p>
105
+ </div>
106
+ <div class="text-2xl font-bold text-gray-500">VS</div>
107
+ <div class="text-center">
108
+ <p class="text-sm text-gray-600">Computer</p>
109
+ <p id="computerScore" class="text-3xl font-bold text-purple-600">0</p>
110
+ </div>
111
+ </div>
112
+ </div>
113
+
114
+ <!-- Moves Display -->
115
+ <div class="w-full flex justify-center gap-8 mb-8">
116
+ <div class="text-center">
117
+ <p class="text-sm text-gray-600 mb-2">You</p>
118
+ <div id="playerMove" class="text-6xl bg-white rounded-full w-20 h-20 flex items-center justify-center shadow-md">?</div>
119
+ </div>
120
+ <div class="text-center">
121
+ <p class="text-sm text-gray-600 mb-2">Computer</p>
122
+ <div id="computerMove" class="text-6xl bg-white rounded-full w-20 h-20 flex items-center justify-center shadow-md">?</div>
123
+ </div>
124
+ </div>
125
+
126
+ <!-- Result Display -->
127
+ <div id="resultDisplay" class="mb-6 text-center hidden">
128
+ <div class="result-bubble inline-block bg-yellow-100 text-yellow-800 px-6 py-3 rounded-full text-xl font-bold">
129
+ Let's Play!
130
+ </div>
131
+ </div>
132
+
133
+ <!-- Controls -->
134
+ <div class="flex flex-col items-center w-full">
135
+ <button id="playButton" class="bg-gradient-to-r from-pink-500 to-orange-500 hover:from-pink-600 hover:to-orange-600 text-white font-bold py-3 px-8 rounded-full text-xl shadow-lg transition transform hover:scale-105 mb-4">
136
+ Play!
137
+ </button>
138
+ <button id="resetButton" class="text-gray-600 hover:text-gray-800 font-medium">
139
+ Reset Game
140
+ </button>
141
+ </div>
142
+ </div>
143
+ </div>
144
+
145
+ <!-- Instructions -->
146
+ <div class="bg-gray-100 p-6">
147
+ <h3 class="text-xl font-bold text-gray-800 mb-3">How to Play:</h3>
148
+ <ol class="list-decimal pl-5 space-y-2 text-gray-700">
149
+ <li>Click "Start Camera" and allow access to your camera</li>
150
+ <li>Show your hand to the camera (rock ✊, paper βœ‹, or scissors ✌️)</li>
151
+ <li>Click "Play!" when you're ready</li>
152
+ <li>The computer will choose its move and show who won!</li>
153
+ </ol>
154
+ </div>
155
+ </div>
156
+
157
+ <script>
158
+ // Game variables
159
+ let playerScore = 0;
160
+ let computerScore = 0;
161
+ let playerMove = '';
162
+ let computerMove = '';
163
+ let gameActive = false;
164
+ let videoStream = null;
165
+ let handposeModel = null;
166
+
167
+ // DOM elements
168
+ const playerScoreElement = document.getElementById('playerScore');
169
+ const computerScoreElement = document.getElementById('computerScore');
170
+ const playerMoveElement = document.getElementById('playerMove');
171
+ const computerMoveElement = document.getElementById('computerMove');
172
+ const resultDisplay = document.getElementById('resultDisplay');
173
+ const playButton = document.getElementById('playButton');
174
+ const resetButton = document.getElementById('resetButton');
175
+ const startCameraButton = document.getElementById('startCamera');
176
+ const stopCameraButton = document.getElementById('stopCamera');
177
+ const videoElement = document.getElementById('video');
178
+ const overlayElement = document.getElementById('overlay');
179
+
180
+ // Initialize the game
181
+ function initGame() {
182
+ updateScores();
183
+ resetMoves();
184
+
185
+ // Event listeners
186
+ playButton.addEventListener('click', playRound);
187
+ resetButton.addEventListener('click', resetGame);
188
+ startCameraButton.addEventListener('click', startCamera);
189
+ stopCameraButton.addEventListener('click', stopCamera);
190
+
191
+ // Load handpose model
192
+ loadHandposeModel();
193
+ }
194
+
195
+ // Load TensorFlow handpose model
196
+ async function loadHandposeModel() {
197
+ try {
198
+ handposeModel = await handpose.load();
199
+ console.log('Handpose model loaded');
200
+ } catch (error) {
201
+ console.error('Error loading handpose model:', error);
202
+ }
203
+ }
204
+
205
+ // Start camera
206
+ async function startCamera() {
207
+ try {
208
+ videoStream = await navigator.mediaDevices.getUserMedia({
209
+ video: {
210
+ facingMode: 'user',
211
+ width: { ideal: 640 },
212
+ height: { ideal: 480 }
213
+ },
214
+ audio: false
215
+ });
216
+ videoElement.srcObject = videoStream;
217
+ gameActive = true;
218
+ detectHandGesture();
219
+ } catch (error) {
220
+ console.error('Error accessing camera:', error);
221
+ alert('Could not access the camera. Please make sure you have granted permission.');
222
+ }
223
+ }
224
+
225
+ // Stop camera
226
+ function stopCamera() {
227
+ if (videoStream) {
228
+ videoStream.getTracks().forEach(track => track.stop());
229
+ videoElement.srcObject = null;
230
+ gameActive = false;
231
+ }
232
+ }
233
+
234
+ // Detect hand gesture from camera
235
+ async function detectHandGesture() {
236
+ if (!gameActive || !handposeModel) return;
237
+
238
+ try {
239
+ // Predict hand landmarks
240
+ const predictions = await handposeModel.estimateHands(videoElement);
241
+
242
+ // Clear overlay
243
+ overlayElement.innerHTML = '';
244
+
245
+ if (predictions.length > 0) {
246
+ const hand = predictions[0];
247
+ const fingersUp = countFingersUp(hand.landmarks);
248
+
249
+ // Determine move based on fingers up
250
+ if (fingersUp === 0) {
251
+ playerMove = 'rock';
252
+ playerMoveElement.textContent = '✊';
253
+ } else if (fingersUp >= 4) {
254
+ playerMove = 'paper';
255
+ playerMoveElement.textContent = 'βœ‹';
256
+ } else if (fingersUp === 2) {
257
+ playerMove = 'scissors';
258
+ playerMoveElement.textContent = '✌️';
259
+ } else {
260
+ playerMove = '';
261
+ playerMoveElement.textContent = '?';
262
+ }
263
+
264
+ // Draw landmarks (for visualization)
265
+ drawLandmarks(hand.landmarks);
266
+ } else {
267
+ playerMove = '';
268
+ playerMoveElement.textContent = '?';
269
+ }
270
+ } catch (error) {
271
+ console.error('Hand detection error:', error);
272
+ }
273
+
274
+ // Continue detecting
275
+ requestAnimationFrame(detectHandGesture);
276
+ }
277
+
278
+ // Count how many fingers are up
279
+ function countFingersUp(landmarks) {
280
+ // Simplified finger detection (thumb, index, middle, ring, pinky)
281
+ const fingerTips = [4, 8, 12, 16, 20]; // Landmark indices for finger tips
282
+ const fingerPips = [2, 6, 10, 14, 18]; // Landmark indices for finger PIP joints
283
+
284
+ let count = 0;
285
+
286
+ for (let i = 1; i < 5; i++) { // Skip thumb (i=0)
287
+ const tip = landmarks[fingerTips[i]];
288
+ const pip = landmarks[fingerPips[i]];
289
+
290
+ // Check if finger is extended (tip is above PIP joint)
291
+ if (tip[1] < pip[1]) { // Compare y-coordinates
292
+ count++;
293
+ }
294
+ }
295
+
296
+ return count;
297
+ }
298
+
299
+ // Draw hand landmarks on overlay
300
+ function drawLandmarks(landmarks) {
301
+ const canvas = document.createElement('canvas');
302
+ canvas.width = videoElement.videoWidth;
303
+ canvas.height = videoElement.videoHeight;
304
+ const ctx = canvas.getContext('2d');
305
+
306
+ // Draw landmarks
307
+ ctx.fillStyle = 'red';
308
+ landmarks.forEach(landmark => {
309
+ ctx.beginPath();
310
+ ctx.arc(landmark[0], landmark[1], 5, 0, 2 * Math.PI);
311
+ ctx.fill();
312
+ });
313
+
314
+ // Draw connections (simplified)
315
+ ctx.strokeStyle = 'blue';
316
+ ctx.lineWidth = 2;
317
+
318
+ // Palm connections
319
+ drawConnection(ctx, landmarks, [0, 1, 2, 5, 9, 13, 17, 0]);
320
+
321
+ // Thumb
322
+ drawConnection(ctx, landmarks, [1, 2, 3, 4]);
323
+
324
+ // Index finger
325
+ drawConnection(ctx, landmarks, [5, 6, 7, 8]);
326
+
327
+ // Middle finger
328
+ drawConnection(ctx, landmarks, [9, 10, 11, 12]);
329
+
330
+ // Ring finger
331
+ drawConnection(ctx, landmarks, [13, 14, 15, 16]);
332
+
333
+ // Pinky finger
334
+ drawConnection(ctx, landmarks, [17, 18, 19, 20]);
335
+
336
+ overlayElement.innerHTML = '';
337
+ overlayElement.appendChild(canvas);
338
+ }
339
+
340
+ // Helper function to draw connections between landmarks
341
+ function drawConnection(ctx, landmarks, indices) {
342
+ ctx.beginPath();
343
+ for (let i = 0; i < indices.length; i++) {
344
+ const landmark = landmarks[indices[i]];
345
+ if (i === 0) {
346
+ ctx.moveTo(landmark[0], landmark[1]);
347
+ } else {
348
+ ctx.lineTo(landmark[0], landmark[1]);
349
+ }
350
+ }
351
+ ctx.stroke();
352
+ }
353
+
354
+ // Play a round of the game
355
+ function playRound() {
356
+ if (!playerMove) {
357
+ showResult('Show your hand to the camera! βœŠβœ‹βœŒοΈ');
358
+ playerMoveElement.classList.add('animate-pulse');
359
+ setTimeout(() => {
360
+ playerMoveElement.classList.remove('animate-pulse');
361
+ }, 1000);
362
+ return;
363
+ }
364
+
365
+ // Computer chooses random move
366
+ const moves = ['rock', 'paper', 'scissors'];
367
+ computerMove = moves[Math.floor(Math.random() * moves.length)];
368
+
369
+ // Update computer move display
370
+ computerMoveElement.textContent =
371
+ computerMove === 'rock' ? '✊' :
372
+ computerMove === 'paper' ? 'βœ‹' : '✌️';
373
+
374
+ // Determine winner
375
+ const result = determineWinner(playerMove, computerMove);
376
+
377
+ // Update scores and display result
378
+ if (result === 'win') {
379
+ playerScore++;
380
+ showResult('You win! πŸŽ‰');
381
+ } else if (result === 'lose') {
382
+ computerScore++;
383
+ showResult('Computer wins! 😒');
384
+ } else {
385
+ showResult("It's a tie! 🀝");
386
+ }
387
+
388
+ updateScores();
389
+ }
390
+
391
+ // Determine the winner of a round
392
+ function determineWinner(player, computer) {
393
+ if (player === computer) return 'tie';
394
+
395
+ if (
396
+ (player === 'rock' && computer === 'scissors') ||
397
+ (player === 'paper' && computer === 'rock') ||
398
+ (player === 'scissors' && computer === 'paper')
399
+ ) {
400
+ return 'win';
401
+ }
402
+
403
+ return 'lose';
404
+ }
405
+
406
+ // Show game result
407
+ function showResult(message) {
408
+ resultDisplay.classList.remove('hidden');
409
+ const resultElement = resultDisplay.querySelector('div');
410
+
411
+ // Update styling based on result
412
+ if (message.includes('win')) {
413
+ resultElement.className = 'result-bubble inline-block bg-green-100 text-green-800 px-6 py-3 rounded-full text-xl font-bold';
414
+ } else if (message.includes('lose')) {
415
+ resultElement.className = 'result-bubble inline-block bg-red-100 text-red-800 px-6 py-3 rounded-full text-xl font-bold';
416
+ } else if (message.includes('tie')) {
417
+ resultElement.className = 'result-bubble inline-block bg-yellow-100 text-yellow-800 px-6 py-3 rounded-full text-xl font-bold';
418
+ } else {
419
+ resultElement.className = 'result-bubble inline-block bg-blue-100 text-blue-800 px-6 py-3 rounded-full text-xl font-bold';
420
+ }
421
+
422
+ resultElement.textContent = message;
423
+ }
424
+
425
+ // Update score displays
426
+ function updateScores() {
427
+ playerScoreElement.textContent = playerScore;
428
+ computerScoreElement.textContent = computerScore;
429
+ }
430
+
431
+ // Reset moves display
432
+ function resetMoves() {
433
+ playerMove = '';
434
+ computerMove = '';
435
+ playerMoveElement.textContent = '?';
436
+ computerMoveElement.textContent = '?';
437
+ showResult("Let's Play!");
438
+ }
439
+
440
+ // Reset the entire game
441
+ function resetGame() {
442
+ playerScore = 0;
443
+ computerScore = 0;
444
+ updateScores();
445
+ resetMoves();
446
+ }
447
+
448
+ // Initialize the game when the page loads
449
+ window.addEventListener('DOMContentLoaded', initGame);
450
+ </script>
451
+ <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=vs4vijay/rock-paper-scissors" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
452
+ </html>