reddythrived commited on
Commit
313a596
·
1 Parent(s): 4b4e4f7

Add highly visible camera flip button and detailed session report

Browse files
Files changed (1) hide show
  1. templates/recognition.html +48 -3
templates/recognition.html CHANGED
@@ -214,6 +214,9 @@
214
  </div>
215
  </div>
216
 
 
 
 
217
  <div class="report-panel" id="reportPanel">
218
  <h3 style="margin-bottom:15px; font-size:1rem;">Session Report</h3>
219
  <div id="reportList"></div>
@@ -227,12 +230,13 @@
227
  let remainingTime = 60; // 1-minute detection session
228
  let mainInterval = null;
229
  let timerInterval = null;
 
230
 
231
  const SESSION_WINDOW = 30000; // 30 seconds
232
  const PRESENCE_THRESHOLD = 20000; // 20 seconds
233
  const INTERVAL = 500; // ms
234
 
235
- async function init() {
236
  // 1. Mandatory Password Check at Start
237
  const password = prompt("AttendNet Administrator Security Check\nEnter password to unlock AI Recognition:");
238
  if (password !== "student1") {
@@ -261,7 +265,7 @@
261
  });
262
 
263
  const cameraPromise = navigator.mediaDevices.getUserMedia({
264
- video: { facingMode: 'user', width: { ideal: 1280 }, height: { ideal: 720 } }
265
  }).catch(err => {
266
  throw new Error("Camera Access Denied or in Use by another Tab. Please close other AttendNet tabs.");
267
  });
@@ -283,6 +287,8 @@
283
  const displaySize = { width: video.videoWidth, height: video.videoHeight };
284
  faceapi.matchDimensions(canvas, displaySize);
285
 
 
 
286
  mainInterval = setInterval(async () => {
287
  if (isProcessing || !sessionActive) return;
288
  isProcessing = true;
@@ -405,6 +411,9 @@
405
  <div style="background:rgba(255,255,255,0.03); border-radius:20px; padding:20px; max-height:200px; overflow-y:auto; text-align:left; margin-bottom:30px;">
406
  <h4 style="font-size:0.8rem; opacity:0.5; margin-bottom:10px;">Newly Marked USNs:</h4>
407
  <p style="font-size:0.9rem; line-height:1.5;">${markedInSession.length > 0 ? markedInSession.join(', ') : 'No new marks.'}</p>
 
 
 
408
  </div>
409
 
410
  <div style="display:flex; gap:12px;">
@@ -501,7 +510,43 @@
501
  }
502
  }
503
 
504
- window.onload = init;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
  </script>
506
  </body>
507
  </html>
 
214
  </div>
215
  </div>
216
 
217
+ <button id="flipBtn" onclick="flipCamera()" style="position:fixed; bottom:40px; right:40px; width:72px; height:72px; border-radius:50%; border:3px solid white; background:#6366f1; color:white; font-size:36px; cursor:pointer; z-index:2147483647; box-shadow:0 15px 35px rgba(0,0,0,0.8); display:flex; align-items:center; justify-content:center; transition:transform 0.2s;">↻</button>
218
+
219
+
220
  <div class="report-panel" id="reportPanel">
221
  <h3 style="margin-bottom:15px; font-size:1rem;">Session Report</h3>
222
  <div id="reportList"></div>
 
230
  let remainingTime = 60; // 1-minute detection session
231
  let mainInterval = null;
232
  let timerInterval = null;
233
+ let currentFacingMode = 'user';
234
 
235
  const SESSION_WINDOW = 30000; // 30 seconds
236
  const PRESENCE_THRESHOLD = 20000; // 20 seconds
237
  const INTERVAL = 500; // ms
238
 
239
+ async function init(mode = 'user') {
240
  // 1. Mandatory Password Check at Start
241
  const password = prompt("AttendNet Administrator Security Check\nEnter password to unlock AI Recognition:");
242
  if (password !== "student1") {
 
265
  });
266
 
267
  const cameraPromise = navigator.mediaDevices.getUserMedia({
268
+ video: { facingMode: mode, width: { ideal: 1280 }, height: { ideal: 720 } }
269
  }).catch(err => {
270
  throw new Error("Camera Access Denied or in Use by another Tab. Please close other AttendNet tabs.");
271
  });
 
287
  const displaySize = { width: video.videoWidth, height: video.videoHeight };
288
  faceapi.matchDimensions(canvas, displaySize);
289
 
290
+ if (mainInterval) clearInterval(mainInterval);
291
+
292
  mainInterval = setInterval(async () => {
293
  if (isProcessing || !sessionActive) return;
294
  isProcessing = true;
 
411
  <div style="background:rgba(255,255,255,0.03); border-radius:20px; padding:20px; max-height:200px; overflow-y:auto; text-align:left; margin-bottom:30px;">
412
  <h4 style="font-size:0.8rem; opacity:0.5; margin-bottom:10px;">Newly Marked USNs:</h4>
413
  <p style="font-size:0.9rem; line-height:1.5;">${markedInSession.length > 0 ? markedInSession.join(', ') : 'No new marks.'}</p>
414
+
415
+ <h4 style="font-size:0.8rem; opacity:0.5; margin-top:20px; margin-bottom:10px;">Already Logged USNs:</h4>
416
+ <p style="font-size:0.9rem; line-height:1.5; color:#f59e0b;">${alreadyMarked.length > 0 ? alreadyMarked.join(', ') : 'None.'}</p>
417
  </div>
418
 
419
  <div style="display:flex; gap:12px;">
 
510
  }
511
  }
512
 
513
+ async function flipCamera() {
514
+ if (!sessionActive) return;
515
+ currentFacingMode = currentFacingMode === 'user' ? 'environment' : 'user';
516
+
517
+ const flipBtn = document.getElementById('flipBtn');
518
+ flipBtn.style.opacity = '0.5';
519
+ flipBtn.style.pointerEvents = 'none';
520
+
521
+ // stop current stream to release hardware
522
+ if (video.srcObject) {
523
+ video.srcObject.getTracks().forEach(track => track.stop());
524
+ if (mainInterval) clearInterval(mainInterval);
525
+ }
526
+
527
+ try {
528
+ const newStream = await navigator.mediaDevices.getUserMedia({
529
+ video: { facingMode: currentFacingMode, width: { ideal: 1280 }, height: { ideal: 720 } }
530
+ });
531
+ video.srcObject = newStream;
532
+ if (currentFacingMode === 'user') {
533
+ video.style.transform = 'scaleX(-1)';
534
+ canvas.style.transform = 'scaleX(-1)';
535
+ } else {
536
+ video.style.transform = 'scaleX(1)';
537
+ canvas.style.transform = 'scaleX(1)';
538
+ }
539
+ } catch (err) {
540
+ alert("Camera flip failed: " + err.message);
541
+ }
542
+
543
+ setTimeout(() => {
544
+ flipBtn.style.opacity = '1';
545
+ flipBtn.style.pointerEvents = 'auto';
546
+ }, 500);
547
+ }
548
+
549
+ window.onload = () => init();
550
  </script>
551
  </body>
552
  </html>